UNPKG

3.76 kBJavaScriptView Raw
1// @flow
2
3import { NativeModules } from 'react-native';
4
5import Asset from './Asset';
6import Constants from './Constants';
7
8function nativeName(name) {
9 return `${Constants.sessionId}-${name}`;
10}
11
12const loaded = {};
13const loading = {};
14const onLoadPromises = {};
15
16export function processFontFamily(name: ?string) {
17 if (!name || Constants.systemFonts.includes(name) || name === 'System') {
18 return name;
19 }
20
21 if (name.includes(Constants.sessionId)) {
22 return name;
23 }
24
25 if (!isLoaded(name)) {
26 if (__DEV__) {
27 if (isLoading(name)) {
28 console.error(
29 `You started loading '${name}', but used it before it finished loading\n\n` +
30 `- You need to wait for Expo.Font.loadAsync to complete before using the font.\n\n` +
31 `- We recommend loading all fonts before rendering the app, and rendering only ` +
32 `Expo.AppLoading while waiting for loading to complete.`
33 );
34 } else {
35 console.error(
36 `fontFamily '${name}' is not a system font and has not been loaded through ` +
37 `Expo.Font.loadAsync.\n\n` +
38 `- If you intended to use a system font, make sure you typed the name ` +
39 `correctly and that it is supported by your device operating system.\n\n` +
40 `- If this is a custom font, be sure to load it with Expo.Font.loadAsync.`
41 );
42 }
43 }
44
45 return 'System';
46 }
47
48 return `ExponentFont-${nativeName(name)}`;
49}
50
51export function isLoaded(name: string) {
52 return !!loaded[name];
53}
54
55export function isLoading(name: string) {
56 return !!onLoadPromises[name];
57}
58
59export async function loadAsync(
60 nameOrMapOrArray: any,
61 uriOrModuleOrAsset: any
62) {
63 if (typeof nameOrMapOrArray === 'object') {
64 if (Array.isArray(nameOrMapOrArray)) {
65 const fontObjs = nameOrMapOrArray;
66 await Promise.all(fontObjs.map(fontObj => loadAsync(fontObj)));
67 } else {
68 const names = Object.keys(nameOrMapOrArray);
69 await Promise.all(
70 names.map(name => loadAsync(name, nameOrMapOrArray[name]))
71 );
72 }
73
74 return;
75 }
76
77 let name = nameOrMapOrArray;
78 if (loaded[name]) {
79 } else if (loading[name]) {
80 await new Promise(resolve => {
81 onLoadPromises[name].push(resolve);
82 });
83 } else {
84 loading[name] = true;
85 onLoadPromises[name] = [];
86
87 let asset;
88 if (typeof uriOrModuleOrAsset === 'string') {
89 // TODO(nikki): need to implement Asset.fromUri(...)
90 // asset = Asset.fromUri(uriOrModuleOrAsset);
91 throw new Error(
92 'Loading fonts from remote URIs is temporarily not supported. Please download the font file and load it using require. See: https://docs.getexponent.com/versions/v8.0.0/guides/using-custom-fonts.html#downloading-the-font'
93 );
94 } else if (typeof uriOrModuleOrAsset === 'number') {
95 asset = Asset.fromModule(uriOrModuleOrAsset);
96 } else {
97 asset = uriOrModuleOrAsset;
98 }
99
100 await asset.downloadAsync();
101 if (asset.downloaded) {
102 await NativeModules.ExponentFontLoader.loadAsync(
103 nativeName(name),
104 asset.localUri
105 );
106 } else {
107 throw new Error(`Couldn't download asset for font '${name}'`);
108 }
109
110 loaded[name] = true;
111 delete loading[name];
112 if (onLoadPromises[name]) {
113 onLoadPromises[name].forEach(resolve => resolve());
114 delete onLoadPromises[name];
115 }
116 }
117}
118
119export function style(
120 name: string,
121 options: { ignoreWarning: boolean } = { ignoreWarning: false }
122) {
123 if (!name) {
124 return {
125 fontFamily: undefined,
126 };
127 }
128
129 if (!loaded[name] && !options.ignoreWarning) {
130 console.warn(`[Expo.Font] No font '${name}', or it hasn't been loaded yet`);
131 }
132 return {
133 fontFamily: `ExponentFont-${nativeName(name)}`,
134 };
135}