diff --git a/CHANGELOG.md b/CHANGELOG.md index d077f71c3..ee2a962ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.11.7...dev) +### Added +- Post edits ([#4416](https://github.com/pixelfed/pixelfed/pull/4416)) ([98cf8f3](https://github.com/pixelfed/pixelfed/commit/98cf8f3)) + ### Updates - Update StatusService, fix bug in getFull method ([4d8b4dcf](https://github.com/pixelfed/pixelfed/commit/4d8b4dcf)) - ([](https://github.com/pixelfed/pixelfed/commit/)) diff --git a/app/Http/Controllers/StatusEditController.php b/app/Http/Controllers/StatusEditController.php new file mode 100644 index 000000000..1d0a22396 --- /dev/null +++ b/app/Http/Controllers/StatusEditController.php @@ -0,0 +1,59 @@ +middleware('auth'); + abort_if(!config('exp.pue'), 404, 'Post editing is not enabled on this server.'); + } + + public function store(StoreStatusEditRequest $request, $id) + { + $validated = $request->validated(); + + $status = Status::findOrFail($id); + abort_if(StatusEdit::whereStatusId($status->id)->count() >= 10, 400, 'You cannot edit your post more than 10 times.'); + $res = UpdateStatusService::call($status, $validated); + + $status = Status::findOrFail($id); + StatusLocalUpdateActivityPubDeliverPipeline::dispatch($status)->delay(now()->addMinutes(1)); + return $res; + } + + public function history(Request $request, $id) + { + abort_if(!$request->user(), 403); + $status = Status::whereNull('reblog_of_id')->findOrFail($id); + abort_if(!in_array($status->scope, ['public', 'unlisted']), 403); + if(!$status->edits()->count()) { + return []; + } + $cached = StatusService::get($status->id, false); + + $res = $status->edits->map(function($edit) use($cached) { + return [ + 'content' => Autolink::create()->autolink($edit->caption), + 'spoiler_text' => $edit->spoiler_text, + 'sensitive' => (bool) $edit->is_nsfw, + 'created_at' => str_replace('+00:00', 'Z', $edit->created_at->format(DATE_RFC3339_EXTENDED)), + 'account' => $cached['account'], + 'media_attachments' => $cached['media_attachments'], + 'emojis' => $cached['emojis'], + ]; + })->reverse()->values()->toArray(); + return $res; + } +} diff --git a/app/Http/Requests/Status/StoreStatusEditRequest.php b/app/Http/Requests/Status/StoreStatusEditRequest.php new file mode 100644 index 000000000..aa9364ca6 --- /dev/null +++ b/app/Http/Requests/Status/StoreStatusEditRequest.php @@ -0,0 +1,69 @@ +user()->profile; + if($profile->status != null) { + return false; + } + if($profile->unlisted == true && $profile->cw == true) { + return false; + } + $types = [ + "photo", + "photo:album", + "photo:video:album", + "reply", + "text", + "video", + "video:album" + ]; + $scopes = ['public', 'unlisted', 'private']; + $status = Status::whereNull('reblog_of_id')->whereIn('type', $types)->whereIn('scope', $scopes)->find($this->route('id')); + return $status && $this->user()->profile_id === $status->profile_id; + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules(): array + { + return [ + 'status' => 'sometimes|max:'.config('pixelfed.max_caption_length', 500), + 'spoiler_text' => 'nullable|string|max:140', + 'sensitive' => 'sometimes|boolean', + 'media_ids' => [ + 'nullable', + 'required_without:status', + 'array', + 'max:' . config('pixelfed.max_album_length'), + function (string $attribute, mixed $value, Closure $fail) { + Media::whereProfileId($this->user()->profile_id) + ->where(function($query) { + return $query->whereNull('status_id') + ->orWhere('status_id', '=', $this->route('id')); + }) + ->findOrFail($value); + }, + ], + 'location' => 'sometimes|nullable', + 'location.id' => 'sometimes|integer|min:1|max:128769', + 'location.country' => 'required_with:location.id', + 'location.name' => 'required_with:location.id', + ]; + } +} diff --git a/app/Jobs/StatusPipeline/StatusLocalUpdateActivityPubDeliverPipeline.php b/app/Jobs/StatusPipeline/StatusLocalUpdateActivityPubDeliverPipeline.php new file mode 100644 index 000000000..745f5f5ff --- /dev/null +++ b/app/Jobs/StatusPipeline/StatusLocalUpdateActivityPubDeliverPipeline.php @@ -0,0 +1,129 @@ +status = $status; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + $status = $this->status; + $profile = $status->profile; + + // ignore group posts + // if($status->group_id != null) { + // return; + // } + + if($status->local == false || $status->url || $status->uri) { + return; + } + + $audience = $status->profile->getAudienceInbox(); + + if(empty($audience) || !in_array($status->scope, ['public', 'unlisted', 'private'])) { + // Return on profiles with no remote followers + return; + } + + switch($status->type) { + case 'poll': + // Polls not yet supported + return; + break; + + default: + $activitypubObject = new UpdateNote(); + break; + } + + + $fractal = new Fractal\Manager(); + $fractal->setSerializer(new ArraySerializer()); + $resource = new Fractal\Resource\Item($status, $activitypubObject); + $activity = $fractal->createData($resource)->toArray(); + + $payload = json_encode($activity); + + $client = new Client([ + 'timeout' => config('federation.activitypub.delivery.timeout') + ]); + + $version = config('pixelfed.version'); + $appUrl = config('app.url'); + $userAgent = "(Pixelfed/{$version}; +{$appUrl})"; + + $requests = function($audience) use ($client, $activity, $profile, $payload, $userAgent) { + foreach($audience as $url) { + $headers = HttpSignature::sign($profile, $url, $activity, [ + 'Content-Type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + 'User-Agent' => $userAgent, + ]); + yield function() use ($client, $url, $headers, $payload) { + return $client->postAsync($url, [ + 'curl' => [ + CURLOPT_HTTPHEADER => $headers, + CURLOPT_POSTFIELDS => $payload, + CURLOPT_HEADER => true, + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_SSL_VERIFYHOST => false + ] + ]); + }; + } + }; + + $pool = new Pool($client, $requests($audience), [ + 'concurrency' => config('federation.activitypub.delivery.concurrency'), + 'fulfilled' => function ($response, $index) { + }, + 'rejected' => function ($reason, $index) { + } + ]); + + $promise = $pool->promise(); + + $promise->wait(); + } +} diff --git a/app/Jobs/StatusPipeline/StatusRemoteUpdatePipeline.php b/app/Jobs/StatusPipeline/StatusRemoteUpdatePipeline.php new file mode 100644 index 000000000..b79f54cce --- /dev/null +++ b/app/Jobs/StatusPipeline/StatusRemoteUpdatePipeline.php @@ -0,0 +1,159 @@ +activity = $activity; + } + + /** + * Execute the job. + */ + public function handle(): void + { + $activity = $this->activity; + $status = Status::with('media')->whereObjectUrl($activity['id'])->first(); + if(!$status) { + return; + } + $this->createPreviousEdit($status); + $this->updateMedia($status, $activity); + $this->updateImmediateAttributes($status, $activity); + $this->createEdit($status, $activity); + } + + protected function createPreviousEdit($status) + { + if(!$status->edits()->count()) { + StatusEdit::create([ + 'status_id' => $status->id, + 'profile_id' => $status->profile_id, + 'caption' => $status->caption, + 'spoiler_text' => $status->cw_summary, + 'is_nsfw' => $status->is_nsfw, + 'ordered_media_attachment_ids' => $status->media()->orderBy('order')->pluck('id')->toArray(), + 'created_at' => $status->created_at + ]); + } + } + + protected function updateMedia($status, $activity) + { + if(!isset($activity['attachment'])) { + return; + } + $ogm = $status->media->count() ? $status->media()->orderBy('order')->get() : collect([]); + $nm = collect($activity['attachment'])->filter(function($nm) { + return isset( + $nm['type'], + $nm['mediaType'], + $nm['url'] + ) && + in_array($nm['type'], ['Document', 'Image', 'Video']) && + in_array($nm['mediaType'], explode(',', config('pixelfed.media_types'))); + }); + + // Skip when no media + if(!$ogm->count() && !$nm->count()) { + return; + } + + Media::whereProfileId($status->profile_id) + ->whereStatusId($status->id) + ->update([ + 'status_id' => null + ]); + + $nm->each(function($n, $key) use($status) { + $m = new Media; + $m->status_id = $status->id; + $m->profile_id = $status->profile_id; + $m->remote_media = true; + $m->media_path = $n['url']; + $m->caption = isset($n['name']) && !empty($n['name']) ? Purify::clean($n['name']) : null; + $m->remote_url = $n['url']; + $m->width = isset($n['width']) && !empty($n['width']) ? $n['width'] : null; + $m->height = isset($n['height']) && !empty($n['height']) ? $n['height'] : null; + $m->skip_optimize = true; + $m->order = $key + 1; + $m->save(); + }); + } + + protected function updateImmediateAttributes($status, $activity) + { + if(isset($activity['content'])) { + $status->caption = strip_tags($activity['content']); + $status->rendered = Purify::clean($activity['content']); + } + + if(isset($activity['sensitive'])) { + if((bool) $activity['sensitive'] == false) { + $status->is_nsfw = false; + $exists = ModLog::whereObjectType('App\Status::class') + ->whereObjectId($status->id) + ->whereAction('admin.status.moderate') + ->exists(); + if($exists == true) { + $status->is_nsfw = true; + } + $profile = Profile::find($status->profile_id); + if(!$profile || $profile->cw == true) { + $status->is_nsfw = true; + } + } else { + $status->is_nsfw = true; + } + } + + if(isset($activity['summary'])) { + $status->cw_summary = Purify::clean($activity['summary']); + } else { + $status->cw_summary = null; + } + + $status->edited_at = now(); + $status->save(); + StatusService::del($status->id); + } + + protected function createEdit($status, $activity) + { + $cleaned = isset($activity['content']) ? Purify::clean($activity['content']) : null; + $spoiler_text = isset($activity['summary']) ? Purify::clean($attributes['summary']) : null; + $sensitive = isset($activity['sensitive']) ? $activity['sensitive'] : null; + $mids = $status->media()->count() ? $status->media()->orderBy('order')->pluck('id')->toArray() : null; + StatusEdit::create([ + 'status_id' => $status->id, + 'profile_id' => $status->profile_id, + 'caption' => $cleaned, + 'spoiler_text' => $spoiler_text, + 'is_nsfw' => $sensitive, + 'ordered_media_attachment_ids' => $mids + ]); + } +} diff --git a/app/Models/StatusEdit.php b/app/Models/StatusEdit.php new file mode 100644 index 000000000..5c9ec5695 --- /dev/null +++ b/app/Models/StatusEdit.php @@ -0,0 +1,19 @@ + 'array', + 'media_descriptions' => 'array', + 'poll_options' => 'array' + ]; + + protected $guarded = []; +} diff --git a/app/Services/Status/UpdateStatusService.php b/app/Services/Status/UpdateStatusService.php new file mode 100644 index 000000000..be50bf70f --- /dev/null +++ b/app/Services/Status/UpdateStatusService.php @@ -0,0 +1,137 @@ +id); + } + + public static function updateMediaAttachements(Status $status, $attributes) + { + $count = $status->media()->count(); + if($count === 0 || $count === 1) { + return; + } + + $oids = $status->media()->orderBy('order')->pluck('id')->map(function($m) { return (string) $m; }); + $nids = collect($attributes['media_ids']); + + if($oids->toArray() === $nids->toArray()) { + return; + } + + foreach($oids->diff($nids)->values()->toArray() as $mid) { + $media = Media::find($mid); + if(!$media) { + continue; + } + $media->status_id = null; + $media->save(); + MediaStorageService::delete($media, true); + } + + $nids->each(function($nid, $idx) { + $media = Media::find($nid); + if(!$media) { + return; + } + $media->order = $idx; + $media->save(); + }); + MediaService::del($status->id); + } + + public static function handleImmediateAttributes(Status $status, $attributes) + { + if(isset($attributes['status'])) { + $cleaned = Purify::clean($attributes['status']); + $status->caption = $cleaned; + $status->rendered = Autolink::create()->autolink($cleaned); + } else { + $status->caption = null; + $status->rendered = null; + } + if(isset($attributes['sensitive'])) { + if($status->is_nsfw != (bool) $attributes['sensitive'] && + (bool) $attributes['sensitive'] == false) + { + $exists = ModLog::whereObjectType('App\Status::class') + ->whereObjectId($status->id) + ->whereAction('admin.status.moderate') + ->exists(); + if(!$exists) { + $status->is_nsfw = (bool) $attributes['sensitive']; + } + } else { + $status->is_nsfw = (bool) $attributes['sensitive']; + } + } + if(isset($attributes['spoiler_text'])) { + $status->cw_summary = Purify::clean($attributes['spoiler_text']); + } else { + $status->cw_summary = null; + } + if(isset($attributes['location'])) { + if (isset($attributes['location']['id'])) { + $status->place_id = $attributes['location']['id']; + } else { + $status->place_id = null; + } + } + if($status->cw_summary && !$status->is_nsfw) { + $status->cw_summary = null; + } + $status->edited_at = now(); + $status->save(); + StatusService::del($status->id); + } + + public static function createPreviousEdit(Status $status) + { + if(!$status->edits()->count()) { + StatusEdit::create([ + 'status_id' => $status->id, + 'profile_id' => $status->profile_id, + 'caption' => $status->caption, + 'spoiler_text' => $status->cw_summary, + 'is_nsfw' => $status->is_nsfw, + 'ordered_media_attachment_ids' => $status->media()->orderBy('order')->pluck('id')->toArray(), + 'created_at' => $status->created_at + ]); + } + } + + public static function createEdit(Status $status, $attributes) + { + $cleaned = isset($attributes['status']) ? Purify::clean($attributes['status']) : null; + $spoiler_text = isset($attributes['spoiler_text']) ? Purify::clean($attributes['spoiler_text']) : null; + $sensitive = isset($attributes['sensitive']) ? $attributes['sensitive'] : null; + $mids = $status->media()->count() ? $status->media()->orderBy('order')->pluck('id')->toArray() : null; + StatusEdit::create([ + 'status_id' => $status->id, + 'profile_id' => $status->profile_id, + 'caption' => $cleaned, + 'spoiler_text' => $spoiler_text, + 'is_nsfw' => $sensitive, + 'ordered_media_attachment_ids' => $mids + ]); + } +} diff --git a/app/Status.php b/app/Status.php index 183c18023..4148a4f99 100644 --- a/app/Status.php +++ b/app/Status.php @@ -9,6 +9,7 @@ use App\Http\Controllers\StatusController; use Illuminate\Database\Eloquent\SoftDeletes; use App\Models\Poll; use App\Services\AccountService; +use App\Models\StatusEdit; class Status extends Model { @@ -27,7 +28,8 @@ class Status extends Model * @var array */ protected $casts = [ - 'deleted_at' => 'datetime' + 'deleted_at' => 'datetime', + 'edited_at' => 'datetime' ]; protected $guarded = []; @@ -393,4 +395,9 @@ class Status extends Model { return $this->hasOne(Poll::class); } + + public function edits() + { + return $this->hasMany(StatusEdit::class); + } } diff --git a/app/Transformer/ActivityPub/Verb/UpdateNote.php b/app/Transformer/ActivityPub/Verb/UpdateNote.php new file mode 100644 index 000000000..bdbb20c45 --- /dev/null +++ b/app/Transformer/ActivityPub/Verb/UpdateNote.php @@ -0,0 +1,133 @@ +mentions->map(function ($mention) { + $webfinger = $mention->emailUrl(); + $name = Str::startsWith($webfinger, '@') ? + $webfinger : + '@' . $webfinger; + return [ + 'type' => 'Mention', + 'href' => $mention->permalink(), + 'name' => $name + ]; + })->toArray(); + + if($status->in_reply_to_id != null) { + $parent = $status->parent()->profile; + if($parent) { + $webfinger = $parent->emailUrl(); + $name = Str::startsWith($webfinger, '@') ? + $webfinger : + '@' . $webfinger; + $reply = [ + 'type' => 'Mention', + 'href' => $parent->permalink(), + 'name' => $name + ]; + $mentions = array_merge($reply, $mentions); + } + } + + $hashtags = $status->hashtags->map(function ($hashtag) { + return [ + 'type' => 'Hashtag', + 'href' => $hashtag->url(), + 'name' => "#{$hashtag->name}", + ]; + })->toArray(); + + $emojis = CustomEmoji::scan($status->caption, true) ?? []; + $emoji = array_merge($emojis, $mentions); + $tags = array_merge($emoji, $hashtags); + + $latestEdit = $status->edits()->latest()->first(); + + return [ + '@context' => [ + 'https://w3id.org/security/v1', + 'https://www.w3.org/ns/activitystreams', + [ + 'Hashtag' => 'as:Hashtag', + 'sensitive' => 'as:sensitive', + 'schema' => 'http://schema.org/', + 'pixelfed' => 'http://pixelfed.org/ns#', + 'commentsEnabled' => [ + '@id' => 'pixelfed:commentsEnabled', + '@type' => 'schema:Boolean' + ], + 'capabilities' => [ + '@id' => 'pixelfed:capabilities', + '@container' => '@set' + ], + 'announce' => [ + '@id' => 'pixelfed:canAnnounce', + '@type' => '@id' + ], + 'like' => [ + '@id' => 'pixelfed:canLike', + '@type' => '@id' + ], + 'reply' => [ + '@id' => 'pixelfed:canReply', + '@type' => '@id' + ], + 'toot' => 'http://joinmastodon.org/ns#', + 'Emoji' => 'toot:Emoji' + ] + ], + 'id' => $status->permalink('#updates/' . $latestEdit->id), + 'type' => 'Update', + 'actor' => $status->profile->permalink(), + 'published' => $latestEdit->created_at->toAtomString(), + 'to' => $status->scopeToAudience('to'), + 'cc' => $status->scopeToAudience('cc'), + 'object' => [ + 'id' => $status->url(), + 'type' => 'Note', + 'summary' => $status->is_nsfw ? $status->cw_summary : null, + 'content' => $status->rendered ?? $status->caption, + 'inReplyTo' => $status->in_reply_to_id ? $status->parent()->url() : null, + 'published' => $status->created_at->toAtomString(), + 'url' => $status->url(), + 'attributedTo' => $status->profile->permalink(), + 'to' => $status->scopeToAudience('to'), + 'cc' => $status->scopeToAudience('cc'), + 'sensitive' => (bool) $status->is_nsfw, + 'attachment' => $status->media()->orderBy('order')->get()->map(function ($media) { + return [ + 'type' => $media->activityVerb(), + 'mediaType' => $media->mime, + 'url' => $media->url(), + 'name' => $media->caption, + ]; + })->toArray(), + 'tag' => $tags, + 'commentsEnabled' => (bool) !$status->comments_disabled, + 'updated' => $latestEdit->created_at->toAtomString(), + 'capabilities' => [ + 'announce' => 'https://www.w3.org/ns/activitystreams#Public', + 'like' => 'https://www.w3.org/ns/activitystreams#Public', + 'reply' => $status->comments_disabled == true ? '[]' : 'https://www.w3.org/ns/activitystreams#Public' + ], + 'location' => $status->place_id ? [ + 'type' => 'Place', + 'name' => $status->place->name, + 'longitude' => $status->place->long, + 'latitude' => $status->place->lat, + 'country' => $status->place->country + ] : null, + ] + ]; + } +} diff --git a/app/Transformer/Api/StatusStatelessTransformer.php b/app/Transformer/Api/StatusStatelessTransformer.php index 38a3fedf8..acb522446 100644 --- a/app/Transformer/Api/StatusStatelessTransformer.php +++ b/app/Transformer/Api/StatusStatelessTransformer.php @@ -65,7 +65,8 @@ class StatusStatelessTransformer extends Fractal\TransformerAbstract 'media_attachments' => MediaService::get($status->id), 'account' => AccountService::get($status->profile_id, true), 'tags' => StatusHashtagService::statusTags($status->id), - 'poll' => $poll + 'poll' => $poll, + 'edited_at' => $status->edited_at ? str_replace('+00:00', 'Z', $status->edited_at->format(DATE_RFC3339_EXTENDED)) : null, ]; } } diff --git a/app/Transformer/Api/StatusTransformer.php b/app/Transformer/Api/StatusTransformer.php index 61c5f875b..f735a57be 100644 --- a/app/Transformer/Api/StatusTransformer.php +++ b/app/Transformer/Api/StatusTransformer.php @@ -70,6 +70,7 @@ class StatusTransformer extends Fractal\TransformerAbstract 'tags' => StatusHashtagService::statusTags($status->id), 'poll' => $poll, 'bookmarked' => BookmarkService::get($pid, $status->id), + 'edited_at' => $status->edited_at ? str_replace('+00:00', 'Z', $status->edited_at->format(DATE_RFC3339_EXTENDED)) : null, ]; } } diff --git a/app/Util/ActivityPub/Inbox.php b/app/Util/ActivityPub/Inbox.php index 790a48e8d..325d9b0c3 100644 --- a/app/Util/ActivityPub/Inbox.php +++ b/app/Util/ActivityPub/Inbox.php @@ -28,6 +28,7 @@ use App\Jobs\DeletePipeline\DeleteRemoteProfilePipeline; use App\Jobs\DeletePipeline\DeleteRemoteStatusPipeline; use App\Jobs\StoryPipeline\StoryExpire; use App\Jobs\StoryPipeline\StoryFetch; +use App\Jobs\StatusPipeline\StatusRemoteUpdatePipeline; use App\Util\ActivityPub\Validator\Accept as AcceptValidator; use App\Util\ActivityPub\Validator\Add as AddValidator; @@ -128,9 +129,9 @@ class Inbox $this->handleFlagActivity(); break; - // case 'Update': - // (new UpdateActivity($this->payload, $this->profile))->handle(); - // break; + case 'Update': + $this->handleUpdateActivity(); + break; default: // TODO: decide how to handle invalid verbs. @@ -1207,4 +1208,19 @@ class Inbox return; } + + public function handleUpdateActivity() + { + $activity = $this->payload['object']; + + if(!isset($activity['type'], $activity['id'])) { + return; + } + + if($activity['type'] === 'Note') { + if(Status::whereObjectUrl($activity['id'])->exists()) { + StatusRemoteUpdatePipeline::dispatch($activity); + } + } + } } diff --git a/config/exp.php b/config/exp.php index 0c9f83706..0ace5135b 100644 --- a/config/exp.php +++ b/config/exp.php @@ -25,6 +25,8 @@ return [ // Cached public timeline for larger instances (beta) 'cached_public_timeline' => env('EXP_CPT', false), + 'cached_home_timeline' => env('EXP_CHT', false), + // Groups (unreleased) 'gps' => env('EXP_GPS', false), @@ -33,4 +35,10 @@ return [ // Enforce Mastoapi Compatibility (alpha) 'emc' => env('EXP_EMC', true), + + // HLS Live Streaming + 'hls' => env('HLS_LIVE', false), + + // Post Update/Edits + 'pue' => env('EXP_PUE', true), ]; diff --git a/public/css/admin.css b/public/css/admin.css index 431e8ca31..658de1dbc 100644 Binary files a/public/css/admin.css and b/public/css/admin.css differ diff --git a/public/css/app.css b/public/css/app.css index a0176c807..0c96787bd 100644 Binary files a/public/css/app.css and b/public/css/app.css differ diff --git a/public/css/appdark.css b/public/css/appdark.css index e8c2fad49..414d666f8 100644 Binary files a/public/css/appdark.css and b/public/css/appdark.css differ diff --git a/public/css/landing.css b/public/css/landing.css index f52fd36d9..152a6a78f 100644 Binary files a/public/css/landing.css and b/public/css/landing.css differ diff --git a/public/css/spa.css b/public/css/spa.css index 8d2e31958..37cce8287 100644 Binary files a/public/css/spa.css and b/public/css/spa.css differ diff --git a/public/js/about.bundle.44a18841089fdde3.js b/public/js/about.bundle.dcf91eae809841f8.js similarity index 100% rename from public/js/about.bundle.44a18841089fdde3.js rename to public/js/about.bundle.dcf91eae809841f8.js diff --git a/public/js/admin.js b/public/js/admin.js index 48d5949b8..cb489e556 100644 Binary files a/public/js/admin.js and b/public/js/admin.js differ diff --git a/public/js/changelog.bundle.7f58a5ccc6659eb2.js b/public/js/changelog.bundle.500c0754dd59045b.js similarity index 100% rename from public/js/changelog.bundle.7f58a5ccc6659eb2.js rename to public/js/changelog.bundle.500c0754dd59045b.js diff --git a/public/js/compose.chunk.c413851da244ae3f.js b/public/js/compose.chunk.eb564854474fa255.js similarity index 100% rename from public/js/compose.chunk.c413851da244ae3f.js rename to public/js/compose.chunk.eb564854474fa255.js diff --git a/public/js/contact.bundle.d6c1d467c11796b1.js b/public/js/contact.bundle.97bd609a4737ae8d.js similarity index 100% rename from public/js/contact.bundle.d6c1d467c11796b1.js rename to public/js/contact.bundle.97bd609a4737ae8d.js diff --git a/public/js/daci.chunk.3f13ec9fc49e9d2b.js b/public/js/daci.chunk.3f13ec9fc49e9d2b.js deleted file mode 100644 index 42f453e93..000000000 Binary files a/public/js/daci.chunk.3f13ec9fc49e9d2b.js and /dev/null differ diff --git a/public/js/daci.chunk.e0ca30e5fa8c81f0.js b/public/js/daci.chunk.e0ca30e5fa8c81f0.js new file mode 100644 index 000000000..727da3337 Binary files /dev/null and b/public/js/daci.chunk.e0ca30e5fa8c81f0.js differ diff --git a/public/js/discover.chunk.5ceb85dcb38dfbef.js b/public/js/discover.chunk.93193c6ec9a42fc4.js similarity index 100% rename from public/js/discover.chunk.5ceb85dcb38dfbef.js rename to public/js/discover.chunk.93193c6ec9a42fc4.js diff --git a/public/js/discover~findfriends.chunk.1aabfedaab1849ba.js b/public/js/discover~findfriends.chunk.1aabfedaab1849ba.js deleted file mode 100644 index 6ed8a0034..000000000 Binary files a/public/js/discover~findfriends.chunk.1aabfedaab1849ba.js and /dev/null differ diff --git a/public/js/discover~findfriends.chunk.1c4a19cf5fda27ad.js b/public/js/discover~findfriends.chunk.1c4a19cf5fda27ad.js new file mode 100644 index 000000000..78fbdcc61 Binary files /dev/null and b/public/js/discover~findfriends.chunk.1c4a19cf5fda27ad.js differ diff --git a/public/js/discover~hashtag.bundle.b8319d6999d3e2e3.js b/public/js/discover~hashtag.bundle.10cb33346c033ea7.js similarity index 100% rename from public/js/discover~hashtag.bundle.b8319d6999d3e2e3.js rename to public/js/discover~hashtag.bundle.10cb33346c033ea7.js diff --git a/public/js/discover~memories.chunk.70b04c7698c2172b.js b/public/js/discover~memories.chunk.70b04c7698c2172b.js deleted file mode 100644 index d01487e44..000000000 Binary files a/public/js/discover~memories.chunk.70b04c7698c2172b.js and /dev/null differ diff --git a/public/js/discover~memories.chunk.a95b0149f5e4817f.js b/public/js/discover~memories.chunk.a95b0149f5e4817f.js new file mode 100644 index 000000000..542314a98 Binary files /dev/null and b/public/js/discover~memories.chunk.a95b0149f5e4817f.js differ diff --git a/public/js/discover~myhashtags.chunk.089b7465b2359979.js b/public/js/discover~myhashtags.chunk.089b7465b2359979.js deleted file mode 100644 index 0cc8aeaa4..000000000 Binary files a/public/js/discover~myhashtags.chunk.089b7465b2359979.js and /dev/null differ diff --git a/public/js/discover~myhashtags.chunk.9aa66068d1e96512.js b/public/js/discover~myhashtags.chunk.9aa66068d1e96512.js new file mode 100644 index 000000000..769d6347f Binary files /dev/null and b/public/js/discover~myhashtags.chunk.9aa66068d1e96512.js differ diff --git a/public/js/discover~serverfeed.chunk.48875685bb3cec75.js b/public/js/discover~serverfeed.chunk.48875685bb3cec75.js new file mode 100644 index 000000000..e7fc5f6b1 Binary files /dev/null and b/public/js/discover~serverfeed.chunk.48875685bb3cec75.js differ diff --git a/public/js/discover~serverfeed.chunk.ff59ca12d08bb810.js b/public/js/discover~serverfeed.chunk.ff59ca12d08bb810.js deleted file mode 100644 index 0e7b1f388..000000000 Binary files a/public/js/discover~serverfeed.chunk.ff59ca12d08bb810.js and /dev/null differ diff --git a/public/js/discover~settings.chunk.5757ad3940569422.js b/public/js/discover~settings.chunk.5757ad3940569422.js deleted file mode 100644 index 1e34fb753..000000000 Binary files a/public/js/discover~settings.chunk.5757ad3940569422.js and /dev/null differ diff --git a/public/js/discover~settings.chunk.58f94c148a395667.js b/public/js/discover~settings.chunk.58f94c148a395667.js new file mode 100644 index 000000000..0ce4ac874 Binary files /dev/null and b/public/js/discover~settings.chunk.58f94c148a395667.js differ diff --git a/public/js/dms.chunk.91ab72a8dcd1a8a8.js b/public/js/dms.chunk.a36285d6eee3b46f.js similarity index 100% rename from public/js/dms.chunk.91ab72a8dcd1a8a8.js rename to public/js/dms.chunk.a36285d6eee3b46f.js diff --git a/public/js/dms~message.chunk.1cfdf19c4525eafa.js b/public/js/dms~message.chunk.1d2a7a110371a12b.js similarity index 100% rename from public/js/dms~message.chunk.1cfdf19c4525eafa.js rename to public/js/dms~message.chunk.1d2a7a110371a12b.js diff --git a/public/js/error404.bundle.5075813f1b00e10d.js b/public/js/error404.bundle.f84c69eed21a7d82.js similarity index 100% rename from public/js/error404.bundle.5075813f1b00e10d.js rename to public/js/error404.bundle.f84c69eed21a7d82.js diff --git a/public/js/help.bundle.7c1195b63e04d568.js b/public/js/help.bundle.0d8a2725bcc8ed81.js similarity index 100% rename from public/js/help.bundle.7c1195b63e04d568.js rename to public/js/help.bundle.0d8a2725bcc8ed81.js diff --git a/public/js/home.chunk.af8ef7b54f61b18d.js b/public/js/home.chunk.af8ef7b54f61b18d.js deleted file mode 100644 index abe40b28e..000000000 Binary files a/public/js/home.chunk.af8ef7b54f61b18d.js and /dev/null differ diff --git a/public/js/home.chunk.f0ab2b4f7e84894c.js b/public/js/home.chunk.f0ab2b4f7e84894c.js new file mode 100644 index 000000000..0c5f28760 Binary files /dev/null and b/public/js/home.chunk.f0ab2b4f7e84894c.js differ diff --git a/public/js/home.chunk.f0ab2b4f7e84894c.js.LICENSE.txt b/public/js/home.chunk.f0ab2b4f7e84894c.js.LICENSE.txt new file mode 100644 index 000000000..ae386fb79 --- /dev/null +++ b/public/js/home.chunk.f0ab2b4f7e84894c.js.LICENSE.txt @@ -0,0 +1 @@ +/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ diff --git a/public/js/i18n.bundle.9b9bf1b64e2aa1c1.js b/public/js/i18n.bundle.83d55d158de68d01.js similarity index 100% rename from public/js/i18n.bundle.9b9bf1b64e2aa1c1.js rename to public/js/i18n.bundle.83d55d158de68d01.js diff --git a/public/js/kb.bundle.f6ebdaac1fd552ca.js b/public/js/kb.bundle.7c3d070a9bcc0489.js similarity index 100% rename from public/js/kb.bundle.f6ebdaac1fd552ca.js rename to public/js/kb.bundle.7c3d070a9bcc0489.js diff --git a/public/js/live-player.js b/public/js/live-player.js index 2ace6e4eb..deac8dcaa 100644 Binary files a/public/js/live-player.js and b/public/js/live-player.js differ diff --git a/public/js/manifest.js b/public/js/manifest.js index c1bfd97d6..5fa7b7185 100644 Binary files a/public/js/manifest.js and b/public/js/manifest.js differ diff --git a/public/js/notifications.chunk.9de71a122956c663.js b/public/js/notifications.chunk.fa21418a86f44a18.js similarity index 100% rename from public/js/notifications.chunk.9de71a122956c663.js rename to public/js/notifications.chunk.fa21418a86f44a18.js diff --git a/public/js/post.chunk.62a9d21c9016fd95.js b/public/js/post.chunk.62a9d21c9016fd95.js deleted file mode 100644 index af462a50d..000000000 Binary files a/public/js/post.chunk.62a9d21c9016fd95.js and /dev/null differ diff --git a/public/js/post.chunk.fc948c7ae6cf23f0.js b/public/js/post.chunk.fc948c7ae6cf23f0.js new file mode 100644 index 000000000..458a6c042 Binary files /dev/null and b/public/js/post.chunk.fc948c7ae6cf23f0.js differ diff --git a/public/js/post.chunk.fc948c7ae6cf23f0.js.LICENSE.txt b/public/js/post.chunk.fc948c7ae6cf23f0.js.LICENSE.txt new file mode 100644 index 000000000..ae386fb79 --- /dev/null +++ b/public/js/post.chunk.fc948c7ae6cf23f0.js.LICENSE.txt @@ -0,0 +1 @@ +/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ diff --git a/public/js/profile.chunk.0f947cc09af5c8c3.js b/public/js/profile.chunk.0f947cc09af5c8c3.js deleted file mode 100644 index a2bdf3278..000000000 Binary files a/public/js/profile.chunk.0f947cc09af5c8c3.js and /dev/null differ diff --git a/public/js/profile.chunk.d1c4aa06ad944495.js b/public/js/profile.chunk.d1c4aa06ad944495.js new file mode 100644 index 000000000..a7a801777 Binary files /dev/null and b/public/js/profile.chunk.d1c4aa06ad944495.js differ diff --git a/public/js/profile~followers.bundle.fe353e697fb7660b.js b/public/js/profile~followers.bundle.eac566ea09458e75.js similarity index 100% rename from public/js/profile~followers.bundle.fe353e697fb7660b.js rename to public/js/profile~followers.bundle.eac566ea09458e75.js diff --git a/public/js/profile~following.bundle.c406db7b14d07d36.js b/public/js/profile~following.bundle.193b1268a32bbd07.js similarity index 100% rename from public/js/profile~following.bundle.c406db7b14d07d36.js rename to public/js/profile~following.bundle.193b1268a32bbd07.js diff --git a/public/js/static~privacy.bundle.24c230550b6938b2.js b/public/js/static~privacy.bundle.60f5c03624e7626e.js similarity index 100% rename from public/js/static~privacy.bundle.24c230550b6938b2.js rename to public/js/static~privacy.bundle.60f5c03624e7626e.js diff --git a/public/js/static~tos.bundle.65caad6c0546d8c9.js b/public/js/static~tos.bundle.d5389c3b8c2569d5.js similarity index 100% rename from public/js/static~tos.bundle.65caad6c0546d8c9.js rename to public/js/static~tos.bundle.d5389c3b8c2569d5.js diff --git a/public/js/vendor.js b/public/js/vendor.js index 3df191c49..64e7deda4 100644 Binary files a/public/js/vendor.js and b/public/js/vendor.js differ diff --git a/public/js/vendor.js.LICENSE.txt b/public/js/vendor.js.LICENSE.txt index 3fce34c8b..f5a9d0ea4 100644 --- a/public/js/vendor.js.LICENSE.txt +++ b/public/js/vendor.js.LICENSE.txt @@ -64,17 +64,6 @@ * Licensed under GPL 3. */ -/*! - * Sizzle CSS Selector Engine v2.3.10 - * https://sizzlejs.com/ - * - * Copyright JS Foundation and other contributors - * Released under the MIT license - * https://js.foundation/ - * - * Date: 2023-02-14 - */ - /*! * Vue.js v2.7.14 * (c) 2014-2022 Evan You @@ -82,17 +71,14 @@ */ /*! - * jQuery JavaScript Library v3.6.4 + * jQuery JavaScript Library v3.7.0 * https://jquery.com/ * - * Includes Sizzle.js - * https://sizzlejs.com/ - * * Copyright OpenJS Foundation and other contributors * Released under the MIT license * https://jquery.org/license * - * Date: 2023-03-08T15:28Z + * Date: 2023-05-11T18:29Z */ /*! @@ -163,628 +149,8 @@ See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ -/*! ../controller/level-helper */ - -/*! ../crypt/decrypter */ - -/*! ../demux/aacdemuxer */ - -/*! ../demux/chunk-cache */ - -/*! ../demux/id3 */ - -/*! ../demux/mp3demuxer */ - -/*! ../demux/mp4demuxer */ - -/*! ../demux/transmuxer */ - -/*! ../demux/transmuxer-interface */ - -/*! ../demux/transmuxer-worker.ts */ - -/*! ../demux/tsdemuxer */ - -/*! ../errors */ - -/*! ../events */ - -/*! ../is-supported */ - -/*! ../loader/date-range */ - -/*! ../loader/fragment */ - -/*! ../loader/fragment-loader */ - -/*! ../loader/level-key */ - -/*! ../loader/load-stats */ - -/*! ../remux/mp4-remuxer */ - -/*! ../remux/passthrough-remuxer */ - -/*! ../task-loop */ - -/*! ../types/cmcd */ - -/*! ../types/demuxer */ - -/*! ../types/level */ - -/*! ../types/loader */ - -/*! ../types/transmuxer */ - -/*! ../utils/attr-list */ - -/*! ../utils/binary-search */ - -/*! ../utils/buffer-helper */ - -/*! ../utils/cea-608-parser */ - -/*! ../utils/codecs */ - -/*! ../utils/discontinuities */ - -/*! ../utils/ewma */ - -/*! ../utils/ewma-bandwidth-estimator */ - -/*! ../utils/hex */ - -/*! ../utils/imsc1-ttml-parser */ - -/*! ../utils/keysystem-util */ - -/*! ../utils/logger */ - -/*! ../utils/mediakeys-helper */ - -/*! ../utils/mediasource-helper */ - -/*! ../utils/mp4-tools */ - -/*! ../utils/numeric-encoding-utils */ - -/*! ../utils/output-filter */ - -/*! ../utils/texttrack-utils */ - -/*! ../utils/time-ranges */ - -/*! ../utils/timescale-conversion */ - -/*! ../utils/typed-array */ - -/*! ../utils/webvtt-parser */ - -/*! ./aac-helper */ - -/*! ./adts */ - -/*! ./aes-crypto */ - -/*! ./aes-decryptor */ - -/*! ./base-audio-demuxer */ - -/*! ./base-playlist-controller */ - -/*! ./base-stream-controller */ - -/*! ./buffer-operation-queue */ - -/*! ./config */ - -/*! ./controller/abr-controller */ - -/*! ./controller/audio-stream-controller */ - -/*! ./controller/audio-track-controller */ - -/*! ./controller/buffer-controller */ - -/*! ./controller/cap-level-controller */ - -/*! ./controller/cmcd-controller */ - -/*! ./controller/eme-controller */ - -/*! ./controller/fps-controller */ - -/*! ./controller/fragment-tracker */ - -/*! ./controller/id3-track-controller */ - -/*! ./controller/latency-controller */ - -/*! ./controller/level-controller */ - -/*! ./controller/stream-controller */ - -/*! ./controller/subtitle-stream-controller */ - -/*! ./controller/subtitle-track-controller */ - -/*! ./controller/timeline-controller */ - -/*! ./date-range */ - -/*! ./dummy-demuxed-track */ - -/*! ./errors */ - -/*! ./events */ - -/*! ./exp-golomb */ - -/*! ./fast-aes-key */ - -/*! ./fragment */ - -/*! ./fragment-finders */ - -/*! ./fragment-loader */ - -/*! ./fragment-tracker */ - -/*! ./gap-controller */ - -/*! ./hex */ - -/*! ./is-supported */ - -/*! ./level-details */ - -/*! ./level-helper */ - -/*! ./level-key */ - -/*! ./load-stats */ - -/*! ./loader/key-loader */ - -/*! ./loader/playlist-loader */ - -/*! ./logger */ - -/*! ./m3u8-parser */ - -/*! ./mp4-generator */ - -/*! ./mp4-remuxer */ - -/*! ./mp4-tools */ - -/*! ./mpegaudio */ - -/*! ./numeric-encoding-utils */ - -/*! ./sample-aes */ - -/*! ./src/polyfills/number */ - -/*! ./texttrack-utils */ - -/*! ./timescale-conversion */ - -/*! ./typed-array */ - -/*! ./types/level */ - -/*! ./utils/cues */ - -/*! ./utils/fetch-loader */ - -/*! ./utils/logger */ - -/*! ./utils/mediakeys-helper */ - -/*! ./utils/mediasource-helper */ - -/*! ./utils/xhr-loader */ - -/*! ./vttcue */ - -/*! ./vttparser */ - -/*! ./webvtt-parser */ - -/*! ./webworkify-webpack */ - -/*! eventemitter3 */ - /*! https://mths.be/punycode v1.4.1 by @mathias */ -/*! url-toolkit */ - -/*!********************!*\ - !*** ./src/hls.ts ***! - \********************/ - -/*!***********************!*\ - !*** ./src/config.ts ***! - \***********************/ - -/*!***********************!*\ - !*** ./src/errors.ts ***! - \***********************/ - -/*!***********************!*\ - !*** ./src/events.ts ***! - \***********************/ - -/*!**************************!*\ - !*** ./src/demux/id3.ts ***! - \**************************/ - -/*!**************************!*\ - !*** ./src/task-loop.ts ***! - \**************************/ - -/*!**************************!*\ - !*** ./src/utils/hex.ts ***! - \**************************/ - -/*!***************************!*\ - !*** ./src/demux/adts.ts ***! - \***************************/ - -/*!***************************!*\ - !*** ./src/types/cmcd.ts ***! - \***************************/ - -/*!***************************!*\ - !*** ./src/utils/cues.ts ***! - \***************************/ - -/*!***************************!*\ - !*** ./src/utils/ewma.ts ***! - \***************************/ - -/*!****************************!*\ - !*** ./src/types/level.ts ***! - \****************************/ - -/*!*****************************!*\ - !*** ./src/is-supported.ts ***! - \*****************************/ - -/*!*****************************!*\ - !*** ./src/types/loader.ts ***! - \*****************************/ - -/*!*****************************!*\ - !*** ./src/utils/codecs.ts ***! - \*****************************/ - -/*!*****************************!*\ - !*** ./src/utils/logger.ts ***! - \*****************************/ - -/*!*****************************!*\ - !*** ./src/utils/vttcue.ts ***! - \*****************************/ - -/*!******************************!*\ - !*** ./src/types/demuxer.ts ***! - \******************************/ - -/*!********************************!*\ - !*** ./src/crypt/decrypter.ts ***! - \********************************/ - -/*!********************************!*\ - !*** ./src/demux/mpegaudio.ts ***! - \********************************/ - -/*!********************************!*\ - !*** ./src/demux/tsdemuxer.ts ***! - \********************************/ - -/*!********************************!*\ - !*** ./src/loader/fragment.ts ***! - \********************************/ - -/*!********************************!*\ - !*** ./src/utils/attr-list.ts ***! - \********************************/ - -/*!********************************!*\ - !*** ./src/utils/mp4-tools.ts ***! - \********************************/ - -/*!********************************!*\ - !*** ./src/utils/vttparser.ts ***! - \********************************/ - -/*!*********************************!*\ - !*** ./src/crypt/aes-crypto.ts ***! - \*********************************/ - -/*!*********************************!*\ - !*** ./src/demux/aacdemuxer.ts ***! - \*********************************/ - -/*!*********************************!*\ - !*** ./src/demux/exp-golomb.ts ***! - \*********************************/ - -/*!*********************************!*\ - !*** ./src/demux/mp3demuxer.ts ***! - \*********************************/ - -/*!*********************************!*\ - !*** ./src/demux/mp4demuxer.ts ***! - \*********************************/ - -/*!*********************************!*\ - !*** ./src/demux/sample-aes.ts ***! - \*********************************/ - -/*!*********************************!*\ - !*** ./src/demux/transmuxer.ts ***! - \*********************************/ - -/*!*********************************!*\ - !*** ./src/loader/level-key.ts ***! - \*********************************/ - -/*!*********************************!*\ - !*** ./src/polyfills/number.ts ***! - \*********************************/ - -/*!*********************************!*\ - !*** ./src/remux/aac-helper.ts ***! - \*********************************/ - -/*!*********************************!*\ - !*** ./src/types/transmuxer.ts ***! - \*********************************/ - -/*!*********************************!*\ - !*** ./src/utils/xhr-loader.ts ***! - \*********************************/ - -/*!**********************************!*\ - !*** ./src/demux/chunk-cache.ts ***! - \**********************************/ - -/*!**********************************!*\ - !*** ./src/loader/date-range.ts ***! - \**********************************/ - -/*!**********************************!*\ - !*** ./src/loader/key-loader.ts ***! - \**********************************/ - -/*!**********************************!*\ - !*** ./src/loader/load-stats.ts ***! - \**********************************/ - -/*!**********************************!*\ - !*** ./src/remux/mp4-remuxer.ts ***! - \**********************************/ - -/*!**********************************!*\ - !*** ./src/utils/time-ranges.ts ***! - \**********************************/ - -/*!**********************************!*\ - !*** ./src/utils/typed-array.ts ***! - \**********************************/ - -/*!***********************************!*\ - !*** ./src/crypt/fast-aes-key.ts ***! - \***********************************/ - -/*!***********************************!*\ - !*** ./src/loader/m3u8-parser.ts ***! - \***********************************/ - -/*!***********************************!*\ - !*** ./src/utils/fetch-loader.ts ***! - \***********************************/ - -/*!************************************!*\ - !*** ./src/crypt/aes-decryptor.ts ***! - \************************************/ - -/*!************************************!*\ - !*** ./src/remux/mp4-generator.ts ***! - \************************************/ - -/*!************************************!*\ - !*** ./src/utils/binary-search.ts ***! - \************************************/ - -/*!************************************!*\ - !*** ./src/utils/buffer-helper.ts ***! - \************************************/ - -/*!************************************!*\ - !*** ./src/utils/output-filter.ts ***! - \************************************/ - -/*!************************************!*\ - !*** ./src/utils/webvtt-parser.ts ***! - \************************************/ - -/*!*************************************!*\ - !*** ./src/loader/level-details.ts ***! - \*************************************/ - -/*!*************************************!*\ - !*** ./src/utils/cea-608-parser.ts ***! - \*************************************/ - -/*!*************************************!*\ - !*** ./src/utils/keysystem-util.ts ***! - \*************************************/ - -/*!**************************************!*\ - !*** ./src/utils/discontinuities.ts ***! - \**************************************/ - -/*!**************************************!*\ - !*** ./src/utils/texttrack-utils.ts ***! - \**************************************/ - -/*!***************************************!*\ - !*** ./src/loader/fragment-loader.ts ***! - \***************************************/ - -/*!***************************************!*\ - !*** ./src/loader/playlist-loader.ts ***! - \***************************************/ - -/*!***************************************!*\ - !*** ./src/utils/mediakeys-helper.ts ***! - \***************************************/ - -/*!****************************************!*\ - !*** ./src/controller/level-helper.ts ***! - \****************************************/ - -/*!****************************************!*\ - !*** ./src/demux/transmuxer-worker.ts ***! - \****************************************/ - -/*!****************************************!*\ - !*** ./src/utils/imsc1-ttml-parser.ts ***! - \****************************************/ - -/*!*****************************************!*\ - !*** ./src/demux/base-audio-demuxer.ts ***! - \*****************************************/ - -/*!*****************************************!*\ - !*** ./src/demux/webworkify-webpack.js ***! - \*****************************************/ - -/*!*****************************************!*\ - !*** ./src/utils/mediasource-helper.ts ***! - \*****************************************/ - -/*!******************************************!*\ - !*** ./src/controller/abr-controller.ts ***! - \******************************************/ - -/*!******************************************!*\ - !*** ./src/controller/eme-controller.ts ***! - \******************************************/ - -/*!******************************************!*\ - !*** ./src/controller/fps-controller.ts ***! - \******************************************/ - -/*!******************************************!*\ - !*** ./src/controller/gap-controller.ts ***! - \******************************************/ - -/*!******************************************!*\ - !*** ./src/demux/dummy-demuxed-track.ts ***! - \******************************************/ - -/*!******************************************!*\ - !*** ./src/remux/passthrough-remuxer.ts ***! - \******************************************/ - -/*!*******************************************!*\ - !*** ./src/controller/cmcd-controller.ts ***! - \*******************************************/ - -/*!*******************************************!*\ - !*** ./src/demux/transmuxer-interface.ts ***! - \*******************************************/ - -/*!*******************************************!*\ - !*** ./src/utils/timescale-conversion.ts ***! - \*******************************************/ - -/*!********************************************!*\ - !*** ./src/controller/fragment-finders.ts ***! - \********************************************/ - -/*!********************************************!*\ - !*** ./src/controller/fragment-tracker.ts ***! - \********************************************/ - -/*!********************************************!*\ - !*** ./src/controller/level-controller.ts ***! - \********************************************/ - -/*!*********************************************!*\ - !*** ./node_modules/eventemitter3/index.js ***! - \*********************************************/ - -/*!*********************************************!*\ - !*** ./src/controller/buffer-controller.ts ***! - \*********************************************/ - -/*!*********************************************!*\ - !*** ./src/controller/stream-controller.ts ***! - \*********************************************/ - -/*!*********************************************!*\ - !*** ./src/utils/numeric-encoding-utils.ts ***! - \*********************************************/ - -/*!**********************************************!*\ - !*** ./src/controller/latency-controller.ts ***! - \**********************************************/ - -/*!***********************************************!*\ - !*** ./src/controller/timeline-controller.ts ***! - \***********************************************/ - -/*!***********************************************!*\ - !*** ./src/utils/ewma-bandwidth-estimator.ts ***! - \***********************************************/ - -/*!************************************************!*\ - !*** ./src/controller/cap-level-controller.ts ***! - \************************************************/ - -/*!************************************************!*\ - !*** ./src/controller/id3-track-controller.ts ***! - \************************************************/ - -/*!**************************************************!*\ - !*** ./src/controller/audio-track-controller.ts ***! - \**************************************************/ - -/*!**************************************************!*\ - !*** ./src/controller/base-stream-controller.ts ***! - \**************************************************/ - -/*!**************************************************!*\ - !*** ./src/controller/buffer-operation-queue.ts ***! - \**************************************************/ - -/*!***************************************************!*\ - !*** ./src/controller/audio-stream-controller.ts ***! - \***************************************************/ - -/*!****************************************************!*\ - !*** ./src/controller/base-playlist-controller.ts ***! - \****************************************************/ - -/*!*****************************************************!*\ - !*** ./node_modules/url-toolkit/src/url-toolkit.js ***! - \*****************************************************/ - -/*!*****************************************************!*\ - !*** ./src/controller/subtitle-track-controller.ts ***! - \*****************************************************/ - -/*!******************************************************!*\ - !*** ./src/controller/subtitle-stream-controller.ts ***! - \******************************************************/ - /** * vue-class-component v7.2.3 * (c) 2015-present Evan You diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 2675c6ea9..8520787b0 100644 Binary files a/public/mix-manifest.json and b/public/mix-manifest.json differ diff --git a/resources/assets/components/Post.vue b/resources/assets/components/Post.vue index 842b15dd5..1cc57c84e 100644 --- a/resources/assets/components/Post.vue +++ b/resources/assets/components/Post.vue @@ -26,7 +26,7 @@

