Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions android/src/main/java/com/margelo/nitro/rive/HybridRiveView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.rive.RiveReactNativeView
import com.rive.ViewConfiguration
import app.rive.runtime.kotlin.core.Fit as RiveFit
import app.rive.runtime.kotlin.core.Alignment as RiveAlignment
import app.rive.runtime.kotlin.core.errors.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

Expand Down Expand Up @@ -46,6 +47,10 @@ object DefaultConfiguration {
@Keep
@DoNotStrip
class HybridRiveView(val context: ThemedReactContext) : HybridRiveViewSpec() {
companion object {
private const val TAG = "HybridRiveView"
}

//region State
override val view: RiveReactNativeView = RiveReactNativeView(context)
private var needsReload = false
Expand Down Expand Up @@ -85,6 +90,7 @@ class HybridRiveView(val context: ThemedReactContext) : HybridRiveViewSpec() {
dataBindingChanged = true
}
}
override var onError: (error: RiveError) -> Unit = {}
Comment thread
mfazekas marked this conversation as resolved.
//endregion

//region View Methods
Expand Down Expand Up @@ -223,12 +229,33 @@ class HybridRiveView(val context: ThemedReactContext) : HybridRiveViewSpec() {
}
}

private fun detectErrorType(exception: Exception): Pair<RiveErrorType, String> {
val message = exception.message ?: exception.toString()
val type = when (exception) {
is ArtboardException -> RiveErrorType.INCORRECTARTBOARDNAME
is StateMachineException -> RiveErrorType.INCORRECTSTATEMACHINENAME
is AnimationException -> RiveErrorType.UNKNOWN
is MalformedFileException -> RiveErrorType.MALFORMEDFILE
is StateMachineInputException -> RiveErrorType.INCORRECTSTATEMACHINEINPUTNAME
is TextValueRunException -> RiveErrorType.UNKNOWN
is ViewModelException -> RiveErrorType.VIEWMODELINSTANCENOTFOUND
else -> RiveErrorType.UNKNOWN
}
return Pair(type, message)
}

