feat: Replace Reanimated with RN Worklets (#1468)

* Setup RN Worklets

* Use RN Worklets on iOS

* Fix console

* Add `installFrameProcessorBindings()` function

* Add `FrameProcessorPlugins` proxy (BREAKING CHANGE)

* Clean up docs

* Update FRAME_PROCESSORS.mdx

* Use RN Worklets 0.2.5

* feat: Android build setup

* Rewrite Android Frame Processor Part

* Update CMakeLists.txt

* fix: Add react-native-worklets Gradle dependency

* Update Podfile.lock

* fix build

* gradle:7.4.1

* Init JSI Bindings in method on Android

* Fix Folly flags

* fix: Init `FrameProcessorRuntimeManager` later

* fix: Wrap in `<GestureHandlerRootView>`

* Refactor plugins

* fix: Remove enableFrameProcessors

* Install RN Worklets from current GH master

* Update babel.config.js

* Update CameraViewModule.kt

* Update ImageProxyUtils.java

* feat: Upgrade to Reanimated v3

* fix: Fix crash on Worklet init

* Update RN Worklets to latest master

* fix: Simplify FP Plugins Proxy
This commit is contained in:
Marc Rousavy
2023-02-13 15:22:45 +01:00
committed by GitHub
parent 11d1e7178d
commit a0590dccb5
55 changed files with 469 additions and 861 deletions

View File

@@ -12,8 +12,6 @@ import com.facebook.react.defaults.DefaultReactNativeHost;
import com.mrousavy.camera.CameraPackage;
import com.mrousavy.camera.frameprocessor.FrameProcessorPlugin;
import com.facebook.react.bridge.JSIModulePackage;
import com.swmansion.reanimated.ReanimatedJSIModulePackage;
public class MainApplication extends Application implements ReactApplication {
@@ -47,11 +45,6 @@ public class MainApplication extends Application implements ReactApplication {
protected Boolean isHermesEnabled() {
return BuildConfig.IS_HERMES_ENABLED;
}
@Override
protected JSIModulePackage getJSIModulePackage() {
return new ReanimatedJSIModulePackage();
}
};
@Override

View File

@@ -13,7 +13,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle")
classpath('com.android.tools.build:gradle:7.4.1')
classpath("com.facebook.react:react-native-gradle-plugin")
}
}

View File

