diff --git a/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt b/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt
index f1abb1ff..a703a3ee 100644
--- a/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt
+++ b/android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt
@@ -118,6 +118,8 @@ class HybridRiveView(val context: ThemedReactContext) : HybridRiveViewSpec() {
override fun reset() = asyncExecuteOnUiThread { view.reset() }
+ override fun playIfNeeded() = view.playIfNeeded()
+
override fun onEventListener(onEvent: (event: UnifiedRiveEvent) -> Unit) =
executeOnUiThread { view.addEventListener(onEvent) }
diff --git a/android/src/main/java/com/rive/RiveReactNativeView.kt b/android/src/main/java/com/rive/RiveReactNativeView.kt
index 5137ee9e..1856ee0d 100644
--- a/android/src/main/java/com/rive/RiveReactNativeView.kt
+++ b/android/src/main/java/com/rive/RiveReactNativeView.kt
@@ -190,6 +190,14 @@ class RiveReactNativeView(context: ThemedReactContext) : FrameLayout(context) {
fun reset() = riveAnimationView?.reset()
+ fun playIfNeeded() {
+ if (riveAnimationView?.isPlaying == false) {
+ riveAnimationView?.post {
+ riveAnimationView?.play()
+ }
+ }
+ }
+
fun addEventListener(onEvent: (event: RNEvent) -> Unit) {
val eventListener = object : RiveFileController.RiveEventListener {
override fun notifyEvent(event: RiveEvent) {
diff --git a/example/assets/rive/movecircle.riv b/example/assets/rive/movecircle.riv
new file mode 100644
index 00000000..9e73a553
Binary files /dev/null and b/example/assets/rive/movecircle.riv differ
diff --git a/example/babel.config.js b/example/babel.config.js
index 96620cc4..5b4caa62 100644
--- a/example/babel.config.js
+++ b/example/babel.config.js
@@ -7,7 +7,10 @@ const root = path.resolve(__dirname, '..');
module.exports = getConfig(
{
presets: ['module:@react-native/babel-preset'],
- plugins: [['babel-plugin-react-compiler', {}]],
+ plugins: [
+ ['babel-plugin-react-compiler', {}],
+ 'react-native-reanimated/plugin',
+ ],
},
{ root, pkg }
);
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index 24d3ea4f..b2313807 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -8,7 +8,7 @@ PODS:
- hermes-engine (0.79.2):
- hermes-engine/Pre-built (= 0.79.2)
- hermes-engine/Pre-built (0.79.2)
- - NitroModules (0.31.4):
+ - NitroModules (0.31.10):
- DoubleConversion
- glog
- hermes-engine
@@ -1803,6 +1803,83 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
+ - RNReanimated (4.1.5):
+ - DoubleConversion
+ - glog
+ - hermes-engine
+ - RCT-Folly (= 2024.11.18.00)
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-hermes
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - RNReanimated/reanimated (= 4.1.5)
+ - RNWorklets
+ - Yoga
+ - RNReanimated/reanimated (4.1.5):
+ - DoubleConversion
+ - glog
+ - hermes-engine
+ - RCT-Folly (= 2024.11.18.00)
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-hermes
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - RNReanimated/reanimated/apple (= 4.1.5)
+ - RNWorklets
+ - Yoga
+ - RNReanimated/reanimated/apple (4.1.5):
+ - DoubleConversion
+ - glog
+ - hermes-engine
+ - RCT-Folly (= 2024.11.18.00)
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-hermes
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - RNWorklets
+ - Yoga
- RNRive (0.1.0):
- DoubleConversion
- glog
@@ -1829,6 +1906,80 @@ PODS:
- ReactCommon/turbomodule/core
- RiveRuntime (= 6.12.0)
- Yoga
+ - RNWorklets (0.6.1):
+ - DoubleConversion
+ - glog
+ - hermes-engine
+ - RCT-Folly (= 2024.11.18.00)
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-hermes
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - RNWorklets/worklets (= 0.6.1)
+ - Yoga
+ - RNWorklets/worklets (0.6.1):
+ - DoubleConversion
+ - glog
+ - hermes-engine
+ - RCT-Folly (= 2024.11.18.00)
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-hermes
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - RNWorklets/worklets/apple (= 0.6.1)
+ - Yoga
+ - RNWorklets/worklets/apple (0.6.1):
+ - DoubleConversion
+ - glog
+ - hermes-engine
+ - RCT-Folly (= 2024.11.18.00)
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-hermes
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - Yoga
- SocketRocket (0.7.1)
- Yoga (0.0.0)
@@ -1908,7 +2059,9 @@ DEPENDENCIES:
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- "RNCPicker (from `../node_modules/@react-native-picker/picker`)"
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
+ - RNReanimated (from `../node_modules/react-native-reanimated`)
- RNRive (from `../..`)
+ - RNWorklets (from `../node_modules/react-native-worklets`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
@@ -2064,8 +2217,12 @@ EXTERNAL SOURCES:
:path: "../node_modules/@react-native-picker/picker"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
+ RNReanimated:
+ :path: "../node_modules/react-native-reanimated"
RNRive:
:path: "../.."
+ RNWorklets:
+ :path: "../node_modules/react-native-worklets"
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
@@ -2077,7 +2234,7 @@ SPEC CHECKSUMS:
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
hermes-engine: 314be5250afa5692b57b4dd1705959e1973a8ebe
- NitroModules: 8229091083785ae690dc9071f07fc412e0cb8243
+ NitroModules: 7f50ee216f8403e8eb243acfc504f3f856d6914c
RCT-Folly: 36fe2295e44b10d831836cc0d1daec5f8abcf809
RCTDeprecation: 83ffb90c23ee5cea353bd32008a7bca100908f8c
RCTRequired: eb7c0aba998009f47a540bec9e9d69a54f68136e
@@ -2144,7 +2301,9 @@ SPEC CHECKSUMS:
RiveRuntime: 8d819993126145fbf5a73089e7634b14b9aa577f
RNCPicker: 83c74db2de8274d8a8f3e18d91dea174a708f8c4
RNGestureHandler: bff91bb5ab5688265c70f74180ef718b94f33fe3
+ RNReanimated: 9a24892f34ea317264883806d2e3de7ce34eab90
RNRive: 6ced82b0b2ff90cbb87813849e9c05761d038119
+ RNWorklets: ddf16938b1ed7e878563a4fc8a690968ef3d27f1
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Yoga: 9f110fc4b7aa538663cba3c14cbb1c335f43c13f
diff --git a/example/package.json b/example/package.json
index 665a1bfd..f73d6cc5 100644
--- a/example/package.json
+++ b/example/package.json
@@ -15,9 +15,11 @@
"@react-navigation/stack": "^7.3.2",
"react": "19.0.0",
"react-native": "0.79.2",
- "react-native-gesture-handler": "^2.25.0",
- "react-native-nitro-modules": "^0.31.3",
- "react-native-safe-area-context": "^5.4.0"
+ "react-native-gesture-handler": "2.29.1",
+ "react-native-nitro-modules": "0.31.10",
+ "react-native-reanimated": "4.1.5",
+ "react-native-safe-area-context": "^5.4.0",
+ "react-native-worklets": "0.6.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",
diff --git a/example/src/pages/SharedValueListenerExample.tsx b/example/src/pages/SharedValueListenerExample.tsx
new file mode 100644
index 00000000..3a3e4f0e
--- /dev/null
+++ b/example/src/pages/SharedValueListenerExample.tsx
@@ -0,0 +1,232 @@
+import {
+ View,
+ Text,
+ StyleSheet,
+ Button,
+ ActivityIndicator,
+} from 'react-native';
+import { type Metadata } from '../helpers/metadata';
+import Animated, {
+ useSharedValue,
+ useAnimatedReaction,
+ useAnimatedStyle,
+ withSpring,
+} from 'react-native-reanimated';
+import {
+ Gesture,
+ GestureDetector,
+ GestureHandlerRootView,
+} from 'react-native-gesture-handler';
+import { useCallback, useEffect, useMemo } from 'react';
+import {
+ NitroModules,
+ type BoxedHybridObject,
+} from 'react-native-nitro-modules';
+import {
+ Fit,
+ RiveView,
+ useRiveFile,
+ type RiveFile,
+ type RiveViewRef,
+ type ViewModelInstance,
+} from '@rive-app/react-native';
+
+export default function SharedValueListenerExample() {
+ const { riveFile, isLoading, error } = useRiveFile(
+ require('../../assets/rive/movecircle.riv')
+ );
+
+ return (
+
+ {isLoading ? (
+
+ ) : riveFile ? (
+
+ ) : (
+ {error || 'Unexpected error'}
+ )}
+
+ );
+}
+
+function WithViewModelSetup({ file }: { file: RiveFile }) {
+ const viewModel = useMemo(() => file.defaultArtboardViewModel(), [file]);
+ const instance = useMemo(
+ () => viewModel?.createDefaultInstance(),
+ [viewModel]
+ );
+
+ if (!instance || !viewModel) {
+ return (
+
+ {!viewModel
+ ? 'No view model found'
+ : 'Failed to create view model instance'}
+
+ );
+ }
+
+ return ;
+}
+
+function AnimatedRiveExample({
+ instance,
+ file,
+}: {
+ instance: ViewModelInstance;
+ file: RiveFile;
+}) {
+ const progress = useSharedValue(0);
+ const startY = useSharedValue(0);
+ const viewRef = useSharedValue | null>(null);
+
+ const boxedProperty = useMemo(() => {
+ const posYProperty = instance.numberProperty('posY');
+ if (!posYProperty) {
+ return null;
+ }
+ return NitroModules.box(posYProperty);
+ }, [instance]);
+
+ useAnimatedReaction(
+ () => progress.value,
+ (value: number) => {
+ 'worklet';
+ if (!boxedProperty) return;
+ const property = boxedProperty.unbox();
+ property.value = value;
+
+ viewRef.value?.unbox()?.playIfNeeded();
+ },
+ [boxedProperty]
+ );
+
+ const panGesture = Gesture.Pan()
+ .onStart(() => {
+ 'worklet';
+ startY.value = progress.value;
+ })
+ .onUpdate((event) => {
+ 'worklet';
+ progress.value = startY.value + event.translationY * 3;
+ })
+ .onEnd((event) => {
+ 'worklet';
+ // Use velocity from gesture to set initial velocity of spring
+ progress.value = withSpring(progress.value > 400 ? 800 : 0, {
+ damping: 10,
+ stiffness: 100,
+ velocity: event.velocityY * 3,
+ });
+ });
+
+ const circleStyle = useAnimatedStyle(() => ({
+ transform: [{ translateY: progress.value / 3 }],
+ }));
+
+ const animateTo800 = useCallback(() => {
+ progress.value = withSpring(800, {
+ damping: 8,
+ stiffness: 80,
+ });
+ }, [progress]);
+
+ const animateTo0 = () => {
+ progress.value = withSpring(0, {
+ damping: 8,
+ stiffness: 80,
+ });
+ };
+
+ useEffect(() => {
+ animateTo800();
+ }, [animateTo800]);
+
+ return (
+
+
+ Drag the blue circle to control position. Release to spring with
+ velocity. (Red = Rive, Blue = React Native)
+
+
+
+ {
+ viewRef.value = NitroModules.box(ref);
+ },
+ }}
+ />
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+SharedValueListenerExample.metadata = {
+ name: 'Reanimated Shared Value',
+ description: 'Drive Rive properties from Reanimated shared values',
+} satisfies Metadata;
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#fff',
+ },
+ title: {
+ fontSize: 24,
+ fontWeight: 'bold',
+ textAlign: 'center',
+ marginTop: 20,
+ marginBottom: 10,
+ },
+ subtitle: {
+ fontSize: 16,
+ color: '#666',
+ textAlign: 'center',
+ marginBottom: 20,
+ paddingHorizontal: 20,
+ },
+ riveContainer: {
+ flex: 1,
+ backgroundColor: '#f5f5f5',
+ },
+ rive: {
+ flex: 1,
+ width: '100%',
+ height: '100%',
+ },
+ errorText: {
+ color: 'red',
+ textAlign: 'center',
+ padding: 20,
+ },
+ buttonContainer: {
+ flexDirection: 'row',
+ justifyContent: 'center',
+ gap: 20,
+ padding: 20,
+ },
+ blueCircle: {
+ position: 'absolute',
+ left: 50,
+ top: -20,
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ backgroundColor: 'blue',
+ },
+});
diff --git a/example/src/pages/index.ts b/example/src/pages/index.ts
index 5dde40fa..3747327e 100644
--- a/example/src/pages/index.ts
+++ b/example/src/pages/index.ts
@@ -8,3 +8,4 @@ export { default as OutOfBandAssets } from './OutOfBandAssets';
export { default as OutOfBandAssetsWithSuspense } from './OutOfBandAssetsWithSuspense';
export { default as ManyViewModels } from './ManyViewModels';
export { default as ResponsiveLayouts } from './ResponsiveLayouts';
+export { default as SharedValueListenerExample } from './SharedValueListenerExample';
diff --git a/expo-example/package.json b/expo-example/package.json
index b75835fe..995538df 100644
--- a/expo-example/package.json
+++ b/expo-example/package.json
@@ -32,13 +32,13 @@
"react": "19.1.0",
"react-dom": "19.1.0",
"react-native": "0.81.5",
- "react-native-gesture-handler": "~2.28.0",
- "react-native-nitro-modules": "^0.31.3",
- "react-native-reanimated": "~4.1.1",
+ "react-native-gesture-handler": "2.29.1",
+ "react-native-nitro-modules": "0.31.10",
+ "react-native-reanimated": "4.1.5",
"react-native-safe-area-context": "~5.6.0",
"react-native-screens": "~4.16.0",
"react-native-web": "~0.21.0",
- "react-native-worklets": "0.5.1"
+ "react-native-worklets": "0.6.1"
},
"devDependencies": {
"@types/react": "~19.1.0",
diff --git a/ios/HybridRiveView.swift b/ios/HybridRiveView.swift
index 1bf3fe92..2067e618 100644
--- a/ios/HybridRiveView.swift
+++ b/ios/HybridRiveView.swift
@@ -83,6 +83,10 @@ class HybridRiveView: HybridRiveViewSpec {
try await self.getRiveView().reset()
}
}
+
+ func playIfNeeded() {
+ try? self.getRiveView().playIfNeeded()
+ }
// MARK: View Props
var dataBind: HybridDataBindMode? {
diff --git a/ios/HybridViewModelNumberProperty.swift b/ios/HybridViewModelNumberProperty.swift
index 9173cb21..97367801 100644
--- a/ios/HybridViewModelNumberProperty.swift
+++ b/ios/HybridViewModelNumberProperty.swift
@@ -3,12 +3,12 @@ import RiveRuntime
class HybridViewModelNumberProperty: HybridViewModelNumberPropertySpec, ValuedPropertyProtocol {
var property: NumberPropertyType!
lazy var helper = PropertyListenerHelper(property: property!)
-
+
init(property: NumberPropertyType) {
self.property = property
super.init()
}
-
+
/// ⚠️ DO NOT REMOVE
/// Nitro requires a parameterless initializer for JS bridging.
/// This is invoked automatically during hybrid module construction.
@@ -16,7 +16,7 @@ class HybridViewModelNumberProperty: HybridViewModelNumberPropertySpec, ValuedPr
override init() {
super.init()
}
-
+
var value: Double {
get {
return Double(property.value)
@@ -25,7 +25,7 @@ class HybridViewModelNumberProperty: HybridViewModelNumberPropertySpec, ValuedPr
property.value = Float(newValue)
}
}
-
+
// Custom addListener needed because ListenerValueType (Float) != ValueType (Double)
func addListener(onChanged: @escaping (Double) -> Void) throws {
helper.addListener { (value: Float) in
diff --git a/ios/RiveReactNativeView.swift b/ios/RiveReactNativeView.swift
index 34d862d8..a2e1ea52 100644
--- a/ios/RiveReactNativeView.swift
+++ b/ios/RiveReactNativeView.swift
@@ -139,6 +139,14 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate {
func reset() {
baseViewModel?.reset()
}
+
+ func playIfNeeded() {
+ if let baseViewModel = baseViewModel, (baseViewModel.isPlaying == false) {
+ Task {
+ baseViewModel.play()
+ }
+ }
+ }
func refreshAfterAssetChange() {
if baseViewModel?.isPlaying == false {
diff --git a/nitrogen/generated/android/c++/JFunc_void.hpp b/nitrogen/generated/android/c++/JFunc_void.hpp
index a113b068..ada9c4bd 100644
--- a/nitrogen/generated/android/c++/JFunc_void.hpp
+++ b/nitrogen/generated/android/c++/JFunc_void.hpp
@@ -11,6 +11,7 @@
#include
#include
+#include
namespace margelo::nitro::rive {
@@ -37,7 +38,7 @@ namespace margelo::nitro::rive {
/**
* An implementation of Func_void that is backed by a C++ implementation (using `std::function<...>`)
*/
- struct JFunc_void_cxx final: public jni::HybridClass {
+ class JFunc_void_cxx final: public jni::HybridClass {
public:
static jni::local_ref fromCpp(const std::function& func) {
return JFunc_void_cxx::newObjectCxxArgs(func);
diff --git a/nitrogen/generated/android/c++/JFunc_void_RiveError.hpp b/nitrogen/generated/android/c++/JFunc_void_RiveError.hpp
index 12d35760..84b6689a 100644
--- a/nitrogen/generated/android/c++/JFunc_void_RiveError.hpp
+++ b/nitrogen/generated/android/c++/JFunc_void_RiveError.hpp
@@ -12,6 +12,7 @@
#include "RiveError.hpp"
#include
+#include
#include "JRiveError.hpp"
#include
#include "RiveErrorType.hpp"
@@ -42,7 +43,7 @@ namespace margelo::nitro::rive {
/**
* An implementation of Func_void_RiveError that is backed by a C++ implementation (using `std::function<...>`)
*/
- struct JFunc_void_RiveError_cxx final: public jni::HybridClass {
+ class JFunc_void_RiveError_cxx final: public jni::HybridClass {
public:
static jni::local_ref fromCpp(const std::function& func) {
return JFunc_void_RiveError_cxx::newObjectCxxArgs(func);
diff --git a/nitrogen/generated/android/c++/JFunc_void_UnifiedRiveEvent.hpp b/nitrogen/generated/android/c++/JFunc_void_UnifiedRiveEvent.hpp
index 6a7798fc..8815b274 100644
--- a/nitrogen/generated/android/c++/JFunc_void_UnifiedRiveEvent.hpp
+++ b/nitrogen/generated/android/c++/JFunc_void_UnifiedRiveEvent.hpp
@@ -12,6 +12,7 @@
#include "UnifiedRiveEvent.hpp"
#include
+#include
#include "JUnifiedRiveEvent.hpp"
#include
#include "RiveEventType.hpp"
@@ -46,7 +47,7 @@ namespace margelo::nitro::rive {
/**
* An implementation of Func_void_UnifiedRiveEvent that is backed by a C++ implementation (using `std::function<...>`)
*/
- struct JFunc_void_UnifiedRiveEvent_cxx final: public jni::HybridClass {
+ class JFunc_void_UnifiedRiveEvent_cxx final: public jni::HybridClass {
public:
static jni::local_ref fromCpp(const std::function& func) {
return JFunc_void_UnifiedRiveEvent_cxx::newObjectCxxArgs(func);
diff --git a/nitrogen/generated/android/c++/JFunc_void_bool.hpp b/nitrogen/generated/android/c++/JFunc_void_bool.hpp
index 9af62391..2608d6e8 100644
--- a/nitrogen/generated/android/c++/JFunc_void_bool.hpp
+++ b/nitrogen/generated/android/c++/JFunc_void_bool.hpp
@@ -11,6 +11,7 @@
#include
#include
+#include
namespace margelo::nitro::rive {
@@ -37,7 +38,7 @@ namespace margelo::nitro::rive {
/**
* An implementation of Func_void_bool that is backed by a C++ implementation (using `std::function<...>`)
*/
- struct JFunc_void_bool_cxx final: public jni::HybridClass {
+ class JFunc_void_bool_cxx final: public jni::HybridClass {
public:
static jni::local_ref fromCpp(const std::function& func) {
return JFunc_void_bool_cxx::newObjectCxxArgs(func);
diff --git a/nitrogen/generated/android/c++/JFunc_void_double.hpp b/nitrogen/generated/android/c++/JFunc_void_double.hpp
index 64f20371..f133cdb9 100644
--- a/nitrogen/generated/android/c++/JFunc_void_double.hpp
+++ b/nitrogen/generated/android/c++/JFunc_void_double.hpp
@@ -11,6 +11,7 @@
#include
#include
+#include
namespace margelo::nitro::rive {
@@ -37,7 +38,7 @@ namespace margelo::nitro::rive {
/**
* An implementation of Func_void_double that is backed by a C++ implementation (using `std::function<...>`)
*/
- struct JFunc_void_double_cxx final: public jni::HybridClass {
+ class JFunc_void_double_cxx final: public jni::HybridClass {
public:
static jni::local_ref fromCpp(const std::function& func) {
return JFunc_void_double_cxx::newObjectCxxArgs(func);
diff --git a/nitrogen/generated/android/c++/JFunc_void_std__string.hpp b/nitrogen/generated/android/c++/JFunc_void_std__string.hpp
index 484fcdce..1fc0fb9f 100644
--- a/nitrogen/generated/android/c++/JFunc_void_std__string.hpp
+++ b/nitrogen/generated/android/c++/JFunc_void_std__string.hpp
@@ -12,6 +12,7 @@
#include
#include
+#include
namespace margelo::nitro::rive {
@@ -38,7 +39,7 @@ namespace margelo::nitro::rive {
/**
* An implementation of Func_void_std__string that is backed by a C++ implementation (using `std::function<...>`)
*/
- struct JFunc_void_std__string_cxx final: public jni::HybridClass {
+ class JFunc_void_std__string_cxx final: public jni::HybridClass {
public:
static jni::local_ref fromCpp(const std::function& func) {
return JFunc_void_std__string_cxx::newObjectCxxArgs(func);
diff --git a/nitrogen/generated/android/c++/JHybridRiveViewSpec.cpp b/nitrogen/generated/android/c++/JHybridRiveViewSpec.cpp
index 5e3df0a8..5cbb9273 100644
--- a/nitrogen/generated/android/c++/JHybridRiveViewSpec.cpp
+++ b/nitrogen/generated/android/c++/JHybridRiveViewSpec.cpp
@@ -48,6 +48,7 @@ namespace margelo::nitro::rive { enum class RiveEventType; }
#include "RiveError.hpp"
#include
#include "JFunc_void_RiveError.hpp"
+#include
#include "JRiveError.hpp"
#include "RiveErrorType.hpp"
#include "JRiveErrorType.hpp"
@@ -171,9 +172,7 @@ namespace margelo::nitro::rive {
return downcast->cthis()->getFunction();
} else {
auto __resultRef = jni::make_global(__result);
- return [__resultRef](RiveError error) -> void {
- return __resultRef->invoke(error);
- };
+ return JNICallable(std::move(__resultRef));
}
}();
}
@@ -253,6 +252,10 @@ namespace margelo::nitro::rive {
return __promise;
}();
}
+ void JHybridRiveViewSpec::playIfNeeded() {
+ static const auto method = javaClassStatic()->getMethod("playIfNeeded");
+ method(_javaPart);
+ }
void JHybridRiveViewSpec::onEventListener(const std::function& onEvent) {
static const auto method = javaClassStatic()->getMethod /* onEvent */)>("onEventListener_cxx");
method(_javaPart, JFunc_void_UnifiedRiveEvent_cxx::fromCpp(onEvent));
diff --git a/nitrogen/generated/android/c++/JHybridRiveViewSpec.hpp b/nitrogen/generated/android/c++/JHybridRiveViewSpec.hpp
index 3fbc581e..321e7a28 100644
--- a/nitrogen/generated/android/c++/JHybridRiveViewSpec.hpp
+++ b/nitrogen/generated/android/c++/JHybridRiveViewSpec.hpp
@@ -77,6 +77,7 @@ namespace margelo::nitro::rive {
std::shared_ptr> play() override;
std::shared_ptr> pause() override;
std::shared_ptr> reset() override;
+ void playIfNeeded() override;
void onEventListener(const std::function& onEvent) override;
void removeEventListeners() override;
void setNumberInputValue(const std::string& name, double value, const std::optional& path) override;
diff --git a/nitrogen/generated/android/c++/JHybridViewModelBooleanPropertySpec.cpp b/nitrogen/generated/android/c++/JHybridViewModelBooleanPropertySpec.cpp
index 23612983..39b2935b 100644
--- a/nitrogen/generated/android/c++/JHybridViewModelBooleanPropertySpec.cpp
+++ b/nitrogen/generated/android/c++/JHybridViewModelBooleanPropertySpec.cpp
@@ -11,6 +11,7 @@
#include
#include "JFunc_void_bool.hpp"
+#include
namespace margelo::nitro::rive {
diff --git a/nitrogen/generated/android/c++/JHybridViewModelColorPropertySpec.cpp b/nitrogen/generated/android/c++/JHybridViewModelColorPropertySpec.cpp
index 644c6acc..0ad45941 100644
--- a/nitrogen/generated/android/c++/JHybridViewModelColorPropertySpec.cpp
+++ b/nitrogen/generated/android/c++/JHybridViewModelColorPropertySpec.cpp
@@ -11,6 +11,7 @@
#include
#include "JFunc_void_double.hpp"
+#include
namespace margelo::nitro::rive {
diff --git a/nitrogen/generated/android/c++/JHybridViewModelEnumPropertySpec.cpp b/nitrogen/generated/android/c++/JHybridViewModelEnumPropertySpec.cpp
index fd65ff72..a477ce8d 100644
--- a/nitrogen/generated/android/c++/JHybridViewModelEnumPropertySpec.cpp
+++ b/nitrogen/generated/android/c++/JHybridViewModelEnumPropertySpec.cpp
@@ -12,6 +12,7 @@
#include
#include
#include "JFunc_void_std__string.hpp"
+#include
namespace margelo::nitro::rive {
diff --git a/nitrogen/generated/android/c++/JHybridViewModelNumberPropertySpec.cpp b/nitrogen/generated/android/c++/JHybridViewModelNumberPropertySpec.cpp
index b7076133..952c90ea 100644
--- a/nitrogen/generated/android/c++/JHybridViewModelNumberPropertySpec.cpp
+++ b/nitrogen/generated/android/c++/JHybridViewModelNumberPropertySpec.cpp
@@ -11,6 +11,7 @@
#include
#include "JFunc_void_double.hpp"
+#include
namespace margelo::nitro::rive {
diff --git a/nitrogen/generated/android/c++/JHybridViewModelStringPropertySpec.cpp b/nitrogen/generated/android/c++/JHybridViewModelStringPropertySpec.cpp
index 3b31e556..9c1ca69c 100644
--- a/nitrogen/generated/android/c++/JHybridViewModelStringPropertySpec.cpp
+++ b/nitrogen/generated/android/c++/JHybridViewModelStringPropertySpec.cpp
@@ -12,6 +12,7 @@
#include
#include
#include "JFunc_void_std__string.hpp"
+#include
namespace margelo::nitro::rive {
diff --git a/nitrogen/generated/android/c++/JHybridViewModelTriggerPropertySpec.cpp b/nitrogen/generated/android/c++/JHybridViewModelTriggerPropertySpec.cpp
index 81ce26ca..666a2060 100644
--- a/nitrogen/generated/android/c++/JHybridViewModelTriggerPropertySpec.cpp
+++ b/nitrogen/generated/android/c++/JHybridViewModelTriggerPropertySpec.cpp
@@ -11,6 +11,7 @@
#include
#include "JFunc_void.hpp"
+#include
namespace margelo::nitro::rive {
diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveViewSpec.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveViewSpec.kt
index 07a2e3b7..a3d3fef1 100644
--- a/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveViewSpec.kt
+++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/rive/HybridRiveViewSpec.kt
@@ -130,6 +130,10 @@ abstract class HybridRiveViewSpec: HybridView() {
@Keep
abstract fun reset(): Promise
+ @DoNotStrip
+ @Keep
+ abstract fun playIfNeeded(): Unit
+
abstract fun onEventListener(onEvent: (event: UnifiedRiveEvent) -> Unit): Unit
@DoNotStrip
diff --git a/nitrogen/generated/ios/c++/HybridRiveViewSpecSwift.hpp b/nitrogen/generated/ios/c++/HybridRiveViewSpecSwift.hpp
index 8fe61aca..2fd5960c 100644
--- a/nitrogen/generated/ios/c++/HybridRiveViewSpecSwift.hpp
+++ b/nitrogen/generated/ios/c++/HybridRiveViewSpecSwift.hpp
@@ -203,6 +203,12 @@ namespace margelo::nitro::rive {
auto __value = std::move(__result.value());
return __value;
}
+ inline void playIfNeeded() override {
+ auto __result = _swiftPart.playIfNeeded();
+ if (__result.hasError()) [[unlikely]] {
+ std::rethrow_exception(__result.error());
+ }
+ }
inline void onEventListener(const std::function& onEvent) override {
auto __result = _swiftPart.onEventListener(onEvent);
if (__result.hasError()) [[unlikely]] {
diff --git a/nitrogen/generated/ios/swift/HybridRiveViewSpec.swift b/nitrogen/generated/ios/swift/HybridRiveViewSpec.swift
index a407a8db..bb5ee52d 100644
--- a/nitrogen/generated/ios/swift/HybridRiveViewSpec.swift
+++ b/nitrogen/generated/ios/swift/HybridRiveViewSpec.swift
@@ -28,6 +28,7 @@ public protocol HybridRiveViewSpec_protocol: HybridObject, HybridView {
func play() throws -> Promise
func pause() throws -> Promise
func reset() throws -> Promise
+ func playIfNeeded() throws -> Void
func onEventListener(onEvent: @escaping (_ event: UnifiedRiveEvent) -> Void) throws -> Void
func removeEventListeners() throws -> Void
func setNumberInputValue(name: String, value: Double, path: String?) throws -> Void
diff --git a/nitrogen/generated/ios/swift/HybridRiveViewSpec_cxx.swift b/nitrogen/generated/ios/swift/HybridRiveViewSpec_cxx.swift
index 7e1c4667..ca441d74 100644
--- a/nitrogen/generated/ios/swift/HybridRiveViewSpec_cxx.swift
+++ b/nitrogen/generated/ios/swift/HybridRiveViewSpec_cxx.swift
@@ -442,6 +442,17 @@ open class HybridRiveViewSpec_cxx {
}
}
+ @inline(__always)
+ public final func playIfNeeded() -> bridge.Result_void_ {
+ do {
+ try self.__implementation.playIfNeeded()
+ return bridge.create_Result_void_()
+ } catch (let __error) {
+ let __exceptionPtr = __error.toCpp()
+ return bridge.create_Result_void_(__exceptionPtr)
+ }
+ }
+
@inline(__always)
public final func onEventListener(onEvent: bridge.Func_void_UnifiedRiveEvent) -> bridge.Result_void_ {
do {
diff --git a/nitrogen/generated/shared/c++/HybridRiveViewSpec.cpp b/nitrogen/generated/shared/c++/HybridRiveViewSpec.cpp
index 7c8efc88..a33a7fc3 100644
--- a/nitrogen/generated/shared/c++/HybridRiveViewSpec.cpp
+++ b/nitrogen/generated/shared/c++/HybridRiveViewSpec.cpp
@@ -38,6 +38,7 @@ namespace margelo::nitro::rive {
prototype.registerHybridMethod("play", &HybridRiveViewSpec::play);
prototype.registerHybridMethod("pause", &HybridRiveViewSpec::pause);
prototype.registerHybridMethod("reset", &HybridRiveViewSpec::reset);
+ prototype.registerHybridMethod("playIfNeeded", &HybridRiveViewSpec::playIfNeeded);
prototype.registerHybridMethod("onEventListener", &HybridRiveViewSpec::onEventListener);
prototype.registerHybridMethod("removeEventListeners", &HybridRiveViewSpec::removeEventListeners);
prototype.registerHybridMethod("setNumberInputValue", &HybridRiveViewSpec::setNumberInputValue);
diff --git a/nitrogen/generated/shared/c++/HybridRiveViewSpec.hpp b/nitrogen/generated/shared/c++/HybridRiveViewSpec.hpp
index 14f387a9..d8754389 100644
--- a/nitrogen/generated/shared/c++/HybridRiveViewSpec.hpp
+++ b/nitrogen/generated/shared/c++/HybridRiveViewSpec.hpp
@@ -99,6 +99,7 @@ namespace margelo::nitro::rive {
virtual std::shared_ptr> play() = 0;
virtual std::shared_ptr> pause() = 0;
virtual std::shared_ptr> reset() = 0;
+ virtual void playIfNeeded() = 0;
virtual void onEventListener(const std::function& onEvent) = 0;
virtual void removeEventListeners() = 0;
virtual void setNumberInputValue(const std::string& name, double value, const std::optional& path) = 0;
diff --git a/package.json b/package.json
index 7559b700..59469812 100644
--- a/package.json
+++ b/package.json
@@ -91,12 +91,12 @@
"eslint-plugin-jest": "^29.1.0",
"eslint-plugin-prettier": "^5.2.3",
"jest": "^29.7.0",
- "nitrogen": "^0.31.6",
+ "nitrogen": "0.31.10",
"prettier": "^3.0.3",
"react": "19.0.0",
"react-native": "0.79.2",
"react-native-builder-bob": "^0.40.10",
- "react-native-nitro-modules": "^0.31.8",
+ "react-native-nitro-modules": "0.31.10",
"react-test-renderer": "19.0.0",
"release-it": "^17.10.0",
"turbo": "^1.10.7",
diff --git a/src/specs/RiveView.nitro.ts b/src/specs/RiveView.nitro.ts
index bcd7fdc8..43792dae 100644
--- a/src/specs/RiveView.nitro.ts
+++ b/src/specs/RiveView.nitro.ts
@@ -66,6 +66,10 @@ export interface RiveViewMethods extends HybridViewMethods {
pause(): Promise;
/** Resets the Rive graphic to its initial state */
reset(): Promise;
+
+ /** play if needed: low overhead function to make sure the rive graphics is playing. Use after property value update, to make sure graphics is updated */
+ playIfNeeded(): void;
+
/**
* Adds an event listener to the Rive view
* @param onEvent - The function to call when an event is triggered
diff --git a/yarn.lock b/yarn.lock
index 58a88991..b7f012a1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4219,12 +4219,12 @@ __metadata:
eslint-plugin-jest: ^29.1.0
eslint-plugin-prettier: ^5.2.3
jest: ^29.7.0
- nitrogen: ^0.31.6
+ nitrogen: 0.31.10
prettier: ^3.0.3
react: 19.0.0
react-native: 0.79.2
react-native-builder-bob: ^0.40.10
- react-native-nitro-modules: ^0.31.8
+ react-native-nitro-modules: 0.31.10
react-test-renderer: 19.0.0
release-it: ^17.10.0
turbo: ^1.10.7
@@ -8242,13 +8242,13 @@ __metadata:
react: 19.1.0
react-dom: 19.1.0
react-native: 0.81.5
- react-native-gesture-handler: ~2.28.0
- react-native-nitro-modules: ^0.31.3
- react-native-reanimated: ~4.1.1
+ react-native-gesture-handler: 2.29.1
+ react-native-nitro-modules: 0.31.10
+ react-native-reanimated: 4.1.5
react-native-safe-area-context: ~5.6.0
react-native-screens: ~4.16.0
react-native-web: ~0.21.0
- react-native-worklets: 0.5.1
+ react-native-worklets: 0.6.1
typescript: ~5.9.2
languageName: unknown
linkType: soft
@@ -12601,18 +12601,18 @@ __metadata:
languageName: node
linkType: hard
-"nitrogen@npm:^0.31.6":
- version: 0.31.8
- resolution: "nitrogen@npm:0.31.8"
+"nitrogen@npm:0.31.10":
+ version: 0.31.10
+ resolution: "nitrogen@npm:0.31.10"
dependencies:
chalk: ^5.3.0
- react-native-nitro-modules: ^0.31.8
+ react-native-nitro-modules: ^0.31.10
ts-morph: ^27.0.0
yargs: ^18.0.0
zod: ^4.0.5
bin:
nitrogen: lib/index.js
- checksum: 00c53f2d7ba5a82f2dd78cc8cb797fa7224b25ec45ac53bb0464abb2a96eea4e8b847a632f3bd11d95b80d3fd54cfdc726121318b0ddd8238d42d23a566efad9
+ checksum: 6bba165b334172d6ea060affefc14aded38294cd9ef23f58a3aff9fc89f41d7b62e6ae9897bec5d8ce181bb9656d387c67f2649b91ad133041db0aa04826ff71
languageName: node
linkType: hard
@@ -13841,7 +13841,7 @@ __metadata:
languageName: node
linkType: hard
-"react-native-gesture-handler@npm:^2.25.0":
+"react-native-gesture-handler@npm:2.29.1":
version: 2.29.1
resolution: "react-native-gesture-handler@npm:2.29.1"
dependencies:
@@ -13855,20 +13855,6 @@ __metadata:
languageName: node
linkType: hard
-"react-native-gesture-handler@npm:~2.28.0":
- version: 2.28.0
- resolution: "react-native-gesture-handler@npm:2.28.0"
- dependencies:
- "@egjs/hammerjs": ^2.0.17
- hoist-non-react-statics: ^3.3.0
- invariant: ^2.2.4
- peerDependencies:
- react: "*"
- react-native: "*"
- checksum: 7bcd7db784b12565fdd5916bbebc2d3511a63159ca553d33e430008940ba7d209f1e85ef02968a920ed19c414fabe7d2c18cc0e967dd4889aae266788562d1e9
- languageName: node
- linkType: hard
-
"react-native-is-edge-to-edge@npm:^1.1.6, react-native-is-edge-to-edge@npm:^1.2.1":
version: 1.2.1
resolution: "react-native-is-edge-to-edge@npm:1.2.1"
@@ -13889,27 +13875,17 @@ __metadata:
languageName: node
linkType: hard
-"react-native-nitro-modules@npm:^0.31.3":
- version: 0.31.4
- resolution: "react-native-nitro-modules@npm:0.31.4"
- peerDependencies:
- react: "*"
- react-native: "*"
- checksum: 9d251ec788eafb5c66033a1f376e2a8f9dfc8962a22e8511f6451bc50bf324549fd4e5113ee5bed59a993c0afc3288e8722d854239a33c00faae26848a211fde
- languageName: node
- linkType: hard
-
-"react-native-nitro-modules@npm:^0.31.8":
- version: 0.31.8
- resolution: "react-native-nitro-modules@npm:0.31.8"
+"react-native-nitro-modules@npm:0.31.10, react-native-nitro-modules@npm:^0.31.10":
+ version: 0.31.10
+ resolution: "react-native-nitro-modules@npm:0.31.10"
peerDependencies:
react: "*"
react-native: "*"
- checksum: 3976b93015011585112c939ba762240b4cd913435de1a5321d18bbb719624fbfcf8ceca68575b5a03528211d02e36982043363fee8d3c874ac358c2f055f7fdf
+ checksum: 1c8d2f12ff29b6733c784c5fd0dedcbec4ceec9f82eb49f49e7734f31b9367346938010dcacf69bf695a352e36fec5aa23fd57b8091f6acd78c3d9a61e14ea7f
languageName: node
linkType: hard
-"react-native-reanimated@npm:~4.1.1":
+"react-native-reanimated@npm:4.1.5":
version: 4.1.5
resolution: "react-native-reanimated@npm:4.1.5"
dependencies:
@@ -13945,9 +13921,11 @@ __metadata:
react: 19.0.0
react-native: 0.79.2
react-native-builder-bob: ^0.40.10
- react-native-gesture-handler: ^2.25.0
- react-native-nitro-modules: ^0.31.3
+ react-native-gesture-handler: 2.29.1
+ react-native-nitro-modules: 0.31.10
+ react-native-reanimated: 4.1.5
react-native-safe-area-context: ^5.4.0
+ react-native-worklets: 0.6.1
languageName: unknown
linkType: soft
@@ -13994,9 +13972,9 @@ __metadata:
languageName: node
linkType: hard
-"react-native-worklets@npm:0.5.1":
- version: 0.5.1
- resolution: "react-native-worklets@npm:0.5.1"
+"react-native-worklets@npm:0.6.1":
+ version: 0.6.1
+ resolution: "react-native-worklets@npm:0.6.1"
dependencies:
"@babel/plugin-transform-arrow-functions": ^7.0.0-0
"@babel/plugin-transform-class-properties": ^7.0.0-0
@@ -14013,7 +13991,7 @@ __metadata:
"@babel/core": ^7.0.0-0
react: "*"
react-native: "*"
- checksum: 5ab09d00f20f621779258ee2e18e825404920cacb6da3b68be29d99cc7daa8f0d402eb6b9a77bde7fe891e98d251cfc51023fb53922a3d04f9e9e341c99feeb0
+ checksum: fee8de844ef2286dee9f81a53f9cf309424d26251953c8524204342c8531fef403c625a23632a6bb65ea57409d6f8522a60e02de772322bebb5ff4aa4cccf569
languageName: node
linkType: hard