Skip to content
Source
Sign inSign up

previewPresentation.ts

38 lines1.6 KB

1import { useNavigation } from "@react-navigation/native";
2import { useEffect, useEffectEvent } from "react";
3import { Keyboard } from "react-native";
4​
5import { mediaVideoThumbnailKey, type VideoPreviewSource } from "./videoPreviewSource";
6​
7/** Identity of a video preview: a different file is a new presentation. */
8export function videoPreviewKey(source: VideoPreviewSource): string {
9 return source.type === "local"
10 ? `local:${source.attachment.id}:${source.attachment.fileUri}`
11 : mediaVideoThumbnailKey(source);
13​
14/**
15 * A full-screen preview owns the screen while it is open: each presented
16 * source dismisses the keyboard, and the preview closes when its route loses
17 * focus, so navigating away never leaves a native viewer or modal behind.
18 * `presentationKey` is the presented source's identity, or null when closed.
19 */
20export function usePreviewPresentation(
21 presentationKey: string | null,
22 onRequestClose: () => void,
23): void {
24 // The v5 card host sits inside a legacy presentation envelope whose focus context
25 // can describe a different route. The preview belongs to this navigation route.
26 const navigation = useNavigation();
27 const close = useEffectEvent(onRequestClose);
28 // oxlint-disable-next-line t3code/no-unreasoned-state-sync -- Navigation blur is an external event and the open state belongs to the caller.
29 useEffect(() => {
30 if (presentationKey === null) return;
31 Keyboard.dismiss();
32 if (!navigation.isFocused()) {
33 close();
34 return;
35 }
36 return navigation.addListener("blur", () => close());
37 }, [presentationKey, navigation]);