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.
- package/android/build/.transforms/107c050573bf60c5e0c8269943a793ec/results.bin +1 -0
- package/android/build/.transforms/107c050573bf60c5e0c8269943a793ec/transformed/classes/classes.dex +0 -0
- package/android/build/.transforms/628785db81ac3052038232fd7a3a06ac/transformed/debug/com/wix/reactnativeuilib/dynamicfont/DynamicFontModule.dex +0 -0
- package/android/build/.transforms/7c61673e4df105aee95a22a8dfbf4af6/results.bin +1 -0
- package/android/build/.transforms/7c61673e4df105aee95a22a8dfbf4af6/transformed/classes/classes.dex +0 -0
- package/android/build/.transforms/dc6c66051bb0a2aed873a6fee209c3de/transformed/classes/classes.dex +0 -0
- package/android/build/intermediates/compile_library_classes_jar/debug/classes.jar +0 -0
- package/android/build/intermediates/javac/debug/classes/com/wix/reactnativeuilib/dynamicfont/DynamicFontModule.class +0 -0
- package/android/build/intermediates/javac/debug/classes/com/wix/reactnativeuilib/dynamicfont/DynamicFontPackage.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/com/wix/reactnativeuilib/dynamicfont/DynamicFontModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/classes.jar +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/src/main/java/com/wix/reactnativeuilib/dynamicfont/DynamicFontModule.java +44 -53
- package/android/src/main/java/com/wix/reactnativeuilib/dynamicfont/DynamicFontPackage.java +2 -1
- package/android/src/main/java/com/wix/reactnativeuilib/keyboardinput/ReactScreenMonitor.java +3 -1
- package/components/DynamicFonts/FontDownloader.ts +48 -9
- package/components/DynamicFonts/FontLoader.ts +31 -28
- package/components/DynamicFonts/NoPermissionsAcquirer.ts +5 -0
- package/components/DynamicFonts/PermissionsAcquirer.android.ts +1 -6
- package/components/DynamicFonts/PermissionsAcquirer.ios.ts +2 -8
- package/components/DynamicFonts/PermissionsAcquirer.web.ts +2 -0
- package/components/DynamicFonts/RNFSPackage.ts +6 -0
- package/components/DynamicFonts/index.ts +70 -31
- package/components/index.ts +2 -1
- package/ios/reactnativeuilib/dynamicfont/DynamicFont.m +22 -21
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
o/classes
|
package/android/build/.transforms/107c050573bf60c5e0c8269943a793ec/transformed/classes/classes.dex
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
o/classes
|
package/android/build/.transforms/7c61673e4df105aee95a22a8dfbf4af6/transformed/classes/classes.dex
ADDED
|
Binary file
|
package/android/build/.transforms/dc6c66051bb0a2aed873a6fee209c3de/transformed/classes/classes.dex
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
+
}
|
package/android/src/main/java/com/wix/reactnativeuilib/keyboardinput/ReactScreenMonitor.java
CHANGED
|
@@ -62,7 +62,9 @@ public class ReactScreenMonitor implements LifecycleEventListener {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
private void registerWindowLayoutListener() {
|
|
65
|
-
getWindow()
|
|
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
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
// if (!filePath) {
|
|
97
|
+
// throw new Error('filePath is a required argument');
|
|
98
|
+
// }
|
|
96
99
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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) {
|
|
@@ -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
|
|
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
|
-
|
|
2
|
-
public async checkPermissions() {
|
|
3
|
-
return Promise.resolve(true);
|
|
4
|
-
}
|
|
1
|
+
import PermissionsAcquirer from './NoPermissionsAcquirer';
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
return Promise.resolve();
|
|
8
|
-
}
|
|
9
|
-
}
|
|
3
|
+
export default PermissionsAcquirer;
|
|
@@ -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
|
|
5
|
-
|
|
6
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
97
|
-
console.log(fontName, 'Loading');
|
|
98
|
-
}
|
|
100
|
+
this.log(fontName, 'Loading');
|
|
99
101
|
const _fontName = await this.loadFont({fontName, base64FontString, fontExtension});
|
|
100
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
}
|
package/components/index.ts
CHANGED
|
@@ -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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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