From d9e0a927c1c98ebd6aa3885ab517af27e7de2522 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Sun, 12 Nov 2023 12:45:25 -0800 Subject: 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 --- src/view/com/modals/UserAddRemoveLists.tsx | 309 +++++++++++++---------------- 1 file changed, 138 insertions(+), 171 deletions(-) (limited to 'src/view/com/modals/UserAddRemoveLists.tsx') diff --git a/src/view/com/modals/UserAddRemoveLists.tsx b/src/view/com/modals/UserAddRemoveLists.tsx index efcfc43be..73b1bc744 100644 --- a/src/view/com/modals/UserAddRemoveLists.tsx +++ b/src/view/com/modals/UserAddRemoveLists.tsx @@ -1,33 +1,32 @@ import React, {useCallback} from 'react' -import {observer} from 'mobx-react-lite' -import {ActivityIndicator, Pressable, StyleSheet, View} from 'react-native' +import {ActivityIndicator, StyleSheet, View} from 'react-native' import {AppBskyGraphDefs as GraphDefs} from '@atproto/api' -import { - FontAwesomeIcon, - FontAwesomeIconStyle, -} from '@fortawesome/react-native-fontawesome' import {Text} from '../util/text/Text' import {UserAvatar} from '../util/UserAvatar' import {ListsList} from '../lists/ListsList' -import {ListsListModel} from 'state/models/lists/lists-list' -import {ListMembershipModel} from 'state/models/content/list-membership' import {Button} from '../util/forms/Button' import * as Toast from '../util/Toast' -import {useStores} from 'state/index' import {sanitizeDisplayName} from 'lib/strings/display-names' import {sanitizeHandle} from 'lib/strings/handles' import {s} from 'lib/styles' import {usePalette} from 'lib/hooks/usePalette' import {isWeb, isAndroid} from 'platform/detection' -import isEqual from 'lodash.isequal' -import {logger} from '#/logger' import {Trans, msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useModalControls} from '#/state/modals' +import { + useDangerousListMembershipsQuery, + getMembership, + ListMembersip, + useListMembershipAddMutation, + useListMembershipRemoveMutation, +} from '#/state/queries/list-memberships' +import {cleanError} from '#/lib/strings/errors' +import {useSession} from '#/state/session' export const snapPoints = ['fullscreen'] -export const Component = observer(function UserAddRemoveListsImpl({ +export function Component({ subject, displayName, onAdd, @@ -38,193 +37,161 @@ export const Component = observer(function UserAddRemoveListsImpl({ onAdd?: (listUri: string) => void onRemove?: (listUri: string) => void }) { - const store = useStores() const {closeModal} = useModalControls() const pal = usePalette('default') const {_} = useLingui() - const palPrimary = usePalette('primary') - const palInverted = usePalette('inverted') - const [originalSelections, setOriginalSelections] = React.useState( - [], - ) - const [selected, setSelected] = React.useState([]) - const [membershipsLoaded, setMembershipsLoaded] = React.useState(false) + const {data: memberships} = useDangerousListMembershipsQuery() - const listsList: ListsListModel = React.useMemo( - () => new ListsListModel(store, store.me.did), - [store], - ) - const memberships: ListMembershipModel = React.useMemo( - () => new ListMembershipModel(store, subject), - [store, subject], - ) - React.useEffect(() => { - listsList.refresh() - memberships.fetch().then( - () => { - const ids = memberships.memberships.map(m => m.value.list) - setOriginalSelections(ids) - setSelected(ids) - setMembershipsLoaded(true) - }, - err => { - logger.error('Failed to fetch memberships', {error: err}) - }, - ) - }, [memberships, listsList, store, setSelected, setMembershipsLoaded]) - - const onPressCancel = useCallback(() => { + const onPressDone = useCallback(() => { closeModal() }, [closeModal]) - const onPressSave = useCallback(async () => { - let changes - try { - changes = await memberships.updateTo(selected) - } catch (err) { - logger.error('Failed to update memberships', {error: err}) - return - } - Toast.show('Lists updated') - for (const uri of changes.added) { - onAdd?.(uri) - } - for (const uri of changes.removed) { - onRemove?.(uri) - } - closeModal() - }, [closeModal, selected, memberships, onAdd, onRemove]) - - const onToggleSelected = useCallback( - (uri: string) => { - if (selected.includes(uri)) { - setSelected(selected.filter(uri2 => uri2 !== uri)) - } else { - setSelected([...selected, uri]) - } - }, - [selected, setSelected], - ) - - const renderItem = useCallback( - (list: GraphDefs.ListView, index: number) => { - const isSelected = selected.includes(list.uri) - return ( - onToggleSelected(list.uri)}> - - - - - - {sanitizeDisplayName(list.name)} - - - {list.purpose === 'app.bsky.graph.defs#curatelist' && - 'User list '} - {list.purpose === 'app.bsky.graph.defs#modlist' && - 'Moderation list '} - by{' '} - {list.creator.did === store.me.did - ? 'you' - : sanitizeHandle(list.creator.handle, '@')} - - - {membershipsLoaded && ( - - {isSelected && ( - - )} - - )} - - ) - }, - [ - pal, - palPrimary, - palInverted, - onToggleSelected, - selected, - store.me.did, - membershipsLoaded, - ], - ) - - // Only show changes button if there are some items on the list to choose from AND user has made changes in selection - const canSaveChanges = - !listsList.isEmpty && !isEqual(selected, originalSelections) - return ( Update {displayName} in Lists ( + + )} style={[styles.list, pal.border]} />