feat!: experimental Rive runtime backend (iOS + Android)#134
feat!: experimental Rive runtime backend (iOS + Android)#134
Conversation
95816cf to
4fe9e12
Compare
8485f9f to
9b4acd8
Compare
There was a problem hiding this comment.
Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit
ktlint
🚫 [ktlint] standard:multiline-if-else reported by reviewdog 🐶
Missing { ... }
🚫 [ktlint] standard:chain-method-continuation reported by reviewdog 🐶
Expected newline before '.'
🚫 [ktlint] standard:chain-method-continuation reported by reviewdog 🐶
Expected newline before '.'
🚫 [ktlint] standard:try-catch-finally-spacing reported by reviewdog 🐶
Expected a newline after '{'
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline after '{'
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline before '}'
🚫 [ktlint] standard:try-catch-finally-spacing reported by reviewdog 🐶
Expected a newline before '}'
🚫 [ktlint] standard:try-catch-finally-spacing reported by reviewdog 🐶
Expected a newline after '{'
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline after '{'
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline before '}'
🚫 [ktlint] standard:try-catch-finally-spacing reported by reviewdog 🐶
Expected a newline before '}'
🚫 [ktlint] standard:no-unused-imports reported by reviewdog 🐶
Unused import
🚫 [ktlint] standard:string-template reported by reviewdog 🐶
Redundant curly braces
🚫 [ktlint] standard:if-else-wrapping reported by reviewdog 🐶
Expected a newline
🚫 [ktlint] standard:multiline-if-else reported by reviewdog 🐶
Missing { ... }
🚫 [ktlint] standard:if-else-wrapping reported by reviewdog 🐶
Expected a newline
🚫 [ktlint] standard:multiline-if-else reported by reviewdog 🐶
Missing { ... }
🚫 [ktlint] standard:chain-method-continuation reported by reviewdog 🐶
Expected newline before '.'
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Argument should be on a separate line (unless all arguments can fit a single line)
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Argument should be on a separate line (unless all arguments can fit a single line)
🚫 [ktlint] standard:string-template reported by reviewdog 🐶
Redundant curly braces
🚫 [ktlint] standard:max-line-length reported by reviewdog 🐶
Exceeded max line length (140)
🚫 [ktlint] standard:string-template reported by reviewdog 🐶
Redundant curly braces
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Missing newline before ")"
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline after '{'
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline after ';'
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline before '}'
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline after '{'
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline after ';'
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline before '}'
🚫 [ktlint] standard:if-else-wrapping reported by reviewdog 🐶
A single line if-statement should be kept simple. The 'THEN' may not be wrapped in a block.
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline after '{'
🚫 [ktlint] standard:string-template reported by reviewdog 🐶
Redundant curly braces
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline after ';'
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline before '}'
🚫 [ktlint] standard:chain-method-continuation reported by reviewdog 🐶
Expected newline before '.'
🚫 [ktlint] standard:chain-method-continuation reported by reviewdog 🐶
Expected newline before '.'
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Argument should be on a separate line (unless all arguments can fit a single line)
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Argument should be on a separate line (unless all arguments can fit a single line)
🚫 [ktlint] standard:max-line-length reported by reviewdog 🐶
Exceeded max line length (140)
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Missing newline before ")"
🚫 [ktlint] standard:function-naming reported by reviewdog 🐶
Function name should start with a lowercase letter (except factory methods) and use camel case
🚫 [ktlint] standard:chain-method-continuation reported by reviewdog 🐶
Expected newline before '.'
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Argument should be on a separate line (unless all arguments can fit a single line)
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Argument should be on a separate line (unless all arguments can fit a single line)
🚫 [ktlint] standard:max-line-length reported by reviewdog 🐶
Exceeded max line length (140)
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Missing newline before ")"
dd06b3a to
a5855c9
Compare
There was a problem hiding this comment.
Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit
ktlint
🚫 [ktlint] standard:if-else-wrapping reported by reviewdog 🐶
A single line if-statement should be kept simple. The 'THEN' may not be wrapped in a block.
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline after '{'
🚫 [ktlint] standard:string-template reported by reviewdog 🐶
Redundant curly braces
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline after ';'
🚫 [ktlint] standard:statement-wrapping reported by reviewdog 🐶
Missing newline before '}'
🚫 [ktlint] standard:chain-method-continuation reported by reviewdog 🐶
Expected newline before '.'
🚫 [ktlint] standard:chain-method-continuation reported by reviewdog 🐶
Expected newline before '.'
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Argument should be on a separate line (unless all arguments can fit a single line)
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Argument should be on a separate line (unless all arguments can fit a single line)
🚫 [ktlint] standard:max-line-length reported by reviewdog 🐶
Exceeded max line length (140)
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Missing newline before ")"
🚫 [ktlint] standard:function-naming reported by reviewdog 🐶
Function name should start with a lowercase letter (except factory methods) and use camel case
🚫 [ktlint] standard:chain-method-continuation reported by reviewdog 🐶
Expected newline before '.'
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Argument should be on a separate line (unless all arguments can fit a single line)
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Argument should be on a separate line (unless all arguments can fit a single line)
🚫 [ktlint] standard:max-line-length reported by reviewdog 🐶
Exceeded max line length (140)
🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Missing newline before ")"
8134a07 to
ec12673
Compare
91e2fb6 to
cfb2ff6
Compare
cfb2ff6 to
44681b5
Compare
f1b851e to
aa2fdf0
Compare
35c6fea to
4f1ab3f
Compare
4e0c53a to
be6d334
Compare
164180e to
7116ac7
Compare
dcdde5e to
0a3d09c
Compare
…E, check WebP explicitly
…ReactNativeView
…allable methods Nitro calls hybrid methods on the JS thread, not the main thread. MainActor.assumeIsolated crashes at runtime when not on main.
…in experimental backend
…nings (#201) ## Summary - Adds `RiveLog` — a general-purpose logging system that surfaces native logs to JS via a configurable handler - Default handler uses `console.error/warn/log` so logs show in the RN console out of the box - On both platforms, hooks into the Rive SDK's pluggable `RiveLog.Logger` to unify C++ runtime logs (state machine, artboard, command queue diagnostics) through the JS handler - Adds `DeprecationWarning` utility that emits once-per-session warnings when deprecated blocking methods are called ## Test plan - [ ] Build exerciser on iOS + Android - [ ] Call a deprecated method (e.g. `riveFile.viewModelByName(...)`) — verify warning in RN console - [ ] Call same method again — verify no duplicate warning - [ ] `RiveLog.setHandler(() => {})` — verify all logs suppressed - [ ] `RiveLog.resetHandler()` — verify back to default console output - [ ] Verify `onError` prop on RiveView still works independently
de3b4b3 to
fb86bf0
Compare
… backend RiveUIView creates its MTKView lazily during the first layout pass. Setting rive.fit immediately after creating the view had no effect because the drawable didn't exist yet. Store the desired fit as pendingFit and apply it in layoutSubviews once the MTKView is present.
ef919d1 to
24bf675
Compare
Add `RiveLog.setLogLevel(level)` to filter log output by severity.
Levels: `debug`, `info`, `warn`, `error`. Default is `warn`.
## Test plan
- `RiveLog.setLogLevel('error')` suppresses warn/info/debug logs
- `RiveLog.setLogLevel('debug')` shows all logs
Bump RiveRuntime from 6.19.0 to 6.19.1. Remove `@_spi(RiveExperimental)` imports — no longer needed with this version.
The experimental factory already has `var backend: String {
"experimental" }`. This adds the matching property to the legacy side so
`RiveFileFactory.backend` works for both backends.
`Int32(value)` traps when ARGB color values exceed `Int32.max` (e.g. `0xFF0000FF` = opaque blue). Uses `Int64` + `truncatingIfNeeded` for safe conversion.
- Pass `fit:` directly in `Rive()` constructor instead of setting it post-creation. Removes the `layoutSubviews`/`pendingFit` workaround since rive-ios 6.19.1 handles this (rive-ios#443) - Warn when `updateReferencedAssets` is called on experimental backend (not supported — concurrency API can't update already-bound artboard assets) - Switch asset registration from parallel `TaskGroup` to sequential to ensure command queue ordering - Add debug logging to `ExperimentalAssetLoader` - Add explicit `type` fields to OutOfBandAssets example - Add `expo-font` plugin for `kanit_regular.ttf` in expo examples ## Test plan - QuickStart + DataBindingArtboards render correctly with `Fit.Layout` on first mount - Out-of-Band Assets example loads initial assets correctly - `updateReferencedAssets` logs a warning instead of silently failing
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 88 out of 183 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add addInstanceAsync, addInstanceAtAsync, removeInstanceAsync, removeInstanceAtAsync, swapAsync. Deprecate sync versions that return before knowing if the operation succeeded.
The library module already depends on the correct version via package.json runtimeVersions. The pin caused version conflicts.
8dcd161 to
e753682
Compare
… app Debug activities that import app.rive.* directly, causing the example app to need an explicit rive-android dependency. Easy to recreate when needed for native SDK debugging.
e753682 to
6af4fdd
Compare
Adds a new native backend using Rive's experimental runtime APIs on both iOS and Android. The new backend is async-native — all ViewModel operations go through a CommandQueue, eliminating the need for
blockingAsync/runBlockingwrappers on the non-deprecated API surface.The experimental backend is now the default. Legacy backend files are moved to
ios/legacy/andandroid/src/legacy/(identical to main exceptgetEnums()stub andbackendproperty). New implementations live inios/new/andandroid/src/new/. CI runs tests on both backends.Release-please configured for beta prereleases (
0.5.0-beta, published as@next).Opting into the legacy backend
Without the flag, the experimental backend is used.
What works
viewModelAsync)RiveUIViewon iOS, custom implementation on Android)play()/pause()(iOS: togglesisPaused; Android: fully implemented)getEnums()for introspectiongetPropertyCountAsync/getInstanceCountAsyncKnown limitations
Android
defaultArtboardViewModeldoesn't expose the ViewModel name — pending rive-android#443. This causesmodelName/propertyCount/instanceCountto throw andviewModelAsyncpath validation to be skipped on those instances.replaceViewModelis a no-op (not yet implemented)iOS
reset()only pauses — doesn't actually reset the state machineBoth platforms