mirror of
https://github.com/zoriya/react-native-video.git
synced 2026-06-02 11:06:11 +00:00
feat: add useVideoPlayer hook
This commit is contained in:
@@ -1 +1 @@
|
|||||||
export NODE_BINARY='/Users/krzysztof/.nvm/versions/node/v18.18.0/bin/node'
|
export NODE_BINARY='/Users/krzysztof/.asdf/installs/nodejs/18.19.0/bin/node'
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ ws_dir = ws_dir.parent until
|
|||||||
ws_dir.expand_path.to_s == '/'
|
ws_dir.expand_path.to_s == '/'
|
||||||
require "#{ws_dir}/node_modules/react-native-test-app/test_app.rb"
|
require "#{ws_dir}/node_modules/react-native-test-app/test_app.rb"
|
||||||
|
|
||||||
|
ENV['RCT_NEW_ARCH_ENABLED'] = '1'
|
||||||
|
|
||||||
|
Pod::UI.puts "Building with RCT_NEW_ARCH_ENABLED = #{ENV['RCT_NEW_ARCH_ENABLED']}..."
|
||||||
|
|
||||||
workspace 'VideoExample.xcworkspace'
|
workspace 'VideoExample.xcworkspace'
|
||||||
|
|
||||||
use_test_app!
|
use_test_app!
|
||||||
|
|||||||
+47
-45
@@ -1510,6 +1510,7 @@ PODS:
|
|||||||
- React-ImageManager
|
- React-ImageManager
|
||||||
- React-jsi
|
- React-jsi
|
||||||
- React-NativeModulesApple
|
- React-NativeModulesApple
|
||||||
|
- React-RCTAppDelegate
|
||||||
- React-RCTFabric
|
- React-RCTFabric
|
||||||
- React-rendererdebug
|
- React-rendererdebug
|
||||||
- React-utils
|
- React-utils
|
||||||
@@ -1555,6 +1556,7 @@ DEPENDENCIES:
|
|||||||
- React-idlecallbacksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`)
|
- React-idlecallbacksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`)
|
||||||
- React-ImageManager (from `../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`)
|
- React-ImageManager (from `../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`)
|
||||||
- React-jsc (from `../node_modules/react-native/ReactCommon/jsc`)
|
- React-jsc (from `../node_modules/react-native/ReactCommon/jsc`)
|
||||||
|
- React-jsc/Fabric (from `../node_modules/react-native/ReactCommon/jsc`)
|
||||||
- React-jserrorhandler (from `../node_modules/react-native/ReactCommon/jserrorhandler`)
|
- React-jserrorhandler (from `../node_modules/react-native/ReactCommon/jserrorhandler`)
|
||||||
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
|
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
|
||||||
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
|
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
|
||||||
@@ -1735,68 +1737,68 @@ SPEC CHECKSUMS:
|
|||||||
FBLazyVector: 7b438dceb9f904bd85ca3c31d64cce32a035472b
|
FBLazyVector: 7b438dceb9f904bd85ca3c31d64cce32a035472b
|
||||||
fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120
|
fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120
|
||||||
glog: 69ef571f3de08433d766d614c73a9838a06bf7eb
|
glog: 69ef571f3de08433d766d614c73a9838a06bf7eb
|
||||||
NitroModules: 0c3d743f46231d351a108ecc5b4ed5f3f5be499f
|
NitroModules: 61cb3152e6e9fc1a5e2a710d07a87ba919d9927c
|
||||||
NitroVideo: 1a93911c012df3f739b68352363ad44582dc3ee8
|
NitroVideo: f7eedff882912134106584f67ae85fc6cb812b07
|
||||||
RCT-Folly: 4464f4d875961fce86008d45f4ecf6cef6de0740
|
RCT-Folly: 34124ae2e667a0e5f0ea378db071d27548124321
|
||||||
RCTDeprecation: 4191f6e64b72d9743f6fe1a8a16e89e868f5e9e7
|
RCTDeprecation: 4191f6e64b72d9743f6fe1a8a16e89e868f5e9e7
|
||||||
RCTRequired: 9bb589570f2bb3abc6518761e3fd1ad9b7f7f06c
|
RCTRequired: 9bb589570f2bb3abc6518761e3fd1ad9b7f7f06c
|
||||||
RCTTypeSafety: 1c1a8741c86df0a0ac1a99cf3fb0e29eedbc2c88
|
RCTTypeSafety: 1c1a8741c86df0a0ac1a99cf3fb0e29eedbc2c88
|
||||||
React: b6810a201ee11e69ae8bfd4eb4aaab86610600bf
|
React: b6810a201ee11e69ae8bfd4eb4aaab86610600bf
|
||||||
React-callinvoker: d6c7898b63e6a2d37bc308f17c05be0ba3630b10
|
React-callinvoker: d6c7898b63e6a2d37bc308f17c05be0ba3630b10
|
||||||
React-Core: bcb0b025382981724a4b9f3708c2bf9e1eab1354
|
React-Core: f7b62828aca95a54f0a2dc56b7162348513a43c0
|
||||||
React-CoreModules: 2d68c251bc4080028f2835fa47504e8f20669a21
|
React-CoreModules: 30c44229d249317498dac4a984925c56e06f61c2
|
||||||
React-cxxreact: bb0dc212b515d6dba6c6ddc4034584e148857db9
|
React-cxxreact: 15841cbdf0ac85c9ea6f70cc418b75541a6ee031
|
||||||
React-debug: fd0ed8ecd5f8a23c7daf5ceaca8aa722a4d083fd
|
React-debug: fd0ed8ecd5f8a23c7daf5ceaca8aa722a4d083fd
|
||||||
React-defaultsnativemodule: 371dc516e5020f8b87f1d32f8fa6872cafcc2081
|
React-defaultsnativemodule: df50d96e3e7fdcb5b9bbc60e18a43d95dc4bbe0d
|
||||||
React-domnativemodule: 5d1288b9b8666b818a1004b56a03befc00eb5698
|
React-domnativemodule: 04bd7a7adf6e1d2ecd3f5f6ffb83bacc10951c36
|
||||||
React-Fabric: c12ce848f72cba42fb9e97a73a7c99abc6353f23
|
React-Fabric: e12790561050e447e16964c8e285e7cd77bc8272
|
||||||
React-FabricComponents: 7813d5575c8ea2cda0fef9be4ff9d10987cba512
|
React-FabricComponents: eaeb8db285343a6ba39357a0496f59f33cda2279
|
||||||
React-FabricImage: c511a5d612479cb4606edf3557c071956c8735f6
|
React-FabricImage: 7036c311ed8e32612790603adaa7dd5d7313d0a4
|
||||||
React-featureflags: cf78861db9318ae29982fa8953c92d31b276c9ac
|
React-featureflags: cf78861db9318ae29982fa8953c92d31b276c9ac
|
||||||
React-featureflagsnativemodule: e774cf495486b0e2a8b324568051d6b4c722fa93
|
React-featureflagsnativemodule: 752c70163fef657b0453ed85419ee0cad60a4b5a
|
||||||
React-graphics: 7572851bca7242416b648c45d6af87d93d29281e
|
React-graphics: 7ed2dc99f706228448b870882729a8303343b5a5
|
||||||
React-idlecallbacksnativemodule: d2009bad67ef232a0ee586f53193f37823e81ef1
|
React-idlecallbacksnativemodule: 3ecc99fdc2bd3603f01851cda748fa2382d3aea4
|
||||||
React-ImageManager: aedf54d34d4475c66f4c3da6b8359b95bee904e4
|
React-ImageManager: 9970421c57b6458d3a4d6ce319c9067217c4882f
|
||||||
React-jsc: 92ac98e0e03ee54fdaa4ac3936285a4fdb166fab
|
React-jsc: 92ac98e0e03ee54fdaa4ac3936285a4fdb166fab
|
||||||
React-jserrorhandler: 0c8949672a00f2a502c767350e591e3ec3d82fb3
|
React-jserrorhandler: 6764a4b7abd617332fb0935c9ba63a6369207a15
|
||||||
React-jsi: 497ac6512d81055258869d1f894472ef71ae85e1
|
React-jsi: 1d8843070910da8209a3df4266c7fbf5fbd169fd
|
||||||
React-jsiexecutor: bcb0a26448cafc995d5c0c8c31960d53fcc93bd9
|
React-jsiexecutor: 66953803059745021c67d0476e77a86f8fb5cdb4
|
||||||
React-jsinspector: 1bcd2707dd2601987bc92cbcd56737f353cc4541
|
React-jsinspector: b3c78200e89e71bf3d64e3531bca6423222be808
|
||||||
React-jsitracing: 3935b092f85bb1e53b8cf8a00f572413648af46b
|
React-jsitracing: bf77e00063522e4fd6d84fa129f0caaf360d275e
|
||||||
React-logger: 4072f39df335ca443932e0ccece41fbeb5ca8404
|
React-logger: 7e56c9eceafd7f45e98c16cb42ff3c9966c67119
|
||||||
React-Mapbuffer: 714f2fae68edcabfc332b754e9fbaa8cfc68fdd4
|
React-Mapbuffer: e68dd904f0f3a84dd35989288ed3bcf5e37f9737
|
||||||
React-microtasksnativemodule: 987cf7e0e0e7129250a48b807e70d3b906c726cf
|
React-microtasksnativemodule: a750218bbaf400d850e5649a1c97d71c40060047
|
||||||
React-nativeconfig: 4a9543185905fe41014c06776bf126083795aed9
|
React-nativeconfig: 4a9543185905fe41014c06776bf126083795aed9
|
||||||
React-NativeModulesApple: 651670a799672bd54469f2981d91493dda361ddf
|
React-NativeModulesApple: 8dfea6320633f58ffa78c0db2218cbd142dfeb6f
|
||||||
React-perflogger: 3bbb82f18e9ac29a1a6931568e99d6305ef4403b
|
React-perflogger: 3bbb82f18e9ac29a1a6931568e99d6305ef4403b
|
||||||
React-performancetimeline: d15a723422ed500f47cb271f3175abbeb217f5ba
|
React-performancetimeline: 05c0372923c2f3a9e8a5ae954258f0436003bffb
|
||||||
React-RCTActionSheet: cb2b38a53d03ec22f1159c89667b86c2c490d92d
|
React-RCTActionSheet: cb2b38a53d03ec22f1159c89667b86c2c490d92d
|
||||||
React-RCTAnimation: 6836c87c7364f471e9077fda80b7349bc674be33
|
React-RCTAnimation: c8be4f58eabb487d6346247ee8e7bac434737ed7
|
||||||
React-RCTAppDelegate: fb2037d3472bda5c31ea16a04cc48e19fe81c792
|
React-RCTAppDelegate: 391de59ae7ff1274eb8f82bf67b83061cd95f83f
|
||||||
React-RCTBlob: 984c80df29f3b3e3193bfbc2768bd302c889719b
|
React-RCTBlob: 04e23eb34ee06009523e3e89583338dc0e3601f8
|
||||||
React-RCTFabric: 5e691cfb4cd3a9060ddbfb04916284c3c6a933e8
|
React-RCTFabric: 43dd5c0d58deba4910b199220e751ba957b8c37b
|
||||||
React-RCTImage: 1b2c2c1716db859ffff2d7a06a30b0ec5c677fc5
|
React-RCTImage: 4fb571875362a78ccc01aded76b94a71ae466b8b
|
||||||
React-RCTLinking: 59c07577767e705b0ab95d11e5ad74c61bf2a022
|
React-RCTLinking: e825182eaf7f4047f6bb11bb6cd2ae5858008e66
|
||||||
React-RCTNetwork: f9a827e7d6bc428e0d99cd1fbe0427854354b8c1
|
React-RCTNetwork: 0e07b83395b6ff5016f7cea4ac99426a893a1438
|
||||||
React-RCTSettings: 614252fecc24840f61590c016aca1664a52cfb0f
|
React-RCTSettings: bd68792732f116994e992cf48e5bb70c4eb3910e
|
||||||
React-RCTText: 424549f68867265aa25969f50e7b9bf8bd70ae55
|
React-RCTText: c3cfce62ddb887cdd86403a6130a58a1f8fed9f3
|
||||||
React-RCTVibration: c8d156e6cce18f00b0310db7670fa997c7cda407
|
React-RCTVibration: 32a10228b7affa8de6401dba6f0d73b5a8433342
|
||||||
React-rendererconsistency: 993f54bb0df644df2922cd87ea55238d510d992b
|
React-rendererconsistency: 993f54bb0df644df2922cd87ea55238d510d992b
|
||||||
React-rendererdebug: 7a8cbb632b68d666ad0fc01b3f9dc1a1bcc9a9f9
|
React-rendererdebug: 9cd1f3e6d12c1d9b99fce6ceb373495b29b3d9ee
|
||||||
React-rncore: 1df26fe0ae861c599f9f2896f45e8834ef4b85f9
|
React-rncore: 1df26fe0ae861c599f9f2896f45e8834ef4b85f9
|
||||||
React-RuntimeApple: d20ee6d0cf3a361ec2e43c09d0f2778a863ce154
|
React-RuntimeApple: e7d1644c53adaa4252185caa2049feb94a12847f
|
||||||
React-RuntimeCore: 0fd059fd563e8ea69528ebd8645b319490e449ad
|
React-RuntimeCore: 1a39b968cf1d1e30a70d0ede2db1b89a43513f65
|
||||||
React-runtimeexecutor: 9a668b94ad5d93755443311715bd57680330286a
|
React-runtimeexecutor: 9a668b94ad5d93755443311715bd57680330286a
|
||||||
React-runtimescheduler: 99993f1fc3d49f13a02784e339e45b36c3aae203
|
React-runtimescheduler: 474215f76370292085bcf201bd642ff13ba7d5d2
|
||||||
React-utils: b2baee839fb869f732d617b97dcfa384b4b4fdb3
|
React-utils: 671c039d72cdff9bb1715934d62cea6c59de06c6
|
||||||
ReactCodegen: f177b8fd67788c5c6ff45a39c7482c5f8d77ace6
|
ReactCodegen: cdeb16519d53f09350a9fc7eb5708c6322c38676
|
||||||
ReactCommon: 627bd3192ef01a351e804e9709673d3741d38fec
|
ReactCommon: 96b80a9a46e9e7aaf77ec132cd0be6a34b323e9a
|
||||||
ReactNativeHost: 5df788fbfbf70e0d6b1cb7e66c8ff976da20533b
|
ReactNativeHost: 4c9aef6f7cd8d7862a53988f392a89513972440d
|
||||||
ReactTestApp-DevSupport: 42abce6b0c88dfb47c86e80aa22831b2abcc3144
|
ReactTestApp-DevSupport: 52ac76197e5accf579592aa3b9aa07fd0766f211
|
||||||
ReactTestApp-Resources: 7db90c026cccdf40cfa495705ad436ccc4d64154
|
ReactTestApp-Resources: 7db90c026cccdf40cfa495705ad436ccc4d64154
|
||||||
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
|
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
|
||||||
Yoga: 4ef80d96a5534f0e01b3055f17d1e19a9fc61b63
|
Yoga: 4ef80d96a5534f0e01b3055f17d1e19a9fc61b63
|
||||||
|
|
||||||
PODFILE CHECKSUM: a2c02c57accb043c57aee60bd47ca4e95390b49c
|
PODFILE CHECKSUM: e5a04e20d0f0f1f4e56349821526c34e42621202
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
it.todo('write a test');
|
|
||||||
+4
-17
@@ -1,19 +1,6 @@
|
|||||||
import { NitroModules } from 'react-native-nitro-modules';
|
|
||||||
import type { VideoPlayerSourceFactory } from './spec/nitro/VideoPlayerSource.nitro';
|
|
||||||
import type { VideoPlayerFactory } from './spec/nitro/VideoPlayer.nitro';
|
|
||||||
|
|
||||||
export { default as VideoView } from './VideoView';
|
export { default as VideoView } from './VideoView';
|
||||||
|
export { useVideoPlayer } from './utils/useVideoPlayer';
|
||||||
|
export { createPlayer, createSource } from './utils/factory';
|
||||||
|
|
||||||
export type { VideoPlayer } from './spec/nitro/VideoPlayer.nitro';
|
export type { VideoPlayer } from './spec/nitro/VideoPlayer.nitro';
|
||||||
|
export type { VideoSource } from './types/VideoConfig';
|
||||||
const VideoPlayerSourceFactory =
|
|
||||||
NitroModules.createHybridObject<VideoPlayerSourceFactory>(
|
|
||||||
'VideoPlayerSourceFactory'
|
|
||||||
);
|
|
||||||
|
|
||||||
const VideoPlayerFactory =
|
|
||||||
NitroModules.createHybridObject<VideoPlayerFactory>('VideoPlayerFactory');
|
|
||||||
|
|
||||||
export const createPlayer = (uri: string) => {
|
|
||||||
const source = VideoPlayerSourceFactory.fromUri(uri);
|
|
||||||
return VideoPlayerFactory.createPlayer(source);
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export type VideoSource = number | string;
|
||||||
|
|
||||||
|
export type VideoConfig = {
|
||||||
|
uri: VideoSource;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { NitroModules } from "react-native-nitro-modules";
|
||||||
|
import type { VideoPlayer, VideoPlayerFactory } from '../spec/nitro/VideoPlayer.nitro';
|
||||||
|
import type { VideoPlayerSourceFactory } from '../spec/nitro/VideoPlayerSource.nitro';
|
||||||
|
import type { VideoConfig, VideoSource } from "../types/VideoConfig";
|
||||||
|
import { Image } from "react-native";
|
||||||
|
|
||||||
|
// ----------- Factories -----------
|
||||||
|
const VideoPlayerSourceFactory =
|
||||||
|
NitroModules.createHybridObject<VideoPlayerSourceFactory>(
|
||||||
|
'VideoPlayerSourceFactory'
|
||||||
|
);
|
||||||
|
|
||||||
|
const VideoPlayerFactory =
|
||||||
|
NitroModules.createHybridObject<VideoPlayerFactory>('VideoPlayerFactory');
|
||||||
|
|
||||||
|
// ----------- Factories functions -----------
|
||||||
|
export const createPlayer = (source: VideoSource | VideoConfig): VideoPlayer => {
|
||||||
|
// If source is a string, we can directly create the player
|
||||||
|
if (typeof source === 'string') {
|
||||||
|
return VideoPlayerFactory.createPlayer(VideoPlayerSourceFactory.fromUri(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If source is a number (asset), we need to resolve the asset source and create the player
|
||||||
|
if (typeof source === 'number') {
|
||||||
|
return VideoPlayerFactory.createPlayer(VideoPlayerSourceFactory.fromUri(Image.resolveAssetSource(source).uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If source is an object (VideoConfig)
|
||||||
|
if (typeof source === 'object' && 'uri' in source) {
|
||||||
|
return createPlayer(source.uri)
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('RNV: Invalid source type');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createSource = (uri: string) => {
|
||||||
|
return VideoPlayerSourceFactory.fromUri(uri);
|
||||||
|
};
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import { useMemo, useRef, useEffect } from 'react';
|
||||||
|
import type { HybridObject } from 'react-native-nitro-modules';
|
||||||
|
|
||||||
|
// https://github.com/expo/expo/blob/main/packages/expo-modules-core/src/hooks/useReleasingSharedObject.ts
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A hook that helps to manage the lifecycle of a hybrid object in a React component.
|
||||||
|
*
|
||||||
|
* @param objectFactory - A function that creates a new hybrid object.
|
||||||
|
* @param dependencies - An array of dependencies that determine when the object should be recreated.
|
||||||
|
* @returns The hybrid object.
|
||||||
|
*/
|
||||||
|
export const useReleasingHybridObject = <THybridObject extends HybridObject>(
|
||||||
|
objectFactory: () => THybridObject,
|
||||||
|
dependencies: unknown[]
|
||||||
|
): THybridObject => {
|
||||||
|
const objectRef = useRef<THybridObject | null>(null);
|
||||||
|
const isFastRefresh = useRef(false);
|
||||||
|
const previousDependencies = useRef(dependencies);
|
||||||
|
|
||||||
|
if (objectRef.current == null) {
|
||||||
|
objectRef.current = objectFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
const object = useMemo(() => {
|
||||||
|
let newObject = objectRef.current;
|
||||||
|
const depsAreEqual =
|
||||||
|
previousDependencies.current?.length === dependencies.length &&
|
||||||
|
dependencies.every((value, index) => value === previousDependencies.current[index]);
|
||||||
|
|
||||||
|
if (!newObject || !depsAreEqual) {
|
||||||
|
// Destroy the old object
|
||||||
|
objectRef.current?.dispose();
|
||||||
|
objectRef.current = null;
|
||||||
|
|
||||||
|
// Create a new object
|
||||||
|
newObject = objectFactory();
|
||||||
|
objectRef.current = newObject;
|
||||||
|
|
||||||
|
// Update the previous dependencies
|
||||||
|
previousDependencies.current = dependencies;
|
||||||
|
} else {
|
||||||
|
isFastRefresh.current = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newObject;
|
||||||
|
}, dependencies);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
isFastRefresh.current = false;
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (!isFastRefresh.current && objectRef.current) {
|
||||||
|
objectRef.current.dispose();
|
||||||
|
objectRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return object;
|
||||||
|
};
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import type { VideoPlayer } from "../spec/nitro/VideoPlayer.nitro";
|
||||||
|
import { useReleasingHybridObject } from "./useReleasingHybridObject";
|
||||||
|
import { createPlayer } from "./factory";
|
||||||
|
import type { VideoSource } from "../types/VideoConfig";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A hook that creates and manages a video player.
|
||||||
|
*
|
||||||
|
* @param source - The source of the video.
|
||||||
|
* @param setup - A function that allow to setup the video player after it is created.
|
||||||
|
* @returns VideoPlayer (see {@link VideoPlayer})
|
||||||
|
*/
|
||||||
|
export const useVideoPlayer = (
|
||||||
|
source: VideoSource,
|
||||||
|
setup: (player: VideoPlayer) => void | undefined
|
||||||
|
) => {
|
||||||
|
return useReleasingHybridObject(
|
||||||
|
() => {
|
||||||
|
const videoPlayer = createPlayer(source);
|
||||||
|
setup?.(videoPlayer);
|
||||||
|
return videoPlayer;
|
||||||
|
},
|
||||||
|
[source]
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user