uilib-native 4.1.0 → 4.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/android/build/.transforms/107c050573bf60c5e0c8269943a793ec/results.bin +1 -0
  2. package/android/build/.transforms/107c050573bf60c5e0c8269943a793ec/transformed/classes/classes.dex +0 -0
  3. package/android/build/.transforms/628785db81ac3052038232fd7a3a06ac/transformed/debug/com/wix/reactnativeuilib/dynamicfont/DynamicFontModule.dex +0 -0
  4. package/android/build/.transforms/7c61673e4df105aee95a22a8dfbf4af6/results.bin +1 -0
  5. package/android/build/.transforms/7c61673e4df105aee95a22a8dfbf4af6/transformed/classes/classes.dex +0 -0
  6. package/android/build/.transforms/dc6c66051bb0a2aed873a6fee209c3de/transformed/classes/classes.dex +0 -0
  7. package/android/build/intermediates/compile_library_classes_jar/debug/classes.jar +0 -0
  8. package/android/build/intermediates/javac/debug/classes/com/wix/reactnativeuilib/dynamicfont/DynamicFontModule.class +0 -0
  9. package/android/build/intermediates/javac/debug/classes/com/wix/reactnativeuilib/dynamicfont/DynamicFontPackage.class +0 -0
  10. package/android/build/intermediates/runtime_library_classes_dir/debug/com/wix/reactnativeuilib/dynamicfont/DynamicFontModule.class +0 -0
  11. package/android/build/intermediates/runtime_library_classes_jar/debug/classes.jar +0 -0
  12. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  13. package/android/src/main/java/com/wix/reactnativeuilib/dynamicfont/DynamicFontModule.java +44 -53
  14. package/android/src/main/java/com/wix/reactnativeuilib/dynamicfont/DynamicFontPackage.java +2 -1
  15. package/android/src/main/java/com/wix/reactnativeuilib/keyboardinput/ReactScreenMonitor.java +3 -1
  16. package/components/DynamicFonts/FontDownloader.ts +48 -9
  17. package/components/DynamicFonts/FontLoader.ts +31 -28
  18. package/components/DynamicFonts/NoPermissionsAcquirer.ts +5 -0
  19. package/components/DynamicFonts/PermissionsAcquirer.android.ts +1 -6
  20. package/components/DynamicFonts/PermissionsAcquirer.ios.ts +2 -8
  21. package/components/DynamicFonts/PermissionsAcquirer.web.ts +2 -0
  22. package/components/DynamicFonts/RNFSPackage.ts +6 -0
  23. package/components/DynamicFonts/index.ts +70 -31
  24. package/components/index.ts +2 -1
  25. package/ios/reactnativeuilib/dynamicfont/DynamicFont.m +22 -21
  26. package/package.json +1 -1
@@ -1,35 +1,24 @@
1
1
  package com.wix.reactnativeuilib.dynamicfont;
2
2
 
3
+ import android.app.Activity;
4
+ import android.graphics.Typeface;
5
+ import android.util.Base64;
6
+
7
+ import com.facebook.react.bridge.Callback;
3
8
  import com.facebook.react.bridge.ReactApplicationContext;
4
9
  import com.facebook.react.bridge.ReactContextBaseJavaModule;
5
10
  import com.facebook.react.bridge.ReactMethod;
6
- import com.facebook.react.bridge.Callback;
7
- import com.facebook.react.bridge.Arguments;
8
11
  import com.facebook.react.bridge.ReadableMap;
9
- import com.facebook.react.bridge.WritableMap;
10
12
  import com.facebook.react.views.text.ReactFontManager;
11
13
 
12
- import android.app.Activity;
13
- import android.graphics.Typeface;
14
- import android.util.Base64;
15
-
16
14
  import java.io.File;
17
15
  import java.io.FileOutputStream;
18
- import java.lang.reflect.Field;
19
- import java.util.ArrayList;
20
- import java.util.HashMap;
21
- import java.util.List;
22
- import java.util.Map;
23
- import java.util.Set;
24
16
 
