diff --git a/extensions/flags/js/src/forum/components/FlagList.tsx b/extensions/flags/js/src/forum/components/FlagList.tsx index 74c9c611b7..eb11b10aa3 100644 --- a/extensions/flags/js/src/forum/components/FlagList.tsx +++ b/extensions/flags/js/src/forum/components/FlagList.tsx @@ -8,6 +8,8 @@ import HeaderListItem from 'flarum/forum/components/HeaderListItem'; import type Mithril from 'mithril'; import type Post from 'flarum/common/models/Post'; import type FlagListState from '../states/FlagListState'; +import type Flag from '../models/Flag'; +import { Page } from 'flarum/common/states/PaginatedListState'; export interface IFlagListAttrs extends ComponentAttrs { state: FlagListState; @@ -16,49 +18,55 @@ export interface IFlagListAttrs extends ComponentAttrs { export default class FlagList extends Component { oninit(vnode: Mithril.Vnode) { super.oninit(vnode); - this.state = this.attrs.state; } view() { - const flags = this.state.cache || []; + const state = this.attrs.state; return ( state.hasNext() && !state.isLoadingNext() && state.loadNext()} > -
    - {!this.state.loading && - flags.map((flag) => { - const post = flag.post() as Post; - - return ( -
  • - } - icon="fas fa-flag" - content={app.translator.trans('flarum-flags.forum.flagged_posts.item_text', { - username: username(post.user()), - em: , - discussion: post.discussion().title(), - })} - excerpt={post.contentPlain()} - datetime={flag.createdAt()} - href={app.route.post(post)} - onclick={(e: MouseEvent) => { - app.flags.index = post; - e.redraw = false; - }} - /> -
  • - ); - })} -
+
    {this.content(state)}
); } + + content(state: FlagListState) { + if (!state.isLoading() && state.hasItems()) { + return state.getPages().map((page: Page) => { + return page.items.map((flag: Flag) => { + const post = flag.post() as Post; + + return ( +
  • + } + icon="fas fa-flag" + content={app.translator.trans('flarum-flags.forum.flagged_posts.item_text', { + username: username(post.user()), + em: , + discussion: post.discussion().title(), + })} + excerpt={post.contentPlain()} + datetime={flag.createdAt()} + href={app.route.post(post)} + onclick={(e: MouseEvent) => { + e.redraw = false; + }} + /> +
  • + ); + }); + }); + } + + return null; + } } diff --git a/extensions/flags/js/src/forum/components/FlagsDropdown.tsx b/extensions/flags/js/src/forum/components/FlagsDropdown.tsx index 3c13211630..e82be705b2 100644 --- a/extensions/flags/js/src/forum/components/FlagsDropdown.tsx +++ b/extensions/flags/js/src/forum/components/FlagsDropdown.tsx @@ -25,7 +25,7 @@ export default class FlagsDropdown('flagCount'); + return app.forum.attribute('flagCount'); } getNewCount() { diff --git a/extensions/flags/js/src/forum/states/FlagListState.tsx b/extensions/flags/js/src/forum/states/FlagListState.tsx index 7afa5543fa..95708ba4c2 100644 --- a/extensions/flags/js/src/forum/states/FlagListState.tsx +++ b/extensions/flags/js/src/forum/states/FlagListState.tsx @@ -1,39 +1,33 @@ import type ForumApplication from 'flarum/forum/ForumApplication'; import type Flag from '../models/Flag'; -import type Post from 'flarum/common/models/Post'; +import PaginatedListState from 'flarum/common/states/PaginatedListState'; -export default class FlagListState { +export default class FlagListState extends PaginatedListState { public app: ForumApplication; - public loading = false; - public cache: Flag[] | null = null; - public index: Post | false | null = null; constructor(app: ForumApplication) { + super({}, 1, null); this.app = app; } + get type(): string { + return 'flags'; + } + /** * Load flags into the application's cache if they haven't already * been loaded. */ - load() { - if (this.cache && !this.app.session.user!.attribute('newFlagCount')) { - return; + load(): Promise { + if (this.app.session.user?.attribute('newFlagCount')) { + this.pages = []; + this.location = { page: 1 }; } - this.loading = true; - m.redraw(); + if (this.pages.length > 0) { + return Promise.resolve(); + } - this.app.store - .find('flags') - .then((flags) => { - this.app.session.user!.pushAttributes({ newFlagCount: 0 }); - this.cache = flags.sort((a, b) => b.createdAt()!.getTime() - a.createdAt()!.getTime()); - }) - .catch(() => {}) - .then(() => { - this.loading = false; - m.redraw(); - }); + return super.loadNext(); } } diff --git a/extensions/flags/src/Api/Controller/ListFlagsController.php b/extensions/flags/src/Api/Controller/ListFlagsController.php index 216f61b05a..534d3abe56 100644 --- a/extensions/flags/src/Api/Controller/ListFlagsController.php +++ b/extensions/flags/src/Api/Controller/ListFlagsController.php @@ -14,6 +14,7 @@ use Flarum\Flags\Api\Serializer\FlagSerializer; use Flarum\Flags\Flag; use Flarum\Http\RequestUtil; +use Flarum\Http\UrlGenerator; use Psr\Http\Message\ServerRequestInterface; use Tobscure\JsonApi\Document; @@ -28,26 +29,52 @@ class ListFlagsController extends AbstractListController 'post.discussion' ]; + public function __construct( + protected UrlGenerator $url + ) { + } + protected function data(ServerRequestInterface $request, Document $document): iterable { $actor = RequestUtil::getActor($request); - $include = $this->extractInclude($request); $actor->assertRegistered(); $actor->read_flags_at = Carbon::now(); $actor->save(); + $limit = $this->extractLimit($request); + $offset = $this->extractOffset($request); + $include = $this->extractInclude($request); + + if (in_array('post.user', $include)) { + $include[] = 'post.user.groups'; + } + $flags = Flag::whereVisibleTo($actor) ->latest('flags.created_at') ->groupBy('post_id') + ->limit($limit + 1) + ->offset($offset) ->get(); - if (in_array('post.user', $include)) { - $include[] = 'post.user.groups'; + $this->loadRelations($flags, $include, $request); + + $flags = $flags->all(); + + $areMoreResults = false; + + if (count($flags) > $limit) { + array_pop($flags); + $areMoreResults = true; } - $this->loadRelations($flags, $include); + $this->addPaginationData( + $document, + $request, + $this->url->to('api')->route('flags.index'), + $areMoreResults ? null : 0 + ); return $flags; }