about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2024-05-08 15:48:05 +0100
committerGitHub <noreply@github.com>2024-05-08 15:48:05 +0100
commit38198fdf7f858a819891e39d418b74cc6b94d756 (patch)
treecbc23d418dff3ab8ed1ce76b669b2dc2e12447a0 /src
parent56f713077f6e663ac77df20f1d67b55fd1da153a (diff)
downloadvoidsky-38198fdf7f858a819891e39d418b74cc6b94d756.tar.zst
[🐴] Mark as read in convo menu (#3913)
* add mark as read option

* optimistic update + link up menu

* rm messageid
Diffstat (limited to 'src')
-rw-r--r--src/components/dms/ConvoMenu.tsx19
-rw-r--r--src/components/icons/Bubble.tsx8
-rw-r--r--src/screens/Messages/List/index.tsx3
-rw-r--r--src/state/queries/messages/conversation.ts12
-rw-r--r--src/state/queries/messages/list-converations.ts17
5 files changed, 51 insertions, 8 deletions
diff --git a/src/components/dms/ConvoMenu.tsx b/src/components/dms/ConvoMenu.tsx
index 16306bb57..263befd56 100644
--- a/src/components/dms/ConvoMenu.tsx
+++ b/src/components/dms/ConvoMenu.tsx
@@ -7,6 +7,7 @@ import {useLingui} from '@lingui/react'
 import {useNavigation} from '@react-navigation/native'
 
 import {NavigationProp} from '#/lib/routes/types'
+import {useMarkAsReadMutation} from '#/state/queries/messages/conversation'
 import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
 import {
   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 * as Menu from '#/components/Menu'
 import * as Prompt from '#/components/Prompt'
+import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '../icons/Bubble'
 
 let ConvoMenu = ({
   convo,
@@ -32,6 +34,7 @@ let ConvoMenu = ({
   control,
   hideTrigger,
   currentScreen,
+  showMarkAsRead,
 }: {
   convo: ChatBskyConvoDefs.ConvoView
   profile: AppBskyActorDefs.ProfileViewBasic
@@ -39,11 +42,13 @@ let ConvoMenu = ({
   control?: Menu.MenuControlProps
   hideTrigger?: boolean
   currentScreen: 'list' | 'conversation'
+  showMarkAsRead?: boolean
 }): React.ReactNode => {
   const navigation = useNavigation<NavigationProp>()
   const {_} = useLingui()
   const t = useTheme()
   const leaveConvoControl = Prompt.usePromptControl()
+  const {mutate: markAsRead} = useMarkAsReadMutation()
 
   const onNavigateToProfile = useCallback(() => {
     navigation.navigate('Profile', {name: profile.did})
@@ -107,6 +112,20 @@ let ConvoMenu = ({
         )}
         <Menu.Outer>
           <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
               label={_(msg`Go to user's profile`)}
               onPress={onNavigateToProfile}>
diff --git a/src/components/icons/Bubble.tsx b/src/components/icons/Bubble.tsx
index d4e08f6d2..ff6da2531 100644
--- a/src/components/icons/Bubble.tsx
+++ b/src/components/icons/Bubble.tsx
@@ -3,3 +3,11 @@ import {createSinglePathSVG} from './TEMPLATE'
 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',
 })
+
+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',
+})
diff --git a/src/screens/Messages/List/index.tsx b/src/screens/Messages/List/index.tsx
index ca757fac0..a82f2f00a 100644
--- a/src/screens/Messages/List/index.tsx
+++ b/src/screens/Messages/List/index.tsx
@@ -275,7 +275,7 @@ function ChatListItem({convo}: {convo: ChatBskyConvoDefs.ConvoView}) {
             a.pl_md,
             a.py_sm,
             a.gap_md,
-            a.pr_2xl,
+            a.pr_xl,
             (hovered || pressed) && t.atoms.bg_contrast_25,
           ]}>
           <View pointerEvents="none">
@@ -340,6 +340,7 @@ function ChatListItem({convo}: {convo: ChatBskyConvoDefs.ConvoView}) {
             // tricky because it captures the mouse event
             hideTrigger
             currentScreen="list"
+            showMarkAsRead={convo.unreadCount > 0}
           />
         </View>
       )}
diff --git a/src/state/queries/messages/conversation.ts b/src/state/queries/messages/conversation.ts
index c322e0c62..551fbe98e 100644
--- a/src/state/queries/messages/conversation.ts
+++ b/src/state/queries/messages/conversation.ts
@@ -1,7 +1,7 @@
 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 {useHeaders} from './temp-headers'
 
@@ -28,7 +28,7 @@ export function useConvoQuery(convoId: string) {
 export function useMarkAsReadMutation() {
   const headers = useHeaders()
   const {serviceUrl} = useDmServiceUrlStorage()
-  const queryClient = useQueryClient()
+  const onMarkAsRead = useOnMarkAsRead()
 
   return useMutation({
     mutationFn: async ({
@@ -50,10 +50,8 @@ export function useMarkAsReadMutation() {
         },
       )
     },
-    onSuccess() {
-      queryClient.invalidateQueries({
-        queryKey: ListConvosQueryKey,
-      })
+    onSuccess(_, {convoId}) {
+      onMarkAsRead(convoId)
     },
   })
 }
diff --git a/src/state/queries/messages/list-converations.ts b/src/state/queries/messages/list-converations.ts
index e66551ceb..32107c0cd 100644
--- a/src/state/queries/messages/list-converations.ts
+++ b/src/state/queries/messages/list-converations.ts
@@ -111,6 +111,23 @@ export function useOnCreateConvo() {
   }, [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(
   chatId: string,
   old: ConvoListQueryData,