fun logged(tag: String, note: String? = null, fn: () -> Unit) {
try {
fn()
} catch (e: Exception) {
// TODO add onError callback
Log.e("[RIVE]", "$tag ${note ?: ""} $e")
val (errorType, errorDescription) = detectErrorType(e)
val noteString = note?.let { " $it" } ?: ""
val errorMessage = "[RIVE] $tag$noteString $errorDescription"
val riveError = RiveError(
type = errorType,
message = errorMessage
)
onError(riveError)
}
}
Comment thread
mfazekas marked this conversation as resolved.
//endregion
Expand Down
60 changes: 30 additions & 30 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1357,32 +1357,6 @@ PODS:
- React-jsiexecutor
- React-RCTFBReactNativeSpec
- ReactCommon/turbomodule/core
- react-native-rive (0.1.0):
- DoubleConversion
- glog
- hermes-engine
- NitroModules
- RCT-Folly (= 2024.11.18.00)
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-hermes
- React-ImageManager
- React-jsi
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- RiveRuntime (= 6.12.0)
- Yoga
- react-native-safe-area-context (5.6.2):
- DoubleConversion
- glog
Expand Down Expand Up @@ -1713,6 +1687,32 @@ PODS:
- React-debug
- React-hermes
- React-jsi (= 0.79.2)
- react_native_rive (0.1.0):
- DoubleConversion
- glog
- hermes-engine
- NitroModules
- RCT-Folly (= 2024.11.18.00)
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-hermes
- React-ImageManager
- React-jsi
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- RiveRuntime (= 6.12.0)
- Yoga
- ReactAppDependencyProvider (0.79.2):
- ReactCodegen
- ReactCodegen (0.79.2):
Expand Down Expand Up @@ -1874,7 +1874,6 @@ DEPENDENCIES:
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- React-Mapbuffer (from `../node_modules/react-native/ReactCommon`)
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
- react-native-rive (from `../..`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
- React-oscompat (from `../node_modules/react-native/ReactCommon/oscompat`)
Expand Down Expand Up @@ -1904,6 +1903,7 @@ DEPENDENCIES:
- React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`)
- React-timing (from `../node_modules/react-native/ReactCommon/react/timing`)
- React-utils (from `../node_modules/react-native/ReactCommon/react/utils`)
- react_native_rive (from `../..`)
- ReactAppDependencyProvider (from `build/generated/ios`)
- ReactCodegen (from `build/generated/ios`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
Expand Down Expand Up @@ -1996,8 +1996,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon"
React-microtasksnativemodule:
:path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
react-native-rive:
:path: "../.."
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
React-NativeModulesApple:
Expand Down Expand Up @@ -2056,6 +2054,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/react/timing"
React-utils:
:path: "../node_modules/react-native/ReactCommon/react/utils"
react_native_rive:
:path: "../.."
ReactAppDependencyProvider:
:path: build/generated/ios
ReactCodegen:
Expand Down Expand Up @@ -2109,7 +2109,6 @@ SPEC CHECKSUMS:
React-logger: 368570a253f00879a1e4fea24ed4047e72e7bbf3
React-Mapbuffer: c04fcda1c6281fc0a6824c7dcc1633dd217ac1ec
React-microtasksnativemodule: ca2804a25fdcefffa0aa942aa23ab53b99614a34
react-native-rive: 7e008c7a01eba3d71d98813f77b4221699290990
react-native-safe-area-context: bc59472155ffb889a1ffe16c19a04c0cd451562b
React-NativeModulesApple: 452b86b29fae99ed0a4015dca3ad9cd222f88abf
React-oscompat: ef5df1c734f19b8003e149317d041b8ce1f7d29c
Expand Down Expand Up @@ -2139,6 +2138,7 @@ SPEC CHECKSUMS:
React-runtimescheduler: e917ab17ae08c204af1ebf8f669b7e411b0220c8
React-timing: a90f4654cbda9c628614f9bee68967f1768bd6a5
React-utils: 51c4e71608b8133fecc9a15801d244ae7bdf3758
react_native_rive: a6e6aa9ef2826c95aeaa7e40619a04f3887c8ac7
ReactAppDependencyProvider: d5dcc564f129632276bd3184e60f053fcd574d6b
ReactCodegen: fda99a79c866370190e162083a35602fdc314e5d
ReactCommon: 4d0da92a5eb8da86c08e3ec34bd23ab439fb2461
Expand Down
51 changes: 50 additions & 1 deletion ios/HybridRiveView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class HybridRiveView: HybridRiveViewSpec {
var alignment: Alignment?
var fit: Fit?
var layoutScaleFactor: Double?
var onError: (RiveError) -> Void = { _ in }
Comment thread
mfazekas marked this conversation as resolved.

func awaitViewReady() throws -> Promise<Bool> {
return Promise.async { [self] in
Expand Down Expand Up @@ -141,7 +142,7 @@ class HybridRiveView: HybridRiveViewSpec {
)

let riveView = try getRiveView()
riveView.configure(
try riveView.configure(
config, dataBindingChanged: dataBindingChanged, reload: needsReload,
initialUpdate: initialUpdate)
needsReload = false
Expand Down Expand Up @@ -187,3 +188,51 @@ class HybridRiveView: HybridRiveViewSpec {
}
}
}

extension HybridRiveView {
func logged(tag: String, note: String? = nil, _ fn: () throws -> Void) {
do {
return try fn()
} catch (let e) {
let (errorType, errorDescription) = detectErrorType(e)
let noteString = note.map { " \($0)" } ?? ""
let errorMessage = "[RIVE] \(tag)\(noteString) \(errorDescription)"

let riveError = RiveError(
message: errorMessage,
type: errorType
)
onError(riveError)
}
}
Comment thread
mfazekas marked this conversation as resolved.

private func detectErrorType(_ error: Error) -> (RiveErrorType, String) {
switch error {
case NitroRiveError.instanceNotFound(let message):
return (.viewmodelinstancenotfound, message)
case NitroRiveError.fileNotFound(let message):
return (.filenotfound, message)
default:
break
}

let nsError = error as NSError
let message = nsError.localizedDescription

// RiveErrorCode from RiveRuntime
switch nsError.code {
case RiveErrorCode.noArtboardFound.rawValue:
return (.incorrectartboardname, message)
case RiveErrorCode.noStateMachineFound.rawValue:
return (.incorrectstatemachinename, message)
case RiveErrorCode.noAnimationFound.rawValue:
return (.unknown, message)
case RiveErrorCode.malformedFile.rawValue:
return (.malformedfile, message)
case RiveErrorCode.noStateMachineInputFound.rawValue:
return (.incorrectstatemachineinputname, message)
default:
return (.unknown, message)
}
}
}
12 changes: 4 additions & 8 deletions ios/ReferencedAssetLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,14 @@ func createIncorrectRiveURL(_ url: String) -> NSError {
])
}

func createAssetFileError(_ assetName: String) -> NSError {
return NSError(
domain: RiveErrorDomain, code: 801,
userInfo: [
NSLocalizedDescriptionKey: "Could not load Rive asset: \(assetName)", "name": "FileNotFound",
])
func createAssetFileError(_ assetName: String) -> NitroRiveError {
return NitroRiveError.fileNotFound(message: "Could not load Rive asset: \(assetName)")
}

final class ReferencedAssetLoader {
private func handleRiveError(error: NSError) {
private func handleRiveError(error: Error) {
// TODO allow user to specify onError callback
RCTLogError(error.localizedDescription)
RCTLogError("\(error)")
}

private func handleInvalidUrlError(url: String) {
Expand Down
13 changes: 9 additions & 4 deletions ios/RiveReactNativeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ struct ViewConfiguration {
let bindData: BindData
}

enum NitroRiveError: Error {
case instanceNotFound(message: String)
case fileNotFound(message: String)
}

class RiveReactNativeView: UIView, RiveStateMachineDelegate {
// MARK: Internal Properties
private var riveView: RiveView?
Expand All @@ -50,7 +55,7 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate {
return true
}

func configure(_ config: ViewConfiguration, dataBindingChanged: Bool = false, reload: Bool = false, initialUpdate: Bool = false) {
func configure(_ config: ViewConfiguration, dataBindingChanged: Bool = false, reload: Bool = false, initialUpdate: Bool = false) throws {
if reload {
cleanup()
let model = RiveModel(riveFile: config.riveFile)
Expand All @@ -75,7 +80,7 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate {
}

if dataBindingChanged || initialUpdate {
applyDataBinding(config.bindData)
try applyDataBinding(config.bindData)
}
}

Expand All @@ -87,7 +92,7 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate {
return baseViewModel?.riveModel?.stateMachine?.viewModelInstance
}

func applyDataBinding(_ bindData: BindData) {
func applyDataBinding(_ bindData: BindData) throws {
let stateMachine = baseViewModel?.riveModel?.stateMachine
let artboard = baseViewModel?.riveModel?.artboard

Expand All @@ -106,7 +111,7 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate {
let viewModel = riveFile.defaultViewModel(for: artboard),
let instance = viewModel.createInstance(fromName: name)
else {
return
throw NitroRiveError.instanceNotFound(message: "\(name) instance not found")
}
stateMachine?.bind(viewModelInstance: instance)
// this should be added if we support only playing artboards on their own - https://github.com/rive-app/rive-nitro-react-native/pull/23#discussion_r2534698281
Expand Down
9 changes: 0 additions & 9 deletions ios/Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,3 @@ final class SendableRef<T: Sendable>: @unchecked Sendable {
self.value = value
}
}

/// Executes a closure, logging any thrown error with an optional note and tag using RCTLogError.
func logged(tag: String, note: String? = nil, _ fn: () throws -> Void) {
do {
return try fn()
} catch (let e) {
RCTLogError("[RIVE] \(tag) \(note ?? "") \(e)")
}
}
2 changes: 1 addition & 1 deletion nitro.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://nitro.margelo.com/nitro.schema.json",
"cxxNamespace": ["rive"],
"ios": {
"iosModuleName": "Rive"
"iosModuleName": "react_native_rive"
},
"android": {
"androidNamespace": ["rive"],
Expand Down
Loading
Loading