Handle blocks in list and chat
This commit is contained in:
@@ -12,6 +12,10 @@ import {
|
|||||||
} from '#/state/queries/messages/conversation'
|
} from '#/state/queries/messages/conversation'
|
||||||
import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
|
import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
|
||||||
import {useMuteConvo} from '#/state/queries/messages/mute-conversation'
|
import {useMuteConvo} from '#/state/queries/messages/mute-conversation'
|
||||||
|
import {
|
||||||
|
useAwaitedProfileBlockMutation,
|
||||||
|
useAwaitedProfileUnblockMutation,
|
||||||
|
} from '#/state/queries/profile'
|
||||||
import * as Toast from '#/view/com/util/Toast'
|
import * as Toast from '#/view/com/util/Toast'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {ArrowBoxLeft_Stroke2_Corner0_Rounded as ArrowBoxLeft} from '#/components/icons/ArrowBoxLeft'
|
import {ArrowBoxLeft_Stroke2_Corner0_Rounded as ArrowBoxLeft} from '#/components/icons/ArrowBoxLeft'
|
||||||
@@ -34,10 +38,11 @@ let ConvoMenu = ({
|
|||||||
showMarkAsRead,
|
showMarkAsRead,
|
||||||
hideTrigger,
|
hideTrigger,
|
||||||
triggerOpacity,
|
triggerOpacity,
|
||||||
|
onUpdateConvo,
|
||||||
}: {
|
}: {
|
||||||
convo: ChatBskyConvoDefs.ConvoView
|
convo: ChatBskyConvoDefs.ConvoView
|
||||||
profile: AppBskyActorDefs.ProfileViewBasic
|
profile: AppBskyActorDefs.ProfileViewBasic
|
||||||
onUpdateConvo?: (convo: ChatBskyConvoDefs.ConvoView) => void
|
onUpdateConvo?: () => void
|
||||||
control?: Menu.MenuControlProps
|
control?: Menu.MenuControlProps
|
||||||
currentScreen: 'list' | 'conversation'
|
currentScreen: 'list' | 'conversation'
|
||||||
showMarkAsRead?: boolean
|
showMarkAsRead?: boolean
|
||||||
@@ -64,12 +69,41 @@ let ConvoMenu = ({
|
|||||||
} else {
|
} else {
|
||||||
Toast.show(_(msg`Chat unmuted`))
|
Toast.show(_(msg`Chat unmuted`))
|
||||||
}
|
}
|
||||||
|
onUpdateConvo?.()
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
Toast.show(_(msg`Could not mute chat`))
|
Toast.show(_(msg`Could not mute chat`))
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const {mutateAsync: blockProfile, isPending: isBlockPending} =
|
||||||
|
useAwaitedProfileBlockMutation()
|
||||||
|
const {mutateAsync: unblockProfile, isPending: isUnblockPending} =
|
||||||
|
useAwaitedProfileUnblockMutation()
|
||||||
|
const isBlockMutationPending = isBlockPending || isUnblockPending
|
||||||
|
const isBlocking = Boolean(profile.viewer?.blocking)
|
||||||
|
|
||||||
|
const toggleBlock = useCallback(async () => {
|
||||||
|
if (isBlockMutationPending) return
|
||||||
|
|
||||||
|
if (profile.viewer?.blocking) {
|
||||||
|
await unblockProfile({
|
||||||
|
subject: profile.did,
|
||||||
|
blockUri: profile.viewer?.blocking,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
await blockProfile({subject: profile.did})
|
||||||
|
}
|
||||||
|
|
||||||
|
onUpdateConvo?.()
|
||||||
|
}, [
|
||||||
|
profile,
|
||||||
|
isBlockMutationPending,
|
||||||
|
blockProfile,
|
||||||
|
unblockProfile,
|
||||||
|
onUpdateConvo,
|
||||||
|
])
|
||||||
|
|
||||||
const {mutate: leaveConvo} = useLeaveConvo(convo?.id, {
|
const {mutate: leaveConvo} = useLeaveConvo(convo?.id, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
if (currentScreen === 'conversation') {
|
if (currentScreen === 'conversation') {
|
||||||
@@ -146,18 +180,17 @@ let ConvoMenu = ({
|
|||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</Menu.Group>
|
</Menu.Group>
|
||||||
<Menu.Divider />
|
<Menu.Divider />
|
||||||
{/* TODO(samuel): implement this */}
|
|
||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Block account`)}
|
disabled={isBlockMutationPending}
|
||||||
onPress={() => {}}
|
label={
|
||||||
disabled>
|
isBlocking ? _(msg`Unblock account`) : _(msg`Block account`)
|
||||||
|
}
|
||||||
|
onPress={toggleBlock}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Block account</Trans>
|
{isBlocking ? _(msg`Unblock account`) : _(msg`Block account`)}
|
||||||
</Menu.ItemText>
|
</Menu.ItemText>
|
||||||
<Menu.ItemIcon
|
<Menu.ItemIcon icon={isBlocking ? PersonX : PersonCheck} />
|
||||||
icon={profile.viewer?.blocking ? PersonCheck : PersonX}
|
|
||||||
/>
|
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Report conversation`)}
|
label={_(msg`Report conversation`)}
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ function Inner() {
|
|||||||
* Any other convo states (atm) are "ready" states
|
* Any other convo states (atm) are "ready" states
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
console.log(convoState.blocks)
|
||||||
return (
|
return (
|
||||||
<KeyboardProvider>
|
<KeyboardProvider>
|
||||||
<KeyboardAvoidingView
|
<KeyboardAvoidingView
|
||||||
@@ -242,6 +243,7 @@ let Header = ({
|
|||||||
convo={convoState.convo}
|
convo={convoState.convo}
|
||||||
profile={profile}
|
profile={profile}
|
||||||
currentScreen="conversation"
|
currentScreen="conversation"
|
||||||
|
onUpdateConvo={convoState.revalidateConvo}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<View style={{width: 30}} />
|
<View style={{width: 30}} />
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import {ChatBskyConvoDefs} from '@atproto/api'
|
|||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {NavigationProp} from '#/lib/routes/types'
|
import {NavigationProp} from '#/lib/routes/types'
|
||||||
import {isNative} from '#/platform/detection'
|
import {isNative} from '#/platform/detection'
|
||||||
|
import {RQKEY as ListConvosQueryKey} from '#/state/queries/messages/list-converations'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {TimeElapsed} from '#/view/com/util/TimeElapsed'
|
import {TimeElapsed} from '#/view/com/util/TimeElapsed'
|
||||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||||
@@ -36,6 +38,7 @@ export function ChatListItem({
|
|||||||
const displayName = isDeletedAccount
|
const displayName = isDeletedAccount
|
||||||
? 'Deleted Account'
|
? 'Deleted Account'
|
||||||
: otherUser?.displayName || otherUser?.handle
|
: otherUser?.displayName || otherUser?.handle
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
let lastMessage = _(msg`No messages yet`)
|
let lastMessage = _(msg`No messages yet`)
|
||||||
let lastMessageSentAt: string | null = null
|
let lastMessageSentAt: string | null = null
|
||||||
@@ -73,6 +76,10 @@ export function ChatListItem({
|
|||||||
})
|
})
|
||||||
}, [convo.id, navigation])
|
}, [convo.id, navigation])
|
||||||
|
|
||||||
|
const onUpdateConvo = React.useCallback(() => {
|
||||||
|
queryClient.invalidateQueries({queryKey: ListConvosQueryKey})
|
||||||
|
}, [queryClient])
|
||||||
|
|
||||||
if (!otherUser) {
|
if (!otherUser) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -204,6 +211,7 @@ export function ChatListItem({
|
|||||||
triggerOpacity={
|
triggerOpacity={
|
||||||
!gtMobile || showActions || menuControl.isOpen ? 1 : 0
|
!gtMobile || showActions || menuControl.isOpen ? 1 : 0
|
||||||
}
|
}
|
||||||
|
onUpdateConvo={onUpdateConvo}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -384,6 +384,9 @@ function useProfileUnmuteMutation() {
|
|||||||
|
|
||||||
export function useProfileBlockMutationQueue(
|
export function useProfileBlockMutationQueue(
|
||||||
profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>,
|
profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>,
|
||||||
|
options?: {
|
||||||
|
onSuccess?: () => void
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const did = profile.did
|
const did = profile.did
|
||||||
@@ -414,6 +417,7 @@ export function useProfileBlockMutationQueue(
|
|||||||
updateProfileShadow(queryClient, did, {
|
updateProfileShadow(queryClient, did, {
|
||||||
blockingUri: finalBlockingUri,
|
blockingUri: finalBlockingUri,
|
||||||
})
|
})
|
||||||
|
options?.onSuccess?.()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -478,6 +482,60 @@ function useProfileUnblockMutation() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useAwaitedProfileBlockMutation() {
|
||||||
|
const {currentAccount} = useSession()
|
||||||
|
const {getAgent} = useAgent()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async ({subject}: {subject: string}) => {
|
||||||
|
if (!currentAccount) {
|
||||||
|
throw new Error('Not signed in')
|
||||||
|
}
|
||||||
|
await getAgent().app.bsky.graph.block.create(
|
||||||
|
{repo: currentAccount.did},
|
||||||
|
{subject: subject, createdAt: new Date().toISOString()},
|
||||||
|
)
|
||||||
|
await whenAppViewReady(
|
||||||
|
getAgent,
|
||||||
|
subject,
|
||||||
|
res => !!res.data.viewer?.blocking,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onSuccess(_, {subject}) {
|
||||||
|
queryClient.invalidateQueries({queryKey: RQKEY_MY_BLOCKED()})
|
||||||
|
resetProfilePostsQueries(queryClient, subject, 1000)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAwaitedProfileUnblockMutation() {
|
||||||
|
const {currentAccount} = useSession()
|
||||||
|
const {getAgent} = useAgent()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
|
return useMutation<void, Error, {subject: string; blockUri: string}>({
|
||||||
|
mutationFn: async ({blockUri, subject}) => {
|
||||||
|
if (!currentAccount) {
|
||||||
|
throw new Error('Not signed in')
|
||||||
|
}
|
||||||
|
const {rkey} = new AtUri(blockUri)
|
||||||
|
await getAgent().app.bsky.graph.block.delete({
|
||||||
|
repo: currentAccount.did,
|
||||||
|
rkey,
|
||||||
|
})
|
||||||
|
await whenAppViewReady(
|
||||||
|
getAgent,
|
||||||
|
subject,
|
||||||
|
res => !res.data.viewer?.blocking,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onSuccess(_, {subject}) {
|
||||||
|
resetProfilePostsQueries(queryClient, subject, 1000)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export function precacheProfile(
|
export function precacheProfile(
|
||||||
queryClient: QueryClient,
|
queryClient: QueryClient,
|
||||||
profile: AppBskyActorDefs.ProfileViewBasic,
|
profile: AppBskyActorDefs.ProfileViewBasic,
|
||||||
|
|||||||
Reference in New Issue
Block a user