From bab44a5a1344f56b90d76e6c09d3066ba4d2ef23 Mon Sep 17 00:00:00 2001
From: dan <dan.abramov@gmail.com>
Date: Tue, 29 Oct 2024 20:27:44 +0000
Subject: Refactor composer state for threads (#5945)

* Refactor composer state for threads

* Remove unnecessary default case

TS can see it's exhaustive.
---
 src/view/com/composer/Composer.tsx | 61 +++++++++++++++++++++++++-------------
 1 file changed, 41 insertions(+), 20 deletions(-)

(limited to 'src/view/com/composer/Composer.tsx')

diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx
index 8fdc62bc3..214f3605e 100644
--- a/src/view/com/composer/Composer.tsx
+++ b/src/view/com/composer/Composer.tsx
@@ -114,11 +114,13 @@ import {Text as NewText} from '#/components/Typography'
 import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet'
 import {
   ComposerAction,
-  ComposerDraft,
   composerReducer,
   createComposerState,
   EmbedDraft,
   MAX_IMAGES,
+  PostAction,
+  PostDraft,
+  ThreadDraft,
 } from './state/composer'
 import {NO_VIDEO, NoVideoState, processVideo, VideoState} from './state/video'
 
@@ -161,11 +163,21 @@ export const ComposePost = ({
   const [publishingStage, setPublishingStage] = useState('')
   const [error, setError] = useState('')
 
-  const [draft, dispatch] = useReducer(
+  const [composerState, composerDispatch] = useReducer(
     composerReducer,
     {initImageUris, initQuoteUri: initQuote?.uri, initText, initMention},
     createComposerState,
   )
+
+  // TODO: Display drafts for other posts in the thread.
+  const draft = composerState.thread.posts[composerState.activePostIndex]
+  const dispatch = useCallback((postAction: PostAction) => {
+    composerDispatch({
+      type: 'update_post',
+      postAction,
+    })
+  }, [])
+
   const richtext = draft.richtext
   let quote: string | undefined
   if (draft.embed.quote) {
@@ -207,7 +219,7 @@ export const ComposePost = ({
         _,
       )
     },
-    [_, agent, currentDid],
+    [_, agent, currentDid, dispatch],
   )
 
   // Whenever we receive an initial video uri, we should immediately run compression if necessary
@@ -333,7 +345,7 @@ export const ComposePost = ({
       try {
         postUri = (
           await apilib.post(agent, queryClient, {
-            draft: draft,
+            thread: composerState.thread,
             replyTo: replyTo?.uri,
             onStateChange: setPublishingStage,
             langs: toPostLanguages(langPrefs.postLanguage),
@@ -409,7 +421,7 @@ export const ComposePost = ({
     [
       _,
       agent,
-      draft,
+      composerState.thread,
       extLink,
       images,
       canPost,
@@ -504,8 +516,9 @@ export const ComposePost = ({
 
           <ComposerPills
             isReply={!!replyTo}
-            draft={draft}
-            dispatch={dispatch}
+            post={draft}
+            thread={composerState.thread}
+            dispatch={composerDispatch}
             bottomBarAnimatedStyle={bottomBarAnimatedStyle}
           />
 
@@ -543,8 +556,8 @@ function ComposerPost({
   onError,
   onPublish,
 }: {
-  draft: ComposerDraft
-  dispatch: (action: ComposerAction) => void
+  draft: PostDraft
+  dispatch: (action: PostAction) => void
   textInput: React.Ref<TextInputRef>
   isReply: boolean
   canRemoveQuote: boolean
@@ -736,7 +749,7 @@ function ComposerEmbeds({
   canRemoveQuote,
 }: {
   embed: EmbedDraft
-  dispatch: (action: ComposerAction) => void
+  dispatch: (action: PostAction) => void
   clearVideo: () => void
   canRemoveQuote: boolean
 }) {
@@ -850,19 +863,21 @@ function ComposerEmbeds({
 
 function ComposerPills({
   isReply,
-  draft,
+  thread,
+  post,
   dispatch,
   bottomBarAnimatedStyle,
 }: {
   isReply: boolean
-  draft: ComposerDraft
+  thread: ThreadDraft
+  post: PostDraft
   dispatch: (action: ComposerAction) => void
   bottomBarAnimatedStyle: StyleProp<ViewStyle>
 }) {
   const t = useTheme()
-  const media = draft.embed.media
+  const media = post.embed.media
   const hasMedia = media?.type === 'images' || media?.type === 'video'
-  const hasLink = !!draft.embed.link
+  const hasLink = !!post.embed.link
 
   // Don't render anything if no pills are going to be displayed
   if (isReply && !hasMedia && !hasLink) {
@@ -879,11 +894,11 @@ function ComposerPills({
         showsHorizontalScrollIndicator={false}>
         {isReply ? null : (
           <ThreadgateBtn
-            postgate={draft.postgate}
+            postgate={thread.postgate}
             onChangePostgate={nextPostgate => {
               dispatch({type: 'update_postgate', postgate: nextPostgate})
             }}
-            threadgateAllowUISettings={draft.threadgate}
+            threadgateAllowUISettings={thread.threadgate}
             onChangeThreadgateAllowUISettings={nextThreadgate => {
               dispatch({
                 type: 'update_threadgate',
@@ -895,9 +910,15 @@ function ComposerPills({
         )}
         {hasMedia || hasLink ? (
           <LabelsBtn
-            labels={draft.labels}
+            labels={post.labels}
             onChange={nextLabels => {
-              dispatch({type: 'update_labels', labels: nextLabels})
+              dispatch({
+                type: 'update_post',
+                postAction: {
+                  type: 'update_labels',
+                  labels: nextLabels,
+                },
+              })
             }}
           />
         ) : null}
@@ -914,8 +935,8 @@ function ComposerFooter({
   onError,
   onSelectVideo,
 }: {
-  draft: ComposerDraft
-  dispatch: (action: ComposerAction) => void
+  draft: PostDraft
+  dispatch: (action: PostAction) => void
   graphemeLength: number
   onEmojiButtonPress: () => void
   onError: (error: string) => void
-- 
cgit 1.4.1

