1import { Asset } from 'expo-asset';
2import { CodedError } from 'expo-modules-core';
3
4import ExpoFontLoader from './ExpoFontLoader';
5import { FontResource, FontSource, FontDisplay } from './Font.types';
6
7function uriFromFontSource(asset: any): string | null {
8  if (typeof asset === 'string') {
9    return asset || null;
10  } else if (typeof asset === 'object') {
11    return asset.uri || asset.localUri || asset.default || null;
12  } else if (typeof asset === 'number') {
13    return uriFromFontSource(Asset.fromModule(asset));
14  }
15  return null;
16}
17
18function displayFromFontSource(asset: any): FontDisplay | undefined {
19  return asset.display || FontDisplay.AUTO;
20}
21
22export function fontFamilyNeedsScoping(name: string): boolean {
23  return false;
24}
25
26export function getAssetForSource(source: FontSource): Asset | FontResource {
27  const uri = uriFromFontSource(source);
28  const display = displayFromFontSource(source);
29
30  if (!uri || typeof uri !== 'string') {
31    throwInvalidSourceError(uri);
32  }
33
34  return {
35    uri: uri!,
36    display,
37  };
38}
39
40function throwInvalidSourceError(source: any): never {
41  let type: string = typeof source;
42  if (type === 'object') type = JSON.stringify(source, null, 2);
43  throw new CodedError(
44    `ERR_FONT_SOURCE`,
45    `Expected font asset of type \`string | FontResource | Asset\` instead got: ${type}`
46  );
47}
48
49// NOTE(EvanBacon): No async keyword!
50export function loadSingleFontAsync(name: string, input: Asset | FontResource): Promise<void> {
51  if (typeof input !== 'object' || typeof input.uri !== 'string' || (input as any).downloadAsync) {
52    throwInvalidSourceError(input);
53  }
54
55  try {
56    return ExpoFontLoader.loadAsync(name, input);
57  } catch {
58    // No-op.
59  }
60
61  return Promise.resolve();
62}
63
64export function getNativeFontName(name: string): string {
65  return name;
66}
67