fix review feedback, clean up

This commit is contained in:
Samuel Newman
2026-06-04 11:06:22 +03:00
parent 9d40d02f95
commit 16265ed79f
6 changed files with 67 additions and 67 deletions
+4 -4
View File
@@ -145,21 +145,21 @@ appId: xyz.blueskyweb.app
id: "profileHeaderDropdownBtn" id: "profileHeaderDropdownBtn"
- tapOn: "Add to Lists" - tapOn: "Add to Lists"
- assertVisible: - assertVisible:
id: "userAddRemoveListsModal" id: "userAddRemoveListsDialog"
- tapOn: - tapOn:
id: "user-bob.test-addBtn" id: "user-bob.test-addBtn"
- tapOn: - tapOn:
id: "doneBtn" id: "doneBtn"
- assertNotVisible: - assertNotVisible:
id: "userAddRemoveListsModal" id: "userAddRemoveListsDialog"
- tapOn: - tapOn:
id: "profileHeaderDropdownBtn" id: "profileHeaderDropdownBtn"
- tapOn: "Add to Lists" - tapOn: "Add to Lists"
- assertVisible: - assertVisible:
id: "userAddRemoveListsModal" id: "userAddRemoveListsDialog"
- tapOn: - tapOn:
id: "user-bob.test-addBtn" id: "user-bob.test-addBtn"
- tapOn: - tapOn:
id: "doneBtn" id: "doneBtn"
- assertNotVisible: - assertNotVisible:
id: "userAddRemoveListsModal" id: "userAddRemoveListsDialog"
@@ -3,6 +3,7 @@ import {View} from 'react-native'
import {Trans, useLingui} from '@lingui/react/macro' import {Trans, useLingui} from '@lingui/react/macro'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name'
import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {isNetworkError} from '#/lib/strings/errors' import {isNetworkError} from '#/lib/strings/errors'
import {sanitizeHandle} from '#/lib/strings/handles' import {sanitizeHandle} from '#/lib/strings/handles'
@@ -27,34 +28,25 @@ import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Ti
import {Loader} from '#/components/Loader' import {Loader} from '#/components/Loader'
import * as Toast from '#/components/Toast' import * as Toast from '#/components/Toast'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import type * as bsky from '#/types/bsky'
export type UserAddRemoveListsDialogProps = { export type UserAddRemoveListsDialogProps = {
control: Dialog.DialogControlProps control: Dialog.DialogControlProps
subjectDid: string profile: bsky.profile.AnyProfileView | undefined
displayName: string
handle: string
onAdd?: (listUri: string) => void onAdd?: (listUri: string) => void
onRemove?: (listUri: string) => void onRemove?: (listUri: string) => void
} }
export function UserAddRemoveListsDialog({ export function UserAddRemoveListsDialog({
control, control,
subjectDid, profile,
displayName,
handle,
onAdd, onAdd,
onRemove, onRemove,
}: UserAddRemoveListsDialogProps) { }: UserAddRemoveListsDialogProps) {
return ( return (
<Dialog.Outer control={control} testID="userAddRemoveListsDialog"> <Dialog.Outer control={control} testID="userAddRemoveListsDialog">
<Dialog.Handle /> <Dialog.Handle />
<ListsContent <ListsContent profile={profile} onAdd={onAdd} onRemove={onRemove} />
subjectDid={subjectDid}
displayName={displayName}
handle={handle}
onAdd={onAdd}
onRemove={onRemove}
/>
</Dialog.Outer> </Dialog.Outer>
) )
} }
@@ -82,12 +74,14 @@ function Empty() {
} }
function ListsContent({ function ListsContent({
subjectDid, profile,
displayName,
handle,
onAdd, onAdd,
onRemove, onRemove,
}: Omit<UserAddRemoveListsDialogProps, 'control'>) { }: {
profile: bsky.profile.AnyProfileView | undefined
onAdd?: (listUri: string) => void
onRemove?: (listUri: string) => void
}) {
const control = Dialog.useDialogContext() const control = Dialog.useDialogContext()
const {t: l} = useLingui() const {t: l} = useLingui()
@@ -98,7 +92,7 @@ function ListsContent({
hasNextPage, hasNextPage,
isFetchingNextPage, isFetchingNextPage,
fetchNextPage, fetchNextPage,
} = useListsWithMembershipQuery({actor: subjectDid}) } = useListsWithMembershipQuery({actor: profile?.did})
const listItems = data?.pages.flatMap(page => page.listsWithMembership) || [] const listItems = data?.pages.flatMap(page => page.listsWithMembership) || []
@@ -112,17 +106,16 @@ function ListsContent({
}, [isFetchingNextPage, hasNextPage, isError, fetchNextPage]) }, [isFetchingNextPage, hasNextPage, isError, fetchNextPage])
const renderItem = useCallback( const renderItem = useCallback(
({item}: {item: ListWithMembership}) => ( ({item}: {item: ListWithMembership}) =>
<ListItem profile ? (
listWithMembership={item} <ListItem
subjectDid={subjectDid} listWithMembership={item}
displayName={displayName} profile={profile}
handle={handle} onAdd={onAdd}
onAdd={onAdd} onRemove={onRemove}
onRemove={onRemove} />
/> ) : null,
), [profile, onAdd, onRemove],
[subjectDid, displayName, handle, onAdd, onRemove],
) )
const onClose = useCallback(() => { const onClose = useCallback(() => {
@@ -139,9 +132,16 @@ function ListsContent({
native(a.pt_lg), native(a.pt_lg),
]}> ]}>
<Text style={[a.text_lg, a.font_semi_bold]}> <Text style={[a.text_lg, a.font_semi_bold]}>
<Trans>Update {sanitizeDisplayName(displayName)} in Lists</Trans> {profile ? (
<Trans>
Update {createSanitizedDisplayName(profile, true)} in Lists
</Trans>
) : (
<Trans>Update in Lists</Trans>
)}
</Text> </Text>
<Button <Button
testID="doneBtn"
label={l`Close`} label={l`Close`}
onPress={onClose} onPress={onClose}
variant="ghost" variant="ghost"
@@ -185,16 +185,12 @@ function ListsContent({
function ListItem({ function ListItem({
listWithMembership, listWithMembership,
subjectDid, profile,
displayName,
handle,
onAdd, onAdd,
onRemove, onRemove,
}: { }: {
listWithMembership: ListWithMembership listWithMembership: ListWithMembership
subjectDid: string profile: bsky.profile.AnyProfileView
displayName: string
handle: string
onAdd?: (listUri: string) => void onAdd?: (listUri: string) => void
onRemove?: (listUri: string) => void onRemove?: (listUri: string) => void
}) { }) {
@@ -214,13 +210,13 @@ function ListItem({
onAdd?.(list.uri) onAdd?.(list.uri)
updateListMembershipOptimistically({ updateListMembershipOptimistically({
queryClient, queryClient,
actor: subjectDid, actor: profile.did,
listUri: list.uri, listUri: list.uri,
membershipUri: data.uri, membershipUri: data.uri,
subject: { subject: {
did: subjectDid, did: profile.did,
handle, handle: profile.handle,
displayName, displayName: profile.displayName,
}, },
}) })
}, },
@@ -239,7 +235,7 @@ function ListItem({
onRemove?.(list.uri) onRemove?.(list.uri)
removeListMembershipOptimistically({ removeListMembershipOptimistically({
queryClient, queryClient,
actor: subjectDid, actor: profile.did,
listUri: list.uri, listUri: list.uri,
}) })
}, },
@@ -259,7 +255,7 @@ function ListItem({
if (!isMember) { if (!isMember) {
addMembership({ addMembership({
listUri: list.uri, listUri: list.uri,
actorDid: subjectDid, actorDid: profile.did,
}) })
} else { } else {
if (!listItem?.uri) { if (!listItem?.uri) {
@@ -268,13 +264,13 @@ function ListItem({
} }
removeMembership({ removeMembership({
listUri: list.uri, listUri: list.uri,
actorDid: subjectDid, actorDid: profile.did,
membershipUri: listItem.uri, membershipUri: listItem.uri,
}) })
} }
}, [ }, [
list.uri, list.uri,
subjectDid, profile.did,
isMember, isMember,
listItem, listItem,
isPending, isPending,
@@ -315,7 +311,7 @@ function ListItem({
</Text> </Text>
</View> </View>
<Button <Button
testID={`user-${handle}-addBtn`} testID={`user-${profile.handle}-addBtn`}
label={isMember ? l`Remove` : l`Add`} label={isMember ? l`Remove` : l`Add`}
onPress={handleToggleMembership} onPress={handleToggleMembership}
disabled={isPending} disabled={isPending}
+12 -3
View File
@@ -9,7 +9,10 @@ import {
useQueryClient, useQueryClient,
} from '@tanstack/react-query' } from '@tanstack/react-query'
import {RQKEY as LIST_MEMBERS_RQKEY} from '#/state/queries/list-members' import {
RQKEY as LIST_MEMBERS_RQKEY,
RQKEY_ALL as LIST_MEMBERS_ALL_RQKEY,
} from '#/state/queries/list-members'
import {useAgent, useSession} from '#/state/session' import {useAgent, useSession} from '#/state/session'
import type * as bsky from '#/types/bsky' import type * as bsky from '#/types/bsky'
import {RQKEY_WITH_MEMBERSHIP as STARTER_PACKS_WITH_MEMBERSHIPS_RKEY} from './actor-starter-packs' import {RQKEY_WITH_MEMBERSHIP as STARTER_PACKS_WITH_MEMBERSHIPS_RKEY} from './actor-starter-packs'
@@ -52,9 +55,12 @@ export function useListMembershipAddMutation({
// invalidate the members queries (used for rendering the listings) // invalidate the members queries (used for rendering the listings)
// use a timeout to wait for the appview // use a timeout to wait for the appview
setTimeout(() => { setTimeout(() => {
queryClient.invalidateQueries({ void queryClient.invalidateQueries({
queryKey: LIST_MEMBERS_RQKEY(variables.listUri), queryKey: LIST_MEMBERS_RQKEY(variables.listUri),
}) })
void queryClient.invalidateQueries({
queryKey: LIST_MEMBERS_ALL_RQKEY(variables.listUri),
})
}, 1e3) }, 1e3)
// update WITH_MEMBERSHIPS query for starter packs // update WITH_MEMBERSHIPS query for starter packs
@@ -144,9 +150,12 @@ export function useListMembershipRemoveMutation({
// invalidate the members queries (used for rendering the listings) // invalidate the members queries (used for rendering the listings)
// use a timeout to wait for the appview // use a timeout to wait for the appview
setTimeout(() => { setTimeout(() => {
queryClient.invalidateQueries({ void queryClient.invalidateQueries({
queryKey: LIST_MEMBERS_RQKEY(variables.listUri), queryKey: LIST_MEMBERS_RQKEY(variables.listUri),
}) })
void queryClient.invalidateQueries({
queryKey: LIST_MEMBERS_ALL_RQKEY(variables.listUri),
})
}, 1e3) }, 1e3)
// update WITH_MEMBERSHIPS query for starter packs // update WITH_MEMBERSHIPS query for starter packs
+5 -4
View File
@@ -9,19 +9,20 @@ import {
useInfiniteQuery, useInfiniteQuery,
} from '@tanstack/react-query' } from '@tanstack/react-query'
import {createQueryKey} from '#/state/queries/util'
import {useAgent} from '#/state/session' import {useAgent} from '#/state/session'
export type ListWithMembership = export type ListWithMembership =
AppBskyGraphGetListsWithMembership.ListWithMembership AppBskyGraphGetListsWithMembership.ListWithMembership
const RQKEY_ROOT = 'lists-with-membership' const RQKEY_ROOT = 'lists-with-membership'
export const RQKEY = (actor: string) => [RQKEY_ROOT, actor] export const RQKEY = (actor: string) => createQueryKey(RQKEY_ROOT, {actor})
export function useListsWithMembershipQuery({ export function useListsWithMembershipQuery({
actor, actor,
enabled = true, enabled = true,
}: { }: {
actor: string actor: string | undefined
enabled?: boolean enabled?: boolean
}) { }) {
const agent = useAgent() const agent = useAgent()
@@ -33,10 +34,10 @@ export function useListsWithMembershipQuery({
QueryKey, QueryKey,
string | undefined string | undefined
>({ >({
queryKey: RQKEY(actor), queryKey: RQKEY(actor ?? ''),
queryFn: async ({pageParam}: {pageParam?: string}) => { queryFn: async ({pageParam}: {pageParam?: string}) => {
const res = await agent.app.bsky.graph.getListsWithMembership({ const res = await agent.app.bsky.graph.getListsWithMembership({
actor, actor: actor!, // the enabled flag prevents this from running until actor is set
limit: 50, limit: 50,
cursor: pageParam, cursor: pageParam,
}) })
+4 -8
View File
@@ -294,14 +294,10 @@ export function ListMembers({
desktopFixedHeight={desktopFixedHeightOffset || true} desktopFixedHeight={desktopFixedHeightOffset || true}
/> />
{selectedProfile && ( <UserAddRemoveListsDialog
<UserAddRemoveListsDialog control={editListsDialogControl}
control={editListsDialogControl} profile={selectedProfile}
subjectDid={selectedProfile.did} />
displayName={selectedProfile.displayName || selectedProfile.handle}
handle={selectedProfile.handle}
/>
)}
</View> </View>
) )
} }
+1 -3
View File
@@ -525,9 +525,7 @@ let ProfileMenu = ({
<UserAddRemoveListsDialog <UserAddRemoveListsDialog
control={addToListsDialogControl} control={addToListsDialogControl}
subjectDid={profile.did} profile={profile}
displayName={profile.displayName || profile.handle}
handle={profile.handle}
onAdd={invalidateProfileQuery} onAdd={invalidateProfileQuery}
onRemove={invalidateProfileQuery} onRemove={invalidateProfileQuery}
/> />