@@ -5,12 +5,8 @@ const pak = require('../package.json');
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'react-native-reanimated/plugin',
{
globals: ['__example_plugin', '__example_plugin_swift'],
},
],
['react-native-reanimated/plugin'],
['react-native-worklets/plugin'],
[
'module-resolver',
{

View File

@@ -283,6 +283,10 @@ PODS:
- react-native-video/Video (= 5.2.1)
- react-native-video/Video (5.2.1):
- React-Core
- react-native-worklets (0.1.0):
- React
- React-callinvoker
- React-Core
- React-perflogger (0.71.2)
- React-RCTActionSheet (0.71.2):
- React-Core/RCTActionSheetHeaders (= 0.71.2)
@@ -369,7 +373,7 @@ PODS:
- React-perflogger (= 0.71.2)
- RNGestureHandler (2.9.0):
- React-Core
- RNReanimated (2.14.4):
- RNReanimated (3.0.0-rc.10):
- DoubleConversion
- FBLazyVector
- FBReactNativeSpec
@@ -407,6 +411,7 @@ PODS:
- React
- React-callinvoker
- React-Core
- react-native-worklets
- Yoga (1.14.0)
DEPENDENCIES:
@@ -437,6 +442,7 @@ DEPENDENCIES:
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- "react-native-slider (from `../node_modules/@react-native-community/slider`)"
- react-native-video (from `../node_modules/react-native-video`)
- react-native-worklets (from `../node_modules/react-native-worklets`)
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
@@ -514,6 +520,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/@react-native-community/slider"
react-native-video:
:path: "../node_modules/react-native-video"
react-native-worklets:
:path: "../node_modules/react-native-worklets"
React-perflogger:
:path: "../node_modules/react-native/ReactCommon/reactperflogger"
React-RCTActionSheet:
@@ -583,6 +591,7 @@ SPEC CHECKSUMS:
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
react-native-slider: 33b8d190b59d4f67a541061bb91775d53d617d9d
react-native-video: c26780b224543c62d5e1b2a7244a5cd1b50e8253
react-native-worklets: c7576ad4ad0f030ff41e8d74ad0077c96054a6c1
React-perflogger: c7ccda3d1d1da837f7ff4e54e816022a6803ee87
React-RCTActionSheet: 01c125aebbad462a24228f68c584c7a921d6c28e
React-RCTAnimation: 5277a9440acffc4a5b7baa6ae3880fe467277ae6
@@ -597,11 +606,11 @@ SPEC CHECKSUMS:
React-runtimeexecutor: 4bf9a9086d27f74065fce1dddac274aa95216952
ReactCommon: f697c0ac52e999aa818e43e2b6f277787c735e2d
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
RNReanimated: cc5e3aa479cb9170bcccf8204291a6950a3be128
RNReanimated: fbc356493970e3acddc15586b1bccb5eab3ff1ec
RNScreens: ea4cd3a853063cda19a4e3c28d2e52180c80f4eb
RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
VisionCamera: b9345e7da5eff343cc1603dd19153e2b9acd0c07
VisionCamera: 312151eb95370d1d764720de3b7dad33d8c7fb40
Yoga: 5b0304b3dbef2b52e078052138e23a19c7dacaef
PODFILE CHECKSUM: d53724fe402c2547f1dd1cc571bbe77d9820e636

View File

@@ -14,8 +14,8 @@
"typescript": "tsc --noEmit"
},
"dependencies": {
"@react-native-community/blur": "^4.3.0",
"@react-native-camera-roll/camera-roll": "^5.2.3",
"@react-native-community/blur": "^4.3.0",
"@react-native-community/slider": "^4.4.2",
"@react-navigation/native": "^6.1.3",
"@react-navigation/native-stack": "^6.9.9",
@@ -23,12 +23,13 @@
"react-native": "^0.71.2",
"react-native-gesture-handler": "^2.9.0",
"react-native-pressable-opacity": "^1.0.10",
"react-native-reanimated": "^2.14.4",
"react-native-reanimated": "^3.0.0-rc.10",
"react-native-safe-area-context": "^4.5.0",
"react-native-screens": "^3.19.0",
"react-native-static-safe-area-insets": "^2.2.0",
"react-native-vector-icons": "^9.2.0",
"react-native-video": "^5.2.1"
"react-native-video": "^5.2.1",
"react-native-worklets": "https://github.com/chrfalch/react-native-worklets#50950aa"
},
"devDependencies": {
"@babel/core": "^7.20.12",

View File

@@ -6,6 +6,7 @@ import { MediaPage } from './MediaPage';
import { CameraPage } from './CameraPage';
import type { Routes } from './Routes';
import { Camera, CameraPermissionStatus } from 'react-native-vision-camera';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
const Stack = createNativeStackNavigator<Routes>();
@@ -28,24 +29,26 @@ export function App(): React.ReactElement | null {
const showPermissionsPage = cameraPermission !== 'authorized' || microphonePermission === 'not-determined';
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerShown: false,
statusBarStyle: 'dark',
animationTypeForReplace: 'push',
}}
initialRouteName={showPermissionsPage ? 'PermissionsPage' : 'CameraPage'}>
<Stack.Screen name="PermissionsPage" component={PermissionsPage} />
<Stack.Screen name="CameraPage" component={CameraPage} />
<Stack.Screen
name="MediaPage"
component={MediaPage}
options={{
animation: 'none',
presentation: 'transparentModal',
<GestureHandlerRootView style={{ flex: 1 }}>
<Stack.Navigator
screenOptions={{
headerShown: false,
statusBarStyle: 'dark',
animationTypeForReplace: 'push',
}}
/>
</Stack.Navigator>
initialRouteName={showPermissionsPage ? 'PermissionsPage' : 'CameraPage'}>
<Stack.Screen name="PermissionsPage" component={PermissionsPage} />
<Stack.Screen name="CameraPage" component={CameraPage} />
<Stack.Screen
name="MediaPage"
component={MediaPage}
options={{
animation: 'none',
presentation: 'transparentModal',
}}
/>
</Stack.Navigator>
</GestureHandlerRootView>
</NavigationContainer>
);
}

View File

@@ -1,20 +1,16 @@
/* global __example_plugin __example_plugin_swift */
import type { Frame } from 'react-native-vision-camera';
declare let _WORKLET: true | undefined;
import { FrameProcessorPlugins, Frame } from 'react-native-vision-camera';
export function examplePluginSwift(frame: Frame): string[] {
'worklet';
if (!_WORKLET) throw new Error('examplePluginSwift must be called from a frame processor!');
// @ts-expect-error because this function is dynamically injected by VisionCamera
return __example_plugin_swift(frame, 'hello!', 'parameter2', true, 42, { test: 0, second: 'test' }, ['another test', 5]);
return FrameProcessorPlugins.example_plugin_swift(frame, 'hello!', 'parameter2', true, 42, { test: 0, second: 'test' }, [
'another test',
5,
]);
}
export function examplePlugin(frame: Frame): string[] {
'worklet';
if (!_WORKLET) throw new Error('examplePlugin must be called from a frame processor!');
// @ts-expect-error because this function is dynamically injected by VisionCamera
return __example_plugin(frame, 'hello!', 'parameter2', true, 42, { test: 0, second: 'test' }, ['another test', 5]);
return FrameProcessorPlugins.example_plugin(frame, 'hello!', 'parameter2', true, 42, { test: 0, second: 'test' }, ['another test', 5]);
}

View File

@@ -1190,7 +1190,7 @@
dependencies:
"@hapi/hoek" "^9.0.0"
"@sideway/formula@^3.0.0":
"@sideway/formula@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
@@ -2259,9 +2259,9 @@ ee-first@1.1.1:
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
electron-to-chromium@^1.4.284:
version "1.4.292"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.292.tgz#e3a3dca3780c8ce01e2c1866b5ec2fbe31c423e3"
integrity sha512-ESWOSyJy5odDlE8wvh5NNAMORv4r6assPwIPGHEMWrWD0SONXcG/xT+9aD9CQyeRwyYDPo6dJT4Bbeg5uevVQQ==
version "1.4.294"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.294.tgz#ad80317b85f0859a9454680fbc1c726fefa7e6fd"
integrity sha512-PuHZB3jEN7D8WPPjLmBQAsqQz8tWHlkkB4n0E2OYw8RwVdmBYV0Wn+rUFH8JqYyIRb4HQhhedgxlZL163wqLrQ==
eme-encryption-scheme-polyfill@^2.0.1:
version "2.1.1"
@@ -2884,7 +2884,7 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3:
get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f"
integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==
@@ -3162,11 +3162,11 @@ inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
internal-slot@^1.0.3, internal-slot@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3"
integrity sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==
version "1.0.5"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986"
integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==
dependencies:
get-intrinsic "^1.1.3"
get-intrinsic "^1.2.0"
has "^1.0.3"
side-channel "^1.0.4"
@@ -3550,14 +3550,14 @@ jest-worker@^27.2.0:
supports-color "^8.0.0"
joi@^17.2.1:
version "17.7.0"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.7.0.tgz#591a33b1fe1aca2bc27f290bcad9b9c1c570a6b3"
integrity sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg==
version "17.7.1"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.7.1.tgz#854fc85c7fa3cfc47c91124d30bffdbb58e06cec"
integrity sha512-teoLhIvWE298R6AeJywcjR4sX2hHjB3/xJX4qPjg+gTg+c0mzUDsziYlqPmLomq9gVsfaMcgPaGc7VxtD/9StA==
dependencies:
"@hapi/hoek" "^9.0.0"
"@hapi/topo" "^5.0.0"
"@sideway/address" "^4.1.3"
"@sideway/formula" "^3.0.0"
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
js-sdsl@^4.1.4:
@@ -4444,9 +4444,9 @@ minimatch@^5.0.1:
brace-expansion "^2.0.1"
minimist@^1.2.6:
version "1.2.7"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
mixin-deep@^1.2.0:
version "1.3.2"
@@ -4984,9 +4984,9 @@ range-parser@~1.2.1:
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
react-devtools-core@^4.26.1:
version "4.27.1"
resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.27.1.tgz#167aa174383c65786cbb7e965a5b39c702f0a2d3"
integrity sha512-qXhcxxDWiFmFAOq48jts9YQYe1+wVoUXzJTlY4jbaATzyio6dd6CUGu3dXBhREeVgpZ+y4kg6vFJzIOZh6vY2w==
version "4.27.2"
resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.27.2.tgz#d20fc57e258c656eedabafc2c851d38b33583148"
integrity sha512-8SzmIkpO87alD7Xr6gWIEa1jHkMjawOZ+6egjazlnjB4UUcbnzGDf/vBJ4BzGuWWEM+pzrxuzsPpcMqlQkYK2g==
dependencies:
shell-quote "^1.6.1"
ws "^7"
@@ -5042,10 +5042,10 @@ react-native-pressable-opacity@^1.0.10:
resolved "https://registry.yarnpkg.com/react-native-pressable-opacity/-/react-native-pressable-opacity-1.0.10.tgz#799df1a913d3b28f42ada765465fe7723eb7166d"
integrity sha512-Py9YH9TlS3Lv1so5JCj6bgiqkeYYGupF4ZImlpoyhhId/t/RiSqR68LlASOHgdctqQuqVJObQiFfzX8oZI9+6w==
react-native-reanimated@^2.14.4:
version "2.14.4"
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.14.4.tgz#3fa3da4e7b99f5dfb28f86bcf24d9d1024d38836"
integrity sha512-DquSbl7P8j4SAmc+kRdd75Ianm8G+IYQ9T4AQ6lrpLVeDkhZmjWI0wkutKWnp6L7c5XNVUrFDUf69dwETLCItQ==
react-native-reanimated@^3.0.0-rc.10:
version "3.0.0-rc.10"
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-3.0.0-rc.10.tgz#40e5b628759aa81f94317fd0301231292b4eacf5"
integrity sha512-0P2jSO+dXHRxSzqSxNp08VaUy89nqeUIvqBS0wlI8lsli8CJcqulL3pjNqTGzBkxXjt13mGdIzJv4u9lSjHPzg==
dependencies:
"@babel/plugin-transform-object-assign" "^7.16.7"
"@babel/preset-typescript" "^7.16.7"
@@ -5091,6 +5091,10 @@ react-native-video@^5.2.1:
prop-types "^15.7.2"
shaka-player "^2.5.9"
"react-native-worklets@https://github.com/chrfalch/react-native-worklets#50950aa":
version "0.1.0"
resolved "https://github.com/chrfalch/react-native-worklets#50950aa1b671a0d8a9e79878e63a3445991e7192"
react-native@^0.71.2:
version "0.71.2"
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.71.2.tgz#b6977eda2a6dc10baa006bf4ab1ee08318607ce9"