1 | import * as types from './types';
|
2 | import { dispatchToMainThread, dispatchToUIThread, isMainThread } from './mainthread-helper';
|
3 | import emojiRegex from 'emoji-regex';
|
4 | import { GC } from './index';
|
5 | export * from './mainthread-helper';
|
6 | export * from './macrotask-scheduler';
|
7 | export const RESOURCE_PREFIX = 'res://';
|
8 | export const SYSTEM_PREFIX = 'sys://';
|
9 | export const FILE_PREFIX = 'file:///';
|
10 | export function escapeRegexSymbols(source) {
|
11 | const escapeRegex = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;
|
12 | return source.replace(escapeRegex, '\\$&');
|
13 | }
|
14 | export function convertString(value) {
|
15 | let result;
|
16 | if (!types.isString(value) || value.trim() === '') {
|
17 | result = value;
|
18 | }
|
19 | else {
|
20 |
|
21 | const valueAsNumber = +value;
|
22 | if (!isNaN(valueAsNumber)) {
|
23 | result = valueAsNumber;
|
24 | }
|
25 | else if (value && (value.toLowerCase() === 'true' || value.toLowerCase() === 'false')) {
|
26 | result = value.toLowerCase() === 'true' ? true : false;
|
27 | }
|
28 | else {
|
29 | result = value;
|
30 | }
|
31 | }
|
32 | return result;
|
33 | }
|
34 | export function getModuleName(path) {
|
35 | const moduleName = path.replace('./', '');
|
36 | return sanitizeModuleName(moduleName);
|
37 | }
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | export function sanitizeModuleName(moduleName, removeExtension = true) {
|
44 | moduleName = moduleName.trim();
|
45 | if (moduleName.startsWith('~/')) {
|
46 | moduleName = moduleName.substring(2);
|
47 | }
|
48 | else if (moduleName.startsWith('~')) {
|
49 | moduleName = moduleName.substring(1);
|
50 | }
|
51 | else if (moduleName.startsWith('/')) {
|
52 | moduleName = moduleName.substring(1);
|
53 | }
|
54 | if (removeExtension) {
|
55 | const extToRemove = ['js', 'ts', 'xml', 'html', 'css', 'scss'];
|
56 | const extensionRegEx = new RegExp(`(.*)\\.(?:${extToRemove.join('|')})`, 'i');
|
57 | moduleName = moduleName.replace(extensionRegEx, '$1');
|
58 | }
|
59 | return moduleName;
|
60 | }
|
61 | export function isFileOrResourcePath(path) {
|
62 | if (!types.isString(path)) {
|
63 | return false;
|
64 | }
|
65 | return (path.indexOf('~/') === 0 ||
|
66 | path.indexOf('/') === 0 ||
|
67 | path.indexOf(RESOURCE_PREFIX) === 0 ||
|
68 | path.indexOf(SYSTEM_PREFIX) === 0);
|
69 | }
|
70 | export function isFontIconURI(uri) {
|
71 | if (!types.isString(uri)) {
|
72 | return false;
|
73 | }
|
74 | const firstSegment = uri.trim().split('//')[0];
|
75 | return firstSegment && firstSegment.indexOf('font:') === 0;
|
76 | }
|
77 | export function isDataURI(uri) {
|
78 | if (!types.isString(uri)) {
|
79 | return false;
|
80 | }
|
81 | const firstSegment = uri.trim().split(',')[0];
|
82 | return firstSegment && firstSegment.indexOf('data:') === 0 && firstSegment.indexOf('base64') >= 0;
|
83 | }
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 | export function getFileExtension(path) {
|
90 | const dotIndex = path.lastIndexOf('.');
|
91 | if (dotIndex && dotIndex >= 0 && dotIndex < path.length) {
|
92 | return path.substring(dotIndex);
|
93 | }
|
94 | return '';
|
95 | }
|
96 | export function mergeSort(arr, compareFunc) {
|
97 | if (arr.length < 2) {
|
98 | return arr;
|
99 | }
|
100 | const middle = arr.length / 2;
|
101 | const left = arr.slice(0, middle);
|
102 | const right = arr.slice(middle, arr.length);
|
103 | return merge(mergeSort(left, compareFunc), mergeSort(right, compareFunc), compareFunc);
|
104 | }
|
105 | export function merge(left, right, compareFunc) {
|
106 | const result = [];
|
107 | while (left.length && right.length) {
|
108 | if (compareFunc(left[0], right[0]) <= 0) {
|
109 | result.push(left.shift());
|
110 | }
|
111 | else {
|
112 | result.push(right.shift());
|
113 | }
|
114 | }
|
115 | while (left.length) {
|
116 | result.push(left.shift());
|
117 | }
|
118 | while (right.length) {
|
119 | result.push(right.shift());
|
120 | }
|
121 | return result;
|
122 | }
|
123 | export function hasDuplicates(arr) {
|
124 | return arr.length !== eliminateDuplicates(arr).length;
|
125 | }
|
126 | export function eliminateDuplicates(arr) {
|
127 | return Array.from(new Set(arr));
|
128 | }
|
129 | export function executeOnMainThread(func) {
|
130 | if (isMainThread()) {
|
131 | return func();
|
132 | }
|
133 | else {
|
134 | dispatchToMainThread(func);
|
135 | }
|
136 | }
|
137 | export function executeOnUIThread(func) {
|
138 | dispatchToUIThread(func);
|
139 | }
|
140 | export function mainThreadify(func) {
|
141 | return function (...args) {
|
142 | const argsToPass = args;
|
143 | executeOnMainThread(() => func.apply(this, argsToPass));
|
144 | };
|
145 | }
|
146 | export function debounce(fn, delay = 300, { leading } = {}) {
|
147 | let timer;
|
148 | return (...args) => {
|
149 | if (timer === undefined && leading) {
|
150 | fn.apply(this, args);
|
151 | }
|
152 | clearTimeout(timer);
|
153 | timer = setTimeout(() => {
|
154 | fn.apply(this, args);
|
155 | timer = undefined;
|
156 | }, delay);
|
157 | };
|
158 | }
|
159 | export function throttle(fn, delay = 300) {
|
160 | let waiting = false;
|
161 | return function (...args) {
|
162 | if (!waiting) {
|
163 | fn.apply(this, args);
|
164 | waiting = true;
|
165 | setTimeout(function () {
|
166 | waiting = false;
|
167 | }, delay);
|
168 | }
|
169 | };
|
170 | }
|
171 | let throttledGC;
|
172 | let debouncedGC;
|
173 | export function queueGC(delay = 900, useThrottle) {
|
174 | |
175 |
|
176 |
|
177 |
|
178 | if (useThrottle) {
|
179 | if (!throttledGC) {
|
180 | throttledGC = new Map();
|
181 | }
|
182 | if (!throttledGC.get(delay)) {
|
183 | throttledGC.set(delay, throttle(() => GC(), delay));
|
184 | }
|
185 | throttledGC.get(delay)();
|
186 | }
|
187 | else {
|
188 | if (!debouncedGC) {
|
189 | debouncedGC = new Map();
|
190 | }
|
191 | if (!debouncedGC.get(delay)) {
|
192 | debouncedGC.set(delay, debounce(() => GC(), delay));
|
193 | }
|
194 | debouncedGC.get(delay)();
|
195 | }
|
196 | }
|
197 | export function isEmoji(value) {
|
198 |
|
199 |
|
200 | return emojiRegex().test(value);
|
201 | }
|
202 |
|
203 |
|
204 |
|
205 | export const CORE_ANIMATION_DEFAULTS = {
|
206 | duration: 0.35,
|
207 | spring: {
|
208 | tension: 140,
|
209 | friction: 10,
|
210 | mass: 1,
|
211 | velocity: 0,
|
212 | },
|
213 | };
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 | export function getDurationWithDampingFromSpring(springSettings) {
|
221 |
|
222 | const opt = {
|
223 | ...CORE_ANIMATION_DEFAULTS.spring,
|
224 | ...(springSettings || {}),
|
225 | };
|
226 | const damping = opt.friction / Math.sqrt(2 * opt.tension);
|
227 | const undampedFrequency = Math.sqrt(opt.tension / opt.mass);
|
228 |
|
229 |
|
230 |
|
231 |
|
232 | const epsilon = 0.001;
|
233 | let duration = 0;
|
234 | if (damping < 1) {
|
235 |
|
236 | const a = Math.sqrt(1 - Math.pow(damping, 2));
|
237 | const b = opt.velocity / (a * undampedFrequency);
|
238 | const c = damping / a;
|
239 | const d = -((b - c) / epsilon);
|
240 | if (d > 0) {
|
241 | duration = Math.log(d) / (damping * undampedFrequency);
|
242 | }
|
243 | }
|
244 | return {
|
245 | duration,
|
246 | damping,
|
247 | };
|
248 | }
|
249 |
|
\ | No newline at end of file |