Skip to content

feat: referenced assets#16

Merged
mfazekas merged 24 commits intomainfrom
feat/referencedAssets
Nov 12, 2025
Merged

feat: referenced assets#16
mfazekas merged 24 commits intomainfrom
feat/referencedAssets

Conversation

@mfazekas
Copy link
Copy Markdown
Collaborator

@mfazekas mfazekas commented Nov 6, 2025

Implements referenced assets for RiveFile on iOS/Android. Create and update.

Since it's on file level to refresh views we need week links to views using that file. Also there is synchronisation so we only refresh after asset download and update has finished. Otherwise it's the same as the non nitro version.

Fixes: #7

@mfazekas mfazekas force-pushed the feat/referencedAssets branch from 61c5558 to 2d35e25 Compare November 6, 2025 08:15
@mfazekas mfazekas changed the title feat(ios): referenced assets feat: referenced assets Nov 6, 2025
@mfazekas mfazekas marked this pull request as ready for review November 6, 2025 16:08
@mfazekas mfazekas force-pushed the feat/referencedAssets branch from 071cc9a to 47e3abc Compare November 7, 2025 07:03
@mfazekas mfazekas force-pushed the feat/referencedAssets branch from 174eefa to e9240aa Compare November 10, 2025 13:20
@mfazekas mfazekas force-pushed the feat/referencedAssets branch from e9240aa to 1171783 Compare November 10, 2025 13:25
@mfazekas mfazekas requested a review from HayesGordon November 10, 2025 14:06
mfazekas and others added 5 commits November 10, 2025 16:22
Fixed race condition where views would refresh before asset downloads
completed. This mirrors the Android fix in commit c5adec2.

Changes:
- ReferencedAssetLoader: Added completion handlers to entire async chain
- Completion fires in both success and failure cases
- HybridRiveFile: Use DispatchGroup to wait for all asset loads
- refreshAfterAssetChange() only called after all downloads finish

This ensures views display updated assets even with slow network.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
}


func refreshAfterAssetChange() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could make something a bit more generic. refresh or restart.

The reason is because atm Android and iOS also does not restart the underlying graphic if it's in a settled state when updating data binding.

Something we should chat about though as part of a separate PR. Additionally, we should introduce the concept of paused/stopped/active in ReactNative that works independently from calling play/pause. But this may need to wait for the iOS and Android rewrites.

Comment on lines +25 to +28
// source: {
// fileName: 'Inter-594377.ttf',
// path: 'fonts', // only needed for Android assets
// },
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add this (and the other two fileName + path options to the Android and iOS resources) if we want to keep these as examples

@HayesGordon
Copy link
Copy Markdown
Contributor

Overall looks great!

A limitation with the old runtime is that you cannot reuse decoded assets across multiple files. Which I was hoping we could solve with this version - by creating a JS object that maps to a native RiveRenderImage, RiveFont, and RiveAudio, which you can then just pass/set at any point.

This will allow you to, for example, decode a font asset at the start of your app and then reuse that for multiple different Rive files.

I believe we might be restricted on iOS from doing this (cc @dskuza). Android has:

private fun processAssetBytes(bytes: ByteArray, asset: FileAsset) {
  when (asset) {
    is ImageAsset -> asset.image = RiveRenderImage.make(bytes)
    is FontAsset -> asset.font = RiveFont.make(bytes)
    is AudioAsset -> asset.audio = RiveAudio.make(bytes)
  }
}

So we can decode whenever.

But for iOS we're currently using the factory from the assetLoader.

Or alternatively, we could have some global cache to reuse decoded assets if the keys are the same across multiple file usage. But this might have limitations.

@mfazekas
Copy link
Copy Markdown
Collaborator Author

Overall looks great!

A limitation with the old runtime is that you cannot reuse decoded assets across multiple files. Which I was hoping we could solve with this version - by creating a JS object that maps to a native RiveRenderImage, RiveFont, and RiveAudio, which you can then just pass/set at any point.

