Add lists listings
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import {makeAutoObservable} from 'mobx'
|
import {makeAutoObservable} from 'mobx'
|
||||||
import {
|
import {
|
||||||
AppBskyGraphGetLists as GetLists,
|
AppBskyGraphGetLists as GetLists,
|
||||||
AppBskyGraphGetListBlocks as GetListBlocks,
|
AppBskyGraphGetListMutes as GetListMutes,
|
||||||
AppBskyGraphDefs as GraphDefs,
|
AppBskyGraphDefs as GraphDefs,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {RootStoreModel} from '../root-store'
|
import {RootStoreModel} from '../root-store'
|
||||||
@@ -25,7 +25,7 @@ export class ListsListModel {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public rootStore: RootStoreModel,
|
public rootStore: RootStoreModel,
|
||||||
public source: 'mutelists' | string,
|
public source: 'my-modlists' | string,
|
||||||
) {
|
) {
|
||||||
makeAutoObservable(
|
makeAutoObservable(
|
||||||
this,
|
this,
|
||||||
@@ -62,11 +62,32 @@ export class ListsListModel {
|
|||||||
this._xLoading(replace)
|
this._xLoading(replace)
|
||||||
try {
|
try {
|
||||||
let res
|
let res
|
||||||
if (this.source === 'mutelists') {
|
if (this.source === 'my-modlists') {
|
||||||
res = await this.rootStore.agent.app.bsky.graph.getListBlocks({
|
res = {
|
||||||
limit: PAGE_SIZE,
|
success: true,
|
||||||
cursor: replace ? undefined : this.loadMoreCursor,
|
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 {
|
} else {
|
||||||
res = await this.rootStore.agent.app.bsky.graph.getLists({
|
res = await this.rootStore.agent.app.bsky.graph.getLists({
|
||||||
actor: this.source,
|
actor: this.source,
|
||||||
@@ -81,7 +102,7 @@ export class ListsListModel {
|
|||||||
}
|
}
|
||||||
this._xIdle()
|
this._xIdle()
|
||||||
} catch (e: any) {
|
} 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
|
// helper functions
|
||||||
// =
|
// =
|
||||||
|
|
||||||
_replaceAll(res: GetLists.Response | GetListBlocks.Response) {
|
_replaceAll(res: GetLists.Response | GetListMutes.Response) {
|
||||||
this.lists = []
|
this.lists = []
|
||||||
this._appendAll(res)
|
this._appendAll(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
_appendAll(res: GetLists.Response | GetListBlocks.Response) {
|
_appendAll(res: GetLists.Response | GetListMutes.Response) {
|
||||||
this.loadMoreCursor = res.data.cursor
|
this.loadMoreCursor = res.data.cursor
|
||||||
this.hasMore = !!this.loadMoreCursor
|
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<GetLists.Response> {
|
||||||
|
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<GetListMutes.Response> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -151,6 +151,8 @@ export class ProfileUiModel {
|
|||||||
.setup()
|
.setup()
|
||||||
.catch(err => this.rootStore.log.error('Failed to fetch feed', err)),
|
.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
|
this.lists
|
||||||
.loadMore()
|
.loadMore()
|
||||||
.catch(err => this.rootStore.log.error('Failed to fetch lists', err))
|
.catch(err => this.rootStore.log.error('Failed to fetch lists', err))
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {RichText as RichTextCom} from '../util/text/RichText'
|
|||||||
import {UserAvatar} from '../util/UserAvatar'
|
import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {useStores} from 'state/index'
|
||||||
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
||||||
|
|
||||||
export const ListCard = ({
|
export const ListCard = ({
|
||||||
@@ -23,6 +24,7 @@ export const ListCard = ({
|
|||||||
renderButton?: () => JSX.Element
|
renderButton?: () => JSX.Element
|
||||||
}) => {
|
}) => {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const store = useStores()
|
||||||
|
|
||||||
const rkey = React.useMemo(() => {
|
const rkey = React.useMemo(() => {
|
||||||
try {
|
try {
|
||||||
@@ -69,8 +71,10 @@ export const ListCard = ({
|
|||||||
{sanitizeDisplayName(list.name)}
|
{sanitizeDisplayName(list.name)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text type="md" style={[pal.textLight]} numberOfLines={1}>
|
<Text type="md" style={[pal.textLight]} numberOfLines={1}>
|
||||||
{list.purpose === 'app.bsky.graph.defs#modlist' && 'Mute list'} by @
|
{list.purpose === 'app.bsky.graph.defs#modlist' && 'Mute list'} by{' '}
|
||||||
{list.creator.handle}
|
{list.creator.did === store.me.did
|
||||||
|
? 'you'
|
||||||
|
: `@${list.creator.handle}`}
|
||||||
</Text>
|
</Text>
|
||||||
{!!list.viewer?.muted && (
|
{!!list.viewer?.muted && (
|
||||||
<View style={s.flexRow}>
|
<View style={s.flexRow}>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export const ModerationMuteListsScreen = withAuthRequired(({route}: Props) => {
|
|||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
|
||||||
const mutelists: ListsListModel = React.useMemo(() => {
|
const mutelists: ListsListModel = React.useMemo(() => {
|
||||||
const list = new ListsListModel(store, 'mutelists')
|
const list = new ListsListModel(store, 'my-modlists')
|
||||||
list.loadMore()
|
list.loadMore()
|
||||||
return list
|
return list
|
||||||
}, [store])
|
}, [store])
|
||||||
|
|||||||
Reference in New Issue
Block a user