about summary refs log tree commit diff
path: root/src/state/models/media/image.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/models/media/image.ts')
-rw-r--r--src/state/models/media/image.ts85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/state/models/media/image.ts b/src/state/models/media/image.ts
new file mode 100644
index 000000000..584bf90cc
--- /dev/null
+++ b/src/state/models/media/image.ts
@@ -0,0 +1,85 @@
+import {Image as RNImage} from 'react-native-image-crop-picker'
+import {RootStoreModel} from 'state/index'
+import {compressAndResizeImageForPost} from 'lib/media/manip'
+import {makeAutoObservable, runInAction} from 'mobx'
+import {openCropper} from 'lib/media/picker'
+import {POST_IMG_MAX} from 'lib/constants'
+import {scaleDownDimensions} from 'lib/media/util'
+
+// TODO: EXIF embed
+// Cases to consider: ExternalEmbed
+export class ImageModel implements RNImage {
+  path: string
+  mime = 'image/jpeg'
+  width: number
+  height: number
+  size: number
+  cropped?: RNImage = undefined
+  compressed?: RNImage = undefined
+  scaledWidth: number = POST_IMG_MAX.width
+  scaledHeight: number = POST_IMG_MAX.height
+
+  constructor(public rootStore: RootStoreModel, image: RNImage) {
+    makeAutoObservable(this, {
+      rootStore: false,
+    })
+
+    this.path = image.path
+    this.width = image.width
+    this.height = image.height
+    this.size = image.size
+    this.calcScaledDimensions()
+  }
+
+  calcScaledDimensions() {
+    const {width, height} = scaleDownDimensions(
+      {width: this.width, height: this.height},
+      POST_IMG_MAX,
+    )
+
+    this.scaledWidth = width
+    this.scaledHeight = height
+  }
+
+  async crop() {
+    try {
+      const cropped = await openCropper(this.rootStore, {
+        mediaType: 'photo',
+        path: this.path,
+        freeStyleCropEnabled: true,
+        width: this.scaledWidth,
+        height: this.scaledHeight,
+      })
+
+      runInAction(() => {
+        this.cropped = cropped
+      })
+    } catch (err) {
+      this.rootStore.log.error('Failed to crop photo', err)
+    }
+
+    this.compress()
+  }
+
+  async compress() {
+    try {
+      const {width, height} = scaleDownDimensions(
+        this.cropped
+          ? {width: this.cropped.width, height: this.cropped.height}
+          : {width: this.width, height: this.height},
+        POST_IMG_MAX,
+      )
+      const compressed = await compressAndResizeImageForPost({
+        ...(this.cropped === undefined ? this : this.cropped),
+        width,
+        height,
+      })
+
+      runInAction(() => {
+        this.compressed = compressed
+      })
+    } catch (err) {
+      this.rootStore.log.error('Failed to compress photo', err)
+    }
+  }
+}