From 6c1429e759a1f3f0d8af3870547ef67c7551dacc Mon Sep 17 00:00:00 2001 From: Hailey Date: Mon, 8 Jul 2024 10:08:48 -0700 Subject: [PATCH] Revert "Video compression in composer (#4638)" This reverts commit 8f06ba70bb02a9dc3f09285719bd1585cc43aaeb. --- app.config.js | 2 - .../videoClip_stroke2_corner0_rounded.svg | 1 - package.json | 2 - src/components/icons/VideoClip.tsx | 5 -- src/lib/hooks/usePermissions.ts | 29 -------- src/lib/hooks/usePermissions.web.ts | 8 --- src/lib/media/video/compress.ts | 30 --------- src/lib/media/video/compress.web.ts | 28 -------- src/lib/media/video/errors.ts | 6 -- src/lib/statsig/gates.ts | 1 - src/view/com/composer/Composer.tsx | 42 ++---------- src/view/com/composer/ExternalEmbed.tsx | 28 +++++++- .../com/composer/ExternalEmbedRemoveBtn.tsx | 34 ---------- .../composer/char-progress/CharProgress.tsx | 7 +- .../com/composer/videos/SelectVideoBtn.tsx | 67 ------------------- src/view/com/composer/videos/VideoPreview.tsx | 39 ----------- .../com/composer/videos/VideoPreview.web.tsx | 27 -------- .../videos/VideoTranscodeBackdrop.tsx | 37 ---------- .../videos/VideoTranscodeBackdrop.web.tsx | 7 -- .../videos/VideoTranscodeProgress.tsx | 53 --------------- src/view/com/composer/videos/state.ts | 51 -------------- .../util/post-embeds/ExternalLinkEmbed.tsx | 2 +- yarn.lock | 10 --- 23 files changed, 33 insertions(+), 483 deletions(-) delete mode 100644 assets/icons/videoClip_stroke2_corner0_rounded.svg delete mode 100644 src/components/icons/VideoClip.tsx delete mode 100644 src/lib/media/video/compress.ts delete mode 100644 src/lib/media/video/compress.web.ts delete mode 100644 src/lib/media/video/errors.ts delete mode 100644 src/view/com/composer/ExternalEmbedRemoveBtn.tsx delete mode 100644 src/view/com/composer/videos/SelectVideoBtn.tsx delete mode 100644 src/view/com/composer/videos/VideoPreview.tsx delete mode 100644 src/view/com/composer/videos/VideoPreview.web.tsx delete mode 100644 src/view/com/composer/videos/VideoTranscodeBackdrop.tsx delete mode 100644 src/view/com/composer/videos/VideoTranscodeBackdrop.web.tsx delete mode 100644 src/view/com/composer/videos/VideoTranscodeProgress.tsx delete mode 100644 src/view/com/composer/videos/state.ts diff --git a/app.config.js b/app.config.js index 1467f762fd..4a44912289 100644 --- a/app.config.js +++ b/app.config.js @@ -211,8 +211,6 @@ module.exports = function (config) { sounds: PLATFORM === 'ios' ? ['assets/dm.aiff'] : ['assets/dm.mp3'], }, ], - 'expo-video', - 'react-native-compressor', './plugins/starterPackAppClipExtension/withStarterPackAppClip.js', './plugins/withAndroidManifestPlugin.js', './plugins/withAndroidManifestFCMIconPlugin.js', diff --git a/assets/icons/videoClip_stroke2_corner0_rounded.svg b/assets/icons/videoClip_stroke2_corner0_rounded.svg deleted file mode 100644 index fd4c08d478..0000000000 --- a/assets/icons/videoClip_stroke2_corner0_rounded.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/package.json b/package.json index 0ea23a2749..5f9f03457a 100644 --- a/package.json +++ b/package.json @@ -136,7 +136,6 @@ "expo-system-ui": "~3.0.4", "expo-task-manager": "~11.8.1", "expo-updates": "~0.25.14", - "expo-video": "^1.1.10", "expo-web-browser": "~13.0.3", "fast-text-encoding": "^1.0.6", "history": "^5.3.0", @@ -167,7 +166,6 @@ "react-dom": "^18.2.0", "react-keyed-flatten-children": "^3.0.0", "react-native": "0.74.1", - "react-native-compressor": "^1.8.24", "react-native-date-picker": "^4.4.2", "react-native-drawer-layout": "^4.0.0-alpha.3", "react-native-fs": "^2.20.0", diff --git a/src/components/icons/VideoClip.tsx b/src/components/icons/VideoClip.tsx deleted file mode 100644 index c2c13c4913..0000000000 --- a/src/components/icons/VideoClip.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import {createSinglePathSVG} from './TEMPLATE' - -export const VideoClip_Stroke2_Corner0_Rounded = createSinglePathSVG({ - path: 'M3 4a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4Zm2 1v2h2V5H5Zm4 0v6h6V5H9Zm8 0v2h2V5h-2Zm2 4h-2v2h2V9Zm0 4h-2v2.444h2V13Zm0 4.444h-2V19h2v-1.556ZM15 19v-6H9v6h6Zm-8 0v-2H5v2h2Zm-2-4h2v-2H5v2Zm0-4h2V9H5v2Z', -}) diff --git a/src/lib/hooks/usePermissions.ts b/src/lib/hooks/usePermissions.ts index d248e19759..9f1f8fb6f7 100644 --- a/src/lib/hooks/usePermissions.ts +++ b/src/lib/hooks/usePermissions.ts @@ -48,35 +48,6 @@ export function usePhotoLibraryPermission() { return {requestPhotoAccessIfNeeded} } -export function useVideoLibraryPermission() { - const [res, requestPermission] = MediaLibrary.usePermissions({ - granularPermissions: ['video'], - }) - const requestVideoAccessIfNeeded = async () => { - // On the, we use 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 b65bbc4141..c550a7d6df 100644 --- a/src/lib/hooks/usePermissions.web.ts +++ b/src/lib/hooks/usePermissions.web.ts @@ -14,11 +14,3 @@ 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 deleted file mode 100644 index 60e5e94a00..0000000000 --- a/src/lib/media/video/compress.ts +++ /dev/null @@ -1,30 +0,0 @@ -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 { - 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 deleted file mode 100644 index 968f2b157a..0000000000 --- a/src/lib/media/video/compress.web.ts +++ /dev/null @@ -1,28 +0,0 @@ -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 { - 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 deleted file mode 100644 index 701a7e2355..0000000000 --- a/src/lib/media/video/errors.ts +++ /dev/null @@ -1,6 +0,0 @@ -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 378b273494..6a4081185f 100644 --- a/src/lib/statsig/gates.ts +++ b/src/lib/statsig/gates.ts @@ -11,4 +11,3 @@ export type Gate = | 'suggested_feeds_interstitial' | 'suggested_follows_interstitial' | 'ungroup_follow_backs' - | 'videos' diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index c8a77385ea..9e2f77d4df 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -1,5 +1,4 @@ import React, { - Suspense, useCallback, useEffect, useImperativeHandle, @@ -43,7 +42,7 @@ import { } from '#/lib/gif-alt-text' import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED' import {LikelyType} from '#/lib/link-meta/link-meta' -import {logEvent, useGate} from '#/lib/statsig/statsig' +import {logEvent} from '#/lib/statsig/statsig' import {logger} from '#/logger' import {emitPostCreated} from '#/state/events' import {useModalControls} from '#/state/modals' @@ -97,10 +96,6 @@ import {SuggestedLanguage} from './select-language/SuggestedLanguage' import {TextInput, TextInputRef} from './text-input/TextInput' import {ThreadgateBtn} from './threadgate/ThreadgateBtn' import {useExternalLinkFetch} from './useExternalLinkFetch' -import {SelectVideoBtn} from './videos/SelectVideoBtn' -import {useVideoState} from './videos/state' -import {VideoPreview} from './videos/VideoPreview' -import {VideoTranscodeProgress} from './videos/VideoTranscodeProgress' import hairlineWidth = StyleSheet.hairlineWidth type CancelRef = { @@ -120,7 +115,6 @@ export const ComposePost = observer(function ComposePost({ }: Props & { cancelRef?: React.RefObject }) { - const gate = useGate() const {currentAccount} = useSession() const agent = useAgent() const {data: currentProfile} = useProfileQuery({did: currentAccount!.did}) @@ -162,14 +156,6 @@ export const ComposePost = observer(function ComposePost({ const [quote, setQuote] = useState( initQuote, ) - const { - video, - onSelectVideo, - videoPending, - videoProcessingData, - clearVideo, - videoProcessingProgress, - } = useVideoState({setError}) const {extLink, setExtLink} = useExternalLinkFetch({setQuote}) const [extGif, setExtGif] = useState() const [labels, setLabels] = useState([]) @@ -389,9 +375,8 @@ export const ComposePost = observer(function ComposePost({ ? _(msg`Write your reply`) : _(msg`What's up?`) - const canSelectImages = - gallery.size < 4 && !extLink && !video && !videoPending - const hasMedia = gallery.size > 0 || Boolean(extLink) || Boolean(video) + const canSelectImages = gallery.size < 4 && !extLink + const hasMedia = gallery.size > 0 || Boolean(extLink) const onEmojiButtonPress = useCallback(() => { openPicker?.(textInput.current?.getCursorPosition()) @@ -615,20 +600,7 @@ export const ComposePost = observer(function ComposePost({ setQuote(undefined)} /> )} - ) : null} - {videoPending && videoProcessingData ? ( - - ) : ( - video && ( - // remove suspense when we get rid of lazy - - - - ) - )} + ) : undefined} @@ -647,12 +619,6 @@ export const ComposePost = observer(function ComposePost({ ]}> - {gate('videos') && ( - - )} { const t = useTheme() + const {_} = useLingui() const linkInfo = React.useMemo( () => @@ -66,7 +70,25 @@ export const ExternalEmbed = ({ ) : null} - + + + ) } diff --git a/src/view/com/composer/ExternalEmbedRemoveBtn.tsx b/src/view/com/composer/ExternalEmbedRemoveBtn.tsx deleted file mode 100644 index 7742900a83..0000000000 --- a/src/view/com/composer/ExternalEmbedRemoveBtn.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react' -import {TouchableOpacity} from 'react-native' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -import {s} from 'lib/styles' - -export function ExternalEmbedRemoveBtn({onRemove}: {onRemove: () => void}) { - const {_} = useLingui() - - return ( - - - - ) -} diff --git a/src/view/com/composer/char-progress/CharProgress.tsx b/src/view/com/composer/char-progress/CharProgress.tsx index a205fe0963..a3fa78a59a 100644 --- a/src/view/com/composer/char-progress/CharProgress.tsx +++ b/src/view/com/composer/char-progress/CharProgress.tsx @@ -1,14 +1,13 @@ import React from 'react' import {View} from 'react-native' +import {Text} from '../../util/text/Text' // @ts-ignore no type definition -prf import ProgressCircle from 'react-native-progress/Circle' // @ts-ignore no type definition -prf import ProgressPie from 'react-native-progress/Pie' - -import {MAX_GRAPHEME_LENGTH} from 'lib/constants' -import {usePalette} from 'lib/hooks/usePalette' import {s} from 'lib/styles' -import {Text} from '../../util/text/Text' +import {usePalette} from 'lib/hooks/usePalette' +import {MAX_GRAPHEME_LENGTH} from 'lib/constants' const DANGER_LENGTH = MAX_GRAPHEME_LENGTH diff --git a/src/view/com/composer/videos/SelectVideoBtn.tsx b/src/view/com/composer/videos/SelectVideoBtn.tsx deleted file mode 100644 index 9c528a92e2..0000000000 --- a/src/view/com/composer/videos/SelectVideoBtn.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import React, {useCallback} from 'react' -import { - ImagePickerAsset, - launchImageLibraryAsync, - MediaTypeOptions, - UIImagePickerPreferredAssetRepresentationMode, -} from 'expo-image-picker' -import {msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -import {useVideoLibraryPermission} from '#/lib/hooks/usePermissions' -import {isNative} from '#/platform/detection' -import {atoms as a, useTheme} from '#/alf' -import {Button} from '#/components/Button' -import {VideoClip_Stroke2_Corner0_Rounded as VideoClipIcon} from '#/components/icons/VideoClip' - -const VIDEO_MAX_DURATION = 90 - -type Props = { - onSelectVideo: (video: ImagePickerAsset) => void - disabled?: boolean -} - -export function SelectVideoBtn({onSelectVideo, disabled}: Props) { - const {_} = useLingui() - const t = useTheme() - const {requestVideoAccessIfNeeded} = useVideoLibraryPermission() - - const onPressSelectVideo = useCallback(async () => { - if (isNative && !(await requestVideoAccessIfNeeded())) { - return - } - - const response = await launchImageLibraryAsync({ - exif: false, - mediaTypes: MediaTypeOptions.Videos, - videoMaxDuration: VIDEO_MAX_DURATION, - quality: 1, - legacy: true, - preferredAssetRepresentationMode: - UIImagePickerPreferredAssetRepresentationMode.Current, - }) - if (response.assets && response.assets.length > 0) { - onSelectVideo(response.assets[0]) - } - }, [onSelectVideo, requestVideoAccessIfNeeded]) - - return ( - <> - - - ) -} diff --git a/src/view/com/composer/videos/VideoPreview.tsx b/src/view/com/composer/videos/VideoPreview.tsx deleted file mode 100644 index b04cdf1c8b..0000000000 --- a/src/view/com/composer/videos/VideoPreview.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/* eslint-disable @typescript-eslint/no-shadow */ -import React from 'react' -import {View} from 'react-native' -import {useVideoPlayer, VideoView} from 'expo-video' - -import {CompressedVideo} from '#/lib/media/video/compress' -import {ExternalEmbedRemoveBtn} from 'view/com/composer/ExternalEmbedRemoveBtn' -import {atoms as a} from '#/alf' - -export function VideoPreview({ - video, - clear, -}: { - video: CompressedVideo - clear: () => void -}) { - const player = useVideoPlayer(video.uri, player => { - player.loop = true - player.play() - }) - - return ( - - - - - ) -} diff --git a/src/view/com/composer/videos/VideoPreview.web.tsx b/src/view/com/composer/videos/VideoPreview.web.tsx deleted file mode 100644 index 223dbd4244..0000000000 --- a/src/view/com/composer/videos/VideoPreview.web.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react' -import {View} from 'react-native' - -import {CompressedVideo} from '#/lib/media/video/compress' -import {ExternalEmbedRemoveBtn} from 'view/com/composer/ExternalEmbedRemoveBtn' -import {atoms as a} from '#/alf' - -export function VideoPreview({ - video, - clear, -}: { - video: CompressedVideo - clear: () => void -}) { - return ( - - - - ) -} diff --git a/src/view/com/composer/videos/VideoTranscodeBackdrop.tsx b/src/view/com/composer/videos/VideoTranscodeBackdrop.tsx deleted file mode 100644 index 1f41736420..0000000000 --- a/src/view/com/composer/videos/VideoTranscodeBackdrop.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import React, {useEffect} from 'react' -import {clearCache, createVideoThumbnail} from 'react-native-compressor' -import Animated, {FadeIn} from 'react-native-reanimated' -import {Image} from 'expo-image' -import {useQuery} from '@tanstack/react-query' - -import {atoms as a} from '#/alf' - -export function VideoTranscodeBackdrop({uri}: {uri: string}) { - const {data: thumbnail} = useQuery({ - queryKey: ['thumbnail', uri], - queryFn: async () => { - return await createVideoThumbnail(uri) - }, - }) - - useEffect(() => { - return () => { - clearCache() - } - }, []) - - return ( - - {thumbnail && ( - - )} - - ) -} diff --git a/src/view/com/composer/videos/VideoTranscodeBackdrop.web.tsx b/src/view/com/composer/videos/VideoTranscodeBackdrop.web.tsx deleted file mode 100644 index 9b580fdf2a..0000000000 --- a/src/view/com/composer/videos/VideoTranscodeBackdrop.web.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -export function VideoTranscodeBackdrop({uri}: {uri: string}) { - return ( -