import { NitroModules } from 'react-native-nitro-modules'; import type { RiveFile, RiveFileFactory as RiveFileFactoryInternal, } from '../specs/RiveFile.nitro'; import { Image } from 'react-native'; import type { ResolvedReferencedAssets } from './ReferencedAssets'; const RiveFileInternal = NitroModules.createHybridObject('RiveFileFactory'); /** * Factory namespace for creating RiveFile instances from different sources. * Provides static methods to load Rive files from URLs, resources, or raw bytes. */ export namespace RiveFileFactory { /** * Creates a RiveFile instance from a URL. * @param url - The URL of the Rive (.riv) file * @param loadCdn - Whether to load from CDN (default: true) * @returns Promise that resolves to a RiveFile instance */ export async function fromURL( url: string, referencedAssets: ResolvedReferencedAssets | undefined, loadCdn: boolean = true ): Promise { return RiveFileInternal.fromURL( url, loadCdn, referencedAssets ? { data: referencedAssets } : undefined ); } /** * Creates a RiveFile instance from a local file path URL. * @param pathURL - The local file path of the Rive (.riv) file * @param loadCdn - Whether to load from CDN (default: true) * @returns Promise that resolves to a RiveFile instance */ export async function fromFileURL( fileURL: string, referencedAssets: ResolvedReferencedAssets | undefined = undefined, loadCdn: boolean = true ): Promise { return RiveFileInternal.fromFileURL( fileURL, loadCdn, referencedAssets ? { data: referencedAssets } : undefined ); } /** * Creates a RiveFile instance from a local resource. * @param resource - The name of the local resource * @param loadCdn - Whether to load from CDN (default: true) * @returns Promise that resolves to a RiveFile instance */ export async function fromResource( resource: string, referencedAssets: ResolvedReferencedAssets | undefined, loadCdn: boolean = true ): Promise { return RiveFileInternal.fromResource( resource, loadCdn, referencedAssets ? { data: referencedAssets } : undefined ); } /** * Creates a RiveFile instance from raw bytes. * @param bytes - The raw bytes of the Rive (.riv) file * @param loadCdn - Whether to load from CDN (default: true) * @returns Promise that resolves to a RiveFile instance */ export async function fromBytes( bytes: ArrayBuffer, referencedAssets: ResolvedReferencedAssets | undefined, loadCdn: boolean = true ): Promise { return RiveFileInternal.fromBytes( bytes, loadCdn, referencedAssets ? { data: referencedAssets } : undefined ); } /** * Creates a RiveFile instance from a source that can be either a resource ID or a URI object. * @param source - Either a number representing a resource ID or an object with a uri property * @param loadCdn - Whether to load from CDN (default: true) * @returns Promise that resolves to a RiveFile instance * @throws Error if the source is invalid or cannot be resolved * @example * // Using a resource ID * const riveFile1 = await RiveFileFactory.fromSource(require('./your_file.riv')); * * // Using a URI object * const riveFile2 = await RiveFileFactory.fromSource({ uri: 'https://example.com/your_file.riv' }); * * // Using a local file URI * const riveFile3 = await RiveFileFactory.fromSource({ uri: 'file:///path/to/your_file.riv' }); * * @note To use .riv files with require(), you need to add 'riv' to the asset extensions in your metro.config.js: * ```js * const config = getDefaultConfig(__dirname); * config.resolver.assetExts = [...config.resolver.assetExts, 'riv']; * ``` */ export async function fromSource( source: number | { uri: string }, referencedAssets: ResolvedReferencedAssets | undefined, loadCdn: boolean = true ): Promise { const assetID = typeof source === 'number' ? source : null; const sourceURI = typeof source === 'object' ? source.uri : null; const assetURI = assetID ? Image.resolveAssetSource(assetID)?.uri : sourceURI; if (!assetURI) { throw new Error( `Invalid source: could not resolve asset ${source}. Ensure 'riv' is in metro.config.js assetExts.` ); } try { // handle http address and dev server if (assetURI.match(/https?:\/\//)) { return RiveFileFactory.fromURL(assetURI, referencedAssets, loadCdn); } // handle iOS bundled asset if (assetURI.match(/file:\/\//)) { return RiveFileFactory.fromFileURL(assetURI, referencedAssets, loadCdn); } // handle Android bundled asset or resource name uri return RiveFileFactory.fromResource(assetURI, referencedAssets, loadCdn); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); throw new Error(`Failed to load Rive file from source: ${errorMessage}`); } } }