Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[Videos] avoid using fetch for blob handling where possible (#5041)

* avoid using fetch where possible

* whoopsie wrong branch

* more import fixes

authored by

Samuel Newman and committed by
GitHub
8647c8e9 c70ec1ce

+47 -18
+1 -4
src/lib/media/video/compress.ts
··· 1 1 import {getVideoMetaData, Video} from 'react-native-compressor' 2 2 3 - export type CompressedVideo = { 4 - uri: string 5 - size: number 6 - } 3 + import {CompressedVideo} from './types' 7 4 8 5 export async function compressVideo( 9 6 file: string,
+33 -8
src/lib/media/video/compress.web.ts
··· 1 1 import {VideoTooLargeError} from 'lib/media/video/errors' 2 + import {CompressedVideo} from './types' 2 3 3 4 const MAX_VIDEO_SIZE = 1024 * 1024 * 100 // 100MB 4 - 5 - export type CompressedVideo = { 6 - uri: string 7 - size: number 8 - } 9 5 10 6 // doesn't actually compress, but throws if >100MB 11 7 export async function compressVideo( ··· 15 11 onProgress?: (progress: number) => void 16 12 }, 17 13 ): Promise<CompressedVideo> { 18 - const blob = await fetch(file).then(res => res.blob()) 19 - const video = URL.createObjectURL(blob) 14 + const {mimeType, base64} = parseDataUrl(file) 15 + const blob = base64ToBlob(base64, mimeType) 16 + const uri = URL.createObjectURL(blob) 20 17 21 18 if (blob.size > MAX_VIDEO_SIZE) { 22 19 throw new VideoTooLargeError() ··· 24 21 25 22 return { 26 23 size: blob.size, 27 - uri: video, 24 + uri, 25 + bytes: await blob.arrayBuffer(), 26 + } 27 + } 28 + 29 + function parseDataUrl(dataUrl: string) { 30 + const [mimeType, base64] = dataUrl.slice('data:'.length).split(';base64,') 31 + if (!mimeType || !base64) { 32 + throw new Error('Invalid data URL') 33 + } 34 + return {mimeType, base64} 35 + } 36 + 37 + function base64ToBlob(base64: string, mimeType: string) { 38 + const byteCharacters = atob(base64) 39 + const byteArrays = [] 40 + 41 + for (let offset = 0; offset < byteCharacters.length; offset += 512) { 42 + const slice = byteCharacters.slice(offset, offset + 512) 43 + const byteNumbers = new Array(slice.length) 44 + 45 + for (let i = 0; i < slice.length; i++) { 46 + byteNumbers[i] = slice.charCodeAt(i) 47 + } 48 + 49 + const byteArray = new Uint8Array(byteNumbers) 50 + byteArrays.push(byteArray) 28 51 } 52 + 53 + return new Blob(byteArrays, {type: mimeType}) 29 54 }
+6
src/lib/media/video/types.ts
··· 1 + export type CompressedVideo = { 2 + uri: string 3 + size: number 4 + // web only, can fall back to uri if missing 5 + bytes?: ArrayBuffer 6 + }
+2 -1
src/state/queries/video/compress-video.ts
··· 2 2 import {useMutation} from '@tanstack/react-query' 3 3 4 4 import {cancelable} from '#/lib/async/cancelable' 5 - import {CompressedVideo, compressVideo} from 'lib/media/video/compress' 5 + import {CompressedVideo} from '#/lib/media/video/types' 6 + import {compressVideo} from 'lib/media/video/compress' 6 7 7 8 export function useCompressVideoMutation({ 8 9 onProgress,
+1 -1
src/state/queries/video/video-upload.ts
··· 4 4 import {nanoid} from 'nanoid/non-secure' 5 5 6 6 import {cancelable} from '#/lib/async/cancelable' 7 - import {CompressedVideo} from '#/lib/media/video/compress' 7 + import {CompressedVideo} from '#/lib/media/video/types' 8 8 import {createVideoEndpointUrl} from '#/state/queries/video/util' 9 9 import {useAgent, useSession} from '#/state/session' 10 10 import {getServiceAuthAudFromUrl} from 'lib/strings/url-helpers'
+1 -1
src/state/queries/video/video-upload.web.ts
··· 3 3 import {nanoid} from 'nanoid/non-secure' 4 4 5 5 import {cancelable} from '#/lib/async/cancelable' 6 - import {CompressedVideo} from '#/lib/media/video/compress' 6 + import {CompressedVideo} from '#/lib/media/video/types' 7 7 import {createVideoEndpointUrl} from '#/state/queries/video/util' 8 8 import {useAgent, useSession} from '#/state/session' 9 9 import {getServiceAuthAudFromUrl} from 'lib/strings/url-helpers'
+1 -1
src/state/queries/video/video.ts
··· 6 6 import {QueryClient, useQuery, useQueryClient} from '@tanstack/react-query' 7 7 8 8 import {logger} from '#/logger' 9 - import {CompressedVideo} from 'lib/media/video/compress' 10 9 import {VideoTooLargeError} from 'lib/media/video/errors' 10 + import {CompressedVideo} from 'lib/media/video/types' 11 11 import {useCompressVideoMutation} from 'state/queries/video/compress-video' 12 12 import {useVideoAgent} from 'state/queries/video/util' 13 13 import {useUploadVideoMutation} from 'state/queries/video/video-upload'
+1 -1
src/view/com/composer/videos/VideoPreview.tsx
··· 4 4 import {ImagePickerAsset} from 'expo-image-picker' 5 5 import {useVideoPlayer, VideoView} from 'expo-video' 6 6 7 - import {CompressedVideo} from '#/lib/media/video/compress' 7 + import {CompressedVideo} from '#/lib/media/video/types' 8 8 import {ExternalEmbedRemoveBtn} from 'view/com/composer/ExternalEmbedRemoveBtn' 9 9 import {atoms as a, useTheme} from '#/alf' 10 10
+1 -1
src/view/com/composer/videos/VideoPreview.web.tsx
··· 2 2 import {View} from 'react-native' 3 3 import {ImagePickerAsset} from 'expo-image-picker' 4 4 5 - import {CompressedVideo} from '#/lib/media/video/compress' 5 + import {CompressedVideo} from '#/lib/media/video/types' 6 6 import {ExternalEmbedRemoveBtn} from 'view/com/composer/ExternalEmbedRemoveBtn' 7 7 import {atoms as a, useTheme} from '#/alf' 8 8