about summary refs log tree commit diff
path: root/src/view/com/composer/state.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/composer/state.ts')
-rw-r--r--src/view/com/composer/state.ts131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/view/com/composer/state.ts b/src/view/com/composer/state.ts
new file mode 100644
index 000000000..5588de1aa
--- /dev/null
+++ b/src/view/com/composer/state.ts
@@ -0,0 +1,131 @@
+import {ComposerImage, createInitialImages} from '#/state/gallery'
+import {ComposerOpts} from '#/state/shell/composer'
+
+type PostRecord = {
+  uri: string
+}
+
+type ImagesMedia = {
+  type: 'images'
+  images: ComposerImage[]
+  labels: string[]
+}
+
+type ComposerEmbed = {
+  // TODO: Other record types.
+  record: PostRecord | undefined
+  // TODO: Other media types.
+  media: ImagesMedia | undefined
+}
+
+export type ComposerState = {
+  // TODO: Other draft data.
+  embed: ComposerEmbed
+}
+
+export type ComposerAction =
+  | {type: 'embed_add_images'; images: ComposerImage[]}
+  | {type: 'embed_update_image'; image: ComposerImage}
+  | {type: 'embed_remove_image'; image: ComposerImage}
+
+const MAX_IMAGES = 4
+
+export function composerReducer(
+  state: ComposerState,
+  action: ComposerAction,
+): ComposerState {
+  switch (action.type) {
+    case 'embed_add_images': {
+      const prevMedia = state.embed.media
+      let nextMedia = prevMedia
+      if (!prevMedia) {
+        nextMedia = {
+          type: 'images',
+          images: action.images.slice(0, MAX_IMAGES),
+          labels: [],
+        }
+      } else if (prevMedia.type === 'images') {
+        nextMedia = {
+          ...prevMedia,
+          images: [...prevMedia.images, ...action.images].slice(0, MAX_IMAGES),
+        }
+      }
+      return {
+        ...state,
+        embed: {
+          ...state.embed,
+          media: nextMedia,
+        },
+      }
+    }
+    case 'embed_update_image': {
+      const prevMedia = state.embed.media
+      if (prevMedia?.type === 'images') {
+        const updatedImage = action.image
+        const nextMedia = {
+          ...prevMedia,
+          images: prevMedia.images.map(img => {
+            if (img.source.id === updatedImage.source.id) {
+              return updatedImage
+            }
+            return img
+          }),
+        }
+        return {
+          ...state,
+          embed: {
+            ...state.embed,
+            media: nextMedia,
+          },
+        }
+      }
+      return state
+    }
+    case 'embed_remove_image': {
+      const prevMedia = state.embed.media
+      if (prevMedia?.type === 'images') {
+        const removedImage = action.image
+        let nextMedia: ImagesMedia | undefined = {
+          ...prevMedia,
+          images: prevMedia.images.filter(img => {
+            return img.source.id !== removedImage.source.id
+          }),
+        }
+        if (nextMedia.images.length === 0) {
+          nextMedia = undefined
+        }
+        return {
+          ...state,
+          embed: {
+            ...state.embed,
+            media: nextMedia,
+          },
+        }
+      }
+      return state
+    }
+    default:
+      return state
+  }
+}
+
+export function createComposerState({
+  initImageUris,
+}: {
+  initImageUris: ComposerOpts['imageUris']
+}): ComposerState {
+  let media: ImagesMedia | undefined
+  if (initImageUris?.length) {
+    media = {
+      type: 'images',
+      images: createInitialImages(initImageUris),
+      labels: [],
+    }
+  }
+  return {
+    embed: {
+      record: undefined,
+      media,
+    },
+  }
+}