about summary refs log tree commit diff
path: root/src/lib/api/index.ts
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2023-02-23 16:02:31 -0600
committerPaul Frazee <pfrazee@gmail.com>2023-02-23 16:02:31 -0600
commit4182edfd7e3333fcf31b94f2f091fe143945b809 (patch)
tree51fa2548f8138603d0f69ab7ff87d56c2d7b70ee /src/lib/api/index.ts
parent0f293ecf950c1563668a3a2d2fefb6e9d4585736 (diff)
downloadvoidsky-4182edfd7e3333fcf31b94f2f091fe143945b809.tar.zst
Implement image uploading in the web composer
Diffstat (limited to 'src/lib/api/index.ts')
-rw-r--r--src/lib/api/index.ts52
1 files changed, 43 insertions, 9 deletions
diff --git a/src/lib/api/index.ts b/src/lib/api/index.ts
index d800c376c..ae156928e 100644
--- a/src/lib/api/index.ts
+++ b/src/lib/api/index.ts
@@ -1,11 +1,16 @@
-import {AppBskyEmbedImages, AppBskyEmbedExternal} from '@atproto/api'
+import {
+  AppBskyEmbedImages,
+  AppBskyEmbedExternal,
+  ComAtprotoBlobUpload,
+} from '@atproto/api'
 import {AtUri} from '../../third-party/uri'
 import {RootStoreModel} from 'state/models/root-store'
 import {extractEntities} from 'lib/strings/rich-text-detection'
 import {isNetworkError} from 'lib/strings/errors'
 import {LinkMeta} from '../link-meta/link-meta'
-import {Image} from '../images'
+import {Image} from '../media/manip'
 import {RichText} from '../strings/rich-text'
+import {isWeb} from 'platform/detection'
 
 export interface ExternalEmbedDraft {
   uri: string
@@ -27,6 +32,25 @@ export async function resolveName(store: RootStoreModel, didOrHandle: string) {
   return res.data.did
 }
 
+export async function uploadBlob(
+  store: RootStoreModel,
+  blob: string,
+  encoding: string,
+): Promise<ComAtprotoBlobUpload.Response> {
+  if (isWeb) {
+    // `blob` should be a data uri
+    return store.api.com.atproto.blob.upload(convertDataURIToUint8Array(blob), {
+      encoding,
+    })
+  } else {
+    // `blob` should be a path to a file in the local FS
+    return store.api.com.atproto.blob.upload(
+      blob, // this will be special-cased by the fetch monkeypatch in /src/state/lib/api.ts
+      {encoding},
+    )
+  }
+}
+
 export async function post(
   store: RootStoreModel,
   rawText: string,
@@ -61,10 +85,7 @@ export async function post(
     let i = 1
     for (const image of images) {
       onStateChange?.(`Uploading image #${i++}...`)
-      const res = await store.api.com.atproto.blob.upload(
-        image, // this will be special-cased by the fetch monkeypatch in /src/state/lib/api.ts
-        {encoding: 'image/jpeg'},
-      )
+      const res = await uploadBlob(store, image, 'image/jpeg')
       embed.images.push({
         image: {
           cid: res.data.cid,
@@ -94,9 +115,10 @@ export async function post(
         )
       }
       if (encoding) {
-        const thumbUploadRes = await store.api.com.atproto.blob.upload(
-          extLink.localThumb.path, // this will be special-cased by the fetch monkeypatch in /src/state/lib/api.ts
-          {encoding},
+        const thumbUploadRes = await uploadBlob(
+          store,
+          extLink.localThumb.path,
+          encoding,
         )
         thumb = {
           cid: thumbUploadRes.data.cid,
@@ -199,3 +221,15 @@ export async function unfollow(store: RootStoreModel, followUri: string) {
     rkey: followUrip.rkey,
   })
 }
+
+// helpers
+// =
+
+function convertDataURIToUint8Array(uri: string): Uint8Array {
+  var raw = window.atob(uri.substring(uri.indexOf(';base64,') + 8))
+  var binary = new Uint8Array(new ArrayBuffer(raw.length))
+  for (let i = 0; i < raw.length; i++) {
+    binary[i] = raw.charCodeAt(i)
+  }
+  return binary
+}