1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
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)
MessageDraftsContext.displayName = 'MessageDraftsContext'
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>
)
}
|