kopia lustrzana https://github.com/pixelfed/pixelfed
commit
f13ba6d08f
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -19,6 +19,8 @@
|
|||
- Add Password change email notification ([de1cca4f](https://github.com/pixelfed/pixelfed/commit/de1cca4f))
|
||||
- Add shared inbox ([4733ca9f](https://github.com/pixelfed/pixelfed/commit/4733ca9f))
|
||||
- Add federated photo filters ([0a5a0e86](https://github.com/pixelfed/pixelfed/commit/0a5a0e86))
|
||||
- Add AccountInterstitial model and controller ([8766ccfe](https://github.com/pixelfed/pixelfed/commit/8766ccfe))
|
||||
- Add Blurhash encoder ([fad102bf](https://github.com/pixelfed/pixelfed/commit/fad102bf))
|
||||
|
||||
### Updated
|
||||
- Updated PostComponent, fix remote urls ([42716ccc](https://github.com/pixelfed/pixelfed/commit/42716ccc))
|
||||
|
@ -106,6 +108,20 @@
|
|||
- Updated federation config, make sharedInbox enabled by default. ([6e3522c0](https://github.com/pixelfed/pixelfed/commit/6e3522c0))
|
||||
- Updated PostComponent, change timestamp format. ([e51665f6](https://github.com/pixelfed/pixelfed/commit/e51665f6))
|
||||
- Updated PostComponent, use proper username context for reply mentions. Fixes ([#2421](https://github.com/pixelfed/pixelfed/issues/2421)). ([dac06088](https://github.com/pixelfed/pixelfed/commit/dac06088))
|
||||
- Updated Navbar, added profile avatar. ([19abf1b4](https://github.com/pixelfed/pixelfed/commit/19abf1b4))
|
||||
- Updated package.json, add blurhash. ([cc1b081a](https://github.com/pixelfed/pixelfed/commit/cc1b081a))
|
||||
- Updated Status model, fix thumb nsfw caching. ([327ef138](https://github.com/pixelfed/pixelfed/commit/327ef138))
|
||||
- Updated User model, add interstitial relation. ([bd321a72](https://github.com/pixelfed/pixelfed/commit/bd321a72))
|
||||
- Updated StatusStatelessTransformer, add missing attributes. ([4d22426d](https://github.com/pixelfed/pixelfed/commit/4d22426d))
|
||||
- Updated media pipeline, add blurhash support. ([473e0495](https://github.com/pixelfed/pixelfed/commit/473e0495))
|
||||
- Updated DeleteAccountPipeline, add AccountInterstitial and DirectMessage purging. ([b3078f27](https://github.com/pixelfed/pixelfed/commit/b3078f27))
|
||||
- Updated ComposeModal.vue component, reuse sharedData. ([e28d022f](https://github.com/pixelfed/pixelfed/commit/e28d022f))
|
||||
- Updated ApiController, return status object after deletion. ([0718711d](https://github.com/pixelfed/pixelfed/commit/0718711d))
|
||||
- Updated InternalApiController, add interstitial logic. ([20681bcf](https://github.com/pixelfed/pixelfed/commit/20681bcf))
|
||||
- Updated PublicApiController, improve stateless object caching. ([342e7a50](https://github.com/pixelfed/pixelfed/commit/342e7a50))
|
||||
- Updated StatusController, add interstitial logic. ([003caf7e](https://github.com/pixelfed/pixelfed/commit/003caf7e))
|
||||
- Updated middleware, add AccountInterstitial support. ([19d6e7df](https://github.com/pixelfed/pixelfed/commit/19d6e7df))
|
||||
- Updated BaseApiController, add favourites method. ([76353ca9](https://github.com/pixelfed/pixelfed/commit/76353ca9))
|
||||
|
||||
## [v0.10.9 (2020-04-17)](https://github.com/pixelfed/pixelfed/compare/v0.10.8...v0.10.9)
|
||||
### Added
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AccountInterstitial extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['read_at', 'appeal_requested_at'];
|
||||
|
||||
public const JSON_MESSAGE = 'Please use web browser to proceed.';
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function status()
|
||||
{
|
||||
if($this->item_type != 'App\Status') {
|
||||
return;
|
||||
}
|
||||
return $this->hasOne(Status::class, 'id', 'item_id');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Status;
|
||||
use App\AccountInterstitial;
|
||||
|
||||
class AccountInterstitialController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
public function get(Request $request)
|
||||
{
|
||||
$interstitial = $request->user()
|
||||
->interstitials()
|
||||
->whereNull('read_at')
|
||||
->first();
|
||||
if(!$interstitial) {
|
||||
$user = $request->user();
|
||||
$user->has_interstitial = false;
|
||||
$user->save();
|
||||
return redirect('/');
|
||||
}
|
||||
$meta = json_decode($interstitial->meta);
|
||||
$view = $interstitial->view;
|
||||
return view($view, compact('interstitial', 'meta'));
|
||||
}
|
||||
|
||||
public function read(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'id' => 'required',
|
||||
'type' => 'required|in:post.cw,post.removed,post.unlist',
|
||||
'action' => 'required|in:appeal,confirm',
|
||||
'appeal_message' => 'nullable|max:500'
|
||||
]);
|
||||
|
||||
$redirect = '/';
|
||||
|
||||
$id = decrypt($request->input('id'));
|
||||
$action = $request->input('action');
|
||||
$user = $request->user();
|
||||
|
||||
$ai = AccountInterstitial::whereUserId($user->id)
|
||||
->whereType($request->input('type'))
|
||||
->findOrFail($id);
|
||||
|
||||
if($action == 'appeal') {
|
||||
$ai->appeal_requested_at = now();
|
||||
$ai->appeal_message = $request->input('appeal_message');
|
||||
}
|
||||
|
||||
$ai->read_at = now();
|
||||
$ai->save();
|
||||
|
||||
$more = AccountInterstitial::whereUserId($user->id)
|
||||
->whereNull('read_at')
|
||||
->exists();
|
||||
|
||||
if(!$more) {
|
||||
$user->has_interstitial = false;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
if(in_array($ai->type, ['post.cw', 'post.unlist'])) {
|
||||
$redirect = Status::findOrFail($ai->item_id)->url();
|
||||
}
|
||||
|
||||
return redirect($redirect);
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use App\{
|
||||
AccountInterstitial,
|
||||
Contact,
|
||||
Hashtag,
|
||||
Newsroom,
|
||||
|
@ -85,6 +86,67 @@ class AdminController extends Controller
|
|||
return view('admin.reports.show', compact('report'));
|
||||
}
|
||||
|
||||
public function appeals(Request $request)
|
||||
{
|
||||
$appeals = AccountInterstitial::whereNotNull('appeal_requested_at')
|
||||
->whereNull('appeal_handled_at')
|
||||
->latest()
|
||||
->paginate(6);
|
||||
return view('admin.reports.appeals', compact('appeals'));
|
||||
}
|
||||
|
||||
public function showAppeal(Request $request, $id)
|
||||
{
|
||||
$appeal = AccountInterstitial::whereNotNull('appeal_requested_at')
|
||||
->whereNull('appeal_handled_at')
|
||||
->findOrFail($id);
|
||||
$meta = json_decode($appeal->meta);
|
||||
return view('admin.reports.show_appeal', compact('appeal', 'meta'));
|
||||
}
|
||||
|
||||
public function updateAppeal(Request $request, $id)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'action' => 'required|in:dismiss,approve'
|
||||
]);
|
||||
|
||||
$action = $request->input('action');
|
||||
$appeal = AccountInterstitial::whereNotNull('appeal_requested_at')
|
||||
->whereNull('appeal_handled_at')
|
||||
->findOrFail($id);
|
||||
|
||||
if($action == 'dismiss') {
|
||||
$appeal->appeal_handled_at = now();
|
||||
$appeal->save();
|
||||
|
||||
return redirect('/i/admin/reports/appeals');
|
||||
}
|
||||
|
||||
switch ($appeal->type) {
|
||||
case 'post.cw':
|
||||
$status = $appeal->status;
|
||||
$status->is_nsfw = false;
|
||||
$status->save();
|
||||
break;
|
||||
|
||||
case 'post.unlist':
|
||||
$status = $appeal->status;
|
||||
$status->scope = 'public';
|
||||
$status->visibility = 'public';
|
||||
$status->save();
|
||||
break;
|
||||
|
||||
default:
|
||||
# code...
|
||||
break;
|
||||
}
|
||||
|
||||
$appeal->appeal_handled_at = now();
|
||||
$appeal->save();
|
||||
|
||||
return redirect('/i/admin/reports/appeals');
|
||||
}
|
||||
|
||||
public function profiles(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
|
|
|
@ -1761,6 +1761,7 @@ class ApiV1Controller extends Controller
|
|||
|
||||
NewStatusPipeline::dispatch($status);
|
||||
Cache::forget('user:account:id:'.$user->id);
|
||||
Cache::forget('_api:statuses:recent_9:'.$user->profile_id);
|
||||
Cache::forget('profile:status_count:'.$user->profile_id);
|
||||
Cache::forget($user->storageUsedKey());
|
||||
|
||||
|
@ -1783,10 +1784,15 @@ class ApiV1Controller extends Controller
|
|||
$status = Status::whereProfileId($request->user()->profile->id)
|
||||
->findOrFail($id);
|
||||
|
||||
$resource = new Fractal\Resource\Item($status, new StatusTransformer());
|
||||
|
||||
Cache::forget('profile:status_count:'.$status->profile_id);
|
||||
StatusDelete::dispatch($status);
|
||||
|
||||
return response()->json(['Status successfully deleted.']);
|
||||
$res = $this->fractal->createData($resource)->toArray();
|
||||
$res['text'] = $res['content'];
|
||||
unset($res['content']);
|
||||
return response()->json($res);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,8 +11,9 @@ use Auth, Cache, Storage, URL;
|
|||
use Carbon\Carbon;
|
||||
use App\{
|
||||
Avatar,
|
||||
Notification,
|
||||
Like,
|
||||
Media,
|
||||
Notification,
|
||||
Profile,
|
||||
Status
|
||||
};
|
||||
|
@ -21,7 +22,8 @@ use App\Transformer\Api\{
|
|||
NotificationTransformer,
|
||||
MediaTransformer,
|
||||
MediaDraftTransformer,
|
||||
StatusTransformer
|
||||
StatusTransformer,
|
||||
StatusStatelessTransformer
|
||||
};
|
||||
use League\Fractal;
|
||||
use App\Util\Media\Filter;
|
||||
|
@ -338,4 +340,29 @@ class BaseApiController extends Controller
|
|||
$res = $this->fractal->createData($resource)->toArray();
|
||||
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
public function accountLikes(Request $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
abort_if(!$request->user(), 403);
|
||||
|
||||
$limit = 10;
|
||||
$page = (int) $request->input('page', 1);
|
||||
|
||||
if($page > 20) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$favourites = $user->profile->likes()
|
||||
->latest()
|
||||
->simplePaginate($limit)
|
||||
->pluck('status_id');
|
||||
|
||||
$statuses = Status::find($favourites)->reverse();
|
||||
|
||||
$resource = new Fractal\Resource\Collection($statuses, new StatusStatelessTransformer());
|
||||
$res = $this->fractal->createData($resource)->toArray();
|
||||
|
||||
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
|||
|
||||
use Illuminate\Http\Request;
|
||||
use App\{
|
||||
AccountInterstitial,
|
||||
DirectMessage,
|
||||
DiscoverCategory,
|
||||
Hashtag,
|
||||
|
@ -213,6 +214,35 @@ class InternalApiController extends Controller
|
|||
])
|
||||
->accessLevel('admin')
|
||||
->save();
|
||||
|
||||
|
||||
if($status->uri == null) {
|
||||
$media = $status->media;
|
||||
$ai = new AccountInterstitial;
|
||||
$ai->user_id = $status->profile->user_id;
|
||||
$ai->type = 'post.cw';
|
||||
$ai->view = 'account.moderation.post.cw';
|
||||
$ai->item_type = 'App\Status';
|
||||
$ai->item_id = $status->id;
|
||||
$ai->has_media = (bool) $media->count();
|
||||
$ai->blurhash = $media->count() ? $media->first()->blurhash : null;
|
||||
$ai->meta = json_encode([
|
||||
'caption' => $status->caption,
|
||||
'created_at' => $status->created_at,
|
||||
'type' => $status->type,
|
||||
'url' => $status->url(),
|
||||
'is_nsfw' => $status->is_nsfw,
|
||||
'scope' => $status->scope,
|
||||
'reblog' => $status->reblog_of_id,
|
||||
'likes_count' => $status->likes_count,
|
||||
'reblogs_count' => $status->reblogs_count,
|
||||
]);
|
||||
$ai->save();
|
||||
|
||||
$u = $status->profile->user;
|
||||
$u->has_interstitial = true;
|
||||
$u->save();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'remcw':
|
||||
|
@ -231,6 +261,14 @@ class InternalApiController extends Controller
|
|||
])
|
||||
->accessLevel('admin')
|
||||
->save();
|
||||
if($status->uri == null) {
|
||||
$ai = AccountInterstitial::whereUserId($status->profile->user_id)
|
||||
->whereType('post.cw')
|
||||
->whereItemId($status->id)
|
||||
->whereItemType('App\Status')
|
||||
->first();
|
||||
$ai->delete();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'unlist':
|
||||
|
@ -250,6 +288,34 @@ class InternalApiController extends Controller
|
|||
])
|
||||
->accessLevel('admin')
|
||||
->save();
|
||||
|
||||
if($status->uri == null) {
|
||||
$media = $status->media;
|
||||
$ai = new AccountInterstitial;
|
||||
$ai->user_id = $status->profile->user_id;
|
||||
$ai->type = 'post.unlist';
|
||||
$ai->view = 'account.moderation.post.unlist';
|
||||
$ai->item_type = 'App\Status';
|
||||
$ai->item_id = $status->id;
|
||||
$ai->has_media = (bool) $media->count();
|
||||
$ai->blurhash = $media->count() ? $media->first()->blurhash : null;
|
||||
$ai->meta = json_encode([
|
||||
'caption' => $status->caption,
|
||||
'created_at' => $status->created_at,
|
||||
'type' => $status->type,
|
||||
'url' => $status->url(),
|
||||
'is_nsfw' => $status->is_nsfw,
|
||||
'scope' => $status->scope,
|
||||
'reblog' => $status->reblog_of_id,
|
||||
'likes_count' => $status->likes_count,
|
||||
'reblogs_count' => $status->reblogs_count,
|
||||
]);
|
||||
$ai->save();
|
||||
|
||||
$u = $status->profile->user;
|
||||
$u->has_interstitial = true;
|
||||
$u->save();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ['msg' => 200];
|
||||
|
@ -364,6 +430,7 @@ class InternalApiController extends Controller
|
|||
|
||||
NewStatusPipeline::dispatch($status);
|
||||
Cache::forget('user:account:id:'.$profile->user_id);
|
||||
Cache::forget('_api:statuses:recent_9:'.$profile->id);
|
||||
Cache::forget('profile:status_count:'.$profile->id);
|
||||
Cache::forget($user->storageUsedKey());
|
||||
return $status->url();
|
||||
|
|
|
@ -66,7 +66,9 @@ class ProfileController extends Controller
|
|||
'list' => $settings->show_profile_followers
|
||||
]
|
||||
];
|
||||
return view('profile.show', compact('profile', 'settings'));
|
||||
$ui = $request->has('ui') && $request->input('ui') == 'memory' ? 'profile.memory' : 'profile.show';
|
||||
|
||||
return view($ui, compact('profile', 'settings'));
|
||||
} else {
|
||||
$key = 'profile:settings:' . $user->id;
|
||||
$ttl = now()->addHours(6);
|
||||
|
@ -103,7 +105,8 @@ class ProfileController extends Controller
|
|||
'list' => $settings->show_profile_followers
|
||||
]
|
||||
];
|
||||
return view('profile.show', compact('profile', 'settings'));
|
||||
$ui = $request->has('ui') && $request->input('ui') == 'memory' ? 'profile.memory' : 'profile.show';
|
||||
return view($ui, compact('profile', 'settings'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@ use League\Fractal;
|
|||
use App\Transformer\Api\{
|
||||
AccountTransformer,
|
||||
RelationshipTransformer,
|
||||
StatusTransformer
|
||||
StatusTransformer,
|
||||
StatusStatelessTransformer
|
||||
};
|
||||
use App\Services\{
|
||||
AccountService,
|
||||
|
@ -86,6 +87,24 @@ class PublicApiController extends Controller
|
|||
$profile = Profile::whereUsername($username)->whereNull('status')->firstOrFail();
|
||||
$status = Status::whereProfileId($profile->id)->findOrFail($postid);
|
||||
$this->scopeCheck($profile, $status);
|
||||
if(!Auth::check()) {
|
||||
$res = Cache::remember('wapi:v1:status:stateless_byid:' . $status->id, now()->addMinutes(30), function() use($status) {
|
||||
$item = new Fractal\Resource\Item($status, new StatusStatelessTransformer());
|
||||
$res = [
|
||||
'status' => $this->fractal->createData($item)->toArray(),
|
||||
'user' => [],
|
||||
'likes' => [],
|
||||
'shares' => [],
|
||||
'reactions' => [
|
||||
'liked' => false,
|
||||
'shared' => false,
|
||||
'bookmarked' => false,
|
||||
],
|
||||
];
|
||||
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
||||
});
|
||||
return $res;
|
||||
}
|
||||
$item = new Fractal\Resource\Item($status, new StatusTransformer());
|
||||
$res = [
|
||||
'status' => $this->fractal->createData($item)->toArray(),
|
||||
|
@ -419,7 +438,6 @@ class PublicApiController extends Controller
|
|||
|
||||
}
|
||||
|
||||
|
||||
public function networkTimelineApi(Request $request)
|
||||
{
|
||||
return response()->json([]);
|
||||
|
@ -543,6 +561,50 @@ class PublicApiController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
$tag = in_array('private', $visibility) ? 'private' : 'public';
|
||||
if($min_id == 1 && $limit == 9 && $tag == 'public') {
|
||||
$limit = 9;
|
||||
$scope = ['photo', 'photo:album', 'video', 'video:album'];
|
||||
$key = '_api:statuses:recent_9:'.$profile->id;
|
||||
$res = Cache::remember($key, now()->addHours(24), function() use($profile, $scope, $visibility, $limit) {
|
||||
$dir = '>';
|
||||
$id = 1;
|
||||
$timeline = Status::select(
|
||||
'id',
|
||||
'uri',
|
||||
'caption',
|
||||
'rendered',
|
||||
'profile_id',
|
||||
'type',
|
||||
'in_reply_to_id',
|
||||
'reblog_of_id',
|
||||
'is_nsfw',
|
||||
'likes_count',
|
||||
'reblogs_count',
|
||||
'scope',
|
||||
'visibility',
|
||||
'local',
|
||||
'place_id',
|
||||
'comments_disabled',
|
||||
'cw_summary',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
)->whereProfileId($profile->id)
|
||||
->whereIn('type', $scope)
|
||||
->where('id', $dir, $id)
|
||||
->whereIn('visibility', $visibility)
|
||||
->limit($limit)
|
||||
->orderByDesc('id')
|
||||
->get();
|
||||
|
||||
$resource = new Fractal\Resource\Collection($timeline, new StatusStatelessTransformer());
|
||||
$res = $this->fractal->createData($resource)->toArray();
|
||||
|
||||
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
||||
});
|
||||
return $res;
|
||||
}
|
||||
|
||||
$dir = $min_id ? '>' : '<';
|
||||
$id = $min_id ?? $max_id;
|
||||
$timeline = Status::select(
|
||||
|
@ -560,6 +622,8 @@ class PublicApiController extends Controller
|
|||
'scope',
|
||||
'visibility',
|
||||
'local',
|
||||
'place_id',
|
||||
'comments_disabled',
|
||||
'cw_summary',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
|
|
|
@ -6,6 +6,7 @@ use App\Jobs\ImageOptimizePipeline\ImageOptimize;
|
|||
use App\Jobs\StatusPipeline\NewStatusPipeline;
|
||||
use App\Jobs\StatusPipeline\StatusDelete;
|
||||
use App\Jobs\SharePipeline\SharePipeline;
|
||||
use App\AccountInterstitial;
|
||||
use App\Media;
|
||||
use App\Profile;
|
||||
use App\Status;
|
||||
|
@ -162,14 +163,49 @@ class StatusController extends Controller
|
|||
|
||||
$status = Status::findOrFail($request->input('item'));
|
||||
|
||||
if ($status->profile_id === Auth::user()->profile->id || Auth::user()->is_admin == true) {
|
||||
$user = Auth::user();
|
||||
|
||||
if($status->profile_id != $user->profile->id &&
|
||||
$user->is_admin == true &&
|
||||
$status->uri == null
|
||||
) {
|
||||
$media = $status->media;
|
||||
|
||||
$ai = new AccountInterstitial;
|
||||
$ai->user_id = $status->profile->user_id;
|
||||
$ai->type = 'post.removed';
|
||||
$ai->view = 'account.moderation.post.removed';
|
||||
$ai->item_type = 'App\Status';
|
||||
$ai->item_id = $status->id;
|
||||
$ai->has_media = (bool) $media->count();
|
||||
$ai->blurhash = $media->count() ? $media->first()->blurhash : null;
|
||||
$ai->meta = json_encode([
|
||||
'caption' => $status->caption,
|
||||
'created_at' => $status->created_at,
|
||||
'type' => $status->type,
|
||||
'url' => $status->url(),
|
||||
'is_nsfw' => $status->is_nsfw,
|
||||
'scope' => $status->scope,
|
||||
'reblog' => $status->reblog_of_id,
|
||||
'likes_count' => $status->likes_count,
|
||||
'reblogs_count' => $status->reblogs_count,
|
||||
]);
|
||||
$ai->save();
|
||||
|
||||
$u = $status->profile->user;
|
||||
$u->has_interstitial = true;
|
||||
$u->save();
|
||||
}
|
||||
|
||||
if ($status->profile_id == $user->profile->id || $user->is_admin == true) {
|
||||
Cache::forget('profile:status_count:'.$status->profile_id);
|
||||
StatusDelete::dispatch($status);
|
||||
}
|
||||
|
||||
if($request->wantsJson()) {
|
||||
return response()->json(['Status successfully deleted.']);
|
||||
} else {
|
||||
return redirect(Auth::user()->url());
|
||||
return redirect($user->url());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ class Kernel extends HttpKernel
|
|||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'twofactor' => \App\Http\Middleware\TwoFactorAuth::class,
|
||||
'validemail' => \App\Http\Middleware\EmailVerificationCheck::class,
|
||||
'interstitial' => \App\Http\Middleware\AccountInterstitial::class,
|
||||
// 'restricted' => \App\Http\Middleware\RestrictedAccess::class,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Auth;
|
||||
use App\User;
|
||||
|
||||
class AccountInterstitial
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$ar = [
|
||||
'login',
|
||||
'logout',
|
||||
'password*',
|
||||
'loginAs*',
|
||||
'i/warning*',
|
||||
'i/auth/checkpoint',
|
||||
'i/auth/sudo',
|
||||
'site/privacy',
|
||||
'site/terms',
|
||||
'site/kb/community-guidelines',
|
||||
];
|
||||
|
||||
if(Auth::check() && !$request->is($ar)) {
|
||||
if($request->user()->has_interstitial) {
|
||||
if($request->wantsJson()) {
|
||||
$res = ['_refresh'=>true,'error' => 403, 'message' => \App\AccountInterstitial::JSON_MESSAGE];
|
||||
return response()->json($res, 403);
|
||||
} else {
|
||||
return redirect('/i/warning');
|
||||
}
|
||||
} else {
|
||||
return $next($request);
|
||||
}
|
||||
} else {
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
|
|||
use DB;
|
||||
use Illuminate\Support\Str;
|
||||
use App\{
|
||||
AccountInterstitial,
|
||||
AccountLog,
|
||||
Activity,
|
||||
Avatar,
|
||||
|
@ -68,6 +69,10 @@ class DeleteAccountPipeline implements ShouldQueue
|
|||
});
|
||||
});
|
||||
|
||||
DB::transaction(function() use ($user) {
|
||||
AccountInterstitial::whereUserId($user->id)->delete();
|
||||
});
|
||||
|
||||
DB::transaction(function() use ($user) {
|
||||
if($user->profile) {
|
||||
$avatar = $user->profile->avatar;
|
||||
|
@ -79,6 +84,7 @@ class DeleteAccountPipeline implements ShouldQueue
|
|||
Bookmark::whereProfileId($user->profile_id)->forceDelete();
|
||||
EmailVerification::whereUserId($user->id)->forceDelete();
|
||||
StatusHashtag::whereProfileId($id)->delete();
|
||||
DirectMessage::whereFromId($user->profile_id)->delete();
|
||||
FollowRequest::whereFollowingId($id)
|
||||
->orWhere('follower_id', $id)
|
||||
->forceDelete();
|
||||
|
|
|
@ -89,7 +89,8 @@ class Status extends Model
|
|||
|
||||
public function thumb($showNsfw = false)
|
||||
{
|
||||
return Cache::remember('status:thumb:'.$this->id, now()->addMinutes(15), function() use ($showNsfw) {
|
||||
$key = $showNsfw ? 'status:thumb:nsfw1'.$this->id : 'status:thumb:nsfw0'.$this->id;
|
||||
return Cache::remember($key, now()->addMinutes(15), function() use ($showNsfw) {
|
||||
$type = $this->type ?? $this->setType();
|
||||
$is_nsfw = !$showNsfw ? $this->is_nsfw : false;
|
||||
if ($this->media->count() == 0 || $is_nsfw || !in_array($type,['photo', 'photo:album', 'video'])) {
|
||||
|
|
|
@ -5,6 +5,8 @@ namespace App\Transformer\Api;
|
|||
use App\Status;
|
||||
use League\Fractal;
|
||||
use Cache;
|
||||
use App\Services\HashidService;
|
||||
use App\Services\MediaTagService;
|
||||
|
||||
class StatusStatelessTransformer extends Fractal\TransformerAbstract
|
||||
{
|
||||
|
@ -17,8 +19,11 @@ class StatusStatelessTransformer extends Fractal\TransformerAbstract
|
|||
|
||||
public function transform(Status $status)
|
||||
{
|
||||
$taggedPeople = MediaTagService::get($status->id);
|
||||
|
||||
return [
|
||||
'id' => (string) $status->id,
|
||||
'shortcode' => HashidService::encode($status->id),
|
||||
'uri' => $status->url(),
|
||||
'url' => $status->url(),
|
||||
'in_reply_to_id' => $status->in_reply_to_id,
|
||||
|
@ -42,13 +47,17 @@ class StatusStatelessTransformer extends Fractal\TransformerAbstract
|
|||
'language' => null,
|
||||
'pinned' => null,
|
||||
|
||||
'mentions' => [],
|
||||
'tags' => [],
|
||||
'pf_type' => $status->type ?? $status->setType(),
|
||||
'reply_count' => (int) $status->reply_count,
|
||||
'comments_disabled' => $status->comments_disabled ? true : false,
|
||||
'thread' => false,
|
||||
'replies' => [],
|
||||
'parent' => $status->parent() ? $this->transform($status->parent()) : [],
|
||||
'parent' => [],
|
||||
'place' => $status->place,
|
||||
'local' => (bool) $status->local,
|
||||
'taggedPeople' => $taggedPeople
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -88,4 +88,9 @@ class User extends Authenticatable
|
|||
return $this->hasMany(AccountLog::class);
|
||||
}
|
||||
|
||||
public function interstitials()
|
||||
{
|
||||
return $this->hasMany(AccountInterstitial::class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace App\Util\Blurhash;
|
||||
|
||||
final class AC {
|
||||
|
||||
public static function encode(array $value, float $max_value): float {
|
||||
$quant_r = static::quantise($value[0] / $max_value);
|
||||
$quant_g = static::quantise($value[1] / $max_value);
|
||||
$quant_b = static::quantise($value[2] / $max_value);
|
||||
return $quant_r * 19 * 19 + $quant_g * 19 + $quant_b;
|
||||
}
|
||||
|
||||
public static function decode(int $value, float $max_value): array {
|
||||
$quant_r = floor($value / (19 * 19));
|
||||
$quant_g = floor($value / 19) % 19;
|
||||
$quant_b = $value % 19;
|
||||
|
||||
return [
|
||||
static::signPow(($quant_r - 9) / 9, 2) * $max_value,
|
||||
static::signPow(($quant_g - 9) / 9, 2) * $max_value,
|
||||
static::signPow(($quant_b - 9) / 9, 2) * $max_value
|
||||
];
|
||||
}
|
||||
|
||||
private static function quantise(float $value): float {
|
||||
return floor(max(0, min(18, floor(static::signPow($value, 0.5) * 9 + 9.5))));
|
||||
}
|
||||
|
||||
private static function signPow(float $base, float $exp): float {
|
||||
$sign = $base <=> 0;
|
||||
return $sign * pow(abs($base), $exp);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace App\Util\Blurhash;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Base83 {
|
||||
private const ALPHABET = [
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
|
||||
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
|
||||
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'x', 'y', 'z', '#', '$', '%', '*', '+', ',', '-', '.',
|
||||
':', ';', '=', '?', '@', '[', ']', '^', '_', '{', '|', '}', '~'
|
||||
];
|
||||
|
||||
private const BASE = 83;
|
||||
|
||||
public static function encode(int $value, int $length): string {
|
||||
if (floor($value / (self::BASE ** $length)) != 0) {
|
||||
throw new InvalidArgumentException('Specified length is too short to encode given value.');
|
||||
}
|
||||
|
||||
$result = '';
|
||||
for ($i = 1; $i <= $length; $i++) {
|
||||
$digit = floor($value / (self::BASE ** ($length - $i))) % self::BASE;
|
||||
$result .= self::ALPHABET[$digit];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function decode(string $hash): int {
|
||||
$result = 0;
|
||||
foreach (str_split($hash) as $char) {
|
||||
$result = $result * self::BASE + (int) array_search($char, self::ALPHABET, true);
|
||||
}
|
||||
return (int) $result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
namespace App\Util\Blurhash;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Blurhash {
|
||||
|
||||
public static function encode(array $image, int $components_x = 4, int $components_y = 4, bool $linear = false): string {
|
||||
if (($components_x < 1 || $components_x > 9) || ($components_y < 1 || $components_y > 9)) {
|
||||
throw new InvalidArgumentException("x and y component counts must be between 1 and 9 inclusive.");
|
||||
}
|
||||
$height = count($image);
|
||||
$width = count($image[0]);
|
||||
|
||||
$image_linear = $image;
|
||||
if (!$linear) {
|
||||
$image_linear = [];
|
||||
for ($y = 0; $y < $height; $y++) {
|
||||
$line = [];
|
||||
for ($x = 0; $x < $width; $x++) {
|
||||
$pixel = $image[$y][$x];
|
||||
$line[] = [
|
||||
Color::toLinear($pixel[0]),
|
||||
Color::toLinear($pixel[1]),
|
||||
Color::toLinear($pixel[2])
|
||||
];
|
||||
}
|
||||
$image_linear[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
$components = [];
|
||||
$scale = 1 / ($width * $height);
|
||||
for ($y = 0; $y < $components_y; $y++) {
|
||||
for ($x = 0; $x < $components_x; $x++) {
|
||||
$normalisation = $x == 0 && $y == 0 ? 1 : 2;
|
||||
$r = $g = $b = 0;
|
||||
for ($i = 0; $i < $width; $i++) {
|
||||
for ($j = 0; $j < $height; $j++) {
|
||||
$color = $image_linear[$j][$i];
|
||||
$basis = $normalisation
|
||||
* cos(M_PI * $i * $x / $width)
|
||||
* cos(M_PI * $j * $y / $height);
|
||||
|
||||
$r += $basis * $color[0];
|
||||
$g += $basis * $color[1];
|
||||
$b += $basis * $color[2];
|
||||
}
|
||||
}
|
||||
|
||||
$components[] = [
|
||||
$r * $scale,
|
||||
$g * $scale,
|
||||
$b * $scale
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$dc_value = DC::encode(array_shift($components) ?: []);
|
||||
|
||||
$max_ac_component = 0;
|
||||
foreach ($components as $component) {
|
||||
$component[] = $max_ac_component;
|
||||
$max_ac_component = max ($component);
|
||||
}
|
||||
|
||||
$quant_max_ac_component = (int) max(0, min(82, floor($max_ac_component * 166 - 0.5)));
|
||||
$ac_component_norm_factor = ($quant_max_ac_component + 1) / 166;
|
||||
|
||||
$ac_values = [];
|
||||
foreach ($components as $component) {
|
||||
$ac_values[] = AC::encode($component, $ac_component_norm_factor);
|
||||
}
|
||||
|
||||
$blurhash = Base83::encode($components_x - 1 + ($components_y - 1) * 9, 1);
|
||||
$blurhash .= Base83::encode($quant_max_ac_component, 1);
|
||||
$blurhash .= Base83::encode($dc_value, 4);
|
||||
foreach ($ac_values as $ac_value) {
|
||||
$blurhash .= Base83::encode((int) $ac_value, 2);
|
||||
}
|
||||
|
||||
return $blurhash;
|
||||
}
|
||||
|
||||
public static function decode (string $blurhash, int $width, int $height, float $punch = 1.0, bool $linear = false): array {
|
||||
if (empty($blurhash) || strlen($blurhash) < 6) {
|
||||
throw new InvalidArgumentException("Blurhash string must be at least 6 characters");
|
||||
}
|
||||
|
||||
$size_info = Base83::decode($blurhash[0]);
|
||||
$size_y = floor($size_info / 9) + 1;
|
||||
$size_x = ($size_info % 9) + 1;
|
||||
|
||||
$length = (int) strlen($blurhash);
|
||||
$expected_length = (int) (4 + (2 * $size_y * $size_x));
|
||||
if ($length !== $expected_length) {
|
||||
throw new InvalidArgumentException("Blurhash length mismatch: length is {$length} but it should be {$expected_length}");
|
||||
}
|
||||
|
||||
$colors = [DC::decode(Base83::decode(substr($blurhash, 2, 4)))];
|
||||
|
||||
$quant_max_ac_component = Base83::decode($blurhash[1]);
|
||||
$max_value = ($quant_max_ac_component + 1) / 166;
|
||||
for ($i = 1; $i < $size_x * $size_y; $i++) {
|
||||
$value = Base83::decode(substr($blurhash, 4 + $i * 2, 2));
|
||||
$colors[$i] = AC::decode($value, $max_value * $punch);
|
||||
}
|
||||
|
||||
$pixels = [];
|
||||
for ($y = 0; $y < $height; $y++) {
|
||||
$row = [];
|
||||
for ($x = 0; $x < $width; $x++) {
|
||||
$r = $g = $b = 0;
|
||||
for ($j = 0; $j < $size_y; $j++) {
|
||||
for ($i = 0; $i < $size_x; $i++) {
|
||||
$color = $colors[$i + $j * $size_x];
|
||||
$basis =
|
||||
cos((M_PI * $x * $i) / $width) *
|
||||
cos((M_PI * $y * $j) / $height);
|
||||
|
||||
$r += $color[0] * $basis;
|
||||
$g += $color[1] * $basis;
|
||||
$b += $color[2] * $basis;
|
||||
}
|
||||
}
|
||||
|
||||
$row[] = $linear ? [$r, $g, $b] : [
|
||||
Color::toSRGB($r),
|
||||
Color::toSRGB($g),
|
||||
Color::toSRGB($b)
|
||||
];
|
||||
}
|
||||
$pixels[] = $row;
|
||||
}
|
||||
|
||||
return $pixels;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Util\Blurhash;
|
||||
|
||||
final class Color {
|
||||
public static function toLinear(int $value): float {
|
||||
$value = $value / 255;
|
||||
return ($value <= 0.04045)
|
||||
? $value / 12.92
|
||||
: pow(($value + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
public static function tosRGB(float $value): int {
|
||||
$normalized = max(0, min(1, $value));
|
||||
return ($normalized <= 0.0031308)
|
||||
? (int) round($normalized * 12.92 * 255 + 0.5)
|
||||
: (int) round((1.055 * pow($normalized, 1 / 2.4) - 0.055) * 255 + 0.5);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace App\Util\Blurhash;
|
||||
|
||||
final class DC {
|
||||
|
||||
public static function encode(array $value): int {
|
||||
$rounded_r = Color::tosRGB($value[0]);
|
||||
$rounded_g = Color::tosRGB($value[1]);
|
||||
$rounded_b = Color::tosRGB($value[2]);
|
||||
return ($rounded_r << 16) + ($rounded_g << 8) + $rounded_b;
|
||||
}
|
||||
|
||||
public static function decode(int $value): array {
|
||||
$r = $value >> 16;
|
||||
$g = ($value >> 8) & 255;
|
||||
$b = $value & 255;
|
||||
return [
|
||||
Color::toLinear($r),
|
||||
Color::toLinear($g),
|
||||
Color::toLinear($b)
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace App\Util\Media;
|
||||
|
||||
use App\Util\Blurhash\Blurhash as BlurhashEngine;
|
||||
use App\Media;
|
||||
|
||||
class Blurhash {
|
||||
|
||||
public static function generate(Media $media)
|
||||
{
|
||||
if(!in_array($media->mime, ['image/png', 'image/jpeg'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$file = storage_path('app/' . $media->thumbnail_path);
|
||||
|
||||
if(!is_file($file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$image = imagecreatefromstring(file_get_contents($file));
|
||||
$width = imagesx($image);
|
||||
$height = imagesy($image);
|
||||
|
||||
$pixels = [];
|
||||
for ($y = 0; $y < $height; ++$y) {
|
||||
$row = [];
|
||||
for ($x = 0; $x < $width; ++$x) {
|
||||
$index = imagecolorat($image, $x, $y);
|
||||
$colors = imagecolorsforindex($image, $index);
|
||||
|
||||
$row[] = [$colors['red'], $colors['green'], $colors['blue']];
|
||||
}
|
||||
$pixels[] = $row;
|
||||
}
|
||||
|
||||
$components_x = 4;
|
||||
$components_y = 4;
|
||||
$blurhash = BlurhashEngine::encode($pixels, $components_x, $components_y);
|
||||
if(strlen($blurhash) > 191) {
|
||||
return;
|
||||
}
|
||||
return $blurhash;
|
||||
}
|
||||
|
||||
}
|
|
@ -182,6 +182,10 @@ class Image
|
|||
|
||||
|
||||
$media->save();
|
||||
|
||||
if($thumbnail) {
|
||||
$this->generateBlurhash($media);
|
||||
}
|
||||
Cache::forget('status:transformer:media:attachments:'.$media->status_id);
|
||||
Cache::forget('status:thumb:'.$media->status_id);
|
||||
} catch (Exception $e) {
|
||||
|
@ -198,4 +202,13 @@ class Image
|
|||
|
||||
return ['path' => $basePath, 'png' => $png];
|
||||
}
|
||||
|
||||
protected function generateBlurhash($media)
|
||||
{
|
||||
$blurhash = Blurhash::generate($media);
|
||||
if($blurhash) {
|
||||
$media->blurhash = $blurhash;
|
||||
$media->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddIndexesToLikesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('likes', function (Blueprint $table) {
|
||||
$table->index('profile_id', 'likes_profile_id_index');
|
||||
$table->index('status_id', 'likes_status_id_index');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('likes', function (Blueprint $table) {
|
||||
$table->dropIndex('likes_profile_id_index');
|
||||
$table->dropIndex('likes_status_id_index');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateAccountInterstitialsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('account_interstitials', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedInteger('user_id')->nullable()->index();
|
||||
$table->string('type')->nullable();
|
||||
$table->string('view')->nullable();
|
||||
$table->bigInteger('item_id')->unsigned()->nullable();
|
||||
$table->string('item_type')->nullable();
|
||||
$table->boolean('has_media')->default(false)->nullable();
|
||||
$table->string('blurhash')->nullable();
|
||||
$table->text('message')->nullable();
|
||||
$table->text('violation_header')->nullable();
|
||||
$table->text('violation_body')->nullable();
|
||||
$table->json('meta')->nullable();
|
||||
$table->text('appeal_message')->nullable();
|
||||
$table->timestamp('appeal_requested_at')->nullable()->index();
|
||||
$table->timestamp('appeal_handled_at')->nullable()->index();
|
||||
$table->timestamp('read_at')->nullable()->index();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::table('users', function(Blueprint $table) {
|
||||
$table->boolean('has_interstitial')->default(false)->index();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('account_interstitials');
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('has_interstitial');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1649,6 +1649,11 @@
|
|||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz",
|
||||
"integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg=="
|
||||
},
|
||||
"blurhash": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/blurhash/-/blurhash-1.1.3.tgz",
|
||||
"integrity": "sha512-yUhPJvXexbqbyijCIE/T2NCXcj9iNPhWmOKbPTuR/cm7Q5snXYIfnVnz6m7MWOXxODMz/Cr3UcVkRdHiuDVRDw=="
|
||||
},
|
||||
"bn.js": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz",
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
"dependencies": {
|
||||
"@trevoreyre/autocomplete-vue": "^2.2.0",
|
||||
"animate.css": "^4.1.0",
|
||||
"blurhash": "^1.1.3",
|
||||
"bootstrap-vue": "^2.16.0",
|
||||
"filesize": "^3.6.1",
|
||||
"howler": "^2.2.0",
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
(window.webpackJsonp=window.webpackJsonp||[]).push([[17],{19:function(t,e,s){t.exports=s("ETg6")},"7wkd":function(t,e,s){"use strict";s.r(e);var o={data:function(){return{loaded:!1,showLoadMore:!0,profiles:[],page:1}},beforeMount:function(){this.fetchData()},methods:{fetchData:function(){var t=this;axios.get("/api/pixelfed/v2/discover/profiles",{params:{page:this.page}}).then((function(e){if(0==e.data.length)return t.showLoadMore=!1,void(t.loaded=!0);t.profiles=e.data,t.showLoadMore=8==t.profiles.length,t.loaded=!0}))},prettyCount:function(t){return App.util.format.count(t)},loadMore:function(){this.loaded=!1,this.page++,this.fetchData()},thumbUrl:function(t){return t.media_attachments[0].url}}},a=s("KHd+"),n=Object(a.a)(o,(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",[s("div",{staticClass:"col-12"},[s("p",{staticClass:"font-weight-bold text-lighter text-uppercase"},[t._v("Profiles Directory")]),t._v(" "),t.loaded?s("div",{},[s("div",{staticClass:"row"},[t._l(t.profiles,(function(e,o){return s("div",{staticClass:"col-12 col-md-6 p-1"},[s("div",{staticClass:"card card-body border shadow-none py-2"},[s("div",{staticClass:"media"},[s("a",{attrs:{href:e.url}},[s("img",{staticClass:"rounded-circle border mr-3",attrs:{src:e.avatar,alt:"...",width:"40px",height:"40px"}})]),t._v(" "),s("div",{staticClass:"media-body"},[s("p",{staticClass:"mt-0 mb-0 font-weight-bold"},[s("a",{staticClass:"text-dark",attrs:{href:e.url}},[t._v(t._s(e.username))])]),t._v(" "),s("p",{staticClass:"mb-1 small text-lighter d-flex justify-content-between font-weight-bold"},[s("span",[s("span",[t._v(t._s(t.prettyCount(e.statuses_count)))]),t._v(" POSTS\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),s("span",[s("span",[t._v(t._s(t.prettyCount(e.followers_count)))]),t._v(" FOLLOWERS\n\t\t\t\t\t\t\t\t\t")])]),t._v(" "),s("p",{staticClass:"mb-1"},t._l(e.posts,(function(e,o){return s("span",{key:"profile_posts_"+o,staticClass:"shadow-sm"},[s("a",{staticClass:"text-decoration-none mr-1",attrs:{href:e.url}},[s("img",{staticClass:"border rounded",attrs:{src:t.thumbUrl(e),width:"62.3px",height:"62.3px"}})])])})),0)])])])])})),t._v(" "),t.showLoadMore?s("div",{staticClass:"col-12"},[s("p",{staticClass:"text-center mb-0 pt-3"},[s("button",{staticClass:"btn btn-outline-secondary btn-sm px-4 py-1 font-weight-bold",on:{click:function(e){return t.loadMore()}}},[t._v("Load More")])])]):t._e()],2)]):s("div",[t._m(0)])])])}),[function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"row"},[e("div",{staticClass:"col-12 d-flex justify-content-center align-items-center"},[e("div",{staticClass:"spinner-border",attrs:{role:"status"}},[e("span",{staticClass:"sr-only"},[this._v("Loading...")])])])])}],!1,null,"7b3eea1c",null);e.default=n.exports},ETg6:function(t,e,s){Vue.component("profile-directory",s("7wkd").default)},"KHd+":function(t,e,s){"use strict";function o(t,e,s,o,a,n,r,i){var c,d="function"==typeof t?t.options:t;if(e&&(d.render=e,d.staticRenderFns=s,d._compiled=!0),o&&(d.functional=!0),n&&(d._scopeId="data-v-"+n),r?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),a&&a.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(r)},d._ssrRegister=c):a&&(c=i?function(){a.call(this,this.$root.$options.shadowRoot)}:a),c)if(d.functional){d._injectStyles=c;var l=d.render;d.render=function(t,e){return c.call(e),l(t,e)}}else{var u=d.beforeCreate;d.beforeCreate=u?[].concat(u,c):[c]}return{exports:t,options:d}}s.d(e,"a",(function(){return o}))}},[[19,0]]]);
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[18],{19:function(t,e,s){t.exports=s("ETg6")},"7wkd":function(t,e,s){"use strict";s.r(e);var o={data:function(){return{loaded:!1,showLoadMore:!0,profiles:[],page:1}},beforeMount:function(){this.fetchData()},methods:{fetchData:function(){var t=this;axios.get("/api/pixelfed/v2/discover/profiles",{params:{page:this.page}}).then((function(e){if(0==e.data.length)return t.showLoadMore=!1,void(t.loaded=!0);t.profiles=e.data,t.showLoadMore=8==t.profiles.length,t.loaded=!0}))},prettyCount:function(t){return App.util.format.count(t)},loadMore:function(){this.loaded=!1,this.page++,this.fetchData()},thumbUrl:function(t){return t.media_attachments[0].url}}},a=s("KHd+"),n=Object(a.a)(o,(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",[s("div",{staticClass:"col-12"},[s("p",{staticClass:"font-weight-bold text-lighter text-uppercase"},[t._v("Profiles Directory")]),t._v(" "),t.loaded?s("div",{},[s("div",{staticClass:"row"},[t._l(t.profiles,(function(e,o){return s("div",{staticClass:"col-12 col-md-6 p-1"},[s("div",{staticClass:"card card-body border shadow-none py-2"},[s("div",{staticClass:"media"},[s("a",{attrs:{href:e.url}},[s("img",{staticClass:"rounded-circle border mr-3",attrs:{src:e.avatar,alt:"...",width:"40px",height:"40px"}})]),t._v(" "),s("div",{staticClass:"media-body"},[s("p",{staticClass:"mt-0 mb-0 font-weight-bold"},[s("a",{staticClass:"text-dark",attrs:{href:e.url}},[t._v(t._s(e.username))])]),t._v(" "),s("p",{staticClass:"mb-1 small text-lighter d-flex justify-content-between font-weight-bold"},[s("span",[s("span",[t._v(t._s(t.prettyCount(e.statuses_count)))]),t._v(" POSTS\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),s("span",[s("span",[t._v(t._s(t.prettyCount(e.followers_count)))]),t._v(" FOLLOWERS\n\t\t\t\t\t\t\t\t\t")])]),t._v(" "),s("p",{staticClass:"mb-1"},t._l(e.posts,(function(e,o){return s("span",{key:"profile_posts_"+o,staticClass:"shadow-sm"},[s("a",{staticClass:"text-decoration-none mr-1",attrs:{href:e.url}},[s("img",{staticClass:"border rounded",attrs:{src:t.thumbUrl(e),width:"62.3px",height:"62.3px"}})])])})),0)])])])])})),t._v(" "),t.showLoadMore?s("div",{staticClass:"col-12"},[s("p",{staticClass:"text-center mb-0 pt-3"},[s("button",{staticClass:"btn btn-outline-secondary btn-sm px-4 py-1 font-weight-bold",on:{click:function(e){return t.loadMore()}}},[t._v("Load More")])])]):t._e()],2)]):s("div",[t._m(0)])])])}),[function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"row"},[e("div",{staticClass:"col-12 d-flex justify-content-center align-items-center"},[e("div",{staticClass:"spinner-border",attrs:{role:"status"}},[e("span",{staticClass:"sr-only"},[this._v("Loading...")])])])])}],!1,null,"7b3eea1c",null);e.default=n.exports},ETg6:function(t,e,s){Vue.component("profile-directory",s("7wkd").default)},"KHd+":function(t,e,s){"use strict";function o(t,e,s,o,a,n,r,i){var c,d="function"==typeof t?t.options:t;if(e&&(d.render=e,d.staticRenderFns=s,d._compiled=!0),o&&(d.functional=!0),n&&(d._scopeId="data-v-"+n),r?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),a&&a.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(r)},d._ssrRegister=c):a&&(c=i?function(){a.call(this,this.$root.$options.shadowRoot)}:a),c)if(d.functional){d._injectStyles=c;var l=d.render;d.render=function(t,e){return c.call(e),l(t,e)}}else{var u=d.beforeCreate;d.beforeCreate=u?[].concat(u,c):[c]}return{exports:t,options:d}}s.d(e,"a",(function(){return o}))}},[[19,0]]]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{15:function(e,a,o){e.exports=o("YMO/")},"YMO/":function(e,a,o){(function(e){function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],(function(e,a,o){a.isDark=!0,a.cssClass="ace-monokai",a.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}",e("../lib/dom").importCssString(a.cssText,a.cssClass)})),ace.require(["ace/theme/monokai"],(function(c){"object"==o(e)&&"object"==o(a)&&e&&(e.exports=c)}))}).call(this,o("YuTi")(e))},YuTi:function(e,a){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}},[[15,0]]]);
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{15:function(e,a,o){e.exports=o("YMO/")},"YMO/":function(e,a,o){(function(e){function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],(function(e,a,o){a.isDark=!0,a.cssClass="ace-monokai",a.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}",e("../lib/dom").importCssString(a.cssText,a.cssClass)})),ace.require(["ace/theme/monokai"],(function(c){"object"==o(e)&&"object"==o(a)&&e&&(e.exports=c)}))}).call(this,o("YuTi")(e))},YuTi:function(e,a){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}},[[15,0]]]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,32 +1,33 @@
|
|||
{
|
||||
"/js/manifest.js": "/js/manifest.js?id=7db827d654313dce4250",
|
||||
"/js/vendor.js": "/js/vendor.js?id=d6ba75064c2942474259",
|
||||
"/js/vendor.js": "/js/vendor.js?id=b9760eb405c3c32b09cf",
|
||||
"/js/ace.js": "/js/ace.js?id=11e5550a450fece75c33",
|
||||
"/js/activity.js": "/js/activity.js?id=838e242ddbe91e559f00",
|
||||
"/js/app.js": "/js/app.js?id=049fdddbb594117f646e",
|
||||
"/js/activity.js": "/js/activity.js?id=85479715e399b3489d25",
|
||||
"/js/app.js": "/js/app.js?id=1c3620016c676056663c",
|
||||
"/css/app.css": "/css/app.css?id=77729cabd5c8a0ad09b8",
|
||||
"/css/appdark.css": "/css/appdark.css?id=995ec87dd4aff426cd1c",
|
||||
"/css/landing.css": "/css/landing.css?id=3092e86721fa8b922c06",
|
||||
"/css/quill.css": "/css/quill.css?id=e3741782d15a3031f785",
|
||||
"/js/collectioncompose.js": "/js/collectioncompose.js?id=3fd79944492361ec7347",
|
||||
"/js/collections.js": "/js/collections.js?id=38be4150f3d2ebb15f50",
|
||||
"/js/collectioncompose.js": "/js/collectioncompose.js?id=72e8fa48c00604a44eb9",
|
||||
"/js/collections.js": "/js/collections.js?id=915db7c1d080d61edcc9",
|
||||
"/js/components.js": "/js/components.js?id=88296701f1382d285031",
|
||||
"/js/compose.js": "/js/compose.js?id=661030734f9228389822",
|
||||
"/js/compose.js": "/js/compose.js?id=e74fdb55681c6d21f4d5",
|
||||
"/js/compose-classic.js": "/js/compose-classic.js?id=283f19c895f4118a2a8b",
|
||||
"/js/developers.js": "/js/developers.js?id=f75deca5ccf47d43eb07",
|
||||
"/js/direct.js": "/js/direct.js?id=6a80114ecc453b2b994a",
|
||||
"/js/discover.js": "/js/discover.js?id=dd07b617f5f5f4714164",
|
||||
"/js/hashtag.js": "/js/hashtag.js?id=eb4ce037114cd78a8678",
|
||||
"/js/direct.js": "/js/direct.js?id=e1e4a830bfedc1870db1",
|
||||
"/js/discover.js": "/js/discover.js?id=87071f23fc6d7118c66a",
|
||||
"/js/hashtag.js": "/js/hashtag.js?id=4ebd78fde7fe65f5772c",
|
||||
"/js/loops.js": "/js/loops.js?id=1dcb3790eb9ea4ea5848",
|
||||
"/js/mode-dot.js": "/js/mode-dot.js?id=d54ad862baf30ee756f8",
|
||||
"/js/profile.js": "/js/profile.js?id=746f776639e98cd4102a",
|
||||
"/js/profile-directory.js": "/js/profile-directory.js?id=3a3be60e979308f9958e",
|
||||
"/js/quill.js": "/js/quill.js?id=e47c5b9f47415104bb6a",
|
||||
"/js/rempos.js": "/js/rempos.js?id=0c655b6b8dca92d06c79",
|
||||
"/js/rempro.js": "/js/rempro.js?id=d26f22f402cd6aab5f20",
|
||||
"/js/search.js": "/js/search.js?id=2af4d1de55be62523b71",
|
||||
"/js/status.js": "/js/status.js?id=142b5d5d938c67abdcf6",
|
||||
"/js/story-compose.js": "/js/story-compose.js?id=6308c4b7cb5baa4517d3",
|
||||
"/js/theme-monokai.js": "/js/theme-monokai.js?id=ece67a5ba28761df4d88",
|
||||
"/js/timeline.js": "/js/timeline.js?id=97f92ccb18f86c57dfad"
|
||||
"/js/memoryprofile.js": "/js/memoryprofile.js?id=828e26d71b4330fedc1b",
|
||||
"/js/mode-dot.js": "/js/mode-dot.js?id=dd9c87024fbaa8e75ac4",
|
||||
"/js/profile.js": "/js/profile.js?id=559d809df9a10adc091a",
|
||||
"/js/profile-directory.js": "/js/profile-directory.js?id=855a548efdf56b8594bf",
|
||||
"/js/quill.js": "/js/quill.js?id=866b31b9b9540305751d",
|
||||
"/js/rempos.js": "/js/rempos.js?id=29dacb6e0ce2c936e5cd",
|
||||
"/js/rempro.js": "/js/rempro.js?id=6e7fc68a65bf82d5aec8",
|
||||
"/js/search.js": "/js/search.js?id=5467143312ebae07695b",
|
||||
"/js/status.js": "/js/status.js?id=70f5597c1069d7ead4bb",
|
||||
"/js/story-compose.js": "/js/story-compose.js?id=13f9606a3c4ce7acf17b",
|
||||
"/js/theme-monokai.js": "/js/theme-monokai.js?id=8842103833ba4861bcfa",
|
||||
"/js/timeline.js": "/js/timeline.js?id=8b144724e85e8bef50bf"
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ require('bootstrap');
|
|||
window.axios = require('axios');
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
require('readmore-js');
|
||||
window.blurhash = require("blurhash");
|
||||
|
||||
let token = document.head.querySelector('meta[name="csrf-token"]');
|
||||
if (token) {
|
||||
|
|
|
@ -635,15 +635,23 @@ export default {
|
|||
methods: {
|
||||
fetchProfile() {
|
||||
let self = this;
|
||||
axios.get('/api/pixelfed/v1/accounts/verify_credentials').then(res => {
|
||||
self.profile = res.data;
|
||||
window.pixelfed.currentUser = res.data;
|
||||
if(res.data.locked == true) {
|
||||
self.visibility = 'private';
|
||||
self.visibilityTag = 'Followers Only';
|
||||
if(window._sharedData.curUser) {
|
||||
self.profile = window._sharedData.curUser;
|
||||
if(self.profile.locked == true) {
|
||||
self.visibility = 'private';
|
||||
self.visibilityTag = 'Followers Only';
|
||||
}
|
||||
}).catch(err => {
|
||||
});
|
||||
} else {
|
||||
axios.get('/api/pixelfed/v1/accounts/verify_credentials').then(res => {
|
||||
self.profile = res.data;
|
||||
window.pixelfed.currentUser = res.data;
|
||||
if(res.data.locked == true) {
|
||||
self.visibility = 'private';
|
||||
self.visibilityTag = 'Followers Only';
|
||||
}
|
||||
}).catch(err => {
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
addMedia(event) {
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
@extends('layouts.blank')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 offset-md-3 text-center">
|
||||
<p class="h1 pb-2" style="font-weight: 200">Your Post Contains Sensitive or Offensive Material</p>
|
||||
<p class="lead py-3">We applied a Content Warning to your post because it doesn't follow our <a class="font-weight-bold text-dark" href="{{route('help.community-guidelines')}}">Community Guidelines</a>.</p>
|
||||
<p class="font-weight-bold alert alert-danger text-left">To continue you must click the "I Understand" button or "REQUEST APPEAL" button at the bottom of this page.</p>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3">
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 mt-3">
|
||||
<p class="h4 font-weight-bold">Post Details</p>
|
||||
@if($interstitial->has_media)
|
||||
<div class="py-4 align-items-center">
|
||||
<div class="d-block text-center text-truncate">
|
||||
@if($interstitial->blurhash)
|
||||
<canvas id="mblur" width="400" height="400" class="rounded shadow"></canvas>
|
||||
@else
|
||||
<img src="/storage/no-preview.png" class="mr-3 img-fluid" alt="No preview available">
|
||||
@endif
|
||||
</div>
|
||||
<div class="mt-2 border rounded p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
Caption: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="mb-0" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary">{{$meta->url}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="py-4 align-items-center">
|
||||
<div class="mt-2 border rounded p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
Comment: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="mb-0" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary">{{$meta->url}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 my-3">
|
||||
<div class="border rounded p-3 border-primary">
|
||||
<p class="h4 font-weight-bold pt-2 text-primary">Review the Community Guidelines</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="appealButton" class="col-12 col-md-6 offset-md-3 mt-3">
|
||||
<button type="button" class="btn btn-outline-primary btn-block font-weight-bold" onclick="requestAppeal()">REQUEST APPEAL</button>
|
||||
</div>
|
||||
<div id="appealForm" class="col-12 col-md-6 offset-md-3 d-none mt-3">
|
||||
<form method="post" action="/i/warning">
|
||||
@csrf
|
||||
<p class="h4 font-weight-bold">Request Appeal</p>
|
||||
<p class="pt-4">
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" rows="4" placeholder="Write your appeal request message here" name="appeal_message"></textarea>
|
||||
</div>
|
||||
</p>
|
||||
{{-- <p class="lead"><span class="font-weight-bold">Learn more</span> about what we remove.</p> --}}
|
||||
<input type="hidden" name="id" value="{{encrypt($interstitial->id)}}">
|
||||
<input type="hidden" name="type" value="{{$interstitial->type}}">
|
||||
<input type="hidden" name="action" value="appeal">
|
||||
<button type="submit" class="btn btn-outline-primary btn-block font-weight-bold">REQUEST APPEAL</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6 offset-md-3 mt-4 mb-4">
|
||||
|
||||
<form method="post" action="/i/warning">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="id" value="{{encrypt($interstitial->id)}}">
|
||||
<input type="hidden" name="type" value="{{$interstitial->type}}">
|
||||
<input type="hidden" name="action" value="confirm">
|
||||
<button type="submit" class="btn btn-primary btn-block font-weight-bold">I Understand</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
function requestAppeal() {
|
||||
$('#appealButton').addClass('d-none');
|
||||
$('#appealForm').removeClass('d-none');
|
||||
}
|
||||
</script>
|
||||
@if($interstitial->blurhash)
|
||||
<script type="text/javascript">
|
||||
const pixels = window.blurhash.decode("{{$interstitial->blurhash}}", 400, 400);
|
||||
const canvas = document.getElementById("mblur");
|
||||
const ctx = canvas.getContext("2d");
|
||||
const imageData = ctx.createImageData(400, 400);
|
||||
imageData.data.set(pixels);
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
</script>
|
||||
@endif
|
||||
@endpush
|
|
@ -0,0 +1,99 @@
|
|||
@extends('layouts.blank')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 offset-md-3 text-center">
|
||||
<p class="h1 pb-2" style="font-weight: 200">Your Post Has Been Deleted</p>
|
||||
<p class="lead py-1">We removed your post because it doesn't follow our <a class="font-weight-bold text-dark" href="{{route('help.community-guidelines')}}">Community Guidelines</a>. If you violate our guidelines again, your account may be restricted or disabled.</p>
|
||||
<p class="font-weight-bold alert alert-danger text-left">To continue you must click the "I Understand" button at the bottom of this page.</p>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3">
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 mt-3">
|
||||
<p class="h4 font-weight-bold">Post Details</p>
|
||||
@if($interstitial->has_media)
|
||||
<div class="py-4 align-items-center">
|
||||
<div class="d-block text-center text-truncate">
|
||||
@if($interstitial->blurhash)
|
||||
<canvas id="mblur" width="400" height="400" class="rounded shadow"></canvas>
|
||||
@else
|
||||
<img src="/storage/no-preview.png" class="mr-3 img-fluid" alt="No preview available">
|
||||
@endif
|
||||
</div>
|
||||
<div class="mt-2 border rounded p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
Caption: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="mb-0" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary">{{$meta->url}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="media py-4 align-items-center">
|
||||
<div class="media-body ml-2">
|
||||
<p class="">
|
||||
Comment: <span class="lead text-break font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
<p class="mb-0 small">
|
||||
Posted on {{$meta->created_at}}
|
||||
</p>
|
||||
<p class="mb-0 font-weight-bold text-primary">
|
||||
{{$meta->url}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 my-3">
|
||||
<div class="border rounded p-3 border-primary">
|
||||
<p class="h4 font-weight-bold pt-2 text-primary">Review the Community Guidelines</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 mt-4 mb-5">
|
||||
<form method="post" action="/i/warning">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="id" value="{{encrypt($interstitial->id)}}">
|
||||
<input type="hidden" name="type" value="{{$interstitial->type}}">
|
||||
<input type="hidden" name="action" value="confirm">
|
||||
<button type="submit" class="btn btn-primary btn-block font-weight-bold">I Understand</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
function requestAppeal() {
|
||||
$('#appealButton').addClass('d-none');
|
||||
$('#appealForm').removeClass('d-none');
|
||||
}
|
||||
</script>
|
||||
@if($interstitial->blurhash)
|
||||
<script type="text/javascript">
|
||||
const pixels = window.blurhash.decode("{{$interstitial->blurhash}}", 400, 400);
|
||||
const canvas = document.getElementById("mblur");
|
||||
const ctx = canvas.getContext("2d");
|
||||
const imageData = ctx.createImageData(400, 400);
|
||||
imageData.data.set(pixels);
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
</script>
|
||||
@endif
|
||||
@endpush
|
|
@ -0,0 +1,128 @@
|
|||
@extends('layouts.blank')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 offset-md-3 text-center">
|
||||
<p class="h1 pb-2" style="font-weight: 200">Your Post Was Unlisted</p>
|
||||
<p class="lead py-3">We removed your post from public timelines because it doesn't follow our <a class="font-weight-bold text-dark" href="{{route('help.community-guidelines')}}">Community Guidelines</a>.</p>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3">
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3">
|
||||
<p class="h4 font-weight-bold">Post Details</p>
|
||||
@if($interstitial->has_media)
|
||||
<div class="py-4 align-items-center">
|
||||
<div class="d-block text-center text-truncate">
|
||||
@if($interstitial->blurhash)
|
||||
<canvas id="mblur" width="400" height="400" class="rounded shadow"></canvas>
|
||||
@else
|
||||
<img src="/storage/no-preview.png" class="mr-3 img-fluid" alt="No preview available">
|
||||
@endif
|
||||
</div>
|
||||
<div class="mt-2 border rounded p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
Caption: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="mb-0" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary">{{$meta->url}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="py-4 align-items-center">
|
||||
<div class="mt-2 border rounded p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
Comment: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="mb-0" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary">{{$meta->url}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-md-6 offset-md-3 my-3">
|
||||
<div class="border rounded p-3 border-primary">
|
||||
<p class="h4 font-weight-bold pt-2 text-primary">Review the Community Guidelines</p>
|
||||
<p class="lead pt-4 text-primary">We want to keep {{config('app.name')}} a safe place for everyone, and we created these <a class="font-weight-bold text-primary" href="{{route('help.community-guidelines')}}">Community Guidelines</a> to support and protect our community.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="appealButton" class="col-12 col-md-6 offset-md-3">
|
||||
<button type="button" class="btn btn-outline-primary btn-block font-weight-bold" onclick="requestAppeal()">REQUEST APPEAL</button>
|
||||
</div>
|
||||
<div id="appealForm" class="col-12 col-md-6 offset-md-3 d-none">
|
||||
<form method="post" action="/i/warning">
|
||||
@csrf
|
||||
|
||||
<p class="h4 font-weight-bold">Request Appeal</p>
|
||||
<p class="pt-4">
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" rows="4" placeholder="Write your appeal request message here" name="appeal_message"></textarea>
|
||||
</div>
|
||||
</p>
|
||||
<input type="hidden" name="id" value="{{encrypt($interstitial->id)}}">
|
||||
<input type="hidden" name="type" value="{{$interstitial->type}}">
|
||||
<input type="hidden" name="action" value="appeal">
|
||||
<button type="submit" class="btn btn-outline-primary btn-block font-weight-bold">REQUEST APPEAL</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6 offset-md-3 mt-4 mb-4">
|
||||
<form method="post" action="/i/warning">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="id" value="{{encrypt($interstitial->id)}}">
|
||||
<input type="hidden" name="type" value="{{$interstitial->type}}">
|
||||
<input type="hidden" name="action" value="confirm">
|
||||
<button type="submit" class="btn btn-primary btn-block font-weight-bold">I Understand</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
function requestAppeal() {
|
||||
$('#appealButton').addClass('d-none');
|
||||
$('#appealForm').removeClass('d-none');
|
||||
}
|
||||
</script>
|
||||
@if($interstitial->blurhash)
|
||||
<script type="text/javascript">
|
||||
const pixels = window.blurhash.decode("{{$interstitial->blurhash}}", 400, 400);
|
||||
const canvas = document.getElementById("mblur");
|
||||
const ctx = canvas.getContext("2d");
|
||||
const imageData = ctx.createImageData(400, 400);
|
||||
imageData.data.set(pixels);
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
</script>
|
||||
@endif
|
||||
@endpush
|
|
@ -0,0 +1,63 @@
|
|||
@extends('admin.partial.template-full')
|
||||
|
||||
@section('section')
|
||||
<div class="title mb-3">
|
||||
<h3 class="font-weight-bold d-inline-block">Appeals</h3>
|
||||
<span class="float-right">
|
||||
</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-3 mb-3">
|
||||
<div class="card border bg-primary text-white rounded-pill shadow">
|
||||
<div class="card-body pl-4 ml-3">
|
||||
<p class="h1 font-weight-bold mb-1" style="font-weight: 700">{{App\AccountInterstitial::whereNull('appeal_handled_at')->whereNotNull('appeal_requested_at')->count()}}</p>
|
||||
<p class="lead mb-0 font-weight-lighter">active appeals</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 card border bg-warning text-dark rounded-pill shadow">
|
||||
<div class="card-body pl-4 ml-3">
|
||||
<p class="h1 font-weight-bold mb-1" style="font-weight: 700">{{App\AccountInterstitial::whereNotNull('appeal_handled_at')->whereNotNull('appeal_requested_at')->count()}}</p>
|
||||
<p class="lead mb-0 font-weight-lighter">closed appeals</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-8 offset-md-1">
|
||||
<ul class="list-group">
|
||||
@if($appeals->count() == 0)
|
||||
<li class="list-group-item text-center py-5">
|
||||
<p class="mb-0 py-5 font-weight-bold">No appeals found!</p>
|
||||
</li>
|
||||
@endif
|
||||
@foreach($appeals as $appeal)
|
||||
<a class="list-group-item text-decoration-none text-dark" href="/i/admin/reports/appeal/{{$appeal->id}}">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex align-items-center">
|
||||
<img src="{{$appeal->has_media ? $appeal->status->thumb(true) : '/storage/no-preview.png'}}" width="64" height="64" class="rounded border">
|
||||
<div class="ml-2">
|
||||
<span class="d-inline-block text-truncate">
|
||||
<p class="mb-0 small font-weight-bold text-primary">{{$appeal->type}}</p>
|
||||
@if($appeal->item_type)
|
||||
<p class="mb-0 font-weight-bold">{{starts_with($appeal->item_type, 'App\\') ? explode('\\',$appeal->item_type)[1] : $appeal->item_type}}</p>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-block">
|
||||
<p class="mb-0 font-weight-bold">@{{$appeal->user->username}}</p>
|
||||
<p class="mb-0 small text-muted font-weight-bold">{{$appeal->created_at->diffForHumans(null, null, true)}}</p>
|
||||
</div>
|
||||
<div class="d-inline-block">
|
||||
<p class="mb-0 small">
|
||||
<i class="fas fa-chevron-right fa-2x text-lighter"></i>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@endforeach
|
||||
</ul>
|
||||
<p>{!!$appeals->render()!!}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
|
@ -15,6 +15,15 @@
|
|||
</a>
|
||||
</span>
|
||||
</div>
|
||||
@php($ai = App\AccountInterstitial::whereNotNull('appeal_requested_at')->whereNull('appeal_handled_at')->count())
|
||||
@if($ai)
|
||||
<div class="mb-4">
|
||||
<a class="btn btn-outline-primary px-5 py-3" href="/i/admin/reports/appeals">
|
||||
<p class="font-weight-bold h4 mb-0">{{$ai}}</p>
|
||||
Appeal {{$ai == 1 ? 'Request' : 'Requests'}}
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
@if($reports->count())
|
||||
<div class="card shadow-none border">
|
||||
<div class="list-group list-group-flush">
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
@extends('admin.partial.template-full')
|
||||
|
||||
@section('section')
|
||||
<div class="d-flex justify-content-between title mb-3">
|
||||
<div>
|
||||
<p class="font-weight-bold h3">Moderation Appeal</p>
|
||||
<p class="text-muted mb-0 lead">From <a href="{{$appeal->user->url()}}" class="text-muted font-weight-bold">@{{$appeal->user->username}}</a> about {{$appeal->appeal_requested_at->diffForHumans()}}.</p>
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-8 mt-3">
|
||||
@if($appeal->type == 'post.cw')
|
||||
<div class="card shadow-none border">
|
||||
<div class="card-header bg-light h5 font-weight-bold py-4">Content Warning applied to {{$appeal->has_media ? 'Post' : 'Comment'}}</div>
|
||||
@if($appeal->has_media)
|
||||
<img class="card-img-top border-bottom" src="{{$appeal->status->thumb(true)}}">
|
||||
@endif
|
||||
<div class="card-body">
|
||||
<div class="mt-2 p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
{{$appeal->has_media ? 'Caption' : 'Comment'}}: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary"><a href="{{$meta->url}}">{{$meta->url}}</a></span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Message: <span class="font-weight-bold">{{$appeal->appeal_message}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@elseif($appeal->type == 'post.unlist')
|
||||
<div class="card shadow-none border">
|
||||
<div class="card-header bg-light h5 font-weight-bold py-4">{{$appeal->has_media ? 'Post' : 'Comment'}} was unlisted from timelines</div>
|
||||
@if($appeal->has_media)
|
||||
<img class="card-img-top border-bottom" src="{{$appeal->status->thumb(true)}}">
|
||||
@endif
|
||||
<div class="card-body">
|
||||
<div class="mt-2 p-3">
|
||||
@if($meta->caption)
|
||||
<p class="text-break">
|
||||
{{$appeal->has_media ? 'Caption' : 'Comment'}}: <span class="font-weight-bold">{{$meta->caption}}</span>
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-0">
|
||||
Like Count: <span class="font-weight-bold">{{$meta->likes_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Share Count: <span class="font-weight-bold">{{$meta->reblogs_count}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Timestamp: <span class="font-weight-bold">{{now()->parse($meta->created_at)->format('r')}}</span>
|
||||
</p>
|
||||
<p class="" style="word-break: break-all !important;">
|
||||
URL: <span class="font-weight-bold text-primary"><a href="{{$meta->url}}">{{$meta->url}}</a></span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Message: <span class="font-weight-bold">{{$appeal->appeal_message}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-md-4 mt-3">
|
||||
<form method="post">
|
||||
@csrf
|
||||
<input type="hidden" name="action" value="dismiss">
|
||||
<button type="submit" class="btn btn-primary btn-block font-weight-bold mb-3">Dismiss Appeal Request</button>
|
||||
</form>
|
||||
<button type="button" class="btn btn-light border btn-block font-weight-bold mb-3" onclick="approveWarning()">Approve Appeal</button>
|
||||
<div class="card shadow-none border mt-5">
|
||||
<div class="card-header text-center font-weight-bold bg-light">
|
||||
@{{$appeal->user->username}} stats
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="">
|
||||
Open Appeals: <span class="font-weight-bold">{{App\AccountInterstitial::whereUserId($appeal->user_id)->whereNotNull('appeal_requested_at')->whereNull('appeal_handled_at')->count()}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Total Appeals: <span class="font-weight-bold">{{App\AccountInterstitial::whereUserId($appeal->user_id)->whereNotNull('appeal_requested_at')->count()}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Total Warnings: <span class="font-weight-bold">{{App\AccountInterstitial::whereUserId($appeal->user_id)->count()}}</span>
|
||||
</p>
|
||||
<p class="">
|
||||
Status Count: <span class="font-weight-bold">{{$appeal->user->statuses()->count()}}</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Joined: <span class="font-weight-bold">{{$appeal->user->created_at->diffForHumans(null, null, false)}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
function approveWarning() {
|
||||
if(window.confirm('Are you sure you want to approve this appeal?') == true) {
|
||||
axios.post(window.location.href, {
|
||||
action: 'approve'
|
||||
}).then(res => {
|
||||
window.location.href = '/i/admin/reports/appeals';
|
||||
}).catch(err => {
|
||||
swal('Oops!', 'An error occured, please try again later.', 'error');
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@endpush
|
|
@ -8,6 +8,5 @@
|
|||
|
||||
@push('scripts')
|
||||
<script type="text/javascript" src="{{ mix('js/discover.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ mix('js/compose.js') }}"></script>
|
||||
<script type="text/javascript">App.boot();</script>
|
||||
@endpush
|
|
@ -0,0 +1,35 @@
|
|||
@extends('layouts.app',['title' => $profile->username . " on " . config('app.name')])
|
||||
|
||||
@section('content')
|
||||
@if (session('error'))
|
||||
<div class="alert alert-danger text-center font-weight-bold mb-0">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<memory-profile profile-id="{{$profile->id}}" profile-username="{{$profile->username}}" :profile-settings="{{json_encode($settings)}}" profile-layout="{{$profile->profile_layout ?? 'metro'}}"></memory-profile>
|
||||
@if($profile->website)
|
||||
<a class="d-none" href="{{$profile->website}}" rel="me">{{$profile->website}}</a>
|
||||
@endif
|
||||
|
||||
<noscript>
|
||||
<div class="container">
|
||||
<p class="pt-5 text-center lead">Please enable javascript to view this content.</p>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('meta')<meta property="og:description" content="{{$profile->bio}}">
|
||||
@if(false == $settings['crawlable'] || $profile->remote_url)
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
@else <meta property="og:image" content="{{$profile->avatarUrl()}}">
|
||||
<link href="{{$profile->permalink('.atom')}}" rel="alternate" title="{{$profile->username}} on Pixelfed" type="application/atom+xml">
|
||||
<link href='{{$profile->permalink()}}' rel='alternate' type='application/activity+json'>
|
||||
@endif
|
||||
@endpush
|
||||
|
||||
@push('scripts')<script type="text/javascript" src="{{ mix('js/memoryprofile.js') }}"></script>
|
||||
<script type="text/javascript" defer>App.boot();</script>
|
||||
|
||||
@endpush
|
|
@ -8,6 +8,9 @@ Route::domain(config('pixelfed.domain.admin'))->prefix('i/admin')->group(functio
|
|||
Route::get('reports/show/{id}', 'AdminController@showReport');
|
||||
Route::post('reports/show/{id}', 'AdminController@updateReport');
|
||||
Route::post('reports/bulk', 'AdminController@bulkUpdateReport');
|
||||
Route::get('reports/appeals', 'AdminController@appeals');
|
||||
Route::get('reports/appeal/{id}', 'AdminController@showAppeal');
|
||||
Route::post('reports/appeal/{id}', 'AdminController@updateAppeal');
|
||||
Route::redirect('statuses', '/statuses/list');
|
||||
Route::get('statuses/list', 'AdminController@statuses')->name('admin.statuses');
|
||||
Route::get('statuses/show/{id}', 'AdminController@showStatus');
|
||||
|
@ -73,7 +76,7 @@ Route::domain(config('pixelfed.domain.admin'))->prefix('i/admin')->group(functio
|
|||
Route::post('newsroom/create', 'AdminController@newsroomStore');
|
||||
});
|
||||
|
||||
Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofactor', 'localization'])->group(function () {
|
||||
Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofactor', 'localization','interstitial'])->group(function () {
|
||||
Route::get('/', 'SiteController@home')->name('timeline.personal');
|
||||
Route::post('/', 'StatusController@store');
|
||||
|
||||
|
@ -125,6 +128,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
|||
Route::get('discover/tag', 'DiscoverController@getHashtags');
|
||||
Route::post('status/compose', 'InternalApiController@composePost')->middleware('throttle:maxPostsPerHour,60')->middleware('throttle:maxPostsPerDay,1440');
|
||||
});
|
||||
|
||||
Route::group(['prefix' => 'pixelfed'], function() {
|
||||
Route::group(['prefix' => 'v1'], function() {
|
||||
Route::get('accounts/verify_credentials', 'ApiController@verifyCredentials');
|
||||
|
@ -146,6 +150,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
|||
Route::get('timelines/home', 'PublicApiController@homeTimelineApi');
|
||||
Route::get('newsroom/timeline', 'NewsroomController@timelineApi');
|
||||
Route::post('newsroom/markasread', 'NewsroomController@markAsRead');
|
||||
Route::get('favourites', 'Api\BaseApiController@accountLikes');
|
||||
});
|
||||
|
||||
Route::group(['prefix' => 'v2'], function() {
|
||||
|
@ -169,6 +174,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
|||
Route::get('discover/posts/places', 'DiscoverController@trendingPlaces');
|
||||
});
|
||||
});
|
||||
|
||||
Route::group(['prefix' => 'local'], function () {
|
||||
// Route::get('accounts/verify_credentials', 'ApiController@verifyCredentials');
|
||||
// Route::get('accounts/relationships', 'PublicApiController@relationships');
|
||||
|
@ -295,6 +301,9 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
|||
Route::get('redirect', 'SiteController@redirectUrl');
|
||||
Route::post('admin/media/block/add', 'MediaBlocklistController@add');
|
||||
Route::post('admin/media/block/delete', 'MediaBlocklistController@delete');
|
||||
|
||||
Route::get('warning', 'AccountInterstitialController@get');
|
||||
Route::post('warning', 'AccountInterstitialController@read');
|
||||
});
|
||||
|
||||
Route::group(['prefix' => 'account'], function () {
|
||||
|
|
Ładowanie…
Reference in New Issue