diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b1f87622..89b1762b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,6 +94,16 @@ - Update reply view, fix visibility filtering ([d419af4b](https://github.com/pixelfed/pixelfed/commit/d419af4b)) - Update AP helpers, ingest attachments in replies ([c504e643](https://github.com/pixelfed/pixelfed/commit/c504e643)) - Update Media model, use cloud filesystem url if enabled instead of cdn_url to easily update S3 media urls ([e6bc57d7](https://github.com/pixelfed/pixelfed/commit/e6bc57d7)) +- Update ap helpers, fix unset media name bug ([083f506b](https://github.com/pixelfed/pixelfed/commit/083f506b)) +- Update MediaStorageService, fix improper path ([964c62da](https://github.com/pixelfed/pixelfed/commit/964c62da)) +- Update ApiV1Controller, fix account statuses and bookmark pagination ([9f66d6b6](https://github.com/pixelfed/pixelfed/commit/9f66d6b6)) +- Update SearchApiV2Service, improve account search results ([f6a588f9](https://github.com/pixelfed/pixelfed/commit/f6a588f9)) +- Update profile model, improve avatarUrl fallback ([620ee826](https://github.com/pixelfed/pixelfed/commit/620ee826)) +- Update ApiV1Controller, use cursor pagination for favourited_by and reblogged_by endpoints ([e1c7e701](https://github.com/pixelfed/pixelfed/commit/e1c7e701)) +- Update ApiV1Controller, fix favourited_by and reblogged_by follows attribute ([1a130f3e](https://github.com/pixelfed/pixelfed/commit/1a130f3e)) +- Update notifications component, improve UX with exponential retry and loading state ([937e6d07](https://github.com/pixelfed/pixelfed/commit/937e6d07)) +- Update likeModal and shareModal components, use new pagination logic and re-add Follow/Unfollow buttons ([b565ead6](https://github.com/pixelfed/pixelfed/commit/b565ead6)) +- Update profileFeed component, fix pagination ([7cf41628](https://github.com/pixelfed/pixelfed/commit/7cf41628)) - ([](https://github.com/pixelfed/pixelfed/commit/)) ## [v0.11.4 (2022-10-04)](https://github.com/pixelfed/pixelfed/compare/v0.11.3...v0.11.4) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index 7d9b28cc0..8e9e7375b 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -2471,15 +2471,21 @@ class ApiV1Controller extends Controller abort_if(!$request->user(), 403); $this->validate($request, [ - 'page' => 'nullable|integer|min:1|max:40', 'limit' => 'nullable|integer|min:1|max:100' ]); - $limit = $request->input('limit') ?? 40; + $limit = $request->input('limit') ?? 10; $user = $request->user(); $status = Status::findOrFail($id); + $author = intval($status->profile_id) === intval($user->profile_id) || $user->is_admin; - if(intval($status->profile_id) !== intval($user->profile_id)) { + abort_if( + !$status->type || + !in_array($status->type, ['photo','photo:album', 'photo:video:album', 'reply', 'text', 'video', 'video:album']), + 404, + ); + + if(!$author) { if($status->scope == 'private') { abort_if(!FollowerService::follows($user->profile_id, $status->profile_id), 403); } else { @@ -2487,35 +2493,46 @@ class ApiV1Controller extends Controller } } - $page = $request->input('page', 1); - $start = $page == 1 ? 0 : (($page * $limit) - $limit); - $end = $start + $limit - 1; + $res = Status::where('reblog_of_id', $status->id) + ->orderByDesc('id') + ->cursorPaginate($limit) + ->withQueryString(); - $ids = ReblogService::getPostReblogs($id, $start, $end); - if(empty($ids)) { - return []; + if(!$res) { + return $this->json([]); } - $res = collect($ids) - ->map(function($id) { - $status = StatusService::get($id); - if($status) { - return AccountService::get($status['account']['id']); + $headers = []; + if($author && $res->hasPages()) { + $links = ''; + if($res->previousPageUrl()) { + $links = '<' . $res->previousPageUrl() .'>; rel="prev"'; + } + + if($res->nextPageUrl()) { + if(!empty($links)) { + $links .= ', '; } - return; - }) - ->filter(function($account) { - return $account && isset($account['id']); - }) - ->values(); + $links .= '<' . $res->nextPageUrl() .'>; rel="next"'; + } - $url = $request->url(); - $page = $request->input('page', 1); - $next = $page < 40 ? $page + 1 : 40; - $prev = $page > 1 ? $page - 1 : 1; - $links = '<'.$url.'?page='.$next.'&limit='.$limit.'>; rel="next", <'.$url.'?page='.$prev.'&limit='.$limit.'>; rel="prev"'; + $headers = ['Link' => $links]; + } - return $this->json($res, 200, ['Link' => $links]); + $res = $res->map(function($status) use($user) { + $account = AccountService::getMastodon($status->profile_id, true); + if(!$account) { + return false; + } + $account['follows'] = $status->profile_id == $user->profile_id ? null : FollowerService::follows($user->profile_id, $status->profile_id); + return $account; + }) + ->filter(function($account) { + return $account && isset($account['id']); + }) + ->values(); + + return $this->json($res, 200, $headers); } /** @@ -2530,58 +2547,72 @@ class ApiV1Controller extends Controller abort_if(!$request->user(), 403); $this->validate($request, [ - 'page' => 'nullable|integer|min:1|max:40', 'limit' => 'nullable|integer|min:1|max:100' ]); - $page = $request->input('page', 1); - $limit = $request->input('limit') ?? 40; + $limit = $request->input('limit') ?? 10; $user = $request->user(); $status = Status::findOrFail($id); - $offset = $page == 1 ? 0 : ($page * $limit - $limit); - if($offset > 100) { - if($user->profile_id != $status->profile_id) { - return []; - } - } + $author = intval($status->profile_id) === intval($user->profile_id) || $user->is_admin; - if(intval($status->profile_id) !== intval($user->profile_id)) { + abort_if( + !$status->type || + !in_array($status->type, ['photo','photo:album', 'photo:video:album', 'reply', 'text', 'video', 'video:album']), + 404, + ); + + if(!$author) { if($status->scope == 'private') { - abort_if(!$status->profile->followedBy($user->profile), 403); + abort_if(!FollowerService::follows($user->profile_id, $status->profile_id), 403); } else { abort_if(!in_array($status->scope, ['public','unlisted']), 403); } + + if($request->has('cursor')) { + return $this->json([]); + } } - $res = DB::table('likes') - ->select('likes.id', 'likes.profile_id', 'likes.status_id', 'followers.created_at') - ->leftJoin('followers', function($join) use($user, $status) { - return $join->on('likes.profile_id', '=', 'followers.following_id') - ->where('followers.profile_id', $user->profile_id) - ->where('likes.status_id', $status->id); - }) - ->whereStatusId($status->id) - ->orderByDesc('followers.created_at') - ->offset($offset) - ->limit($limit) - ->get() - ->map(function($like) { - $account = AccountService::getMastodon($like->profile_id, true); - $account['follows'] = isset($like->created_at); - return $account; - }) - ->filter(function($account) use($user) { - return $account && isset($account['id']); - }) - ->values(); + $res = Like::where('status_id', $status->id) + ->orderByDesc('id') + ->cursorPaginate($limit) + ->withQueryString(); - $url = $request->url(); - $page = $request->input('page', 1); - $next = $page < 40 ? $page + 1 : 40; - $prev = $page > 1 ? $page - 1 : 1; - $links = '<'.$url.'?page='.$next.'&limit='.$limit.'>; rel="next", <'.$url.'?page='.$prev.'&limit='.$limit.'>; rel="prev"'; + if(!$res) { + return $this->json([]); + } - return $this->json($res, 200, ['Link' => $links]); + $headers = []; + if($author && $res->hasPages()) { + $links = ''; + if($res->previousPageUrl()) { + $links = '<' . $res->previousPageUrl() .'>; rel="prev"'; + } + + if($res->nextPageUrl()) { + if(!empty($links)) { + $links .= ', '; + } + $links .= '<' . $res->nextPageUrl() .'>; rel="next"'; + } + + $headers = ['Link' => $links]; + } + + $res = $res->map(function($like) use($user) { + $account = AccountService::getMastodon($like->profile_id, true); + if(!$account) { + return false; + } + $account['follows'] = $like->profile_id == $user->profile_id ? null : FollowerService::follows($user->profile_id, $like->profile_id); + return $account; + }) + ->filter(function($account) use($user) { + return $account && isset($account['id']); + }) + ->values(); + + return $this->json($res, 200, $headers); } /** diff --git a/app/Profile.php b/app/Profile.php index f02144f09..450520880 100644 --- a/app/Profile.php +++ b/app/Profile.php @@ -160,6 +160,10 @@ class Profile extends Model $url = Cache::remember('avatar:'.$this->id, 1209600, function () { $avatar = $this->avatar; + if(!$avatar) { + return url('/storage/avatars/default.jpg'); + } + if($avatar->cdn_url) { if(substr($avatar->cdn_url, 0, 8) === 'https://') { return $avatar->cdn_url; @@ -170,6 +174,10 @@ class Profile extends Model $path = $avatar->media_path; + if(!$path) { + return url('/storage/avatars/default.jpg'); + } + if(substr($path, 0, 6) !== 'public') { return url('/storage/avatars/default.jpg'); } diff --git a/package-lock.json b/package-lock.json index e80555910..08f48785a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "dependencies": { "@fancyapps/fancybox": "^3.5.7", "@trevoreyre/autocomplete-vue": "^2.2.0", + "@web3-storage/parse-link-header": "^3.1.0", "animate.css": "^4.1.0", "bigpicture": "^2.6.2", "blurhash": "^1.1.3", @@ -2171,6 +2172,11 @@ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", "dev": true }, + "node_modules/@web3-storage/parse-link-header": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@web3-storage/parse-link-header/-/parse-link-header-3.1.0.tgz", + "integrity": "sha512-K1undnK70vLLauqdE8bq/l98isTF2FDhcP0UPpXVSjkSWe3xhAn5eRXk5jfA1E5ycNm84Ws/rQFUD7ue11nciw==" + }, "node_modules/@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -10970,6 +10976,11 @@ } } }, + "@web3-storage/parse-link-header": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@web3-storage/parse-link-header/-/parse-link-header-3.1.0.tgz", + "integrity": "sha512-K1undnK70vLLauqdE8bq/l98isTF2FDhcP0UPpXVSjkSWe3xhAn5eRXk5jfA1E5ycNm84Ws/rQFUD7ue11nciw==" + }, "@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", diff --git a/package.json b/package.json index 2bce70309..1a6fa47be 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "dependencies": { "@fancyapps/fancybox": "^3.5.7", "@trevoreyre/autocomplete-vue": "^2.2.0", + "@web3-storage/parse-link-header": "^3.1.0", "animate.css": "^4.1.0", "bigpicture": "^2.6.2", "blurhash": "^1.1.3", diff --git a/public/js/about.bundle.b4e0fef2bfd282de.js b/public/js/about.bundle.a0398e8c630f7036.js similarity index 100% rename from public/js/about.bundle.b4e0fef2bfd282de.js rename to public/js/about.bundle.a0398e8c630f7036.js diff --git a/public/js/admin.js b/public/js/admin.js index 9f4e01513..2940baed0 100644 Binary files a/public/js/admin.js and b/public/js/admin.js differ diff --git a/public/js/app.js b/public/js/app.js index a01c4d453..2480c310d 100644 Binary files a/public/js/app.js and b/public/js/app.js differ diff --git a/public/js/changelog.bundle.1346cd4a2aea418e.js b/public/js/changelog.bundle.9ac9432f209bde4e.js similarity index 100% rename from public/js/changelog.bundle.1346cd4a2aea418e.js rename to public/js/changelog.bundle.9ac9432f209bde4e.js diff --git a/public/js/components.js b/public/js/components.js index 97a68861d..4604aedf5 100644 Binary files a/public/js/components.js and b/public/js/components.js differ diff --git a/public/js/compose.chunk.88ef87270cef7295.js b/public/js/compose.chunk.f335df0cd85ea00b.js similarity index 100% rename from public/js/compose.chunk.88ef87270cef7295.js rename to public/js/compose.chunk.f335df0cd85ea00b.js diff --git a/public/js/contact.bundle.de2898072b8b7c67.js b/public/js/contact.bundle.3c0833e75a8155f2.js similarity index 100% rename from public/js/contact.bundle.de2898072b8b7c67.js rename to public/js/contact.bundle.3c0833e75a8155f2.js diff --git a/public/js/daci.chunk.fc282ba63a43593c.js b/public/js/daci.chunk.232f6f724c527858.js similarity index 100% rename from public/js/daci.chunk.fc282ba63a43593c.js rename to public/js/daci.chunk.232f6f724c527858.js diff --git a/public/js/discover.chunk.3ef6d6fe45dbe91b.js b/public/js/discover.chunk.3ef6d6fe45dbe91b.js deleted file mode 100644 index 2f9c2799b..000000000 Binary files a/public/js/discover.chunk.3ef6d6fe45dbe91b.js and /dev/null differ diff --git a/public/js/discover.chunk.b33cd1cc42853828.js b/public/js/discover.chunk.b33cd1cc42853828.js new file mode 100644 index 000000000..304f6631b Binary files /dev/null and b/public/js/discover.chunk.b33cd1cc42853828.js differ diff --git a/public/js/discover~findfriends.chunk.53fdd18a929791f0.js b/public/js/discover~findfriends.chunk.e3a7e0813bc9e3ec.js similarity index 100% rename from public/js/discover~findfriends.chunk.53fdd18a929791f0.js rename to public/js/discover~findfriends.chunk.e3a7e0813bc9e3ec.js diff --git a/public/js/discover~hashtag.bundle.2f72cbbe9aa1b317.js b/public/js/discover~hashtag.bundle.2f72cbbe9aa1b317.js deleted file mode 100644 index dd918732c..000000000 Binary files a/public/js/discover~hashtag.bundle.2f72cbbe9aa1b317.js and /dev/null differ diff --git a/public/js/discover~hashtag.bundle.7c5f7f5c21a1d88c.js b/public/js/discover~hashtag.bundle.7c5f7f5c21a1d88c.js new file mode 100644 index 000000000..cd23b2045 Binary files /dev/null and b/public/js/discover~hashtag.bundle.7c5f7f5c21a1d88c.js differ diff --git a/public/js/discover~memories.chunk.1cb17840dc8aea5f.js b/public/js/discover~memories.chunk.487c14a0180fbf85.js similarity index 100% rename from public/js/discover~memories.chunk.1cb17840dc8aea5f.js rename to public/js/discover~memories.chunk.487c14a0180fbf85.js diff --git a/public/js/discover~myhashtags.chunk.075cc9fe49783f65.js b/public/js/discover~myhashtags.chunk.075cc9fe49783f65.js new file mode 100644 index 000000000..1b65bf6c8 Binary files /dev/null and b/public/js/discover~myhashtags.chunk.075cc9fe49783f65.js differ diff --git a/public/js/discover~myhashtags.chunk.8cbed746da3c3307.js b/public/js/discover~myhashtags.chunk.8cbed746da3c3307.js deleted file mode 100644 index f7ed59d7c..000000000 Binary files a/public/js/discover~myhashtags.chunk.8cbed746da3c3307.js and /dev/null differ diff --git a/public/js/discover~serverfeed.chunk.a24b7b8c20612b1b.js b/public/js/discover~serverfeed.chunk.c37e8a7a49d49297.js similarity index 100% rename from public/js/discover~serverfeed.chunk.a24b7b8c20612b1b.js rename to public/js/discover~serverfeed.chunk.c37e8a7a49d49297.js diff --git a/public/js/discover~settings.chunk.9e385ba7c7242192.js b/public/js/discover~settings.chunk.ddc15c2d10514bf9.js similarity index 100% rename from public/js/discover~settings.chunk.9e385ba7c7242192.js rename to public/js/discover~settings.chunk.ddc15c2d10514bf9.js diff --git a/public/js/dms.chunk.37131c41fc288259.js b/public/js/dms.chunk.37131c41fc288259.js new file mode 100644 index 000000000..a115ec58f Binary files /dev/null and b/public/js/dms.chunk.37131c41fc288259.js differ diff --git a/public/js/dms.chunk.ffe36114c17441be.js b/public/js/dms.chunk.ffe36114c17441be.js deleted file mode 100644 index 9a197a5f8..000000000 Binary files a/public/js/dms.chunk.ffe36114c17441be.js and /dev/null differ diff --git a/public/js/dms~message.chunk.3396750e3f3e370d.js b/public/js/dms~message.chunk.848e25098152c821.js similarity index 100% rename from public/js/dms~message.chunk.3396750e3f3e370d.js rename to public/js/dms~message.chunk.848e25098152c821.js diff --git a/public/js/error404.bundle.2358054dc4c0a62b.js b/public/js/error404.bundle.6f43a867cb75b343.js similarity index 100% rename from public/js/error404.bundle.2358054dc4c0a62b.js rename to public/js/error404.bundle.6f43a867cb75b343.js diff --git a/public/js/help.bundle.37981267c6a91fdd.js b/public/js/help.bundle.4157e6be875557da.js similarity index 100% rename from public/js/help.bundle.37981267c6a91fdd.js rename to public/js/help.bundle.4157e6be875557da.js diff --git a/public/js/home.chunk.294faaa69171455b.js b/public/js/home.chunk.294faaa69171455b.js new file mode 100644 index 000000000..e31ea1e5e Binary files /dev/null and b/public/js/home.chunk.294faaa69171455b.js differ diff --git a/public/js/home.chunk.c5608f771be873ca.js b/public/js/home.chunk.c5608f771be873ca.js deleted file mode 100644 index 8d8dcdec5..000000000 Binary files a/public/js/home.chunk.c5608f771be873ca.js and /dev/null differ diff --git a/public/js/i18n.bundle.233c3a2e6c08c397.js b/public/js/i18n.bundle.c5c5f4ddf5b18688.js similarity index 100% rename from public/js/i18n.bundle.233c3a2e6c08c397.js rename to public/js/i18n.bundle.c5c5f4ddf5b18688.js diff --git a/public/js/installer.js b/public/js/installer.js index bf0dfa03f..7b77a31f4 100644 Binary files a/public/js/installer.js and b/public/js/installer.js differ diff --git a/public/js/kb.bundle.ffb0bccb31e767a2.js b/public/js/kb.bundle.e5709245effd8e20.js similarity index 100% rename from public/js/kb.bundle.ffb0bccb31e767a2.js rename to public/js/kb.bundle.e5709245effd8e20.js diff --git a/public/js/manifest.js b/public/js/manifest.js index e31fe7d73..55dce5ee8 100644 Binary files a/public/js/manifest.js and b/public/js/manifest.js differ diff --git a/public/js/notifications.chunk.e36cd010dbca7065.js b/public/js/notifications.chunk.a310984a7cefe091.js similarity index 100% rename from public/js/notifications.chunk.e36cd010dbca7065.js rename to public/js/notifications.chunk.a310984a7cefe091.js diff --git a/public/js/post.chunk.02abe63d47f8d51e.js b/public/js/post.chunk.02abe63d47f8d51e.js deleted file mode 100644 index 47a5bfa98..000000000 Binary files a/public/js/post.chunk.02abe63d47f8d51e.js and /dev/null differ diff --git a/public/js/post.chunk.dffb139831cf2ae9.js b/public/js/post.chunk.dffb139831cf2ae9.js new file mode 100644 index 000000000..8f10d000d Binary files /dev/null and b/public/js/post.chunk.dffb139831cf2ae9.js differ diff --git a/public/js/profile.chunk.99838eb369862e91.js b/public/js/profile.chunk.99838eb369862e91.js new file mode 100644 index 000000000..26cd2b70a Binary files /dev/null and b/public/js/profile.chunk.99838eb369862e91.js differ diff --git a/public/js/profile.chunk.cdad3298b78ff083.js b/public/js/profile.chunk.cdad3298b78ff083.js deleted file mode 100644 index 8756522cb..000000000 Binary files a/public/js/profile.chunk.cdad3298b78ff083.js and /dev/null differ diff --git a/public/js/profile~followers.bundle.d4dc19a65836f5ba.js b/public/js/profile~followers.bundle.f18a24d3924b651a.js similarity index 100% rename from public/js/profile~followers.bundle.d4dc19a65836f5ba.js rename to public/js/profile~followers.bundle.f18a24d3924b651a.js diff --git a/public/js/profile~following.bundle.3d192304050edfc2.js b/public/js/profile~following.bundle.8a269b2c4fd0722c.js similarity index 100% rename from public/js/profile~following.bundle.3d192304050edfc2.js rename to public/js/profile~following.bundle.8a269b2c4fd0722c.js diff --git a/public/js/search.js b/public/js/search.js index 48ec33bd4..20662454d 100644 Binary files a/public/js/search.js and b/public/js/search.js differ diff --git a/public/js/spa.js b/public/js/spa.js index 80d5da162..cc7348084 100644 Binary files a/public/js/spa.js and b/public/js/spa.js differ diff --git a/public/js/static~privacy.bundle.1e765099c99b7409.js b/public/js/static~privacy.bundle.c647cbc1674cfea8.js similarity index 100% rename from public/js/static~privacy.bundle.1e765099c99b7409.js rename to public/js/static~privacy.bundle.c647cbc1674cfea8.js diff --git a/public/js/static~tos.bundle.dcf1fb170b2dae10.js b/public/js/static~tos.bundle.fc0a2c6ff6297f24.js similarity index 100% rename from public/js/static~tos.bundle.dcf1fb170b2dae10.js rename to public/js/static~tos.bundle.fc0a2c6ff6297f24.js diff --git a/public/js/vendor.js b/public/js/vendor.js index 9fbfb5468..1b875e7c3 100644 Binary files a/public/js/vendor.js and b/public/js/vendor.js differ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index bb79ed99d..4101c4f46 100644 Binary files a/public/mix-manifest.json and b/public/mix-manifest.json differ diff --git a/resources/assets/components/partials/post/LikeModal.vue b/resources/assets/components/partials/post/LikeModal.vue new file mode 100644 index 000000000..a5164752c --- /dev/null +++ b/resources/assets/components/partials/post/LikeModal.vue @@ -0,0 +1,239 @@ + + + diff --git a/resources/assets/components/partials/post/ShareModal.vue b/resources/assets/components/partials/post/ShareModal.vue new file mode 100644 index 000000000..f9301d2b4 --- /dev/null +++ b/resources/assets/components/partials/post/ShareModal.vue @@ -0,0 +1,239 @@ + + + diff --git a/resources/assets/components/sections/Notifications.vue b/resources/assets/components/sections/Notifications.vue new file mode 100644 index 000000000..276bac037 --- /dev/null +++ b/resources/assets/components/sections/Notifications.vue @@ -0,0 +1,415 @@ + + + + +