diff options
author | Hailey <me@haileyok.com> | 2024-04-29 23:34:26 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-29 23:34:26 -0700 |
commit | eb8bfd11d14a87983b210bea4a619d2dd7c51cdf (patch) | |
tree | 6f322f86ba92e989570daa1ada94ad5f10258506 /src/screens/Messages/Temp/query/query.ts | |
parent | 5d19f27052ebd3642db58742f7efaaee0b3a6720 (diff) | |
download | voidsky-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.ts | 219 |
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, + }) +} |