diff options
author | Samuel Newman <mozzius@protonmail.com> | 2024-05-02 00:15:10 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-02 00:15:10 +0100 |
commit | e19f88245048a6aa41481735e170cee966d3e276 (patch) | |
tree | c6bb6731e9ca0e83318ca9492836aafd7be356ef /src/state | |
parent | d3fafdc066f5b305b1d8838f040593fd744d30a6 (diff) | |
download | voidsky-e19f88245048a6aa41481735e170cee966d3e276.tar.zst |
[Clipclops] Clop menu, leave clop, mute/unmute clop (#3804)
* convo menu * memoize convomenu * add convoId to useChat + memoize value * leave convo * Create mute-conversation.ts * add mutes, remove changes to useChat and use chat.convo instead * add todo comments * leave convo confirm prompt * remove dependency on useChat and pass in props instead * show menu on long press * optimistic update * optimistic update leave + add error capture * don't `popToTop` when unnecessary --------- Co-authored-by: Hailey <me@haileyok.com>
Diffstat (limited to 'src/state')
-rw-r--r-- | src/state/messages/index.tsx | 31 | ||||
-rw-r--r-- | src/state/queries/messages/get-convo-for-members.ts | 6 | ||||
-rw-r--r-- | src/state/queries/messages/leave-conversation.ts | 68 | ||||
-rw-r--r-- | src/state/queries/messages/mute-conversation.ts | 84 |
4 files changed, 171 insertions, 18 deletions
diff --git a/src/state/messages/index.tsx b/src/state/messages/index.tsx index c59915253..cdc5a4db2 100644 --- a/src/state/messages/index.tsx +++ b/src/state/messages/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, {useContext, useEffect, useMemo, useState} from 'react' import {BskyAgent} from '@atproto-labs/api' import {Convo, ConvoParams} from '#/state/messages/convo' @@ -8,15 +8,14 @@ import {useDmServiceUrlStorage} from '#/screens/Messages/Temp/useDmServiceUrlSto const ChatContext = React.createContext<{ service: Convo state: Convo['state'] -}>({ - // @ts-ignore - service: null, - // @ts-ignore - state: null, -}) +} | null>(null) export function useChat() { - return React.useContext(ChatContext) + const ctx = useContext(ChatContext) + if (!ctx) { + throw new Error('useChat must be used within a ChatProvider') + } + return ctx } export function ChatProvider({ @@ -25,7 +24,7 @@ export function ChatProvider({ }: Pick<ConvoParams, 'convoId'> & {children: React.ReactNode}) { const {serviceUrl} = useDmServiceUrlStorage() const {getAgent} = useAgent() - const [service] = React.useState( + const [service] = useState( () => new Convo({ convoId, @@ -35,13 +34,13 @@ export function ChatProvider({ __tempFromUserDid: getAgent().session?.did!, }), ) - const [state, setState] = React.useState(service.state) + const [state, setState] = useState(service.state) - React.useEffect(() => { + useEffect(() => { service.initialize() }, [service]) - React.useEffect(() => { + useEffect(() => { const update = () => setState(service.state) service.on('update', update) return () => { @@ -49,9 +48,7 @@ export function ChatProvider({ } }, [service]) - return ( - <ChatContext.Provider value={{state, service}}> - {children} - </ChatContext.Provider> - ) + const value = useMemo(() => ({service, state}), [service, state]) + + return <ChatContext.Provider value={value}>{children}</ChatContext.Provider> } diff --git a/src/state/queries/messages/get-convo-for-members.ts b/src/state/queries/messages/get-convo-for-members.ts index 8a58a98d8..0a657c07e 100644 --- a/src/state/queries/messages/get-convo-for-members.ts +++ b/src/state/queries/messages/get-convo-for-members.ts @@ -1,6 +1,7 @@ import {BskyAgent, ChatBskyConvoGetConvoForMembers} from '@atproto-labs/api' import {useMutation, useQueryClient} from '@tanstack/react-query' +import {logger} from '#/logger' import {useDmServiceUrlStorage} from '#/screens/Messages/Temp/useDmServiceUrlStorage' import {RQKEY as CONVO_KEY} from './conversation' import {useHeaders} from './temp-headers' @@ -30,6 +31,9 @@ export function useGetConvoForMembers({ queryClient.setQueryData(CONVO_KEY(data.convo.id), data.convo) onSuccess?.(data) }, - onError, + onError: error => { + logger.error(error) + onError?.(error) + }, }) } diff --git a/src/state/queries/messages/leave-conversation.ts b/src/state/queries/messages/leave-conversation.ts new file mode 100644 index 000000000..0dd67fa0b --- /dev/null +++ b/src/state/queries/messages/leave-conversation.ts @@ -0,0 +1,68 @@ +import { + BskyAgent, + ChatBskyConvoLeaveConvo, + ChatBskyConvoListConvos, +} from '@atproto-labs/api' +import {useMutation, useQueryClient} from '@tanstack/react-query' + +import {logger} from '#/logger' +import {useDmServiceUrlStorage} from '#/screens/Messages/Temp/useDmServiceUrlStorage' +import {RQKEY as CONVO_LIST_KEY} from './list-converations' +import {useHeaders} from './temp-headers' + +export function useLeaveConvo( + convoId: string, + { + onSuccess, + onError, + }: { + onSuccess?: (data: ChatBskyConvoLeaveConvo.OutputSchema) => void + onError?: (error: Error) => void + }, +) { + const queryClient = useQueryClient() + const headers = useHeaders() + const {serviceUrl} = useDmServiceUrlStorage() + + return useMutation({ + mutationFn: async () => { + const agent = new BskyAgent({service: serviceUrl}) + const {data} = await agent.api.chat.bsky.convo.leaveConvo( + {convoId}, + {headers, encoding: 'application/json'}, + ) + + return data + }, + onMutate: () => { + queryClient.setQueryData( + CONVO_LIST_KEY, + (old?: { + pageParams: Array<string | undefined> + pages: Array<ChatBskyConvoListConvos.OutputSchema> + }) => { + console.log('old', old) + if (!old) return old + return { + ...old, + pages: old.pages.map(page => { + return { + ...page, + convos: page.convos.filter(convo => convo.id !== convoId), + } + }), + } + }, + ) + }, + onSuccess: data => { + queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY}) + onSuccess?.(data) + }, + onError: error => { + logger.error(error) + queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY}) + onError?.(error) + }, + }) +} diff --git a/src/state/queries/messages/mute-conversation.ts b/src/state/queries/messages/mute-conversation.ts new file mode 100644 index 000000000..4840c65ad --- /dev/null +++ b/src/state/queries/messages/mute-conversation.ts @@ -0,0 +1,84 @@ +import { + BskyAgent, + ChatBskyConvoMuteConvo, + ChatBskyConvoUnmuteConvo, +} from '@atproto-labs/api' +import {useMutation, useQueryClient} from '@tanstack/react-query' + +import {logger} from '#/logger' +import {useDmServiceUrlStorage} from '#/screens/Messages/Temp/useDmServiceUrlStorage' +import {RQKEY as CONVO_KEY} from './conversation' +import {RQKEY as CONVO_LIST_KEY} from './list-converations' +import {useHeaders} from './temp-headers' + +export function useMuteConvo( + convoId: string, + { + onSuccess, + onError, + }: { + onSuccess?: (data: ChatBskyConvoMuteConvo.OutputSchema) => void + onError?: (error: Error) => void + }, +) { + const queryClient = useQueryClient() + const headers = useHeaders() + const {serviceUrl} = useDmServiceUrlStorage() + + return useMutation({ + mutationFn: async () => { + const agent = new BskyAgent({service: serviceUrl}) + const {data} = await agent.api.chat.bsky.convo.muteConvo( + {convoId}, + {headers, encoding: 'application/json'}, + ) + + return data + }, + onSuccess: data => { + queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY}) + queryClient.invalidateQueries({queryKey: CONVO_KEY(convoId)}) + onSuccess?.(data) + }, + onError: error => { + logger.error(error) + onError?.(error) + }, + }) +} + +export function useUnmuteConvo( + convoId: string, + { + onSuccess, + onError, + }: { + onSuccess?: (data: ChatBskyConvoUnmuteConvo.OutputSchema) => void + onError?: (error: Error) => void + }, +) { + const queryClient = useQueryClient() + const headers = useHeaders() + const {serviceUrl} = useDmServiceUrlStorage() + + return useMutation({ + mutationFn: async () => { + const agent = new BskyAgent({service: serviceUrl}) + const {data} = await agent.api.chat.bsky.convo.unmuteConvo( + {convoId}, + {headers, encoding: 'application/json'}, + ) + + return data + }, + onSuccess: data => { + queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY}) + queryClient.invalidateQueries({queryKey: CONVO_KEY(convoId)}) + onSuccess?.(data) + }, + onError: error => { + logger.error(error) + onError?.(error) + }, + }) +} |