This will allow you to, for example, decode a font asset at the start of your app and then reuse that for multiple different Rive files.

I believe we might be restricted on iOS from doing this (cc @dskuza). Android has:

private fun processAssetBytes(bytes: ByteArray, asset: FileAsset) {
  when (asset) {
    is ImageAsset -> asset.image = RiveRenderImage.make(bytes)
    is FontAsset -> asset.font = RiveFont.make(bytes)
    is AudioAsset -> asset.audio = RiveAudio.make(bytes)
  }
}

So we can decode whenever.

But for iOS we're currently using the factory from the assetLoader.

Or alternatively, we could have some global cache to reuse decoded assets if the keys are the same across multiple file usage. But this might have limitations.

I think for this a good first step could be like a HybridRiveImage we could accept values as HybridRiveImage-s, the the object we pass to referencedAssets.

@mfazekas mfazekas requested a review from HayesGordon November 12, 2025 13:40
@HayesGordon
Copy link
Copy Markdown
Contributor

Overall looks great!
A limitation with the old runtime is that you cannot reuse decoded assets across multiple files. Which I was hoping we could solve with this version - by creating a JS object that maps to a native RiveRenderImage, RiveFont, and RiveAudio, which you can then just pass/set at any point.
This will allow you to, for example, decode a font asset at the start of your app and then reuse that for multiple different Rive files.
I believe we might be restricted on iOS from doing this (cc @dskuza). Android has:

private fun processAssetBytes(bytes: ByteArray, asset: FileAsset) {
  when (asset) {
    is ImageAsset -> asset.image = RiveRenderImage.make(bytes)
    is FontAsset -> asset.font = RiveFont.make(bytes)
    is AudioAsset -> asset.audio = RiveAudio.make(bytes)
  }
}

So we can decode whenever.
But for iOS we're currently using the factory from the assetLoader.
Or alternatively, we could have some global cache to reuse decoded assets if the keys are the same across multiple file usage. But this might have limitations.

I think for this a good first step could be like a HybridRiveImage we could accept values as HybridRiveImage-s, the the object we pass to referencedAssets.

Agreed, and should not be needed for releasing this as is.

Copy link
Copy Markdown
Contributor

@HayesGordon HayesGordon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, it's great!

@mfazekas mfazekas merged commit ea6543f into main Nov 12, 2025
5 checks passed
mfazekas added a commit that referenced this pull request Nov 17, 2025
* feat: referencedAssets (ios)

* fix: referencedAssets (ios) - missing files

* feat: referencedAssets (ios)

* nitrogen files

* fix typecheck

* fix typecheck

* fix: allow useRiveFile to work with undefined input

* feat(andorid): implement referencedAssets

* feat(ios): referencedAssetLoader - update on native side

* chore: added test for useRiveFile

* fix(ios): refresh after updating the asset

* fix: adderss race condition on doanlowd finished -> refresh

* fix: js lint/test

* remove rive view

* added exmpla

* update

* fix: typecheck

* fix(ios): prevent race condition in referenced asset loading

Fixed race condition where views would refresh before asset downloads
completed. This mirrors the Android fix in commit c5adec2.

Changes:
- ReferencedAssetLoader: Added completion handlers to entire async chain
- Completion fires in both success and failure cases
- HybridRiveFile: Use DispatchGroup to wait for all asset loads
- refreshAfterAssetChange() only called after all downloads finish

This ensures views display updated assets even with slow network.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: remove rn82-example submodule

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* reactor: streamline rivefile factory

* refactor: decouple riveFile and riveView

* refactor: remove unused export

* chore: refresh

* removed unused buildFile

---------

Co-authored-by: Claude <noreply@anthropic.com>
@HayesGordon HayesGordon deleted the feat/referencedAssets branch December 9, 2025 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add referenced (out-of-band) asset support

2 participants