@symbiote-native/video 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +240 -2
- package/build/angular/index.d.ts +4 -0
- package/build/angular/index.js +5 -0
- package/build/angular/inject-video-player.d.ts +4 -0
- package/build/angular/inject-video-player.js +6 -0
- package/build/angular/video-airplay-button/index.d.ts +12 -0
- package/build/angular/video-airplay-button/index.js +78 -0
- package/build/angular/video-view/index.d.ts +17 -0
- package/build/angular/video-view/index.js +97 -0
- package/build/core/constants.d.ts +12 -0
- package/build/core/constants.js +13 -0
- package/build/core/index.d.ts +10 -0
- package/build/core/index.js +8 -0
- package/build/core/native-module.d.ts +10 -0
- package/build/core/native-module.js +3 -0
- package/build/core/player-types.d.ts +221 -0
- package/build/core/player-types.js +1 -0
- package/build/core/video-airplay-button.d.ts +4 -0
- package/build/core/video-airplay-button.js +29 -0
- package/build/core/video-module.d.ts +12 -0
- package/build/core/video-module.js +21 -0
- package/build/core/video-player-controller.d.ts +15 -0
- package/build/core/video-player-controller.js +21 -0
- package/build/core/video-player.d.ts +7 -0
- package/build/core/video-player.js +22 -0
- package/build/core/video-source.d.ts +3 -0
- package/build/core/video-source.js +20 -0
- package/build/core/video-thumbnail.d.ts +4 -0
- package/build/core/video-thumbnail.js +3 -0
- package/build/core/video-view.d.ts +18 -0
- package/build/core/video-view.js +63 -0
- package/build/core/view-types.d.ts +90 -0
- package/build/core/view-types.js +1 -0
- package/build/react/index.d.ts +4 -0
- package/build/react/index.js +4 -0
- package/build/react/use-video-player.d.ts +7 -0
- package/build/react/use-video-player.js +11 -0
- package/build/react/video-view.d.ts +13 -0
- package/build/react/video-view.js +10 -0
- package/build/solid/index.d.ts +3 -0
- package/build/solid/index.js +4 -0
- package/build/solid/use-video-player.d.ts +8 -0
- package/build/solid/use-video-player.js +11 -0
- package/build/solid/video-view.d.ts +33 -0
- package/build/solid/video-view.js +6 -0
- package/build/svelte/index.d.ts +5 -0
- package/build/svelte/index.js +5 -0
- package/build/svelte/use-video-player.svelte.d.ts +10 -0
- package/build/svelte/use-video-player.svelte.js +15 -0
- package/build/svelte/video-airplay-button.svelte +12 -0
- package/build/svelte/video-airplay-button.svelte.d.ts +4 -0
- package/build/svelte/video-view.svelte +25 -0
- package/build/svelte/video-view.svelte.d.ts +9 -0
- package/build/vue/index.d.ts +3 -0
- package/build/vue/index.js +4 -0
- package/build/vue/use-video-player.d.ts +8 -0
- package/build/vue/use-video-player.js +16 -0
- package/build/vue/video-view.d.ts +5 -0
- package/build/vue/video-view.js +14 -0
- package/build-ngc/angular/index.d.ts +4 -0
- package/build-ngc/angular/index.js +6 -0
- package/build-ngc/angular/index.js.map +1 -0
- package/build-ngc/angular/inject-video-player.d.ts +4 -0
- package/build-ngc/angular/inject-video-player.js +7 -0
- package/build-ngc/angular/inject-video-player.js.map +1 -0
- package/build-ngc/angular/video-airplay-button/index.d.ts +15 -0
- package/build-ngc/angular/video-airplay-button/index.js +37 -0
- package/build-ngc/angular/video-airplay-button/index.js.map +1 -0
- package/build-ngc/angular/video-view/index.d.ts +20 -0
- package/build-ngc/angular/video-view/index.js +56 -0
- package/build-ngc/angular/video-view/index.js.map +1 -0
- package/build-ngc/core/constants.d.ts +12 -0
- package/build-ngc/core/constants.js +14 -0
- package/build-ngc/core/constants.js.map +1 -0
- package/build-ngc/core/index.d.ts +10 -0
- package/build-ngc/core/index.js +9 -0
- package/build-ngc/core/index.js.map +1 -0
- package/build-ngc/core/native-module.d.ts +10 -0
- package/build-ngc/core/native-module.js +4 -0
- package/build-ngc/core/native-module.js.map +1 -0
- package/build-ngc/core/player-types.d.ts +221 -0
- package/build-ngc/core/player-types.js +2 -0
- package/build-ngc/core/player-types.js.map +1 -0
- package/build-ngc/core/video-airplay-button.d.ts +4 -0
- package/build-ngc/core/video-airplay-button.js +30 -0
- package/build-ngc/core/video-airplay-button.js.map +1 -0
- package/build-ngc/core/video-module.d.ts +12 -0
- package/build-ngc/core/video-module.js +22 -0
- package/build-ngc/core/video-module.js.map +1 -0
- package/build-ngc/core/video-player-controller.d.ts +15 -0
- package/build-ngc/core/video-player-controller.js +22 -0
- package/build-ngc/core/video-player-controller.js.map +1 -0
- package/build-ngc/core/video-player.d.ts +7 -0
- package/build-ngc/core/video-player.js +23 -0
- package/build-ngc/core/video-player.js.map +1 -0
- package/build-ngc/core/video-source.d.ts +3 -0
- package/build-ngc/core/video-source.js +21 -0
- package/build-ngc/core/video-source.js.map +1 -0
- package/build-ngc/core/video-thumbnail.d.ts +4 -0
- package/build-ngc/core/video-thumbnail.js +4 -0
- package/build-ngc/core/video-thumbnail.js.map +1 -0
- package/build-ngc/core/video-view.d.ts +18 -0
- package/build-ngc/core/video-view.js +64 -0
- package/build-ngc/core/video-view.js.map +1 -0
- package/build-ngc/core/view-types.d.ts +90 -0
- package/build-ngc/core/view-types.js +2 -0
- package/build-ngc/core/view-types.js.map +1 -0
- package/native-link.json +33 -0
- package/package.json +144 -3
- package/src/angular/index.ts +6 -0
- package/src/angular/inject-video-player.ts +20 -0
- package/src/angular/video-airplay-button/index.ts +38 -0
- package/src/angular/video-view/index.ts +59 -0
- package/src/core/constants.ts +16 -0
- package/src/core/index.ts +56 -0
- package/src/core/native-module.ts +15 -0
- package/src/core/player-types.ts +241 -0
- package/src/core/video-airplay-button.ts +45 -0
- package/src/core/video-module.ts +25 -0
- package/src/core/video-player-controller.ts +53 -0
- package/src/core/video-player.ts +38 -0
- package/src/core/video-source.ts +21 -0
- package/src/core/video-thumbnail.ts +7 -0
- package/src/core/video-view.ts +119 -0
- package/src/core/view-types.ts +114 -0
- package/src/react/index.ts +6 -0
- package/src/react/use-video-player.ts +22 -0
- package/src/react/video-view.ts +35 -0
- package/src/solid/index.ts +5 -0
- package/src/solid/use-video-player.ts +24 -0
- package/src/solid/video-view.ts +22 -0
- package/src/svelte/index.ts +7 -0
- package/src/svelte/svelte-ambient.d.ts +3 -0
- package/src/svelte/svelte-compile.test-helper.ts +6 -0
- package/src/svelte/use-video-player.svelte.ts +31 -0
- package/src/svelte/video-airplay-button.svelte +12 -0
- package/src/svelte/video-view.svelte +25 -0
- package/src/vue/index.ts +5 -0
- package/src/vue/use-video-player.ts +33 -0
- package/src/vue/video-view.ts +24 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import type { SharedObject, SharedRef } from 'expo-modules-core';
|
|
2
|
+
export type IVideoPlayerStatus = 'idle' | 'loading' | 'readyToPlay' | 'error';
|
|
3
|
+
export type IVideoContentType = 'auto' | 'progressive' | 'hls' | 'dash' | 'smoothStreaming';
|
|
4
|
+
export type IVideoDrmType = 'clearkey' | 'fairplay' | 'playready' | 'widevine';
|
|
5
|
+
export type IVideoDrmOptions = {
|
|
6
|
+
type: IVideoDrmType;
|
|
7
|
+
licenseServer: string;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
/** Android only */
|
|
10
|
+
multiKey?: boolean;
|
|
11
|
+
/** iOS only */
|
|
12
|
+
contentId?: string;
|
|
13
|
+
/** iOS only */
|
|
14
|
+
certificateUrl?: string;
|
|
15
|
+
/** iOS only */
|
|
16
|
+
base64CertificateData?: string;
|
|
17
|
+
};
|
|
18
|
+
export type IVideoMetadata = {
|
|
19
|
+
title?: string;
|
|
20
|
+
artist?: string;
|
|
21
|
+
artwork?: string;
|
|
22
|
+
};
|
|
23
|
+
export type IVideoSourceObject = {
|
|
24
|
+
uri?: string;
|
|
25
|
+
/** A `require`d asset, `uri` wins when both are set */
|
|
26
|
+
assetId?: number;
|
|
27
|
+
drm?: IVideoDrmOptions;
|
|
28
|
+
metadata?: IVideoMetadata;
|
|
29
|
+
headers?: Record<string, string>;
|
|
30
|
+
/** Caches the video on disk, off by default */
|
|
31
|
+
useCaching?: boolean;
|
|
32
|
+
contentType?: IVideoContentType;
|
|
33
|
+
};
|
|
34
|
+
/** A URI, a `require`d asset or an object, `null` unloads the player */
|
|
35
|
+
export type IVideoSource = string | number | null | IVideoSourceObject;
|
|
36
|
+
export type IVideoPlayerError = {
|
|
37
|
+
message: string;
|
|
38
|
+
};
|
|
39
|
+
export type IVideoAudioMixingMode = 'mixWithOthers' | 'duckOthers' | 'auto' | 'doNotMix';
|
|
40
|
+
export type IVideoBufferOptions = {
|
|
41
|
+
/** iOS only, in seconds */
|
|
42
|
+
readonly preferredForwardBufferDuration?: number;
|
|
43
|
+
/** iOS only */
|
|
44
|
+
readonly waitsToMinimizeStalling?: boolean;
|
|
45
|
+
/** Android only, in seconds */
|
|
46
|
+
readonly minBufferForPlayback?: number;
|
|
47
|
+
/** Android only, in bytes */
|
|
48
|
+
readonly maxBufferBytes?: number | null;
|
|
49
|
+
/** Android only */
|
|
50
|
+
readonly prioritizeTimeOverSizeThreshold?: boolean;
|
|
51
|
+
};
|
|
52
|
+
export type IVideoTextTrack = {
|
|
53
|
+
id?: string;
|
|
54
|
+
language: string;
|
|
55
|
+
label: string;
|
|
56
|
+
name?: string;
|
|
57
|
+
isDefault?: boolean;
|
|
58
|
+
autoSelect?: boolean;
|
|
59
|
+
};
|
|
60
|
+
export type IVideoSubtitleTrack = IVideoTextTrack;
|
|
61
|
+
export type IVideoAudioTrack = IVideoTextTrack;
|
|
62
|
+
export type IVideoSize = {
|
|
63
|
+
width: number;
|
|
64
|
+
height: number;
|
|
65
|
+
};
|
|
66
|
+
export type IVideoRange = 'sdr' | 'hlg' | 'pq';
|
|
67
|
+
export type IVideoTrack = {
|
|
68
|
+
id: string;
|
|
69
|
+
url: string | null;
|
|
70
|
+
size: IVideoSize;
|
|
71
|
+
mimeType: string | null;
|
|
72
|
+
isSupported: boolean;
|
|
73
|
+
bitrate: number | null;
|
|
74
|
+
averageBitrate: number | null;
|
|
75
|
+
peakBitrate: number | null;
|
|
76
|
+
frameRate: number | null;
|
|
77
|
+
videoRange: IVideoRange;
|
|
78
|
+
};
|
|
79
|
+
export type IVideoSeekTolerance = {
|
|
80
|
+
/** iOS only, in seconds */
|
|
81
|
+
toleranceBefore?: number;
|
|
82
|
+
/** iOS only, in seconds */
|
|
83
|
+
toleranceAfter?: number;
|
|
84
|
+
};
|
|
85
|
+
export type IVideoScrubbingModeOptions = {
|
|
86
|
+
/** Android only */
|
|
87
|
+
scrubbingModeEnabled?: boolean;
|
|
88
|
+
increaseCodecOperatingRate?: boolean;
|
|
89
|
+
enableDynamicScheduling?: boolean;
|
|
90
|
+
useDecodeOnlyFlag?: boolean;
|
|
91
|
+
allowSkippingMediaCodecFlush?: boolean;
|
|
92
|
+
};
|
|
93
|
+
/** Options of the Android player builder, applied before the native constructor runs */
|
|
94
|
+
export type IVideoPlayerBuilderOptions = {
|
|
95
|
+
/** In seconds */
|
|
96
|
+
seekBackwardIncrement?: number;
|
|
97
|
+
/** In seconds */
|
|
98
|
+
seekForwardIncrement?: number;
|
|
99
|
+
};
|
|
100
|
+
export type IVideoThumbnailOptions = {
|
|
101
|
+
maxWidth?: number;
|
|
102
|
+
maxHeight?: number;
|
|
103
|
+
};
|
|
104
|
+
export type IVideoPlayerEvents = {
|
|
105
|
+
statusChange(payload: {
|
|
106
|
+
status: IVideoPlayerStatus;
|
|
107
|
+
oldStatus?: IVideoPlayerStatus;
|
|
108
|
+
error?: IVideoPlayerError;
|
|
109
|
+
}): void;
|
|
110
|
+
playingChange(payload: {
|
|
111
|
+
isPlaying: boolean;
|
|
112
|
+
oldIsPlaying?: boolean;
|
|
113
|
+
}): void;
|
|
114
|
+
playbackRateChange(payload: {
|
|
115
|
+
playbackRate: number;
|
|
116
|
+
oldPlaybackRate?: number;
|
|
117
|
+
}): void;
|
|
118
|
+
volumeChange(payload: {
|
|
119
|
+
volume: number;
|
|
120
|
+
oldVolume?: number;
|
|
121
|
+
}): void;
|
|
122
|
+
mutedChange(payload: {
|
|
123
|
+
muted: boolean;
|
|
124
|
+
oldMuted?: boolean;
|
|
125
|
+
}): void;
|
|
126
|
+
playToEnd(): void;
|
|
127
|
+
timeUpdate(payload: {
|
|
128
|
+
currentTime: number;
|
|
129
|
+
currentLiveTimestamp: number | null;
|
|
130
|
+
currentOffsetFromLive: number | null;
|
|
131
|
+
bufferedPosition: number;
|
|
132
|
+
}): void;
|
|
133
|
+
sourceChange(payload: {
|
|
134
|
+
source: IVideoSource;
|
|
135
|
+
oldSource?: IVideoSource;
|
|
136
|
+
}): void;
|
|
137
|
+
availableSubtitleTracksChange(payload: {
|
|
138
|
+
availableSubtitleTracks: IVideoSubtitleTrack[];
|
|
139
|
+
oldAvailableSubtitleTracks?: IVideoSubtitleTrack[];
|
|
140
|
+
}): void;
|
|
141
|
+
subtitleTrackChange(payload: {
|
|
142
|
+
subtitleTrack: IVideoSubtitleTrack | null;
|
|
143
|
+
oldSubtitleTrack?: IVideoSubtitleTrack | null;
|
|
144
|
+
}): void;
|
|
145
|
+
availableAudioTracksChange(payload: {
|
|
146
|
+
availableAudioTracks: IVideoAudioTrack[];
|
|
147
|
+
oldAvailableAudioTracks?: IVideoAudioTrack[];
|
|
148
|
+
}): void;
|
|
149
|
+
audioTrackChange(payload: {
|
|
150
|
+
audioTrack: IVideoAudioTrack | null;
|
|
151
|
+
oldAudioTrack?: IVideoAudioTrack | null;
|
|
152
|
+
}): void;
|
|
153
|
+
videoTrackChange(payload: {
|
|
154
|
+
videoTrack: IVideoTrack | null;
|
|
155
|
+
oldVideoTrack?: IVideoTrack | null;
|
|
156
|
+
}): void;
|
|
157
|
+
sourceLoad(payload: {
|
|
158
|
+
videoSource: IVideoSource | null;
|
|
159
|
+
duration: number;
|
|
160
|
+
availableVideoTracks: IVideoTrack[];
|
|
161
|
+
availableSubtitleTracks: IVideoSubtitleTrack[];
|
|
162
|
+
availableAudioTracks: IVideoAudioTrack[];
|
|
163
|
+
}): void;
|
|
164
|
+
isExternalPlaybackActiveChange(payload: {
|
|
165
|
+
isExternalPlaybackActive: boolean;
|
|
166
|
+
oldIsExternalPlaybackActive?: boolean;
|
|
167
|
+
}): void;
|
|
168
|
+
};
|
|
169
|
+
/** The native thumbnail, `expo-image` takes it as an image source */
|
|
170
|
+
export declare class VideoThumbnail extends SharedRef<'image'> {
|
|
171
|
+
width: number;
|
|
172
|
+
height: number;
|
|
173
|
+
/** In seconds */
|
|
174
|
+
requestedTime: number;
|
|
175
|
+
/** In seconds, iOS only */
|
|
176
|
+
actualTime: number;
|
|
177
|
+
}
|
|
178
|
+
export declare class VideoPlayer extends SharedObject<IVideoPlayerEvents> {
|
|
179
|
+
readonly playing: boolean;
|
|
180
|
+
loop: boolean;
|
|
181
|
+
/** iOS only */
|
|
182
|
+
allowsExternalPlayback: boolean;
|
|
183
|
+
audioMixingMode: IVideoAudioMixingMode;
|
|
184
|
+
muted: boolean;
|
|
185
|
+
/** In seconds, assigning seeks */
|
|
186
|
+
currentTime: number;
|
|
187
|
+
readonly currentLiveTimestamp: number | null;
|
|
188
|
+
readonly currentOffsetFromLive: number | null;
|
|
189
|
+
targetOffsetFromLive: number;
|
|
190
|
+
readonly duration: number;
|
|
191
|
+
volume: number;
|
|
192
|
+
preservesPitch: boolean;
|
|
193
|
+
/** In seconds, `0` turns the `timeUpdate` event off */
|
|
194
|
+
timeUpdateEventInterval: number;
|
|
195
|
+
playbackRate: number;
|
|
196
|
+
keepScreenOnWhilePlaying: boolean;
|
|
197
|
+
readonly isLive: boolean;
|
|
198
|
+
readonly status: IVideoPlayerStatus;
|
|
199
|
+
showNowPlayingNotification: boolean;
|
|
200
|
+
staysActiveInBackground: boolean;
|
|
201
|
+
readonly bufferedPosition: number;
|
|
202
|
+
bufferOptions: IVideoBufferOptions;
|
|
203
|
+
subtitleTrack: IVideoSubtitleTrack | null;
|
|
204
|
+
audioTrack: IVideoAudioTrack | null;
|
|
205
|
+
readonly availableAudioTracks: IVideoAudioTrack[];
|
|
206
|
+
readonly availableSubtitleTracks: IVideoSubtitleTrack[];
|
|
207
|
+
readonly videoTrack: IVideoTrack | null;
|
|
208
|
+
readonly availableVideoTracks: IVideoTrack[];
|
|
209
|
+
readonly isExternalPlaybackActive: boolean;
|
|
210
|
+
seekTolerance: IVideoSeekTolerance;
|
|
211
|
+
scrubbingModeOptions: IVideoScrubbingModeOptions;
|
|
212
|
+
constructor(source: IVideoSource, useSynchronousReplace?: boolean, playerBuilderOptions?: IVideoPlayerBuilderOptions);
|
|
213
|
+
play(): void;
|
|
214
|
+
pause(): void;
|
|
215
|
+
/** On iOS it loads the asset on the main thread, prefer `replaceAsync` */
|
|
216
|
+
replace(source: IVideoSource, disableWarning?: boolean): void;
|
|
217
|
+
replaceAsync(source: IVideoSource): Promise<void>;
|
|
218
|
+
seekBy(seconds: number): void;
|
|
219
|
+
replay(): void;
|
|
220
|
+
generateThumbnailsAsync(times: number | number[], options?: IVideoThumbnailOptions): Promise<VideoThumbnail[]>;
|
|
221
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player-types.js","sourceRoot":"","sources":["../../src/core/player-types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IDescriptor } from '@symbiote-native/components';
|
|
2
|
+
export declare const videoAirPlayButtonViewName: () => string;
|
|
3
|
+
/** A plain view with the minimum size where the system route picker does not exist */
|
|
4
|
+
export declare function renderVideoAirPlayButton(props: object): IDescriptor;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Platform, requireNativeViewManager } from 'expo-modules-core';
|
|
2
|
+
import { el } from '@symbiote-native/components';
|
|
3
|
+
import { defineExpoNativeView } from '@symbiote-native/engine';
|
|
4
|
+
import { VIDEO_MODULE_NAME, VIDEO_VIEW_NAMES } from './constants';
|
|
5
|
+
// Регистрация идёт при рендере: побочный эффект барреля теряется в release
|
|
6
|
+
const airPlayButton = defineExpoNativeView(requireNativeViewManager, VIDEO_MODULE_NAME, VIDEO_VIEW_NAMES.airPlayButton);
|
|
7
|
+
export const videoAirPlayButtonViewName = airPlayButton.name;
|
|
8
|
+
const MIN_SIZE = { minWidth: 30, minHeight: 30 };
|
|
9
|
+
// What only the native route picker takes, the plain fallback view must not get it
|
|
10
|
+
const AIRPLAY_ONLY_PROPS = new Set([
|
|
11
|
+
'tint',
|
|
12
|
+
'activeTint',
|
|
13
|
+
'prioritizeVideoDevices',
|
|
14
|
+
'onBeginPresentingRoutes',
|
|
15
|
+
'onEndPresentingRoutes',
|
|
16
|
+
]);
|
|
17
|
+
function isAirPlayAvailable() {
|
|
18
|
+
return (Platform.select({ ios: true, default: false }) &&
|
|
19
|
+
airPlayButton.ensureRegistered());
|
|
20
|
+
}
|
|
21
|
+
/** A plain view with the minimum size where the system route picker does not exist */
|
|
22
|
+
export function renderVideoAirPlayButton(props) {
|
|
23
|
+
const style = [MIN_SIZE, Reflect.get(props, 'style')];
|
|
24
|
+
if (isAirPlayAvailable()) {
|
|
25
|
+
return el(airPlayButton.name(), { ...props, style });
|
|
26
|
+
}
|
|
27
|
+
const viewProps = Object.entries(props).filter(([key]) => !AIRPLAY_ONLY_PROPS.has(key));
|
|
28
|
+
return el('view', { ...Object.fromEntries(viewProps), style });
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=video-airplay-button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-airplay-button.js","sourceRoot":"","sources":["../../src/core/video-airplay-button.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AAEjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGlE,2EAA2E;AAC3E,MAAM,aAAa,GAAG,oBAAoB,CACxC,wBAAwB,EACxB,iBAAiB,EACjB,gBAAgB,CAAC,aAAa,CAC/B,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAG,aAAa,CAAC,IAAI,CAAC;AAE7D,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AAEjD,mFAAmF;AACnF,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAS;IACzC,MAAM;IACN,YAAY;IACZ,wBAAwB;IACxB,yBAAyB;IACzB,uBAAuB;CACuC,CAAC,CAAC;AAElE,SAAS,kBAAkB;IACzB,OAAO,CACL,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC9C,aAAa,CAAC,gBAAgB,EAAE,CACjC,CAAC;AACJ,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,wBAAwB,CAAC,KAAa;IACpD,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,IAAI,kBAAkB,EAAE,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAC5C,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CACxC,CAAC;IACF,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Whether the device supports Picture in Picture */
|
|
2
|
+
export declare function isPictureInPictureSupported(): boolean;
|
|
3
|
+
/** Clears the video cache, only while no `VideoPlayer` exists */
|
|
4
|
+
export declare function clearVideoCacheAsync(): Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* Sets the cache size in bytes, 1GB by default, and the value persists
|
|
7
|
+
*
|
|
8
|
+
* Only while no `VideoPlayer` exists, and the real size may be slightly larger
|
|
9
|
+
*/
|
|
10
|
+
export declare function setVideoCacheSizeAsync(sizeBytes: number): Promise<void>;
|
|
11
|
+
/** The space the video cache occupies, in bytes */
|
|
12
|
+
export declare function getCurrentVideoCacheSize(): number;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { expoVideo } from './native-module';
|
|
2
|
+
/** Whether the device supports Picture in Picture */
|
|
3
|
+
export function isPictureInPictureSupported() {
|
|
4
|
+
return expoVideo.isPictureInPictureSupported();
|
|
5
|
+
}
|
|
6
|
+
/** Clears the video cache, only while no `VideoPlayer` exists */
|
|
7
|
+
export function clearVideoCacheAsync() {
|
|
8
|
+
return expoVideo.clearVideoCacheAsync();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Sets the cache size in bytes, 1GB by default, and the value persists
|
|
12
|
+
*
|
|
13
|
+
* Only while no `VideoPlayer` exists, and the real size may be slightly larger
|
|
14
|
+
*/
|
|
15
|
+
export function setVideoCacheSizeAsync(sizeBytes) {
|
|
16
|
+
return expoVideo.setVideoCacheSizeAsync(sizeBytes);
|
|
17
|
+
}
|
|
18
|
+
/** The space the video cache occupies, in bytes */
|
|
19
|
+
export function getCurrentVideoCacheSize() {
|
|
20
|
+
return expoVideo.getCurrentVideoCacheSize();
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=video-module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-module.js","sourceRoot":"","sources":["../../src/core/video-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,qDAAqD;AACrD,MAAM,UAAU,2BAA2B;IACzC,OAAO,SAAS,CAAC,2BAA2B,EAAE,CAAC;AACjD,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,oBAAoB;IAClC,OAAO,SAAS,CAAC,oBAAoB,EAAE,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,OAAO,SAAS,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;AACrD,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,wBAAwB;IACtC,OAAO,SAAS,CAAC,wBAAwB,EAAE,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { IResourceController } from '@symbiote-native/engine';
|
|
2
|
+
import type { IVideoPlayerBuilderOptions, IVideoSource, VideoPlayer } from './player-types';
|
|
3
|
+
type IVideoPlayerKey = {
|
|
4
|
+
source: IVideoSource;
|
|
5
|
+
options?: IVideoPlayerBuilderOptions;
|
|
6
|
+
};
|
|
7
|
+
export type IVideoPlayerController = {
|
|
8
|
+
/** `setup` runs only on a player this call creates */
|
|
9
|
+
resolve: (source: IVideoSource, options?: IVideoPlayerBuilderOptions, setup?: (player: VideoPlayer) => void) => VideoPlayer;
|
|
10
|
+
flushDispose: IResourceController<IVideoPlayerKey, VideoPlayer>['flushDispose'];
|
|
11
|
+
dispose: IResourceController<IVideoPlayerKey, VideoPlayer>['dispose'];
|
|
12
|
+
};
|
|
13
|
+
/** Twin of `useVideoPlayer`'s releasing shared object, one per mounted owner */
|
|
14
|
+
export declare function createVideoPlayerController(): IVideoPlayerController;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createJsonKeyedResourceController } from '@symbiote-native/engine';
|
|
2
|
+
import { createVideoPlayer } from './video-player';
|
|
3
|
+
import { parseSource } from './video-source';
|
|
4
|
+
/** Twin of `useVideoPlayer`'s releasing shared object, one per mounted owner */
|
|
5
|
+
export function createVideoPlayerController() {
|
|
6
|
+
// The latest setup, it is not part of the key and must not recreate the player
|
|
7
|
+
let latestSetup;
|
|
8
|
+
const controller = createJsonKeyedResourceController(key => {
|
|
9
|
+
const player = createVideoPlayer(key.source, key.options);
|
|
10
|
+
latestSetup?.(player);
|
|
11
|
+
return player;
|
|
12
|
+
}, player => player.release());
|
|
13
|
+
return {
|
|
14
|
+
resolve: (source, options, setup) => {
|
|
15
|
+
latestSetup = setup;
|
|
16
|
+
return controller.resolve({ source: parseSource(source), options });
|
|
17
|
+
},
|
|
18
|
+
flushDispose: controller.flushDispose,
|
|
19
|
+
dispose: controller.dispose,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=video-player-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-player-controller.js","sourceRoot":"","sources":["../../src/core/video-player-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iCAAiC,EAAE,MAAM,yBAAyB,CAAC;AAO5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAqB7C,gFAAgF;AAChF,MAAM,UAAU,2BAA2B;IACzC,+EAA+E;IAC/E,IAAI,WAAwD,CAAC;IAC7D,MAAM,UAAU,GAAG,iCAAiC,CAIlD,GAAG,CAAC,EAAE;QACJ,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC1D,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC;QACtB,OAAO,MAAM,CAAC;IAChB,CAAC,EACD,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAC3B,CAAC;IACF,OAAO;QACL,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YAClC,WAAW,GAAG,KAAK,CAAC;YACpB,OAAO,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACtE,CAAC;QACD,YAAY,EAAE,UAAU,CAAC,YAAY;QACrC,OAAO,EAAE,UAAU,CAAC,OAAO;KAC5B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IVideoPlayerBuilderOptions, IVideoSource, VideoPlayer } from './player-types';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a player that does not release automatically, call `release()` when done
|
|
4
|
+
*
|
|
5
|
+
* The adapter hooks release it on unmount
|
|
6
|
+
*/
|
|
7
|
+
export declare function createVideoPlayer(source: IVideoSource, playerBuilderOptions?: IVideoPlayerBuilderOptions): VideoPlayer;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { expoVideo } from './native-module';
|
|
2
|
+
import { parseSource } from './video-source';
|
|
3
|
+
const SYNC_REPLACE_WARNING = 'On iOS `VideoPlayer.replace` loads the asset data synchronously on the main thread, which can lead to UI freezes and will be deprecated in a future release. Switch to `replaceAsync` for better user experience.';
|
|
4
|
+
// Upstream patches these two methods onto the native prototype at load, a subclass does the same
|
|
5
|
+
class SourceParsingVideoPlayer extends expoVideo.VideoPlayer {
|
|
6
|
+
replace(source, disableWarning = false) {
|
|
7
|
+
if (!disableWarning)
|
|
8
|
+
console.warn(SYNC_REPLACE_WARNING);
|
|
9
|
+
super.replace(parseSource(source));
|
|
10
|
+
}
|
|
11
|
+
replaceAsync(source) {
|
|
12
|
+
return super.replaceAsync(parseSource(source));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Creates a player that does not release automatically, call `release()` when done
|
|
17
|
+
*
|
|
18
|
+
* The adapter hooks release it on unmount
|
|
19
|
+
*/
|
|
20
|
+
export function createVideoPlayer(source, playerBuilderOptions) {
|
|
21
|
+
return new SourceParsingVideoPlayer(parseSource(source), false, playerBuilderOptions);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=video-player.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-player.js","sourceRoot":"","sources":["../../src/core/video-player.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,oBAAoB,GACxB,mNAAmN,CAAC;AAEtN,iGAAiG;AACjG,MAAM,wBAAyB,SAAQ,SAAS,CAAC,WAAW;IACjD,OAAO,CAAC,MAAoB,EAAE,cAAc,GAAG,KAAK;QAC3D,IAAI,CAAC,cAAc;YAAE,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACxD,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IACrC,CAAC;IAEQ,YAAY,CAAC,MAAoB;QACxC,OAAO,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAoB,EACpB,oBAAiD;IAEjD,OAAO,IAAI,wBAAwB,CACjC,WAAW,CAAC,MAAM,CAAC,EACnB,KAAK,EACL,oBAAoB,CACrB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { resolveAssetSource } from '@symbiote-native/engine';
|
|
2
|
+
function uriOfAsset(assetId) {
|
|
3
|
+
const resolved = resolveAssetSource(assetId);
|
|
4
|
+
const uri = Reflect.get(Object(resolved), 'uri');
|
|
5
|
+
if (typeof uri !== 'string') {
|
|
6
|
+
throw new Error(`The asset ${assetId} could not be resolved`);
|
|
7
|
+
}
|
|
8
|
+
return uri;
|
|
9
|
+
}
|
|
10
|
+
/** What the native player takes: a `require`d asset and a string both become a uri */
|
|
11
|
+
export function parseSource(source) {
|
|
12
|
+
if (typeof source === 'number')
|
|
13
|
+
return { uri: uriOfAsset(source) };
|
|
14
|
+
if (typeof source === 'string')
|
|
15
|
+
return { uri: source };
|
|
16
|
+
if (typeof source?.assetId === 'number' && !source.uri) {
|
|
17
|
+
return { ...source, uri: uriOfAsset(source.assetId) };
|
|
18
|
+
}
|
|
19
|
+
return source;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=video-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-source.js","sourceRoot":"","sources":["../../src/core/video-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,SAAS,UAAU,CAAC,OAAe;IACjC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAY,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;IAC1D,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,aAAa,OAAO,wBAAwB,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,WAAW,CAAC,MAAoB;IAC9C,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;IACnE,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IACvD,IAAI,OAAO,MAAM,EAAE,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QACvD,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { VideoThumbnail as IVideoThumbnailInstance } from './player-types';
|
|
2
|
+
/** The native class of a thumbnail, `generateThumbnailsAsync` resolves to instances of it */
|
|
3
|
+
export declare const VideoThumbnail: typeof IVideoThumbnailInstance;
|
|
4
|
+
export type VideoThumbnail = IVideoThumbnailInstance;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-thumbnail.js","sourceRoot":"","sources":["../../src/core/video-thumbnail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,6FAA6F;AAC7F,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC,cAAc,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IDescriptor } from '@symbiote-native/components';
|
|
2
|
+
import type { ISymbioteNode } from '@symbiote-native/engine';
|
|
3
|
+
export type IVideoViewHandle = {
|
|
4
|
+
/** Always shows the native controls */
|
|
5
|
+
enterFullscreen(): Promise<void>;
|
|
6
|
+
/** On Android it works only from a native listener, the JS runtime sleeps in fullscreen */
|
|
7
|
+
exitFullscreen(): Promise<void>;
|
|
8
|
+
/** Needs `supportsPictureInPicture` of the app setup, one player at a time */
|
|
9
|
+
startPictureInPicture(): Promise<void>;
|
|
10
|
+
stopPictureInPicture(): Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
export type IVideoView = {
|
|
13
|
+
handle: IVideoViewHandle;
|
|
14
|
+
/** `null` means the view cannot register and the caller renders nothing */
|
|
15
|
+
render(props: object): IDescriptor | null;
|
|
16
|
+
};
|
|
17
|
+
/** One per mounted view, `getNode` answers the host node once it exists */
|
|
18
|
+
export declare function createVideoView(getNode: () => ISymbioteNode | null | undefined): IVideoView;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Ядро `VideoView`: нативный view плеера, функции вызываются через `ViewPrototypes`
|
|
2
|
+
import { Platform, requireNativeModule, requireNativeViewManager, } from 'expo-modules-core';
|
|
3
|
+
import { el } from '@symbiote-native/components';
|
|
4
|
+
import { defineExpoNativeViews, defineExpoViewMethods, getNativeTag, isDevBuild, } from '@symbiote-native/engine';
|
|
5
|
+
import { VIDEO_MODULE_NAME, VIDEO_VIEW_NAMES } from './constants';
|
|
6
|
+
import { expoVideo } from './native-module';
|
|
7
|
+
const VIEW_NAMES = {
|
|
8
|
+
video: VIDEO_VIEW_NAMES.video,
|
|
9
|
+
surface: VIDEO_VIEW_NAMES.surface,
|
|
10
|
+
texture: VIDEO_VIEW_NAMES.texture,
|
|
11
|
+
};
|
|
12
|
+
// Регистрация идёт при рендере: побочный эффект барреля теряется в release
|
|
13
|
+
const views = defineExpoNativeViews(requireNativeViewManager, VIDEO_MODULE_NAME, VIEW_NAMES);
|
|
14
|
+
const callers = {
|
|
15
|
+
video: defineExpoViewMethods(requireNativeModule, VIDEO_MODULE_NAME, VIEW_NAMES.video),
|
|
16
|
+
surface: defineExpoViewMethods(requireNativeModule, VIDEO_MODULE_NAME, VIEW_NAMES.surface),
|
|
17
|
+
texture: defineExpoViewMethods(requireNativeModule, VIDEO_MODULE_NAME, VIEW_NAMES.texture),
|
|
18
|
+
};
|
|
19
|
+
function viewKeyFor(surfaceType) {
|
|
20
|
+
return Platform.select({
|
|
21
|
+
android: surfaceType === 'textureView' ? 'texture' : 'surface',
|
|
22
|
+
default: 'video',
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
// The native view takes the id of the shared object, not the player itself
|
|
26
|
+
function playerIdOf(player) {
|
|
27
|
+
if (player instanceof expoVideo.VideoPlayer) {
|
|
28
|
+
const id = Reflect.get(player, '__expo_shared_object_id__');
|
|
29
|
+
return typeof id === 'number' ? id : null;
|
|
30
|
+
}
|
|
31
|
+
return typeof player === 'number' ? player : null;
|
|
32
|
+
}
|
|
33
|
+
/** One per mounted view, `getNode` answers the host node once it exists */
|
|
34
|
+
export function createVideoView(getNode) {
|
|
35
|
+
let renderedKey = viewKeyFor(undefined);
|
|
36
|
+
async function call(method) {
|
|
37
|
+
const node = getNode();
|
|
38
|
+
if (!node || getNativeTag(node) === undefined)
|
|
39
|
+
return;
|
|
40
|
+
await callers[renderedKey](node, method, []);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
handle: {
|
|
44
|
+
enterFullscreen: () => call('enterFullscreen'),
|
|
45
|
+
exitFullscreen: () => call('exitFullscreen'),
|
|
46
|
+
startPictureInPicture: () => call('startPictureInPicture'),
|
|
47
|
+
stopPictureInPicture: () => call('stopPictureInPicture'),
|
|
48
|
+
},
|
|
49
|
+
render: props => {
|
|
50
|
+
renderedKey = viewKeyFor(Reflect.get(props, 'surfaceType'));
|
|
51
|
+
const view = views[renderedKey];
|
|
52
|
+
if (!view.ensureRegistered()) {
|
|
53
|
+
if (isDevBuild())
|
|
54
|
+
console.warn("'VideoView' is not available.");
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return el(view.name(), {
|
|
58
|
+
...Object.fromEntries(Object.entries(props)),
|
|
59
|
+
player: playerIdOf(Reflect.get(props, 'player')),
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=video-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video-view.js","sourceRoot":"","sources":["../../src/core/video-view.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { IAccessibilityProps, IAriaProps, IResponderProps } from '@symbiote-native/components';
|
|
2
|
+
import type { IColorValue, IStyleProp, ISymbioteEvent, IViewStyle } from '@symbiote-native/engine';
|
|
3
|
+
import type { VideoPlayer } from './player-types';
|
|
4
|
+
/** `fill` stretches the video, `cover` crops it, `contain` letterboxes it */
|
|
5
|
+
export type IVideoContentFit = 'contain' | 'cover' | 'fill';
|
|
6
|
+
/** Android only: `textureView` for overlapping views, `surfaceView` otherwise */
|
|
7
|
+
export type IVideoSurfaceType = 'textureView' | 'surfaceView';
|
|
8
|
+
/** Android only, which buttons the native controls show */
|
|
9
|
+
export type IVideoButtonOptions = {
|
|
10
|
+
/** `false` by default */
|
|
11
|
+
showNext?: boolean;
|
|
12
|
+
/** `false` by default */
|
|
13
|
+
showPrevious?: boolean;
|
|
14
|
+
/** `true` by default */
|
|
15
|
+
showSeekForward?: boolean;
|
|
16
|
+
/** `true` by default */
|
|
17
|
+
showSeekBackward?: boolean;
|
|
18
|
+
/** `true` always, `false` never, `null` only when subtitles exist */
|
|
19
|
+
showSubtitles?: boolean | null;
|
|
20
|
+
/** `true` by default */
|
|
21
|
+
showSettings?: boolean;
|
|
22
|
+
/** `true` by default */
|
|
23
|
+
showPlayPause?: boolean;
|
|
24
|
+
/** `true` by default, fullscreen shows it anyway */
|
|
25
|
+
showBottomBar?: boolean;
|
|
26
|
+
};
|
|
27
|
+
export type IVideoFullscreenOrientation = 'default' | 'portrait' | 'portraitUp' | 'portraitDown' | 'landscape' | 'landscapeLeft' | 'landscapeRight';
|
|
28
|
+
export type IVideoKeepFullscreenOnPiPStop = 'always' | 'autoEnter' | 'never';
|
|
29
|
+
export type IVideoFullscreenOptions = {
|
|
30
|
+
/** Shows the fullscreen button, `true` by default */
|
|
31
|
+
enable: boolean;
|
|
32
|
+
orientation?: IVideoFullscreenOrientation;
|
|
33
|
+
/** Leaves fullscreen when the device turns away from `orientation` */
|
|
34
|
+
autoExitOnRotate?: boolean;
|
|
35
|
+
/** iOS only, `autoEnter` by default */
|
|
36
|
+
keepFullscreenOnPiPStop?: IVideoKeepFullscreenOnPiPStop;
|
|
37
|
+
};
|
|
38
|
+
export type IVideoViewProps = IAccessibilityProps & IAriaProps & IResponderProps & {
|
|
39
|
+
/** From `useVideoPlayer` */
|
|
40
|
+
player?: VideoPlayer | null;
|
|
41
|
+
/** Always on in fullscreen, `true` by default */
|
|
42
|
+
nativeControls?: boolean;
|
|
43
|
+
/** `contain` by default */
|
|
44
|
+
contentFit?: IVideoContentFit;
|
|
45
|
+
fullscreenOptions?: IVideoFullscreenOptions;
|
|
46
|
+
/** iOS only, `true` by default */
|
|
47
|
+
showsTimecodes?: boolean;
|
|
48
|
+
/** Forbids skipping, `false` by default */
|
|
49
|
+
requiresLinearPlayback?: boolean;
|
|
50
|
+
buttonOptions?: IVideoButtonOptions;
|
|
51
|
+
/** Android only, must not change at runtime */
|
|
52
|
+
surfaceType?: IVideoSurfaceType;
|
|
53
|
+
/** iOS only, `{ dx: 0, dy: 0 }` by default */
|
|
54
|
+
contentPosition?: {
|
|
55
|
+
dx?: number;
|
|
56
|
+
dy?: number;
|
|
57
|
+
};
|
|
58
|
+
onPictureInPictureStart?: () => void;
|
|
59
|
+
onPictureInPictureStop?: () => void;
|
|
60
|
+
/** Needs `supportsPictureInPicture` of the app setup */
|
|
61
|
+
allowsPictureInPicture?: boolean;
|
|
62
|
+
/** Android 12+ and iOS, `false` by default */
|
|
63
|
+
startsPictureInPictureAutomatically?: boolean;
|
|
64
|
+
/** iOS 16+, `true` by default */
|
|
65
|
+
allowsVideoFrameAnalysis?: boolean;
|
|
66
|
+
onFullscreenEnter?: () => void;
|
|
67
|
+
onFullscreenExit?: () => void;
|
|
68
|
+
/** The first frame is rendered, also when the video track changes */
|
|
69
|
+
onFirstFrameRender?: () => void;
|
|
70
|
+
/** Android only, `false` by default */
|
|
71
|
+
useExoShutter?: boolean;
|
|
72
|
+
style?: IStyleProp<IViewStyle>;
|
|
73
|
+
testID?: string;
|
|
74
|
+
nativeID?: string;
|
|
75
|
+
onLayout?: (event: ISymbioteEvent) => void;
|
|
76
|
+
};
|
|
77
|
+
export type IVideoAirPlayButtonProps = IAccessibilityProps & IAriaProps & {
|
|
78
|
+
/** The icon colour while AirPlay is not active */
|
|
79
|
+
tint?: IColorValue;
|
|
80
|
+
/** The icon colour while AirPlay is active */
|
|
81
|
+
activeTint?: IColorValue;
|
|
82
|
+
/** Lists the video outputs first, `true` by default */
|
|
83
|
+
prioritizeVideoDevices?: boolean;
|
|
84
|
+
onBeginPresentingRoutes?: () => void;
|
|
85
|
+
onEndPresentingRoutes?: () => void;
|
|
86
|
+
style?: IStyleProp<IViewStyle>;
|
|
87
|
+
testID?: string;
|
|
88
|
+
nativeID?: string;
|
|
89
|
+
onLayout?: (event: ISymbioteEvent) => void;
|
|
90
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-types.js","sourceRoot":"","sources":["../../src/core/view-types.ts"],"names":[],"mappings":""}
|