Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 25 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 @@ -89,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 @@ -227,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
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)")
}
}
79 changes: 79 additions & 0 deletions nitrogen/generated/android/c++/JFunc_void_RiveError.hpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 29 additions & 1 deletion nitrogen/generated/android/c++/JHybridRiveViewSpec.cpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions nitrogen/generated/android/c++/JHybridRiveViewSpec.hpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading