mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-12-23 05:23:17 +00:00
Merge pull request #1560 from pixelfed/frontend-ui-refactor
Frontend ui refactor
This commit is contained in:
commit
320542888b
14 changed files with 42 additions and 403 deletions
|
@ -296,4 +296,11 @@ class Profile extends Model
|
|||
{
|
||||
return $this->hasMany(Collection::class);
|
||||
}
|
||||
|
||||
public function hasFollowRequestById(int $id)
|
||||
{
|
||||
return FollowRequest::whereFollowerId($id)
|
||||
->whereFollowingId($this->id)
|
||||
->exists();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ class Helpers {
|
|||
{
|
||||
$audience = self::normalizeAudience($data);
|
||||
$url = $profile->permalink();
|
||||
return in_array($url, $audience);
|
||||
return in_array($url, $audience['to']) || in_array($url, $audience['cc']);
|
||||
}
|
||||
|
||||
public static function validateUrl($url)
|
||||
|
@ -328,7 +328,9 @@ class Helpers {
|
|||
$status->scope = $scope;
|
||||
$status->visibility = $scope;
|
||||
$status->save();
|
||||
if($reply_to == null) {
|
||||
self::importNoteAttachment($res, $status);
|
||||
}
|
||||
return $status;
|
||||
});
|
||||
|
||||
|
|
|
@ -137,15 +137,13 @@ class Inbox
|
|||
|
||||
public function handleNoteCreate()
|
||||
{
|
||||
return;
|
||||
|
||||
$activity = $this->payload['object'];
|
||||
$actor = $this->actorFirstOrCreate($this->payload['actor']);
|
||||
if(!$actor || $actor->domain == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(Helpers::userInAudience($this->profile, $this->payload) == false) {
|
||||
if($actor->followers()->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ trait User {
|
|||
|
||||
public function getMaxPostsPerHourAttribute()
|
||||
{
|
||||
return 20;
|
||||
return 50;
|
||||
}
|
||||
|
||||
public function getMaxPostsPerDayAttribute()
|
||||
|
|
|
@ -29,5 +29,15 @@ return [
|
|||
]
|
||||
],
|
||||
|
||||
'page' => [
|
||||
'404' => [
|
||||
'header' => env('PAGE_404_HEADER', 'Sorry, this page isn\'t available.'),
|
||||
'body' => env('PAGE_404_BODY', 'The link you followed may be broken, or the page may have been removed. <a href="/">Go back to Pixelfed.</a>')
|
||||
],
|
||||
'503' => [
|
||||
'header' => env('PAGE_503_HEADER', 'Service Unavailable'),
|
||||
'body' => env('PAGE_503_BODY', 'Our service is in maintenance mode, please try again later.')
|
||||
]
|
||||
],
|
||||
|
||||
];
|
16
resources/assets/js/app.js
vendored
16
resources/assets/js/app.js
vendored
|
@ -1 +1,15 @@
|
|||
require('./bootstrap');
|
||||
window._ = require('lodash');
|
||||
window.Popper = require('popper.js').default;
|
||||
window.pixelfed = window.pixelfed || {};
|
||||
window.$ = window.jQuery = require('jquery');
|
||||
require('bootstrap');
|
||||
window.axios = require('axios');
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
require('readmore-js');
|
||||
|
||||
let token = document.head.querySelector('meta[name="csrf-token"]');
|
||||
if (token) {
|
||||
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
|
||||
} else {
|
||||
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
|
||||
}
|
||||
|
|
15
resources/assets/js/bootstrap.js
vendored
15
resources/assets/js/bootstrap.js
vendored
|
@ -1,15 +0,0 @@
|
|||
window._ = require('lodash');
|
||||
window.Popper = require('popper.js').default;
|
||||
window.pixelfed = window.pixelfed || {};
|
||||
window.$ = window.jQuery = require('jquery');
|
||||
require('bootstrap');
|
||||
window.axios = require('axios');
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
require('readmore-js');
|
||||
|
||||
let token = document.head.querySelector('meta[name="csrf-token"]');
|
||||
if (token) {
|
||||
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
|
||||
} else {
|
||||
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
$(document).ready(function() {
|
||||
$(document).on('submit', '.bookmark-form', function(e) {
|
||||
e.preventDefault();
|
||||
var el = $(this);
|
||||
var id = el.data('id');
|
||||
var res = axios.post('/i/bookmark', {item: id});
|
||||
});
|
||||
});
|
51
resources/assets/js/components/commentform.js
vendored
51
resources/assets/js/components/commentform.js
vendored
|
@ -1,51 +0,0 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
$('.status-card > .card-footer').each(function() {
|
||||
$(this).addClass('d-none');
|
||||
});
|
||||
|
||||
$(document).on('click', '.status-comment-focus', function(el) {
|
||||
var form = $(this).parents().eq(2).find('.card-footer');
|
||||
form.removeClass('d-none');
|
||||
var el = $(this).parents().eq(2).find('input[name="comment"]');
|
||||
el.focus();
|
||||
});
|
||||
|
||||
$(document).on('submit', '.comment-form', function(e, data) {
|
||||
e.preventDefault();
|
||||
|
||||
let el = $(this);
|
||||
let id = el.data('id');
|
||||
let commentform = el.find('input[name="comment"]');
|
||||
let commenttext = commentform.val();
|
||||
let item = {item: id, comment: commenttext};
|
||||
|
||||
commentform.prop('disabled', true);
|
||||
axios.post('/i/comment', item)
|
||||
.then(function (res) {
|
||||
|
||||
var username = res.data.username;
|
||||
var permalink = res.data.url;
|
||||
var profile = res.data.profile;
|
||||
var reply = res.data.comment;
|
||||
|
||||
if($('.status-container').length == 1) {
|
||||
var comments = el.parents().eq(3).find('.comments');
|
||||
} else {
|
||||
var comments = el.parents().eq(1).find('.comments');
|
||||
}
|
||||
|
||||
var comment = '<p class="mb-0"><span class="font-weight-bold pr-1"><bdi><a class="text-dark" href="' + profile + '">' + username + '</a></bdi></span><span class="comment-text">'+ reply + '</span></p>';
|
||||
|
||||
comments.prepend(comment);
|
||||
|
||||
commentform.val('');
|
||||
commentform.blur();
|
||||
commentform.prop('disabled', false);
|
||||
|
||||
})
|
||||
.catch(function (res) {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
33
resources/assets/js/components/localstorage.js
vendored
33
resources/assets/js/components/localstorage.js
vendored
|
@ -1,33 +0,0 @@
|
|||
window.ls = {};
|
||||
|
||||
window.ls.get = function(key) {
|
||||
return JSON.parse(localStorage.getItem(key));
|
||||
}
|
||||
|
||||
|
||||
window.ls.set = function(key, val) {
|
||||
try {
|
||||
localStorage.setItem(key, JSON.stringify(val));
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
window.ls.del = function(key) {
|
||||
try {
|
||||
localStorage.removeItem(key);
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
window.ls.clear = function() {
|
||||
try {
|
||||
localStorage.clear();
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
159
resources/assets/js/components/notifications.js
vendored
159
resources/assets/js/components/notifications.js
vendored
|
@ -1,159 +0,0 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
$('.nav-link.nav-notification').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
let el = $(this);
|
||||
if(el.attr('data-toggle') == 'tooltip') {
|
||||
el.attr('data-toggle', 'dropdown');
|
||||
el.tooltip('dispose');
|
||||
}
|
||||
let container = $('.navbar .nav-notification-dropdown');
|
||||
if(pixelfed.notifications) {
|
||||
return;
|
||||
}
|
||||
axios.get('/api/v2/notifications')
|
||||
.then((res) => {
|
||||
$('.nav-notification-dropdown .loader').hide();
|
||||
let data = res.data;
|
||||
data.forEach(function(v, k) {
|
||||
let action = v.action;
|
||||
let notification = $('<li>').addClass('dropdown-item py-3')
|
||||
if(v.read_at == null) {
|
||||
notification.attr('style', 'border: 1px solid #6cb2eb;background-color: #eff8ff;border-bottom:none;');
|
||||
} else {
|
||||
notification.attr('style', 'border-bottom: 1px solid #ccc;');
|
||||
}
|
||||
switch(action) {
|
||||
case 'comment':
|
||||
let avatar = $('<span>')
|
||||
.attr('class', 'notification-icon pr-3');
|
||||
let avatarImg = $('<img>')
|
||||
.attr('width', '32px')
|
||||
.attr('height', '32px')
|
||||
.attr('class', 'rounded-circle')
|
||||
.attr('style', 'border: 1px solid #ccc')
|
||||
.attr('src', v.actor.avatar);
|
||||
avatar = avatar.append(avatarImg);
|
||||
|
||||
let text = $('<span>')
|
||||
.attr('href', v.url)
|
||||
.attr('class', 'font-weight-bold')
|
||||
.html(v.rendered);
|
||||
|
||||
notification.append(avatar);
|
||||
notification.append(text);
|
||||
container.append(notification);
|
||||
break;
|
||||
|
||||
case 'follow':
|
||||
avatar = $('<span>')
|
||||
.attr('class', 'notification-icon pr-3');
|
||||
avatarImg = $('<img>')
|
||||
.attr('width', '32px')
|
||||
.attr('height', '32px')
|
||||
.attr('class', 'rounded-circle')
|
||||
.attr('style', 'border: 1px solid #ccc')
|
||||
.attr('src', v.actor.avatar);
|
||||
avatar = avatar.append(avatarImg);
|
||||
|
||||
text = $('<span>')
|
||||
.attr('href', v.url)
|
||||
.attr('class', 'font-weight-bold')
|
||||
.html(v.rendered);
|
||||
|
||||
notification.append(avatar);
|
||||
notification.append(text);
|
||||
container.append(notification);
|
||||
break;
|
||||
}
|
||||
});
|
||||
let all = $('<a>')
|
||||
.attr('class', 'dropdown-item py-3 text-center text-primary font-weight-bold')
|
||||
.attr('href', '/account/activity')
|
||||
.attr('style', 'border-top:1px solid #ccc')
|
||||
.text('View all notifications');
|
||||
container.append(all);
|
||||
pixelfed.notifications = true;
|
||||
}).catch((err) => {
|
||||
$('.nav-notification-dropdown .loader').addClass('font-weight-bold').text('Something went wrong. Please try again later.');
|
||||
});
|
||||
});
|
||||
|
||||
$('.notification-action[data-type="mark_read"]').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
axios.post('/api/v2/notifications', {
|
||||
'action': 'mark_read'
|
||||
}).then(res => {
|
||||
pixelfed.notifications = false;
|
||||
ls.del('n.lastCheck');
|
||||
ls.del('n.count');
|
||||
swal(
|
||||
'Success!',
|
||||
'All of your notifications have been marked as read.',
|
||||
'success'
|
||||
);
|
||||
}).catch(err => {
|
||||
swal(
|
||||
'Something went wrong!',
|
||||
'An error occurred, please try again later.',
|
||||
'error'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
pixelfed.n.showCount = (count = 1) => {
|
||||
let el = $('.nav-link.nav-notification');
|
||||
el.tooltip('dispose');
|
||||
el.attr('title', count)
|
||||
el.attr('data-toggle', 'tooltip');
|
||||
el.tooltip({
|
||||
template: '<div class="tooltip notification-tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner bg-danger px-3"></div></div>'
|
||||
});
|
||||
setTimeout(function() {
|
||||
el.fadeIn(function() {
|
||||
el.tooltip('show')
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
pixelfed.n.sound = () => {
|
||||
let beep = new Audio('/static/beep.mp3');
|
||||
beep.play();
|
||||
}
|
||||
|
||||
pixelfed.n.check = (count) => {
|
||||
// pixelfed.n.sound();
|
||||
pixelfed.n.showCount(count);
|
||||
}
|
||||
|
||||
pixelfed.n.fetch = (force = false) => {
|
||||
let now = Date.now();
|
||||
let ts = ls.get('n.lastCheck');
|
||||
let count = ls.get('n.count');
|
||||
let offset = now - 9e5;
|
||||
|
||||
if(ts == null) {
|
||||
ts = now;
|
||||
}
|
||||
|
||||
if(!force && count != null || ts > offset) {
|
||||
//pixelfed.n.showCount(count);
|
||||
ls.set('n.lastCheck', ts);
|
||||
return;
|
||||
}
|
||||
|
||||
axios.get('/api/v2/notifications')
|
||||
.then(res => {
|
||||
let len = res.data.length;
|
||||
if(len > 0) {
|
||||
ls.set('n.count', len);
|
||||
ls.set('n.lastCheck', Date.now());
|
||||
pixelfed.n.check(len);
|
||||
}
|
||||
}).catch(err => {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
});
|
126
resources/assets/js/components/statusform.js
vendored
126
resources/assets/js/components/statusform.js
vendored
|
@ -1,126 +0,0 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
pixelfed.create = {};
|
||||
pixelfed.filters = {};
|
||||
pixelfed.create.hasGeneratedSelect = false;
|
||||
pixelfed.create.selectedFilter = false;
|
||||
pixelfed.create.currentFilterName = false;
|
||||
pixelfed.create.currentFilterClass = false;
|
||||
|
||||
pixelfed.filters.list = [
|
||||
['1977','filter-1977'],
|
||||
['Aden','filter-aden'],
|
||||
['Amaro','filter-amaro'],
|
||||
['Ashby','filter-ashby'],
|
||||
['Brannan','filter-brannan'],
|
||||
['Brooklyn','filter-brooklyn'],
|
||||
['Charmes','filter-charmes'],
|
||||
['Clarendon','filter-clarendon'],
|
||||
['Crema','filter-crema'],
|
||||
['Dogpatch','filter-dogpatch'],
|
||||
['Earlybird','filter-earlybird'],
|
||||
['Gingham','filter-gingham'],
|
||||
['Ginza','filter-ginza'],
|
||||
['Hefe','filter-hefe'],
|
||||
['Helena','filter-helena'],
|
||||
['Hudson','filter-hudson'],
|
||||
['Inkwell','filter-inkwell'],
|
||||
['Kelvin','filter-kelvin'],
|
||||
['Kuno','filter-juno'],
|
||||
['Lark','filter-lark'],
|
||||
['Lo-Fi','filter-lofi'],
|
||||
['Ludwig','filter-ludwig'],
|
||||
['Maven','filter-maven'],
|
||||
['Mayfair','filter-mayfair'],
|
||||
['Moon','filter-moon'],
|
||||
['Nashville','filter-nashville'],
|
||||
['Perpetua','filter-perpetua'],
|
||||
['Poprocket','filter-poprocket'],
|
||||
['Reyes','filter-reyes'],
|
||||
['Rise','filter-rise'],
|
||||
['Sierra','filter-sierra'],
|
||||
['Skyline','filter-skyline'],
|
||||
['Slumber','filter-slumber'],
|
||||
['Stinson','filter-stinson'],
|
||||
['Sutro','filter-sutro'],
|
||||
['Toaster','filter-toaster'],
|
||||
['Valencia','filter-valencia'],
|
||||
['Vesper','filter-vesper'],
|
||||
['Walden','filter-walden'],
|
||||
['Willow','filter-willow'],
|
||||
['X-Pro II','filter-xpro-ii']
|
||||
];
|
||||
|
||||
function previewImage(input) {
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
$('.filterPreview').attr('src', e.target.result);
|
||||
}
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
function generateFilterSelect() {
|
||||
let filters = pixelfed.filters.list;
|
||||
for(var i = 0, len = filters.length; i < len; i++) {
|
||||
let filter = filters[i];
|
||||
let name = filter[0];
|
||||
let className = filter[1];
|
||||
let select = $('#filterSelectDropdown');
|
||||
var template = '<option value="' + className + '">' + name + '</option>';
|
||||
select.append(template);
|
||||
}
|
||||
pixelfed.create.hasGeneratedSelect = true;
|
||||
}
|
||||
|
||||
$(document).on('change', '#fileInput', function() {
|
||||
previewImage(this);
|
||||
$('#statusForm .form-filters.d-none').removeClass('d-none');
|
||||
$('#statusForm .form-preview.d-none').removeClass('d-none');
|
||||
$('#statusForm #collapsePreview').collapse('show');
|
||||
if(!pixelfed.create.hasGeneratedSelect) {
|
||||
generateFilterSelect();
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('change', '#filterSelectDropdown', function() {
|
||||
let el = $(this);
|
||||
let filter = el.val();
|
||||
let oldFilter = pixelfed.create.currentFilterClass;
|
||||
if(filter == 'none') {
|
||||
$('input[name=filter_class]').val('');
|
||||
$('input[name=filter_name]').val('');
|
||||
$('.filterContainer').removeClass(oldFilter);
|
||||
pixelfed.create.currentFilterClass = false;
|
||||
pixelfed.create.currentFilterName = 'None';
|
||||
$('.form-group.form-preview .form-text').text('Current Filter: No filter selected');
|
||||
return;
|
||||
} else {
|
||||
$('.filterContainer').removeClass(oldFilter).addClass(filter);
|
||||
pixelfed.create.currentFilterClass = filter;
|
||||
pixelfed.create.currentFilterName = el.find(':selected').text();
|
||||
$('.form-group.form-preview .form-text').text('Current Filter: ' + pixelfed.create.currentFilterName);
|
||||
$('input[name=filter_class]').val(pixelfed.create.currentFilterClass);
|
||||
$('input[name=filter_name]').val(pixelfed.create.currentFilterName);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('keyup keydown', '#statusForm textarea[name=caption]', function() {
|
||||
const el = $(this);
|
||||
const len = el.val().length;
|
||||
const limit = el.data('limit');
|
||||
if(len > limit) {
|
||||
const diff = limit - len;
|
||||
$('#statusForm .caption-counter').text(diff).addClass('text-danger');
|
||||
} else {
|
||||
$('#statusForm .caption-counter').text(len).removeClass('text-danger');
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('focus', '#statusForm textarea[name=caption]', function() {
|
||||
const el = $(this);
|
||||
el.attr('rows', '3');
|
||||
});
|
||||
});
|
|
@ -3,8 +3,8 @@
|
|||
@section('content')
|
||||
<div class="container">
|
||||
<div class="error-page py-5 my-5 text-center">
|
||||
<h3 class="font-weight-bold">Sorry, this page isn't available.</h3>
|
||||
<p class="lead">The link you followed may be broken, or the page may have been removed. <a href="/">Go back to Pixelfed.</a></p>
|
||||
<h3 class="font-weight-bold">{!!config('instance.page.404.header')!!}</h3>
|
||||
<p class="lead">{!!config('instance.page.404.body')!!}</p>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
@section('content')
|
||||
<div class="container">
|
||||
<div class="error-page py-5 my-5 text-center">
|
||||
<h3 class="font-weight-bold">Service Unavailable</h3>
|
||||
<p class="lead">Our service is in maintenance mode, please try again later. <a href="/">Go back to Pixelfed.</a></p>
|
||||
<h3 class="font-weight-bold">{!!config('instance.page.503.header')!!}</h3>
|
||||
<p class="lead">{!!config('instance.page.503.body')!!}</p>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
Loading…
Reference in a new issue