about summary refs log tree commit diff
path: root/src/screens/Messages/Temp/query/query.ts
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-04-29 23:34:26 -0700
committerGitHub <noreply@github.com>2024-04-29 23:34:26 -0700
commiteb8bfd11d14a87983b210bea4a619d2dd7c51cdf (patch)
tree6f322f86ba92e989570daa1ada94ad5f10258506 /src/screens/Messages/Temp/query/query.ts
parent5d19f27052ebd3642db58742f7efaaee0b3a6720 (diff)
downloadvoidsky-eb8bfd11d14a87983b210bea4a619d2dd7c51cdf.tar.zst
[Clipclops] Add screen to view and send clip clops (#3754)
* add new routes with placeholder screens

* add clops list

* add a clop input

* add some better padding to the clops

* some more adjustments

* add rnkc

* implement rnkc

* implement rnkc

* be a little less weird about it

* rename clop stuff

* rename more clop

* one more

* [Clipclops] Temp codegenerated lexicon (#3749)

* add codegenerated lexicon

* replace hailey's types

* use codegen'd types in components

* fix error + throw if fetch failed

* remove bad imports

* update messageslist and messageitem

* import useState

* add clop service URL hook

* add dm service url storage

* use context

* use context for service url (temp)

* remove log

* nits

---------

Co-authored-by: Samuel Newman <mozzius@protonmail.com>
Diffstat (limited to 'src/screens/Messages/Temp/query/query.ts')
-rw-r--r--src/screens/Messages/Temp/query/query.ts219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/screens/Messages/Temp/query/query.ts b/src/screens/Messages/Temp/query/query.ts
new file mode 100644
index 000000000..2477dc569
--- /dev/null
+++ b/src/screens/Messages/Temp/query/query.ts
@@ -0,0 +1,219 @@
+import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
+
+import {useSession} from 'state/session'
+import {useDmServiceUrlStorage} from '#/screens/Messages/Temp/useDmServiceUrlStorage'
+import * as TempDmChatDefs from '#/temp/dm/defs'
+import * as TempDmChatGetChat from '#/temp/dm/getChat'
+import * as TempDmChatGetChatLog from '#/temp/dm/getChatLog'
+import * as TempDmChatGetChatMessages from '#/temp/dm/getChatMessages'
+
+/**
+ * TEMPORARY, PLEASE DO NOT JUDGE ME REACT QUERY OVERLORDS 🙏
+ * (and do not try this at home)
+ */
+
+function createHeaders(did: string) {
+  return {
+    Authorization: did,
+  }
+}
+
+type Chat = {
+  chatId: string
+  messages: TempDmChatGetChatMessages.OutputSchema['messages']
+  lastCursor?: string
+  lastRev?: string
+}
+
+export function useChat(chatId: string) {
+  const queryClient = useQueryClient()
+
+  const {serviceUrl} = useDmServiceUrlStorage()
+  const {currentAccount} = useSession()
+  const did = currentAccount?.did ?? ''
+
+  return useQuery({
+    queryKey: ['chat', chatId],
+    queryFn: async () => {
+      const currentChat = queryClient.getQueryData(['chat', chatId])
+
+      if (currentChat) {
+        return currentChat as Chat
+      }
+
+      const messagesResponse = await fetch(
+        `${serviceUrl}/xrpc/temp.dm.getChatMessages?chatId=${chatId}`,
+        {
+          headers: createHeaders(did),
+        },
+      )
+
+      if (!messagesResponse.ok) throw new Error('Failed to fetch messages')
+
+      const messagesJson =
+        (await messagesResponse.json()) as TempDmChatGetChatMessages.OutputSchema
+
+      const chatResponse = await fetch(
+        `${serviceUrl}/xrpc/temp.dm.getChat?chatId=${chatId}`,
+        {
+          headers: createHeaders(did),
+        },
+      )
+
+      if (!chatResponse.ok) throw new Error('Failed to fetch chat')
+
+      const chatJson =
+        (await chatResponse.json()) as TempDmChatGetChat.OutputSchema
+
+      const newChat = {
+        chatId,
+        messages: messagesJson.messages,
+        lastCursor: messagesJson.cursor,
+        lastRev: chatJson.chat.rev,
+      } satisfies Chat
+
+      queryClient.setQueryData(['chat', chatId], newChat)
+
+      return newChat
+    },
+  })
+}
+
+interface SendMessageMutationVariables {
+  message: string
+  tempId: string
+}
+
+export function createTempId() {
+  return Math.random().toString(36).substring(7).toString()
+}
+
+export function useSendMessageMutation(chatId: string) {
+  const queryClient = useQueryClient()
+
+  const {serviceUrl} = useDmServiceUrlStorage()
+  const {currentAccount} = useSession()
+  const did = currentAccount?.did ?? ''
+
+  return useMutation<
+    TempDmChatDefs.Message,
+    Error,
+    SendMessageMutationVariables,
+    unknown
+  >({
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    mutationFn: async ({message, tempId}) => {
+      const response = await fetch(
+        `${serviceUrl}/xrpc/temp.dm.sendMessage?chatId=${chatId}`,
+        {
+          method: 'POST',
+          headers: {
+            ...createHeaders(did),
+            'Content-Type': 'application/json',
+          },
+          body: JSON.stringify({
+            chatId,
+            message: {
+              text: message,
+            },
+          }),
+        },
+      )
+
+      if (!response.ok) throw new Error('Failed to send message')
+
+      return response.json()
+    },
+    onMutate: async variables => {
+      queryClient.setQueryData(['chat', chatId], (prev: Chat) => {
+        return {
+          ...prev,
+          messages: [
+            {
+              id: variables.tempId,
+              text: variables.message,
+            },
+            ...prev.messages,
+          ],
+        }
+      })
+    },
+    onSuccess: (result, variables) => {
+      queryClient.setQueryData(['chat', chatId], (prev: Chat) => {
+        return {
+          ...prev,
+          messages: prev.messages.map(m =>
+            m.id === variables.tempId
+              ? {
+                  ...m,
+                  id: result.id,
+                }
+              : m,
+          ),
+        }
+      })
+    },
+    onError: (_, variables) => {
+      console.log(_)
+      queryClient.setQueryData(['chat', chatId], (prev: Chat) => ({
+        ...prev,
+        messages: prev.messages.filter(m => m.id !== variables.tempId),
+      }))
+    },
+  })
+}
+
+export function useChatLogQuery() {
+  const queryClient = useQueryClient()
+
+  const {serviceUrl} = useDmServiceUrlStorage()
+  const {currentAccount} = useSession()
+  const did = currentAccount?.did ?? ''
+
+  return useQuery({
+    queryKey: ['chatLog'],
+    queryFn: async () => {
+      const prevLog = queryClient.getQueryData([
+        'chatLog',
+      ]) as TempDmChatGetChatLog.OutputSchema
+
+      try {
+        const response = await fetch(
+          `${serviceUrl}/xrpc/temp.dm.getChatLog?cursor=${
+            prevLog?.cursor ?? ''
+          }`,
+          {
+            headers: createHeaders(did),
+          },
+        )
+
+        if (!response.ok) throw new Error('Failed to fetch chat log')
+
+        const json =
+          (await response.json()) as TempDmChatGetChatLog.OutputSchema
+
+        for (const log of json.logs) {
+          if (TempDmChatDefs.isLogDeleteMessage(log)) {
+            queryClient.setQueryData(['chat', log.chatId], (prev: Chat) => {
+              // What to do in this case
+              if (!prev) return
+
+              // HACK we don't know who the creator of a message is, so just filter by id for now
+              if (prev.messages.find(m => m.id === log.message.id)) return prev
+
+              return {
+                ...prev,
+                messages: [log.message, ...prev.messages],
+              }
+            })
+          }
+        }
+
+        return json
+      } catch (e) {
+        console.log(e)
+      }
+    },
+    refetchInterval: 5000,
+  })
+}