diff --git a/src/state/models/lists/lists-list.ts b/src/state/models/lists/lists-list.ts index 862f96f566..309ab0e032 100644 --- a/src/state/models/lists/lists-list.ts +++ b/src/state/models/lists/lists-list.ts @@ -1,7 +1,7 @@ import {makeAutoObservable} from 'mobx' import { AppBskyGraphGetLists as GetLists, - AppBskyGraphGetListBlocks as GetListBlocks, + AppBskyGraphGetListMutes as GetListMutes, AppBskyGraphDefs as GraphDefs, } from '@atproto/api' import {RootStoreModel} from '../root-store' @@ -25,7 +25,7 @@ export class ListsListModel { constructor( public rootStore: RootStoreModel, - public source: 'mutelists' | string, + public source: 'my-modlists' | string, ) { makeAutoObservable( this, @@ -62,11 +62,32 @@ export class ListsListModel { this._xLoading(replace) try { let res - if (this.source === 'mutelists') { - res = await this.rootStore.agent.app.bsky.graph.getListBlocks({ - limit: PAGE_SIZE, - cursor: replace ? undefined : this.loadMoreCursor, - }) + 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) + } + } + 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) + } + } } else { res = await this.rootStore.agent.app.bsky.graph.getLists({ actor: this.source, @@ -81,7 +102,7 @@ export class ListsListModel { } this._xIdle() } catch (e: any) { - this._xIdle(replace ?? e, !replace ?? e) + this._xIdle(replace ? e : undefined, !replace ? e : undefined) } }) @@ -120,14 +141,74 @@ export class ListsListModel { // helper functions // = - _replaceAll(res: GetLists.Response | GetListBlocks.Response) { + _replaceAll(res: GetLists.Response | GetListMutes.Response) { this.lists = [] this._appendAll(res) } - _appendAll(res: GetLists.Response | GetListBlocks.Response) { + _appendAll(res: GetLists.Response | GetListMutes.Response) { this.loadMoreCursor = res.data.cursor this.hasMore = !!this.loadMoreCursor - this.lists = this.lists.concat(res.data.lists) + this.lists = this.lists.concat( + res.data.lists.map(list => ({...list, _reactKey: list.uri})), + ) } } + +async function fetchAllUserLists( + store: RootStoreModel, + did: string, +): Promise { + let acc: GetLists.Response = { + success: true, + headers: {}, + data: { + subject: undefined, + lists: [], + }, + } + + let cursor + for (let i = 0; i < 100; i++) { + const res = 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 { + let acc: GetListMutes.Response = { + success: true, + headers: {}, + data: { + subject: undefined, + lists: [], + }, + } + + let cursor + for (let i = 0; i < 100; i++) { + const res = 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 +} diff --git a/src/state/models/ui/profile.ts b/src/state/models/ui/profile.ts index a4bff69de0..861b3df0eb 100644 --- a/src/state/models/ui/profile.ts +++ b/src/state/models/ui/profile.ts @@ -151,6 +151,8 @@ export class ProfileUiModel { .setup() .catch(err => this.rootStore.log.error('Failed to fetch feed', err)), ]) + // HACK: need to use the DID as a param, not the username -prf + this.lists.source = this.profile.did this.lists .loadMore() .catch(err => this.rootStore.log.error('Failed to fetch lists', err)) diff --git a/src/view/com/lists/ListCard.tsx b/src/view/com/lists/ListCard.tsx index 46994c13ef..f203ee3a21 100644 --- a/src/view/com/lists/ListCard.tsx +++ b/src/view/com/lists/ListCard.tsx @@ -7,6 +7,7 @@ import {RichText as RichTextCom} from '../util/text/RichText' import {UserAvatar} from '../util/UserAvatar' import {s} from 'lib/styles' import {usePalette} from 'lib/hooks/usePalette' +import {useStores} from 'state/index' import {sanitizeDisplayName} from 'lib/strings/display-names' export const ListCard = ({ @@ -23,6 +24,7 @@ export const ListCard = ({ renderButton?: () => JSX.Element }) => { const pal = usePalette('default') + const store = useStores() const rkey = React.useMemo(() => { try { @@ -69,8 +71,10 @@ export const ListCard = ({ {sanitizeDisplayName(list.name)} - {list.purpose === 'app.bsky.graph.defs#modlist' && 'Mute list'} by @ - {list.creator.handle} + {list.purpose === 'app.bsky.graph.defs#modlist' && 'Mute list'} by{' '} + {list.creator.did === store.me.did + ? 'you' + : `@${list.creator.handle}`} {!!list.viewer?.muted && ( diff --git a/src/view/screens/ModerationMuteLists.tsx b/src/view/screens/ModerationMuteLists.tsx index cee57af958..ab7d566787 100644 --- a/src/view/screens/ModerationMuteLists.tsx +++ b/src/view/screens/ModerationMuteLists.tsx @@ -28,7 +28,7 @@ export const ModerationMuteListsScreen = withAuthRequired(({route}: Props) => { const navigation = useNavigation() const mutelists: ListsListModel = React.useMemo(() => { - const list = new ListsListModel(store, 'mutelists') + const list = new ListsListModel(store, 'my-modlists') list.loadMore() return list }, [store])