diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/hooks/usePermissions.ts | 29 | ||||
-rw-r--r-- | src/lib/hooks/usePermissions.web.ts | 8 | ||||
-rw-r--r-- | src/lib/media/video/compress.ts | 30 | ||||
-rw-r--r-- | src/lib/media/video/compress.web.ts | 28 | ||||
-rw-r--r-- | src/lib/media/video/errors.ts | 6 | ||||
-rw-r--r-- | src/lib/statsig/gates.ts | 1 |
6 files changed, 102 insertions, 0 deletions
diff --git a/src/lib/hooks/usePermissions.ts b/src/lib/hooks/usePermissions.ts index 9f1f8fb6f..d248e1975 100644 --- a/src/lib/hooks/usePermissions.ts +++ b/src/lib/hooks/usePermissions.ts @@ -48,6 +48,35 @@ export function usePhotoLibraryPermission() { return {requestPhotoAccessIfNeeded} } +export function useVideoLibraryPermission() { + const [res, requestPermission] = MediaLibrary.usePermissions({ + granularPermissions: ['video'], + }) + const requestVideoAccessIfNeeded = async () => { + // On the, we use <input type="file"> to produce a filepicker + // This does not need any permission granting. + if (isWeb) { + return true + } + + if (res?.granted) { + return true + } else if (!res || res.status === 'undetermined' || res?.canAskAgain) { + const {canAskAgain, granted, status} = await requestPermission() + + if (!canAskAgain && status === 'undetermined') { + openPermissionAlert('video library') + } + + return granted + } else { + openPermissionAlert('video library') + return false + } + } + return {requestVideoAccessIfNeeded} +} + export function useCameraPermission() { const [res, requestPermission] = Camera.useCameraPermissions() diff --git a/src/lib/hooks/usePermissions.web.ts b/src/lib/hooks/usePermissions.web.ts index c550a7d6d..b65bbc414 100644 --- a/src/lib/hooks/usePermissions.web.ts +++ b/src/lib/hooks/usePermissions.web.ts @@ -14,3 +14,11 @@ export function useCameraPermission() { return {requestCameraAccessIfNeeded} } + +export function useVideoLibraryPermission() { + const requestVideoAccessIfNeeded = async () => { + return true + } + + return {requestVideoAccessIfNeeded} +} diff --git a/src/lib/media/video/compress.ts b/src/lib/media/video/compress.ts new file mode 100644 index 000000000..60e5e94a0 --- /dev/null +++ b/src/lib/media/video/compress.ts @@ -0,0 +1,30 @@ +import {getVideoMetaData, Video} from 'react-native-compressor' + +export type CompressedVideo = { + uri: string + size: number +} + +export async function compressVideo( + file: string, + opts?: { + getCancellationId?: (id: string) => void + onProgress?: (progress: number) => void + }, +): Promise<CompressedVideo> { + const {onProgress, getCancellationId} = opts || {} + + const compressed = await Video.compress( + file, + { + getCancellationId, + compressionMethod: 'manual', + bitrate: 3_000_000, // 3mbps + maxSize: 1920, + }, + onProgress, + ) + + const info = await getVideoMetaData(compressed) + return {uri: compressed, size: info.size} +} diff --git a/src/lib/media/video/compress.web.ts b/src/lib/media/video/compress.web.ts new file mode 100644 index 000000000..968f2b157 --- /dev/null +++ b/src/lib/media/video/compress.web.ts @@ -0,0 +1,28 @@ +import {VideoTooLargeError} from 'lib/media/video/errors' + +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, + _callbacks?: { + onProgress: (progress: number) => void + }, +): Promise<CompressedVideo> { + const blob = await fetch(file).then(res => res.blob()) + const video = URL.createObjectURL(blob) + + if (blob.size > MAX_VIDEO_SIZE) { + throw new VideoTooLargeError() + } + + return { + size: blob.size, + uri: video, + } +} diff --git a/src/lib/media/video/errors.ts b/src/lib/media/video/errors.ts new file mode 100644 index 000000000..701a7e235 --- /dev/null +++ b/src/lib/media/video/errors.ts @@ -0,0 +1,6 @@ +export class VideoTooLargeError extends Error { + constructor() { + super('Videos cannot be larger than 100MB') + this.name = 'VideoTooLargeError' + } +} diff --git a/src/lib/statsig/gates.ts b/src/lib/statsig/gates.ts index 6a4081185..378b27349 100644 --- a/src/lib/statsig/gates.ts +++ b/src/lib/statsig/gates.ts @@ -11,3 +11,4 @@ export type Gate = | 'suggested_feeds_interstitial' | 'suggested_follows_interstitial' | 'ungroup_follow_backs' + | 'videos' |