esoftplay 0.0.124 → 0.0.125
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/bin/build.js +26 -27
- package/bin/cli.js +3 -3
- package/bin/router.js +4 -2
- package/esp.ts +10 -3
- package/global.ts +15 -6
- package/libs/worker.tsx +15 -135
- package/modules/lib/autoreload.ts +19 -20
- package/modules/lib/curl.ts +12 -12
- package/modules/lib/gradient.tsx +59 -0
- package/modules/lib/infinite.tsx +5 -4
- package/modules/lib/list.tsx +5 -3
- package/modules/lib/picture.tsx +2 -125
- package/modules/user/index.tsx +3 -26
- package/moment.ts +29 -4
- package/package.json +1 -1
package/bin/build.js
CHANGED
|
@@ -143,36 +143,35 @@ if (fs.existsSync(packjson)) {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
const easconfg = `{
|
|
146
|
-
"cli": {
|
|
147
|
-
|
|
148
|
-
},
|
|
149
|
-
"build": {
|
|
150
|
-
"development": {
|
|
151
|
-
"developmentClient": true,
|
|
152
|
-
"distribution": "internal",
|
|
153
|
-
"ios": {
|
|
154
|
-
"simulator": true,
|
|
155
|
-
"resourceClass": "m1-medium"
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
"preview": {
|
|
159
|
-
"distribution": "internal",
|
|
160
|
-
"ios": {
|
|
161
|
-
"simulator": true,
|
|
162
|
-
"resourceClass": "m1-medium"
|
|
163
|
-
}
|
|
146
|
+
"cli": {
|
|
147
|
+
"version": ">= 0.52.0"
|
|
164
148
|
},
|
|
165
|
-
"
|
|
166
|
-
"
|
|
167
|
-
|
|
168
|
-
"
|
|
149
|
+
"build": {
|
|
150
|
+
"development": {
|
|
151
|
+
"developmentClient": true,
|
|
152
|
+
"distribution": "internal",
|
|
153
|
+
"ios": {
|
|
154
|
+
"simulator": true
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
"preview": {
|
|
158
|
+
"distribution": "internal",
|
|
159
|
+
"ios": {
|
|
160
|
+
"simulator": true
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
"preview_build": {
|
|
164
|
+
"distribution": "internal",
|
|
165
|
+
"android": {
|
|
166
|
+
"buildType": "apk"
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"production": {
|
|
169
170
|
}
|
|
170
171
|
},
|
|
171
|
-
"
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
"production": {}
|
|
175
|
-
}
|
|
172
|
+
"submit": {
|
|
173
|
+
"production": {}
|
|
174
|
+
}
|
|
176
175
|
}`
|
|
177
176
|
|
|
178
177
|
fs.writeFile(easjson, easconfg, (err) => {
|
package/bin/cli.js
CHANGED
|
@@ -170,7 +170,7 @@ function jsEng(file, isHermes) {
|
|
|
170
170
|
return
|
|
171
171
|
}
|
|
172
172
|
let app = JSON.parse(txt)
|
|
173
|
-
app.expo.jsEngine = isHermes ? "hermes" : "
|
|
173
|
+
app.expo.jsEngine = isHermes ? "hermes" : "hermes"
|
|
174
174
|
fs.writeFileSync(file, JSON.stringify(app, undefined, 2))
|
|
175
175
|
} else {
|
|
176
176
|
consoleError(file)
|
|
@@ -669,8 +669,8 @@ function buildPrepare(include = true) {
|
|
|
669
669
|
comm.push(`cp -n ./node_modules/esoftplay/modules/${module}/* ./modules/${module}`)
|
|
670
670
|
}
|
|
671
671
|
});
|
|
672
|
-
comm.push('cp ./node_modules/esoftplay/libs/worker.tsx ./assets/')
|
|
673
|
-
comm.push('node ./node_modules/esoftplay/assets/prepare.mjs')
|
|
672
|
+
// comm.push('cp ./node_modules/esoftplay/libs/worker.tsx ./assets/')
|
|
673
|
+
// comm.push('node ./node_modules/esoftplay/assets/prepare.mjs')
|
|
674
674
|
consoleSucces("\n\nPLEASE COPY AND EXECUTE THE FOLLOWING COMMAND\n\n" + comm.join('\n') + "\n")
|
|
675
675
|
}
|
|
676
676
|
} else {
|
package/bin/router.js
CHANGED
|
@@ -429,14 +429,16 @@ declare module "esoftplay" {
|
|
|
429
429
|
backgroundWhite: string,
|
|
430
430
|
}
|
|
431
431
|
}
|
|
432
|
+
|
|
432
433
|
interface useGlobalReturn<T> {
|
|
433
|
-
useState: () => [T, (newState: T
|
|
434
|
-
get: () => T,
|
|
434
|
+
useState: () => [T, (newState: T) => void, () => void],
|
|
435
|
+
get: (param?: string, ...params: string[]) => T,
|
|
435
436
|
set: (x: T) => void,
|
|
436
437
|
reset: () => void,
|
|
437
438
|
connect: (props: useGlobalConnect<T>) => any,
|
|
438
439
|
useSelector: (selector: (state: T) => any) => any;
|
|
439
440
|
}
|
|
441
|
+
|
|
440
442
|
interface useGlobalOption {
|
|
441
443
|
persistKey?: string,
|
|
442
444
|
inFile?: boolean,
|
package/esp.ts
CHANGED
|
@@ -31,8 +31,6 @@ console.warn = (...arg) => {
|
|
|
31
31
|
};
|
|
32
32
|
LogBox.ignoreLogs(ignoreWarns);
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
34
|
let app = require('../../app.json');
|
|
37
35
|
let conf = require('../../config.json');
|
|
38
36
|
let lconf: any
|
|
@@ -41,6 +39,8 @@ try {
|
|
|
41
39
|
} catch (error) {
|
|
42
40
|
|
|
43
41
|
}
|
|
42
|
+
if (conf?.config?.isDebug == 0)
|
|
43
|
+
LogBox.ignoreAllLogs();
|
|
44
44
|
|
|
45
45
|
const esp = {
|
|
46
46
|
mergeDeep(target: any, ...sources: any[]) {
|
|
@@ -205,7 +205,14 @@ const esp = {
|
|
|
205
205
|
},
|
|
206
206
|
log(message?: any, ...optionalParams: any[]) {
|
|
207
207
|
if (esp.config("isDebug") == 1) {
|
|
208
|
-
|
|
208
|
+
let out = [message]
|
|
209
|
+
if (optionalParams)
|
|
210
|
+
out.push(...optionalParams)
|
|
211
|
+
out.forEach((x) => {
|
|
212
|
+
if (x != undefined)
|
|
213
|
+
console.log(JSON.stringify(x, undefined, 2), "\x1b[0m");
|
|
214
|
+
console.log(x, "\x1b[0m")
|
|
215
|
+
})
|
|
209
216
|
}
|
|
210
217
|
},
|
|
211
218
|
logColor: {
|
package/global.ts
CHANGED
|
@@ -6,9 +6,10 @@ import * as R from 'react';
|
|
|
6
6
|
import { fastFilter, fastLoop } from './fast';
|
|
7
7
|
const isEqual = require('react-fast-compare');
|
|
8
8
|
|
|
9
|
+
|
|
9
10
|
export interface useGlobalReturn<T> {
|
|
10
11
|
useState: () => [T, (newState: T) => void, () => void],
|
|
11
|
-
get: () => T,
|
|
12
|
+
get: (param?: string, ...params: string[]) => T,
|
|
12
13
|
set: (x: T) => void,
|
|
13
14
|
reset: () => void,
|
|
14
15
|
connect: (props: useGlobalConnect<T>) => any,
|
|
@@ -19,6 +20,7 @@ export interface useGlobalOption {
|
|
|
19
20
|
persistKey?: string,
|
|
20
21
|
inFile?: boolean,
|
|
21
22
|
listener?: (data: any) => void,
|
|
23
|
+
jsonBeautify?: boolean,
|
|
22
24
|
isUserData?: boolean
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -47,12 +49,19 @@ export default function useGlobalState<T>(initValue: T, o?: useGlobalOption): us
|
|
|
47
49
|
|
|
48
50
|
if (o?.persistKey) {
|
|
49
51
|
let persistKey = o?.persistKey
|
|
50
|
-
STORAGE.getItem(persistKey).then((p) => {
|
|
52
|
+
STORAGE.getItem(persistKey).then((p: any) => {
|
|
51
53
|
if (p) {
|
|
52
54
|
if (p != undefined && typeof p == 'string' && (p.startsWith("{") || p.startsWith("[")))
|
|
53
55
|
try { set(JSON.parse(p)) } catch (error) { }
|
|
54
|
-
else
|
|
55
|
-
|
|
56
|
+
else {
|
|
57
|
+
if (p == "true" || p == "false") {
|
|
58
|
+
try { /* @ts-ignore */ set(eval(p)) } catch (error) { }
|
|
59
|
+
} else if (isNaN(p)) {
|
|
60
|
+
try { /* @ts-ignore */ set(p) } catch (error) { }
|
|
61
|
+
} else {
|
|
62
|
+
try { /* @ts-ignore */ set(eval(p)) } catch (error) { }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
56
65
|
}
|
|
57
66
|
})
|
|
58
67
|
}
|
|
@@ -60,7 +69,7 @@ export default function useGlobalState<T>(initValue: T, o?: useGlobalOption): us
|
|
|
60
69
|
/* register to userData to automatically reset state and persist */
|
|
61
70
|
if (o?.isUserData) {
|
|
62
71
|
function resetFunction() {
|
|
63
|
-
|
|
72
|
+
del()
|
|
64
73
|
}
|
|
65
74
|
if (o?.persistKey) {
|
|
66
75
|
if (UserData)
|
|
@@ -79,7 +88,7 @@ export default function useGlobalState<T>(initValue: T, o?: useGlobalOption): us
|
|
|
79
88
|
switch (typeof ns) {
|
|
80
89
|
case 'object':
|
|
81
90
|
if (ns != null || ns != undefined)
|
|
82
|
-
data = JSON.stringify(ns)
|
|
91
|
+
data = o.jsonBeautify ? JSON.stringify(ns, undefined, 2) : JSON.stringify(ns)
|
|
83
92
|
break;
|
|
84
93
|
default:
|
|
85
94
|
data = String(ns)
|
package/libs/worker.tsx
CHANGED
|
@@ -1,166 +1,46 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import _global from "esoftplay/_global";
|
|
3
|
-
import React, { useRef } from "react";
|
|
4
|
-
import { Platform, View } from 'react-native';
|
|
5
|
-
import WebView from "react-native-webview";
|
|
1
|
+
import { useRef } from "react";
|
|
6
2
|
|
|
7
|
-
_global.WorkerBase = React.createRef()
|
|
8
|
-
_global.WorkerTasks = new Map()
|
|
9
|
-
_global.injectedJavaScripts = []
|
|
10
|
-
_global.WorkerReady = 0
|
|
11
|
-
_global.WorkerCount = 0
|
|
12
3
|
|
|
13
4
|
const Worker = {
|
|
14
5
|
delete(taskId: string) {
|
|
15
|
-
_global.WorkerTasks.delete(taskId)
|
|
16
6
|
},
|
|
17
7
|
useWorker(name: string, func: (...fparams: any[]) => Promise<any>): (params: any[], res: (data: any) => void) => void {
|
|
8
|
+
console.warn("Esoftplay Worker DEPRECATED, please remove from your code")
|
|
18
9
|
const ref = useRef(Worker.registerJobAsync(name, func)).current
|
|
19
10
|
return ref
|
|
20
11
|
},
|
|
21
12
|
registerJob(name: string, func: Function): (params: any[], res: (data: any) => void) => void {
|
|
22
|
-
|
|
23
|
-
const x = func.toString().replace('function', 'function ' + name)
|
|
24
|
-
_global.injectedJavaScripts.push(x)
|
|
25
|
-
Worker.dispatch(() => x, '', () => { })
|
|
13
|
+
console.warn("Esoftplay Worker DEPRECATED, please remove from your code");
|
|
26
14
|
return (params: (string | number | boolean)[], res: (data: string) => void) => {
|
|
27
|
-
|
|
28
|
-
if (Platform.Version <= 22) {
|
|
29
|
-
return res(func(...params))
|
|
30
|
-
}
|
|
31
|
-
Worker.dispatch(
|
|
32
|
-
(id: number) => {
|
|
33
|
-
let _params = params.map((param) => {
|
|
34
|
-
if (typeof param == 'string')
|
|
35
|
-
return `"` + param + `"`
|
|
36
|
-
return param
|
|
37
|
-
})
|
|
38
|
-
return (`window.ReactNativeWebView.postMessage(JSON.stringify({ data: ` + name + `(` + _params.join(", ") + `), id: ` + id + ` }));true;`)
|
|
39
|
-
}
|
|
40
|
-
, '', res)
|
|
15
|
+
return res(func(...params))
|
|
41
16
|
}
|
|
42
17
|
},
|
|
43
18
|
registerJobAsync(name: string, func: (...fparams: any[]) => Promise<any>): (params: any[], res: (data: any) => void) => void {
|
|
44
|
-
|
|
45
|
-
const x = func.toString().replace('function', 'function ' + name)
|
|
46
|
-
_global.injectedJavaScripts.push(x)
|
|
47
|
-
Worker.dispatch(() => x, '', () => { })
|
|
19
|
+
console.warn("Esoftplay Worker DEPRECATED, please remove from your code");
|
|
48
20
|
return (params: (string | number | boolean)[], res: (data: string) => void) => {
|
|
49
|
-
|
|
50
|
-
if (Platform.Version <= 22) {
|
|
51
|
-
(async () => res(await func(...params)))()
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
Worker.dispatch(
|
|
56
|
-
(id: number) => {
|
|
57
|
-
let _params = params.map((param) => {
|
|
58
|
-
if (typeof param == 'string')
|
|
59
|
-
return `"` + param + `"`
|
|
60
|
-
return param
|
|
61
|
-
})
|
|
62
|
-
return (`(async () => window.ReactNativeWebView.postMessage(JSON.stringify({ data: await ` + name + `(` + _params.join(", ") + `), id: ` + id + ` })))();true;`)
|
|
63
|
-
}
|
|
64
|
-
, '', res)
|
|
21
|
+
(async () => res(await func(...params)))()
|
|
65
22
|
}
|
|
66
23
|
},
|
|
67
24
|
objToString(data: any): string {
|
|
68
|
-
|
|
69
|
-
if (Platform.Version <= 22) {
|
|
70
|
-
return JSON.stringify(data)
|
|
71
|
-
}
|
|
72
|
-
return JSON.stringify(JSON.stringify(data)).slice(1, -1);
|
|
25
|
+
return JSON.stringify(data)
|
|
73
26
|
},
|
|
74
27
|
jobAsync(func: (...fparams: any[]) => Promise<any>, params: (string | number | boolean)[], res: (data: any) => void): void {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (Platform.Version <= 22) {
|
|
78
|
-
(async () => res(await func(...params)))()
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
Worker.dispatch(
|
|
82
|
-
(id: number) => {
|
|
83
|
-
const nameFunction = func.toString().replace('function', 'function tempFunction')
|
|
84
|
-
let _params = params.map((param) => {
|
|
85
|
-
if (typeof param == 'string')
|
|
86
|
-
return `"` + param + `"`
|
|
87
|
-
return param
|
|
88
|
-
})
|
|
89
|
-
return (`(async () => window.ReactNativeWebView.postMessage(JSON.stringify({ data: await ` + nameFunction + `(` + _params.join(", ") + `), id: ` + id + ` })))();true;`)
|
|
90
|
-
}
|
|
91
|
-
, '', res)
|
|
28
|
+
console.warn("Esoftplay Worker DEPRECATED, please remove from your code");
|
|
29
|
+
(async () => res(await func(...params)))()
|
|
92
30
|
},
|
|
93
31
|
job(func: Function, params: (string | number | boolean)[], res: (data: any) => void): void {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (Platform.Version <= 22) {
|
|
97
|
-
return res(func(...params))
|
|
98
|
-
}
|
|
99
|
-
Worker.dispatch(
|
|
100
|
-
(id: number) => {
|
|
101
|
-
const nameFunction = func.toString().replace('function', 'function tempFunction')
|
|
102
|
-
let _params = params.map((param) => {
|
|
103
|
-
if (typeof param == 'string')
|
|
104
|
-
return `"` + param + `"`
|
|
105
|
-
return param
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
const out = nameFunction + `\nwindow.ReactNativeWebView.postMessage(JSON.stringify({ data: tempFunction` + `(` + _params.join(",") + `), id: ` + id + ` }));true;`
|
|
109
|
-
return out
|
|
110
|
-
}
|
|
111
|
-
, '', res)
|
|
32
|
+
console.warn("Esoftplay Worker DEPRECATED, please remove from your code");
|
|
33
|
+
return res(func(...params))
|
|
112
34
|
},
|
|
113
35
|
dispatch(task: (id: number) => string, url: string, result: (r: string) => void): void {
|
|
114
|
-
|
|
115
|
-
_global.WorkerCount++
|
|
116
|
-
var _task = task(_global.WorkerCount)
|
|
117
|
-
_global.WorkerTasks.set(String(_global.WorkerCount), {
|
|
118
|
-
task: _task,
|
|
119
|
-
result: result
|
|
120
|
-
})
|
|
121
|
-
_global.WorkerBase?.current?.injectJavaScript?.(_task)
|
|
122
|
-
} else {
|
|
123
|
-
setTimeout(() => {
|
|
124
|
-
Worker.dispatch(task, url, result)
|
|
125
|
-
}, 1000);
|
|
126
|
-
}
|
|
36
|
+
|
|
127
37
|
},
|
|
128
38
|
onMessage(withRefName: string): any {
|
|
129
|
-
|
|
130
|
-
if (e.nativeEvent.data == withRefName) {
|
|
131
|
-
_global.WorkerReady += 1
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
const dt = e.nativeEvent.data
|
|
135
|
-
const x = JSON.parse(dt)
|
|
136
|
-
const itemTask = _global.WorkerTasks.get(String(x.id))
|
|
137
|
-
if (itemTask) {
|
|
138
|
-
itemTask.result(x.data)
|
|
139
|
-
Worker.delete(x.id)
|
|
140
|
-
}
|
|
141
|
-
}
|
|
39
|
+
|
|
142
40
|
},
|
|
143
41
|
Provider(props: any): any {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return props.children
|
|
147
|
-
}
|
|
148
|
-
return (
|
|
149
|
-
<View style={{ flex: 1 }} >
|
|
150
|
-
<View style={{ height: 0, width: 0 }} >
|
|
151
|
-
<WebView
|
|
152
|
-
ref={_global.WorkerBase}
|
|
153
|
-
style={{ width: 0, height: 0 }}
|
|
154
|
-
javaScriptEnabled={true}
|
|
155
|
-
injectedJavaScript={`\nwindow.ReactNativeWebView.postMessage("BaseWorkerIsReady")\n` + _global.injectedJavaScripts.join('\n') + '\ntrue;'}
|
|
156
|
-
originWhitelist={["*"]}
|
|
157
|
-
source={{ uri: esp.config("protocol") + "://" + esp.config("domain") + esp.config("uri") + "dummyPageToBypassCORS" }}
|
|
158
|
-
onMessage={Worker.onMessage('BaseWorkerIsReady')}
|
|
159
|
-
/>
|
|
160
|
-
</View>
|
|
161
|
-
{props.children}
|
|
162
|
-
</View>
|
|
163
|
-
)
|
|
42
|
+
console.warn("Esoftplay Worker DEPRECATED, please remove from your code")
|
|
43
|
+
return props.children
|
|
164
44
|
}
|
|
165
45
|
}
|
|
166
46
|
export default Worker
|
|
@@ -2,25 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
import { InteractionManager } from 'react-native'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
updater = undefined
|
|
12
|
-
}
|
|
13
|
-
updater = setInterval(() => {
|
|
14
|
-
InteractionManager.runAfterInteractions(() => {
|
|
15
|
-
callback()
|
|
16
|
-
});
|
|
17
|
-
}, duration || 6000)
|
|
18
|
-
},
|
|
19
|
-
clear(): void {
|
|
20
|
-
if (updater != undefined) {
|
|
21
|
-
clearInterval(updater)
|
|
22
|
-
updater = undefined
|
|
23
|
-
}
|
|
5
|
+
let updater: any
|
|
6
|
+
export default class m {
|
|
7
|
+
static set(callback: () => void, duration?: number): void {
|
|
8
|
+
if (updater != undefined) {
|
|
9
|
+
clearInterval(updater)
|
|
10
|
+
updater = undefined
|
|
24
11
|
}
|
|
12
|
+
updater = setInterval(() => {
|
|
13
|
+
InteractionManager.runAfterInteractions(() => {
|
|
14
|
+
callback()
|
|
15
|
+
});
|
|
16
|
+
}, duration || 6000)
|
|
25
17
|
}
|
|
26
|
-
|
|
18
|
+
|
|
19
|
+
static clear(): void {
|
|
20
|
+
if (updater != undefined) {
|
|
21
|
+
clearInterval(updater)
|
|
22
|
+
updater = undefined
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
package/modules/lib/curl.ts
CHANGED
|
@@ -6,8 +6,8 @@ import { LibNet_status } from 'esoftplay/cache/lib/net_status/import';
|
|
|
6
6
|
import { LibProgress } from 'esoftplay/cache/lib/progress/import';
|
|
7
7
|
import { LibToastProperty } from 'esoftplay/cache/lib/toast/import';
|
|
8
8
|
import { LibUtils } from 'esoftplay/cache/lib/utils/import';
|
|
9
|
-
import esp from 'esoftplay/esp';
|
|
10
9
|
import { reportApiError } from "esoftplay/error";
|
|
10
|
+
import esp from 'esoftplay/esp';
|
|
11
11
|
import Constants from 'expo-constants';
|
|
12
12
|
|
|
13
13
|
//api_logger_import
|
|
@@ -288,6 +288,7 @@ export default class m {
|
|
|
288
288
|
esp.log(this.url + this.uri, options)
|
|
289
289
|
this.fetchConf = { url: this.url + this.uri, options: options }
|
|
290
290
|
this.initTimeout(this.timeout);
|
|
291
|
+
//api_init_time
|
|
291
292
|
fetch(this.url + this.uri, options).then(async (res) => {
|
|
292
293
|
this.cancelTimeout()
|
|
293
294
|
var resText = await res.text()
|
|
@@ -301,6 +302,7 @@ export default class m {
|
|
|
301
302
|
LibProgress.hide()
|
|
302
303
|
this.onError(resText)
|
|
303
304
|
}
|
|
305
|
+
//api_logger
|
|
304
306
|
}).catch((e) => {
|
|
305
307
|
this.cancelTimeout()
|
|
306
308
|
LibProgress.hide()
|
|
@@ -441,16 +443,14 @@ export default class m {
|
|
|
441
443
|
LibProgress.hide()
|
|
442
444
|
}
|
|
443
445
|
|
|
444
|
-
protected getTimeByTimeZone(
|
|
445
|
-
|
|
446
|
-
let
|
|
447
|
-
let
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
let time = new Date().getTime() + (diff * 60 * 1000 * -1);
|
|
454
|
-
return time;
|
|
446
|
+
protected getTimeByTimeZone(GMT: number): number {
|
|
447
|
+
const date = new Date()
|
|
448
|
+
let currentOffsetInMinutes = date.getTimezoneOffset();
|
|
449
|
+
let currentOffsetInHours = currentOffsetInMinutes / 60;
|
|
450
|
+
let currentGMT = -currentOffsetInHours;
|
|
451
|
+
let currentOffset = currentGMT * 60 * 60 * 1000;
|
|
452
|
+
let targetOffset = 7/* Asia/Jakarta */ * 60 * 60 * 1000;
|
|
453
|
+
let gmtDiff = targetOffset - currentOffset;
|
|
454
|
+
return date.getTime() + gmtDiff
|
|
455
455
|
}
|
|
456
456
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// withHooks
|
|
2
|
+
|
|
3
|
+
import { LinearGradient } from 'expo-linear-gradient';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
export interface LibGradientArgs {
|
|
7
|
+
|
|
8
|
+
}
|
|
9
|
+
export interface LibGradientProps {
|
|
10
|
+
style?: any,
|
|
11
|
+
children: any,
|
|
12
|
+
direction: "top-to-bottom" | "bottom-to-top" | "left-to-right" | "right-to-left" | "top-left-to-bottom-right" | "bottom-right-to-top-left" | "top-right-to-bottom-left" | "bottom-left-to-top-right",
|
|
13
|
+
colors: string[]
|
|
14
|
+
}
|
|
15
|
+
const direction = {
|
|
16
|
+
"top-to-bottom": {
|
|
17
|
+
start: { x: 0.5, y: 0 },
|
|
18
|
+
end: { x: 0.5, y: 1 }
|
|
19
|
+
},
|
|
20
|
+
"bottom-to-top": {
|
|
21
|
+
start: { x: 0.5, y: 1 },
|
|
22
|
+
end: { x: 0.5, y: 0 }
|
|
23
|
+
},
|
|
24
|
+
"left-to-right": {
|
|
25
|
+
start: { x: 0, y: 0.5 },
|
|
26
|
+
end: { x: 1, y: 0.5 }
|
|
27
|
+
},
|
|
28
|
+
"right-to-left": {
|
|
29
|
+
start: { x: 1, y: 0.5 },
|
|
30
|
+
end: { x: 0, y: 0.5 }
|
|
31
|
+
},
|
|
32
|
+
"top-left-to-bottom-right": {
|
|
33
|
+
start: { x: 0, y: 0 },
|
|
34
|
+
end: { x: 1, y: 1 }
|
|
35
|
+
},
|
|
36
|
+
"bottom-right-to-top-left": {
|
|
37
|
+
start: { x: 1, y: 1 },
|
|
38
|
+
end: { x: 0, y: 0 }
|
|
39
|
+
},
|
|
40
|
+
"top-right-to-bottom-left": {
|
|
41
|
+
start: { x: 1, y: 0 },
|
|
42
|
+
end: { x: 0, y: 1 }
|
|
43
|
+
},
|
|
44
|
+
"bottom-left-to-top-right": {
|
|
45
|
+
start: { x: 0, y: 1 },
|
|
46
|
+
end: { x: 1, y: 0 }
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default function m(props: LibGradientProps): any {
|
|
51
|
+
return (
|
|
52
|
+
<LinearGradient
|
|
53
|
+
colors={props.colors}
|
|
54
|
+
style={props.style}
|
|
55
|
+
{...direction[props.direction]} >
|
|
56
|
+
{props.children}
|
|
57
|
+
</LinearGradient>
|
|
58
|
+
)
|
|
59
|
+
}
|
package/modules/lib/infinite.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// noPage
|
|
2
|
-
|
|
2
|
+
import { FlashList } from "@shopify/flash-list";
|
|
3
3
|
import { LibComponent } from 'esoftplay/cache/lib/component/import';
|
|
4
4
|
import { LibCurl } from 'esoftplay/cache/lib/curl/import';
|
|
5
5
|
import { LibListItemLayout } from 'esoftplay/cache/lib/list/import';
|
|
@@ -10,7 +10,7 @@ import esp from 'esoftplay/esp';
|
|
|
10
10
|
|
|
11
11
|
import React from 'react';
|
|
12
12
|
import isEqual from 'react-fast-compare';
|
|
13
|
-
import {
|
|
13
|
+
import { View } from 'react-native';
|
|
14
14
|
|
|
15
15
|
export interface LibInfiniteProps {
|
|
16
16
|
url: string,
|
|
@@ -66,7 +66,7 @@ export default class m extends LibComponent<LibInfiniteProps, LibInfiniteState>{
|
|
|
66
66
|
isStop: boolean = false
|
|
67
67
|
page: number | undefined = 0
|
|
68
68
|
pages: number[]
|
|
69
|
-
flatlist = React.createRef<
|
|
69
|
+
flatlist = React.createRef<FlashList<View>>()
|
|
70
70
|
|
|
71
71
|
constructor(props: LibInfiniteProps) {
|
|
72
72
|
super(props);
|
|
@@ -179,7 +179,7 @@ export default class m extends LibComponent<LibInfiniteProps, LibInfiniteState>{
|
|
|
179
179
|
const { data, error } = this.state
|
|
180
180
|
const { errorView, refreshEnabled } = this.props
|
|
181
181
|
// const AutoLayoutViewNativeComponent = require("@shopify/flash-list/src/native/auto-layout/AutoLayoutViewNativeComponent")
|
|
182
|
-
const List = /* !!AutoLayoutViewNativeComponent ? FlashList : */
|
|
182
|
+
const List = /* !!AutoLayoutViewNativeComponent ? FlashList : */ FlashList
|
|
183
183
|
return (
|
|
184
184
|
<View style={{ flex: 1 }} >
|
|
185
185
|
{
|
|
@@ -205,6 +205,7 @@ export default class m extends LibComponent<LibInfiniteProps, LibInfiniteState>{
|
|
|
205
205
|
}
|
|
206
206
|
showsHorizontalScrollIndicator={false}
|
|
207
207
|
showsVerticalScrollIndicator={false}
|
|
208
|
+
estimatedItemSize={this.props.staticHeight || 100}
|
|
208
209
|
initialNumToRender={5}
|
|
209
210
|
maxToRenderPerBatch={10}
|
|
210
211
|
windowSize={10}
|
package/modules/lib/list.tsx
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
//
|
|
5
|
+
import { FlashList } from "@shopify/flash-list";
|
|
5
6
|
import { LibComponent } from 'esoftplay/cache/lib/component/import';
|
|
6
7
|
import React from "react";
|
|
7
|
-
import {
|
|
8
|
+
import { View } from 'react-native';
|
|
8
9
|
|
|
9
10
|
export interface LibListItemLayout {
|
|
10
11
|
length: number,
|
|
@@ -50,7 +51,7 @@ export interface LibListState {
|
|
|
50
51
|
export default class m extends LibComponent<LibListProps, LibListState> {
|
|
51
52
|
|
|
52
53
|
view: any = React.createRef()
|
|
53
|
-
flatlist = React.createRef<
|
|
54
|
+
flatlist = React.createRef<FlashList<View>>()
|
|
54
55
|
constructor(props: LibListProps) {
|
|
55
56
|
super(props);
|
|
56
57
|
this.scrollToIndex = this.scrollToIndex.bind(this);
|
|
@@ -77,7 +78,7 @@ export default class m extends LibComponent<LibListProps, LibListState> {
|
|
|
77
78
|
return ({ getItemLayout: (data, index) => this.props.staticHeight ? ({ length: this.props.staticHeight, offset: this.props.staticHeight, index: index }) : undefined })
|
|
78
79
|
}
|
|
79
80
|
// const AutoLayoutViewNativeComponent = require("@shopify/flash-list/src/native/auto-layout/AutoLayoutViewNativeComponent")
|
|
80
|
-
const List = /* !!AutoLayoutViewNativeComponent ? FlashList : */
|
|
81
|
+
const List = /* !!AutoLayoutViewNativeComponent ? FlashList : */ FlashList
|
|
81
82
|
return (
|
|
82
83
|
<View ref={(e) => this.view = e} style={[{ flex: 1 }]} >
|
|
83
84
|
<List
|
|
@@ -89,6 +90,7 @@ export default class m extends LibComponent<LibListProps, LibListState> {
|
|
|
89
90
|
refreshing={false}
|
|
90
91
|
nestedScrollEnabled
|
|
91
92
|
initialNumToRender={5}
|
|
93
|
+
estimatedItemSize={this.props.staticHeight || 100}
|
|
92
94
|
maxToRenderPerBatch={10}
|
|
93
95
|
windowSize={10}
|
|
94
96
|
{...this.props}
|
package/modules/lib/picture.tsx
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
// withHooks
|
|
2
2
|
// noPage
|
|
3
|
-
import
|
|
4
|
-
import { LibStyle } from 'esoftplay/cache/lib/style/import';
|
|
5
|
-
import { LibWorkloop } from 'esoftplay/cache/lib/workloop/import';
|
|
6
|
-
import Worker from 'esoftplay/libs/worker';
|
|
7
|
-
import * as FileSystem from 'expo-file-system';
|
|
8
|
-
import React, { useLayoutEffect } from 'react';
|
|
9
|
-
import { PixelRatio, Platform, View } from 'react-native';
|
|
3
|
+
import React from 'react';
|
|
10
4
|
import FastImage from 'react-native-fast-image';
|
|
11
|
-
const sh = require("shorthash")
|
|
12
5
|
|
|
13
6
|
export interface LibPictureSource {
|
|
14
7
|
uri: string
|
|
@@ -21,74 +14,7 @@ export interface LibPictureProps {
|
|
|
21
14
|
onError?: () => void,
|
|
22
15
|
}
|
|
23
16
|
|
|
24
|
-
const CACHE_DIR = `${FileSystem.cacheDirectory}lib-picture-cache/`;
|
|
25
|
-
|
|
26
|
-
(() => {
|
|
27
|
-
try {
|
|
28
|
-
FileSystem.makeDirectoryAsync(CACHE_DIR).then().catch(e => { });
|
|
29
|
-
} catch (e) {
|
|
30
|
-
// do nothing
|
|
31
|
-
}
|
|
32
|
-
})()
|
|
33
|
-
|
|
34
|
-
const getCacheEntry = async (uri: string, toSize: number): Promise<{ exists: boolean; path: string }> => {
|
|
35
|
-
const path = `${CACHE_DIR}${sh.unique(uri)}-${toSize}.png`;
|
|
36
|
-
const info = await FileSystem.getInfoAsync(path);
|
|
37
|
-
const { exists } = info;
|
|
38
|
-
return { exists, path };
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const fetchPicture = Worker.registerJobAsync('lib_picture_fetch', (url: string, toSize: number) => {
|
|
42
|
-
'show source';
|
|
43
|
-
return new Promise((resolve, reject) => {
|
|
44
|
-
'show source';
|
|
45
|
-
fetch(url, { mode: 'cors' })
|
|
46
|
-
.then(response => response.blob())
|
|
47
|
-
.then(blob => {
|
|
48
|
-
let reader = new FileReader();
|
|
49
|
-
reader.onload = function () {
|
|
50
|
-
let img = document.createElement('img');
|
|
51
|
-
img.onload = function () {
|
|
52
|
-
let wantedMaxSize = toSize
|
|
53
|
-
let rawheight = img.height
|
|
54
|
-
let rawwidth = img.width
|
|
55
|
-
let wantedheight = 0
|
|
56
|
-
let wantedwidth = 0
|
|
57
|
-
let ratio = rawwidth / rawheight
|
|
58
|
-
if (Math.max(rawheight, rawwidth) > wantedMaxSize) {
|
|
59
|
-
if (rawheight > rawwidth) {
|
|
60
|
-
wantedwidth = wantedMaxSize * ratio;
|
|
61
|
-
wantedheight = wantedMaxSize;
|
|
62
|
-
} else {
|
|
63
|
-
wantedwidth = wantedMaxSize;
|
|
64
|
-
wantedheight = wantedMaxSize / ratio;
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
wantedwidth = rawwidth
|
|
68
|
-
wantedheight = rawheight
|
|
69
|
-
}
|
|
70
|
-
let canvas = document.createElement('canvas');
|
|
71
|
-
let ctx = canvas.getContext('2d');
|
|
72
|
-
canvas.width = wantedwidth;
|
|
73
|
-
canvas.height = wantedheight;
|
|
74
|
-
//@ts-ignore
|
|
75
|
-
ctx.drawImage(this, 0, 0, wantedwidth, wantedheight);
|
|
76
|
-
let x = canvas.toDataURL();
|
|
77
|
-
resolve(x.replace("data:image/png;base64,", ""))
|
|
78
|
-
}
|
|
79
|
-
img.src = String(reader.result)
|
|
80
|
-
};
|
|
81
|
-
reader.readAsDataURL(blob);
|
|
82
|
-
});
|
|
83
|
-
})
|
|
84
|
-
})
|
|
85
|
-
|
|
86
17
|
export default function m(props: LibPictureProps): any {
|
|
87
|
-
const [uri, setUri] = useSafeState('')
|
|
88
|
-
let b_uri = props?.source?.uri?.replace?.('://api.', '://')
|
|
89
|
-
b_uri = b_uri?.replace?.('://data.', '://')
|
|
90
|
-
let { width, height } = props.style
|
|
91
|
-
const valid = b_uri?.includes?.(esp.config('domain'))
|
|
92
18
|
|
|
93
19
|
let resizeMode
|
|
94
20
|
if (props?.style?.resizeMode == 'cover')
|
|
@@ -102,54 +28,5 @@ export default function m(props: LibPictureProps): any {
|
|
|
102
28
|
else
|
|
103
29
|
resizeMode = FastImage.resizeMode.cover
|
|
104
30
|
|
|
105
|
-
|
|
106
|
-
if (width) {
|
|
107
|
-
height = width
|
|
108
|
-
} else {
|
|
109
|
-
width = height
|
|
110
|
-
}
|
|
111
|
-
console.warn("Width and Height is Required");
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
useLayoutEffect(() => {
|
|
115
|
-
if (!valid || (Platform.OS == 'android' && Platform.Version <= 22)) {
|
|
116
|
-
return
|
|
117
|
-
}
|
|
118
|
-
if (b_uri) {
|
|
119
|
-
let toSize = Math.max(width, height)
|
|
120
|
-
toSize = isNaN(toSize) ? LibStyle.width * 0.5 : toSize
|
|
121
|
-
getCacheEntry(b_uri, toSize).then(({ path, exists }) => {
|
|
122
|
-
if (exists) {
|
|
123
|
-
setUri(path)
|
|
124
|
-
} else {
|
|
125
|
-
fetchPicture([b_uri, PixelRatio.getPixelSizeForLayoutSize(toSize)], (uri) => {
|
|
126
|
-
setUri("data:image/png;base64," + uri)
|
|
127
|
-
if (!props.noCache)
|
|
128
|
-
LibWorkloop.execNextTix(FileSystem.writeAsStringAsync, [path, uri, { encoding: "base64" }])
|
|
129
|
-
})
|
|
130
|
-
}
|
|
131
|
-
})
|
|
132
|
-
}
|
|
133
|
-
}, [props?.source?.uri])
|
|
134
|
-
|
|
135
|
-
if (!valid || (Platform.Version <= 22 && Platform.OS == 'android')) {
|
|
136
|
-
if (typeof props.source != 'number' && !b_uri) {
|
|
137
|
-
return <View style={props.style} />
|
|
138
|
-
}
|
|
139
|
-
return <FastImage {...props} resizeMode={resizeMode} />
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (!valid || (!props.source.hasOwnProperty("uri"))) {
|
|
143
|
-
return <FastImage {...props} resizeMode={resizeMode} />
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (uri == '') {
|
|
147
|
-
return (
|
|
148
|
-
<View style={[{ backgroundColor: '#f1f2f3', borderRadius: 10 }, props.style]} />
|
|
149
|
-
)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return (
|
|
153
|
-
<FastImage key={b_uri + uri} {...props} source={{ uri: uri }} style={props.style} resizeMode={resizeMode} />
|
|
154
|
-
)
|
|
31
|
+
return <FastImage {...props} resizeMode={resizeMode} />
|
|
155
32
|
}
|
package/modules/user/index.tsx
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// noPage
|
|
3
3
|
import { esp, useSafeState } from 'esoftplay';
|
|
4
4
|
import { LibDialog } from 'esoftplay/cache/lib/dialog/import';
|
|
5
|
+
import { LibIcon } from 'esoftplay/cache/lib/icon/import';
|
|
5
6
|
import { LibImage } from 'esoftplay/cache/lib/image/import';
|
|
6
7
|
import { LibNet_status } from 'esoftplay/cache/lib/net_status/import';
|
|
7
8
|
import { LibProgress } from 'esoftplay/cache/lib/progress/import';
|
|
@@ -14,14 +15,12 @@ import Navs from 'esoftplay/cache/navs';
|
|
|
14
15
|
import { UseDeeplink } from 'esoftplay/cache/use/deeplink/import';
|
|
15
16
|
import { UserClass } from 'esoftplay/cache/user/class/import';
|
|
16
17
|
import { UserHook } from 'esoftplay/cache/user/hook/import';
|
|
17
|
-
import { LibIcon } from 'esoftplay/cache/lib/icon/import';
|
|
18
18
|
import { UserLoading } from 'esoftplay/cache/user/loading/import';
|
|
19
19
|
import { UserRoutes } from 'esoftplay/cache/user/routes/import';
|
|
20
20
|
import useGlobalState from 'esoftplay/global';
|
|
21
|
-
import _global from 'esoftplay/_global';
|
|
22
21
|
import * as Font from "expo-font";
|
|
23
22
|
import React, { useEffect, useLayoutEffect } from 'react';
|
|
24
|
-
import { Platform, Pressable,
|
|
23
|
+
import { Platform, Pressable, View } from "react-native";
|
|
25
24
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
26
25
|
|
|
27
26
|
export interface UserIndexProps {
|
|
@@ -46,18 +45,6 @@ function setFonts(): Promise<void> {
|
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
function isWorkerReady(onReady: () => void): void {
|
|
51
|
-
// @ts-ignore
|
|
52
|
-
if (_global.WorkerReady < 1) {
|
|
53
|
-
|
|
54
|
-
setTimeout(() => isWorkerReady(onReady), 10)
|
|
55
|
-
} else {
|
|
56
|
-
onReady()
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
48
|
const route = useGlobalState<any>(undefined, { persistKey: 'user_index_routes_initial' })
|
|
62
49
|
export default function m(props: UserIndexProps): any {
|
|
63
50
|
const [loading, setLoading] = useSafeState(true)
|
|
@@ -77,7 +64,7 @@ export default function m(props: UserIndexProps): any {
|
|
|
77
64
|
}
|
|
78
65
|
|
|
79
66
|
useLayoutEffect(() => {
|
|
80
|
-
let limitReady =
|
|
67
|
+
let limitReady = 2
|
|
81
68
|
|
|
82
69
|
if (esp.config("asyncWorker") == true) {
|
|
83
70
|
limitReady = 2
|
|
@@ -89,16 +76,6 @@ export default function m(props: UserIndexProps): any {
|
|
|
89
76
|
}
|
|
90
77
|
}
|
|
91
78
|
|
|
92
|
-
if (limitReady == 3) {
|
|
93
|
-
|
|
94
|
-
isWorkerReady(() => {
|
|
95
|
-
ready.current += 1
|
|
96
|
-
if (ready.current >= limitReady) {
|
|
97
|
-
setLoading(false)
|
|
98
|
-
}
|
|
99
|
-
})
|
|
100
|
-
}
|
|
101
|
-
|
|
102
79
|
(async () => {
|
|
103
80
|
await setFonts()
|
|
104
81
|
ready.current += 1
|
package/moment.ts
CHANGED
|
@@ -16,6 +16,30 @@ const dayjsType: any = ["day", "week", "month", "quarter", "year", "hour", "minu
|
|
|
16
16
|
function isNumeric(n) {
|
|
17
17
|
return !isNaN(parseFloat(n)) && isFinite(n);
|
|
18
18
|
}
|
|
19
|
+
export function setTimeOffset(date?: string | Date | any): Date {
|
|
20
|
+
const _date = (date instanceof Date ? date : (typeof date == 'string' ? new Date(date) : new Date()))
|
|
21
|
+
let currentOffsetInMinutes = _date.getTimezoneOffset();
|
|
22
|
+
let currentOffsetInHours = currentOffsetInMinutes / 60;
|
|
23
|
+
let currentGMT = -currentOffsetInHours;
|
|
24
|
+
let currentOffset = currentGMT * 60 * 60 * 1000;
|
|
25
|
+
let targetOffset = 7/* Asia/Jakarta */ * 60 * 60 * 1000;
|
|
26
|
+
let gmtDiff = targetOffset - currentOffset;
|
|
27
|
+
let timeWithOffset = new Date(_date.getTime() + gmtDiff);
|
|
28
|
+
return timeWithOffset
|
|
29
|
+
}
|
|
30
|
+
export function resetTimeOffset(date: Date): Date {
|
|
31
|
+
if (!(date instanceof Date)) {
|
|
32
|
+
date = dayjs(date).toDate()
|
|
33
|
+
}
|
|
34
|
+
let currentOffsetInMinutes = date.getTimezoneOffset();
|
|
35
|
+
let currentOffsetInHours = currentOffsetInMinutes / 60;
|
|
36
|
+
let currentGMT = -currentOffsetInHours;
|
|
37
|
+
let currentOffset = currentGMT * 60 * 60 * 1000;
|
|
38
|
+
let targetOffset = 7/* Asia/Jakarta */ * 60 * 60 * 1000;
|
|
39
|
+
let gmtDiff = targetOffset - currentOffset;
|
|
40
|
+
let originalTime = new Date(date.getTime() - gmtDiff);
|
|
41
|
+
return originalTime;
|
|
42
|
+
}
|
|
19
43
|
|
|
20
44
|
export default function moment(date?: string | Date | any) {
|
|
21
45
|
let _date = isNumeric(date) ? new Date(date * 1000) : date
|
|
@@ -40,11 +64,12 @@ export default function moment(date?: string | Date | any) {
|
|
|
40
64
|
},
|
|
41
65
|
/* last chain */
|
|
42
66
|
fromNow: () => {
|
|
43
|
-
const out = dayjs(_date).fromNow()
|
|
67
|
+
const out = dayjs(resetTimeOffset(_date)).fromNow()
|
|
44
68
|
return out
|
|
45
69
|
},
|
|
46
|
-
format: (custom: string) => {
|
|
47
|
-
const
|
|
70
|
+
format: (custom: string, ignoreTimezone?: boolean) => {
|
|
71
|
+
const _d = ignoreTimezone ? _date : resetTimeOffset(_date)
|
|
72
|
+
const out = dayjs(_d).format(custom)
|
|
48
73
|
return out
|
|
49
74
|
},
|
|
50
75
|
toDate: () => {
|
|
@@ -52,7 +77,7 @@ export default function moment(date?: string | Date | any) {
|
|
|
52
77
|
return out
|
|
53
78
|
},
|
|
54
79
|
toMiliseconds: () => {
|
|
55
|
-
const out = String(dayjs(_date).valueOf())
|
|
80
|
+
const out = String(dayjs(resetTimeOffset(_date)).valueOf())
|
|
56
81
|
return out
|
|
57
82
|
},
|
|
58
83
|
duration: (other_date: string | Date) => {
|