Page MenuHomePhorge

D7254.1768416611.diff
No OneTemporary

Size
8 KB
Referenced Files
None
Subscribers
None

D7254.1768416611.diff

diff --git a/native/data/sqlite-data-handler.js b/native/data/sqlite-data-handler.js
--- a/native/data/sqlite-data-handler.js
+++ b/native/data/sqlite-data-handler.js
@@ -5,6 +5,7 @@
import { useDispatch } from 'react-redux';
import { setClientDBStoreActionType } from 'lib/actions/client-db-store-actions.js';
+import { MediaCacheContext } from 'lib/components/media-cache-provider.react.js';
import { isLoggedIn } from 'lib/selectors/user-selectors.js';
import {
logInActionSources,
@@ -14,6 +15,7 @@
import { getMessageForException } from 'lib/utils/errors.js';
import { convertClientDBThreadInfosToRawThreadInfos } from 'lib/utils/thread-ops-utils.js';
+import { filesystemMediaCache } from '../media/media-cache.js';
import { commCoreModule } from '../native-modules.js';
import { setStoreLoadedActionType } from '../redux/action-types.js';
import { useSelector } from '../redux/redux-utils.js';
@@ -36,6 +38,7 @@
const currentLoggedInUserID = useSelector(state =>
state.currentUserInfo?.anonymous ? undefined : state.currentUserInfo?.id,
);
+ const mediaCacheContext = React.useContext(MediaCacheContext);
const callFetchNewCookieFromNativeCredentials = React.useCallback(
async (source: LogInActionSource) => {
@@ -69,6 +72,7 @@
Alert.alert('Starting SQLite database deletion process');
}
await commCoreModule.clearSensitiveData();
+ await filesystemMediaCache.clearCache();
if (staffCanSee || staffUserHasBeenLoggedIn) {
Alert.alert(
'SQLite database successfully deleted',
@@ -142,7 +146,10 @@
return;
}
(async () => {
- await sensitiveDataHandled;
+ await Promise.all([
+ sensitiveDataHandled,
+ mediaCacheContext?.evictCache(),
+ ]);
try {
const { threads, messages, drafts } =
await commCoreModule.getClientDBStore();
@@ -188,6 +195,7 @@
staffUserHasBeenLoggedIn,
callFetchNewCookieFromNativeCredentials,
callClearSensitiveData,
+ mediaCacheContext,
]);
return null;
diff --git a/native/media/encrypted-image.react.js b/native/media/encrypted-image.react.js
--- a/native/media/encrypted-image.react.js
+++ b/native/media/encrypted-image.react.js
@@ -2,6 +2,8 @@
import * as React from 'react';
+import { MediaCacheContext } from 'lib/components/media-cache-provider.react.js';
+
import { decryptMedia } from './encryption-utils.js';
import LoadableImage from './loadable-image.react.js';
import { useSelector } from '../redux/redux-utils.js';
@@ -22,6 +24,7 @@
function EncryptedImage(props: Props): React.Node {
const { holder, encryptionKey, onLoad: onLoadProp } = props;
+ const mediaCache = React.useContext(MediaCacheContext);
const [source, setSource] = React.useState(null);
const connectionStatus = useSelector(state => state.connection.status);
@@ -40,11 +43,18 @@
setSource(null);
const loadDecrypted = async () => {
+ const cached = await mediaCache?.get(holder);
+ if (cached && isMounted) {
+ setSource({ uri: cached });
+ return;
+ }
+
const { result } = await decryptMedia(holder, encryptionKey, {
destination: 'data_uri',
});
// TODO: decide what to do if decryption fails
if (result.success && isMounted) {
+ mediaCache?.set(holder, result.uri);
setSource({ uri: result.uri });
}
};
@@ -54,7 +64,7 @@
return () => {
isMounted = false;
};
- }, [attempt, holder, encryptionKey]);
+ }, [attempt, holder, encryptionKey, mediaCache]);
const onLoad = React.useCallback(() => {
onLoadProp && onLoadProp(holder);
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
@@ -12,6 +12,7 @@
import { SafeAreaView } from 'react-native-safe-area-context';
import Video from 'react-native-video';
+import { MediaCacheContext } from 'lib/components/media-cache-provider.react.js';
import { useIsAppBackgroundedOrInactive } from 'lib/shared/lifecycle-utils.js';
import type { MediaInfo } from 'lib/types/media-types.js';
@@ -78,11 +79,13 @@
function VideoPlaybackModal(props: Props): React.Node {
const { mediaInfo } = props.route.params;
- const { uri, holder, encryptionKey } = mediaInfo;
+ const { uri: videoUri, holder, encryptionKey } = mediaInfo;
const [videoSource, setVideoSource] = React.useState(
- uri ? { uri } : undefined,
+ videoUri ? { uri: videoUri } : undefined,
);
+ const mediaCache = React.useContext(MediaCacheContext);
+
React.useEffect(() => {
// skip for unencrypted videos
if (!holder || !encryptionKey) {
@@ -94,12 +97,27 @@
setVideoSource(undefined);
const loadDecrypted = async () => {
+ const cached = await mediaCache?.get(holder);
+ if (cached && isMounted) {
+ setVideoSource({ uri: cached });
+ return;
+ }
+
const { result } = await decryptMedia(holder, encryptionKey, {
destination: 'file',
});
- if (result.success && isMounted) {
- uriToDispose = result.uri;
- setVideoSource({ uri: result.uri });
+ if (result.success) {
+ const { uri } = result;
+ const cacheSetPromise = mediaCache?.set(holder, uri);
+ if (isMounted) {
+ uriToDispose = uri;
+ setVideoSource({ uri });
+ } else {
+ // dispose of the temporary file immediately when unmounted
+ // but wait for the cache to be set
+ await cacheSetPromise;
+ filesystem.unlink(uri);
+ }
}
};
loadDecrypted();
@@ -111,7 +129,7 @@
filesystem.unlink(uriToDispose);
}
};
- }, [holder, encryptionKey]);
+ }, [holder, encryptionKey, mediaCache]);
const closeButtonX = useValue(-1);
const closeButtonY = useValue(-1);
diff --git a/native/root.react.js b/native/root.react.js
--- a/native/root.react.js
+++ b/native/root.react.js
@@ -19,6 +19,7 @@
import { PersistGate as ReduxPersistGate } from 'redux-persist/es/integration/react.js';
import { ENSCacheProvider } from 'lib/components/ens-cache-provider.react.js';
+import { MediaCacheProvider } from 'lib/components/media-cache-provider.react.js';
import { actionLogger } from 'lib/utils/action-logger.js';
import ChatContextProvider from './chat/chat-context-provider.react.js';
@@ -30,6 +31,7 @@
import InputStateContainer from './input/input-state-container.react.js';
import LifecycleHandler from './lifecycle/lifecycle-handler.react.js';
import MarkdownContextProvider from './markdown/markdown-context-provider.react.js';
+import { filesystemMediaCache } from './media/media-cache.js';
import { defaultNavigationState } from './navigation/default-state.js';
import DisconnectedBarVisibilityHandler from './navigation/disconnected-bar-visibility-handler.react.js';
import { setGlobalNavContext } from './navigation/icky-global.js';
@@ -253,23 +255,25 @@
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<ActionSheetProvider>
<ENSCacheProvider provider={provider}>
- <MarkdownContextProvider>
- <ChatContextProvider>
- <SQLiteDataHandler />
- <ConnectedStatusBar />
- <ReduxPersistGate persistor={getPersistor()}>
- {gated}
- </ReduxPersistGate>
- <PersistedStateGate>
- <Socket
- detectUnsupervisedBackgroundRef={
- detectUnsupervisedBackgroundRef
- }
- />
- </PersistedStateGate>
- {navigation}
- </ChatContextProvider>
- </MarkdownContextProvider>
+ <MediaCacheProvider persistence={filesystemMediaCache}>
+ <MarkdownContextProvider>
+ <ChatContextProvider>
+ <SQLiteDataHandler />
+ <ConnectedStatusBar />
+ <ReduxPersistGate persistor={getPersistor()}>
+ {gated}
+ </ReduxPersistGate>
+ <PersistedStateGate>
+ <Socket
+ detectUnsupervisedBackgroundRef={
+ detectUnsupervisedBackgroundRef
+ }
+ />
+ </PersistedStateGate>
+ {navigation}
+ </ChatContextProvider>
+ </MarkdownContextProvider>
+ </MediaCacheProvider>
</ENSCacheProvider>
</ActionSheetProvider>
</SafeAreaProvider>

File Metadata

Mime Type
text/plain
Expires
Wed, Jan 14, 6:50 PM (15 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5933454
Default Alt Text
D7254.1768416611.diff (8 KB)

Event Timeline