From 9861494e341b482a522d0ecc6a2194bb12a769fb Mon Sep 17 00:00:00 2001
From: Samuel Newman <mozzius@protonmail.com>
Date: Tue, 14 May 2024 18:55:43 +0100
Subject: [🐴] Message drafts (#3993)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* drafts

* don't throw if no convo ID

* Remove labs package

---------

Co-authored-by: Eric Bailey <git@esb.lol>
---
 src/state/messages/message-drafts.tsx | 83 +++++++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)
 create mode 100644 src/state/messages/message-drafts.tsx

(limited to 'src/state/messages/message-drafts.tsx')

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>
+  )
+}
-- 
cgit 1.4.1

