@rive-app/react-native 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -77,6 +77,7 @@ class RiveReactNativeView(context: ThemedReactContext) : FrameLayout(context) {
77
77
  private var eventListeners: MutableList<RiveFileController.RiveEventListener> = mutableListOf()
78
78
  private val viewReadyDeferred = CompletableDeferred<Boolean>()
79
79
  private var _activeStateMachineName: String? = null
80
+ private var _pendingBindData: BindData? = null
80
81
  private var willDispose = false
81
82
 
82
83
  init {
@@ -119,8 +120,8 @@ class RiveReactNativeView(context: ThemedReactContext) : FrameLayout(context) {
119
120
  riveAnimationView?.layoutScaleFactor = config.layoutScaleFactor
120
121
  }
121
122
 
122
- if (dataBindingChanged || initialUpdate) {
123
- applyDataBinding(config.bindData)
123
+ if (dataBindingChanged || initialUpdate || reload) {
124
+ applyDataBinding(config.bindData, config.autoPlay)
124
125
  }
125
126
 
126
127
  viewReadyDeferred.complete(true)
@@ -142,50 +143,36 @@ class RiveReactNativeView(context: ThemedReactContext) : FrameLayout(context) {
142
143
  }
143
144
  }
144
145
 
145
- fun applyDataBinding(bindData: BindData) {
146
+ fun applyDataBinding(bindData: BindData, autoPlay: Boolean) {
146
147
  val stateMachines = riveAnimationView?.controller?.stateMachines
147
- if (stateMachines.isNullOrEmpty()) return
148
+ if (stateMachines.isNullOrEmpty()) {
149
+ _pendingBindData = bindData
150
+ return
151
+ }
148
152
 
149
- val stateMachine = stateMachines.first()
153
+ bindToStateMachine(bindData)
150
154
 
151
- when (bindData) {
152
- is BindData.None -> {
153
- stateMachine.viewModelInstance = null
154
- }
155
- is BindData.Auto -> {
156
- val artboard = riveAnimationView?.controller?.activeArtboard
157
- val file = riveAnimationView?.controller?.file
158
- if (artboard != null && file != null) {
159
- try {
160
- file.defaultViewModelForArtboard(artboard)
161
- } catch (e: ViewModelException) {
162
- null
163
- }?.let {
164
- val instance = it.createDefaultInstance()
165
- stateMachine.viewModelInstance = instance
166
- }
167
- }
168
- }
169
- is BindData.Instance -> {
170
- stateMachine.viewModelInstance = bindData.instance
171
- }
172
- is BindData.ByName -> {
173
- val artboard = riveAnimationView?.controller?.activeArtboard
174
- val file = riveAnimationView?.controller?.file
175
- if (artboard != null && file != null) {
176
- val viewModel = file.defaultViewModelForArtboard(artboard)
177
- val instance = viewModel.createInstanceFromName(bindData.name)
178
- stateMachine.viewModelInstance = instance
179
- }
155
+ if (autoPlay) {
156
+ stateMachines.first().name.let { smName ->
157
+ riveAnimationView?.play(smName, isStateMachine = true)
180
158
  }
181
159
  }
160
+ }
182
161
 
183
- stateMachine.name.let { smName ->
184
- riveAnimationView?.play(smName, isStateMachine = true)
162
+ fun play() {
163
+ if (_activeStateMachineName == null) {
164
+ _activeStateMachineName = getSafeStateMachineName()
185
165
  }
166
+ riveAnimationView?.play()
167
+ applyPendingBindData()
186
168
  }
187
169
 
188
- fun play() = riveAnimationView?.play()
170
+ private fun applyPendingBindData() {
171
+ _pendingBindData?.let { bindData ->
172
+ _pendingBindData = null
173
+ bindToStateMachine(bindData)
174
+ }
175
+ }
189
176
 
190
177
  fun pause() = riveAnimationView?.pause()
191
178
 
@@ -324,6 +311,44 @@ class RiveReactNativeView(context: ThemedReactContext) : FrameLayout(context) {
324
311
 
325
312
  //region Internal
326
313
 
314
+ private fun bindToStateMachine(bindData: BindData) {
315
+ val stateMachines = riveAnimationView?.controller?.stateMachines
316
+ if (stateMachines.isNullOrEmpty()) return
317
+ val stateMachine = stateMachines.first()
318
+
319
+ when (bindData) {
320
+ is BindData.None -> {
321
+ stateMachine.viewModelInstance = null
322
+ }
323
+ is BindData.Auto -> {
324
+ val artboard = riveAnimationView?.controller?.activeArtboard
325
+ val file = riveAnimationView?.controller?.file
326
+ if (artboard != null && file != null) {
327
+ try {
328
+ file.defaultViewModelForArtboard(artboard)
329
+ } catch (e: ViewModelException) {
330
+ null
331
+ }?.let {
332
+ val instance = it.createDefaultInstance()
333
+ stateMachine.viewModelInstance = instance
334
+ }
335
+ }
336
+ }
337
+ is BindData.Instance -> {
338
+ stateMachine.viewModelInstance = bindData.instance
339
+ }
340
+ is BindData.ByName -> {
341
+ val artboard = riveAnimationView?.controller?.activeArtboard
342
+ val file = riveAnimationView?.controller?.file
343
+ if (artboard != null && file != null) {
344
+ val viewModel = file.defaultViewModelForArtboard(artboard)
345
+ val instance = viewModel.createInstanceFromName(bindData.name)
346
+ stateMachine.viewModelInstance = instance
347
+ }
348
+ }
349
+ }
350
+ }
351
+
327
352
  private fun convertEventProperties(properties: Map<String, Any>?): Map<String, EventPropertiesOutput>? {
328
353
  if (properties == null) return null
329
354
 
@@ -363,24 +388,17 @@ class RiveReactNativeView(context: ThemedReactContext) : FrameLayout(context) {
363
388
  }
364
389
  }
365
390
 
366
- // TODO: this is throwing when autoplay is false
367
- // TODO: This is a temporary solution to get the state machine name as Android supports
391
+ // This is a temporary solution to get the state machine name as Android supports
368
392
  // playing multiple state machines, but in React Native we only allow playing one.
369
393
  /**
370
- * Gets the name of the active state machine.
371
- * @throws Error if the state machine name could not be found
372
- * @return The name of the state machine that "is playing" / "will be played"
394
+ * Gets the name of the active state machine, or null if no state machines are loaded yet
395
+ * (e.g. when autoPlay is false and the state machine hasn't been started).
396
+ * @return The name of the state machine, or null
373
397
  */
374
- private fun getSafeStateMachineName(): String {
375
- try {
376
- val stateMachines = riveAnimationView?.controller?.stateMachines
377
- if (stateMachines.isNullOrEmpty()) {
378
- throw Exception("No state machines found in the Rive file")
379
- }
380
- return stateMachines.first().name
381
- } catch (e: Exception) {
382
- throw Error(e.message)
383
- }
398
+ private fun getSafeStateMachineName(): String? {
399
+ val stateMachines = riveAnimationView?.controller?.stateMachines
400
+ if (stateMachines.isNullOrEmpty()) return null
401
+ return stateMachines.first().name
384
402
  }
385
403
 
386
404
  /**
@@ -81,8 +81,8 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate {
81
81
  viewReadyContinuation = nil
82
82
  }
83
83
 
84
- if dataBindingChanged || initialUpdate {
85
- try applyDataBinding(config.bindData)
84
+ if dataBindingChanged || initialUpdate || reload {
85
+ try applyDataBinding(config.bindData, autoPlay: config.autoPlay)
86
86
  }
87
87
  }
88
88
 
@@ -94,19 +94,28 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate {
94
94
  return baseViewModel?.riveModel?.stateMachine?.viewModelInstance
95
95
  }
96
96
 
97
- func applyDataBinding(_ bindData: BindData) throws {
97
+ func applyDataBinding(_ bindData: BindData, autoPlay: Bool) throws {
98
+ try bindToStateMachine(bindData)
99
+
100
+ if autoPlay {
101
+ play()
102
+ }
103
+ }
104
+
105
+ @MainActor
106
+ func play() {
107
+ baseViewModel?.play()
108
+ }
109
+
110
+ private func bindToStateMachine(_ bindData: BindData) throws {
98
111
  let stateMachine = baseViewModel?.riveModel?.stateMachine
99
112
  let artboard = baseViewModel?.riveModel?.artboard
100
113
 
101
114
  switch bindData {
102
115
  case .none:
103
116
  baseViewModel?.riveModel?.disableAutoBind()
104
-
105
117
  case .auto:
106
- baseViewModel?.riveModel?.enableAutoBind { _ in
107
- // Auto-bind callback
108
- }
109
-
118
+ baseViewModel?.riveModel?.enableAutoBind { _ in }
110
119
  case .byName(let name):
111
120
  guard let artboard = artboard,
112
121
  let riveFile = baseViewModel?.riveModel?.riveFile,
@@ -116,20 +125,9 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate {
116
125
  throw NitroRiveError.instanceNotFound(message: "\(name) instance not found")
117
126
  }
118
127
  stateMachine?.bind(viewModelInstance: instance)
119
- // 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
120
- // artboard.bind(viewModelInstance: instance)
121
-
122
128
  case .instance(let instance):
123
129
  stateMachine?.bind(viewModelInstance: instance)
124
- // 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
125
- // artboard?.bind(viewModelInstance: instance)
126
130
  }
127
- play()
128
- }
129
-
130
- @MainActor
131
- func play() {
132
- baseViewModel?.play()
133
131
  }
134
132
 
135
133
  @MainActor
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rive-app/react-native",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Rive React Native",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",