Replace Add User to Lists modal with modern Dialog component
Migrate from deprecated modal system to modern Dialog system using the efficient getListsWithMembership() API instead of the inefficient useDangerousListMembershipsQuery(). Adds optimistic updates for faster UI feedback on add/remove operations. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,6 @@ import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
import {logger} from '#/logger'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {useListMembersQuery} from '#/state/queries/list-members'
|
||||
import {useSession} from '#/state/session'
|
||||
@@ -23,6 +22,8 @@ import {ProfileCardFeedLoadingPlaceholder} from '#/view/com/util/LoadingPlacehol
|
||||
import {LoadMoreRetryBtn} from '#/view/com/util/LoadMoreRetryBtn'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {UserAddRemoveListsDialog} from '#/components/dialogs/lists/UserAddRemoveListsDialog'
|
||||
import {ListFooter} from '#/components/Lists'
|
||||
import * as ProfileCard from '#/components/ProfileCard'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
@@ -58,9 +59,12 @@ export function ListMembers({
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const [isRefreshing, setIsRefreshing] = useState(false)
|
||||
const {openModal} = useModalControls()
|
||||
const {currentAccount} = useSession()
|
||||
const moderationOpts = useModerationOpts()
|
||||
const editListsDialogControl = useDialogControl()
|
||||
const [selectedProfile, setSelectedProfile] = React.useState<
|
||||
bsky.profile.AnyProfileView | undefined
|
||||
>()
|
||||
|
||||
const {
|
||||
data,
|
||||
@@ -128,14 +132,10 @@ export function ListMembers({
|
||||
const onPressEditMembership = useCallback(
|
||||
(e: GestureResponderEvent, profile: bsky.profile.AnyProfileView) => {
|
||||
e.preventDefault()
|
||||
openModal({
|
||||
name: 'user-add-remove-lists',
|
||||
subject: profile.did,
|
||||
displayName: profile.displayName || profile.handle,
|
||||
handle: profile.handle,
|
||||
})
|
||||
setSelectedProfile(profile)
|
||||
editListsDialogControl.open()
|
||||
},
|
||||
[openModal],
|
||||
[editListsDialogControl],
|
||||
)
|
||||
|
||||
// rendering
|
||||
@@ -263,6 +263,15 @@ export function ListMembers({
|
||||
removeClippedSubviews={true}
|
||||
desktopFixedHeight={desktopFixedHeightOffset || true}
|
||||
/>
|
||||
|
||||
{selectedProfile && (
|
||||
<UserAddRemoveListsDialog
|
||||
control={editListsDialogControl}
|
||||
subjectDid={selectedProfile.did}
|
||||
displayName={selectedProfile.displayName || selectedProfile.handle}
|
||||
handle={selectedProfile.handle}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import {usePalette} from '#/lib/hooks/usePalette'
|
||||
import {useModalControls, useModals} from '#/state/modals'
|
||||
import {FullWindowOverlay} from '#/components/FullWindowOverlay'
|
||||
import {createCustomBackdrop} from '../util/BottomSheetCustomBackdrop'
|
||||
import * as UserAddRemoveListsModal from './UserAddRemoveLists'
|
||||
|
||||
const DEFAULT_SNAPPOINTS = ['90%']
|
||||
const HANDLE_HEIGHT = 24
|
||||
@@ -40,10 +39,7 @@ export function ModalsContainer() {
|
||||
|
||||
let snapPoints: (string | number)[] = DEFAULT_SNAPPOINTS
|
||||
let element
|
||||
if (activeModal?.name === 'user-add-remove-lists') {
|
||||
snapPoints = UserAddRemoveListsModal.snapPoints
|
||||
element = <UserAddRemoveListsModal.Component {...activeModal} />
|
||||
} else {
|
||||
{
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import {usePalette} from '#/lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
||||
import {type Modal as ModalIface} from '#/state/modals'
|
||||
import {useModalControls, useModals} from '#/state/modals'
|
||||
import * as UserAddRemoveLists from './UserAddRemoveLists'
|
||||
|
||||
export function ModalsContainer() {
|
||||
const {isModalActive, activeModals} = useModals()
|
||||
@@ -44,9 +43,7 @@ function Modal({modal}: {modal: ModalIface}) {
|
||||
}
|
||||
|
||||
let element
|
||||
if (modal.name === 'user-add-remove-lists') {
|
||||
element = <UserAddRemoveLists.Component {...modal} />
|
||||
} else {
|
||||
{
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import {type NavigationProp} from '#/lib/routes/types'
|
||||
import {shareText, shareUrl} from '#/lib/sharing'
|
||||
import {toShareUrl} from '#/lib/strings/url-helpers'
|
||||
import {type Shadow} from '#/state/cache/types'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {Nux, useNux, useSaveNux} from '#/state/queries/nuxs'
|
||||
import {
|
||||
RQKEY as profileQueryKey,
|
||||
@@ -25,6 +24,7 @@ import {EventStopper} from '#/view/com/util/EventStopper'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button, ButtonIcon} from '#/components/Button'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {UserAddRemoveListsDialog} from '#/components/dialogs/lists/UserAddRemoveListsDialog'
|
||||
import {StarterPackDialog} from '#/components/dialogs/StarterPackDialog'
|
||||
import {ArrowOutOfBoxModified_Stroke2_Corner2_Rounded as ArrowOutOfBoxIcon} from '#/components/icons/ArrowOutOfBox'
|
||||
import {ChainLink_Stroke2_Corner0_Rounded as ChainLinkIcon} from '#/components/icons/ChainLink'
|
||||
@@ -74,7 +74,6 @@ let ProfileMenu = ({
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {currentAccount, hasSession} = useSession()
|
||||
const {openModal} = useModalControls()
|
||||
const reportDialogControl = useReportDialogControl()
|
||||
const queryClient = useQueryClient()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
@@ -107,6 +106,7 @@ let ProfileMenu = ({
|
||||
const goLiveDialogControl = useDialogControl()
|
||||
const goLiveDisabledDialogControl = useDialogControl()
|
||||
const addToStarterPacksDialogControl = useDialogControl()
|
||||
const addToListsDialogControl = useDialogControl()
|
||||
|
||||
const showLoggedOutWarning = useMemo(() => {
|
||||
return (
|
||||
@@ -131,15 +131,8 @@ let ProfileMenu = ({
|
||||
}, [profile])
|
||||
|
||||
const onPressAddRemoveLists = useCallback(() => {
|
||||
openModal({
|
||||
name: 'user-add-remove-lists',
|
||||
subject: profile.did,
|
||||
handle: profile.handle,
|
||||
displayName: profile.displayName || profile.handle,
|
||||
onAdd: invalidateProfileQuery,
|
||||
onRemove: invalidateProfileQuery,
|
||||
})
|
||||
}, [profile, openModal, invalidateProfileQuery])
|
||||
addToListsDialogControl.open()
|
||||
}, [addToListsDialogControl])
|
||||
|
||||
const onPressMuteAccount = useCallback(async () => {
|
||||
if (profile.viewer?.muted) {
|
||||
@@ -530,6 +523,15 @@ let ProfileMenu = ({
|
||||
targetDid={profile.did}
|
||||
/>
|
||||
|
||||
<UserAddRemoveListsDialog
|
||||
control={addToListsDialogControl}
|
||||
subjectDid={profile.did}
|
||||
displayName={profile.displayName || profile.handle}
|
||||
handle={profile.handle}
|
||||
onAdd={invalidateProfileQuery}
|
||||
onRemove={invalidateProfileQuery}
|
||||
/>
|
||||
|
||||
<ReportDialog
|
||||
control={reportDialogControl}
|
||||
subject={{
|
||||
|
||||
Reference in New Issue
Block a user