-
Notifications
You must be signed in to change notification settings - Fork 13
feat!: remove onStop callback in favor of data-binding triggers #364
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
892f3f4
feat!: remove onStop callback in favor of data-binding triggers
mfazekas cc681f3
fix: add finished_trigger schema types; skip introspection test on le…
mfazekas a9c8989
docs: drop onStop rationale paragraph from README
mfazekas 1f9e082
docs: drop lifecycle-callbacks row from feature table
mfazekas 8fff2c9
docs: make the finished-trigger snippet self-contained and non-deprec…
mfazekas File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| import { | ||
| describe, | ||
| it, | ||
| expect, | ||
| render, | ||
| waitFor, | ||
| cleanup, | ||
| } from 'react-native-harness'; | ||
| import { View } from 'react-native'; | ||
| import { | ||
| RiveView, | ||
| RiveFileFactory, | ||
| Fit, | ||
| useRiveTrigger, | ||
| type RiveFile, | ||
| type RiveViewRef, | ||
| type ViewModelInstance, | ||
| } from '@rive-app/react-native'; | ||
|
|
||
| // One-shot animation that fires the 'finished' view-model trigger when it | ||
| // completes (state machine exit-time transition action) — the data-binding | ||
| // replacement for the removed onStop prop. | ||
| const FINISHED_TRIGGER = require('../assets/rive/finished_trigger.riv'); | ||
|
|
||
| const delay = (ms: number) => new Promise((r) => setTimeout(r, ms)); | ||
|
|
||
| function expectDefined<T>(value: T): asserts value is NonNullable<T> { | ||
| expect(value).toBeDefined(); | ||
| } | ||
|
|
||
| type TestContext = { | ||
| ref: RiveViewRef | null; | ||
| triggerCount: number; | ||
| error: string | null; | ||
| }; | ||
|
|
||
| function FinishedView({ | ||
| file, | ||
| instance, | ||
| context, | ||
| }: { | ||
| file: RiveFile; | ||
| instance: ViewModelInstance; | ||
| context: TestContext; | ||
| }) { | ||
| useRiveTrigger('finished', instance, { | ||
| onTrigger: () => { | ||
| context.triggerCount++; | ||
| }, | ||
| }); | ||
|
|
||
| return ( | ||
| <View style={{ width: 200, height: 200 }}> | ||
| <RiveView | ||
| hybridRef={{ | ||
| f: (ref: RiveViewRef | null) => { | ||
| context.ref = ref; | ||
| }, | ||
| }} | ||
| style={{ flex: 1 }} | ||
| file={file} | ||
| autoPlay={true} | ||
| fit={Fit.Contain} | ||
| dataBind={instance} | ||
| onError={(e) => { | ||
| context.error = e.message; | ||
| }} | ||
| /> | ||
| </View> | ||
| ); | ||
| } | ||
|
|
||
| // getPropertiesAsync is not implemented on the legacy backend, so the | ||
| // introspection test only runs on the new runtime. The behavioral test below | ||
| // runs on every backend. | ||
| const isExperimental = RiveFileFactory.getBackend() === 'experimental'; | ||
|
|
||
| describe('finished-trigger.riv', () => { | ||
| (isExperimental ? it : it.skip)( | ||
| 'loads and exposes a view model with a finished trigger', | ||
| async () => { | ||
| const file = await RiveFileFactory.fromSource( | ||
| FINISHED_TRIGGER, | ||
| undefined | ||
| ); | ||
| expectDefined(file); | ||
|
|
||
| const artboards = await file.getArtboardNamesAsync(); | ||
| const vmNames = await file.getViewModelNamesAsync(); | ||
| console.log(`artboards: ${JSON.stringify(artboards)}`); | ||
| console.log(`viewModels: ${JSON.stringify(vmNames)}`); | ||
|
|
||
| for (const name of vmNames) { | ||
| const vm = await file.viewModelByNameAsync(name); | ||
| expectDefined(vm); | ||
| const props = await vm.getPropertiesAsync(); | ||
| console.log(`VM "${name}" properties: ${JSON.stringify(props)}`); | ||
| } | ||
|
|
||
| const vm = await file.defaultArtboardViewModelAsync(); | ||
| expectDefined(vm); | ||
| const props = await vm.getPropertiesAsync(); | ||
| const finished = props.find((p) => p.name === 'finished'); | ||
| expectDefined(finished); | ||
| cleanup(); | ||
| } | ||
| ); | ||
|
|
||
| it('fires the finished trigger exactly once when the animation completes', async () => { | ||
| const file = await RiveFileFactory.fromSource(FINISHED_TRIGGER, undefined); | ||
| const vm = await file.defaultArtboardViewModelAsync(); | ||
| expectDefined(vm); | ||
| const instance = await vm.createDefaultInstanceAsync(); | ||
| expectDefined(instance); | ||
|
|
||
| const context: TestContext = { ref: null, triggerCount: 0, error: null }; | ||
| const mountedAt = Date.now(); | ||
| await render( | ||
| <FinishedView file={file} instance={instance} context={context} /> | ||
| ); | ||
|
|
||
| await waitFor(() => expect(context.triggerCount).toBeGreaterThan(0), { | ||
| timeout: 10000, | ||
| }); | ||
|
|
||
| // The one-shot timeline is ~1s; a fire much earlier means the state | ||
| // machine exited the animation state immediately (e.g. exit time not | ||
| // set to 100% in the editor) instead of at completion. | ||
| const firedAfterMs = Date.now() - mountedAt; | ||
| console.log(`finished trigger fired ${firedAfterMs} ms after mount`); | ||
| expect(firedAfterMs).toBeGreaterThan(500); | ||
|
|
||
| const samples: number[] = []; | ||
| for (let i = 0; i < 3; i++) { | ||
| await delay(1000); | ||
| samples.push(context.triggerCount); | ||
| } | ||
| console.log(`finished trigger count progression: ${samples.join(', ')}`); | ||
| expect(context.error).toBeNull(); | ||
| expect(context.triggerCount).toBe(1); | ||
| cleanup(); | ||
| }); | ||
| }); |
This file was deleted.
Oops, something went wrong.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| // Generated by rive-gen-types — do not edit manually. @generated | ||
| /* eslint-disable */ | ||
| // Source: finished_trigger.riv | ||
| import type { RiveAsset } from '@rive-app/react-native'; | ||
| declare const asset: RiveAsset<{ | ||
| artboards: 'Artboard'; | ||
| defaultArtboard: 'Artboard'; | ||
| stateMachines: { | ||
| Artboard: 'State Machine 1'; | ||
| }; | ||
| viewModels: { | ||
| ViewModel1: { | ||
| finished: 'trigger'; | ||
| }; | ||
| }; | ||
| }>; | ||
| export default asset; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.