[🐴] Mark as read in convo menu (#3913)
* add mark as read option * optimistic update + link up menu * rm messageidzio/stable
parent
56f713077f
commit
38198fdf7f
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M2.002 7a4 4 0 0 1 4-4h12a4 4 0 0 1 4 4v8a4 4 0 0 1-4 4H12.28l-4.762 2.858A1 1 0 0 1 6.002 21v-2a4 4 0 0 1-4-4V7Zm4-2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h1a1 1 0 0 1 1 1v1.234l3.486-2.092a1 1 0 0 1 .514-.142h6a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-12Z" clip-rule="evenodd"/></svg>
|
After Width: | Height: | Size: 381 B |
|
@ -7,6 +7,7 @@ import {useLingui} from '@lingui/react'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {NavigationProp} from '#/lib/routes/types'
|
import {NavigationProp} from '#/lib/routes/types'
|
||||||
|
import {useMarkAsReadMutation} from '#/state/queries/messages/conversation'
|
||||||
import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
|
import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
|
||||||
import {
|
import {
|
||||||
useMuteConvo,
|
useMuteConvo,
|
||||||
|
@ -24,6 +25,7 @@ import {PersonX_Stroke2_Corner0_Rounded as PersonX} from '#/components/icons/Per
|
||||||
import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as Unmute} from '#/components/icons/Speaker'
|
import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as Unmute} from '#/components/icons/Speaker'
|
||||||
import * as Menu from '#/components/Menu'
|
import * as Menu from '#/components/Menu'
|
||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
|
import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '../icons/Bubble'
|
||||||
|
|
||||||
let ConvoMenu = ({
|
let ConvoMenu = ({
|
||||||
convo,
|
convo,
|
||||||
|
@ -32,6 +34,7 @@ let ConvoMenu = ({
|
||||||
control,
|
control,
|
||||||
hideTrigger,
|
hideTrigger,
|
||||||
currentScreen,
|
currentScreen,
|
||||||
|
showMarkAsRead,
|
||||||
}: {
|
}: {
|
||||||
convo: ChatBskyConvoDefs.ConvoView
|
convo: ChatBskyConvoDefs.ConvoView
|
||||||
profile: AppBskyActorDefs.ProfileViewBasic
|
profile: AppBskyActorDefs.ProfileViewBasic
|
||||||
|
@ -39,11 +42,13 @@ let ConvoMenu = ({
|
||||||
control?: Menu.MenuControlProps
|
control?: Menu.MenuControlProps
|
||||||
hideTrigger?: boolean
|
hideTrigger?: boolean
|
||||||
currentScreen: 'list' | 'conversation'
|
currentScreen: 'list' | 'conversation'
|
||||||
|
showMarkAsRead?: boolean
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const leaveConvoControl = Prompt.usePromptControl()
|
const leaveConvoControl = Prompt.usePromptControl()
|
||||||
|
const {mutate: markAsRead} = useMarkAsReadMutation()
|
||||||
|
|
||||||
const onNavigateToProfile = useCallback(() => {
|
const onNavigateToProfile = useCallback(() => {
|
||||||
navigation.navigate('Profile', {name: profile.did})
|
navigation.navigate('Profile', {name: profile.did})
|
||||||
|
@ -107,6 +112,20 @@ let ConvoMenu = ({
|
||||||
)}
|
)}
|
||||||
<Menu.Outer>
|
<Menu.Outer>
|
||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
|
{showMarkAsRead && (
|
||||||
|
<Menu.Item
|
||||||
|
label={_(msg`Mark as read`)}
|
||||||
|
onPress={() =>
|
||||||
|
markAsRead({
|
||||||
|
convoId: convo.id,
|
||||||
|
})
|
||||||
|
}>
|
||||||
|
<Menu.ItemText>
|
||||||
|
<Trans>Mark as read</Trans>
|
||||||
|
</Menu.ItemText>
|
||||||
|
<Menu.ItemIcon icon={Bubble} />
|
||||||
|
</Menu.Item>
|
||||||
|
)}
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Go to user's profile`)}
|
label={_(msg`Go to user's profile`)}
|
||||||
onPress={onNavigateToProfile}>
|
onPress={onNavigateToProfile}>
|
||||||
|
|
|
@ -3,3 +3,11 @@ import {createSinglePathSVG} from './TEMPLATE'
|
||||||
export const BubbleQuestion_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
export const BubbleQuestion_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||||
path: 'M5.002 17.036V5h14v12.036h-3.986a1 1 0 0 0-.639.23l-2.375 1.968-2.344-1.965a1 1 0 0 0-.643-.233H5.002ZM20.002 3h-16a1 1 0 0 0-1 1v14.036a1 1 0 0 0 1 1h4.65l2.704 2.266a1 1 0 0 0 1.28.004l2.74-2.27h4.626a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Zm-7.878 3.663c-1.39 0-2.5 1.135-2.5 2.515a1 1 0 0 0 2 0c0-.294.232-.515.5-.515a.507.507 0 0 1 .489.6.174.174 0 0 1-.027.048 1.1 1.1 0 0 1-.267.226c-.508.345-1.128.923-1.286 1.978a1 1 0 1 0 1.978.297.762.762 0 0 1 .14-.359c.063-.086.155-.169.293-.262.436-.297 1.18-.885 1.18-2.013 0-1.38-1.11-2.515-2.5-2.515ZM12 15.75a1.25 1.25 0 1 1 0-2.5 1.25 1.25 0 0 1 0 2.5Z',
|
path: 'M5.002 17.036V5h14v12.036h-3.986a1 1 0 0 0-.639.23l-2.375 1.968-2.344-1.965a1 1 0 0 0-.643-.233H5.002ZM20.002 3h-16a1 1 0 0 0-1 1v14.036a1 1 0 0 0 1 1h4.65l2.704 2.266a1 1 0 0 0 1.28.004l2.74-2.27h4.626a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Zm-7.878 3.663c-1.39 0-2.5 1.135-2.5 2.515a1 1 0 0 0 2 0c0-.294.232-.515.5-.515a.507.507 0 0 1 .489.6.174.174 0 0 1-.027.048 1.1 1.1 0 0 1-.267.226c-.508.345-1.128.923-1.286 1.978a1 1 0 1 0 1.978.297.762.762 0 0 1 .14-.359c.063-.086.155-.169.293-.262.436-.297 1.18-.885 1.18-2.013 0-1.38-1.11-2.515-2.5-2.515ZM12 15.75a1.25 1.25 0 1 1 0-2.5 1.25 1.25 0 0 1 0 2.5Z',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const Bubble_Stroke2_Corner2_Rounded = createSinglePathSVG({
|
||||||
|
path: 'M2.002 6a3 3 0 0 1 3-3h14a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H12.28l-4.762 2.858A1 1 0 0 1 6.002 21v-2h-1a3 3 0 0 1-3-3V6Zm3-1a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v1.234l3.486-2.092a1 1 0 0 1 .514-.142h7a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-14Z',
|
||||||
|
})
|
||||||
|
|
||||||
|
export const Bubble_Stroke2_Corner3_Rounded = createSinglePathSVG({
|
||||||
|
path: 'M2.002 7a4 4 0 0 1 4-4h12a4 4 0 0 1 4 4v8a4 4 0 0 1-4 4H12.28l-4.762 2.858A1 1 0 0 1 6.002 21v-2a4 4 0 0 1-4-4V7Zm4-2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h1a1 1 0 0 1 1 1v1.234l3.486-2.092a1 1 0 0 1 .514-.142h6a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-12Z',
|
||||||
|
})
|
||||||
|
|
|
@ -275,7 +275,7 @@ function ChatListItem({convo}: {convo: ChatBskyConvoDefs.ConvoView}) {
|
||||||
a.pl_md,
|
a.pl_md,
|
||||||
a.py_sm,
|
a.py_sm,
|
||||||
a.gap_md,
|
a.gap_md,
|
||||||
a.pr_2xl,
|
a.pr_xl,
|
||||||
(hovered || pressed) && t.atoms.bg_contrast_25,
|
(hovered || pressed) && t.atoms.bg_contrast_25,
|
||||||
]}>
|
]}>
|
||||||
<View pointerEvents="none">
|
<View pointerEvents="none">
|
||||||
|
@ -340,6 +340,7 @@ function ChatListItem({convo}: {convo: ChatBskyConvoDefs.ConvoView}) {
|
||||||
// tricky because it captures the mouse event
|
// tricky because it captures the mouse event
|
||||||
hideTrigger
|
hideTrigger
|
||||||
currentScreen="list"
|
currentScreen="list"
|
||||||
|
showMarkAsRead={convo.unreadCount > 0}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {BskyAgent} from '@atproto-labs/api'
|
import {BskyAgent} from '@atproto-labs/api'
|
||||||
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
|
import {useMutation, useQuery} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {RQKEY as ListConvosQueryKey} from '#/state/queries/messages/list-converations'
|
import {useOnMarkAsRead} from '#/state/queries/messages/list-converations'
|
||||||
import {useDmServiceUrlStorage} from '#/screens/Messages/Temp/useDmServiceUrlStorage'
|
import {useDmServiceUrlStorage} from '#/screens/Messages/Temp/useDmServiceUrlStorage'
|
||||||
import {useHeaders} from './temp-headers'
|
import {useHeaders} from './temp-headers'
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ export function useConvoQuery(convoId: string) {
|
||||||
export function useMarkAsReadMutation() {
|
export function useMarkAsReadMutation() {
|
||||||
const headers = useHeaders()
|
const headers = useHeaders()
|
||||||
const {serviceUrl} = useDmServiceUrlStorage()
|
const {serviceUrl} = useDmServiceUrlStorage()
|
||||||
const queryClient = useQueryClient()
|
const onMarkAsRead = useOnMarkAsRead()
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({
|
mutationFn: async ({
|
||||||
|
@ -50,10 +50,8 @@ export function useMarkAsReadMutation() {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onSuccess() {
|
onSuccess(_, {convoId}) {
|
||||||
queryClient.invalidateQueries({
|
onMarkAsRead(convoId)
|
||||||
queryKey: ListConvosQueryKey,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,23 @@ export function useOnCreateConvo() {
|
||||||
}, [queryClient])
|
}, [queryClient])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useOnMarkAsRead() {
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
|
return useCallback(
|
||||||
|
(chatId: string) => {
|
||||||
|
queryClient.setQueryData(RQKEY, (old: ConvoListQueryData) => {
|
||||||
|
return optimisticUpdate(chatId, old, convo => ({
|
||||||
|
...convo,
|
||||||
|
unreadCount: 0,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
queryClient.invalidateQueries({queryKey: RQKEY})
|
||||||
|
},
|
||||||
|
[queryClient],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function optimisticUpdate(
|
function optimisticUpdate(
|
||||||
chatId: string,
|
chatId: string,
|
||||||
old: ConvoListQueryData,
|
old: ConvoListQueryData,
|
||||||
|
|
Loading…
Reference in New Issue