about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2024-08-30 19:05:38 +0100
committerGitHub <noreply@github.com>2024-08-30 19:05:38 +0100
commit8647c8e9f589401b1763fa8af596a6fd12bad04e (patch)
tree488475f9aec7423c9d8d6c230c04a20642cdf3fd /src
parentc70ec1ce1aff6072934add1f543576d5200c1b02 (diff)
downloadvoidsky-8647c8e9f589401b1763fa8af596a6fd12bad04e.tar.zst
[Videos] avoid using fetch for blob handling where possible (#5041)
* avoid using fetch where possible

* whoopsie wrong branch

* more import fixes
Diffstat (limited to 'src')
-rw-r--r--src/lib/media/video/compress.ts5
-rw-r--r--src/lib/media/video/compress.web.ts41
-rw-r--r--src/lib/media/video/types.ts6
-rw-r--r--src/state/queries/video/compress-video.ts3
-rw-r--r--src/state/queries/video/video-upload.ts2
-rw-r--r--src/state/queries/video/video-upload.web.ts2
-rw-r--r--src/state/queries/video/video.ts2
-rw-r--r--src/view/com/composer/videos/VideoPreview.tsx2
-rw-r--r--src/view/com/composer/videos/VideoPreview.web.tsx2
9 files changed, 47 insertions, 18 deletions
diff --git a/src/lib/media/video/compress.ts b/src/lib/media/video/compress.ts
index 957617596..709f2a77a 100644
--- a/src/lib/media/video/compress.ts
+++ b/src/lib/media/video/compress.ts
@@ -1,9 +1,6 @@
 import {getVideoMetaData, Video} from 'react-native-compressor'
 
-export type CompressedVideo = {
-  uri: string
-  size: number
-}
+import {CompressedVideo} from './types'
 
 export async function compressVideo(
   file: string,
diff --git a/src/lib/media/video/compress.web.ts b/src/lib/media/video/compress.web.ts
index 11ccb5104..c08702534 100644
--- a/src/lib/media/video/compress.web.ts
+++ b/src/lib/media/video/compress.web.ts
@@ -1,12 +1,8 @@
 import {VideoTooLargeError} from 'lib/media/video/errors'
+import {CompressedVideo} from './types'
 
 const MAX_VIDEO_SIZE = 1024 * 1024 * 100 // 100MB
 
-export type CompressedVideo = {
-  uri: string
-  size: number
-}
-
 // doesn't actually compress, but throws if >100MB
 export async function compressVideo(
   file: string,
@@ -15,8 +11,9 @@ export async function compressVideo(
     onProgress?: (progress: number) => void
   },
 ): Promise<CompressedVideo> {
-  const blob = await fetch(file).then(res => res.blob())
-  const video = URL.createObjectURL(blob)
+  const {mimeType, base64} = parseDataUrl(file)
+  const blob = base64ToBlob(base64, mimeType)
+  const uri = URL.createObjectURL(blob)
 
   if (blob.size > MAX_VIDEO_SIZE) {
     throw new VideoTooLargeError()
@@ -24,6 +21,34 @@ export async function compressVideo(
 
   return {
     size: blob.size,
-    uri: video,
+    uri,
+    bytes: await blob.arrayBuffer(),
+  }
+}
+
+function parseDataUrl(dataUrl: string) {
+  const [mimeType, base64] = dataUrl.slice('data:'.length).split(';base64,')
+  if (!mimeType || !base64) {
+    throw new Error('Invalid data URL')
+  }
+  return {mimeType, base64}
+}
+
+function base64ToBlob(base64: string, mimeType: string) {
+  const byteCharacters = atob(base64)
+  const byteArrays = []
+
+  for (let offset = 0; offset < byteCharacters.length; offset += 512) {
+    const slice = byteCharacters.slice(offset, offset + 512)
+    const byteNumbers = new Array(slice.length)
+
+    for (let i = 0; i < slice.length; i++) {
+      byteNumbers[i] = slice.charCodeAt(i)
+    }
+
+    const byteArray = new Uint8Array(byteNumbers)
+    byteArrays.push(byteArray)
   }
+
+  return new Blob(byteArrays, {type: mimeType})
 }
diff --git a/src/lib/media/video/types.ts b/src/lib/media/video/types.ts
new file mode 100644
index 000000000..ba0070054
--- /dev/null
+++ b/src/lib/media/video/types.ts
@@ -0,0 +1,6 @@
+export type CompressedVideo = {
+  uri: string
+  size: number
+  // web only, can fall back to uri if missing
+  bytes?: ArrayBuffer
+}
diff --git a/src/state/queries/video/compress-video.ts b/src/state/queries/video/compress-video.ts
index a4c17eace..533b58416 100644
--- a/src/state/queries/video/compress-video.ts
+++ b/src/state/queries/video/compress-video.ts
@@ -2,7 +2,8 @@ import {ImagePickerAsset} from 'expo-image-picker'
 import {useMutation} from '@tanstack/react-query'
 
 import {cancelable} from '#/lib/async/cancelable'
-import {CompressedVideo, compressVideo} from 'lib/media/video/compress'
+import {CompressedVideo} from '#/lib/media/video/types'
+import {compressVideo} from 'lib/media/video/compress'
 
 export function useCompressVideoMutation({
   onProgress,
diff --git a/src/state/queries/video/video-upload.ts b/src/state/queries/video/video-upload.ts
index 5dde5c31b..6fdd9d5bb 100644
--- a/src/state/queries/video/video-upload.ts
+++ b/src/state/queries/video/video-upload.ts
@@ -4,7 +4,7 @@ import {useMutation} from '@tanstack/react-query'
 import {nanoid} from 'nanoid/non-secure'
 
 import {cancelable} from '#/lib/async/cancelable'
-import {CompressedVideo} from '#/lib/media/video/compress'
+import {CompressedVideo} from '#/lib/media/video/types'
 import {createVideoEndpointUrl} from '#/state/queries/video/util'
 import {useAgent, useSession} from '#/state/session'
 import {getServiceAuthAudFromUrl} from 'lib/strings/url-helpers'
diff --git a/src/state/queries/video/video-upload.web.ts b/src/state/queries/video/video-upload.web.ts
index a8494970a..c3ad39268 100644
--- a/src/state/queries/video/video-upload.web.ts
+++ b/src/state/queries/video/video-upload.web.ts
@@ -3,7 +3,7 @@ import {useMutation} from '@tanstack/react-query'
 import {nanoid} from 'nanoid/non-secure'
 
 import {cancelable} from '#/lib/async/cancelable'
-import {CompressedVideo} from '#/lib/media/video/compress'
+import {CompressedVideo} from '#/lib/media/video/types'
 import {createVideoEndpointUrl} from '#/state/queries/video/util'
 import {useAgent, useSession} from '#/state/session'
 import {getServiceAuthAudFromUrl} from 'lib/strings/url-helpers'
diff --git a/src/state/queries/video/video.ts b/src/state/queries/video/video.ts
index f787a6af0..3c5094c71 100644
--- a/src/state/queries/video/video.ts
+++ b/src/state/queries/video/video.ts
@@ -6,8 +6,8 @@ import {useLingui} from '@lingui/react'
 import {QueryClient, useQuery, useQueryClient} from '@tanstack/react-query'
 
 import {logger} from '#/logger'
-import {CompressedVideo} from 'lib/media/video/compress'
 import {VideoTooLargeError} from 'lib/media/video/errors'
+import {CompressedVideo} from 'lib/media/video/types'
 import {useCompressVideoMutation} from 'state/queries/video/compress-video'
 import {useVideoAgent} from 'state/queries/video/util'
 import {useUploadVideoMutation} from 'state/queries/video/video-upload'
diff --git a/src/view/com/composer/videos/VideoPreview.tsx b/src/view/com/composer/videos/VideoPreview.tsx
index 7e43dcd65..994076273 100644
--- a/src/view/com/composer/videos/VideoPreview.tsx
+++ b/src/view/com/composer/videos/VideoPreview.tsx
@@ -4,7 +4,7 @@ import {View} from 'react-native'
 import {ImagePickerAsset} from 'expo-image-picker'
 import {useVideoPlayer, VideoView} from 'expo-video'
 
-import {CompressedVideo} from '#/lib/media/video/compress'
+import {CompressedVideo} from '#/lib/media/video/types'
 import {ExternalEmbedRemoveBtn} from 'view/com/composer/ExternalEmbedRemoveBtn'
 import {atoms as a, useTheme} from '#/alf'
 
diff --git a/src/view/com/composer/videos/VideoPreview.web.tsx b/src/view/com/composer/videos/VideoPreview.web.tsx
index 5bf4d2a7f..8556640b7 100644
--- a/src/view/com/composer/videos/VideoPreview.web.tsx
+++ b/src/view/com/composer/videos/VideoPreview.web.tsx
@@ -2,7 +2,7 @@ import React, {useEffect, useRef} from 'react'
 import {View} from 'react-native'
 import {ImagePickerAsset} from 'expo-image-picker'
 
-import {CompressedVideo} from '#/lib/media/video/compress'
+import {CompressedVideo} from '#/lib/media/video/types'
 import {ExternalEmbedRemoveBtn} from 'view/com/composer/ExternalEmbedRemoveBtn'
 import {atoms as a, useTheme} from '#/alf'