diff options
author | Paul Frazee <pfrazee@gmail.com> | 2023-11-01 16:15:40 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-01 16:15:40 -0700 |
commit | f57a8cf8ba0cd10a54abf35d960d8fb90266fa6b (patch) | |
tree | a9da6032bcbd587d92fd1030e698aea2dbef9f72 /src/state/models/lists/lists-list.ts | |
parent | f9944b55e26fe6109bc2e7a25b88979111470ed9 (diff) | |
download | voidsky-f57a8cf8ba0cd10a54abf35d960d8fb90266fa6b.tar.zst |
Lists updates: curate lists and blocklists (#1689)
* Add lists screen * Update Lists screen and List create/edit modal to support curate lists * Rework the ProfileList screen and add curatelist support * More ProfileList progress * Update list modals * Rename mutelists to modlists * Layout updates/fixes * More layout fixes * Modal fixes * List list screen updates * Update feed page to give more info * Layout fixes to ListAddUser modal * Layout fixes to FlatList and Feed on desktop * Layout fix to LoadLatestBtn on Web * Handle did resolution before showing the ProfileList screen * Rename the CustomFeed routes to ProfileFeed for consistency * Fix layout issues with the pager and feeds * Factor out some common code * Fix UIs for mobile * Fix user list rendering * Fix: dont bubble custom feed errors in the merge feed * Refactor feed models to reduce usage of the SavedFeeds model * Replace CustomFeedModel with FeedSourceModel which abstracts feed-generators and lists * Add the ability to pin lists * Add pinned lists to mobile * Remove dead code * Rework the ProfileScreenHeader to create more real-estate for action buttons * Improve layout behavior on web mobile breakpoints * Refactor feed & list pages to use new Tabs layout component * Refactor to ProfileSubpageHeader * Implement modlist block and mute * Switch to new api and just modify state on modlist actions * Fix some UI overflows * Fix: dont show edit buttons on lists you dont own * Fix alignment issue on long titles * Improve loading and error states for feeds & lists * Update list dropdown icons for ios * Fetch feed display names in the mergefeed * Improve rendering off offline feeds in the feed-listing page * Update Feeds listing UI to react to changes in saved/pinned state * Refresh list and feed on posts tab press * Fix pinned feed ordering UI * Fixes to list pinning * Remove view=simple qp * Add list to feed tuners * Render richtext * Add list href * Add 'view avatar' * Remove unused import * Fix missing import * Correctly reflect block by list state * Replace the <Tabs> component with the more effective <PagerWithHeader> component * Improve the responsiveness of the PagerWithHeader * Fix visual jank in the feed loading state * Improve performance of the PagerWithHeader * Fix a case that would cause the header to animate too aggressively * Add the ability to scroll to top by tapping the selected tab * Fix unit test runner * Update modlists test * Add curatelist tests * Fix: remove link behavior in ListAddUser modal * Fix some layout jank in the PagerWithHeader on iOS * Simplify ListItems header rendering * Wait for the appview to recognize the list before proceeding with list creation * Fix glitch in the onPageSelecting index of the Pager * Fix until() * Copy fix Co-authored-by: Eric Bailey <git@esb.lol> --------- Co-authored-by: Eric Bailey <git@esb.lol>
Diffstat (limited to 'src/state/models/lists/lists-list.ts')
-rw-r--r-- | src/state/models/lists/lists-list.ts | 205 |
1 files changed, 108 insertions, 97 deletions
diff --git a/src/state/models/lists/lists-list.ts b/src/state/models/lists/lists-list.ts index 54e2f5fde..42638757a 100644 --- a/src/state/models/lists/lists-list.ts +++ b/src/state/models/lists/lists-list.ts @@ -1,12 +1,9 @@ import {makeAutoObservable} from 'mobx' -import { - AppBskyGraphGetLists as GetLists, - AppBskyGraphGetListMutes as GetListMutes, - AppBskyGraphDefs as GraphDefs, -} from '@atproto/api' +import {AppBskyGraphDefs as GraphDefs} from '@atproto/api' import {RootStoreModel} from '../root-store' import {cleanError} from 'lib/strings/errors' import {bundleAsync} from 'lib/async/bundle' +import {accumulate} from 'lib/async/accumulate' const PAGE_SIZE = 30 @@ -25,7 +22,7 @@ export class ListsListModel { constructor( public rootStore: RootStoreModel, - public source: 'my-modlists' | string, + public source: 'mine' | 'my-curatelists' | 'my-modlists' | string, ) { makeAutoObservable( this, @@ -48,6 +45,26 @@ export class ListsListModel { return this.hasLoaded && !this.hasContent } + get curatelists() { + return this.lists.filter( + list => list.purpose === 'app.bsky.graph.defs#curatelist', + ) + } + + get isCuratelistsEmpty() { + return this.hasLoaded && this.curatelists.length === 0 + } + + get modlists() { + return this.lists.filter( + list => list.purpose === 'app.bsky.graph.defs#modlist', + ) + } + + get isModlistsEmpty() { + return this.hasLoaded && this.modlists.length === 0 + } + /** * Removes posts from the feed upon deletion. */ @@ -76,44 +93,85 @@ export class ListsListModel { } this._xLoading(replace) try { - let res: GetLists.Response - if (this.source === 'my-modlists') { - res = { - success: true, - headers: {}, - data: { - subject: undefined, - lists: [], - }, - } - const [res1, res2] = await Promise.all([ - fetchAllUserLists(this.rootStore, this.rootStore.me.did), - fetchAllMyMuteLists(this.rootStore), - ]) - for (let list of res1.data.lists) { - if (list.purpose === 'app.bsky.graph.defs#modlist') { - res.data.lists.push(list) - } + let cursor: string | undefined + let lists: GraphDefs.ListView[] = [] + if ( + this.source === 'mine' || + this.source === 'my-curatelists' || + this.source === 'my-modlists' + ) { + const promises = [ + accumulate(cursor => + this.rootStore.agent.app.bsky.graph + .getLists({ + actor: this.rootStore.me.did, + cursor, + limit: 50, + }) + .then(res => ({cursor: res.data.cursor, items: res.data.lists})), + ), + ] + if (this.source === 'my-modlists') { + promises.push( + accumulate(cursor => + this.rootStore.agent.app.bsky.graph + .getListMutes({ + cursor, + limit: 50, + }) + .then(res => ({ + cursor: res.data.cursor, + items: res.data.lists, + })), + ), + ) + promises.push( + accumulate(cursor => + this.rootStore.agent.app.bsky.graph + .getListBlocks({ + cursor, + limit: 50, + }) + .then(res => ({ + cursor: res.data.cursor, + items: res.data.lists, + })), + ), + ) } - for (let list of res2.data.lists) { - if ( - list.purpose === 'app.bsky.graph.defs#modlist' && - !res.data.lists.find(l => l.uri === list.uri) - ) { - res.data.lists.push(list) + const resultset = await Promise.all(promises) + for (const res of resultset) { + for (let list of res) { + if ( + this.source === 'my-curatelists' && + list.purpose !== 'app.bsky.graph.defs#curatelist' + ) { + continue + } + if ( + this.source === 'my-modlists' && + list.purpose !== 'app.bsky.graph.defs#modlist' + ) { + continue + } + if (!lists.find(l => l.uri === list.uri)) { + lists.push(list) + } } } } else { - res = await this.rootStore.agent.app.bsky.graph.getLists({ + const res = await this.rootStore.agent.app.bsky.graph.getLists({ actor: this.source, limit: PAGE_SIZE, cursor: replace ? undefined : this.loadMoreCursor, }) + lists = res.data.lists + cursor = res.data.cursor } if (replace) { - this._replaceAll(res) + this._replaceAll({lists, cursor}) } else { - this._appendAll(res) + this._appendAll({lists, cursor}) } this._xIdle() } catch (e: any) { @@ -156,75 +214,28 @@ export class ListsListModel { // helper functions // = - _replaceAll(res: GetLists.Response | GetListMutes.Response) { + _replaceAll({ + lists, + cursor, + }: { + lists: GraphDefs.ListView[] + cursor: string | undefined + }) { this.lists = [] - this._appendAll(res) + this._appendAll({lists, cursor}) } - _appendAll(res: GetLists.Response | GetListMutes.Response) { - this.loadMoreCursor = res.data.cursor + _appendAll({ + lists, + cursor, + }: { + lists: GraphDefs.ListView[] + cursor: string | undefined + }) { + this.loadMoreCursor = cursor this.hasMore = !!this.loadMoreCursor this.lists = this.lists.concat( - res.data.lists.map(list => ({...list, _reactKey: list.uri})), + lists.map(list => ({...list, _reactKey: list.uri})), ) } } - -async function fetchAllUserLists( - store: RootStoreModel, - did: string, -): Promise<GetLists.Response> { - let acc: GetLists.Response = { - success: true, - headers: {}, - data: { - subject: undefined, - lists: [], - }, - } - - let cursor - for (let i = 0; i < 100; i++) { - const res: GetLists.Response = await store.agent.app.bsky.graph.getLists({ - actor: did, - cursor, - limit: 50, - }) - cursor = res.data.cursor - acc.data.lists = acc.data.lists.concat(res.data.lists) - if (!cursor) { - break - } - } - - return acc -} - -async function fetchAllMyMuteLists( - store: RootStoreModel, -): Promise<GetListMutes.Response> { - let acc: GetListMutes.Response = { - success: true, - headers: {}, - data: { - subject: undefined, - lists: [], - }, - } - - let cursor - for (let i = 0; i < 100; i++) { - const res: GetListMutes.Response = - await store.agent.app.bsky.graph.getListMutes({ - cursor, - limit: 50, - }) - cursor = res.data.cursor - acc.data.lists = acc.data.lists.concat(res.data.lists) - if (!cursor) { - break - } - } - - return acc -} |