-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathRiveFile.ts
More file actions
149 lines (137 loc) · 5.03 KB
/
RiveFile.ts
File metadata and controls
149 lines (137 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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 '../hooks/useRiveFile';
const RiveFileInternal =
NitroModules.createHybridObject<RiveFileFactoryInternal>('RiveFileFactory');
/**
* Factory namespace for creating RiveFile instances from different sources.
* Provides static methods to load Rive animations from URLs, resources, or raw bytes.
*/
export namespace RiveFileFactory {
/**
* Creates a RiveFile instance from a URL.
* @param url - The URL of the Rive animation 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<RiveFile> {
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 animation 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<RiveFile> {
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<RiveFile> {
return RiveFileInternal.fromResource(
resource,
loadCdn,
referencedAssets ? { data: referencedAssets } : undefined
);
}
/**
* Creates a RiveFile instance from raw bytes.
* @param bytes - The raw bytes of the Rive animation 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<RiveFile> {
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('./animation.riv'));
*
* // Using a URI object
* const riveFile2 = await RiveFileFactory.fromSource({ uri: 'https://example.com/animation.riv' });
*
* // Using a local file URI
* const riveFile3 = await RiveFileFactory.fromSource({ uri: 'file:///path/to/animation.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<RiveFile> {
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 provided, ${source} is not a valid asset ID or URI`
);
}
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}`);
}
}
}