From f53046286c9ad354475e4828e5941a78a695eb38 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Thu, 20 Aug 2026 17:07:36 +0200 Subject: [PATCH 1/5] feat: Upgrade Nitro to 0.37 for View improvements --- apps/simple-camera/ios/Podfile.lock | 4 +- apps/simple-camera/package.json | 2 +- bun.lock | 40 ++++-- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 4 +- .../package.json | 2 +- .../package.json | 4 +- .../JHybridFrameRendererViewStateUpdater.cpp | 58 ++++++--- .../JHybridFrameRendererViewStateUpdater.hpp | 7 +- .../views/JHybridPreviewViewStateUpdater.cpp | 93 +++++++++----- .../views/JHybridPreviewViewStateUpdater.hpp | 7 +- .../views/HybridFrameRendererViewManager.kt | 36 ++++-- .../HybridFrameRendererViewStateUpdater.kt | 4 +- .../camera/views/HybridPreviewViewManager.kt | 36 ++++-- .../views/HybridPreviewViewStateUpdater.kt | 4 +- .../views/HybridFrameRendererViewComponent.mm | 66 ++++++---- .../c++/views/HybridPreviewViewComponent.mm | 121 +++++++++++------- .../HybridFrameRendererViewComponent.cpp | 61 +-------- .../HybridFrameRendererViewComponent.hpp | 70 ++++------ .../c++/views/HybridPreviewViewComponent.cpp | 116 ++--------------- .../c++/views/HybridPreviewViewComponent.hpp | 90 ++++++------- .../react-native-vision-camera/package.json | 4 +- 23 files changed, 398 insertions(+), 439 deletions(-) diff --git a/apps/simple-camera/ios/Podfile.lock b/apps/simple-camera/ios/Podfile.lock index 4ed30e9640..13b42835de 100644 --- a/apps/simple-camera/ios/Podfile.lock +++ b/apps/simple-camera/ios/Podfile.lock @@ -94,7 +94,7 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - NitroModules (0.36.5): + - NitroModules (0.37.0-beta.0): - hermes-engine - RCTRequired - RCTTypeSafety @@ -2788,7 +2788,7 @@ SPEC CHECKSUMS: MLKitVision: 39a5a812db83c4a0794445088e567f3631c11961 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 NitroImage: 2f592086cbdecbbaa1c10dd97e0cdd43b1bb0817 - NitroModules: 452230d9b63c6c3f59dd97eeaa27ec3449271d4a + NitroModules: 6b173a14405398cc5db9568ee4b1ac091aebc20a PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 RCTDeprecation: a4c521821fab57cbb125b36effe84d897d0dfa12 RCTRequired: 9f3a7e5645d4bc3f551593de7550bb66ab6e42bc diff --git a/apps/simple-camera/package.json b/apps/simple-camera/package.json index afe92fae19..1218031b5f 100644 --- a/apps/simple-camera/package.json +++ b/apps/simple-camera/package.json @@ -26,7 +26,7 @@ "react-native": "0.85.3", "react-native-gesture-handler": "^3.0.0", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-reanimated": "4.4.0", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2", diff --git a/bun.lock b/bun.lock index 7fd41c396a..d24ff88d37 100644 --- a/bun.lock +++ b/bun.lock @@ -33,7 +33,7 @@ "react-native": "0.85.3", "react-native-gesture-handler": "^3.0.0", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-reanimated": "4.4.0", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2", @@ -106,11 +106,11 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "typescript": "6.0.3", }, "peerDependencies": { @@ -128,11 +128,11 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-vision-camera": "*", "typescript": "6.0.3", }, @@ -152,10 +152,10 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-vision-camera": "*", "typescript": "6.0.3", }, @@ -174,10 +174,10 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-vision-camera": "*", "typescript": "6.0.3", }, @@ -199,7 +199,7 @@ "@types/react": "19.2.15", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-reanimated": "4.4.0", "react-native-vision-camera": "*", "react-native-vision-camera-worklets": "*", @@ -221,10 +221,10 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-vision-camera": "*", "react-native-worklets": "0.9.1", "typescript": "6.0.3", @@ -2220,7 +2220,7 @@ "next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="], - "nitrogen": ["nitrogen@0.36.5", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.36.5", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-PvlHrBVaoKEaD6CCUCG7om8MTvLeh4ZSDxHoRx2YiEWUVXPXrRN9NwMn1gjie9Bd91jHA3dYMF7no9Eme4txMA=="], + "nitrogen": ["nitrogen@0.37.0-beta.0", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.37.0-beta.0", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-pKrlM7ZYlAVdVNpho9XvGeGOw7gzH0IglQjnmkeDk3aZASLBhGEMlmfq+LsaRGcONxpO4kayTMH/fd3/IaBoTA=="], "nocache": ["nocache@3.0.4", "", {}, "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw=="], @@ -2406,7 +2406,7 @@ "react-native-nitro-image": ["react-native-nitro-image@0.15.1", "", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-nitro-modules": "*" } }, "sha512-slrImfUgasAdzylTiNWuTkawE0R4t7LGh+7N2VFa/D9+SxlQbkKYp1J6hA3XkkEnTnUCKaea39ZVg+1xx665MQ=="], - "react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], + "react-native-nitro-modules": ["react-native-nitro-modules@0.37.0-beta.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-kGfWyj3IS7+B3IaukbaO84/YcdevhXWCGqBHzwQ7yvALBty56MPt18H9hCKAaua7oNEk0ZZUo3kgMr3o9CYpGA=="], "react-native-reanimated": ["react-native-reanimated@4.4.0", "", { "dependencies": { "react-native-is-edge-to-edge": "^1.3.1", "semver": "^7.7.3" }, "peerDependencies": { "react": "*", "react-native": "0.83 - 0.86", "react-native-worklets": "0.9.x" } }, "sha512-0XbC1SpF3JZOz5QfmTEx3vt8VkmkTlS05CBIOKEg5q5ZSNlGtlacntlhj5CrfZlN1ciHAeoliJouTC2cLGKbDA=="], @@ -3530,8 +3530,20 @@ "react-native/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + "react-native-nitro-image/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], + "react-native-vector-icons/yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], + "react-native-vision-camera/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], + + "react-native-vision-camera-barcode-scanner/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], + + "react-native-vision-camera-location/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], + + "react-native-vision-camera-resizer/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], + + "react-native-vision-camera-worklets/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], + "react-reconciler/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], "release-it/url-join": ["url-join@5.0.0", "", {}, "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA=="], diff --git a/packages/react-native-vision-camera-barcode-scanner/package.json b/packages/react-native-vision-camera-barcode-scanner/package.json index eb778c4057..cc7ced3c46 100644 --- a/packages/react-native-vision-camera-barcode-scanner/package.json +++ b/packages/react-native-vision-camera-barcode-scanner/package.json @@ -66,11 +66,11 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-vision-camera": "*", "typescript": "6.0.3" }, diff --git a/packages/react-native-vision-camera-location/package.json b/packages/react-native-vision-camera-location/package.json index 9118dc47e4..41300d3dc8 100644 --- a/packages/react-native-vision-camera-location/package.json +++ b/packages/react-native-vision-camera-location/package.json @@ -65,10 +65,10 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-vision-camera": "*", "typescript": "6.0.3" }, diff --git a/packages/react-native-vision-camera-resizer/package.json b/packages/react-native-vision-camera-resizer/package.json index 528ccc9580..7bbbf296d7 100644 --- a/packages/react-native-vision-camera-resizer/package.json +++ b/packages/react-native-vision-camera-resizer/package.json @@ -70,10 +70,10 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-vision-camera": "*", "typescript": "6.0.3" }, diff --git a/packages/react-native-vision-camera-skia/package.json b/packages/react-native-vision-camera-skia/package.json index 9528860cfe..d8ad7e261a 100644 --- a/packages/react-native-vision-camera-skia/package.json +++ b/packages/react-native-vision-camera-skia/package.json @@ -56,7 +56,7 @@ "@types/react": "19.2.15", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-reanimated": "4.4.0", "react-native-worklets": "0.9.1", "react-native-vision-camera": "*", diff --git a/packages/react-native-vision-camera-worklets/package.json b/packages/react-native-vision-camera-worklets/package.json index c443136174..7efa7b7b64 100644 --- a/packages/react-native-vision-camera-worklets/package.json +++ b/packages/react-native-vision-camera-worklets/package.json @@ -66,10 +66,10 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-worklets": "0.9.1", "react-native-vision-camera": "*", "typescript": "6.0.3" diff --git a/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridFrameRendererViewStateUpdater.cpp b/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridFrameRendererViewStateUpdater.cpp index 6d3a83af77..bf8b0acd55 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridFrameRendererViewStateUpdater.cpp +++ b/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridFrameRendererViewStateUpdater.cpp @@ -15,41 +15,59 @@ namespace margelo::nitro::camera::views { using namespace facebook; using ConcreteStateData = react::ConcreteState; -void JHybridFrameRendererViewStateUpdater::updateViewProps(jni::alias_ref /* class */, - jni::alias_ref javaView, - jni::alias_ref stateWrapperInterface) { - std::shared_ptr hybridView = javaView->getJHybridFrameRendererViewSpec(); - +std::shared_ptr JHybridFrameRendererViewStateUpdater::getPropsFromStateWrapper( + jni::alias_ref stateWrapper) { + if (stateWrapper.get() == nullptr) { + return nullptr; + } // Get concrete StateWrapperImpl from passed StateWrapper interface object - jobject rawStateWrapper = stateWrapperInterface.get(); - if (!stateWrapperInterface->isInstanceOf(react::StateWrapperImpl::javaClassStatic())) [[unlikely]] { - throw std::runtime_error("StateWrapper is not a StateWrapperImpl"); + jobject rawStateWrapper = stateWrapper.get(); + if (!stateWrapper->isInstanceOf(react::StateWrapperImpl::javaClassStatic())) [[unlikely]] { + throw std::runtime_error("StateWrapper is not a StateWrapperImpl"); + } + auto stateWrapperImpl = jni::alias_ref{ + static_cast(rawStateWrapper) + }; + std::shared_ptr state = stateWrapperImpl->cthis()->getState(); + if (state == nullptr) { + return nullptr; } - auto stateWrapper = jni::alias_ref{ - static_cast(rawStateWrapper)}; - std::shared_ptr state = stateWrapper->cthis()->getState(); auto concreteState = std::static_pointer_cast(state); const HybridFrameRendererViewState& data = concreteState->getData(); - const std::shared_ptr& props = data.getProps(); + const std::shared_ptr& props = data.getProps(); if (props == nullptr) [[unlikely]] { - // Props aren't set yet! throw std::runtime_error("HybridFrameRendererViewState's data doesn't contain any props!"); } + return props; +} + +void JHybridFrameRendererViewStateUpdater::updateViewProps(jni::alias_ref /* class */, + jni::alias_ref javaView, + jni::alias_ref newState, + jni::alias_ref oldState) { + std::shared_ptr hybridView = javaView->getJHybridFrameRendererViewSpec(); + std::shared_ptr newProps = getPropsFromStateWrapper(newState); + std::shared_ptr oldProps = getPropsFromStateWrapper(oldState); + if (newProps == nullptr) [[unlikely]] { + throw std::runtime_error("Current StateWrapper doesn't contain any props!"); + } - // Update all props if they are dirty - if (props->renderer.isDirty) { - hybridView->setRenderer(props->renderer.value); - props->renderer.isDirty = false; + // Update only props that differ from the previous State snapshot. + if (oldProps == nullptr + ? newProps->renderer.isProvided() + : !newProps->renderer.hasSameValue(oldProps->renderer)) { + hybridView->setRenderer(newProps->renderer.get()); } // Update hybridRef if it changed - if (props->hybridRef.isDirty) { + if (oldProps == nullptr + ? newProps->hybridRef.isProvided() + : !newProps->hybridRef.hasSameValue(oldProps->hybridRef)) { // hybridRef changed - call it with new this - const auto& maybeFunc = props->hybridRef.value; + const auto& maybeFunc = newProps->hybridRef.get(); if (maybeFunc.has_value()) { maybeFunc.value()(hybridView); } - props->hybridRef.isDirty = false; } } diff --git a/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridFrameRendererViewStateUpdater.hpp b/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridFrameRendererViewStateUpdater.hpp index 46c9a4ca5c..387f411f39 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridFrameRendererViewStateUpdater.hpp +++ b/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridFrameRendererViewStateUpdater.hpp @@ -31,7 +31,12 @@ class JHybridFrameRendererViewStateUpdater final: public jni::JavaClass /* class */, jni::alias_ref view, - jni::alias_ref stateWrapperInterface); + jni::alias_ref newState, + jni::alias_ref oldState); + +private: + static std::shared_ptr getPropsFromStateWrapper( + jni::alias_ref stateWrapper); public: static void registerNatives() { diff --git a/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridPreviewViewStateUpdater.cpp b/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridPreviewViewStateUpdater.cpp index e21b794c7d..ed5395c657 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridPreviewViewStateUpdater.cpp +++ b/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridPreviewViewStateUpdater.cpp @@ -15,61 +15,84 @@ namespace margelo::nitro::camera::views { using namespace facebook; using ConcreteStateData = react::ConcreteState; -void JHybridPreviewViewStateUpdater::updateViewProps(jni::alias_ref /* class */, - jni::alias_ref javaView, - jni::alias_ref stateWrapperInterface) { - std::shared_ptr hybridView = javaView->getJHybridPreviewViewSpec(); - +std::shared_ptr JHybridPreviewViewStateUpdater::getPropsFromStateWrapper( + jni::alias_ref stateWrapper) { + if (stateWrapper.get() == nullptr) { + return nullptr; + } // Get concrete StateWrapperImpl from passed StateWrapper interface object - jobject rawStateWrapper = stateWrapperInterface.get(); - if (!stateWrapperInterface->isInstanceOf(react::StateWrapperImpl::javaClassStatic())) [[unlikely]] { - throw std::runtime_error("StateWrapper is not a StateWrapperImpl"); + jobject rawStateWrapper = stateWrapper.get(); + if (!stateWrapper->isInstanceOf(react::StateWrapperImpl::javaClassStatic())) [[unlikely]] { + throw std::runtime_error("StateWrapper is not a StateWrapperImpl"); + } + auto stateWrapperImpl = jni::alias_ref{ + static_cast(rawStateWrapper) + }; + std::shared_ptr state = stateWrapperImpl->cthis()->getState(); + if (state == nullptr) { + return nullptr; } - auto stateWrapper = jni::alias_ref{ - static_cast(rawStateWrapper)}; - std::shared_ptr state = stateWrapper->cthis()->getState(); auto concreteState = std::static_pointer_cast(state); const HybridPreviewViewState& data = concreteState->getData(); - const std::shared_ptr& props = data.getProps(); + const std::shared_ptr& props = data.getProps(); if (props == nullptr) [[unlikely]] { - // Props aren't set yet! throw std::runtime_error("HybridPreviewViewState's data doesn't contain any props!"); } + return props; +} + +void JHybridPreviewViewStateUpdater::updateViewProps(jni::alias_ref /* class */, + jni::alias_ref javaView, + jni::alias_ref newState, + jni::alias_ref oldState) { + std::shared_ptr hybridView = javaView->getJHybridPreviewViewSpec(); + std::shared_ptr newProps = getPropsFromStateWrapper(newState); + std::shared_ptr oldProps = getPropsFromStateWrapper(oldState); + if (newProps == nullptr) [[unlikely]] { + throw std::runtime_error("Current StateWrapper doesn't contain any props!"); + } - // Update all props if they are dirty - if (props->previewOutput.isDirty) { - hybridView->setPreviewOutput(props->previewOutput.value); - props->previewOutput.isDirty = false; + // Update only props that differ from the previous State snapshot. + if (oldProps == nullptr + ? newProps->previewOutput.isProvided() + : !newProps->previewOutput.hasSameValue(oldProps->previewOutput)) { + hybridView->setPreviewOutput(newProps->previewOutput.get()); } - if (props->resizeMode.isDirty) { - hybridView->setResizeMode(props->resizeMode.value); - props->resizeMode.isDirty = false; + if (oldProps == nullptr + ? newProps->resizeMode.isProvided() + : !newProps->resizeMode.hasSameValue(oldProps->resizeMode)) { + hybridView->setResizeMode(newProps->resizeMode.get()); } - if (props->implementationMode.isDirty) { - hybridView->setImplementationMode(props->implementationMode.value); - props->implementationMode.isDirty = false; + if (oldProps == nullptr + ? newProps->implementationMode.isProvided() + : !newProps->implementationMode.hasSameValue(oldProps->implementationMode)) { + hybridView->setImplementationMode(newProps->implementationMode.get()); } - if (props->gestureControllers.isDirty) { - hybridView->setGestureControllers(props->gestureControllers.value); - props->gestureControllers.isDirty = false; + if (oldProps == nullptr + ? newProps->gestureControllers.isProvided() + : !newProps->gestureControllers.hasSameValue(oldProps->gestureControllers)) { + hybridView->setGestureControllers(newProps->gestureControllers.get()); } - if (props->onPreviewStarted.isDirty) { - hybridView->setOnPreviewStarted(props->onPreviewStarted.value); - props->onPreviewStarted.isDirty = false; + if (oldProps == nullptr + ? newProps->onPreviewStarted.isProvided() + : !newProps->onPreviewStarted.hasSameValue(oldProps->onPreviewStarted)) { + hybridView->setOnPreviewStarted(newProps->onPreviewStarted.get()); } - if (props->onPreviewStopped.isDirty) { - hybridView->setOnPreviewStopped(props->onPreviewStopped.value); - props->onPreviewStopped.isDirty = false; + if (oldProps == nullptr + ? newProps->onPreviewStopped.isProvided() + : !newProps->onPreviewStopped.hasSameValue(oldProps->onPreviewStopped)) { + hybridView->setOnPreviewStopped(newProps->onPreviewStopped.get()); } // Update hybridRef if it changed - if (props->hybridRef.isDirty) { + if (oldProps == nullptr + ? newProps->hybridRef.isProvided() + : !newProps->hybridRef.hasSameValue(oldProps->hybridRef)) { // hybridRef changed - call it with new this - const auto& maybeFunc = props->hybridRef.value; + const auto& maybeFunc = newProps->hybridRef.get(); if (maybeFunc.has_value()) { maybeFunc.value()(hybridView); } - props->hybridRef.isDirty = false; } } diff --git a/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridPreviewViewStateUpdater.hpp b/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridPreviewViewStateUpdater.hpp index 02c4652bd4..60c6ee0643 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridPreviewViewStateUpdater.hpp +++ b/packages/react-native-vision-camera/nitrogen/generated/android/c++/views/JHybridPreviewViewStateUpdater.hpp @@ -31,7 +31,12 @@ class JHybridPreviewViewStateUpdater final: public jni::JavaClass /* class */, jni::alias_ref view, - jni::alias_ref stateWrapperInterface); + jni::alias_ref newState, + jni::alias_ref oldState); + +private: + static std::shared_ptr getPropsFromStateWrapper( + jni::alias_ref stateWrapper); public: static void registerNatives() { diff --git a/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridFrameRendererViewManager.kt b/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridFrameRendererViewManager.kt index ade581cb64..883c5bfd15 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridFrameRendererViewManager.kt +++ b/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridFrameRendererViewManager.kt @@ -20,6 +20,14 @@ import com.margelo.nitro.camera.* * Represents the React Native `ViewManager` for the "FrameRendererView" Nitro HybridView. */ public class HybridFrameRendererViewManager: SimpleViewManager() { + /** + * Represents the View and its last state snapshot (mutable) + */ + private class HybridViewHolder( + val hybridView: HybridFrameRendererView, + var lastState: StateWrapper? = null, + ) + init { if (RecyclableView::class.java.isAssignableFrom(HybridFrameRendererView::class.java)) { // Enable view recycling @@ -34,33 +42,41 @@ public class HybridFrameRendererViewManager: SimpleViewManager() { override fun createViewInstance(reactContext: ThemedReactContext): View { val hybridView = HybridFrameRendererView(reactContext) val view = hybridView.view - view.setTag(associated_hybrid_view_tag, hybridView) + view.setTag(associated_hybrid_view_tag, HybridViewHolder(hybridView)) return view } override fun updateState(view: View, props: ReactStylesDiffMap, stateWrapper: StateWrapper): Any? { - val hybridView = getHybridView(view) + val holder = getHybridViewHolder(view) ?: throw Error("Couldn't find view $view in local views table!") + val hybridView = holder.hybridView + val oldState = holder.lastState + val newState = stateWrapper // 1. Update each prop individually hybridView.beforeUpdate() - HybridFrameRendererViewStateUpdater.updateViewProps(hybridView, stateWrapper) + HybridFrameRendererViewStateUpdater.updateViewProps(hybridView, newState, oldState) hybridView.afterUpdate() + holder.lastState = newState // 2. Continue in base View props - return super.updateState(view, props, stateWrapper) + return super.updateState(view, props, newState) } override fun onDropViewInstance(view: View) { - val hybridView = getHybridView(view) - hybridView?.onDropView() + val holder = getHybridViewHolder(view) + holder?.lastState = null + holder?.hybridView?.onDropView() return super.onDropViewInstance(view) } protected override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? { - super.prepareToRecycleView(reactContext, view) - val hybridView = getHybridView(view) + val preparedView = super.prepareToRecycleView(reactContext, view) + ?: return null + val holder = getHybridViewHolder(preparedView) ?: return null + val hybridView = holder.hybridView + holder.lastState = null @Suppress("USELESS_IS_CHECK") if (hybridView is RecyclableView) { @@ -74,7 +90,7 @@ public class HybridFrameRendererViewManager: SimpleViewManager() { } } - private fun getHybridView(view: View): HybridFrameRendererView? { - return view.getTag(associated_hybrid_view_tag) as? HybridFrameRendererView + private fun getHybridViewHolder(view: View): HybridViewHolder? { + return view.getTag(associated_hybrid_view_tag) as? HybridViewHolder } } diff --git a/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridFrameRendererViewStateUpdater.kt b/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridFrameRendererViewStateUpdater.kt index cb09475a10..85615e7006 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridFrameRendererViewStateUpdater.kt +++ b/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridFrameRendererViewStateUpdater.kt @@ -14,10 +14,10 @@ internal class HybridFrameRendererViewStateUpdater { companion object { /** * Updates the props for [view] through C++. - * The [state] prop is expected to contain [view]'s props as wrapped Fabric state. + * The [newState] prop is expected to contain [view]'s props as wrapped Fabric state. */ @Suppress("KotlinJniMissingFunction") @JvmStatic - external fun updateViewProps(view: HybridFrameRendererViewSpec, state: StateWrapper) + external fun updateViewProps(view: HybridFrameRendererViewSpec, newState: StateWrapper, oldState: StateWrapper?) } } diff --git a/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridPreviewViewManager.kt b/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridPreviewViewManager.kt index 2e3f5b4a62..d2a79480d0 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridPreviewViewManager.kt +++ b/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridPreviewViewManager.kt @@ -20,6 +20,14 @@ import com.margelo.nitro.camera.* * Represents the React Native `ViewManager` for the "PreviewView" Nitro HybridView. */ public class HybridPreviewViewManager: SimpleViewManager() { + /** + * Represents the View and its last state snapshot (mutable) + */ + private class HybridViewHolder( + val hybridView: HybridPreviewView, + var lastState: StateWrapper? = null, + ) + init { if (RecyclableView::class.java.isAssignableFrom(HybridPreviewView::class.java)) { // Enable view recycling @@ -34,33 +42,41 @@ public class HybridPreviewViewManager: SimpleViewManager() { override fun createViewInstance(reactContext: ThemedReactContext): View { val hybridView = HybridPreviewView(reactContext) val view = hybridView.view - view.setTag(associated_hybrid_view_tag, hybridView) + view.setTag(associated_hybrid_view_tag, HybridViewHolder(hybridView)) return view } override fun updateState(view: View, props: ReactStylesDiffMap, stateWrapper: StateWrapper): Any? { - val hybridView = getHybridView(view) + val holder = getHybridViewHolder(view) ?: throw Error("Couldn't find view $view in local views table!") + val hybridView = holder.hybridView + val oldState = holder.lastState + val newState = stateWrapper // 1. Update each prop individually hybridView.beforeUpdate() - HybridPreviewViewStateUpdater.updateViewProps(hybridView, stateWrapper) + HybridPreviewViewStateUpdater.updateViewProps(hybridView, newState, oldState) hybridView.afterUpdate() + holder.lastState = newState // 2. Continue in base View props - return super.updateState(view, props, stateWrapper) + return super.updateState(view, props, newState) } override fun onDropViewInstance(view: View) { - val hybridView = getHybridView(view) - hybridView?.onDropView() + val holder = getHybridViewHolder(view) + holder?.lastState = null + holder?.hybridView?.onDropView() return super.onDropViewInstance(view) } protected override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? { - super.prepareToRecycleView(reactContext, view) - val hybridView = getHybridView(view) + val preparedView = super.prepareToRecycleView(reactContext, view) + ?: return null + val holder = getHybridViewHolder(preparedView) ?: return null + val hybridView = holder.hybridView + holder.lastState = null @Suppress("USELESS_IS_CHECK") if (hybridView is RecyclableView) { @@ -74,7 +90,7 @@ public class HybridPreviewViewManager: SimpleViewManager() { } } - private fun getHybridView(view: View): HybridPreviewView? { - return view.getTag(associated_hybrid_view_tag) as? HybridPreviewView + private fun getHybridViewHolder(view: View): HybridViewHolder? { + return view.getTag(associated_hybrid_view_tag) as? HybridViewHolder } } diff --git a/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridPreviewViewStateUpdater.kt b/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridPreviewViewStateUpdater.kt index d4736fe730..bad443073e 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridPreviewViewStateUpdater.kt +++ b/packages/react-native-vision-camera/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/views/HybridPreviewViewStateUpdater.kt @@ -14,10 +14,10 @@ internal class HybridPreviewViewStateUpdater { companion object { /** * Updates the props for [view] through C++. - * The [state] prop is expected to contain [view]'s props as wrapped Fabric state. + * The [newState] prop is expected to contain [view]'s props as wrapped Fabric state. */ @Suppress("KotlinJniMissingFunction") @JvmStatic - external fun updateViewProps(view: HybridPreviewViewSpec, state: StateWrapper) + external fun updateViewProps(view: HybridPreviewViewSpec, newState: StateWrapper, oldState: StateWrapper?) } } diff --git a/packages/react-native-vision-camera/nitrogen/generated/ios/c++/views/HybridFrameRendererViewComponent.mm b/packages/react-native-vision-camera/nitrogen/generated/ios/c++/views/HybridFrameRendererViewComponent.mm index 9a33d534da..3b6dda44dc 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/ios/c++/views/HybridFrameRendererViewComponent.mm +++ b/packages/react-native-vision-camera/nitrogen/generated/ios/c++/views/HybridFrameRendererViewComponent.mm @@ -37,6 +37,7 @@ + (BOOL)shouldBeRecycled; @implementation HybridFrameRendererViewComponent { std::shared_ptr _hybridView; + BOOL _didDropView; } + (void) load { @@ -50,6 +51,7 @@ + (void) load { - (instancetype) init { if (self = [super init]) { + _props = HybridFrameRendererViewShadowNode::defaultSharedProps(); std::shared_ptr hybridView = VisionCamera::VisionCameraAutolinking::createFrameRendererView(); _hybridView = std::dynamic_pointer_cast(hybridView); [self updateView]; @@ -69,35 +71,55 @@ - (void) updateView { [self setContentView:view]; } +- (void) notifyOnDropView { + // A recycled component can later be invalidated. Notify only once per mount. + if (_didDropView) { + return; + } + VisionCamera::HybridFrameRendererViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); + swiftPart.onDropView(); + _didDropView = YES; +} + - (void) updateProps:(const std::shared_ptr&)props oldProps:(const std::shared_ptr&)oldProps { + // A props update marks a newly mounted or still-active component. + _didDropView = NO; + // 1. Downcast props - const auto& newViewPropsConst = *std::static_pointer_cast(props); - auto& newViewProps = const_cast(newViewPropsConst); + const auto& newViewProps = *std::static_pointer_cast(props); + const auto* oldViewProps = static_cast(oldProps.get()); VisionCamera::HybridFrameRendererViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); - // 2. Update each prop individually - swiftPart.beforeUpdate(); - - // renderer: optional - if (newViewProps.renderer.isDirty) { - swiftPart.setRenderer(newViewProps.renderer.value); - newViewProps.renderer.isDirty = false; - } - - swiftPart.afterUpdate(); + // 2. Update only props that differ from the previous Props snapshot. + const bool hasTransactionPropChanges = oldViewProps == nullptr + ? newViewProps.hasAnyProvidedProps() + : !newViewProps.hasSameProps(*oldViewProps); + if (hasTransactionPropChanges) { + swiftPart.beforeUpdate(); + + // renderer: optional + if (oldViewProps == nullptr + ? newViewProps.renderer.isProvided() + : !newViewProps.renderer.hasSameValue(oldViewProps->renderer)) { + swiftPart.setRenderer(newViewProps.renderer.get()); + } - // 3. Update hybridRef if it changed - if (newViewProps.hybridRef.isDirty) { - // hybridRef changed - call it with new this - const auto& maybeFunc = newViewProps.hybridRef.value; - if (maybeFunc.has_value()) { - maybeFunc.value()(_hybridView); + // Update hybridRef if it changed + if (oldViewProps == nullptr + ? newViewProps.hybridRef.isProvided() + : !newViewProps.hybridRef.hasSameValue(oldViewProps->hybridRef)) { + // hybridRef changed - call it with new this + const auto& maybeFunc = newViewProps.hybridRef.get(); + if (maybeFunc.has_value()) { + maybeFunc.value()(_hybridView); + } } - newViewProps.hybridRef.isDirty = false; + + swiftPart.afterUpdate(); } - // 4. Continue in base class + // 3. Continue in base class [super updateProps:props oldProps:oldProps]; } @@ -106,6 +128,7 @@ + (BOOL)shouldBeRecycled { } - (void)prepareForRecycle { + [self notifyOnDropView]; [super prepareForRecycle]; VisionCamera::HybridFrameRendererViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); swiftPart.maybePrepareForRecycle(); @@ -113,8 +136,7 @@ - (void)prepareForRecycle { #ifdef ENABLE_RCT_COMPONENT_VIEW_INVALIDATE - (void)invalidate { - VisionCamera::HybridFrameRendererViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); - swiftPart.onDropView(); + [self notifyOnDropView]; [super invalidate]; } #endif diff --git a/packages/react-native-vision-camera/nitrogen/generated/ios/c++/views/HybridPreviewViewComponent.mm b/packages/react-native-vision-camera/nitrogen/generated/ios/c++/views/HybridPreviewViewComponent.mm index 888870cb39..3251d7b4fe 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/ios/c++/views/HybridPreviewViewComponent.mm +++ b/packages/react-native-vision-camera/nitrogen/generated/ios/c++/views/HybridPreviewViewComponent.mm @@ -37,6 +37,7 @@ + (BOOL)shouldBeRecycled; @implementation HybridPreviewViewComponent { std::shared_ptr _hybridView; + BOOL _didDropView; } + (void) load { @@ -50,6 +51,7 @@ + (void) load { - (instancetype) init { if (self = [super init]) { + _props = HybridPreviewViewShadowNode::defaultSharedProps(); std::shared_ptr hybridView = VisionCamera::VisionCameraAutolinking::createPreviewView(); _hybridView = std::dynamic_pointer_cast(hybridView); [self updateView]; @@ -69,60 +71,85 @@ - (void) updateView { [self setContentView:view]; } +- (void) notifyOnDropView { + // A recycled component can later be invalidated. Notify only once per mount. + if (_didDropView) { + return; + } + VisionCamera::HybridPreviewViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); + swiftPart.onDropView(); + _didDropView = YES; +} + - (void) updateProps:(const std::shared_ptr&)props oldProps:(const std::shared_ptr&)oldProps { + // A props update marks a newly mounted or still-active component. + _didDropView = NO; + // 1. Downcast props - const auto& newViewPropsConst = *std::static_pointer_cast(props); - auto& newViewProps = const_cast(newViewPropsConst); + const auto& newViewProps = *std::static_pointer_cast(props); + const auto* oldViewProps = static_cast(oldProps.get()); VisionCamera::HybridPreviewViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); - // 2. Update each prop individually - swiftPart.beforeUpdate(); - - // previewOutput: optional - if (newViewProps.previewOutput.isDirty) { - swiftPart.setPreviewOutput(newViewProps.previewOutput.value); - newViewProps.previewOutput.isDirty = false; - } - // resizeMode: optional - if (newViewProps.resizeMode.isDirty) { - swiftPart.setResizeMode(newViewProps.resizeMode.value); - newViewProps.resizeMode.isDirty = false; - } - // implementationMode: optional - if (newViewProps.implementationMode.isDirty) { - swiftPart.setImplementationMode(newViewProps.implementationMode.value); - newViewProps.implementationMode.isDirty = false; - } - // gestureControllers: optional - if (newViewProps.gestureControllers.isDirty) { - swiftPart.setGestureControllers(newViewProps.gestureControllers.value); - newViewProps.gestureControllers.isDirty = false; - } - // onPreviewStarted: optional - if (newViewProps.onPreviewStarted.isDirty) { - swiftPart.setOnPreviewStarted(newViewProps.onPreviewStarted.value); - newViewProps.onPreviewStarted.isDirty = false; - } - // onPreviewStopped: optional - if (newViewProps.onPreviewStopped.isDirty) { - swiftPart.setOnPreviewStopped(newViewProps.onPreviewStopped.value); - newViewProps.onPreviewStopped.isDirty = false; - } - - swiftPart.afterUpdate(); + // 2. Update only props that differ from the previous Props snapshot. + const bool hasTransactionPropChanges = oldViewProps == nullptr + ? newViewProps.hasAnyProvidedProps() + : !newViewProps.hasSameProps(*oldViewProps); + if (hasTransactionPropChanges) { + swiftPart.beforeUpdate(); + + // previewOutput: optional + if (oldViewProps == nullptr + ? newViewProps.previewOutput.isProvided() + : !newViewProps.previewOutput.hasSameValue(oldViewProps->previewOutput)) { + swiftPart.setPreviewOutput(newViewProps.previewOutput.get()); + } + // resizeMode: optional + if (oldViewProps == nullptr + ? newViewProps.resizeMode.isProvided() + : !newViewProps.resizeMode.hasSameValue(oldViewProps->resizeMode)) { + swiftPart.setResizeMode(newViewProps.resizeMode.get()); + } + // implementationMode: optional + if (oldViewProps == nullptr + ? newViewProps.implementationMode.isProvided() + : !newViewProps.implementationMode.hasSameValue(oldViewProps->implementationMode)) { + swiftPart.setImplementationMode(newViewProps.implementationMode.get()); + } + // gestureControllers: optional + if (oldViewProps == nullptr + ? newViewProps.gestureControllers.isProvided() + : !newViewProps.gestureControllers.hasSameValue(oldViewProps->gestureControllers)) { + swiftPart.setGestureControllers(newViewProps.gestureControllers.get()); + } + // onPreviewStarted: optional + if (oldViewProps == nullptr + ? newViewProps.onPreviewStarted.isProvided() + : !newViewProps.onPreviewStarted.hasSameValue(oldViewProps->onPreviewStarted)) { + swiftPart.setOnPreviewStarted(newViewProps.onPreviewStarted.get()); + } + // onPreviewStopped: optional + if (oldViewProps == nullptr + ? newViewProps.onPreviewStopped.isProvided() + : !newViewProps.onPreviewStopped.hasSameValue(oldViewProps->onPreviewStopped)) { + swiftPart.setOnPreviewStopped(newViewProps.onPreviewStopped.get()); + } - // 3. Update hybridRef if it changed - if (newViewProps.hybridRef.isDirty) { - // hybridRef changed - call it with new this - const auto& maybeFunc = newViewProps.hybridRef.value; - if (maybeFunc.has_value()) { - maybeFunc.value()(_hybridView); + // Update hybridRef if it changed + if (oldViewProps == nullptr + ? newViewProps.hybridRef.isProvided() + : !newViewProps.hybridRef.hasSameValue(oldViewProps->hybridRef)) { + // hybridRef changed - call it with new this + const auto& maybeFunc = newViewProps.hybridRef.get(); + if (maybeFunc.has_value()) { + maybeFunc.value()(_hybridView); + } } - newViewProps.hybridRef.isDirty = false; + + swiftPart.afterUpdate(); } - // 4. Continue in base class + // 3. Continue in base class [super updateProps:props oldProps:oldProps]; } @@ -131,6 +158,7 @@ + (BOOL)shouldBeRecycled { } - (void)prepareForRecycle { + [self notifyOnDropView]; [super prepareForRecycle]; VisionCamera::HybridPreviewViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); swiftPart.maybePrepareForRecycle(); @@ -138,8 +166,7 @@ - (void)prepareForRecycle { #ifdef ENABLE_RCT_COMPONENT_VIEW_INVALIDATE - (void)invalidate { - VisionCamera::HybridPreviewViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); - swiftPart.onDropView(); + [self notifyOnDropView]; [super invalidate]; } #endif diff --git a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.cpp b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.cpp index fc6741057b..ec9596c446 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.cpp +++ b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.cpp @@ -7,45 +7,21 @@ #include "HybridFrameRendererViewComponent.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include namespace margelo::nitro::camera::views { + using namespace facebook; + extern const char HybridFrameRendererViewComponentName[] = "FrameRendererView"; HybridFrameRendererViewProps::HybridFrameRendererViewProps(const react::PropsParserContext& context, const HybridFrameRendererViewProps& sourceProps, const react::RawProps& rawProps): react::ViewProps(context, sourceProps, rawProps, filterObjectKeys), - renderer([&]() -> CachedProp>> { - try { - const react::RawValue* rawValue = rawProps.at("renderer", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.renderer; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp>>::fromRawValue(*runtime, value, sourceProps.renderer); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("FrameRendererView.renderer: ") + exc.what()); - } - }()), - hybridRef([&]() -> CachedProp& /* ref */)>>> { - try { - const react::RawValue* rawValue = rawProps.at("hybridRef", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.hybridRef; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp& /* ref */)>>>::fromRawValue(*runtime, value.asObject(*runtime).getProperty(*runtime, PropNameIDCache::get(*runtime, "f")), sourceProps.hybridRef); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("FrameRendererView.hybridRef: ") + exc.what()); - } - }()) { } + renderer(nitro::CachedProp>>::fromRawValue("FrameRendererView", "renderer", rawProps, sourceProps.renderer)), + hybridRef(nitro::CachedProp& /* ref */)>>>::fromRawValue("FrameRendererView", "hybridRef", rawProps, sourceProps.hybridRef)) { } bool HybridFrameRendererViewProps::filterObjectKeys(const std::string& propName) { switch (hashString(propName)) { @@ -55,29 +31,4 @@ namespace margelo::nitro::camera::views { } } - HybridFrameRendererViewComponentDescriptor::HybridFrameRendererViewComponentDescriptor(const react::ComponentDescriptorParameters& parameters) - : ConcreteComponentDescriptor(parameters, - react::RawPropsParser()) {} - - std::shared_ptr HybridFrameRendererViewComponentDescriptor::cloneProps(const react::PropsParserContext& context, - const std::shared_ptr& props, - react::RawProps rawProps) const { - // 1. Prepare raw props parser - rawProps.parse(rawPropsParser_); - // 2. Copy props with Nitro's cached copy constructor - return HybridFrameRendererViewShadowNode::Props(context, /* & */ rawProps, props); - } - -#ifdef ANDROID - void HybridFrameRendererViewComponentDescriptor::adopt(react::ShadowNode& shadowNode) const { - // This is called immediately after `ShadowNode` is created, cloned or in progress. - // On Android, we need to wrap props in our state, which gets routed through Java and later unwrapped in JNI/C++. - auto& concreteShadowNode = static_cast(shadowNode); - const std::shared_ptr& constProps = concreteShadowNode.getConcreteSharedProps(); - const std::shared_ptr& props = std::const_pointer_cast(constProps); - HybridFrameRendererViewState state{props}; - concreteShadowNode.setStateData(std::move(state)); - } -#endif - } // namespace margelo::nitro::camera::views diff --git a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.hpp b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.hpp index cac70f501e..ccc618dc06 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.hpp +++ b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.hpp @@ -7,14 +7,15 @@ #pragma once -#include -#include -#include #include -#include -#include +#include +#include #include #include +#include +#include + +#include #include #include "HybridFrameRendererSpec.hpp" @@ -42,8 +43,20 @@ namespace margelo::nitro::camera::views { const react::RawProps& rawProps); public: - CachedProp>> renderer; - CachedProp& /* ref */)>>> hybridRef; + nitro::CachedProp>> renderer; + nitro::CachedProp& /* ref */)>>> hybridRef; + + [[nodiscard]] + bool hasSameProps(const HybridFrameRendererViewProps& other) const noexcept { + return renderer.hasSameValue(other.renderer) && + hybridRef.hasSameValue(other.hybridRef); + } + + [[nodiscard]] + bool hasAnyProvidedProps() const noexcept { + return renderer.isProvided() || + hybridRef.isProvided(); + } private: static bool filterObjectKeys(const std::string& propName); @@ -52,32 +65,7 @@ namespace margelo::nitro::camera::views { /** * State for the "FrameRendererView" View. */ - class HybridFrameRendererViewState final { - public: - HybridFrameRendererViewState() = default; - explicit HybridFrameRendererViewState(const std::shared_ptr& props): - _props(props) {} - - public: - [[nodiscard]] - const std::shared_ptr& getProps() const { - return _props; - } - - public: -#ifdef ANDROID - HybridFrameRendererViewState(const HybridFrameRendererViewState& /* previousState */, folly::dynamic /* data */) {} - folly::dynamic getDynamic() const { - throw std::runtime_error("HybridFrameRendererViewState does not support folly!"); - } - react::MapBuffer getMapBuffer() const { - throw std::runtime_error("HybridFrameRendererViewState does not support MapBuffer!"); - }; -#endif - - private: - std::shared_ptr _props; - }; + using HybridFrameRendererViewState = nitro::ViewPropsHolderState; /** * The Shadow Node for the "FrameRendererView" View. @@ -90,21 +78,7 @@ namespace margelo::nitro::camera::views { /** * The Component Descriptor for the "FrameRendererView" View. */ - class HybridFrameRendererViewComponentDescriptor final: public react::ConcreteComponentDescriptor { - public: - explicit HybridFrameRendererViewComponentDescriptor(const react::ComponentDescriptorParameters& parameters); - - public: - /** - * A faster path for cloning props - reuses the caching logic from `HybridFrameRendererViewProps`. - */ - std::shared_ptr cloneProps(const react::PropsParserContext& context, - const std::shared_ptr& props, - react::RawProps rawProps) const override; -#ifdef ANDROID - void adopt(react::ShadowNode& shadowNode) const override; -#endif - }; + using HybridFrameRendererViewComponentDescriptor = nitro::ViewComponentDescriptor; /* The actual view for "FrameRendererView" needs to be implemented in platform-specific code. */ diff --git a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.cpp b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.cpp index d9eac55a28..b789563915 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.cpp +++ b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.cpp @@ -7,95 +7,26 @@ #include "HybridPreviewViewComponent.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include namespace margelo::nitro::camera::views { + using namespace facebook; + extern const char HybridPreviewViewComponentName[] = "PreviewView"; HybridPreviewViewProps::HybridPreviewViewProps(const react::PropsParserContext& context, const HybridPreviewViewProps& sourceProps, const react::RawProps& rawProps): react::ViewProps(context, sourceProps, rawProps, filterObjectKeys), - previewOutput([&]() -> CachedProp>> { - try { - const react::RawValue* rawValue = rawProps.at("previewOutput", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.previewOutput; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp>>::fromRawValue(*runtime, value, sourceProps.previewOutput); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("PreviewView.previewOutput: ") + exc.what()); - } - }()), - resizeMode([&]() -> CachedProp> { - try { - const react::RawValue* rawValue = rawProps.at("resizeMode", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.resizeMode; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp>::fromRawValue(*runtime, value, sourceProps.resizeMode); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("PreviewView.resizeMode: ") + exc.what()); - } - }()), - implementationMode([&]() -> CachedProp> { - try { - const react::RawValue* rawValue = rawProps.at("implementationMode", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.implementationMode; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp>::fromRawValue(*runtime, value, sourceProps.implementationMode); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("PreviewView.implementationMode: ") + exc.what()); - } - }()), - gestureControllers([&]() -> CachedProp>>> { - try { - const react::RawValue* rawValue = rawProps.at("gestureControllers", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.gestureControllers; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp>>>::fromRawValue(*runtime, value, sourceProps.gestureControllers); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("PreviewView.gestureControllers: ") + exc.what()); - } - }()), - onPreviewStarted([&]() -> CachedProp>> { - try { - const react::RawValue* rawValue = rawProps.at("onPreviewStarted", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.onPreviewStarted; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp>>::fromRawValue(*runtime, value.asObject(*runtime).getProperty(*runtime, PropNameIDCache::get(*runtime, "f")), sourceProps.onPreviewStarted); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("PreviewView.onPreviewStarted: ") + exc.what()); - } - }()), - onPreviewStopped([&]() -> CachedProp>> { - try { - const react::RawValue* rawValue = rawProps.at("onPreviewStopped", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.onPreviewStopped; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp>>::fromRawValue(*runtime, value.asObject(*runtime).getProperty(*runtime, PropNameIDCache::get(*runtime, "f")), sourceProps.onPreviewStopped); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("PreviewView.onPreviewStopped: ") + exc.what()); - } - }()), - hybridRef([&]() -> CachedProp& /* ref */)>>> { - try { - const react::RawValue* rawValue = rawProps.at("hybridRef", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.hybridRef; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp& /* ref */)>>>::fromRawValue(*runtime, value.asObject(*runtime).getProperty(*runtime, PropNameIDCache::get(*runtime, "f")), sourceProps.hybridRef); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("PreviewView.hybridRef: ") + exc.what()); - } - }()) { } + previewOutput(nitro::CachedProp>>::fromRawValue("PreviewView", "previewOutput", rawProps, sourceProps.previewOutput)), + resizeMode(nitro::CachedProp>::fromRawValue("PreviewView", "resizeMode", rawProps, sourceProps.resizeMode)), + implementationMode(nitro::CachedProp>::fromRawValue("PreviewView", "implementationMode", rawProps, sourceProps.implementationMode)), + gestureControllers(nitro::CachedProp>>>::fromRawValue("PreviewView", "gestureControllers", rawProps, sourceProps.gestureControllers)), + onPreviewStarted(nitro::CachedProp>>::fromRawValue("PreviewView", "onPreviewStarted", rawProps, sourceProps.onPreviewStarted)), + onPreviewStopped(nitro::CachedProp>>::fromRawValue("PreviewView", "onPreviewStopped", rawProps, sourceProps.onPreviewStopped)), + hybridRef(nitro::CachedProp& /* ref */)>>>::fromRawValue("PreviewView", "hybridRef", rawProps, sourceProps.hybridRef)) { } bool HybridPreviewViewProps::filterObjectKeys(const std::string& propName) { switch (hashString(propName)) { @@ -110,29 +41,4 @@ namespace margelo::nitro::camera::views { } } - HybridPreviewViewComponentDescriptor::HybridPreviewViewComponentDescriptor(const react::ComponentDescriptorParameters& parameters) - : ConcreteComponentDescriptor(parameters, - react::RawPropsParser()) {} - - std::shared_ptr HybridPreviewViewComponentDescriptor::cloneProps(const react::PropsParserContext& context, - const std::shared_ptr& props, - react::RawProps rawProps) const { - // 1. Prepare raw props parser - rawProps.parse(rawPropsParser_); - // 2. Copy props with Nitro's cached copy constructor - return HybridPreviewViewShadowNode::Props(context, /* & */ rawProps, props); - } - -#ifdef ANDROID - void HybridPreviewViewComponentDescriptor::adopt(react::ShadowNode& shadowNode) const { - // This is called immediately after `ShadowNode` is created, cloned or in progress. - // On Android, we need to wrap props in our state, which gets routed through Java and later unwrapped in JNI/C++. - auto& concreteShadowNode = static_cast(shadowNode); - const std::shared_ptr& constProps = concreteShadowNode.getConcreteSharedProps(); - const std::shared_ptr& props = std::const_pointer_cast(constProps); - HybridPreviewViewState state{props}; - concreteShadowNode.setStateData(std::move(state)); - } -#endif - } // namespace margelo::nitro::camera::views diff --git a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.hpp b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.hpp index 1aa231c0d5..b2d585a68e 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.hpp +++ b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.hpp @@ -7,14 +7,15 @@ #pragma once -#include -#include -#include #include -#include -#include +#include +#include #include #include +#include +#include + +#include #include #include "HybridCameraPreviewOutputSpec.hpp" @@ -46,13 +47,35 @@ namespace margelo::nitro::camera::views { const react::RawProps& rawProps); public: - CachedProp>> previewOutput; - CachedProp> resizeMode; - CachedProp> implementationMode; - CachedProp>>> gestureControllers; - CachedProp>> onPreviewStarted; - CachedProp>> onPreviewStopped; - CachedProp& /* ref */)>>> hybridRef; + nitro::CachedProp>> previewOutput; + nitro::CachedProp> resizeMode; + nitro::CachedProp> implementationMode; + nitro::CachedProp>>> gestureControllers; + nitro::CachedProp>> onPreviewStarted; + nitro::CachedProp>> onPreviewStopped; + nitro::CachedProp& /* ref */)>>> hybridRef; + + [[nodiscard]] + bool hasSameProps(const HybridPreviewViewProps& other) const noexcept { + return previewOutput.hasSameValue(other.previewOutput) && + resizeMode.hasSameValue(other.resizeMode) && + implementationMode.hasSameValue(other.implementationMode) && + gestureControllers.hasSameValue(other.gestureControllers) && + onPreviewStarted.hasSameValue(other.onPreviewStarted) && + onPreviewStopped.hasSameValue(other.onPreviewStopped) && + hybridRef.hasSameValue(other.hybridRef); + } + + [[nodiscard]] + bool hasAnyProvidedProps() const noexcept { + return previewOutput.isProvided() || + resizeMode.isProvided() || + implementationMode.isProvided() || + gestureControllers.isProvided() || + onPreviewStarted.isProvided() || + onPreviewStopped.isProvided() || + hybridRef.isProvided(); + } private: static bool filterObjectKeys(const std::string& propName); @@ -61,32 +84,7 @@ namespace margelo::nitro::camera::views { /** * State for the "PreviewView" View. */ - class HybridPreviewViewState final { - public: - HybridPreviewViewState() = default; - explicit HybridPreviewViewState(const std::shared_ptr& props): - _props(props) {} - - public: - [[nodiscard]] - const std::shared_ptr& getProps() const { - return _props; - } - - public: -#ifdef ANDROID - HybridPreviewViewState(const HybridPreviewViewState& /* previousState */, folly::dynamic /* data */) {} - folly::dynamic getDynamic() const { - throw std::runtime_error("HybridPreviewViewState does not support folly!"); - } - react::MapBuffer getMapBuffer() const { - throw std::runtime_error("HybridPreviewViewState does not support MapBuffer!"); - }; -#endif - - private: - std::shared_ptr _props; - }; + using HybridPreviewViewState = nitro::ViewPropsHolderState; /** * The Shadow Node for the "PreviewView" View. @@ -99,21 +97,7 @@ namespace margelo::nitro::camera::views { /** * The Component Descriptor for the "PreviewView" View. */ - class HybridPreviewViewComponentDescriptor final: public react::ConcreteComponentDescriptor { - public: - explicit HybridPreviewViewComponentDescriptor(const react::ComponentDescriptorParameters& parameters); - - public: - /** - * A faster path for cloning props - reuses the caching logic from `HybridPreviewViewProps`. - */ - std::shared_ptr cloneProps(const react::PropsParserContext& context, - const std::shared_ptr& props, - react::RawProps rawProps) const override; -#ifdef ANDROID - void adopt(react::ShadowNode& shadowNode) const override; -#endif - }; + using HybridPreviewViewComponentDescriptor = nitro::ViewComponentDescriptor; /* The actual view for "PreviewView" needs to be implemented in platform-specific code. */ diff --git a/packages/react-native-vision-camera/package.json b/packages/react-native-vision-camera/package.json index 40efb063bd..affd14edfd 100644 --- a/packages/react-native-vision-camera/package.json +++ b/packages/react-native-vision-camera/package.json @@ -70,11 +70,11 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "typescript": "6.0.3" }, "peerDependencies": { From 1dd437d67dd26f914a7a3ec5e982331f93b8b382 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Thu, 20 Aug 2026 17:20:43 +0200 Subject: [PATCH 2/5] fix: Override `react-native-nitro-modules` to 0.37.0-beta.0 `*` in peerDependencies does not match prereleases, so bun could not dedupe the peer onto the hoisted 0.37.0-beta.0 and installed a second copy at 0.36.5 under each package. That auto-installed peer state also broke `bun install --frozen-lockfile` in CI - the lockfile round-trips byte-identically, so regenerating it never helped. Pin it via a root override for now. --- bun.lock | 15 +++------------ package.json | 3 +++ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/bun.lock b/bun.lock index d24ff88d37..58431dd02a 100644 --- a/bun.lock +++ b/bun.lock @@ -247,6 +247,9 @@ "patchedDependencies": { "react-native@0.85.3": "patches/react-native@0.85.3.patch", }, + "overrides": { + "react-native-nitro-modules": "0.37.0-beta.0", + }, "packages": { "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], @@ -3530,20 +3533,8 @@ "react-native/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - "react-native-nitro-image/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], - "react-native-vector-icons/yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], - "react-native-vision-camera/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], - - "react-native-vision-camera-barcode-scanner/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], - - "react-native-vision-camera-location/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], - - "react-native-vision-camera-resizer/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], - - "react-native-vision-camera-worklets/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], - "react-reconciler/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], "release-it/url-join": ["url-join@5.0.0", "", {}, "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA=="], diff --git a/package.json b/package.json index ec25425ab4..f1e1fb937d 100644 --- a/package.json +++ b/package.json @@ -125,6 +125,9 @@ } } }, + "overrides": { + "react-native-nitro-modules": "0.37.0-beta.0" + }, "patchedDependencies": { "react-native@0.85.3": "patches/react-native@0.85.3.patch" }, From 148a48d78ca64e8c042a298250f5d3f071472111 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Thu, 20 Aug 2026 18:39:29 +0200 Subject: [PATCH 3/5] feat: Upgrade Nitro to 0.37.0-beta.1 Regenerates specs with nitrogen 0.37.0-beta.1, which migrates the View prop types from `CachedProp` to `ReactProp`. beta.1 also re-adds legacy `CachedProp` as deprecated, so `react-native-nitro-image@0.15.1` - whose generated code still uses `CachedProp::isDirty`/`::value` - compiles again. That was what broke Build Android on beta.0. --- apps/simple-camera/ios/Podfile.lock | 4 +-- apps/simple-camera/package.json | 2 +- bun.lock | 30 +++++++++---------- package.json | 2 +- .../package.json | 4 +-- .../package.json | 4 +-- .../package.json | 4 +-- .../package.json | 2 +- .../package.json | 4 +-- .../HybridFrameRendererViewComponent.cpp | 6 ++-- .../HybridFrameRendererViewComponent.hpp | 6 ++-- .../c++/views/HybridPreviewViewComponent.cpp | 16 +++++----- .../c++/views/HybridPreviewViewComponent.hpp | 16 +++++----- .../react-native-vision-camera/package.json | 4 +-- 14 files changed, 52 insertions(+), 52 deletions(-) diff --git a/apps/simple-camera/ios/Podfile.lock b/apps/simple-camera/ios/Podfile.lock index 13b42835de..3df1cef3a4 100644 --- a/apps/simple-camera/ios/Podfile.lock +++ b/apps/simple-camera/ios/Podfile.lock @@ -94,7 +94,7 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - NitroModules (0.37.0-beta.0): + - NitroModules (0.37.0-beta.1): - hermes-engine - RCTRequired - RCTTypeSafety @@ -2788,7 +2788,7 @@ SPEC CHECKSUMS: MLKitVision: 39a5a812db83c4a0794445088e567f3631c11961 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 NitroImage: 2f592086cbdecbbaa1c10dd97e0cdd43b1bb0817 - NitroModules: 6b173a14405398cc5db9568ee4b1ac091aebc20a + NitroModules: 7b1bbaed4743fc48e3dfc50d1f8aaf58a8421c31 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 RCTDeprecation: a4c521821fab57cbb125b36effe84d897d0dfa12 RCTRequired: 9f3a7e5645d4bc3f551593de7550bb66ab6e42bc diff --git a/apps/simple-camera/package.json b/apps/simple-camera/package.json index 1218031b5f..01c900d395 100644 --- a/apps/simple-camera/package.json +++ b/apps/simple-camera/package.json @@ -26,7 +26,7 @@ "react-native": "0.85.3", "react-native-gesture-handler": "^3.0.0", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-reanimated": "4.4.0", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2", diff --git a/bun.lock b/bun.lock index 58431dd02a..59b7e64e4d 100644 --- a/bun.lock +++ b/bun.lock @@ -33,7 +33,7 @@ "react-native": "0.85.3", "react-native-gesture-handler": "^3.0.0", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-reanimated": "4.4.0", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2", @@ -106,11 +106,11 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "typescript": "6.0.3", }, "peerDependencies": { @@ -128,11 +128,11 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-vision-camera": "*", "typescript": "6.0.3", }, @@ -152,10 +152,10 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-vision-camera": "*", "typescript": "6.0.3", }, @@ -174,10 +174,10 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-vision-camera": "*", "typescript": "6.0.3", }, @@ -199,7 +199,7 @@ "@types/react": "19.2.15", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-reanimated": "4.4.0", "react-native-vision-camera": "*", "react-native-vision-camera-worklets": "*", @@ -221,10 +221,10 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-vision-camera": "*", "react-native-worklets": "0.9.1", "typescript": "6.0.3", @@ -248,7 +248,7 @@ "react-native@0.85.3": "patches/react-native@0.85.3.patch", }, "overrides": { - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", }, "packages": { "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], @@ -2223,7 +2223,7 @@ "next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="], - "nitrogen": ["nitrogen@0.37.0-beta.0", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.37.0-beta.0", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-pKrlM7ZYlAVdVNpho9XvGeGOw7gzH0IglQjnmkeDk3aZASLBhGEMlmfq+LsaRGcONxpO4kayTMH/fd3/IaBoTA=="], + "nitrogen": ["nitrogen@0.37.0-beta.1", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.37.0-beta.1", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-DMe2KA168ZWY9pkn1BFhTPjg2yfcVF4e/Fboj9lQElK3wBMYzDECIgcgHvfeoxo+z9ZBRVV4PR4p8c57PiOccQ=="], "nocache": ["nocache@3.0.4", "", {}, "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw=="], @@ -2409,7 +2409,7 @@ "react-native-nitro-image": ["react-native-nitro-image@0.15.1", "", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-nitro-modules": "*" } }, "sha512-slrImfUgasAdzylTiNWuTkawE0R4t7LGh+7N2VFa/D9+SxlQbkKYp1J6hA3XkkEnTnUCKaea39ZVg+1xx665MQ=="], - "react-native-nitro-modules": ["react-native-nitro-modules@0.37.0-beta.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-kGfWyj3IS7+B3IaukbaO84/YcdevhXWCGqBHzwQ7yvALBty56MPt18H9hCKAaua7oNEk0ZZUo3kgMr3o9CYpGA=="], + "react-native-nitro-modules": ["react-native-nitro-modules@0.37.0-beta.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-PQfd8YVgK+sDrcw+m8EZ9jBD1bgmoHhofDO882EGDaRlKoCAUy1yvMP16esouk8CnMEBGdKToWW2EBOu13JUBA=="], "react-native-reanimated": ["react-native-reanimated@4.4.0", "", { "dependencies": { "react-native-is-edge-to-edge": "^1.3.1", "semver": "^7.7.3" }, "peerDependencies": { "react": "*", "react-native": "0.83 - 0.86", "react-native-worklets": "0.9.x" } }, "sha512-0XbC1SpF3JZOz5QfmTEx3vt8VkmkTlS05CBIOKEg5q5ZSNlGtlacntlhj5CrfZlN1ciHAeoliJouTC2cLGKbDA=="], diff --git a/package.json b/package.json index f1e1fb937d..4a11660b6d 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ } }, "overrides": { - "react-native-nitro-modules": "0.37.0-beta.0" + "react-native-nitro-modules": "0.37.0-beta.1" }, "patchedDependencies": { "react-native@0.85.3": "patches/react-native@0.85.3.patch" diff --git a/packages/react-native-vision-camera-barcode-scanner/package.json b/packages/react-native-vision-camera-barcode-scanner/package.json index cc7ced3c46..d272843f39 100644 --- a/packages/react-native-vision-camera-barcode-scanner/package.json +++ b/packages/react-native-vision-camera-barcode-scanner/package.json @@ -66,11 +66,11 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-vision-camera": "*", "typescript": "6.0.3" }, diff --git a/packages/react-native-vision-camera-location/package.json b/packages/react-native-vision-camera-location/package.json index 41300d3dc8..bb8f3f65c0 100644 --- a/packages/react-native-vision-camera-location/package.json +++ b/packages/react-native-vision-camera-location/package.json @@ -65,10 +65,10 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-vision-camera": "*", "typescript": "6.0.3" }, diff --git a/packages/react-native-vision-camera-resizer/package.json b/packages/react-native-vision-camera-resizer/package.json index 7bbbf296d7..1d1da27df6 100644 --- a/packages/react-native-vision-camera-resizer/package.json +++ b/packages/react-native-vision-camera-resizer/package.json @@ -70,10 +70,10 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-vision-camera": "*", "typescript": "6.0.3" }, diff --git a/packages/react-native-vision-camera-skia/package.json b/packages/react-native-vision-camera-skia/package.json index d8ad7e261a..5d952b3eb7 100644 --- a/packages/react-native-vision-camera-skia/package.json +++ b/packages/react-native-vision-camera-skia/package.json @@ -56,7 +56,7 @@ "@types/react": "19.2.15", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-reanimated": "4.4.0", "react-native-worklets": "0.9.1", "react-native-vision-camera": "*", diff --git a/packages/react-native-vision-camera-worklets/package.json b/packages/react-native-vision-camera-worklets/package.json index 7efa7b7b64..532f47ca67 100644 --- a/packages/react-native-vision-camera-worklets/package.json +++ b/packages/react-native-vision-camera-worklets/package.json @@ -66,10 +66,10 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-worklets": "0.9.1", "react-native-vision-camera": "*", "typescript": "6.0.3" diff --git a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.cpp b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.cpp index ec9596c446..5255f8e05c 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.cpp +++ b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.cpp @@ -8,7 +8,7 @@ #include "HybridFrameRendererViewComponent.hpp" #include -#include +#include namespace margelo::nitro::camera::views { @@ -20,8 +20,8 @@ namespace margelo::nitro::camera::views { const HybridFrameRendererViewProps& sourceProps, const react::RawProps& rawProps): react::ViewProps(context, sourceProps, rawProps, filterObjectKeys), - renderer(nitro::CachedProp>>::fromRawValue("FrameRendererView", "renderer", rawProps, sourceProps.renderer)), - hybridRef(nitro::CachedProp& /* ref */)>>>::fromRawValue("FrameRendererView", "hybridRef", rawProps, sourceProps.hybridRef)) { } + renderer(nitro::ReactProp>>::fromRawValue("FrameRendererView", "renderer", rawProps, sourceProps.renderer)), + hybridRef(nitro::ReactProp& /* ref */)>>>::fromRawValue("FrameRendererView", "hybridRef", rawProps, sourceProps.hybridRef)) { } bool HybridFrameRendererViewProps::filterObjectKeys(const std::string& propName) { switch (hashString(propName)) { diff --git a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.hpp b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.hpp index ccc618dc06..537ae4a3ad 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.hpp +++ b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridFrameRendererViewComponent.hpp @@ -7,7 +7,7 @@ #pragma once -#include +#include #include #include #include @@ -43,8 +43,8 @@ namespace margelo::nitro::camera::views { const react::RawProps& rawProps); public: - nitro::CachedProp>> renderer; - nitro::CachedProp& /* ref */)>>> hybridRef; + nitro::ReactProp>> renderer; + nitro::ReactProp& /* ref */)>>> hybridRef; [[nodiscard]] bool hasSameProps(const HybridFrameRendererViewProps& other) const noexcept { diff --git a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.cpp b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.cpp index b789563915..7e6f73b6d1 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.cpp +++ b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.cpp @@ -8,7 +8,7 @@ #include "HybridPreviewViewComponent.hpp" #include -#include +#include namespace margelo::nitro::camera::views { @@ -20,13 +20,13 @@ namespace margelo::nitro::camera::views { const HybridPreviewViewProps& sourceProps, const react::RawProps& rawProps): react::ViewProps(context, sourceProps, rawProps, filterObjectKeys), - previewOutput(nitro::CachedProp>>::fromRawValue("PreviewView", "previewOutput", rawProps, sourceProps.previewOutput)), - resizeMode(nitro::CachedProp>::fromRawValue("PreviewView", "resizeMode", rawProps, sourceProps.resizeMode)), - implementationMode(nitro::CachedProp>::fromRawValue("PreviewView", "implementationMode", rawProps, sourceProps.implementationMode)), - gestureControllers(nitro::CachedProp>>>::fromRawValue("PreviewView", "gestureControllers", rawProps, sourceProps.gestureControllers)), - onPreviewStarted(nitro::CachedProp>>::fromRawValue("PreviewView", "onPreviewStarted", rawProps, sourceProps.onPreviewStarted)), - onPreviewStopped(nitro::CachedProp>>::fromRawValue("PreviewView", "onPreviewStopped", rawProps, sourceProps.onPreviewStopped)), - hybridRef(nitro::CachedProp& /* ref */)>>>::fromRawValue("PreviewView", "hybridRef", rawProps, sourceProps.hybridRef)) { } + previewOutput(nitro::ReactProp>>::fromRawValue("PreviewView", "previewOutput", rawProps, sourceProps.previewOutput)), + resizeMode(nitro::ReactProp>::fromRawValue("PreviewView", "resizeMode", rawProps, sourceProps.resizeMode)), + implementationMode(nitro::ReactProp>::fromRawValue("PreviewView", "implementationMode", rawProps, sourceProps.implementationMode)), + gestureControllers(nitro::ReactProp>>>::fromRawValue("PreviewView", "gestureControllers", rawProps, sourceProps.gestureControllers)), + onPreviewStarted(nitro::ReactProp>>::fromRawValue("PreviewView", "onPreviewStarted", rawProps, sourceProps.onPreviewStarted)), + onPreviewStopped(nitro::ReactProp>>::fromRawValue("PreviewView", "onPreviewStopped", rawProps, sourceProps.onPreviewStopped)), + hybridRef(nitro::ReactProp& /* ref */)>>>::fromRawValue("PreviewView", "hybridRef", rawProps, sourceProps.hybridRef)) { } bool HybridPreviewViewProps::filterObjectKeys(const std::string& propName) { switch (hashString(propName)) { diff --git a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.hpp b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.hpp index b2d585a68e..7c586454ea 100644 --- a/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.hpp +++ b/packages/react-native-vision-camera/nitrogen/generated/shared/c++/views/HybridPreviewViewComponent.hpp @@ -7,7 +7,7 @@ #pragma once -#include +#include #include #include #include @@ -47,13 +47,13 @@ namespace margelo::nitro::camera::views { const react::RawProps& rawProps); public: - nitro::CachedProp>> previewOutput; - nitro::CachedProp> resizeMode; - nitro::CachedProp> implementationMode; - nitro::CachedProp>>> gestureControllers; - nitro::CachedProp>> onPreviewStarted; - nitro::CachedProp>> onPreviewStopped; - nitro::CachedProp& /* ref */)>>> hybridRef; + nitro::ReactProp>> previewOutput; + nitro::ReactProp> resizeMode; + nitro::ReactProp> implementationMode; + nitro::ReactProp>>> gestureControllers; + nitro::ReactProp>> onPreviewStarted; + nitro::ReactProp>> onPreviewStopped; + nitro::ReactProp& /* ref */)>>> hybridRef; [[nodiscard]] bool hasSameProps(const HybridPreviewViewProps& other) const noexcept { diff --git a/packages/react-native-vision-camera/package.json b/packages/react-native-vision-camera/package.json index affd14edfd..bd529336a3 100644 --- a/packages/react-native-vision-camera/package.json +++ b/packages/react-native-vision-camera/package.json @@ -70,11 +70,11 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "typescript": "6.0.3" }, "peerDependencies": { From d2b7108b24a92b0edfbdf854986db7ebf24396b4 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Thu, 20 Aug 2026 18:44:38 +0200 Subject: [PATCH 4/5] fix: Drop `react-native-nitro-modules` override Superseded by #4165 - marking the peer dependency optional stops the package manager from resolving a second, stable Nitro next to the pre-release, so the root override is no longer needed. Verified from a clean node_modules: exactly one Nitro copy (0.37.0-beta.1) and `bun install --frozen-lockfile` passes. --- bun.lock | 3 --- package.json | 3 --- 2 files changed, 6 deletions(-) diff --git a/bun.lock b/bun.lock index 59b7e64e4d..d401c5e688 100644 --- a/bun.lock +++ b/bun.lock @@ -247,9 +247,6 @@ "patchedDependencies": { "react-native@0.85.3": "patches/react-native@0.85.3.patch", }, - "overrides": { - "react-native-nitro-modules": "0.37.0-beta.1", - }, "packages": { "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], diff --git a/package.json b/package.json index 4a11660b6d..ec25425ab4 100644 --- a/package.json +++ b/package.json @@ -125,9 +125,6 @@ } } }, - "overrides": { - "react-native-nitro-modules": "0.37.0-beta.1" - }, "patchedDependencies": { "react-native@0.85.3": "patches/react-native@0.85.3.patch" }, From 343fcdce3be116c6d012a4e338f39b79a6cf9d88 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Thu, 20 Aug 2026 19:56:03 +0200 Subject: [PATCH 5/5] feat: Upgrade Nitro to 0.37.0 and Nitro Image to 0.15.2 Nitro 0.37.0 and nitrogen 0.37.0 are now stable; nitrogen's generated output is identical to 0.37.0-beta.1, so no spec changes were needed. Nitro Image 0.15.2 is regenerated with nitrogen 0.37.0 (no more deprecated `CachedProp`) and marks its `react-native-nitro-modules` peer dependency as optional. --- apps/simple-camera/ios/Podfile.lock | 8 ++--- apps/simple-camera/package.json | 4 +-- bun.lock | 36 +++++++++---------- .../package.json | 6 ++-- .../package.json | 4 +-- .../package.json | 4 +-- .../package.json | 2 +- .../package.json | 4 +-- .../react-native-vision-camera/package.json | 6 ++-- 9 files changed, 37 insertions(+), 37 deletions(-) diff --git a/apps/simple-camera/ios/Podfile.lock b/apps/simple-camera/ios/Podfile.lock index 3df1cef3a4..63e9f1ed57 100644 --- a/apps/simple-camera/ios/Podfile.lock +++ b/apps/simple-camera/ios/Podfile.lock @@ -70,7 +70,7 @@ PODS: - nanopb/encode (= 3.30910.0) - nanopb/decode (3.30910.0) - nanopb/encode (3.30910.0) - - NitroImage (0.15.1): + - NitroImage (0.15.2): - hermes-engine - NitroModules - RCTRequired @@ -94,7 +94,7 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - NitroModules (0.37.0-beta.1): + - NitroModules (0.37.0): - hermes-engine - RCTRequired - RCTTypeSafety @@ -2787,8 +2787,8 @@ SPEC CHECKSUMS: MLKitCommon: 47d47b50a031d00db62f1b0efe5a1d8b09a3b2e6 MLKitVision: 39a5a812db83c4a0794445088e567f3631c11961 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 - NitroImage: 2f592086cbdecbbaa1c10dd97e0cdd43b1bb0817 - NitroModules: 7b1bbaed4743fc48e3dfc50d1f8aaf58a8421c31 + NitroImage: 5daf897d2f37ed419186278d6b0fcdd8aab313b0 + NitroModules: cda827b31eb05c1bfcc0e2bbd9b647a69c6c314f PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 RCTDeprecation: a4c521821fab57cbb125b36effe84d897d0dfa12 RCTRequired: 9f3a7e5645d4bc3f551593de7550bb66ab6e42bc diff --git a/apps/simple-camera/package.json b/apps/simple-camera/package.json index 01c900d395..c10d75e32e 100644 --- a/apps/simple-camera/package.json +++ b/apps/simple-camera/package.json @@ -25,8 +25,8 @@ "react": "19.2.3", "react-native": "0.85.3", "react-native-gesture-handler": "^3.0.0", - "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-image": "0.15.2", + "react-native-nitro-modules": "0.37.0", "react-native-reanimated": "4.4.0", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2", diff --git a/bun.lock b/bun.lock index d401c5e688..b9a390d059 100644 --- a/bun.lock +++ b/bun.lock @@ -32,8 +32,8 @@ "react": "19.2.3", "react-native": "0.85.3", "react-native-gesture-handler": "^3.0.0", - "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-image": "0.15.2", + "react-native-nitro-modules": "0.37.0", "react-native-reanimated": "4.4.0", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2", @@ -106,11 +106,11 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-image": "0.15.2", + "react-native-nitro-modules": "0.37.0", "typescript": "6.0.3", }, "peerDependencies": { @@ -128,11 +128,11 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-image": "0.15.2", + "react-native-nitro-modules": "0.37.0", "react-native-vision-camera": "*", "typescript": "6.0.3", }, @@ -152,10 +152,10 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "react-native-vision-camera": "*", "typescript": "6.0.3", }, @@ -174,10 +174,10 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "react-native-vision-camera": "*", "typescript": "6.0.3", }, @@ -199,7 +199,7 @@ "@types/react": "19.2.15", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "react-native-reanimated": "4.4.0", "react-native-vision-camera": "*", "react-native-vision-camera-worklets": "*", @@ -221,10 +221,10 @@ "version": "5.2.2", "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "react-native-vision-camera": "*", "react-native-worklets": "0.9.1", "typescript": "6.0.3", @@ -2220,7 +2220,7 @@ "next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="], - "nitrogen": ["nitrogen@0.37.0-beta.1", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.37.0-beta.1", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-DMe2KA168ZWY9pkn1BFhTPjg2yfcVF4e/Fboj9lQElK3wBMYzDECIgcgHvfeoxo+z9ZBRVV4PR4p8c57PiOccQ=="], + "nitrogen": ["nitrogen@0.37.0", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.37.0", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-lrWmvctRyazMLU6y4ThUl6q129wMCOvmQfdtqCeZShgmmh3Nbplm9dSJLN2OZSBnDWA5k+T2P8aiNyjr1yiJAg=="], "nocache": ["nocache@3.0.4", "", {}, "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw=="], @@ -2404,9 +2404,9 @@ "react-native-is-edge-to-edge": ["react-native-is-edge-to-edge@1.3.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-NIXU/iT5+ORyCc7p0z2nnlkouYKX425vuU1OEm6bMMtWWR9yvb+Xg5AZmImTKoF9abxCPqrKC3rOZsKzUYgYZA=="], - "react-native-nitro-image": ["react-native-nitro-image@0.15.1", "", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-nitro-modules": "*" } }, "sha512-slrImfUgasAdzylTiNWuTkawE0R4t7LGh+7N2VFa/D9+SxlQbkKYp1J6hA3XkkEnTnUCKaea39ZVg+1xx665MQ=="], + "react-native-nitro-image": ["react-native-nitro-image@0.15.2", "", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-nitro-modules": "*" }, "optionalPeers": ["react-native-nitro-modules"] }, "sha512-WiaGnORmfNIIqtRJW76TWYNet1YZx1MWDlSOxd0jfcIBN4KjkVVMDVpvO01eCfpxKVG0ez9nA2iLQkPVlGFj+A=="], - "react-native-nitro-modules": ["react-native-nitro-modules@0.37.0-beta.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-PQfd8YVgK+sDrcw+m8EZ9jBD1bgmoHhofDO882EGDaRlKoCAUy1yvMP16esouk8CnMEBGdKToWW2EBOu13JUBA=="], + "react-native-nitro-modules": ["react-native-nitro-modules@0.37.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-ULS2CBZcdwGw5d4Y35EV/tbCOsNsQOnQ9LC9CehMhDNm5c90lwF/LxRamzKuFpjI547G7teTQgD0peqYSGnP9g=="], "react-native-reanimated": ["react-native-reanimated@4.4.0", "", { "dependencies": { "react-native-is-edge-to-edge": "^1.3.1", "semver": "^7.7.3" }, "peerDependencies": { "react": "*", "react-native": "0.83 - 0.86", "react-native-worklets": "0.9.x" } }, "sha512-0XbC1SpF3JZOz5QfmTEx3vt8VkmkTlS05CBIOKEg5q5ZSNlGtlacntlhj5CrfZlN1ciHAeoliJouTC2cLGKbDA=="], diff --git a/packages/react-native-vision-camera-barcode-scanner/package.json b/packages/react-native-vision-camera-barcode-scanner/package.json index d272843f39..6f2000c686 100644 --- a/packages/react-native-vision-camera-barcode-scanner/package.json +++ b/packages/react-native-vision-camera-barcode-scanner/package.json @@ -66,11 +66,11 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-image": "0.15.2", + "react-native-nitro-modules": "0.37.0", "react-native-vision-camera": "*", "typescript": "6.0.3" }, diff --git a/packages/react-native-vision-camera-location/package.json b/packages/react-native-vision-camera-location/package.json index bb8f3f65c0..42ee31490e 100644 --- a/packages/react-native-vision-camera-location/package.json +++ b/packages/react-native-vision-camera-location/package.json @@ -65,10 +65,10 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "react-native-vision-camera": "*", "typescript": "6.0.3" }, diff --git a/packages/react-native-vision-camera-resizer/package.json b/packages/react-native-vision-camera-resizer/package.json index 1d1da27df6..e077328f1a 100644 --- a/packages/react-native-vision-camera-resizer/package.json +++ b/packages/react-native-vision-camera-resizer/package.json @@ -70,10 +70,10 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "react-native-vision-camera": "*", "typescript": "6.0.3" }, diff --git a/packages/react-native-vision-camera-skia/package.json b/packages/react-native-vision-camera-skia/package.json index 5d952b3eb7..61de147577 100644 --- a/packages/react-native-vision-camera-skia/package.json +++ b/packages/react-native-vision-camera-skia/package.json @@ -56,7 +56,7 @@ "@types/react": "19.2.15", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "react-native-reanimated": "4.4.0", "react-native-worklets": "0.9.1", "react-native-vision-camera": "*", diff --git a/packages/react-native-vision-camera-worklets/package.json b/packages/react-native-vision-camera-worklets/package.json index 532f47ca67..7d3f2e8d48 100644 --- a/packages/react-native-vision-camera-worklets/package.json +++ b/packages/react-native-vision-camera-worklets/package.json @@ -66,10 +66,10 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "react-native-worklets": "0.9.1", "react-native-vision-camera": "*", "typescript": "6.0.3" diff --git a/packages/react-native-vision-camera/package.json b/packages/react-native-vision-camera/package.json index bd529336a3..e0832ce100 100644 --- a/packages/react-native-vision-camera/package.json +++ b/packages/react-native-vision-camera/package.json @@ -70,11 +70,11 @@ }, "devDependencies": { "@types/react": "19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-image": "0.15.1", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-image": "0.15.2", + "react-native-nitro-modules": "0.37.0", "typescript": "6.0.3" }, "peerDependencies": {