mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React, {useEffect, useMemo, useReducer, useRef} from 'react'
2
3import {useCurrentConvoId} from './current-convo-id'
4
5const MessageDraftsContext = React.createContext<{
6 state: State
7 dispatch: React.Dispatch<Actions>
8} | null>(null)
9
10function useMessageDraftsContext() {
11 const ctx = React.useContext(MessageDraftsContext)
12 if (!ctx) {
13 throw new Error(
14 'useMessageDrafts must be used within a MessageDraftsContext',
15 )
16 }
17 return ctx
18}
19
20export function useMessageDraft() {
21 const {currentConvoId} = useCurrentConvoId()
22 const {state, dispatch} = useMessageDraftsContext()
23 return useMemo(
24 () => ({
25 getDraft: () => (currentConvoId && state[currentConvoId]) || '',
26 clearDraft: () => {
27 if (currentConvoId) {
28 dispatch({type: 'clear', convoId: currentConvoId})
29 }
30 },
31 }),
32 [state, dispatch, currentConvoId],
33 )
34}
35
36export function useSaveMessageDraft(message: string) {
37 const {currentConvoId} = useCurrentConvoId()
38 const {dispatch} = useMessageDraftsContext()
39 const messageRef = useRef(message)
40 messageRef.current = message
41
42 useEffect(() => {
43 return () => {
44 if (currentConvoId) {
45 dispatch({
46 type: 'set',
47 convoId: currentConvoId,
48 draft: messageRef.current,
49 })
50 }
51 }
52 }, [currentConvoId, dispatch])
53}
54
55type State = {[convoId: string]: string}
56type Actions =
57 | {type: 'set'; convoId: string; draft: string}
58 | {type: 'clear'; convoId: string}
59
60function reducer(state: State, action: Actions): State {
61 switch (action.type) {
62 case 'set':
63 return {...state, [action.convoId]: action.draft}
64 case 'clear':
65 return {...state, [action.convoId]: ''}
66 default:
67 return state
68 }
69}
70
71export function MessageDraftsProvider({children}: {children: React.ReactNode}) {
72 const [state, dispatch] = useReducer(reducer, {})
73
74 const ctx = useMemo(() => {
75 return {state, dispatch}
76 }, [state])
77
78 return (
79 <MessageDraftsContext.Provider value={ctx}>
80 {children}
81 </MessageDraftsContext.Provider>
82 )
83}