@oxyhq/bloom 1.0.6 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/level-picker.mdx +105 -0
- package/docs/media-flight.mdx +272 -0
- package/docs/migrating-the-media-gallery.mdx +103 -0
- package/docs/migrating-to-1.0.mdx +1 -1
- package/docs/slider.mdx +3 -1
- package/docs/zoomable-media-gallery.mdx +116 -0
- package/lib/commonjs/floating/index.js.map +1 -1
- package/lib/commonjs/image-aspect-ratio-cache/aspect-ratio-cache.js +1 -1
- package/lib/commonjs/index.js +8 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +33 -25
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/level-picker/LevelPicker.js +349 -0
- package/lib/commonjs/level-picker/LevelPicker.js.map +1 -0
- package/lib/commonjs/level-picker/LevelPicker.web.js +346 -0
- package/lib/commonjs/level-picker/LevelPicker.web.js.map +1 -0
- package/lib/commonjs/level-picker/constants.js +137 -0
- package/lib/commonjs/level-picker/constants.js.map +1 -0
- package/lib/commonjs/level-picker/index.js +13 -0
- package/lib/commonjs/level-picker/index.js.map +1 -0
- package/lib/commonjs/level-picker/index.web.js +13 -0
- package/lib/commonjs/level-picker/index.web.js.map +1 -0
- package/lib/commonjs/level-picker/types.js +6 -0
- package/lib/commonjs/level-picker/types.js.map +1 -0
- package/lib/commonjs/media-flight/MediaFlightLayer.js +151 -0
- package/lib/commonjs/media-flight/MediaFlightLayer.js.map +1 -0
- package/lib/commonjs/media-flight/MediaSurface.js +188 -0
- package/lib/commonjs/media-flight/MediaSurface.js.map +1 -0
- package/lib/commonjs/media-flight/constants.js +39 -0
- package/lib/commonjs/media-flight/constants.js.map +1 -0
- package/lib/commonjs/media-flight/expo-video-module.js +148 -0
- package/lib/commonjs/media-flight/expo-video-module.js.map +1 -0
- package/lib/commonjs/media-flight/index.js +102 -0
- package/lib/commonjs/media-flight/index.js.map +1 -0
- package/lib/commonjs/media-flight/store.js +457 -0
- package/lib/commonjs/media-flight/store.js.map +1 -0
- package/lib/commonjs/media-flight/types.js +6 -0
- package/lib/commonjs/media-flight/types.js.map +1 -0
- package/lib/commonjs/media-flight/use-media-flight.js +41 -0
- package/lib/commonjs/media-flight/use-media-flight.js.map +1 -0
- package/lib/commonjs/tab-bar/TabBarBase.js +1 -1
- package/lib/commonjs/{zoomable-image-gallery/ZoomableImageGallery.js → zoomable-media-gallery/ZoomableMediaGallery.js} +185 -131
- package/lib/commonjs/zoomable-media-gallery/ZoomableMediaGallery.js.map +1 -0
- package/lib/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/constants.js.map +1 -1
- package/lib/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/index.js +5 -5
- package/lib/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/index.js.map +1 -1
- package/lib/commonjs/zoomable-media-gallery/types.js +6 -0
- package/lib/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/types.js.map +1 -1
- package/lib/module/floating/index.js +5 -0
- package/lib/module/floating/index.js.map +1 -1
- package/lib/module/image-aspect-ratio-cache/aspect-ratio-cache.js +1 -1
- package/lib/module/index.js +3 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +3 -1
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/level-picker/LevelPicker.js +343 -0
- package/lib/module/level-picker/LevelPicker.js.map +1 -0
- package/lib/module/level-picker/LevelPicker.web.js +340 -0
- package/lib/module/level-picker/LevelPicker.web.js.map +1 -0
- package/lib/module/level-picker/constants.js +131 -0
- package/lib/module/level-picker/constants.js.map +1 -0
- package/lib/module/level-picker/index.js +4 -0
- package/lib/module/level-picker/index.js.map +1 -0
- package/lib/module/level-picker/index.web.js +4 -0
- package/lib/module/level-picker/index.web.js.map +1 -0
- package/lib/module/level-picker/types.js +4 -0
- package/lib/module/level-picker/types.js.map +1 -0
- package/lib/module/media-flight/MediaFlightLayer.js +146 -0
- package/lib/module/media-flight/MediaFlightLayer.js.map +1 -0
- package/lib/module/media-flight/MediaSurface.js +180 -0
- package/lib/module/media-flight/MediaSurface.js.map +1 -0
- package/lib/module/media-flight/constants.js +35 -0
- package/lib/module/media-flight/constants.js.map +1 -0
- package/lib/module/media-flight/expo-video-module.js +142 -0
- package/lib/module/media-flight/expo-video-module.js.map +1 -0
- package/lib/module/media-flight/index.js +9 -0
- package/lib/module/media-flight/index.js.map +1 -0
- package/lib/module/media-flight/store.js +439 -0
- package/lib/module/media-flight/store.js.map +1 -0
- package/lib/module/media-flight/types.js +4 -0
- package/lib/module/media-flight/types.js.map +1 -0
- package/lib/module/media-flight/use-media-flight.js +36 -0
- package/lib/module/media-flight/use-media-flight.js.map +1 -0
- package/lib/module/tab-bar/TabBarBase.js +1 -1
- package/lib/module/{zoomable-image-gallery/ZoomableImageGallery.js → zoomable-media-gallery/ZoomableMediaGallery.js} +184 -130
- package/lib/module/zoomable-media-gallery/ZoomableMediaGallery.js.map +1 -0
- package/lib/module/{zoomable-image-gallery → zoomable-media-gallery}/constants.js.map +1 -1
- package/lib/module/zoomable-media-gallery/index.js +5 -0
- package/lib/module/zoomable-media-gallery/index.js.map +1 -0
- package/lib/module/zoomable-media-gallery/types.js +4 -0
- package/lib/module/{zoomable-image-gallery → zoomable-media-gallery}/types.js.map +1 -1
- package/lib/typescript/commonjs/floating/index.d.ts +5 -0
- package/lib/typescript/commonjs/floating/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +2 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.web.d.ts +2 -0
- package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/level-picker/LevelPicker.d.ts +6 -0
- package/lib/typescript/commonjs/level-picker/LevelPicker.d.ts.map +1 -0
- package/lib/typescript/commonjs/level-picker/LevelPicker.web.d.ts +6 -0
- package/lib/typescript/commonjs/level-picker/LevelPicker.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/level-picker/constants.d.ts +93 -0
- package/lib/typescript/commonjs/level-picker/constants.d.ts.map +1 -0
- package/lib/typescript/commonjs/level-picker/index.d.ts +3 -0
- package/lib/typescript/commonjs/level-picker/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/level-picker/index.web.d.ts +3 -0
- package/lib/typescript/commonjs/level-picker/index.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/level-picker/types.d.ts +63 -0
- package/lib/typescript/commonjs/level-picker/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/media-flight/MediaFlightLayer.d.ts +11 -0
- package/lib/typescript/commonjs/media-flight/MediaFlightLayer.d.ts.map +1 -0
- package/lib/typescript/commonjs/media-flight/MediaSurface.d.ts +106 -0
- package/lib/typescript/commonjs/media-flight/MediaSurface.d.ts.map +1 -0
- package/lib/typescript/commonjs/media-flight/constants.d.ts +18 -0
- package/lib/typescript/commonjs/media-flight/constants.d.ts.map +1 -0
- package/lib/typescript/commonjs/media-flight/expo-video-module.d.ts +103 -0
- package/lib/typescript/commonjs/media-flight/expo-video-module.d.ts.map +1 -0
- package/lib/typescript/commonjs/media-flight/index.d.ts +9 -0
- package/lib/typescript/commonjs/media-flight/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/media-flight/store.d.ts +132 -0
- package/lib/typescript/commonjs/media-flight/store.d.ts.map +1 -0
- package/lib/typescript/commonjs/media-flight/types.d.ts +195 -0
- package/lib/typescript/commonjs/media-flight/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/media-flight/use-media-flight.d.ts +4 -0
- package/lib/typescript/commonjs/media-flight/use-media-flight.d.ts.map +1 -0
- package/lib/typescript/commonjs/zoomable-media-gallery/ZoomableMediaGallery.d.ts +5 -0
- package/lib/typescript/commonjs/zoomable-media-gallery/ZoomableMediaGallery.d.ts.map +1 -0
- package/lib/typescript/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/constants.d.ts.map +1 -1
- package/lib/typescript/commonjs/zoomable-media-gallery/index.d.ts +4 -0
- package/lib/typescript/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/zoomable-media-gallery/types.d.ts +90 -0
- package/lib/typescript/commonjs/zoomable-media-gallery/types.d.ts.map +1 -0
- package/lib/typescript/module/floating/index.d.ts +5 -0
- package/lib/typescript/module/floating/index.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +2 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/index.web.d.ts +2 -0
- package/lib/typescript/module/index.web.d.ts.map +1 -1
- package/lib/typescript/module/level-picker/LevelPicker.d.ts +6 -0
- package/lib/typescript/module/level-picker/LevelPicker.d.ts.map +1 -0
- package/lib/typescript/module/level-picker/LevelPicker.web.d.ts +6 -0
- package/lib/typescript/module/level-picker/LevelPicker.web.d.ts.map +1 -0
- package/lib/typescript/module/level-picker/constants.d.ts +93 -0
- package/lib/typescript/module/level-picker/constants.d.ts.map +1 -0
- package/lib/typescript/module/level-picker/index.d.ts +3 -0
- package/lib/typescript/module/level-picker/index.d.ts.map +1 -0
- package/lib/typescript/module/level-picker/index.web.d.ts +3 -0
- package/lib/typescript/module/level-picker/index.web.d.ts.map +1 -0
- package/lib/typescript/module/level-picker/types.d.ts +63 -0
- package/lib/typescript/module/level-picker/types.d.ts.map +1 -0
- package/lib/typescript/module/media-flight/MediaFlightLayer.d.ts +11 -0
- package/lib/typescript/module/media-flight/MediaFlightLayer.d.ts.map +1 -0
- package/lib/typescript/module/media-flight/MediaSurface.d.ts +106 -0
- package/lib/typescript/module/media-flight/MediaSurface.d.ts.map +1 -0
- package/lib/typescript/module/media-flight/constants.d.ts +18 -0
- package/lib/typescript/module/media-flight/constants.d.ts.map +1 -0
- package/lib/typescript/module/media-flight/expo-video-module.d.ts +103 -0
- package/lib/typescript/module/media-flight/expo-video-module.d.ts.map +1 -0
- package/lib/typescript/module/media-flight/index.d.ts +9 -0
- package/lib/typescript/module/media-flight/index.d.ts.map +1 -0
- package/lib/typescript/module/media-flight/store.d.ts +132 -0
- package/lib/typescript/module/media-flight/store.d.ts.map +1 -0
- package/lib/typescript/module/media-flight/types.d.ts +195 -0
- package/lib/typescript/module/media-flight/types.d.ts.map +1 -0
- package/lib/typescript/module/media-flight/use-media-flight.d.ts +4 -0
- package/lib/typescript/module/media-flight/use-media-flight.d.ts.map +1 -0
- package/lib/typescript/module/zoomable-media-gallery/ZoomableMediaGallery.d.ts +5 -0
- package/lib/typescript/module/zoomable-media-gallery/ZoomableMediaGallery.d.ts.map +1 -0
- package/lib/typescript/module/{zoomable-image-gallery → zoomable-media-gallery}/constants.d.ts.map +1 -1
- package/lib/typescript/module/zoomable-media-gallery/index.d.ts +4 -0
- package/lib/typescript/module/{zoomable-image-gallery → zoomable-media-gallery}/index.d.ts.map +1 -1
- package/lib/typescript/module/zoomable-media-gallery/types.d.ts +90 -0
- package/lib/typescript/module/zoomable-media-gallery/types.d.ts.map +1 -0
- package/package.json +61 -8
- package/src/floating/index.ts +5 -0
- package/src/image-aspect-ratio-cache/aspect-ratio-cache.ts +1 -1
- package/src/index.ts +4 -1
- package/src/index.web.ts +4 -1
- package/src/level-picker/LevelPicker.tsx +365 -0
- package/src/level-picker/LevelPicker.web.tsx +374 -0
- package/src/level-picker/constants.ts +131 -0
- package/src/level-picker/index.ts +2 -0
- package/src/level-picker/index.web.ts +2 -0
- package/src/level-picker/types.ts +63 -0
- package/src/media-flight/MediaFlightLayer.tsx +144 -0
- package/src/media-flight/MediaSurface.tsx +233 -0
- package/src/media-flight/constants.ts +32 -0
- package/src/media-flight/expo-video-module.ts +181 -0
- package/src/media-flight/index.ts +33 -0
- package/src/media-flight/store.ts +497 -0
- package/src/media-flight/types.ts +210 -0
- package/src/media-flight/use-media-flight.ts +42 -0
- package/src/tab-bar/TabBarBase.tsx +1 -1
- package/src/{zoomable-image-gallery/ZoomableImageGallery.tsx → zoomable-media-gallery/ZoomableMediaGallery.tsx} +192 -117
- package/src/zoomable-media-gallery/index.ts +11 -0
- package/src/zoomable-media-gallery/types.ts +100 -0
- package/docs/zoomable-image-gallery.mdx +0 -66
- package/lib/commonjs/zoomable-image-gallery/ZoomableImageGallery.js.map +0 -1
- package/lib/commonjs/zoomable-image-gallery/types.js +0 -2
- package/lib/module/zoomable-image-gallery/ZoomableImageGallery.js.map +0 -1
- package/lib/module/zoomable-image-gallery/index.js +0 -5
- package/lib/module/zoomable-image-gallery/index.js.map +0 -1
- package/lib/module/zoomable-image-gallery/types.js +0 -2
- package/lib/typescript/commonjs/zoomable-image-gallery/ZoomableImageGallery.d.ts +0 -5
- package/lib/typescript/commonjs/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +0 -1
- package/lib/typescript/commonjs/zoomable-image-gallery/index.d.ts +0 -4
- package/lib/typescript/commonjs/zoomable-image-gallery/types.d.ts +0 -56
- package/lib/typescript/commonjs/zoomable-image-gallery/types.d.ts.map +0 -1
- package/lib/typescript/module/zoomable-image-gallery/ZoomableImageGallery.d.ts +0 -5
- package/lib/typescript/module/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +0 -1
- package/lib/typescript/module/zoomable-image-gallery/index.d.ts +0 -4
- package/lib/typescript/module/zoomable-image-gallery/types.d.ts +0 -56
- package/lib/typescript/module/zoomable-image-gallery/types.d.ts.map +0 -1
- package/src/zoomable-image-gallery/index.ts +0 -9
- package/src/zoomable-image-gallery/types.ts +0 -59
- /package/lib/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/constants.js +0 -0
- /package/lib/module/{zoomable-image-gallery → zoomable-media-gallery}/constants.js +0 -0
- /package/lib/typescript/commonjs/{zoomable-image-gallery → zoomable-media-gallery}/constants.d.ts +0 -0
- /package/lib/typescript/module/{zoomable-image-gallery → zoomable-media-gallery}/constants.d.ts +0 -0
- /package/src/{zoomable-image-gallery → zoomable-media-gallery}/constants.ts +0 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
2
|
+
|
|
3
|
+
import type { VideoPlayerLike, VideoSurfaceType } from './expo-video-module';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* On-screen rectangle of a media anchor, in WINDOW coordinates (what
|
|
7
|
+
* `measureInWindow` reports). Bloom-owned so consumers don't depend on an
|
|
8
|
+
* app-local shape.
|
|
9
|
+
*/
|
|
10
|
+
export interface MeasuredRect {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Anything that can report its own window rect. This is exactly react-native's
|
|
19
|
+
* `View` instance shape (and react-native-web's), narrowed to the one method
|
|
20
|
+
* the flight layer calls — so a consumer passes its host node straight through
|
|
21
|
+
* without Bloom naming `View` in its public API.
|
|
22
|
+
*/
|
|
23
|
+
export interface MediaFlightAnchorNode {
|
|
24
|
+
measureInWindow(
|
|
25
|
+
callback: (x: number, y: number, width: number, height: number) => void,
|
|
26
|
+
): void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** A still image painted into a media surface. */
|
|
30
|
+
export interface MediaSurfaceImage {
|
|
31
|
+
/**
|
|
32
|
+
* Present so the union discriminates. Optional on the image arm so an image
|
|
33
|
+
* literal stays `{ uri }` — the shape every existing gallery caller writes.
|
|
34
|
+
*/
|
|
35
|
+
kind?: 'image';
|
|
36
|
+
/** Source URI rendered as the image. */
|
|
37
|
+
uri: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* A video painted into a media surface.
|
|
42
|
+
*
|
|
43
|
+
* **Bloom neither creates nor destroys the player.** The consumer owns it (via
|
|
44
|
+
* expo-video's `useVideoPlayer`, a store, whatever it likes) and hands the same
|
|
45
|
+
* object to every surface that should show that video. That is the entire
|
|
46
|
+
* mechanism behind "the video does not restart": expo-video separates the
|
|
47
|
+
* `VideoPlayer` OBJECT from the `VideoView` that displays it, and one player may
|
|
48
|
+
* feed several views. Swapping which view is mounted therefore moves the picture
|
|
49
|
+
* without touching playback — whereas re-creating the player would seek back to
|
|
50
|
+
* zero and re-open the network stream.
|
|
51
|
+
*/
|
|
52
|
+
export interface MediaSurfaceVideo {
|
|
53
|
+
kind: 'video';
|
|
54
|
+
/** The expo-video `VideoPlayer` the CONSUMER created and owns. */
|
|
55
|
+
player: VideoPlayerLike;
|
|
56
|
+
/**
|
|
57
|
+
* Still frame shown behind the video surface. It is what the user sees before
|
|
58
|
+
* the first video frame renders, and the only thing rendered at all when the
|
|
59
|
+
* optional `expo-video` peer is absent.
|
|
60
|
+
*/
|
|
61
|
+
poster?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** What a media surface paints: a still image, or a consumer-owned video. */
|
|
65
|
+
export type MediaSurfaceContent = MediaSurfaceImage | MediaSurfaceVideo;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* A media surface currently owned by the flight layer.
|
|
69
|
+
*
|
|
70
|
+
* One per id, ever — that is the contract. `flyTo` on an id that is already in
|
|
71
|
+
* flight RETARGETS this record rather than adding a second surface, which is
|
|
72
|
+
* what keeps a single `VideoView` alive across the whole transition.
|
|
73
|
+
*/
|
|
74
|
+
export interface MediaFlight {
|
|
75
|
+
id: string;
|
|
76
|
+
content: MediaSurfaceContent;
|
|
77
|
+
/** Rect the current leg starts from. */
|
|
78
|
+
from: MeasuredRect;
|
|
79
|
+
/** Rect the current leg ends at. */
|
|
80
|
+
to: MeasuredRect;
|
|
81
|
+
cornerRadius: number;
|
|
82
|
+
contentFit: 'contain' | 'cover';
|
|
83
|
+
/** See {@link MediaFlightOptions.surfaceType}. Fixed for the surface's life. */
|
|
84
|
+
surfaceType: VideoSurfaceType;
|
|
85
|
+
/**
|
|
86
|
+
* The leg's progress, 0 at `from` and 1 at `to`. Owned by the store (created
|
|
87
|
+
* with `makeMutable`, not a hook) because the animation is STARTED by an
|
|
88
|
+
* imperative call and only READ by the layer — an effect in the layer would
|
|
89
|
+
* have to re-derive from a prop and would fire a frame late.
|
|
90
|
+
*/
|
|
91
|
+
progress: SharedValue<number>;
|
|
92
|
+
/**
|
|
93
|
+
* True once `flyBack` has aimed this surface at its anchor: when the leg
|
|
94
|
+
* settles, the surface is released instead of parked.
|
|
95
|
+
*/
|
|
96
|
+
landing: boolean;
|
|
97
|
+
/** Bumped on every retarget, so React remounts nothing but the layer re-reads. */
|
|
98
|
+
generation: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Options for a single `flyTo` leg. */
|
|
102
|
+
export interface MediaFlightOptions {
|
|
103
|
+
/**
|
|
104
|
+
* Rect the surface starts from, used only when nothing is live for the id
|
|
105
|
+
* yet. This is the origin thumbnail's measured rect — `measureAnchor(id)` is
|
|
106
|
+
* what produces it. Omitted, the surface appears at its destination instead
|
|
107
|
+
* of flying in from a corner, which is the right degradation when the origin
|
|
108
|
+
* could not be measured (virtualised away, already unmounted).
|
|
109
|
+
*
|
|
110
|
+
* It is ignored on a retarget: a surface already in flight resumes from where
|
|
111
|
+
* it currently IS, never from where it once started.
|
|
112
|
+
*/
|
|
113
|
+
from?: MeasuredRect;
|
|
114
|
+
/**
|
|
115
|
+
* Corner radius of the flying box. Defaults to Bloom's `radius-12`, the same
|
|
116
|
+
* default the media gallery uses for its fitted media.
|
|
117
|
+
*/
|
|
118
|
+
cornerRadius?: number;
|
|
119
|
+
/**
|
|
120
|
+
* How the media fills the flying box. `'cover'` matches a cropped feed
|
|
121
|
+
* thumbnail; `'contain'` matches a fitted fullscreen view. Defaults to
|
|
122
|
+
* `'cover'`, because a flight almost always STARTS at a cropped thumbnail.
|
|
123
|
+
*/
|
|
124
|
+
contentFit?: 'contain' | 'cover';
|
|
125
|
+
/**
|
|
126
|
+
* Android's rendering surface for the FLYING video view.
|
|
127
|
+
*
|
|
128
|
+
* Defaults to `'textureView'` because a `SurfaceView` is composited by the
|
|
129
|
+
* system outside the view hierarchy: it ignores its parent's clip, corner
|
|
130
|
+
* radius and transform, which is every property a flying box depends on.
|
|
131
|
+
*
|
|
132
|
+
* **This means a flight crosses a surface-type boundary at hand-off whenever
|
|
133
|
+
* the destination uses expo-video's own `'surfaceView'` default.** Whether
|
|
134
|
+
* that boundary is visible is a device question, not a code question, and it
|
|
135
|
+
* is the reason this is a knob rather than a constant: with it you can fly as
|
|
136
|
+
* `'surfaceView'` and match a destination that has not changed, or leave it
|
|
137
|
+
* and change the destination instead. Measure before choosing — the flight
|
|
138
|
+
* may not flicker at all, in which case the right answer is to do nothing.
|
|
139
|
+
*/
|
|
140
|
+
surfaceType?: VideoSurfaceType;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The imperative surface of the flight layer, returned by `useMediaFlight()`.
|
|
145
|
+
*
|
|
146
|
+
* Origin and destination only DECLARE where they want the surface; the layer is
|
|
147
|
+
* what paints it. Neither renders the media itself while a flight is live, so
|
|
148
|
+
* there is never a second copy to keep in sync.
|
|
149
|
+
*/
|
|
150
|
+
export interface MediaFlightController {
|
|
151
|
+
/**
|
|
152
|
+
* Register (or, with `null`, clear) the node that anchors `id` on screen.
|
|
153
|
+
* Wire it as a callback ref on the host view the media would otherwise
|
|
154
|
+
* occupy. The most recently registered node for an id is the current anchor,
|
|
155
|
+
* which is what makes a destination screen mounting over an origin screen
|
|
156
|
+
* take over as the fly-back target.
|
|
157
|
+
*/
|
|
158
|
+
registerAnchor: (id: string, node: MediaFlightAnchorNode | null) => void;
|
|
159
|
+
/**
|
|
160
|
+
* Measure the current anchor for `id` in window coordinates. Resolves `null`
|
|
161
|
+
* when no anchor is registered (unmounted / virtualised) or it has no area,
|
|
162
|
+
* which is the signal to skip the transition rather than fly to nowhere.
|
|
163
|
+
*/
|
|
164
|
+
measureAnchor: (id: string) => Promise<MeasuredRect | null>;
|
|
165
|
+
/**
|
|
166
|
+
* Take the surface for `id` live (if it is not already) and move it to
|
|
167
|
+
* `rect`. The first call flies in from {@link MediaFlightOptions.from} when
|
|
168
|
+
* the caller measured an origin, and appears in place when it did not. A call
|
|
169
|
+
* for an id already in flight RETARGETS the same surface — one surface per
|
|
170
|
+
* id, always.
|
|
171
|
+
*
|
|
172
|
+
* **Await it before tearing the origin down** (on web: before navigating).
|
|
173
|
+
* The promise resolves once the layer has committed its surface, which is what
|
|
174
|
+
* puts it in expo-video's mounted set while the origin is still there — the
|
|
175
|
+
* mechanism that carries `currentTime` across instead of restarting at zero.
|
|
176
|
+
* It resolves on a short timeout if no layer is mounted, so a missing root
|
|
177
|
+
* component degrades to "no transition" rather than to a dead feed.
|
|
178
|
+
*/
|
|
179
|
+
flyTo: (
|
|
180
|
+
id: string,
|
|
181
|
+
rect: MeasuredRect,
|
|
182
|
+
content: MediaSurfaceContent,
|
|
183
|
+
options?: MediaFlightOptions,
|
|
184
|
+
) => Promise<void>;
|
|
185
|
+
/**
|
|
186
|
+
* Fly the live surface for `id` back to its current anchor and release it
|
|
187
|
+
* once it lands. With no measurable anchor the surface is released at once —
|
|
188
|
+
* the caller is expected to render its own copy again at that point.
|
|
189
|
+
*/
|
|
190
|
+
flyBack: (id: string) => void;
|
|
191
|
+
/**
|
|
192
|
+
* Tell the layer a destination surface is LIVE, so the flying copy can go.
|
|
193
|
+
*
|
|
194
|
+
* Usually you do not call this: give the destination's `<MediaSurface>` a
|
|
195
|
+
* `flightId` and it reports its own first frame. It is here for a destination
|
|
196
|
+
* that renders something other than a Bloom surface.
|
|
197
|
+
*
|
|
198
|
+
* Called mid-flight it is remembered, not obeyed — the surface finishes
|
|
199
|
+
* travelling first, or it would vanish between the two rects.
|
|
200
|
+
*/
|
|
201
|
+
handOff: (id: string) => void;
|
|
202
|
+
/**
|
|
203
|
+
* Progress of the most recent leg, 0 → 1. Read it from a worklet to fade an
|
|
204
|
+
* origin placeholder out and a destination's chrome in, in lockstep with the
|
|
205
|
+
* flight. Shared by every flight: concurrent flights (which the one-surface-
|
|
206
|
+
* per-id contract permits across DIFFERENT ids) overwrite each other here,
|
|
207
|
+
* and each surface's own geometry is driven by its own value regardless.
|
|
208
|
+
*/
|
|
209
|
+
progress: SharedValue<number>;
|
|
210
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The consumer-facing handle on the flight layer.
|
|
3
|
+
*
|
|
4
|
+
* Every member is a module-level function over a `globalThis`-anchored registry,
|
|
5
|
+
* so the object is a frozen constant rather than something rebuilt per render:
|
|
6
|
+
* a caller may hold it in a dependency array, a callback ref or a gesture
|
|
7
|
+
* closure without any of them going stale, and there is no provider to mount.
|
|
8
|
+
*/
|
|
9
|
+
import {
|
|
10
|
+
flightProgress,
|
|
11
|
+
flyBack,
|
|
12
|
+
flyTo,
|
|
13
|
+
handOffFlight,
|
|
14
|
+
measureAnchor,
|
|
15
|
+
registerAnchor,
|
|
16
|
+
} from './store';
|
|
17
|
+
import type { MediaFlightController } from './types';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* `flyTo` / `flyBack` / `registerAnchor` / `measureAnchor`, plus the shared
|
|
21
|
+
* `progress` value of the most recent leg.
|
|
22
|
+
*
|
|
23
|
+
* `progress` is resolved through a getter rather than captured at module load,
|
|
24
|
+
* because `resetMediaFlight()` (the test seam) replaces the registry — a
|
|
25
|
+
* captured value would keep pointing at the discarded one and every assertion
|
|
26
|
+
* about progress would read a box nothing writes.
|
|
27
|
+
*/
|
|
28
|
+
const controller: MediaFlightController = Object.freeze({
|
|
29
|
+
registerAnchor,
|
|
30
|
+
measureAnchor,
|
|
31
|
+
flyTo,
|
|
32
|
+
flyBack,
|
|
33
|
+
handOff: handOffFlight,
|
|
34
|
+
get progress() {
|
|
35
|
+
return flightProgress();
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/** The media-flight controller. Stable for the life of the bundle. */
|
|
40
|
+
export function useMediaFlight(): MediaFlightController {
|
|
41
|
+
return controller;
|
|
42
|
+
}
|
|
@@ -340,7 +340,7 @@ function TabBarBody({
|
|
|
340
340
|
// never minimize and the highlight would never move, with no error anywhere.
|
|
341
341
|
// Native (plugin present) auto-tracks and ignores the extra deps, so listing
|
|
342
342
|
// them is correct on both platforms. Same rule as `BottomSheetBase` and
|
|
343
|
-
// `
|
|
343
|
+
// `ZoomableMediaGallery`. Do NOT strip these.
|
|
344
344
|
const barStyle = useAnimatedStyle(() => {
|
|
345
345
|
const height = interpolate(
|
|
346
346
|
progress.value,
|