feat: bump up fabric example react-native iOS (#3951)
* feat: 🔥 version bump react native for ios FabricExample * feat: ✨ copied newly created basic example TS files
This commit is contained in:
parent
322d7e993d
commit
e5a2ee3bd3
@ -1,6 +1,6 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
extends: '@react-native-community',
|
extends: '@react-native',
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
plugins: ['@typescript-eslint'],
|
plugins: ['@typescript-eslint'],
|
||||||
overrides: [
|
overrides: [
|
||||||
|
3
examples/FabricExample/.gitignore
vendored
3
examples/FabricExample/.gitignore
vendored
@ -62,3 +62,6 @@ buck-out/
|
|||||||
# Ruby / CocoaPods
|
# Ruby / CocoaPods
|
||||||
/ios/Pods/
|
/ios/Pods/
|
||||||
/vendor/bundle/
|
/vendor/bundle/
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
@ -1,6 +1,7 @@
|
|||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
|
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
|
||||||
ruby '2.7.5'
|
ruby ">= 2.6.10"
|
||||||
|
|
||||||
gem 'cocoapods', '~> 1.11', '>= 1.11.2'
|
gem 'cocoapods', '~> 1.13'
|
||||||
|
gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
|
||||||
|
@ -1,26 +1,29 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
CFPropertyList (3.0.6)
|
CFPropertyList (3.0.7)
|
||||||
|
base64
|
||||||
|
nkf
|
||||||
rexml
|
rexml
|
||||||
activesupport (7.0.4.3)
|
activesupport (7.0.4.3)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 1.6, < 2)
|
i18n (>= 1.6, < 2)
|
||||||
minitest (>= 5.1)
|
minitest (>= 5.1)
|
||||||
tzinfo (~> 2.0)
|
tzinfo (~> 2.0)
|
||||||
addressable (2.8.4)
|
addressable (2.8.7)
|
||||||
public_suffix (>= 2.0.2, < 6.0)
|
public_suffix (>= 2.0.2, < 7.0)
|
||||||
algoliasearch (1.27.5)
|
algoliasearch (1.27.5)
|
||||||
httpclient (~> 2.8, >= 2.8.3)
|
httpclient (~> 2.8, >= 2.8.3)
|
||||||
json (>= 1.5.1)
|
json (>= 1.5.1)
|
||||||
atomos (0.1.3)
|
atomos (0.1.3)
|
||||||
|
base64 (0.2.0)
|
||||||
claide (1.1.0)
|
claide (1.1.0)
|
||||||
cocoapods (1.12.0)
|
cocoapods (1.15.2)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
claide (>= 1.0.2, < 2.0)
|
claide (>= 1.0.2, < 2.0)
|
||||||
cocoapods-core (= 1.12.0)
|
cocoapods-core (= 1.15.2)
|
||||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||||
cocoapods-downloader (>= 1.6.0, < 2.0)
|
cocoapods-downloader (>= 2.1, < 3.0)
|
||||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||||
cocoapods-search (>= 1.0.0, < 2.0)
|
cocoapods-search (>= 1.0.0, < 2.0)
|
||||||
cocoapods-trunk (>= 1.6.0, < 2.0)
|
cocoapods-trunk (>= 1.6.0, < 2.0)
|
||||||
@ -32,8 +35,8 @@ GEM
|
|||||||
molinillo (~> 0.8.0)
|
molinillo (~> 0.8.0)
|
||||||
nap (~> 1.0)
|
nap (~> 1.0)
|
||||||
ruby-macho (>= 2.3.0, < 3.0)
|
ruby-macho (>= 2.3.0, < 3.0)
|
||||||
xcodeproj (>= 1.21.0, < 2.0)
|
xcodeproj (>= 1.23.0, < 2.0)
|
||||||
cocoapods-core (1.12.0)
|
cocoapods-core (1.15.2)
|
||||||
activesupport (>= 5.0, < 8)
|
activesupport (>= 5.0, < 8)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
algoliasearch (~> 1.0)
|
algoliasearch (~> 1.0)
|
||||||
@ -44,7 +47,7 @@ GEM
|
|||||||
public_suffix (~> 4.0)
|
public_suffix (~> 4.0)
|
||||||
typhoeus (~> 1.0)
|
typhoeus (~> 1.0)
|
||||||
cocoapods-deintegrate (1.0.5)
|
cocoapods-deintegrate (1.0.5)
|
||||||
cocoapods-downloader (1.6.3)
|
cocoapods-downloader (2.1)
|
||||||
cocoapods-plugins (1.0.0)
|
cocoapods-plugins (1.0.0)
|
||||||
nap
|
nap
|
||||||
cocoapods-search (1.0.1)
|
cocoapods-search (1.0.1)
|
||||||
@ -57,27 +60,30 @@ GEM
|
|||||||
escape (0.0.4)
|
escape (0.0.4)
|
||||||
ethon (0.16.0)
|
ethon (0.16.0)
|
||||||
ffi (>= 1.15.0)
|
ffi (>= 1.15.0)
|
||||||
ffi (1.15.5)
|
ffi (1.17.0)
|
||||||
fourflusher (2.3.1)
|
fourflusher (2.3.1)
|
||||||
fuzzy_match (2.0.4)
|
fuzzy_match (2.0.4)
|
||||||
gh_inspector (1.1.3)
|
gh_inspector (1.1.3)
|
||||||
httpclient (2.8.3)
|
httpclient (2.8.3)
|
||||||
i18n (1.12.0)
|
i18n (1.12.0)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
json (2.6.3)
|
json (2.7.2)
|
||||||
minitest (5.18.0)
|
minitest (5.18.0)
|
||||||
molinillo (0.8.0)
|
molinillo (0.8.0)
|
||||||
nanaimo (0.3.0)
|
nanaimo (0.3.0)
|
||||||
nap (1.1.0)
|
nap (1.1.0)
|
||||||
netrc (0.11.0)
|
netrc (0.11.0)
|
||||||
|
nkf (0.2.0)
|
||||||
public_suffix (4.0.7)
|
public_suffix (4.0.7)
|
||||||
rexml (3.2.5)
|
rexml (3.2.9)
|
||||||
|
strscan
|
||||||
ruby-macho (2.5.1)
|
ruby-macho (2.5.1)
|
||||||
typhoeus (1.4.0)
|
strscan (3.1.0)
|
||||||
|
typhoeus (1.4.1)
|
||||||
ethon (>= 0.9.0)
|
ethon (>= 0.9.0)
|
||||||
tzinfo (2.0.6)
|
tzinfo (2.0.6)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
xcodeproj (1.22.0)
|
xcodeproj (1.24.0)
|
||||||
CFPropertyList (>= 2.3.3, < 4.0)
|
CFPropertyList (>= 2.3.3, < 4.0)
|
||||||
atomos (~> 0.1.3)
|
atomos (~> 0.1.3)
|
||||||
claide (>= 1.0.2, < 2.0)
|
claide (>= 1.0.2, < 2.0)
|
||||||
@ -89,7 +95,8 @@ PLATFORMS
|
|||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
cocoapods (~> 1.11, >= 1.11.2)
|
activesupport (>= 6.1.7.3, < 7.1.0)
|
||||||
|
cocoapods (~> 1.13)
|
||||||
|
|
||||||
RUBY VERSION
|
RUBY VERSION
|
||||||
ruby 2.7.5p203
|
ruby 2.7.5p203
|
||||||
|
@ -6,6 +6,9 @@ import 'react-native';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import App from '../App';
|
import App from '../App';
|
||||||
|
|
||||||
|
// Note: import explicitly to use the types shipped with jest.
|
||||||
|
import {it} from '@jest/globals';
|
||||||
|
|
||||||
// Note: test renderer must be required after react-native.
|
// Note: test renderer must be required after react-native.
|
||||||
import renderer from 'react-test-renderer';
|
import renderer from 'react-test-renderer';
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
16
|
|
@ -2,7 +2,7 @@ const path = require('path');
|
|||||||
const pak = require('../../package.json');
|
const pak = require('../../package.json');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
presets: ['module:metro-react-native-babel-preset'],
|
presets: ['module:@react-native/babel-preset'],
|
||||||
plugins: [
|
plugins: [
|
||||||
[
|
[
|
||||||
'module-resolver',
|
'module-resolver',
|
||||||
|
@ -437,7 +437,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = FabricExampleTests/Info.plist;
|
INFOPLIST_FILE = FabricExampleTests/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@ -461,7 +461,7 @@
|
|||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
INFOPLIST_FILE = FabricExampleTests/Info.plist;
|
INFOPLIST_FILE = FabricExampleTests/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@ -535,7 +535,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
@ -580,7 +580,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
/usr/lib/swift,
|
/usr/lib/swift,
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@ -592,18 +592,25 @@
|
|||||||
);
|
);
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
OTHER_CFLAGS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"-DRN_FABRIC_ENABLED",
|
||||||
|
);
|
||||||
OTHER_CPLUSPLUSFLAGS = (
|
OTHER_CPLUSPLUSFLAGS = (
|
||||||
"$(OTHER_CFLAGS)",
|
"$(OTHER_CFLAGS)",
|
||||||
"-DFOLLY_NO_CONFIG",
|
"-DFOLLY_NO_CONFIG",
|
||||||
"-DFOLLY_MOBILE=1",
|
"-DFOLLY_MOBILE=1",
|
||||||
"-DFOLLY_USE_LIBCPP=1",
|
"-DFOLLY_USE_LIBCPP=1",
|
||||||
|
"-DRN_FABRIC_ENABLED",
|
||||||
);
|
);
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
" ",
|
"-Wl",
|
||||||
|
"-ld_classic",
|
||||||
);
|
);
|
||||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
USE_HERMES = true;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@ -612,7 +619,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
@ -653,7 +660,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
/usr/lib/swift,
|
/usr/lib/swift,
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@ -664,18 +671,25 @@
|
|||||||
"\"$(inherited)\"",
|
"\"$(inherited)\"",
|
||||||
);
|
);
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
OTHER_CFLAGS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"-DRN_FABRIC_ENABLED",
|
||||||
|
);
|
||||||
OTHER_CPLUSPLUSFLAGS = (
|
OTHER_CPLUSPLUSFLAGS = (
|
||||||
"$(OTHER_CFLAGS)",
|
"$(OTHER_CFLAGS)",
|
||||||
"-DFOLLY_NO_CONFIG",
|
"-DFOLLY_NO_CONFIG",
|
||||||
"-DFOLLY_MOBILE=1",
|
"-DFOLLY_MOBILE=1",
|
||||||
"-DFOLLY_USE_LIBCPP=1",
|
"-DFOLLY_USE_LIBCPP=1",
|
||||||
|
"-DRN_FABRIC_ENABLED",
|
||||||
);
|
);
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
" ",
|
"-Wl",
|
||||||
|
"-ld_classic",
|
||||||
);
|
);
|
||||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
USE_HERMES = true;
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -1,8 +1,6 @@
|
|||||||
#import <React/RCTBridgeDelegate.h>
|
#import <RCTAppDelegate.h>
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
|
@interface AppDelegate : RCTAppDelegate
|
||||||
|
|
||||||
@property (nonatomic, strong) UIWindow *window;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -1,88 +1,25 @@
|
|||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
#import <React/RCTBridge.h>
|
|
||||||
#import <React/RCTBundleURLProvider.h>
|
#import <React/RCTBundleURLProvider.h>
|
||||||
#import <React/RCTRootView.h>
|
|
||||||
|
|
||||||
#import <React/RCTAppSetupUtils.h>
|
|
||||||
|
|
||||||
#if RCT_NEW_ARCH_ENABLED
|
|
||||||
#import <React/CoreModulesPlugins.h>
|
|
||||||
#import <React/RCTCxxBridgeDelegate.h>
|
|
||||||
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
|
|
||||||
#import <React/RCTSurfacePresenter.h>
|
|
||||||
#import <React/RCTSurfacePresenterBridgeAdapter.h>
|
|
||||||
#import <ReactCommon/RCTTurboModuleManager.h>
|
|
||||||
|
|
||||||
#import <react/config/ReactNativeConfig.h>
|
|
||||||
|
|
||||||
static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
|
||||||
|
|
||||||
@interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate> {
|
|
||||||
RCTTurboModuleManager *_turboModuleManager;
|
|
||||||
RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
|
|
||||||
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
|
|
||||||
facebook::react::ContextContainer::Shared _contextContainer;
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@implementation AppDelegate
|
@implementation AppDelegate
|
||||||
|
|
||||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||||
{
|
{
|
||||||
RCTAppSetupPrepareApp(application, true);
|
self.moduleName = @"FabricExample";
|
||||||
|
// You can add your custom initial props in the dictionary below.
|
||||||
|
// They will be passed down to the ViewController used by React Native.
|
||||||
|
self.initialProps = @{};
|
||||||
|
|
||||||
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
|
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||||
|
|
||||||
#if RCT_NEW_ARCH_ENABLED
|
|
||||||
_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
|
|
||||||
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
|
|
||||||
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
|
|
||||||
_bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
|
|
||||||
bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NSDictionary *initProps = [self prepareInitialProps];
|
|
||||||
UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"FabricExample", initProps, true);
|
|
||||||
|
|
||||||
if (@available(iOS 13.0, *)) {
|
|
||||||
rootView.backgroundColor = [UIColor systemBackgroundColor];
|
|
||||||
} else {
|
|
||||||
rootView.backgroundColor = [UIColor whiteColor];
|
|
||||||
}
|
|
||||||
|
|
||||||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
|
||||||
UIViewController *rootViewController = [UIViewController new];
|
|
||||||
rootViewController.view = rootView;
|
|
||||||
self.window.rootViewController = rootViewController;
|
|
||||||
[self.window makeKeyAndVisible];
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
|
|
||||||
///
|
|
||||||
/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
|
|
||||||
/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
|
|
||||||
/// @return: `true` if the `concurrentRoot` feture is enabled. Otherwise, it returns `false`.
|
|
||||||
- (BOOL)concurrentRootEnabled
|
|
||||||
{
|
|
||||||
// Switch this bool to turn on and off the concurrent root
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSDictionary *)prepareInitialProps
|
|
||||||
{
|
|
||||||
NSMutableDictionary *initProps = [NSMutableDictionary new];
|
|
||||||
|
|
||||||
#ifdef RCT_NEW_ARCH_ENABLED
|
|
||||||
initProps[kRNConcurrentRoot] = @([self concurrentRootEnabled]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return initProps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
|
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
|
||||||
|
{
|
||||||
|
return [self getBundleURL];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSURL *)getBundleURL
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
|
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
|
||||||
@ -91,43 +28,4 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RCT_NEW_ARCH_ENABLED
|
|
||||||
|
|
||||||
#pragma mark - RCTCxxBridgeDelegate
|
|
||||||
|
|
||||||
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
|
|
||||||
{
|
|
||||||
_turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
|
|
||||||
delegate:self
|
|
||||||
jsInvoker:bridge.jsCallInvoker];
|
|
||||||
return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark RCTTurboModuleManagerDelegate
|
|
||||||
|
|
||||||
- (Class)getModuleClassFromName:(const char *)name
|
|
||||||
{
|
|
||||||
return RCTCoreModulesClassProvider(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
|
|
||||||
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
|
|
||||||
initParams:
|
|
||||||
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
|
|
||||||
{
|
|
||||||
return RCTAppSetupDefaultModuleFromClass(moduleClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -26,17 +26,13 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSExceptionDomains</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
<dict>
|
<false/>
|
||||||
<key>localhost</key>
|
<key>NSAllowsLocalNetworking</key>
|
||||||
<dict>
|
|
||||||
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>NSLocationWhenInUseUsageDescription</key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
<string/>
|
<string></string>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIRequiredDeviceCapabilities</key>
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
@ -1,28 +1,25 @@
|
|||||||
ENV['RCT_NEW_ARCH_ENABLED'] = "1"
|
ENV['RCT_NEW_ARCH_ENABLED'] = "1"
|
||||||
require_relative '../node_modules/react-native/scripts/react_native_pods'
|
|
||||||
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
|
|
||||||
|
|
||||||
platform :ios, '12.4'
|
# Resolve react_native_pods.rb with node to allow for hoisting
|
||||||
|
require Pod::Executable.execute_command('node', ['-p',
|
||||||
|
'require.resolve(
|
||||||
|
"react-native/scripts/react_native_pods.rb",
|
||||||
|
{paths: [process.argv[1]]},
|
||||||
|
)', __dir__]).strip
|
||||||
|
|
||||||
|
platform :ios, '13.4'
|
||||||
install! 'cocoapods', :deterministic_uuids => false
|
install! 'cocoapods', :deterministic_uuids => false
|
||||||
|
|
||||||
target 'FabricExample' do
|
target 'FabricExample' do
|
||||||
config = use_native_modules!
|
config = use_native_modules!
|
||||||
|
|
||||||
# Flags change depending on the env values.
|
|
||||||
flags = get_default_flags()
|
|
||||||
|
|
||||||
use_react_native!(
|
use_react_native!(
|
||||||
:path => config[:reactNativePath],
|
:path => config[:reactNativePath],
|
||||||
# Hermes is now enabled by default. Disable by setting this flag to false.
|
|
||||||
# Upcoming versions of React Native may rely on get_default_flags(), but
|
|
||||||
# we make it explicit here to aid in the React Native upgrade process.
|
|
||||||
:hermes_enabled => true,
|
|
||||||
:fabric_enabled => flags[:fabric_enabled],
|
|
||||||
# Enables Flipper.
|
# Enables Flipper.
|
||||||
#
|
#
|
||||||
# Note that if you have use_frameworks! enabled, Flipper will not work and
|
# Note that if you have use_frameworks! enabled, Flipper will not work and
|
||||||
# you should disable the next line.
|
# you should disable the next line.
|
||||||
:flipper_configuration => FlipperConfiguration.enabled,
|
# :flipper_configuration => FlipperConfiguration.enabled,
|
||||||
# An absolute path to your application root.
|
# An absolute path to your application root.
|
||||||
:app_path => "#{Pod::Config.instance.installation_root}/.."
|
:app_path => "#{Pod::Config.instance.installation_root}/.."
|
||||||
)
|
)
|
||||||
@ -35,10 +32,8 @@ target 'FabricExample' do
|
|||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
react_native_post_install(
|
react_native_post_install(
|
||||||
installer,
|
installer,
|
||||||
# Set `mac_catalyst_enabled` to `true` in order to apply patches
|
config[:reactNativePath],
|
||||||
# necessary for Mac Catalyst builds
|
|
||||||
:mac_catalyst_enabled => false
|
:mac_catalyst_enabled => false
|
||||||
)
|
)
|
||||||
__apply_Xcode_12_5_M1_post_install_workaround(installer)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
File diff suppressed because it is too large
Load Diff
3
examples/FabricExample/jest.config.js
Normal file
3
examples/FabricExample/jest.config.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
preset: 'react-native',
|
||||||
|
};
|
@ -2,6 +2,7 @@ const path = require('path');
|
|||||||
const escape = require('escape-string-regexp');
|
const escape = require('escape-string-regexp');
|
||||||
const exclusionList = require('metro-config/src/defaults/exclusionList');
|
const exclusionList = require('metro-config/src/defaults/exclusionList');
|
||||||
const pak = require('../../package.json');
|
const pak = require('../../package.json');
|
||||||
|
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
|
||||||
|
|
||||||
const root = path.resolve(__dirname, '../../');
|
const root = path.resolve(__dirname, '../../');
|
||||||
|
|
||||||
@ -9,7 +10,7 @@ const modules = Object.keys({
|
|||||||
...pak.peerDependencies,
|
...pak.peerDependencies,
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = {
|
const config = {
|
||||||
projectRoot: __dirname,
|
projectRoot: __dirname,
|
||||||
watchFolders: [root],
|
watchFolders: [root],
|
||||||
|
|
||||||
@ -37,4 +38,6 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
|
module.exports = mergeConfig(getDefaultConfig(__dirname), config);
|
||||||
|
@ -11,27 +11,33 @@
|
|||||||
"pod-install": "bundle exec npx pod-install --project-directory=ios --verbose"
|
"pod-install": "bundle exec npx pod-install --project-directory=ios --verbose"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@react-native-picker/picker": "2.7.5",
|
||||||
"react": "18.1.0",
|
"react": "18.1.0",
|
||||||
"react-native": "^0.71.6"
|
"react-native": "0.73.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.12.9",
|
"@babel/core": "^7.12.9",
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"@react-native-community/eslint-config": "^2.0.0",
|
"@react-native-community/eslint-config": "^2.0.0",
|
||||||
|
"@react-native/babel-preset": "0.73.19",
|
||||||
|
"@react-native/eslint-config": "0.73.2",
|
||||||
|
"@react-native/metro-config": "0.73.3",
|
||||||
|
"@react-native/typescript-config": "0.73.1",
|
||||||
"@tsconfig/react-native": "^2.0.2",
|
"@tsconfig/react-native": "^2.0.2",
|
||||||
"@types/jest": "^26.0.23",
|
"@types/jest": "^26.0.23",
|
||||||
"@types/react": "^18.0.21",
|
"@types/react": "^18.2.6",
|
||||||
"@types/react-native": "^0.70.6",
|
"@types/react-native": "^0.70.6",
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
"@types/react-test-renderer": "^18.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.37.0",
|
"@typescript-eslint/eslint-plugin": "^5.37.0",
|
||||||
"@typescript-eslint/parser": "^5.37.0",
|
"@typescript-eslint/parser": "^5.37.0",
|
||||||
"babel-jest": "^26.6.3",
|
"babel-jest": "^29.6.3",
|
||||||
"babel-plugin-module-resolver": "^5.0.0",
|
"babel-plugin-module-resolver": "^5.0.0",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
"jest": "^26.6.3",
|
"jest": "^29.6.3",
|
||||||
"metro-react-native-babel-preset": "0.72.3",
|
"metro-react-native-babel-preset": "0.72.3",
|
||||||
|
"prettier": "2.8.8",
|
||||||
"react-test-renderer": "18.1.0",
|
"react-test-renderer": "18.1.0",
|
||||||
"typescript": "^4.8.3"
|
"typescript": "5.0.4"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"preset": "react-native",
|
"preset": "react-native",
|
||||||
@ -43,5 +49,8 @@
|
|||||||
"json",
|
"json",
|
||||||
"node"
|
"node"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
75
examples/FabricExample/src/MultiValueControl.tsx
Normal file
75
examples/FabricExample/src/MultiValueControl.tsx
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import React, {FunctionComponent} from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
StyleSheet,
|
||||||
|
Text,
|
||||||
|
TextStyle,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
} from 'react-native';
|
||||||
|
import {ResizeMode} from 'react-native-video';
|
||||||
|
|
||||||
|
export type MultiValueControlPropType = number | string | ResizeMode;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MultiValueControl displays a list clickable text view
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface MultiValueControlType<T> {
|
||||||
|
// a list a string or number to be displayed
|
||||||
|
values: Array<T>;
|
||||||
|
// The selected value in values
|
||||||
|
selected?: T;
|
||||||
|
// callback to press onPress
|
||||||
|
onPress: (arg: MultiValueControlPropType) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MultiValueControl: FunctionComponent<
|
||||||
|
MultiValueControlType<MultiValueControlPropType>
|
||||||
|
> = ({values, selected, onPress}) => {
|
||||||
|
const selectedStyle: TextStyle = StyleSheet.flatten([
|
||||||
|
styles.option,
|
||||||
|
{fontWeight: 'bold'},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const unselectedStyle: TextStyle = StyleSheet.flatten([
|
||||||
|
styles.option,
|
||||||
|
{fontWeight: 'normal'},
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
{values.map((value: MultiValueControlPropType) => {
|
||||||
|
const _style = value === selected ? selectedStyle : unselectedStyle;
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
key={value}
|
||||||
|
onPress={() => {
|
||||||
|
onPress?.(value);
|
||||||
|
}}>
|
||||||
|
<Text style={_style}>{value}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
option: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
fontSize: 11,
|
||||||
|
color: 'white',
|
||||||
|
paddingLeft: 2,
|
||||||
|
paddingRight: 2,
|
||||||
|
lineHeight: 12,
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default MultiValueControl;
|
73
examples/FabricExample/src/ToggleControl.tsx
Normal file
73
examples/FabricExample/src/ToggleControl.tsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
StyleSheet,
|
||||||
|
Text,
|
||||||
|
TextStyle,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ToggleControl displays a 2 states clickable text
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface ToggleControlType {
|
||||||
|
// boolean indicating if text is selected state
|
||||||
|
isSelected?: boolean;
|
||||||
|
// value of text when selected
|
||||||
|
selectedText?: string;
|
||||||
|
// value of text when NOT selected
|
||||||
|
unselectedText?: string;
|
||||||
|
// default text if no only one text field is needed
|
||||||
|
text?: string;
|
||||||
|
// callback called when pressing the component
|
||||||
|
onPress: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ToggleControl = ({
|
||||||
|
isSelected,
|
||||||
|
selectedText,
|
||||||
|
unselectedText,
|
||||||
|
text,
|
||||||
|
onPress,
|
||||||
|
}: ToggleControlType) => {
|
||||||
|
const selectedStyle: TextStyle = StyleSheet.flatten([
|
||||||
|
styles.controlOption,
|
||||||
|
{fontWeight: 'bold'},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const unselectedStyle: TextStyle = StyleSheet.flatten([
|
||||||
|
styles.controlOption,
|
||||||
|
{fontWeight: 'normal'},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const style = isSelected ? selectedStyle : unselectedStyle;
|
||||||
|
const _text = text ? text : isSelected ? selectedText : unselectedText;
|
||||||
|
return (
|
||||||
|
<View style={styles.resizeModeControl}>
|
||||||
|
<TouchableOpacity onPress={onPress}>
|
||||||
|
<Text style={style}>{_text}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
controlOption: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
fontSize: 11,
|
||||||
|
color: 'white',
|
||||||
|
paddingLeft: 2,
|
||||||
|
paddingRight: 2,
|
||||||
|
lineHeight: 12,
|
||||||
|
},
|
||||||
|
resizeModeControl: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ToggleControl;
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,53 @@
|
|||||||
|
import {Picker} from '@react-native-picker/picker';
|
||||||
|
import {Text} from 'react-native';
|
||||||
|
import {AudioTrack, SelectedTrack} from 'react-native-video';
|
||||||
|
import styles from '../styles';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export interface AudioTrackSelectorType {
|
||||||
|
audioTracks: Array<AudioTrack>;
|
||||||
|
selectedAudioTrack: SelectedTrack | undefined;
|
||||||
|
onValueChange: (arg0: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AudioTrackSelector = ({
|
||||||
|
audioTracks,
|
||||||
|
selectedAudioTrack,
|
||||||
|
onValueChange,
|
||||||
|
}: AudioTrackSelectorType) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Text style={styles.controlOption}>AudioTrack</Text>
|
||||||
|
<Picker
|
||||||
|
style={styles.picker}
|
||||||
|
itemStyle={styles.pickerItem}
|
||||||
|
selectedValue={selectedAudioTrack?.value}
|
||||||
|
onValueChange={itemValue => {
|
||||||
|
if (itemValue !== 'empty') {
|
||||||
|
console.log('on audio value change ' + itemValue);
|
||||||
|
onValueChange(`${itemValue}`);
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
{audioTracks?.length <= 0 ? (
|
||||||
|
<Picker.Item label={'empty'} value={'empty'} key={'empty'} />
|
||||||
|
) : (
|
||||||
|
<Picker.Item label={'none'} value={'none'} key={'none'} />
|
||||||
|
)}
|
||||||
|
{audioTracks.map(track => {
|
||||||
|
if (!track) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Picker.Item
|
||||||
|
label={`${track.language} - ${track.title} - ${track.selected}`}
|
||||||
|
value={`${track.index}`}
|
||||||
|
key={`${track.index}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Picker>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AudioTrackSelector;
|
154
examples/FabricExample/src/components/Seeker.tsx
Normal file
154
examples/FabricExample/src/components/Seeker.tsx
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import React, {useCallback, useEffect, useState} from 'react';
|
||||||
|
import {PanResponder, View} from 'react-native';
|
||||||
|
import styles from '../styles';
|
||||||
|
|
||||||
|
interface SeekerProps {
|
||||||
|
currentTime: number;
|
||||||
|
duration: number;
|
||||||
|
isLoading: boolean;
|
||||||
|
isUISeeking: boolean;
|
||||||
|
videoSeek: (arg0: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Seeker = ({
|
||||||
|
currentTime,
|
||||||
|
duration,
|
||||||
|
isLoading,
|
||||||
|
isUISeeking,
|
||||||
|
videoSeek,
|
||||||
|
}: SeekerProps) => {
|
||||||
|
const [seeking, setSeeking] = useState(false);
|
||||||
|
const [seekerPosition, setSeekerPosition] = useState(0);
|
||||||
|
const [seekerWidth, setSeekerWidth] = useState(0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the position of the seekbar's components
|
||||||
|
* (both fill and handle) according to the
|
||||||
|
* position supplied.
|
||||||
|
*
|
||||||
|
* @param {float} position position in px of seeker handle}
|
||||||
|
*/
|
||||||
|
const updateSeekerPosition = useCallback(
|
||||||
|
(position = 0) => {
|
||||||
|
if (position <= 0) {
|
||||||
|
position = 0;
|
||||||
|
} else if (position >= seekerWidth) {
|
||||||
|
position = seekerWidth;
|
||||||
|
}
|
||||||
|
setSeekerPosition(position);
|
||||||
|
},
|
||||||
|
[seekerWidth],
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the time that the video should be at
|
||||||
|
* based on where the seeker handle is.
|
||||||
|
*
|
||||||
|
* @return {float} time in ms based on seekerPosition.
|
||||||
|
*/
|
||||||
|
const calculateTimeFromSeekerPosition = () => {
|
||||||
|
const percent = seekerPosition / seekerWidth;
|
||||||
|
return duration * percent;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get our seekbar responder going
|
||||||
|
*/
|
||||||
|
|
||||||
|
const seekPanResponder = PanResponder.create({
|
||||||
|
// Ask to be the responder.
|
||||||
|
onStartShouldSetPanResponder: (_evt, _gestureState) => true,
|
||||||
|
onMoveShouldSetPanResponder: (_evt, _gestureState) => true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When we start the pan tell the machine that we're
|
||||||
|
* seeking. This stops it from updating the seekbar
|
||||||
|
* position in the onProgress listener.
|
||||||
|
*/
|
||||||
|
onPanResponderGrant: (evt, _gestureState) => {
|
||||||
|
const position = evt.nativeEvent.locationX;
|
||||||
|
updateSeekerPosition(position);
|
||||||
|
setSeeking(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When panning, update the seekbar position, duh.
|
||||||
|
*/
|
||||||
|
onPanResponderMove: (evt, _gestureState) => {
|
||||||
|
const position = evt.nativeEvent.locationX;
|
||||||
|
updateSeekerPosition(position);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On release we update the time and seek to it in the video.
|
||||||
|
* If you seek to the end of the video we fire the
|
||||||
|
* onEnd callback
|
||||||
|
*/
|
||||||
|
onPanResponderRelease: (_evt, _gestureState) => {
|
||||||
|
const time = calculateTimeFromSeekerPosition();
|
||||||
|
if (time >= duration && !isLoading) {
|
||||||
|
// FIXME ...
|
||||||
|
// state.paused = true;
|
||||||
|
// this.onEnd();
|
||||||
|
} else {
|
||||||
|
videoSeek(time);
|
||||||
|
setSeeking(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isLoading && !seeking && !isUISeeking) {
|
||||||
|
const percent = currentTime / duration;
|
||||||
|
const position = seekerWidth * percent;
|
||||||
|
updateSeekerPosition(position);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
currentTime,
|
||||||
|
duration,
|
||||||
|
isLoading,
|
||||||
|
seekerWidth,
|
||||||
|
seeking,
|
||||||
|
isUISeeking,
|
||||||
|
updateSeekerPosition,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!seekPanResponder) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const seekerStyle = [
|
||||||
|
styles.seekbarFill,
|
||||||
|
{
|
||||||
|
width: seekerPosition > 0 ? seekerPosition : 0,
|
||||||
|
backgroundColor: '#FFF',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const seekerPositionStyle = [
|
||||||
|
styles.seekbarHandle,
|
||||||
|
{
|
||||||
|
left: seekerPosition > 0 ? seekerPosition : 0,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const seekerPointerStyle = [styles.seekbarCircle, {backgroundColor: '#FFF'}];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={styles.seekbarContainer}
|
||||||
|
{...seekPanResponder.panHandlers}
|
||||||
|
{...styles.generalControls}>
|
||||||
|
<View
|
||||||
|
style={styles.seekbarTrack}
|
||||||
|
onLayout={event => setSeekerWidth(event.nativeEvent.layout.width)}
|
||||||
|
pointerEvents={'none'}>
|
||||||
|
<View style={seekerStyle} pointerEvents={'none'} />
|
||||||
|
</View>
|
||||||
|
<View style={seekerPositionStyle} pointerEvents={'none'}>
|
||||||
|
<View style={seekerPointerStyle} pointerEvents={'none'} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Seeker;
|
64
examples/FabricExample/src/components/TextTracksSelector.tsx
Normal file
64
examples/FabricExample/src/components/TextTracksSelector.tsx
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import {Picker} from '@react-native-picker/picker';
|
||||||
|
import {Text} from 'react-native';
|
||||||
|
import {TextTrack, SelectedTrack} from 'react-native-video';
|
||||||
|
import styles from '../styles';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export interface TextTrackSelectorType {
|
||||||
|
textTracks: Array<TextTrack>;
|
||||||
|
selectedTextTrack: SelectedTrack | undefined;
|
||||||
|
onValueChange: (arg0: string) => void;
|
||||||
|
textTracksSelectionBy: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TextTrackSelector = ({
|
||||||
|
textTracks,
|
||||||
|
selectedTextTrack,
|
||||||
|
onValueChange,
|
||||||
|
textTracksSelectionBy,
|
||||||
|
}: TextTrackSelectorType) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Text style={styles.controlOption}>TextTrack</Text>
|
||||||
|
<Picker
|
||||||
|
style={styles.picker}
|
||||||
|
itemStyle={styles.pickerItem}
|
||||||
|
selectedValue={`${selectedTextTrack?.value}`}
|
||||||
|
onValueChange={itemValue => {
|
||||||
|
if (itemValue !== 'empty') {
|
||||||
|
onValueChange(itemValue);
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
{textTracks?.length <= 0 ? (
|
||||||
|
<Picker.Item label={'empty'} value={'empty'} key={'empty'} />
|
||||||
|
) : (
|
||||||
|
<Picker.Item label={'none'} value={'none'} key={'none'} />
|
||||||
|
)}
|
||||||
|
{textTracks.map(track => {
|
||||||
|
if (!track) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (textTracksSelectionBy === 'index') {
|
||||||
|
return (
|
||||||
|
<Picker.Item
|
||||||
|
label={`${track.index}`}
|
||||||
|
value={track.index}
|
||||||
|
key={track.index}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Picker.Item
|
||||||
|
label={track.language}
|
||||||
|
value={track.language}
|
||||||
|
key={track.language}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</Picker>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TextTrackSelector;
|
@ -0,0 +1,64 @@
|
|||||||
|
import {Picker} from '@react-native-picker/picker';
|
||||||
|
import {Text} from 'react-native';
|
||||||
|
import {
|
||||||
|
SelectedVideoTrack,
|
||||||
|
SelectedVideoTrackType,
|
||||||
|
VideoTrack,
|
||||||
|
} from 'react-native-video';
|
||||||
|
import styles from '../styles';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export interface VideoTrackSelectorType {
|
||||||
|
videoTracks: Array<VideoTrack>;
|
||||||
|
selectedVideoTrack: SelectedVideoTrack | undefined;
|
||||||
|
onValueChange: (arg0: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VideoTrackSelector = ({
|
||||||
|
videoTracks,
|
||||||
|
selectedVideoTrack,
|
||||||
|
onValueChange,
|
||||||
|
}: VideoTrackSelectorType) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Text style={styles.controlOption}>VideoTrack</Text>
|
||||||
|
<Picker
|
||||||
|
style={styles.picker}
|
||||||
|
itemStyle={styles.pickerItem}
|
||||||
|
selectedValue={
|
||||||
|
selectedVideoTrack === undefined ||
|
||||||
|
selectedVideoTrack?.type === SelectedVideoTrackType.AUTO
|
||||||
|
? 'auto'
|
||||||
|
: `${selectedVideoTrack?.value}`
|
||||||
|
}
|
||||||
|
onValueChange={itemValue => {
|
||||||
|
if (itemValue !== 'empty') {
|
||||||
|
onValueChange(itemValue);
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<Picker.Item label={'auto'} value={'auto'} key={'auto'} />
|
||||||
|
{videoTracks?.length <= 0 || videoTracks?.length <= 0 ? (
|
||||||
|
<Picker.Item label={'empty'} value={'empty'} key={'empty'} />
|
||||||
|
) : (
|
||||||
|
<Picker.Item label={'none'} value={'none'} key={'none'} />
|
||||||
|
)}
|
||||||
|
{videoTracks?.map(track => {
|
||||||
|
if (!track) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Picker.Item
|
||||||
|
label={`${track.width}x${track.height} ${Math.floor(
|
||||||
|
(track.bitrate || 0) / 8 / 1024,
|
||||||
|
)} Kbps`}
|
||||||
|
value={`${track.index}`}
|
||||||
|
key={track.index}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Picker>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VideoTrackSelector;
|
BIN
examples/FabricExample/src/portrait.mp4
Normal file
BIN
examples/FabricExample/src/portrait.mp4
Normal file
Binary file not shown.
167
examples/FabricExample/src/styles.tsx
Normal file
167
examples/FabricExample/src/styles.tsx
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
import {StyleSheet} from 'react-native';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: 'black',
|
||||||
|
},
|
||||||
|
halfScreen: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 50,
|
||||||
|
left: 50,
|
||||||
|
bottom: 100,
|
||||||
|
right: 100,
|
||||||
|
},
|
||||||
|
fullScreen: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
bottom: 0,
|
||||||
|
right: 0,
|
||||||
|
},
|
||||||
|
bottomControls: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderRadius: 5,
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 20,
|
||||||
|
left: 20,
|
||||||
|
right: 20,
|
||||||
|
},
|
||||||
|
leftControls: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderRadius: 5,
|
||||||
|
position: 'absolute',
|
||||||
|
top: 20,
|
||||||
|
bottom: 20,
|
||||||
|
left: 20,
|
||||||
|
},
|
||||||
|
rightControls: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderRadius: 5,
|
||||||
|
position: 'absolute',
|
||||||
|
top: 20,
|
||||||
|
bottom: 20,
|
||||||
|
right: 20,
|
||||||
|
},
|
||||||
|
topControls: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderRadius: 4,
|
||||||
|
position: 'absolute',
|
||||||
|
top: 20,
|
||||||
|
left: 20,
|
||||||
|
right: 20,
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
overflow: 'hidden',
|
||||||
|
paddingBottom: 10,
|
||||||
|
},
|
||||||
|
generalControls: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
borderRadius: 4,
|
||||||
|
overflow: 'hidden',
|
||||||
|
paddingBottom: 10,
|
||||||
|
},
|
||||||
|
rateControl: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
volumeControl: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
resizeModeControl: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
leftRightControlOption: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
fontSize: 11,
|
||||||
|
color: 'white',
|
||||||
|
padding: 10,
|
||||||
|
lineHeight: 12,
|
||||||
|
},
|
||||||
|
controlOption: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
fontSize: 11,
|
||||||
|
color: 'white',
|
||||||
|
paddingLeft: 2,
|
||||||
|
paddingRight: 2,
|
||||||
|
lineHeight: 12,
|
||||||
|
},
|
||||||
|
pickerContainer: {
|
||||||
|
width: 100,
|
||||||
|
alignSelf: 'center',
|
||||||
|
color: 'white',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: 'red',
|
||||||
|
},
|
||||||
|
IndicatorStyle: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
seekbarContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
borderRadius: 4,
|
||||||
|
height: 30,
|
||||||
|
},
|
||||||
|
seekbarTrack: {
|
||||||
|
backgroundColor: '#333',
|
||||||
|
height: 1,
|
||||||
|
position: 'relative',
|
||||||
|
top: 14,
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
seekbarFill: {
|
||||||
|
backgroundColor: '#FFF',
|
||||||
|
height: 1,
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
seekbarHandle: {
|
||||||
|
position: 'absolute',
|
||||||
|
marginLeft: -7,
|
||||||
|
height: 28,
|
||||||
|
width: 28,
|
||||||
|
},
|
||||||
|
seekbarCircle: {
|
||||||
|
borderRadius: 12,
|
||||||
|
position: 'relative',
|
||||||
|
top: 8,
|
||||||
|
left: 8,
|
||||||
|
height: 12,
|
||||||
|
width: 12,
|
||||||
|
},
|
||||||
|
picker: {
|
||||||
|
flex: 1,
|
||||||
|
color: 'white',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
width: 100,
|
||||||
|
height: 40,
|
||||||
|
},
|
||||||
|
pickerItem: {
|
||||||
|
color: 'white',
|
||||||
|
width: 100,
|
||||||
|
height: 40,
|
||||||
|
},
|
||||||
|
emptyPickerItem: {
|
||||||
|
color: 'white',
|
||||||
|
marginTop: 20,
|
||||||
|
marginLeft: 20,
|
||||||
|
flex: 1,
|
||||||
|
width: 100,
|
||||||
|
height: 40,
|
||||||
|
},
|
||||||
|
topControlsContainer: {
|
||||||
|
paddingTop: 30,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default styles;
|
@ -1,6 +1,6 @@
|
|||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
{
|
{
|
||||||
"extends": "@tsconfig/react-native/tsconfig.json", /* Recommended React Native TSConfig base */
|
"extends": "@react-native/typescript-config/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||||
"paths": {
|
"paths": {
|
||||||
|
Loading…
Reference in New Issue
Block a user