Page MenuHomePhabricator

D7226.id24487.diff
No OneTemporary

D7226.id24487.diff

diff --git a/native/media/video-playback-modal.react.js b/native/media/video-playback-modal.react.js
--- a/native/media/video-playback-modal.react.js
+++ b/native/media/video-playback-modal.react.js
@@ -5,6 +5,7 @@
import * as React from 'react';
import { useState } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
+import filesystem from 'react-native-fs';
import { TapGestureHandler } from 'react-native-gesture-handler';
import * as Progress from 'react-native-progress';
import Animated from 'react-native-reanimated';
@@ -14,6 +15,7 @@
import { useIsAppBackgroundedOrInactive } from 'lib/shared/lifecycle-utils.js';
import type { MediaInfo } from 'lib/types/media-types.js';
+import { decryptMedia } from './encryption-utils.js';
import { formatDuration } from './video-utils.js';
import ConnectedStatusBar from '../connected-status-bar.react.js';
import type { AppNavigationProp } from '../navigation/app-navigator.react.js';
@@ -76,6 +78,41 @@
function VideoPlaybackModal(props: Props): React.Node {
const { mediaInfo } = props.route.params;
+ const { uri, holder, encryptionKey } = mediaInfo;
+ const [videoSource, setVideoSource] = React.useState(
+ uri ? { uri } : undefined,
+ );
+
+ React.useEffect(() => {
+ // skip for unencrypted videos
+ if (!holder || !encryptionKey) {
+ return;
+ }
+
+ let isMounted = true;
+ let uriToDispose;
+ setVideoSource(undefined);
+
+ const loadDecrypted = async () => {
+ const { result } = await decryptMedia(holder, encryptionKey, {
+ destination: 'file',
+ });
+ if (result.success && isMounted) {
+ uriToDispose = result.uri;
+ setVideoSource({ uri: result.uri });
+ }
+ };
+ loadDecrypted();
+
+ return () => {
+ isMounted = false;
+ if (uriToDispose) {
+ // remove the temporary file created by decryptMedia
+ filesystem.unlink(uriToDispose);
+ }
+ };
+ }, [holder, encryptionKey]);
+
const closeButtonX = useValue(-1);
const closeButtonY = useValue(-1);
const closeButtonWidth = useValue(-1);
@@ -517,14 +554,7 @@
}
}, [backgroundedOrInactive, controlsShowing]);
- const {
- navigation,
- route: {
- params: {
- mediaInfo: { uri: videoUri },
- },
- },
- } = props;
+ const { navigation } = props;
const togglePlayback = React.useCallback(() => {
setPaused(!paused);
@@ -573,52 +603,59 @@
styles.contentContainer,
]);
- const controls = (
- <Animated.View
- style={[styles.controls, { opacity: controlsOpacity }]}
- pointerEvents={controlsEnabled ? 'box-none' : 'none'}
- >
- <SafeAreaView style={styles.fill}>
- <View style={styles.fill}>
- <View style={styles.header}>
- <View style={styles.closeButton}>
+ let controls;
+ if (videoSource) {
+ controls = (
+ <Animated.View
+ style={[styles.controls, { opacity: controlsOpacity }]}
+ pointerEvents={controlsEnabled ? 'box-none' : 'none'}
+ >
+ <SafeAreaView style={styles.fill}>
+ <View style={styles.fill}>
+ <View style={styles.header}>
+ <View style={styles.closeButton}>
+ <TouchableOpacity
+ onPress={navigation.goBackOnce}
+ ref={(closeButtonRef: any)}
+ onLayout={onCloseButtonLayout}
+ >
+ <Icon name="close" size={30} style={styles.iconButton} />
+ </TouchableOpacity>
+ </View>
+ </View>
+ <View
+ style={styles.footer}
+ ref={footerRef}
+ onLayout={onFooterLayout}
+ >
<TouchableOpacity
- onPress={navigation.goBackOnce}
- ref={(closeButtonRef: any)}
- onLayout={onCloseButtonLayout}
+ onPress={togglePlayback}
+ style={styles.playPauseButton}
>
- <Icon name="close" size={30} style={styles.iconButton} />
+ <Icon
+ name={paused ? 'play' : 'pause'}
+ size={28}
+ style={styles.iconButton}
+ />
</TouchableOpacity>
+ <View style={styles.progressBar}>
+ <Progress.Bar
+ progress={percentElapsed / 100}
+ height={4}
+ width={null}
+ color={styles.progressBar.color}
+ style={styles.expand}
+ />
+ </View>
+ <Text style={styles.durationText}>
+ {timeElapsed} / {totalDuration}
+ </Text>
</View>
</View>
- <View style={styles.footer} ref={footerRef} onLayout={onFooterLayout}>
- <TouchableOpacity
- onPress={togglePlayback}
- style={styles.playPauseButton}
- >
- <Icon
- name={paused ? 'play' : 'pause'}
- size={28}
- style={styles.iconButton}
- />
- </TouchableOpacity>
- <View style={styles.progressBar}>
- <Progress.Bar
- progress={percentElapsed / 100}
- height={4}
- width={null}
- color={styles.progressBar.color}
- style={styles.expand}
- />
- </View>
- <Text style={styles.durationText}>
- {timeElapsed} / {totalDuration}
- </Text>
- </View>
- </View>
- </SafeAreaView>
- </Animated.View>
- );
+ </SafeAreaView>
+ </Animated.View>
+ );
+ }
let spinner;
if (spinnerVisible) {
@@ -632,6 +669,21 @@
);
}
+ let videoPlayer;
+ if (videoSource) {
+ videoPlayer = (
+ <Video
+ source={videoSource}
+ ref={videoRef}
+ style={styles.backgroundVideo}
+ paused={paused}
+ onProgress={progressCallback}
+ onEnd={resetVideo}
+ onReadyForDisplay={readyForDisplayCallback}
+ />
+ );
+ }
+
return (
<TapGestureHandler onHandlerStateChange={singleTapEvent} minPointers={1}>
<Animated.View style={styles.expand}>
@@ -640,15 +692,7 @@
<View style={contentContainerStyle}>
{spinner}
<Animated.View style={videoContainerStyle}>
- <Video
- source={{ uri: videoUri }}
- ref={videoRef}
- style={styles.backgroundVideo}
- paused={paused}
- onProgress={progressCallback}
- onEnd={resetVideo}
- onReadyForDisplay={readyForDisplayCallback}
- />
+ {videoPlayer}
</Animated.View>
</View>
{controls}

File Metadata

Mime Type
text/plain
Expires
Mon, Dec 23, 3:25 PM (18 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2694511
Default Alt Text
D7226.id24487.diff (6 KB)

Event Timeline