25
17
  public class DynamicFontModule extends ReactContextBaseJavaModule {
26
18
  int tempNameCounter = 0;
27
19
 
28
- private final ReactApplicationContext reactContext;
29
-
30
20
  public DynamicFontModule(ReactApplicationContext reactContext) {
31
21
  super(reactContext);
32
- this.reactContext = reactContext;
33
22
  }
34
23
 
35
24
  @Override
@@ -37,42 +26,44 @@ public class DynamicFontModule extends ReactContextBaseJavaModule {
37
26
  return "DynamicFont";
38
27
  }
39
28
 
40
- @ReactMethod
41
- public void loadFontFromFile(final ReadableMap options, final Callback callback) {
42
- Activity currentActivity = getCurrentActivity();
43
- if (currentActivity == null) {
44
- callback.invoke("Invalid activity");
45
- return;
46
- }
47
-
48
- String filePath = options.hasKey("filePath") ? options.getString("filePath") : null,
49
- name = (options.hasKey("name")) ? options.getString("name") : null;
50
-
51
- if (filePath == null || filePath.length() == 0) {
52
- callback.invoke("filePath property empty");
53
- return;
54
- }
55
-
56
- File f = new File(filePath);
57
-
58
- if (f.exists() && f.canRead()) {
59
- boolean wasLoaded = false;
60
- try {
61
- Typeface typeface = Typeface.createFromFile(f);
62
- //Cache the font for react
63
- ReactFontManager.getInstance().setTypeface(name, typeface.getStyle(), typeface);
64
- wasLoaded = true;
65
- } catch (Throwable e) {
66
- callback.invoke(e.getMessage());
67
- } finally {
68
- if (wasLoaded) {
69
- callback.invoke(null, name);
70
- }
71
- }
72
- } else {
73
- callback.invoke("invalid file");
74
- }
75
- }
29
+ // TODO: Needs to be tested
30
+ // @ReactMethod
31
+ // public void loadFontFromFile(final ReadableMap options, final Callback callback) {
32
+ // Activity currentActivity = getCurrentActivity();
33
+ // if (currentActivity == null) {
34
+ // callback.invoke("Invalid activity");
35
+ // return;
36
+ // }
37
+
38
+ // String filePath = options.hasKey("filePath") ? options.getString("filePath") : null,
39
+ // name = (options.hasKey("name")) ? options.getString("name") : null;
40
+
41
+ // if (filePath == null || filePath.length() == 0) {
42
+ // callback.invoke("filePath property empty");
43
+ // return;
44
+ // }
45
+
46
+ // File f = new File(filePath);
47
+
48
+ // if (f.exists() && f.canRead()) {
49
+ // boolean wasLoaded = false;
50
+ // try {
51
+ // Typeface typeface = Typeface.createFromFile(f);
52
+ // //Cache the font for react
53
+ // TODO: probably needs to be Typeface.NORMAL and not typeface.getStyle()
54
+ // ReactFontManager.getInstance().setTypeface(name, typeface.getStyle(), typeface);
55
+ // wasLoaded = true;
56
+ // } catch (Throwable e) {
57
+ // callback.invoke(e.getMessage());
58
+ // } finally {
59
+ // if (wasLoaded) {
60
+ // callback.invoke(null, name);
61
+ // }
62
+ // }
63
+ // } else {
64
+ // callback.invoke("invalid file");
65
+ // }
66
+ // }
76
67
 
77
68
  @ReactMethod
78
69
  public void loadFont(final ReadableMap options, final Callback callback) throws Exception {
@@ -136,7 +127,7 @@ public class DynamicFontModule extends ReactContextBaseJavaModule {
136
127
  Typeface typeface = Typeface.createFromFile(cacheFile);
137
128
 
138
129
  //Cache the font for react
139
- ReactFontManager.getInstance().setTypeface(name, typeface.getStyle(), typeface);
130
+ ReactFontManager.getInstance().setTypeface(name, Typeface.NORMAL, typeface);
140
131
 
141
132
  cacheFile.delete();
142
133
  } catch(Exception e) {
@@ -9,6 +9,7 @@ import com.facebook.react.bridge.NativeModule;
9
9
  import com.facebook.react.bridge.ReactApplicationContext;
10
10
  import com.facebook.react.uimanager.ViewManager;
11
11
  import com.facebook.react.bridge.JavaScriptModule;
12
+
12
13
  public class DynamicFontPackage implements ReactPackage {
13
14
  @Override
14
15
  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
@@ -24,4 +25,4 @@ public class DynamicFontPackage implements ReactPackage {
24
25
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
25
26
  return Collections.emptyList();
26
27
  }
27
- }
28
+ }
@@ -62,7 +62,9 @@ public class ReactScreenMonitor implements LifecycleEventListener {
62
62
  }
63
63
 
64
64
  private void registerWindowLayoutListener() {
65
- getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(mWindowLayoutListener);
65
+ if (getWindow() != null) {
66
+ getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(mWindowLayoutListener);
67
+ }
66
68
  }
67
69
 
68
70
  private void removeWindowLayoutListener() {
@@ -1,5 +1,5 @@
1
1
  import {Platform} from 'react-native';
2
- import fs from 'react-native-fs';
2
+ import RNFS from './RNFSPackage';
3
3
  import {FontExtension} from './FontLoader';
4
4
 
5
5
  const DEFAULT_DYNAMIC_FONTS_FOLDER = '/dynamicFonts';
@@ -20,6 +20,7 @@ export type FontDownloaderProps = {
20
20
  // TODO: this can probably be a more general "downloader" if we so choose
21
21
  export default class FontDownloader {
22
22
  private readonly props: FontDownloaderProps;
23
+ private readonly fs: NonNullable<typeof RNFS>;
23
24
 
24
25
  constructor(props: FontDownloaderProps) {
25
26
  this.props = {
@@ -27,11 +28,25 @@ export default class FontDownloader {
27
28
  downloadErrorMessage: DEFAULT_DOWNLOAD_ERROR_MESSAGE,
28
29
  ...props
29
30
  };
31
+
32
+ if (!RNFS) {
33
+ throw new Error(`RNUILib FontDownloader requires installing "react-native-fs" dependency`);
34
+ }
35
+ this.fs = RNFS;
36
+ }
37
+
38
+ private log(message?: any, ...optionalParams: any[]) {
39
+ const {debug} = this.props;
40
+ if (debug) {
41
+ console.log(message, optionalParams);
42
+ }
30
43
  }
31
44
 
32
45
  private getPrivateFolder() {
33
46
  const {dynamicFontsFolder} = this.props;
34
- return (Platform.OS === 'android' ? fs.ExternalDirectoryPath : fs.DocumentDirectoryPath) + dynamicFontsFolder;
47
+ return (
48
+ (Platform.OS === 'android' ? this.fs.ExternalDirectoryPath : this.fs.DocumentDirectoryPath) + dynamicFontsFolder
49
+ );
35
50
  }
36
51
 
37
52
  private getPrivateFilePath(fileName: string) {
@@ -44,13 +59,13 @@ export default class FontDownloader {
44
59
 
45
60
  private async _isFontDownloaded(fileName: string) {
46
61
  const privateFilePath = this.getPrivateFilePath(fileName);
47
- return await fs.exists(privateFilePath);
62
+ return await this.fs.exists(privateFilePath);
48
63
  }
49
64
 
50
65
  private async createPrivateFolderIfNeeded() {
51
66
  const privateFolder = this.getPrivateFolder();
52
- if (!(await fs.exists(privateFolder))) {
53
- await fs.mkdir(privateFolder);
67
+ if (!(await this.fs.exists(privateFolder))) {
68
+ await this.fs.mkdir(privateFolder);
54
69
  }
55
70
  }
56
71
 
@@ -95,19 +110,24 @@ export default class FontDownloader {
95
110
  const downloadLocation = this.getPrivateFilePath(fileName);
96
111
 
97
112
  try {
98
- const result = await fs.downloadFile(this.getDownloadFontOptions(fontUri, downloadLocation, timeout)).promise;
113
+ this.log(fontName, 'Starting to download');
114
+ const result = await this.fs.downloadFile(this.getDownloadFontOptions(fontUri, downloadLocation, timeout))
115
+ .promise;
99
116
  if (result.statusCode === 200) {
117
+ this.log(fontName, 'Finished downloading');
100
118
  return downloadLocation;
101
119
  } else {
120
+ this.log(fontName, 'Error downloading statusCode:', result.statusCode);
102
121
  return Promise.reject({
103
122
  source: 'uilib:FontDownloader:downloadFont',
104
123
  message: `${downloadErrorMessage} fontName: ${fontName} statusCode: ${result.statusCode}`
105
124
  });
106
125
  }
107
126
  } catch (error) {
127
+ this.log(fontName, 'Error downloading error:', error);
108
128
  return Promise.reject({
109
129
  source: 'uilib:FontDownloader:downloadFont',
110
- message: `${downloadErrorMessage} fontName: ${fontName} error: ${error}`
130
+ message: `${downloadErrorMessage} fontName: ${fontName} error: ${JSON.stringify(error)}`
111
131
  });
112
132
  }
113
133
  }
@@ -126,10 +146,29 @@ export default class FontDownloader {
126
146
  let base64FontString;
127
147
  const fileName = this.getFileName(fontName, fontExtension);
128
148
  const privateFilePath = this.getPrivateFilePath(fileName);
129
- if (await fs.exists(privateFilePath)) {
130
- base64FontString = await fs.readFile(privateFilePath, 'base64').catch(() => {});
149
+ if (await this.fs.exists(privateFilePath)) {
150
+ this.log(fontName, 'Starting to read from disk');
151
+ base64FontString = await this.fs.readFile(privateFilePath, 'base64').catch(err => {
152
+ this.log(fontName, 'Failed reading from disk:', err);
153
+ });
154
+ this.log(fontName, 'Finished reading from disk');
155
+ } else {
156
+ this.log(fontName, 'File does not exist (read)');
131
157
  }
132
158
 
133
159
  return base64FontString;
134
160
  }
161
+
162
+ public async deleteFontFromDisk(fontFullName: string): Promise<void> {
163
+ const privateFilePath = this.getPrivateFilePath(fontFullName);
164
+ if (await this.fs.exists(privateFilePath)) {
165
+ this.log(fontFullName, 'Starting to delete');
166
+ await this.fs.unlink(privateFilePath).catch(err => {
167
+ this.log(fontFullName, 'Failed deleting:', err);
168
+ });
169
+ this.log(fontFullName, 'Finished deleting');
170
+ } else {
171
+ this.log(fontFullName, 'File does not exist (delete)');
172
+ }
173
+ }
135
174
  }
@@ -40,18 +40,22 @@ export default class FontLoader {
40
40
  this.props = props;
41
41
  }
42
42
 
43
+ private log(message?: any, ...optionalParams: any[]) {
44
+ const {debug} = this.props;
45
+ if (debug) {
46
+ console.log(message, optionalParams);
47
+ }
48
+ }
49
+
43
50
  public loadFont = ({
44
51
  fontName,
45
52
  base64FontString,
46
53
  fontExtension = 'ttf',
47
54
  forceLoad = false
48
55
  }: LoadFontInput): Promise<string> => {
49
- const {debug} = this.props;
50
56
  /* Check if this font was already loaded */
51
57
  if (!forceLoad && this.loadedFonts.has(fontName)) {
52
- if (debug) {
53
- console.log(fontName, 'Already loaded');
54
- }
58
+ this.log(fontName, 'Already loaded');
55
59
  return Promise.resolve(this.loadedFonts.get(fontName) as string);
56
60
  }
57
61
 
@@ -63,9 +67,7 @@ export default class FontLoader {
63
67
  throw new Error('base64FontString is a required argument');
64
68
  }
65
69
 
66
- if (debug) {
67
- console.log(fontName, 'Starting to load');
68
- }
70
+ this.log(fontName, 'Starting to load');
69
71
  /* Load font via native binary code */
70
72
  return new Promise((resolve, reject) => {
71
73
  DynamicFont.loadFont({
@@ -85,29 +87,30 @@ export default class FontLoader {
85
87
  });
86
88
  };
87
89
 
88
- public loadFontFromFile = (fontName: string, filePath: string) => {
89
- if (!fontName) {
90
- throw new Error('name is a required argument');
91
- }
90
+ // TODO: Needs to be tested
91
+ // public loadFontFromFile = (fontName: string, filePath: string) => {
92
+ // if (!fontName) {
93
+ // throw new Error('name is a required argument');
94
+ // }
92
95
 
93
- if (!filePath) {
94
- throw new Error('filePath is a required argument');
95
- }
96
+ // if (!filePath) {
97
+ // throw new Error('filePath is a required argument');
98
+ // }
96
99
 
97
- return new Promise((resolve, reject) => {
98
- DynamicFont.loadFontFromFile({
99
- name: fontName,
100
- filePath
101
- },
102
- (err: string, givenName: string) => {
103
- if (err) {
104
- reject(err);
105
- return;
106
- }
107
- resolve(givenName);
108
- });
109
- });
110
- };
100
+ // return new Promise((resolve, reject) => {
101
+ // DynamicFont.loadFontFromFile({
102
+ // name: fontName,
103
+ // filePath
104
+ // },
105
+ // (err: string, givenName: string) => {
106
+ // if (err) {
107
+ // reject(err);
108
+ // return;
109
+ // }
110
+ // resolve(givenName);
111
+ // });
112
+ // });
113
+ // };
111
114
 
112
115
  public loadFonts = (fonts: LoadFontInput | LoadFontInput[], forceLoad?: boolean) => {
113
116
  if (!fonts) {
@@ -0,0 +1,5 @@
1
+ export default class NoPermissionsAcquirer {
2
+ public async getPermissions() {
3
+ return Promise.resolve();
4
+ }
5
+ }
@@ -4,7 +4,6 @@ const AndroidOsVersion = Platform.OS === 'android' ? Platform.constants.Release
4
4
  export type PermissionsAcquirerProps = {
5
5
  requestPermissionsTitle?: string;
6
6
  requestPermissionsMessage?: string;
7
- requestPermissionsNegativeButtonText?: string;
8
7
  requestPermissionsPositiveButtonText?: string;
9
8
  permissionsRefusalMessage?: string;
10
9
  permissionsErrorMessage?: string;
@@ -12,8 +11,7 @@ export type PermissionsAcquirerProps = {
12
11
 
13
12
  const DEFAULT_PERMISSIONS_ACQUIRER_PROPS: Required<PermissionsAcquirerProps> = {
14
13
  requestPermissionsTitle: 'Allow Storage Access',
15
- requestPermissionsMessage: 'Give the Spaces app permission to access the files and storage on your device.',
16
- requestPermissionsNegativeButtonText: 'Cancel',
14
+ requestPermissionsMessage: 'Give the app permission to access the files and storage on your device.',
17
15
  requestPermissionsPositiveButtonText: 'Continue',
18
16
  permissionsRefusalMessage: 'Please edit your permission settings to continue.',
19
17
  permissionsErrorMessage: `We weren't able to obtain the required permissions. Please try Again.`
@@ -38,9 +36,6 @@ export default class PermissionsAcquirer {
38
36
  const result = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, {
39
37
  title: this.props.requestPermissionsTitle ?? DEFAULT_PERMISSIONS_ACQUIRER_PROPS.requestPermissionsTitle,
40
38
  message: this.props.requestPermissionsMessage ?? DEFAULT_PERMISSIONS_ACQUIRER_PROPS.requestPermissionsMessage,
41
- buttonNegative:
42
- this.props.requestPermissionsNegativeButtonText ??
43
- DEFAULT_PERMISSIONS_ACQUIRER_PROPS.requestPermissionsNegativeButtonText,
44
39
  buttonPositive:
45
40
  this.props.requestPermissionsPositiveButtonText ??
46
41
  DEFAULT_PERMISSIONS_ACQUIRER_PROPS.requestPermissionsPositiveButtonText
@@ -1,9 +1,3 @@
1
- export default class PermissionsAcquirer {
2
- public async checkPermissions() {
3
- return Promise.resolve(true);
4
- }
1
+ import PermissionsAcquirer from './NoPermissionsAcquirer';
5
2
 
6
- public async getPermissions() {
7
- return Promise.resolve();
8
- }
9
- }
3
+ export default PermissionsAcquirer;
@@ -0,0 +1,2 @@
1
+ import PermissionsAcquirer from './NoPermissionsAcquirer';
2
+ export default PermissionsAcquirer;
@@ -0,0 +1,6 @@
1
+ let RNFS: typeof import('react-native-fs') | undefined;
2
+ try {
3
+ RNFS = require('react-native-fs');
4
+ } catch (error) {}
5
+
6
+ export default RNFS;
@@ -1,9 +1,9 @@
1
- import {Platform} from 'react-native';
2
1
  import FontLoader, {FontExtension, LoadFontInput} from './FontLoader';
3
2
  import FontDownloader, {FontDownloaderProps} from './FontDownloader';
4
- import PermissionsAcquirerAndroid, {PermissionsAcquirerProps} from './PermissionsAcquirer.android';
5
- import PermissionsAcquirerIOS from './PermissionsAcquirer.ios';
6
- const PermissionsAcquirer = Platform.OS === 'android' ? PermissionsAcquirerAndroid : PermissionsAcquirerIOS;
3
+ import type {PermissionsAcquirerProps} from './PermissionsAcquirer.android';
4
+ // @ts-expect-error
5
+ import PermissionsAcquirer from './PermissionsAcquirer';
6
+ import NoPermissionsAcquirer from './NoPermissionsAcquirer';
7
7
 
8
8
  const DEFAULT_FONT_LOAD_ERROR_MESSAGE = 'Unable to load this font.';
9
9
 
@@ -15,6 +15,10 @@ type DynamicFontsProps = {
15
15
  * Enable debug mode to print extra logs
16
16
  */
17
17
  debug?: boolean;
18
+ /**
19
+ * Do not request permissions
20
+ */
21
+ doNotRequestPermissions?: boolean;
18
22
  };
19
23
 
20
24
  type GetFontInput = {
@@ -45,14 +49,23 @@ export default class DynamicFonts {
45
49
  private readonly fontDownloader: InstanceType<typeof FontDownloader>;
46
50
 
47
51
  constructor(props: DynamicFontsProps) {
48
- const {debug} = props;
52
+ const {debug = __DEV__, doNotRequestPermissions} = props;
49
53
  this.props = {fontLoadErrorMessage: DEFAULT_FONT_LOAD_ERROR_MESSAGE, ...props};
50
- this.permissionsAcquirer = new PermissionsAcquirer(this.props.permissionsAcquirerProps ?? {});
54
+ this.permissionsAcquirer = doNotRequestPermissions
55
+ ? new NoPermissionsAcquirer()
56
+ : new PermissionsAcquirer(this.props.permissionsAcquirerProps ?? {});
51
57
  this.fontLoader = new FontLoader({debug});
52
58
  const fontDownloadingProps = this.props.fontDownloadingProps ?? {};
53
59
  this.fontDownloader = new FontDownloader({...fontDownloadingProps, debug});
54
60
  }
55
61
 
62
+ private log(message?: any, ...optionalParams: any[]) {
63
+ const {debug} = this.props;
64
+ if (debug) {
65
+ console.log(message, optionalParams);
66
+ }
67
+ }
68
+
56
69
  private async loadFont(input: LoadFontInput) {
57
70
  const {fontLoadErrorMessage} = this.props;
58
71
  try {
@@ -60,7 +73,7 @@ export default class DynamicFonts {
60
73
  } catch (err) {
61
74
  return Promise.reject({
62
75
  source: 'uilib:FontDownloader:loadFont',
63
- message: `${fontLoadErrorMessage} fontName: ${input.fontName}`
76
+ message: `${fontLoadErrorMessage} fontName: ${input.fontName} error: ${JSON.stringify(err)}`
64
77
  });
65
78
  }
66
79
  }
@@ -74,32 +87,19 @@ export default class DynamicFonts {
74
87
  * @param timeout milliseconds for the download to complete in (defaults to 5000)
75
88
  */
76
89
  public async getFont({fontUri, fontName, fontExtension, timeout = 5000}: GetFontInput): Promise<string> {
77
- const {debug} = this.props;
78
90
  const {fontLoadErrorMessage} = this.props;
79
91
  await this.permissionsAcquirer.getPermissions();
80
92
  if (await this.fontDownloader.isFontDownloaded(fontName, fontExtension)) {
81
- if (debug) {
82
- console.log(fontName, 'Already downloaded');
83
- }
93
+ this.log(fontName, 'Already downloaded');
84
94
  } else {
85
- if (debug) {
86
- console.log(fontName, 'Starting to download');
87
- }
88
95
  await this.fontDownloader.downloadFont(fontUri, fontName, fontExtension, timeout);
89
- if (debug) {
90
- console.log(fontName, 'Finished downloading');
91
- }
92
96
  }
93
97
 
94
98
  const base64FontString = await this.fontDownloader.readFontFromDisk(fontName, fontExtension);
95
99
  if (base64FontString) {
96
- if (debug) {
97
- console.log(fontName, 'Loading');
98
- }
100
+ this.log(fontName, 'Loading');
99
101
  const _fontName = await this.loadFont({fontName, base64FontString, fontExtension});
100
- if (debug) {
101
- console.log(_fontName, 'Finished loading');
102
- }
102
+ this.log(_fontName, 'Finished loading');
103
103
  return Promise.resolve(_fontName);
104
104
  } else {
105
105
  return Promise.reject({
@@ -118,13 +118,13 @@ export default class DynamicFonts {
118
118
  }
119
119
  }
120
120
 
121
- private buildFontName(rootUri: string,
121
+ private buildFontData(rootUri: string,
122
122
  fontName: string,
123
123
  fontExtension: FontExtension,
124
- fontNamePrefix?: string): GetFontInput {
124
+ fontNamePrefix?: string): GetFontInput & {fullFontName: string} {
125
125
  const _fontName = `${fontNamePrefix ?? ''}${fontName}`;
126
126
  const fullFontName = `${_fontName}.${fontExtension}`;
127
- return {fontUri: `${rootUri}${fullFontName}`, fontName: _fontName, fontExtension};
127
+ return {fontUri: `${rootUri}${fullFontName}`, fontName: _fontName, fontExtension, fullFontName};
128
128
  }
129
129
 
130
130
  // eslint-disable-next-line max-params
@@ -133,9 +133,8 @@ export default class DynamicFonts {
133
133
  fontExtension: FontExtension,
134
134
  fontNamePrefix?: string,
135
135
  retries = 1): Promise<string[]> {
136
- const {debug} = this.props;
137
136
  const fonts: GetFontInput[] = fontNames.map(fontName =>
138
- this.buildFontName(rootUri, fontName, fontExtension, fontNamePrefix));
137
+ this.buildFontData(rootUri, fontName, fontExtension, fontNamePrefix));
139
138
  let fontsLoaded: string[] = [];
140
139
  let tryCounter = 0;
141
140
  while (fontsLoaded.length < fontNames.length && tryCounter < retries) {
@@ -144,12 +143,52 @@ export default class DynamicFonts {
144
143
  // TODO: we should return successful loaded fonts and not fail all of them
145
144
  fontsLoaded = await this.getFonts(fonts);
146
145
  } catch (error) {
147
- if (debug) {
148
- console.log(`getFontFamily failed (try #${tryCounter}) error: ${error}`);
149
- }
146
+ this.log(`getFontFamily failed (try #${tryCounter}) error:`, error);
150
147
  }
151
148
  }
152
149
 
153
150
  return Promise.resolve(fontsLoaded);
154
151
  }
152
+
153
+ private async deleteFontFromDisk(fontName: string, fontExtension: FontExtension, fontNamePrefix?: string) {
154
+ const fontInput = this.buildFontData('', fontName, fontExtension, fontNamePrefix);
155
+ await this.fontDownloader.deleteFontFromDisk(fontInput.fullFontName);
156
+ }
157
+
158
+ public async deleteFont(fontName: string, fontExtension: FontExtension): Promise<void> {
159
+ await this.permissionsAcquirer.getPermissions();
160
+ await this.deleteFontFromDisk(fontName, fontExtension);
161
+ }
162
+
163
+ public async deleteFontFamily(fontNames: string[],
164
+ fontExtension: FontExtension,
165
+ fontNamePrefix?: string): Promise<void> {
166
+ await this.permissionsAcquirer.getPermissions();
167
+ fontNames.forEach(async fontName => {
168
+ await this.deleteFontFromDisk(fontName, fontExtension, fontNamePrefix);
169
+ });
170
+ }
171
+
172
+ public async isFontDownloaded(fontName: string, fontExtension: FontExtension): Promise<boolean> {
173
+ return await this.fontDownloader.isFontDownloaded(fontName, fontExtension);
174
+ }
175
+
176
+ public async isFontFamilyDownloaded(rootUri: string,
177
+ fontNames: string[],
178
+ fontExtension: FontExtension,
179
+ fontNamePrefix?: string): Promise<boolean> {
180
+ const fonts: GetFontInput[] = fontNames.map(fontName =>
181
+ this.buildFontData(rootUri, fontName, fontExtension, fontNamePrefix));
182
+ try {
183
+ const areDownloaded = await Promise.all(fonts
184
+ .filter(font => font)
185
+ .map(font => {
186
+ return this.fontDownloader.isFontDownloaded(font.fontName, font.fontExtension);
187
+ }));
188
+ return Promise.resolve(areDownloaded.every(v => v === true));
189
+ } catch (error) {
190
+ this.log(`isFontFamilyDownloaded failed error:`, error);
191
+ return Promise.resolve(false);
192
+ }
193
+ }
155
194
  }
@@ -1,4 +1,4 @@
1
- import DynamicFonts from './DynamicFonts';
1
+ import DynamicFonts, {FontExtension} from './DynamicFonts';
2
2
  import HighlighterOverlayView from './HighlighterOverlayView';
3
3
  import SafeAreaSpacerView from './SafeArea/SafeAreaSpacerView';
4
4
  import SafeAreaInsetsManager from './SafeArea/SafeAreaInsetsManager';
@@ -6,6 +6,7 @@ import Keyboard, {KeyboardTrackingViewProps, KeyboardAccessoryViewProps} from '.
6
6
 
7
7
  export {
8
8
  DynamicFonts,
9
+ FontExtension,
9
10
  HighlighterOverlayView,
10
11
  SafeAreaSpacerView,
11
12
  SafeAreaInsetsManager,
@@ -11,27 +11,28 @@
11
11
  }
12
12
  RCT_EXPORT_MODULE()
13
13
 
14
- RCT_EXPORT_METHOD(
15
- loadFontFromFile:(NSDictionary *)options callback:(RCTResponseSenderBlock)callback)
16
- {
17
- NSString *path = [options valueForKey:@"path"];
18
- NSString *name = [options valueForKey:@"name"];
19
- NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
20
- CFErrorRef error;
21
- CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
22
- CGFontRef font = CGFontCreateWithDataProvider(provider);
23
- NSString *newFontName = (__bridge NSString *)CGFontCopyPostScriptName(font);
24
- if (! CTFontManagerRegisterGraphicsFont(font, &error)) {
25
- CFStringRef errorDescription = CFErrorCopyDescription(error);
26
- NSLog(@"Failed to load font: %@", errorDescription);
27
- CFRelease(errorDescription);
28
- callback(@[@"Failed to load font: %@", (__bridge NSString *)errorDescription]);
29
- }
30
- CFRelease(font);
31
- CFRelease(provider);
32
- // Resolve to the caller.
33
- callback(@[[NSNull null], newFontName]);
34
- }
14
+ // TODO: Needs to be tested (notice param name "path" here)
15
+ // RCT_EXPORT_METHOD(
16
+ // loadFontFromFile:(NSDictionary *)options callback:(RCTResponseSenderBlock)callback)
17
+ // {
18
+ // NSString *path = [options valueForKey:@"path"];
19
+ // NSString *name = [options valueForKey:@"name"];
20
+ // NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
21
+ // CFErrorRef error;
22
+ // CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
23
+ // CGFontRef font = CGFontCreateWithDataProvider(provider);
24
+ // NSString *newFontName = (__bridge NSString *)CGFontCopyPostScriptName(font);
25
+ // if (! CTFontManagerRegisterGraphicsFont(font, &error)) {
26
+ // CFStringRef errorDescription = CFErrorCopyDescription(error);
27
+ // NSLog(@"Failed to load font: %@", errorDescription);
28
+ // CFRelease(errorDescription);
29
+ // callback(@[@"Failed to load font: %@", (__bridge NSString *)errorDescription]);
30
+ // }
31
+ // CFRelease(font);
32
+ // CFRelease(provider);
33
+ // // Resolve to the caller.
34
+ // callback(@[[NSNull null], newFontName]);
35
+ // }
35
36
 
36
37
  RCT_EXPORT_METHOD(loadFont:(NSDictionary *)options callback:(RCTResponseSenderBlock)callback)
37
38
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uilib-native",
3
- "version": "4.1.0",
3
+ "version": "4.1.2",
4
4
  "homepage": "https://github.com/wix/react-native-ui-lib",
5
5
  "description": "uilib native components (separated from js components)",
6
6
  "main": "components/index.js",