+ + @@ -119,6 +125,7 @@ import LikesModal from './partials/post/LikeModal.vue'; import SharesModal from './partials/post/ShareModal.vue'; import ReportModal from './partials/modal/ReportPost.vue'; + import PostEditModal from './partials/post/PostEditModal.vue'; export default { props: { @@ -140,7 +147,8 @@ "likes-modal": LikesModal, "shares-modal": SharesModal, "rightbar": Rightbar, - "report-modal": ReportModal + "report-modal": ReportModal, + "post-edit-modal": PostEditModal }, data() { @@ -156,7 +164,8 @@ isReply: false, reply: {}, showSharesModal: false, - postStateError: false + postStateError: false, + forceUpdateIdx: 0 } }, @@ -405,6 +414,17 @@ break; } }, + + handleEdit(status) { + this.$refs.editModal.show(status); + }, + + mergeUpdatedPost(post) { + this.post = post; + this.$nextTick(() => { + this.forceUpdateIdx++; + }); + } } } diff --git a/resources/assets/components/partials/post/EditHistoryModal.vue b/resources/assets/components/partials/post/EditHistoryModal.vue new file mode 100644 index 000000000..67cf89e0a --- /dev/null +++ b/resources/assets/components/partials/post/EditHistoryModal.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/resources/assets/components/partials/post/PostHeader.vue b/resources/assets/components/partials/post/PostHeader.vue new file mode 100644 index 000000000..ddbbf740c --- /dev/null +++ b/resources/assets/components/partials/post/PostHeader.vue @@ -0,0 +1,348 @@ + + + diff --git a/resources/assets/sass/admin.scss b/resources/assets/sass/admin.scss index 93c513f82..cb01e4c69 100644 --- a/resources/assets/sass/admin.scss +++ b/resources/assets/sass/admin.scss @@ -13,3 +13,23 @@ body, button, input, textarea { font-size: 30px; } } + +.nav-pills .nav-item { + padding-right: 1rem; +} + +.list-fade-bottom { + position: relative; + + &:after { + content: ""; + position: absolute; + z-index: 1; + bottom: 0; + left: 0; + pointer-events: none; + background-image: linear-gradient(to bottom, rgba(255,255,255, 0), rgba(255,255,255, 1) 90%); + width: 100%; + height: 10em; + } +} diff --git a/resources/assets/sass/spa.scss b/resources/assets/sass/spa.scss index 3fea3e7e2..e2ed0e054 100644 --- a/resources/assets/sass/spa.scss +++ b/resources/assets/sass/spa.scss @@ -210,6 +210,7 @@ a.text-dark:hover { .autocomplete-result-list { background: var(--light) !important; + z-index: 2 !important; } .dropdown-menu, @@ -261,7 +262,8 @@ span.twitter-typeahead .tt-suggestion:focus { border-color: var(--border-color) !important; } -.modal-header { +.modal-header, +.modal-footer { border-color: var(--border-color); } @@ -328,3 +330,66 @@ span.twitter-typeahead .tt-suggestion:focus { } } } + +.compose-modal-component { + .form-control:focus { + color: var(--body-color); + } +} + +.modal-body { + .nav-tabs .nav-link.active, + .nav-tabs .nav-item.show .nav-link { + background-color: transparent; + border-color: var(--border-color); + } + + .nav-tabs .nav-link:hover, + .nav-tabs .nav-link:focus { + border-color: var(--border-color); + } + + .form-control:focus { + color: var(--body-color); + } +} + +.tribute-container { + border: 0; + + ul { + margin-top: 0; + border-color: var(--border-color); + } + + li { + padding: 0.5rem 1rem; + border-top: 0; + border-left: 0; + border-right: 0; + font-size: 13px; + + &:not(:last-child) { + border-bottom: 1px solid var(--border-color); + } + + &.highlight, + &:hover { + color: var(--body-color); + font-weight: bold; + background: rgba(44, 120, 191, 0.25); + } + } +} + +.timeline-status-component { + .username { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + margin-bottom: -3px; + word-break: break-word; + + @media (min-width: 768px) { + font-size: 17px; + } + } +} diff --git a/routes/api.php b/routes/api.php index 7e996df1d..a0b8b5155 100644 --- a/routes/api.php +++ b/routes/api.php @@ -94,6 +94,9 @@ Route::group(['prefix' => 'api'], function() use($middleware) { Route::post('tags/{id}/follow', 'Api\ApiV1Controller@followHashtag')->middleware($middleware); Route::post('tags/{id}/unfollow', 'Api\ApiV1Controller@unfollowHashtag')->middleware($middleware); Route::get('tags/{id}', 'Api\ApiV1Controller@getHashtag')->middleware($middleware); + + Route::get('statuses/{id}/history', 'StatusEditController@history')->middleware($middleware); + Route::put('statuses/{id}', 'StatusEditController@store')->middleware($middleware); }); Route::group(['prefix' => 'v2'], function() use($middleware) {