diff options
author | Samuel Newman <mozzius@protonmail.com> | 2024-05-14 18:55:43 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-14 18:55:43 +0100 |
commit | 9861494e341b482a522d0ecc6a2194bb12a769fb (patch) | |
tree | ea57b047639058f2b28ee9347cc2b811ff407095 /src/state/messages/message-drafts.tsx | |
parent | f147256fdca45d6b460f53aacc777c7a0957e4c6 (diff) | |
download | voidsky-9861494e341b482a522d0ecc6a2194bb12a769fb.tar.zst |
[🐴] Message drafts (#3993)
* drafts * don't throw if no convo ID * Remove labs package --------- Co-authored-by: Eric Bailey <git@esb.lol>
Diffstat (limited to 'src/state/messages/message-drafts.tsx')
-rw-r--r-- | src/state/messages/message-drafts.tsx | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/state/messages/message-drafts.tsx b/src/state/messages/message-drafts.tsx new file mode 100644 index 000000000..132e85967 --- /dev/null +++ b/src/state/messages/message-drafts.tsx @@ -0,0 +1,83 @@ +import React, {useEffect, useMemo, useReducer, useRef} from 'react' + +import {useCurrentConvoId} from './current-convo-id' + +const MessageDraftsContext = React.createContext<{ + state: State + dispatch: React.Dispatch<Actions> +} | null>(null) + +function useMessageDraftsContext() { + const ctx = React.useContext(MessageDraftsContext) + if (!ctx) { + throw new Error( + 'useMessageDrafts must be used within a MessageDraftsContext', + ) + } + return ctx +} + +export function useMessageDraft() { + const {currentConvoId} = useCurrentConvoId() + const {state, dispatch} = useMessageDraftsContext() + return useMemo( + () => ({ + getDraft: () => (currentConvoId && state[currentConvoId]) || '', + clearDraft: () => { + if (currentConvoId) { + dispatch({type: 'clear', convoId: currentConvoId}) + } + }, + }), + [state, dispatch, currentConvoId], + ) +} + +export function useSaveMessageDraft(message: string) { + const {currentConvoId} = useCurrentConvoId() + const {dispatch} = useMessageDraftsContext() + const messageRef = useRef(message) + messageRef.current = message + + useEffect(() => { + return () => { + if (currentConvoId) { + dispatch({ + type: 'set', + convoId: currentConvoId, + draft: messageRef.current, + }) + } + } + }, [currentConvoId, dispatch]) +} + +type State = {[convoId: string]: string} +type Actions = + | {type: 'set'; convoId: string; draft: string} + | {type: 'clear'; convoId: string} + +function reducer(state: State, action: Actions): State { + switch (action.type) { + case 'set': + return {...state, [action.convoId]: action.draft} + case 'clear': + return {...state, [action.convoId]: ''} + default: + return state + } +} + +export function MessageDraftsProvider({children}: {children: React.ReactNode}) { + const [state, dispatch] = useReducer(reducer, {}) + + const ctx = useMemo(() => { + return {state, dispatch} + }, [state]) + + return ( + <MessageDraftsContext.Provider value={ctx}> + {children} + </MessageDraftsContext.Provider> + ) +} |