diff options
author | Paul Frazee <pfrazee@gmail.com> | 2023-11-12 12:45:25 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-12 12:45:25 -0800 |
commit | d9e0a927c1c98ebd6aa3885ab517af27e7de2522 (patch) | |
tree | cee196297391e497f1aa3b650d66633f3a86ca34 /src/view/com/lists | |
parent | 05b728fffcdb17708fdb52685725faf7fdc545bc (diff) | |
download | voidsky-d9e0a927c1c98ebd6aa3885ab517af27e7de2522.tar.zst |
Refactor lists to use new queries (#1875)
* Refactor lists queries to react-query * Delete old lists-list model * Implement list, list-members, and list-memberships react-queries * Update CreateOrEditList modal * First pass at my-follows and actor-autocomplete queries * Update ListAddUserModal to use new queries, change to ListAddRemoveUsersModal * Update UserAddRemoveLists modal * Remove old TODO * Fix indent, autocomplete query * Add a todo --------- Co-authored-by: Eric Bailey <git@esb.lol>
Diffstat (limited to 'src/view/com/lists')
-rw-r--r-- | src/view/com/lists/ListCard.tsx | 6 | ||||
-rw-r--r-- | src/view/com/lists/ListMembers.tsx (renamed from src/view/com/lists/ListItems.tsx) | 94 | ||||
-rw-r--r-- | src/view/com/lists/ListsList.tsx | 70 |
3 files changed, 74 insertions, 96 deletions
diff --git a/src/view/com/lists/ListCard.tsx b/src/view/com/lists/ListCard.tsx index a481902d8..774e9e916 100644 --- a/src/view/com/lists/ListCard.tsx +++ b/src/view/com/lists/ListCard.tsx @@ -7,7 +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 {useSession} from '#/state/session' import {sanitizeDisplayName} from 'lib/strings/display-names' import {sanitizeHandle} from 'lib/strings/handles' import {makeProfileLink} from 'lib/routes/links' @@ -28,7 +28,7 @@ export const ListCard = ({ style?: StyleProp<ViewStyle> }) => { const pal = usePalette('default') - const store = useStores() + const {currentAccount} = useSession() const rkey = React.useMemo(() => { try { @@ -80,7 +80,7 @@ export const ListCard = ({ {list.purpose === 'app.bsky.graph.defs#modlist' && 'Moderation list '} by{' '} - {list.creator.did === store.me.did + {list.creator.did === currentAccount?.did ? 'you' : sanitizeHandle(list.creator.handle, '@')} </Text> diff --git a/src/view/com/lists/ListItems.tsx b/src/view/com/lists/ListMembers.tsx index cf6fd3b42..4a25c53e6 100644 --- a/src/view/com/lists/ListItems.tsx +++ b/src/view/com/lists/ListMembers.tsx @@ -9,27 +9,28 @@ import { } from 'react-native' import {AppBskyActorDefs, AppBskyGraphDefs} from '@atproto/api' import {FlatList} from '../util/Views' -import {observer} from 'mobx-react-lite' import {ProfileCardFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' import {ErrorMessage} from '../util/error/ErrorMessage' import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn' import {ProfileCard} from '../profile/ProfileCard' import {Button} from '../util/forms/Button' -import {ListModel} from 'state/models/content/list' import {useAnalytics} from 'lib/analytics/analytics' import {usePalette} from 'lib/hooks/usePalette' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' +import {useListMembersQuery} from '#/state/queries/list-members' import {OnScrollHandler} from 'lib/hooks/useOnMainScroll' import {logger} from '#/logger' import {useModalControls} from '#/state/modals' import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED' +import {useSession} from '#/state/session' +import {cleanError} from '#/lib/strings/errors' const LOADING_ITEM = {_reactKey: '__loading__'} const EMPTY_ITEM = {_reactKey: '__empty__'} const ERROR_ITEM = {_reactKey: '__error__'} const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'} -export const ListItems = observer(function ListItemsImpl({ +export function ListMembers({ list, style, scrollElRef, @@ -42,7 +43,7 @@ export const ListItems = observer(function ListItemsImpl({ headerOffset = 0, desktopFixedHeightOffset, }: { - list: ListModel + list: string style?: StyleProp<ViewStyle> scrollElRef?: MutableRefObject<FlatList<any> | null> onScroll: OnScrollHandler @@ -59,33 +60,43 @@ export const ListItems = observer(function ListItemsImpl({ const [isRefreshing, setIsRefreshing] = React.useState(false) const {isMobile} = useWebMediaQueries() const {openModal} = useModalControls() + const {currentAccount} = useSession() - const data = React.useMemo(() => { + const { + data, + isFetching, + isFetched, + isError, + error, + refetch, + fetchNextPage, + hasNextPage, + } = useListMembersQuery(list) + const isEmpty = !isFetching && !data?.pages[0].items.length + const isOwner = + currentAccount && data?.pages[0].list.creator.did === currentAccount.did + + const items = React.useMemo(() => { let items: any[] = [] - if (list.hasLoaded) { - if (list.hasError) { + if (isFetched) { + if (isEmpty && isError) { items = items.concat([ERROR_ITEM]) } - if (list.isEmpty) { + if (isEmpty) { items = items.concat([EMPTY_ITEM]) - } else { - items = items.concat(list.items) + } else if (data) { + for (const page of data.pages) { + items = items.concat(page.items) + } } - if (list.loadMoreError) { + if (!isEmpty && isError) { items = items.concat([LOAD_MORE_ERROR_ITEM]) } - } else if (list.isLoading) { + } else if (isFetching) { items = items.concat([LOADING_ITEM]) } return items - }, [ - list.hasError, - list.hasLoaded, - list.isLoading, - list.isEmpty, - list.items, - list.loadMoreError, - ]) + }, [isFetched, isEmpty, isError, data, isFetching]) // events // = @@ -94,25 +105,26 @@ export const ListItems = observer(function ListItemsImpl({ track('Lists:onRefresh') setIsRefreshing(true) try { - await list.refresh() + await refetch() } catch (err) { logger.error('Failed to refresh lists', {error: err}) } setIsRefreshing(false) - }, [list, track, setIsRefreshing]) + }, [refetch, track, setIsRefreshing]) const onEndReached = React.useCallback(async () => { + if (isFetching || !hasNextPage || isError) return track('Lists:onEndReached') try { - await list.loadMore() + await fetchNextPage() } catch (err) { logger.error('Failed to load more lists', {error: err}) } - }, [list, track]) + }, [isFetching, hasNextPage, isError, fetchNextPage, track]) const onPressRetryLoadMore = React.useCallback(() => { - list.retryLoadMore() - }, [list]) + fetchNextPage() + }, [fetchNextPage]) const onPressEditMembership = React.useCallback( (profile: AppBskyActorDefs.ProfileViewBasic) => { @@ -120,19 +132,9 @@ export const ListItems = observer(function ListItemsImpl({ name: 'user-add-remove-lists', subject: profile.did, displayName: profile.displayName || profile.handle, - onAdd(listUri: string) { - if (listUri === list.uri) { - list.cacheAddMember(profile) - } - }, - onRemove(listUri: string) { - if (listUri === list.uri) { - list.cacheRemoveMember(profile) - } - }, }) }, - [openModal, list], + [openModal], ) // rendering @@ -140,7 +142,7 @@ export const ListItems = observer(function ListItemsImpl({ const renderMemberButton = React.useCallback( (profile: AppBskyActorDefs.ProfileViewBasic) => { - if (!list.isOwner) { + if (!isOwner) { return null } return ( @@ -152,7 +154,7 @@ export const ListItems = observer(function ListItemsImpl({ /> ) }, - [list, onPressEditMembership], + [isOwner, onPressEditMembership], ) const renderItem = React.useCallback( @@ -162,7 +164,7 @@ export const ListItems = observer(function ListItemsImpl({ } else if (item === ERROR_ITEM) { return ( <ErrorMessage - message={list.error} + message={cleanError(error)} onPressTryAgain={onPressTryAgain} /> ) @@ -190,7 +192,7 @@ export const ListItems = observer(function ListItemsImpl({ [ renderMemberButton, renderEmptyState, - list.error, + error, onPressTryAgain, onPressRetryLoadMore, isMobile, @@ -200,10 +202,10 @@ export const ListItems = observer(function ListItemsImpl({ const Footer = React.useCallback( () => ( <View style={{paddingTop: 20, paddingBottom: 200}}> - {list.isLoading && <ActivityIndicator />} + {isFetching && <ActivityIndicator />} </View> ), - [list.isLoading], + [isFetching], ) const scrollHandler = useAnimatedScrollHandler(onScroll) @@ -212,8 +214,8 @@ export const ListItems = observer(function ListItemsImpl({ <FlatList testID={testID ? `${testID}-flatlist` : undefined} ref={scrollElRef} - data={data} - keyExtractor={(item: any) => item._reactKey} + data={items} + keyExtractor={(item: any) => item.uri || item._reactKey} renderItem={renderItem} ListHeaderComponent={renderHeader} ListFooterComponent={Footer} @@ -241,4 +243,4 @@ export const ListItems = observer(function ListItemsImpl({ /> </View> ) -}) +} diff --git a/src/view/com/lists/ListsList.tsx b/src/view/com/lists/ListsList.tsx index 2883a31d5..100e0d609 100644 --- a/src/view/com/lists/ListsList.tsx +++ b/src/view/com/lists/ListsList.tsx @@ -8,68 +8,59 @@ import { View, ViewStyle, } from 'react-native' -import {observer} from 'mobx-react-lite' import {AppBskyGraphDefs as GraphDefs} from '@atproto/api' import {ListCard} from './ListCard' +import {MyListsFilter, useMyListsQuery} from '#/state/queries/my-lists' import {ErrorMessage} from '../util/error/ErrorMessage' import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn' import {Text} from '../util/text/Text' -import {ListsListModel} from 'state/models/lists/lists-list' import {useAnalytics} from 'lib/analytics/analytics' import {usePalette} from 'lib/hooks/usePalette' import {FlatList} from '../util/Views' import {s} from 'lib/styles' import {logger} from '#/logger' import {Trans} from '@lingui/macro' +import {cleanError} from '#/lib/strings/errors' const LOADING = {_reactKey: '__loading__'} const EMPTY = {_reactKey: '__empty__'} const ERROR_ITEM = {_reactKey: '__error__'} const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'} -export const ListsList = observer(function ListsListImpl({ - listsList, +export function ListsList({ + filter, inline, style, - onPressTryAgain, renderItem, testID, }: { - listsList: ListsListModel + filter: MyListsFilter inline?: boolean style?: StyleProp<ViewStyle> - onPressTryAgain?: () => void renderItem?: (list: GraphDefs.ListView, index: number) => JSX.Element testID?: string }) { const pal = usePalette('default') const {track} = useAnalytics() const [isRefreshing, setIsRefreshing] = React.useState(false) + const {data, isFetching, isFetched, isError, error, refetch} = + useMyListsQuery(filter) + const isEmpty = !isFetching && !data?.length - const data = React.useMemo(() => { + const items = React.useMemo(() => { let items: any[] = [] - if (listsList.hasError) { + if (isError && isEmpty) { items = items.concat([ERROR_ITEM]) } - if (!listsList.hasLoaded && listsList.isLoading) { + if (!isFetched && isFetching) { items = items.concat([LOADING]) - } else if (listsList.isEmpty) { + } else if (isEmpty) { items = items.concat([EMPTY]) } else { - items = items.concat(listsList.lists) - } - if (listsList.loadMoreError) { - items = items.concat([LOAD_MORE_ERROR_ITEM]) + items = items.concat(data) } return items - }, [ - listsList.hasError, - listsList.hasLoaded, - listsList.isLoading, - listsList.lists, - listsList.isEmpty, - listsList.loadMoreError, - ]) + }, [isError, isEmpty, isFetched, isFetching, data]) // events // = @@ -78,25 +69,12 @@ export const ListsList = observer(function ListsListImpl({ track('Lists:onRefresh') setIsRefreshing(true) try { - await listsList.refresh() + await refetch() } catch (err) { logger.error('Failed to refresh lists', {error: err}) } setIsRefreshing(false) - }, [listsList, track, setIsRefreshing]) - - const onEndReached = React.useCallback(async () => { - track('Lists:onEndReached') - try { - await listsList.loadMore() - } catch (err) { - logger.error('Failed to load more lists', {error: err}) - } - }, [listsList, track]) - - const onPressRetryLoadMore = React.useCallback(() => { - listsList.retryLoadMore() - }, [listsList]) + }, [refetch, track, setIsRefreshing]) // rendering // = @@ -116,15 +94,15 @@ export const ListsList = observer(function ListsListImpl({ } else if (item === ERROR_ITEM) { return ( <ErrorMessage - message={listsList.error} - onPressTryAgain={onPressTryAgain} + message={cleanError(error)} + onPressTryAgain={onRefresh} /> ) } else if (item === LOAD_MORE_ERROR_ITEM) { return ( <LoadMoreRetryBtn label="There was an issue fetching your lists. Tap here to try again." - onPress={onPressRetryLoadMore} + onPress={onRefresh} /> ) } else if (item === LOADING) { @@ -144,16 +122,16 @@ export const ListsList = observer(function ListsListImpl({ /> ) }, - [listsList, onPressTryAgain, onPressRetryLoadMore, renderItem, pal], + [error, onRefresh, renderItem, pal], ) const FlatListCom = inline ? RNFlatList : FlatList return ( <View testID={testID} style={style}> - {data.length > 0 && ( + {items.length > 0 && ( <FlatListCom testID={testID ? `${testID}-flatlist` : undefined} - data={data} + data={items} keyExtractor={(item: any) => item._reactKey} renderItem={renderItemInner} refreshControl={ @@ -165,8 +143,6 @@ export const ListsList = observer(function ListsListImpl({ /> } contentContainerStyle={[s.contentContainer]} - onEndReached={onEndReached} - onEndReachedThreshold={0.6} removeClippedSubviews={true} // @ts-ignore our .web version only -prf desktopFixedHeight @@ -174,7 +150,7 @@ export const ListsList = observer(function ListsListImpl({ )} </View> ) -}) +} const styles = StyleSheet.create({ item: { |