@symbiote-native/video 0.0.0-stage → 0.0.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 +67 -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 +11 -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 +31 -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 +39 -0
- package/src/angular/video-view/index.ts +58 -0
- package/src/core/constants.ts +16 -0
- package/src/core/index.ts +56 -0
- package/src/core/native-module.ts +16 -0
- package/src/core/player-types.ts +245 -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 +50 -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 +107 -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 +33 -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 +27 -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 +31 -0
- package/src/vue/video-view.ts +21 -0
|
@@ -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,21 @@
|
|
|
1
|
+
import { expoVideo } from './native-module.js';
|
|
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
|
+
}
|
|
@@ -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,21 @@
|
|
|
1
|
+
import { createJsonKeyedResourceController } from '@symbiote-native/engine';
|
|
2
|
+
import { createVideoPlayer } from './video-player.js';
|
|
3
|
+
import { parseSource } from './video-source.js';
|
|
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
|
+
}
|
|
@@ -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,22 @@
|
|
|
1
|
+
import { expoVideo } from './native-module.js';
|
|
2
|
+
import { parseSource } from './video-source.js';
|
|
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
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
}
|
|
@@ -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,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,63 @@
|
|
|
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.js';
|
|
6
|
+
import { expoVideo } from './native-module.js';
|
|
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
|
+
}
|
|
@@ -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
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IVideoPlayerBuilderOptions, IVideoSource, VideoPlayer } from '../core';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a player that is released when the component unmounts
|
|
4
|
+
*
|
|
5
|
+
* `setup` runs once on each new player, a changed source or options make a new one
|
|
6
|
+
*/
|
|
7
|
+
export declare function useVideoPlayer(source: IVideoSource, setup?: (player: VideoPlayer) => void, playerBuilderOptions?: IVideoPlayerBuilderOptions): VideoPlayer;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createResourceHook } from '@symbiote-native/react';
|
|
2
|
+
import { createVideoPlayerController } from '../core/video-player-controller.js';
|
|
3
|
+
const usePlayerResource = createResourceHook(createVideoPlayerController);
|
|
4
|
+
/**
|
|
5
|
+
* Creates a player that is released when the component unmounts
|
|
6
|
+
*
|
|
7
|
+
* `setup` runs once on each new player, a changed source or options make a new one
|
|
8
|
+
*/
|
|
9
|
+
export function useVideoPlayer(source, setup, playerBuilderOptions) {
|
|
10
|
+
return usePlayerResource(source, playerBuilderOptions, setup);
|
|
11
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReactElement, Ref } from 'react';
|
|
2
|
+
import type { IVideoAirPlayButtonProps, IVideoViewHandle, IVideoViewProps } from '../core';
|
|
3
|
+
export type IVideoViewReactProps = IVideoViewProps & {
|
|
4
|
+
ref?: Ref<IVideoViewHandle>;
|
|
5
|
+
className?: string;
|
|
6
|
+
};
|
|
7
|
+
export type IVideoAirPlayButtonReactProps = IVideoAirPlayButtonProps & {
|
|
8
|
+
className?: string;
|
|
9
|
+
};
|
|
10
|
+
/** React twin of `expo-video`'s `VideoView` */
|
|
11
|
+
export declare function VideoView({ ref, ...props }: IVideoViewReactProps): ReactElement | null;
|
|
12
|
+
/** React twin of `expo-video`'s `VideoAirPlayButton`, a plain view off iOS */
|
|
13
|
+
export declare function VideoAirPlayButton(props: IVideoAirPlayButtonReactProps): ReactElement;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { descriptorToReact, useNativeViewController, } from '@symbiote-native/react';
|
|
2
|
+
import { createVideoView, renderVideoAirPlayButton } from '../core/index.js';
|
|
3
|
+
/** React twin of `expo-video`'s `VideoView` */
|
|
4
|
+
export function VideoView({ ref, ...props }) {
|
|
5
|
+
return useNativeViewController(ref, createVideoView, props);
|
|
6
|
+
}
|
|
7
|
+
/** React twin of `expo-video`'s `VideoAirPlayButton`, a plain view off iOS */
|
|
8
|
+
export function VideoAirPlayButton(props) {
|
|
9
|
+
return descriptorToReact(renderVideoAirPlayButton(props));
|
|
10
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Accessor } from 'solid-js';
|
|
2
|
+
import type { IVideoPlayerBuilderOptions, IVideoSource, VideoPlayer } from '../core';
|
|
3
|
+
/**
|
|
4
|
+
* Solid twin of `expo-video`'s `useVideoPlayer`, released when the owner is disposed
|
|
5
|
+
*
|
|
6
|
+
* `setup` runs once on each new player, a changed source or options make a new one
|
|
7
|
+
*/
|
|
8
|
+
export declare function useVideoPlayer(source: Accessor<IVideoSource>, setup?: (player: VideoPlayer) => void, playerBuilderOptions?: Accessor<IVideoPlayerBuilderOptions | undefined>): Accessor<VideoPlayer>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createResourceHook } from '@symbiote-native/solid';
|
|
2
|
+
import { createVideoPlayerController } from '../core/video-player-controller.js';
|
|
3
|
+
const usePlayerResource = createResourceHook(createVideoPlayerController);
|
|
4
|
+
/**
|
|
5
|
+
* Solid twin of `expo-video`'s `useVideoPlayer`, released when the owner is disposed
|
|
6
|
+
*
|
|
7
|
+
* `setup` runs once on each new player, a changed source or options make a new one
|
|
8
|
+
*/
|
|
9
|
+
export function useVideoPlayer(source, setup, playerBuilderOptions = () => undefined) {
|
|
10
|
+
return usePlayerResource(() => [source(), playerBuilderOptions(), setup]);
|
|
11
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { IVideoAirPlayButtonProps, IVideoViewHandle } from '../core';
|
|
2
|
+
/** Solid twin of `expo-video`'s `VideoView`, `ref` gets the handle of the view */
|
|
3
|
+
export declare const VideoView: (props: import("@symbiote-native/components").IAccessibilityProps & import("@symbiote-native/components").IAriaProps & import("@symbiote-native/components").IResponderProps & {
|
|
4
|
+
player?: import(".").VideoPlayer | null;
|
|
5
|
+
nativeControls?: boolean;
|
|
6
|
+
contentFit?: import(".").IVideoContentFit;
|
|
7
|
+
fullscreenOptions?: import(".").IVideoFullscreenOptions;
|
|
8
|
+
showsTimecodes?: boolean;
|
|
9
|
+
requiresLinearPlayback?: boolean;
|
|
10
|
+
buttonOptions?: import(".").IVideoButtonOptions;
|
|
11
|
+
surfaceType?: import(".").IVideoSurfaceType;
|
|
12
|
+
contentPosition?: {
|
|
13
|
+
dx?: number;
|
|
14
|
+
dy?: number;
|
|
15
|
+
};
|
|
16
|
+
onPictureInPictureStart?: () => void;
|
|
17
|
+
onPictureInPictureStop?: () => void;
|
|
18
|
+
allowsPictureInPicture?: boolean;
|
|
19
|
+
startsPictureInPictureAutomatically?: boolean;
|
|
20
|
+
allowsVideoFrameAnalysis?: boolean;
|
|
21
|
+
onFullscreenEnter?: () => void;
|
|
22
|
+
onFullscreenExit?: () => void;
|
|
23
|
+
onFirstFrameRender?: () => void;
|
|
24
|
+
useExoShutter?: boolean;
|
|
25
|
+
style?: import("@symbiote-native/engine").IStyleProp<import("@symbiote-native/engine").IViewStyle>;
|
|
26
|
+
testID?: string;
|
|
27
|
+
nativeID?: string;
|
|
28
|
+
onLayout?: (event: import("@symbiote-native/engine").ISymbioteEvent) => void;
|
|
29
|
+
} & {
|
|
30
|
+
ref?: ((handle: IVideoViewHandle) => void) | undefined;
|
|
31
|
+
}) => import("@symbiote-native/engine").ISymbioteNode | null;
|
|
32
|
+
/** Solid twin of `expo-video`'s `VideoAirPlayButton`, a plain view off iOS */
|
|
33
|
+
export declare const VideoAirPlayButton: (props: IVideoAirPlayButtonProps) => import("@symbiote-native/engine").ISymbioteNode | null;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { defineNativeViewComponent, defineOptionalDescriptorComponent, } from '@symbiote-native/solid';
|
|
2
|
+
import { createVideoView, renderVideoAirPlayButton } from '../core/index.js';
|
|
3
|
+
/** Solid twin of `expo-video`'s `VideoView`, `ref` gets the handle of the view */
|
|
4
|
+
export const VideoView = defineNativeViewComponent(createVideoView);
|
|
5
|
+
/** Solid twin of `expo-video`'s `VideoAirPlayButton`, a plain view off iOS */
|
|
6
|
+
export const VideoAirPlayButton = defineOptionalDescriptorComponent(renderVideoAirPlayButton);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as VideoView } from './video-view.svelte';
|
|
2
|
+
export { default as VideoAirPlayButton } from './video-airplay-button.svelte';
|
|
3
|
+
export { useVideoPlayer } from './use-video-player.svelte';
|
|
4
|
+
export type { IUseVideoPlayerResult } from './use-video-player.svelte';
|
|
5
|
+
export * from '../core';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @symbiote-native/video/svelte: плеер, view, миниатюры, кэш и кнопка AirPlay на общем ядре
|
|
2
|
+
export { default as VideoView } from './video-view.svelte';
|
|
3
|
+
export { default as VideoAirPlayButton } from './video-airplay-button.svelte';
|
|
4
|
+
export { useVideoPlayer } from './use-video-player.svelte';
|
|
5
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IVideoPlayerBuilderOptions, IVideoSource, VideoPlayer } from '../core';
|
|
2
|
+
export type IUseVideoPlayerResult = {
|
|
3
|
+
readonly current: VideoPlayer;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Svelte twin of `expo-video`'s `useVideoPlayer`, boxed getter shape of the other resource hooks
|
|
7
|
+
*
|
|
8
|
+
* `setup` runs once on each new player, a changed source or options make a new one
|
|
9
|
+
*/
|
|
10
|
+
export declare function useVideoPlayer(getSource: () => IVideoSource, setup?: (player: VideoPlayer) => void, getPlayerBuilderOptions?: () => IVideoPlayerBuilderOptions | undefined): IUseVideoPlayerResult;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createResourceHook } from '@symbiote-native/svelte/runes/create-resource-hook';
|
|
2
|
+
import { createVideoPlayerController } from '../core/video-player-controller.js';
|
|
3
|
+
const usePlayerResource = createResourceHook(createVideoPlayerController);
|
|
4
|
+
/**
|
|
5
|
+
* Svelte twin of `expo-video`'s `useVideoPlayer`, boxed getter shape of the other resource hooks
|
|
6
|
+
*
|
|
7
|
+
* `setup` runs once on each new player, a changed source or options make a new one
|
|
8
|
+
*/
|
|
9
|
+
export function useVideoPlayer(getSource, setup, getPlayerBuilderOptions = () => undefined) {
|
|
10
|
+
return usePlayerResource(() => [getSource(), getPlayerBuilderOptions(), setup]);
|
|
11
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// The native view name is mixed-case, which a literal tag would parse as a component reference,
|
|
3
|
+
// so the tag is dynamic
|
|
4
|
+
import { hostProps } from '@symbiote-native/svelte/native-view-bridge';
|
|
5
|
+
import { renderVideoAirPlayButton } from '../core';
|
|
6
|
+
import type { IVideoAirPlayButtonProps } from '../core';
|
|
7
|
+
|
|
8
|
+
const props: IVideoAirPlayButtonProps = $props();
|
|
9
|
+
const descriptor = $derived(renderVideoAirPlayButton({ ...props }));
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<svelte:element this={descriptor.type} {@attach hostProps(descriptor.props)} />
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// The native view name is mixed-case, which a literal tag would parse as a component reference,
|
|
3
|
+
// so the tag is dynamic
|
|
4
|
+
import { hostProps } from '@symbiote-native/svelte/native-view-bridge';
|
|
5
|
+
import { useNativeViewController } from '@symbiote-native/svelte/runes/use-native-view-controller';
|
|
6
|
+
import { createVideoView } from '../core';
|
|
7
|
+
import type { IVideoViewProps } from '../core';
|
|
8
|
+
|
|
9
|
+
const props: IVideoViewProps = $props();
|
|
10
|
+
const view = useNativeViewController(createVideoView, () => ({ ...props }));
|
|
11
|
+
|
|
12
|
+
// The functions of the view are instance members, `bind:this` reaches them
|
|
13
|
+
export const enterFullscreen = view.handle.enterFullscreen;
|
|
14
|
+
export const exitFullscreen = view.handle.exitFullscreen;
|
|
15
|
+
export const startPictureInPicture = view.handle.startPictureInPicture;
|
|
16
|
+
export const stopPictureInPicture = view.handle.stopPictureInPicture;
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
{#if view.descriptor}
|
|
20
|
+
<svelte:element
|
|
21
|
+
this={view.descriptor.type}
|
|
22
|
+
{@attach view.attachHost}
|
|
23
|
+
{@attach hostProps(view.descriptor.props)}
|
|
24
|
+
/>
|
|
25
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IVideoViewProps } from '../core';
|
|
2
|
+
declare const VideoView: import("svelte").Component<IVideoViewProps, {
|
|
3
|
+
enterFullscreen: () => Promise<void>;
|
|
4
|
+
exitFullscreen: () => Promise<void>;
|
|
5
|
+
startPictureInPicture: () => Promise<void>;
|
|
6
|
+
stopPictureInPicture: () => Promise<void>;
|
|
7
|
+
}, "">;
|
|
8
|
+
type VideoView = ReturnType<typeof VideoView>;
|
|
9
|
+
export default VideoView;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ComputedRef, type MaybeRefOrGetter } from '@vue/runtime-core';
|
|
2
|
+
import type { IVideoPlayerBuilderOptions, IVideoSource, VideoPlayer } from '../core';
|
|
3
|
+
/**
|
|
4
|
+
* Vue twin of `expo-video`'s `useVideoPlayer`, released when the owner unmounts
|
|
5
|
+
*
|
|
6
|
+
* `setup` runs once on each new player, a changed source or options make a new one
|
|
7
|
+
*/
|
|
8
|
+
export declare function useVideoPlayer(source: MaybeRefOrGetter<IVideoSource>, setup?: (player: VideoPlayer) => void, playerBuilderOptions?: MaybeRefOrGetter<IVideoPlayerBuilderOptions | undefined>): ComputedRef<VideoPlayer>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { toValue, } from '@vue/runtime-core';
|
|
2
|
+
import { createResourceHook } from '@symbiote-native/vue';
|
|
3
|
+
import { createVideoPlayerController } from '../core/video-player-controller.js';
|
|
4
|
+
const usePlayerResource = createResourceHook(createVideoPlayerController);
|
|
5
|
+
/**
|
|
6
|
+
* Vue twin of `expo-video`'s `useVideoPlayer`, released when the owner unmounts
|
|
7
|
+
*
|
|
8
|
+
* `setup` runs once on each new player, a changed source or options make a new one
|
|
9
|
+
*/
|
|
10
|
+
export function useVideoPlayer(source, setup, playerBuilderOptions) {
|
|
11
|
+
return usePlayerResource(() => [
|
|
12
|
+
toValue(source),
|
|
13
|
+
toValue(playerBuilderOptions),
|
|
14
|
+
setup,
|
|
15
|
+
]);
|
|
16
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type VNode } from '@vue/runtime-core';
|
|
2
|
+
/** Vue twin of `expo-video`'s `VideoView` */
|
|
3
|
+
export declare const VideoView: import("vue").DefineComponent<{}, () => VNode | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
4
|
+
/** Vue twin of `expo-video`'s `VideoAirPlayButton`, a plain view off iOS */
|
|
5
|
+
export declare const VideoAirPlayButton: import("vue").DefineComponent<{}, () => VNode, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineComponent } from '@vue/runtime-core';
|
|
2
|
+
import { defineNativeViewComponent, descriptorToVue, normalizeVueAttrs, } from '@symbiote-native/vue';
|
|
3
|
+
import { createVideoView, renderVideoAirPlayButton } from '../core/index.js';
|
|
4
|
+
/** Vue twin of `expo-video`'s `VideoView` */
|
|
5
|
+
export const VideoView = defineNativeViewComponent('VideoView', createVideoView);
|
|
6
|
+
/** Vue twin of `expo-video`'s `VideoAirPlayButton`, a plain view off iOS */
|
|
7
|
+
export const VideoAirPlayButton = defineComponent({
|
|
8
|
+
name: 'VideoAirPlayButton',
|
|
9
|
+
// Все атрибуты это пропсы нативного view, на обёртку ничего не должно просочиться
|
|
10
|
+
inheritAttrs: false,
|
|
11
|
+
setup(_props, { attrs }) {
|
|
12
|
+
return () => descriptorToVue(renderVideoAirPlayButton(normalizeVueAttrs(attrs)));
|
|
13
|
+
},
|
|
14
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// @symbiote-native/video/angular: плеер, view, миниатюры, кэш и кнопка AirPlay на общем ядре
|
|
2
|
+
export { VideoView } from './video-view';
|
|
3
|
+
export { VideoAirPlayButton } from './video-airplay-button';
|
|
4
|
+
export { injectVideoPlayer } from './inject-video-player';
|
|
5
|
+
export * from '../core';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|