about summary refs log tree commit diff
path: root/src/view/com/composer/state/composer.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/composer/state/composer.ts')
-rw-r--r--src/view/com/composer/state/composer.ts81
1 files changed, 80 insertions, 1 deletions
diff --git a/src/view/com/composer/state/composer.ts b/src/view/com/composer/state/composer.ts
index 4c94d5eac..27bed6d44 100644
--- a/src/view/com/composer/state/composer.ts
+++ b/src/view/com/composer/state/composer.ts
@@ -85,7 +85,9 @@ export type ThreadDraft = {
 
 export type ComposerState = {
   thread: ThreadDraft
-  activePostIndex: number // TODO: Add actions to update this.
+  activePostIndex: number
+  mutableNeedsFocusActive: boolean
+  mutableNeedsScrollToBottom: boolean
 }
 
 export type ComposerAction =
@@ -96,6 +98,17 @@ export type ComposerAction =
       postId: string
       postAction: PostAction
     }
+  | {
+      type: 'add_post'
+    }
+  | {
+      type: 'remove_post'
+      postId: string
+    }
+  | {
+      type: 'focus_post'
+      postId: string
+    }
 
 export const MAX_IMAGES = 4
 
@@ -142,6 +155,69 @@ export function composerReducer(
         },
       }
     }
+    case 'add_post': {
+      const activePostIndex = state.activePostIndex
+      const isAtTheEnd = activePostIndex === state.thread.posts.length - 1
+      const nextPosts = [...state.thread.posts]
+      nextPosts.splice(activePostIndex + 1, 0, {
+        id: nanoid(),
+        richtext: new RichText({text: ''}),
+        shortenedGraphemeLength: 0,
+        labels: [],
+        embed: {
+          quote: undefined,
+          media: undefined,
+          link: undefined,
+        },
+      })
+      return {
+        ...state,
+        mutableNeedsScrollToBottom: isAtTheEnd,
+        thread: {
+          ...state.thread,
+          posts: nextPosts,
+        },
+      }
+    }
+    case 'remove_post': {
+      if (state.thread.posts.length < 2) {
+        return state
+      }
+      let nextActivePostIndex = state.activePostIndex
+      const indexToRemove = state.thread.posts.findIndex(
+        p => p.id === action.postId,
+      )
+      let nextPosts = [...state.thread.posts]
+      if (indexToRemove !== -1) {
+        const postToRemove = state.thread.posts[indexToRemove]
+        if (postToRemove.embed.media?.type === 'video') {
+          postToRemove.embed.media.video.abortController.abort()
+        }
+        nextPosts.splice(indexToRemove, 1)
+        nextActivePostIndex = Math.max(0, indexToRemove - 1)
+      }
+      return {
+        ...state,
+        activePostIndex: nextActivePostIndex,
+        mutableNeedsFocusActive: true,
+        thread: {
+          ...state.thread,
+          posts: nextPosts,
+        },
+      }
+    }
+    case 'focus_post': {
+      const nextActivePostIndex = state.thread.posts.findIndex(
+        p => p.id === action.postId,
+      )
+      if (nextActivePostIndex === -1) {
+        return state
+      }
+      return {
+        ...state,
+        activePostIndex: nextActivePostIndex,
+      }
+    }
   }
 }
 
@@ -275,6 +351,7 @@ function postReducer(state: PostDraft, action: PostAction): PostDraft {
       const prevMedia = state.embed.media
       let nextMedia = prevMedia
       if (prevMedia?.type === 'video') {
+        prevMedia.video.abortController.abort()
         nextMedia = undefined
       }
       let nextLabels = state.labels
@@ -436,6 +513,8 @@ export function createComposerState({
   })
   return {
     activePostIndex: 0,
+    mutableNeedsFocusActive: false,
+    mutableNeedsScrollToBottom: false,
     thread: {
       posts: [
         {