esoftplay 0.0.141 → 0.0.142-b
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 +6 -4
- package/error.ts +15 -6
- package/modules/lib/autoreload.ts +3 -0
- package/modules/lib/carrousel.tsx +1 -0
- package/modules/lib/carrousel_snap.tsx +1 -0
- package/modules/lib/collaps.tsx +3 -2
- package/modules/lib/component.tsx +1 -0
- package/modules/lib/compose.tsx +178 -0
- package/modules/lib/curl.ts +1 -1
- package/modules/lib/custom.tsx +27 -20
- package/modules/lib/fadescroll.tsx +50 -0
- package/modules/lib/image.tsx +12 -12
- package/modules/lib/image_crop.tsx +64 -58
- package/modules/lib/infinite.tsx +2 -0
- package/modules/lib/keyboard_avoid.tsx +4 -62
- package/modules/lib/picture.tsx +9 -8
- package/modules/lib/toast.tsx +13 -6
- package/modules/lib/version.tsx +10 -7
- package/modules/lib/version_view.tsx +34 -0
- package/modules/main/index.tsx +1 -1
- package/modules/use/deeplink.ts +4 -2
- package/modules/user/data.ts +2 -0
- package/modules/user/hook.tsx +1 -0
- package/modules/user/index.tsx +27 -21
- package/modules/user/loading.tsx +1 -0
- package/modules/user/notification.tsx +1 -0
- package/modules/user/notification_item.tsx +1 -0
- package/modules/user/routes.ts +4 -0
- package/package.json +1 -1
- package/render.tsx +11 -1
- package/timeout.ts +6 -0
package/bin/build.js
CHANGED
|
@@ -234,7 +234,7 @@ if (fs.existsSync(packjson)) {
|
|
|
234
234
|
"lib": [\n\
|
|
235
235
|
"es2017"\n\
|
|
236
236
|
],\n\
|
|
237
|
-
"module": "
|
|
237
|
+
"module": "ES2020",\n\
|
|
238
238
|
"moduleResolution": "node", \n\
|
|
239
239
|
"noEmitHelpers": true,\n\
|
|
240
240
|
"noImplicitReturns": true,\n\
|
|
@@ -278,9 +278,9 @@ yarn-error.log\n\
|
|
|
278
278
|
const AppJS = `import { LibNotification } from 'esoftplay/cache/lib/notification/import';
|
|
279
279
|
import { UserIndex } from 'esoftplay/cache/user/index/import';
|
|
280
280
|
import * as Notifications from 'expo-notifications';
|
|
281
|
-
import {
|
|
281
|
+
import { enableFreeze, enableScreens } from 'react-native-screens';
|
|
282
282
|
|
|
283
|
-
|
|
283
|
+
enableFreeze()
|
|
284
284
|
enableScreens()
|
|
285
285
|
|
|
286
286
|
Notifications.addNotificationResponseReceivedListener(x => LibNotification.onAction(x));
|
|
@@ -305,6 +305,7 @@ export default UserIndex`;
|
|
|
305
305
|
'expo-dev-client',
|
|
306
306
|
'expo-file-system',
|
|
307
307
|
'expo-font',
|
|
308
|
+
'expo-image',
|
|
308
309
|
'expo-image-manipulator',
|
|
309
310
|
'expo-image-picker',
|
|
310
311
|
'expo-linear-gradient',
|
|
@@ -313,13 +314,14 @@ export default UserIndex`;
|
|
|
313
314
|
'expo-status-bar',
|
|
314
315
|
'expo-splash-screen',
|
|
315
316
|
'expo-secure-store',
|
|
317
|
+
// 'expo-sqlite',
|
|
316
318
|
'expo-updates',
|
|
317
319
|
'immhelper',
|
|
318
320
|
'dayjs',
|
|
319
321
|
'react-fast-compare',
|
|
320
322
|
'react-native-gesture-handler',
|
|
321
323
|
'react-native-awesome-gallery',
|
|
322
|
-
'react-native-fast-image',
|
|
324
|
+
// 'react-native-fast-image',
|
|
323
325
|
'react-native-keyboard-controller',
|
|
324
326
|
'react-native-mmkv',
|
|
325
327
|
'react-native-pan-pinch-view',
|
package/error.ts
CHANGED
|
@@ -14,14 +14,15 @@ function getTime() {
|
|
|
14
14
|
const isoStringWithGMTPlus7 = new Date(adjustedDate).toISOString();
|
|
15
15
|
return isoStringWithGMTPlus7.replace('T', ' ').replace(/\.[0-9]+Z/g, "")
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
const defaultErrorHandler = ErrorUtils?.getGlobalHandler?.()
|
|
18
18
|
|
|
19
19
|
const myErrorHandler = (e: any, isFatal: any) => {
|
|
20
|
-
if (!
|
|
20
|
+
if (!__DEV__)
|
|
21
21
|
setError(e)
|
|
22
|
-
|
|
22
|
+
defaultErrorHandler?.(e, isFatal)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/error.md#setError) untuk melihat dokumentasi*/
|
|
25
26
|
export function setError(error?: any) {
|
|
26
27
|
const config = esp?.config?.();
|
|
27
28
|
const routes = UserRoutes?.state()?.get?.();
|
|
@@ -42,6 +43,7 @@ export function setError(error?: any) {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
|
|
46
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/error.md#reportApiError) untuk melihat dokumentasi*/
|
|
45
47
|
export function reportApiError(fetch: any, error: any) {
|
|
46
48
|
let routes = UserRoutes?.state?.()?.get?.()
|
|
47
49
|
let lastIndex = routes?.routes?.length - 1 ?? 0
|
|
@@ -59,7 +61,7 @@ export function reportApiError(fetch: any, error: any) {
|
|
|
59
61
|
'fetch: ' + String(JSON.stringify(fetch || {}, undefined, 2)).replace(/[\[\]\{\}\"]+/g, ''),
|
|
60
62
|
].join('\n')
|
|
61
63
|
|
|
62
|
-
if (
|
|
64
|
+
if (__DEV__) {
|
|
63
65
|
let post = {
|
|
64
66
|
text: msg,
|
|
65
67
|
chat_id: '-1001737180019',
|
|
@@ -79,6 +81,7 @@ export function reportApiError(fetch: any, error: any) {
|
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
83
|
|
|
84
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/error.md#sendTm) untuk melihat dokumentasi*/
|
|
82
85
|
export function sendTm(message: string, chat_id?: string, bot?: string, res?: (result: any) => void): void {
|
|
83
86
|
let _chatids: string[] = []
|
|
84
87
|
if (chat_id) {
|
|
@@ -123,9 +126,15 @@ export function getError() {
|
|
|
123
126
|
// remove error that unsolved
|
|
124
127
|
} else if (msg.includes(`SyntaxError: JSON Parse error: Unexpected token:`)) {
|
|
125
128
|
// remove error that unsolved
|
|
129
|
+
} else if (msg.includes(`FirebaseError: [code=invalid-argument]`)) {
|
|
130
|
+
let post = {
|
|
131
|
+
text: msg,
|
|
132
|
+
chat_id: '-1001737180019',
|
|
133
|
+
disable_web_page_preview: true
|
|
134
|
+
}
|
|
135
|
+
new LibCurl()?.custom?.('https://api.telegram.org/bot923808407:AAEFBlllQNKCEn8E66fwEzCj5vs9qGwVGT4/sendMessage', post)
|
|
126
136
|
} else {
|
|
127
137
|
const telegramIds = config?.errorReport?.telegramIds || {}
|
|
128
|
-
|
|
129
138
|
Object.values(telegramIds).forEach?.(id => {
|
|
130
139
|
let post = {
|
|
131
140
|
text: msg,
|
|
@@ -140,4 +149,4 @@ export function getError() {
|
|
|
140
149
|
}
|
|
141
150
|
})
|
|
142
151
|
}
|
|
143
|
-
|
|
152
|
+
ErrorUtils.setGlobalHandler(myErrorHandler)
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
import { InteractionManager } from 'react-native'
|
|
4
4
|
|
|
5
5
|
let updater: any
|
|
6
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/autoreload.md) untuk melihat dokumentasi*/
|
|
6
7
|
export default {
|
|
8
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/autoreload.md#set) untuk melihat dokumentasi*/
|
|
7
9
|
set(callback: () => void, duration?: number): void {
|
|
8
10
|
if (updater != undefined) {
|
|
9
11
|
clearInterval(updater)
|
|
@@ -15,6 +17,7 @@ export default {
|
|
|
15
17
|
});
|
|
16
18
|
}, duration || 6000)
|
|
17
19
|
},
|
|
20
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/autoreload.md#clear) untuk melihat dokumentasi*/
|
|
18
21
|
clear(): void {
|
|
19
22
|
if (updater != undefined) {
|
|
20
23
|
clearInterval(updater)
|
|
@@ -39,6 +39,7 @@ export interface LibCarrouselState {
|
|
|
39
39
|
childrenLength: number,
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/carrousel.md) untuk melihat dokumentasi*/
|
|
42
43
|
export default class m extends LibComponent<LibCarrouselProps, LibCarrouselState> {
|
|
43
44
|
|
|
44
45
|
static defaultProps = {
|
|
@@ -18,6 +18,7 @@ export interface LibCarrousel_snapProps {
|
|
|
18
18
|
initialPage?: number,
|
|
19
19
|
renderItem: (item: any, key: number | string, itemWidth: number) => any
|
|
20
20
|
}
|
|
21
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/carrousel_snap.md) untuk melihat dokumentasi*/
|
|
21
22
|
export default function m(props: LibCarrousel_snapProps): any {
|
|
22
23
|
const LibFocus = useRef(esp.mod("lib/focus")).current
|
|
23
24
|
const autoCycle = props.autoCycle || false
|
package/modules/lib/collaps.tsx
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import useSafeState from 'esoftplay/state';
|
|
4
4
|
import React, { useEffect } from 'react';
|
|
5
5
|
import { Pressable, ViewStyle } from 'react-native';
|
|
6
|
-
import Animated, { runOnJS, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
|
|
6
|
+
import Animated, { ReduceMotion, runOnJS, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
export interface LibCollapsArgs {
|
|
@@ -15,6 +15,7 @@ export interface LibCollapsProps {
|
|
|
15
15
|
onToggle?: (expanded: boolean) => void,
|
|
16
16
|
style?: ViewStyle
|
|
17
17
|
}
|
|
18
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/collaps.md) untuk melihat dokumentasi*/
|
|
18
19
|
export default function m(props: LibCollapsProps): any {
|
|
19
20
|
const [expand, setExpand] = useSafeState(props.show)
|
|
20
21
|
const opacity = useSharedValue(0);
|
|
@@ -34,7 +35,7 @@ export default function m(props: LibCollapsProps): any {
|
|
|
34
35
|
}, [expand])
|
|
35
36
|
|
|
36
37
|
const toggleAnimation = () => {
|
|
37
|
-
opacity.value = withTiming(opacity.value === 0 ? 1 : 0, { duration: 300 }, (status) => {
|
|
38
|
+
opacity.value = withTiming(opacity.value === 0 ? 1 : 0, { duration: 300, reduceMotion: ReduceMotion.Never }, (status) => {
|
|
38
39
|
if (opacity.value == 0 && status) {
|
|
39
40
|
runOnJS(setExpand)(false)
|
|
40
41
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Component } from "react";
|
|
3
3
|
import isEqual from "react-fast-compare";
|
|
4
4
|
|
|
5
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/component.md) untuk melihat dokumentasi*/
|
|
5
6
|
export default class m<K, S> extends Component<K, S> {
|
|
6
7
|
private _isMounted: boolean = false;
|
|
7
8
|
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// withHooks
|
|
2
|
+
import { LibNavigationRoutes } from 'esoftplay';
|
|
3
|
+
import { LibNavigation } from 'esoftplay/cache/lib/navigation/import';
|
|
4
|
+
import { LibObject } from 'esoftplay/cache/lib/object/import';
|
|
5
|
+
import { LibUtils } from 'esoftplay/cache/lib/utils/import';
|
|
6
|
+
import { EspRouterInterface } from 'esoftplay/cache/routers';
|
|
7
|
+
import esp from 'esoftplay/esp';
|
|
8
|
+
import useGlobalState from 'esoftplay/global';
|
|
9
|
+
import React, { createElement, ReactElement } from 'react';
|
|
10
|
+
import { ScrollView, Text, View } from "react-native";
|
|
11
|
+
|
|
12
|
+
export interface RNTypes extends EspRouterInterface {
|
|
13
|
+
"View": typeof View,
|
|
14
|
+
"Text": typeof Text,
|
|
15
|
+
"ScrollView": typeof ScrollView,
|
|
16
|
+
// "TouchableOpacity": typeof TouchableOpacity,
|
|
17
|
+
// "TextInput": typeof TextInput,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const formState = useGlobalState({})
|
|
21
|
+
|
|
22
|
+
function buildUIFromJSON(json: any): ReactElement {
|
|
23
|
+
const { component, props } = json;
|
|
24
|
+
|
|
25
|
+
let children = null;
|
|
26
|
+
if (props?.children) {
|
|
27
|
+
if (Array.isArray(props?.children)) {
|
|
28
|
+
children = props?.children?.map?.((child: any) => buildUIFromJSON(child));
|
|
29
|
+
} else if (typeof props.children != 'string') {
|
|
30
|
+
children = buildUIFromJSON(props?.children);
|
|
31
|
+
} else {
|
|
32
|
+
children = props.children;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
let _props = props
|
|
36
|
+
|
|
37
|
+
if (props) {
|
|
38
|
+
Object.keys(props).map((key) => {
|
|
39
|
+
if (typeof props[key] == 'string' && String(props[key]).includes("#esp|")) {
|
|
40
|
+
const cleanFunction = (props[key]).replace("#esp|", "")
|
|
41
|
+
const [modules, func, args] = cleanFunction.split("|")
|
|
42
|
+
_props[key] = () => {
|
|
43
|
+
esp.mod(modules)[func](...eval(args))
|
|
44
|
+
}
|
|
45
|
+
} else if (typeof props[key] == 'string' && String(props[key]).includes("#espProp|")) {
|
|
46
|
+
const cleanFunction = (props[key]).replace("#espProp|", "")
|
|
47
|
+
const [modules, func, args] = cleanFunction.split("|")
|
|
48
|
+
_props[key] = () => {
|
|
49
|
+
esp.modProp(modules)[func](...eval(args))
|
|
50
|
+
}
|
|
51
|
+
} else if (typeof props[key] == 'string' && String(props[key]).includes("#action.")) {
|
|
52
|
+
const cleanFunction = (props[key]).replace("#action.", "")
|
|
53
|
+
const [func, argument] = cleanFunction.split('.')
|
|
54
|
+
_props[key] = () => {
|
|
55
|
+
action[func](eval(argument))
|
|
56
|
+
}
|
|
57
|
+
} else if (typeof props[key] == 'string' && String(props[key]).includes("#form.")) {
|
|
58
|
+
const cleanForm = (props[key]).replace("#form.", "")
|
|
59
|
+
const [type, postkey] = cleanForm.split('.')
|
|
60
|
+
if (type == 'input') {
|
|
61
|
+
_props[key] = (input: string) => {
|
|
62
|
+
formState.set(LibObject.set(formState.get(), input)(postkey))
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (type == 'select') {
|
|
66
|
+
console.log(type, postkey, key)
|
|
67
|
+
const [_key, _value] = postkey.split(":")
|
|
68
|
+
_props[key] = () => {
|
|
69
|
+
formState.set(LibObject.set(formState.get(), _value)(_key))
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
_props[key] = props[key]
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Create the element based on the component type
|
|
79
|
+
if (component?.includes?.('/')) {
|
|
80
|
+
return esp.mod(component)(_props);
|
|
81
|
+
} else {
|
|
82
|
+
return createElement("RCT" + component, { ..._props, children });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/compose.md) untuk melihat dokumentasi*/
|
|
88
|
+
export default function m({ schema }: { schema: any }): ReactElement {
|
|
89
|
+
return buildUIFromJSON(schema)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const action: any = {
|
|
93
|
+
"navigate": (args: any[]) => esp.mod("lib/navigation").navigate(args[0], args[1]),
|
|
94
|
+
"replace": (args: any[]) => esp.mod("lib/navigation").replace(args[0], args[1]),
|
|
95
|
+
"back": (args: any[]) => esp.mod("lib/navigation").back(),
|
|
96
|
+
"copy": (args: any[]) => {
|
|
97
|
+
esp.mod("lib/utils").copyToClipboard(JSON.stringify(args))
|
|
98
|
+
esp.modProp("lib/toast").show(args + " copied!")
|
|
99
|
+
},
|
|
100
|
+
"curl": (args: any[]) => {
|
|
101
|
+
esp.mod("lib/progress").show("Please Wait..")
|
|
102
|
+
let post = args?.[1]
|
|
103
|
+
try {
|
|
104
|
+
post = JSON.parse(args?.[1])
|
|
105
|
+
} catch (error) {
|
|
106
|
+
post = args?.[1]
|
|
107
|
+
}
|
|
108
|
+
post = Object.assign({}, post, formState.get())
|
|
109
|
+
new (esp.mod('lib/curl'))(args[0], post, (res, msg) => {
|
|
110
|
+
esp.modProp("lib/toast").show(msg)
|
|
111
|
+
esp.mod("lib/progress").hide()
|
|
112
|
+
}, (err) => {
|
|
113
|
+
esp.modProp("lib/toast").show(err.message)
|
|
114
|
+
esp.mod("lib/progress").hide()
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/compose.md#forms) untuk melihat dokumentasi*/
|
|
120
|
+
export const forms = {
|
|
121
|
+
select: (postKey: string, value: string) => `#form.select.${postKey}:${value}`,
|
|
122
|
+
input: (postKey: string) => `#form.input.${postKey}`,
|
|
123
|
+
}
|
|
124
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/compose.md#actions) untuk melihat dokumentasi*/
|
|
125
|
+
export const actions = {
|
|
126
|
+
navigate: (module: LibNavigationRoutes, params: any) => {
|
|
127
|
+
LibNavigation.navigate(module, params)
|
|
128
|
+
},
|
|
129
|
+
replace: (module: LibNavigationRoutes, params: any) => {
|
|
130
|
+
LibNavigation.replace(module, params)
|
|
131
|
+
},
|
|
132
|
+
back: () => {
|
|
133
|
+
LibNavigation.back()
|
|
134
|
+
},
|
|
135
|
+
copy: (args: string) => {
|
|
136
|
+
LibUtils.copyToClipboard(args)
|
|
137
|
+
esp.modProp("lib/toast").show(args + " copied!")
|
|
138
|
+
},
|
|
139
|
+
curl: (uri: string, post?: any) => {
|
|
140
|
+
new (esp.mod('lib/curl'))(uri, post, (res, msg) => {
|
|
141
|
+
esp.modProp("lib/toast").show(msg)
|
|
142
|
+
}, (err) => {
|
|
143
|
+
esp.modProp("lib/toast").show(err.message)
|
|
144
|
+
}, 1)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/lib/compose.md#build) untuk melihat dokumentasi*/
|
|
149
|
+
export function build<T extends keyof RNTypes>(cmpn: T, props: React.ComponentProps<RNTypes[T]>): any {
|
|
150
|
+
let obj: any = {};
|
|
151
|
+
obj.component = cmpn;
|
|
152
|
+
let _props = props
|
|
153
|
+
if (props) {
|
|
154
|
+
Object.keys(props).map((key) => {
|
|
155
|
+
if (typeof props[key] == 'function') {
|
|
156
|
+
_props[key] = `@clientFn` + String(props[key])
|
|
157
|
+
} else {
|
|
158
|
+
_props[key] = props[key]
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
obj.props = { ..._props }; // Shallow copy the props
|
|
163
|
+
|
|
164
|
+
// If there are children, process them
|
|
165
|
+
if (props?.children) {
|
|
166
|
+
if (Array.isArray(props.children)) {
|
|
167
|
+
// If children is an array, recursively build each child
|
|
168
|
+
obj.props.children = props.children.map((child: any) =>
|
|
169
|
+
typeof child === 'string' ? child : build(child.component, child.props)
|
|
170
|
+
);
|
|
171
|
+
} else if (typeof props.children !== 'string') {
|
|
172
|
+
// If there's only one child and it's not a string, build it
|
|
173
|
+
obj.props.children = build(props.children.component, props.children.props);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return obj;
|
|
178
|
+
}
|
package/modules/lib/curl.ts
CHANGED
package/modules/lib/custom.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// withHooks
|
|
2
2
|
|
|
3
3
|
import esp from 'esoftplay/esp';
|
|
4
|
+
import useSafeState from 'esoftplay/state';
|
|
4
5
|
import React, { useEffect, useRef } from 'react';
|
|
5
|
-
import { Linking
|
|
6
|
-
import WebView from 'react-native-webview';
|
|
6
|
+
import { Linking } from 'react-native';
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
export interface LibCustomArgs {
|
|
@@ -12,34 +12,41 @@ export interface LibCustomArgs {
|
|
|
12
12
|
export interface LibCustomProps {
|
|
13
13
|
|
|
14
14
|
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
json_to_view
|
|
20
|
+
https://api.test.bbo.co.id/main?module=lib.custom&link=https%3A%2F%2Ftest.bbo.co.id%2Fsaya-tidak-bisa-login-akun-bbo_432.htm
|
|
21
|
+
|
|
22
|
+
deeplink
|
|
23
|
+
https://api.test.bbo.co.id/main?module=lib.custom&link=bbt%3A%2F%2Ftest.bbo.co.id%2Fjual%2Farcanealley2024
|
|
24
|
+
*/
|
|
15
25
|
export default function m(props: LibCustomProps): any {
|
|
16
|
-
const
|
|
26
|
+
const LibCompose = useRef(esp.mod("lib/compose")).current
|
|
17
27
|
|
|
18
28
|
const { url, title } = esp.mod("lib/navigation").getArgsAll(props)
|
|
19
|
-
|
|
29
|
+
const [schema, setSchema] = useSafeState<any>(null)
|
|
30
|
+
|
|
20
31
|
useEffect(() => {
|
|
21
32
|
if (!String(url).startsWith("http")) {
|
|
22
33
|
Linking.openURL(url)
|
|
23
34
|
esp.mod("lib/navigation").back()
|
|
35
|
+
} else {
|
|
36
|
+
new (esp.mod("lib/curl"))(url, null,
|
|
37
|
+
(res, msg) => {
|
|
38
|
+
setSchema(res)
|
|
39
|
+
},
|
|
40
|
+
(err) => {
|
|
41
|
+
esp.modProp("lib/toast").show(err?.message)
|
|
42
|
+
esp.mod("lib/navigation").back()
|
|
43
|
+
}
|
|
44
|
+
)
|
|
24
45
|
}
|
|
25
46
|
}, [])
|
|
26
47
|
|
|
27
|
-
if (String(url).startsWith("http"))
|
|
28
|
-
return
|
|
29
|
-
<View style={{ flex: 1 }} >
|
|
30
|
-
<View style={[{ height: 60 + esp.mod("lib/style").STATUSBAR_HEIGHT, paddingTop: esp.mod("lib/style").STATUSBAR_HEIGHT, backgroundColor: "#fff", flexDirection: 'row', alignItems: 'center', marginBottom: 3 }, esp.mod("lib/style").elevation(3)]} >
|
|
31
|
-
<Pressable onPress={() => esp.mod("lib/navigation").back()} style={{ height: 60, width: 60, alignItems: 'center', justifyContent: 'center' }} >
|
|
32
|
-
<LibIcon name='arrow-left' />
|
|
33
|
-
</Pressable>
|
|
34
|
-
<Text style={{ fontWeight: "bold", marginLeft: 0 }}>{title ? title : ""}</Text>
|
|
35
|
-
</View>
|
|
36
|
-
<WebView
|
|
37
|
-
style={{ flex: 1 }}
|
|
38
|
-
source={{ uri: url }}
|
|
39
|
-
startInLoadingState={true}
|
|
40
|
-
/>
|
|
41
|
-
</View>
|
|
42
|
-
)
|
|
48
|
+
if (String(url).startsWith("http") && schema)
|
|
49
|
+
return <LibCompose schema={schema} />
|
|
43
50
|
else
|
|
44
51
|
return null
|
|
45
52
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// withHooks
|
|
2
|
+
|
|
3
|
+
import useSafeState from 'esoftplay/state';
|
|
4
|
+
import React, { ReactElement } from 'react';
|
|
5
|
+
import { ViewStyle } from 'react-native';
|
|
6
|
+
import Animated, { Extrapolation, interpolate, runOnJS, SharedValue, useAnimatedReaction, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export interface LibFadescrollArgs {
|
|
10
|
+
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface LibFadescrollProps {
|
|
14
|
+
scrollController: SharedValue<number>,
|
|
15
|
+
style?: ViewStyle,
|
|
16
|
+
children?: ReactElement,
|
|
17
|
+
interpolateOpacity: number[],
|
|
18
|
+
interpolateScroll: number[],
|
|
19
|
+
}
|
|
20
|
+
export default function m(props: LibFadescrollProps): any {
|
|
21
|
+
let opacity = useSharedValue(0)
|
|
22
|
+
const [pointerEvents, setPointerEvents] = useSafeState<any>('none')
|
|
23
|
+
const { scrollController, interpolateScroll, interpolateOpacity } = props
|
|
24
|
+
|
|
25
|
+
// Animated style for opacity based on external scrollController value
|
|
26
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
27
|
+
opacity.value = interpolate(
|
|
28
|
+
scrollController.value,
|
|
29
|
+
interpolateScroll,
|
|
30
|
+
interpolateOpacity,
|
|
31
|
+
Extrapolation.CLAMP
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return { opacity: opacity.value };
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
useAnimatedReaction(
|
|
38
|
+
() => opacity.value,
|
|
39
|
+
(currentValue) => {
|
|
40
|
+
runOnJS(setPointerEvents)(currentValue == 1 ? 'auto' : 'none');
|
|
41
|
+
},
|
|
42
|
+
[]
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<Animated.View style={[props.style, animatedStyle]} pointerEvents={pointerEvents}>
|
|
47
|
+
{props.children}
|
|
48
|
+
</Animated.View>
|
|
49
|
+
);
|
|
50
|
+
}
|
package/modules/lib/image.tsx
CHANGED
|
@@ -7,7 +7,7 @@ import { LibProgress } from 'esoftplay/cache/lib/progress/import';
|
|
|
7
7
|
import { LibStyle } from 'esoftplay/cache/lib/style/import';
|
|
8
8
|
import esp from 'esoftplay/esp';
|
|
9
9
|
import useGlobalState from 'esoftplay/global';
|
|
10
|
-
import {
|
|
10
|
+
import { CameraView } from 'expo-camera';
|
|
11
11
|
import * as ImageManipulator from 'expo-image-manipulator';
|
|
12
12
|
import { SaveFormat } from 'expo-image-manipulator';
|
|
13
13
|
import * as ImagePicker from 'expo-image-picker';
|
|
@@ -80,7 +80,7 @@ class m extends LibComponent<LibImageProps, LibImageState> {
|
|
|
80
80
|
constructor(props: LibImageProps) {
|
|
81
81
|
super(props);
|
|
82
82
|
this.state = {
|
|
83
|
-
type:
|
|
83
|
+
type: 'back',
|
|
84
84
|
loading: false,
|
|
85
85
|
image: null,
|
|
86
86
|
flashLight: 'off'
|
|
@@ -302,17 +302,17 @@ class m extends LibComponent<LibImageProps, LibImageState> {
|
|
|
302
302
|
return (
|
|
303
303
|
<View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }} >
|
|
304
304
|
<View style={{ flex: 1 }} >
|
|
305
|
-
<
|
|
305
|
+
<CameraView
|
|
306
306
|
ref={(camera: any) => this.camera = camera}
|
|
307
|
-
|
|
307
|
+
facing={type}
|
|
308
308
|
ratio={'4:3'}
|
|
309
|
-
|
|
309
|
+
flash={flashLight}
|
|
310
310
|
zoom={0.1}
|
|
311
311
|
style={{ height: LibStyle.width * 4 / 3, width: LibStyle.width }}>
|
|
312
312
|
<View style={{ height: height, width: width, backgroundColor: 'transparent' }} >
|
|
313
|
-
{image ? <Image source={image} style={{ height: LibStyle.width * 4 / 3, width: width, resizeMode: 'cover', transform: [{ scaleX: this.state.type ==
|
|
313
|
+
{image ? <Image source={image} style={{ height: LibStyle.width * 4 / 3, width: width, resizeMode: 'cover', transform: [{ scaleX: this.state.type == 'back' ? 'front' : 'back' }] }} /> : null}
|
|
314
314
|
</View>
|
|
315
|
-
</
|
|
315
|
+
</CameraView>
|
|
316
316
|
<View style={{ position: 'absolute', top: 10 + LibStyle.STATUSBAR_HEIGHT, left: 10 }} >
|
|
317
317
|
<TouchableOpacity onPress={() => this.setState({ flashLight: flashLight == 'on' ? 'off' : 'on' })} >
|
|
318
318
|
<LibIcon color={'white'} size={24} name={flashLight == 'on' ? 'flash' : "flash-off"} />
|
|
@@ -324,11 +324,11 @@ class m extends LibComponent<LibImageProps, LibImageState> {
|
|
|
324
324
|
{
|
|
325
325
|
image ?
|
|
326
326
|
<TouchableOpacity onPress={() => this.setState({ image: false })} >
|
|
327
|
-
<LibIcon.Ionicons name='
|
|
327
|
+
<LibIcon.Ionicons name='close-circle' style={{ fontSize: 40, color: 'white' }} />
|
|
328
328
|
</TouchableOpacity>
|
|
329
329
|
:
|
|
330
|
-
<TouchableOpacity onPress={() => this.setState({ type: this.state.type ===
|
|
331
|
-
<LibIcon.Ionicons name='
|
|
330
|
+
<TouchableOpacity onPress={() => this.setState({ type: this.state.type === 'back' ? 'front' : 'back' })} >
|
|
331
|
+
<LibIcon.Ionicons name='refresh-circle' style={{ fontSize: 40, color: 'white' }} />
|
|
332
332
|
</TouchableOpacity>
|
|
333
333
|
}
|
|
334
334
|
</View>
|
|
@@ -358,7 +358,7 @@ class m extends LibComponent<LibImageProps, LibImageState> {
|
|
|
358
358
|
clearTimeout(timer)
|
|
359
359
|
});
|
|
360
360
|
}} >
|
|
361
|
-
<LibIcon.Ionicons name='
|
|
361
|
+
<LibIcon.Ionicons name='checkmark-circle' style={{ fontSize: 40, color: 'white' }} />
|
|
362
362
|
</TouchableOpacity>
|
|
363
363
|
:
|
|
364
364
|
<TouchableOpacity onPress={() => {
|
|
@@ -369,7 +369,7 @@ class m extends LibComponent<LibImageProps, LibImageState> {
|
|
|
369
369
|
});
|
|
370
370
|
clearTimeout(timer)
|
|
371
371
|
}} >
|
|
372
|
-
<LibIcon.Ionicons name='
|
|
372
|
+
<LibIcon.Ionicons name='close-circle' style={{ fontSize: 40, color: 'white' }} />
|
|
373
373
|
</TouchableOpacity>
|
|
374
374
|
}
|
|
375
375
|
</View>
|
|
@@ -12,13 +12,13 @@ export interface LibImage_cropProps {
|
|
|
12
12
|
|
|
13
13
|
}
|
|
14
14
|
export default function m(props: LibImage_cropProps): any {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
const LibIcon = useRef(esp.mod("lib/icon")).current
|
|
16
|
+
const LibNavigation = useRef(esp.mod("lib/navigation")).current
|
|
17
|
+
const LibProgress = useRef(esp.mod("lib/progress")).current
|
|
18
|
+
const LibStatusbar = useRef(esp.mod("lib/statusbar")).current
|
|
19
|
+
const LibStyle = useRef(esp.mod("lib/style")).current
|
|
20
|
+
const LibTextstyle = useRef(esp.mod("lib/textstyle")).current
|
|
21
|
+
const LibToastProperty = useRef(esp.modProp("lib/toast")).current
|
|
22
22
|
|
|
23
23
|
const { image, ratio, forceCrop, message } = LibNavigation.getArgsAll(props)
|
|
24
24
|
const [_image, setImage] = useSafeState(image)
|
|
@@ -43,6 +43,8 @@ export default function m(props: LibImage_cropProps): any {
|
|
|
43
43
|
ratioSize[1] = _ratio[1] / _ratio[0] * minimalRatioSize
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
|
|
47
|
+
|
|
46
48
|
function resize(image: string) {
|
|
47
49
|
LibProgress.show(esp.lang("lib/image_crop", "waiting"))
|
|
48
50
|
Image.getSize(image, async (actualWidth, actualHeight) => {
|
|
@@ -179,37 +181,7 @@ export default function m(props: LibImage_cropProps): any {
|
|
|
179
181
|
return (
|
|
180
182
|
<View style={{ flex: 1, backgroundColor: "#000" }} key={counter} >
|
|
181
183
|
<LibStatusbar style="light" />
|
|
182
|
-
<
|
|
183
|
-
ref={imageRef}
|
|
184
|
-
style={{ resizeMode: "contain", marginTop: marginTop, height: size, width: LibStyle.width }} source={{ uri: _image }} />
|
|
185
|
-
<View style={{ flex: 1, marginTop: -(LibStyle.height - marginTop - (LibStyle.isIphoneX ? 35 : 0)) + LibStyle.STATUSBAR_HEIGHT, alignItems: 'center', justifyContent: 'center' }} >
|
|
186
|
-
<PanPinchView
|
|
187
|
-
key={_image}
|
|
188
|
-
minScale={0.5}
|
|
189
|
-
containerDimensions={{
|
|
190
|
-
width: LibStyle.width,
|
|
191
|
-
height: size,
|
|
192
|
-
}}
|
|
193
|
-
contentDimensions={{
|
|
194
|
-
width: ratioSize[0],
|
|
195
|
-
height: ratioSize[1]
|
|
196
|
-
}}
|
|
197
|
-
// style={{ backgroundColor: "transparent", flex: undefined, width: LibStyle.height * 100, height: LibStyle.height * 100, alignSelf: 'center', justifyContent: 'center' }}
|
|
198
|
-
maxScale={2}>
|
|
199
|
-
{/* <> */}
|
|
200
|
-
{/* <View style={{ backgroundColor: "rgba(0,0,0,0.5 )", flex: 1 }} />
|
|
201
|
-
<View style={{ flexDirection: "row" }} >
|
|
202
|
-
<View style={{ backgroundColor: "rgba(0,0,0,0.5 )", flex: 1 }} /> */}
|
|
203
|
-
<View ref={viewRef} style={{ height: ratioSize[1], width: ratioSize[0], backgroundColor: 'transparent', borderWidth: 1.5, borderColor: "white", borderStyle: 'dashed' }} >
|
|
204
|
-
<View style={{ flex: 1, backgroundColor: 'transparent', borderWidth: 1.5, borderColor: "black", borderStyle: 'dashed' }} />
|
|
205
|
-
</View>
|
|
206
|
-
{/* <View style={{ backgroundColor: "rgba(0,0,0,0.5 )", flex: 1 }} />
|
|
207
|
-
</View>
|
|
208
|
-
<View style={{ backgroundColor: "rgba(0,0,0,0.5 )", flex: 1 }} /> */}
|
|
209
|
-
{/* </> */}
|
|
210
|
-
</PanPinchView>
|
|
211
|
-
</View>
|
|
212
|
-
<View style={{ position: "absolute", top: LibStyle.STATUSBAR_HEIGHT, left: 0, right: 0, height: 50, flexDirection: "row", justifyContent: 'space-between' }} >
|
|
184
|
+
<View style={{ marginTop: LibStyle.STATUSBAR_HEIGHT, height: 50, flexDirection: "row", justifyContent: 'space-between' }} >
|
|
213
185
|
<TouchableOpacity
|
|
214
186
|
onPress={() => LibNavigation.back()}
|
|
215
187
|
style={{ height: 50, width: 50, alignItems: 'center', justifyContent: 'center' }} >
|
|
@@ -228,28 +200,62 @@ export default function m(props: LibImage_cropProps): any {
|
|
|
228
200
|
</TouchableOpacity>
|
|
229
201
|
</View>
|
|
230
202
|
</View>
|
|
231
|
-
{
|
|
232
|
-
|
|
233
|
-
<
|
|
234
|
-
|
|
235
|
-
style={{
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
onPress={() => {
|
|
244
|
-
Image.getSize(_image, (width, height) => {
|
|
245
|
-
LibNavigation.sendBackResult({ uri: _image, width, height }, LibNavigation.getResultKey(props))
|
|
246
|
-
}, () => { })
|
|
203
|
+
<View style={{ flex: 1 }} >
|
|
204
|
+
|
|
205
|
+
<Image
|
|
206
|
+
ref={imageRef}
|
|
207
|
+
style={{ resizeMode: "contain", height: size, width: LibStyle.width }} source={{ uri: _image }} />
|
|
208
|
+
<View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, alignItems: 'center', justifyContent: 'center' }} >
|
|
209
|
+
<PanPinchView
|
|
210
|
+
key={_image}
|
|
211
|
+
minScale={0.5}
|
|
212
|
+
containerDimensions={{
|
|
213
|
+
width: LibStyle.width,
|
|
214
|
+
height: size,
|
|
247
215
|
}}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
216
|
+
contentDimensions={{
|
|
217
|
+
width: ratioSize[0],
|
|
218
|
+
height: ratioSize[1]
|
|
219
|
+
}}
|
|
220
|
+
// style={{ backgroundColor: "transparent", flex: undefined, width: LibStyle.height * 100, height: LibStyle.height * 100, alignSelf: 'center', justifyContent: 'center' }}
|
|
221
|
+
maxScale={2}>
|
|
222
|
+
{/* <> */}
|
|
223
|
+
{/* <View style={{ backgroundColor: "rgba(0,0,0,0.5 )", flex: 1 }} />
|
|
224
|
+
<View style={{ flexDirection: "row" }} >
|
|
225
|
+
<View style={{ backgroundColor: "rgba(0,0,0,0.5 )", flex: 1 }} /> */}
|
|
226
|
+
<View ref={viewRef} style={{ height: ratioSize[1], width: ratioSize[0], backgroundColor: 'transparent', borderWidth: 1, borderColor: "white", borderStyle: 'dashed', zIndex: 100 }} >
|
|
227
|
+
<View style={{ flex: 1, backgroundColor: 'transparent', borderWidth: 1, borderColor: "black", borderStyle: 'dashed' }} />
|
|
228
|
+
</View>
|
|
229
|
+
{/* <View style={{ backgroundColor: "rgba(0,0,0,0.5 )", flex: 1 }} />
|
|
230
|
+
</View>
|
|
231
|
+
<View style={{ backgroundColor: "rgba(0,0,0,0.5 )", flex: 1 }} /> */}
|
|
232
|
+
{/* </> */}
|
|
233
|
+
</PanPinchView>
|
|
251
234
|
</View>
|
|
252
|
-
|
|
235
|
+
|
|
236
|
+
{
|
|
237
|
+
// hint &
|
|
238
|
+
<Pressable
|
|
239
|
+
onPress={() => setHint(!hint)}
|
|
240
|
+
style={{ opacity: hint ? 1 : 0, position: 'absolute', left: 0, right: 0, bottom: 50, backgroundColor: 'rgba(0,0,0,0.5)', alignItems: 'center', justifyContent: 'center', padding: 30 }} >
|
|
241
|
+
<Text style={{ color: "white", textAlign: 'center' }} >{message || esp.lang("lib/image_crop", "text_msg")}</Text>
|
|
242
|
+
</Pressable>
|
|
243
|
+
}
|
|
244
|
+
{
|
|
245
|
+
(!forceCrop || cropCount > 0) &&
|
|
246
|
+
<View style={{ position: "absolute", bottom: 10, left: 0, right: 0 }} >
|
|
247
|
+
<TouchableOpacity
|
|
248
|
+
onPress={() => {
|
|
249
|
+
Image.getSize(_image, (width, height) => {
|
|
250
|
+
LibNavigation.sendBackResult({ uri: _image, width, height }, LibNavigation.getResultKey(props))
|
|
251
|
+
}, () => { })
|
|
252
|
+
}}
|
|
253
|
+
style={{ height: 50, alignItems: 'center', justifyContent: 'center', backgroundColor: 'rgba(255,255,255,0.3)' }} >
|
|
254
|
+
<LibTextstyle textStyle="body" text={esp.lang("lib/image_crop", "btn_save")} style={{ color: "white" }} />
|
|
255
|
+
</TouchableOpacity>
|
|
256
|
+
</View>
|
|
257
|
+
}
|
|
258
|
+
</View>
|
|
253
259
|
</View>
|
|
254
260
|
)
|
|
255
261
|
}
|
package/modules/lib/infinite.tsx
CHANGED
|
@@ -130,6 +130,7 @@ export default class m extends LibComponent<LibInfiniteProps, LibInfiniteState>
|
|
|
130
130
|
this.isStop = true
|
|
131
131
|
this.setState((state: LibInfiniteState, props: LibInfiniteProps) => {
|
|
132
132
|
return {
|
|
133
|
+
isStop: this.isStop,
|
|
133
134
|
error: this.props.error || esp.lang("lib/infinite", "empty_data"),
|
|
134
135
|
data: page == 0
|
|
135
136
|
? []
|
|
@@ -142,6 +143,7 @@ export default class m extends LibComponent<LibInfiniteProps, LibInfiniteState>
|
|
|
142
143
|
this.setState((state: LibInfiniteState, props: LibInfiniteProps) => {
|
|
143
144
|
const latestData = [...state.data, ...mainIndex.list]
|
|
144
145
|
return {
|
|
146
|
+
isStop: this.isStop,
|
|
145
147
|
error: '',
|
|
146
148
|
data: page == 0
|
|
147
149
|
? (typeof this.props?.filterData == 'function' ? mainIndex.list.filter(this.props.filterData) : mainIndex.list)
|
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
// withHooks
|
|
2
2
|
// noPage
|
|
3
3
|
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import React, { useRef, useState } from 'react';
|
|
8
|
-
import { KeyboardAvoidingView, Platform, ViewStyle } from 'react-native';
|
|
9
|
-
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { Platform, ViewStyle } from 'react-native';
|
|
6
|
+
import { KeyboardAvoidingView } from 'react-native-keyboard-controller';
|
|
10
7
|
|
|
11
8
|
export interface LibKeyboard_avoidProps {
|
|
12
9
|
children?: any,
|
|
13
10
|
style?: ViewStyle
|
|
14
11
|
}
|
|
15
|
-
export default function m(props: LibKeyboard_avoidProps): any {
|
|
16
|
-
|
|
17
|
-
// const isFocussed = useIsFocused();
|
|
18
12
|
|
|
19
|
-
// const Custom = isFocussed ? KeyboardAvoidingView : View
|
|
20
13
|
|
|
14
|
+
export default function m(props: LibKeyboard_avoidProps): any {
|
|
21
15
|
return (
|
|
22
16
|
<KeyboardAvoidingView behavior={Platform.OS == 'android' ? 'height' : 'padding'} style={[{ flex: 1 }, props.style]} >
|
|
23
17
|
{props.children}
|
|
@@ -25,55 +19,3 @@ export default function m(props: LibKeyboard_avoidProps): any {
|
|
|
25
19
|
)
|
|
26
20
|
}
|
|
27
21
|
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Hook to access the navigation prop of the parent screen anywhere.
|
|
31
|
-
*
|
|
32
|
-
* @returns Navigation prop of the parent screen.
|
|
33
|
-
*/
|
|
34
|
-
function useNavigation<T = NavigationProp<ReactNavigation.RootParamList>>(): T {
|
|
35
|
-
const root = React.useContext(NavigationContainerRefContext);
|
|
36
|
-
const navigation = React.useContext(NavigationContext);
|
|
37
|
-
|
|
38
|
-
if (navigation === undefined && root === undefined) {
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
return (navigation ?? root) as unknown as T;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function useIsFocused(): boolean {
|
|
45
|
-
const navigation = useNavigation();
|
|
46
|
-
|
|
47
|
-
const forceTrue = useRef(false)
|
|
48
|
-
|
|
49
|
-
if (navigation == undefined) {
|
|
50
|
-
forceTrue.current = true
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const [isFocused, setIsFocused] = useState(navigation?.isFocused);
|
|
54
|
-
|
|
55
|
-
const valueToReturn = !!navigation?.isFocused?.();
|
|
56
|
-
|
|
57
|
-
if (isFocused !== valueToReturn) {
|
|
58
|
-
setIsFocused(valueToReturn);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
React.useEffect(() => {
|
|
62
|
-
const unsubscribeFocus = navigation?.addListener?.('focus', () =>
|
|
63
|
-
setIsFocused(true)
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
const unsubscribeBlur = navigation?.addListener?.('blur', () =>
|
|
67
|
-
setIsFocused(false)
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
return () => {
|
|
71
|
-
unsubscribeFocus?.();
|
|
72
|
-
unsubscribeBlur?.();
|
|
73
|
-
};
|
|
74
|
-
}, [navigation]);
|
|
75
|
-
|
|
76
|
-
React.useDebugValue(valueToReturn);
|
|
77
|
-
|
|
78
|
-
return (forceTrue.current || valueToReturn);
|
|
79
|
-
}
|
package/modules/lib/picture.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// withHooks
|
|
2
2
|
// noPage
|
|
3
|
+
import { Image } from 'expo-image';
|
|
3
4
|
import React from 'react';
|
|
4
5
|
import { ImageStyle } from 'react-native';
|
|
5
|
-
import FastImage from 'react-native-fast-image';
|
|
6
6
|
|
|
7
7
|
export interface LibPictureSource {
|
|
8
8
|
uri: string
|
|
@@ -11,7 +11,6 @@ export interface LibPictureProps {
|
|
|
11
11
|
source: LibPictureSource | any,
|
|
12
12
|
style: ImageStyle,
|
|
13
13
|
resizeMode?: "contain" | "cover",
|
|
14
|
-
noCache?: boolean,
|
|
15
14
|
onError?: () => void,
|
|
16
15
|
}
|
|
17
16
|
|
|
@@ -19,15 +18,17 @@ export default function m(props: LibPictureProps): any {
|
|
|
19
18
|
|
|
20
19
|
let resizeMode
|
|
21
20
|
if (props?.style?.resizeMode == 'cover')
|
|
22
|
-
resizeMode =
|
|
21
|
+
resizeMode = "cover"
|
|
23
22
|
else if (props?.style?.resizeMode == 'contain')
|
|
24
|
-
resizeMode =
|
|
23
|
+
resizeMode = "contain"
|
|
25
24
|
else if (props?.resizeMode == 'cover')
|
|
26
|
-
resizeMode =
|
|
25
|
+
resizeMode = "cover"
|
|
27
26
|
else if (props?.resizeMode == 'contain')
|
|
28
|
-
resizeMode =
|
|
27
|
+
resizeMode = "contain"
|
|
29
28
|
else
|
|
30
|
-
resizeMode =
|
|
29
|
+
resizeMode = "cover"
|
|
31
30
|
|
|
32
|
-
return
|
|
31
|
+
return (
|
|
32
|
+
<Image {...props} contentFit={resizeMode} allowDownscaling cachePolicy={"memory-disk"} />
|
|
33
|
+
)
|
|
33
34
|
}
|
package/modules/lib/toast.tsx
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
import { LibStyle } from 'esoftplay/cache/lib/style/import';
|
|
5
5
|
import useGlobalState from 'esoftplay/global';
|
|
6
|
-
import React, { useEffect } from 'react';
|
|
6
|
+
import React, { useEffect, useRef } from 'react';
|
|
7
7
|
import { Text, View } from 'react-native';
|
|
8
|
-
import Animated, { interpolate, useAnimatedProps, useSharedValue, withTiming } from 'react-native-reanimated';
|
|
8
|
+
import Animated, { interpolate, ReduceMotion, useAnimatedProps, useSharedValue, withTiming } from 'react-native-reanimated';
|
|
9
9
|
|
|
10
10
|
export interface LibToastProps {
|
|
11
11
|
|
|
@@ -16,7 +16,7 @@ const initState = {
|
|
|
16
16
|
timeout: 3000
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const state = useGlobalState
|
|
19
|
+
const state = useGlobalState(initState)
|
|
20
20
|
|
|
21
21
|
let _timeout: any = undefined
|
|
22
22
|
|
|
@@ -34,12 +34,13 @@ export function show(message: string, timeout?: number): void {
|
|
|
34
34
|
_timeout = undefined
|
|
35
35
|
}
|
|
36
36
|
_timeout = setTimeout(() => {
|
|
37
|
-
hide()
|
|
38
37
|
clearTimeout(_timeout)
|
|
38
|
+
hide()
|
|
39
39
|
}, timeout || initState.timeout);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export default function m(props: LibToastProps): any {
|
|
43
|
+
const isFirstInit = useRef(true)
|
|
43
44
|
const [data] = state.useState()
|
|
44
45
|
const anim = useSharedValue(0)
|
|
45
46
|
|
|
@@ -51,11 +52,17 @@ export default function m(props: LibToastProps): any {
|
|
|
51
52
|
}))
|
|
52
53
|
|
|
53
54
|
useEffect(() => {
|
|
54
|
-
|
|
55
|
+
if (!isFirstInit.current && data.message == undefined) {
|
|
56
|
+
anim.value = 1
|
|
57
|
+
}
|
|
58
|
+
if (isFirstInit.current) {
|
|
59
|
+
isFirstInit.current = false
|
|
60
|
+
}
|
|
61
|
+
anim.value = withTiming(data.message != undefined ? 1 : 0, { duration: 500, reduceMotion: ReduceMotion.Never })
|
|
55
62
|
}, [data])
|
|
56
63
|
|
|
57
64
|
return (
|
|
58
|
-
<Animated.View pointerEvents={'none'} style={[{ flex: 1, position: 'absolute', justifyContent: 'center', alignContent: 'center', alignItems: 'center', top: LibStyle.STATUSBAR_HEIGHT + 20, left: 0, right: 0, }, style, LibStyle.elevation(2)]} >
|
|
65
|
+
<Animated.View pointerEvents={'none'} style={[{ flex: 1, position: 'absolute', justifyContent: 'center', alignContent: 'center', alignItems: 'center', top: LibStyle.STATUSBAR_HEIGHT + 20, opacity: 0, left: 0, right: 0, }, style, LibStyle.elevation(2)]} >
|
|
59
66
|
<View style={{ maxWidth: Math.min(500, LibStyle.width - 30), minWidth: Math.min(500, LibStyle.width - 30), marginHorizontal: 15, marginVertical: 4, borderRadius: 4, borderWidth: 1, borderColor: '#505050', backgroundColor: '#323232', paddingVertical: 13, paddingHorizontal: 16, }} >
|
|
60
67
|
<Text style={{ fontSize: 14, textAlign: "center", color: 'white' }} >{String(data?.message || '')}</Text>
|
|
61
68
|
</View>
|
package/modules/lib/version.tsx
CHANGED
|
@@ -22,7 +22,7 @@ export interface LibVersionState {
|
|
|
22
22
|
export default class m extends LibComponent<LibVersionProps, LibVersionState> {
|
|
23
23
|
|
|
24
24
|
static appVersion(): string {
|
|
25
|
-
let version: any = (Platform.OS == 'android' ? Constants?.
|
|
25
|
+
let version: any = (Platform.OS == 'android' ? Constants?.manifest?.android?.versionCode : Constants?.manifest?.ios?.buildNumber)
|
|
26
26
|
return version
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -43,7 +43,7 @@ export default class m extends LibComponent<LibVersionProps, LibVersionState> {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
static onDone(res: any, msg: string): void {
|
|
46
|
-
const { title, version, android, ios,
|
|
46
|
+
const { title, version, android, ios, version_publish } = res
|
|
47
47
|
|
|
48
48
|
function isAvailableNewVersion(newVersion: string): boolean {
|
|
49
49
|
let oldVersion = m.appVersion()
|
|
@@ -51,10 +51,13 @@ export default class m extends LibComponent<LibVersionProps, LibVersionState> {
|
|
|
51
51
|
}
|
|
52
52
|
if (isAvailableNewVersion(version)) {
|
|
53
53
|
LibNavigation.backToRoot()
|
|
54
|
-
LibNavigation.replace("lib/version", { res, msg: msg == 'success' ?
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
LibNavigation.replace("lib/version", { res, msg: msg == 'success' ? 'Update to a new version now' : msg })
|
|
55
|
+
} else {
|
|
56
|
+
const currentVersion = esp.config('publish_id')
|
|
57
|
+
if (currentVersion < version_publish && !__DEV__) {
|
|
58
|
+
LibNavigation.reset("lib/version_view")
|
|
59
|
+
LibUpdaterProperty.check((isNew) => { if (isNew) LibUpdaterProperty.install() })
|
|
60
|
+
}
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
static check(): void {
|
|
@@ -67,7 +70,7 @@ export default class m extends LibComponent<LibVersionProps, LibVersionState> {
|
|
|
67
70
|
return (
|
|
68
71
|
<ImageBackground source={esp.assets("splash.png")} blurRadius={100} style={{ flex: 1, justifyContent: 'center', alignItems: 'center', borderStartColor: 'white', paddingHorizontal: 17 }} >
|
|
69
72
|
<LibIcon.SimpleLineIcons name="info" size={60} />
|
|
70
|
-
<LibTextstyle textStyle="headline" text={title ||
|
|
73
|
+
<LibTextstyle textStyle="headline" text={title || 'A new version is available'} style={{ textAlign: 'center', marginTop: 10 }} />
|
|
71
74
|
<LibTextstyle textStyle="callout" text={msg} style={{ textAlign: 'center', marginTop: 10, color: '#333' }} />
|
|
72
75
|
<TouchableOpacity
|
|
73
76
|
onPress={() => { Linking.openURL(link) }}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// withHooks
|
|
2
|
+
|
|
3
|
+
import { LibTextstyle } from 'esoftplay/cache/lib/textstyle/import';
|
|
4
|
+
import esp from 'esoftplay/esp';
|
|
5
|
+
import { useTimeout } from 'esoftplay/timeout';
|
|
6
|
+
import * as Updates from 'expo-updates';
|
|
7
|
+
import React, { useEffect } from 'react';
|
|
8
|
+
import { ActivityIndicator, ImageBackground, View } from 'react-native';
|
|
9
|
+
|
|
10
|
+
export interface LibVersion_viewArgs {
|
|
11
|
+
|
|
12
|
+
}
|
|
13
|
+
export interface LibVersion_viewProps {
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
export default function m(props: LibVersion_viewProps): any {
|
|
17
|
+
const timeout = useTimeout()
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
timeout(() => {
|
|
20
|
+
Updates.reloadAsync()
|
|
21
|
+
}, 15000);
|
|
22
|
+
}, [])
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<ImageBackground source={esp.assets('splash.png')} style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }} >
|
|
26
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }} >
|
|
27
|
+
<LibTextstyle style={{ textAlign: 'center' }} textStyle='headline' text={esp.lang("lib/version_view", "msg")} />
|
|
28
|
+
</View>
|
|
29
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }} >
|
|
30
|
+
<ActivityIndicator size={'large'} />
|
|
31
|
+
</View>
|
|
32
|
+
</ImageBackground>
|
|
33
|
+
)
|
|
34
|
+
}
|
package/modules/main/index.tsx
CHANGED
|
@@ -12,7 +12,7 @@ export default function m(props: MainIndexProps): any {
|
|
|
12
12
|
|
|
13
13
|
return (
|
|
14
14
|
<View style={{ flex: 1, backgroundColor: "white", justifyContent: 'center', alignItems: 'center' }} >
|
|
15
|
-
<Text>{`Hellow Esoftplay Developer, jangan lupa bismillah dulu ଘ(੭ˊᵕˋ)੭*`}</Text>
|
|
15
|
+
<Text style={{ textAlign: 'center' }} >{`Hellow Esoftplay Developer, jangan lupa bismillah dulu ଘ(੭ˊᵕˋ)੭*`}</Text>
|
|
16
16
|
</View>
|
|
17
17
|
)
|
|
18
18
|
}
|
package/modules/use/deeplink.ts
CHANGED
|
@@ -47,10 +47,12 @@ export default function m(defaultUrl?: string): void {
|
|
|
47
47
|
useEffect(() => {
|
|
48
48
|
(async () => {
|
|
49
49
|
const url = await Linking.getInitialURL();
|
|
50
|
-
|
|
50
|
+
if (url) {
|
|
51
|
+
doLink({ url: url })
|
|
52
|
+
}
|
|
51
53
|
})()
|
|
52
54
|
|
|
53
55
|
Linking.addEventListener('url', doLink);
|
|
54
|
-
return () => Linking.
|
|
56
|
+
return () => Linking.removeAllListeners('url')
|
|
55
57
|
}, [])
|
|
56
58
|
}
|
package/modules/user/data.ts
CHANGED
|
@@ -5,7 +5,9 @@ import { userDataReset } from 'esoftplay/global';
|
|
|
5
5
|
import FastStorage from 'esoftplay/mmkv';
|
|
6
6
|
import Storage from 'esoftplay/storage';
|
|
7
7
|
|
|
8
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/user/data.md) untuk melihat dokumentasi*/
|
|
8
9
|
export default {
|
|
10
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/user/data.md#register) untuk melihat dokumentasi*/
|
|
9
11
|
register(name: string): void {
|
|
10
12
|
AsyncStorage.getItem("user_data_dependent").then((x) => {
|
|
11
13
|
let all: string[] = []
|
package/modules/user/hook.tsx
CHANGED
|
@@ -7,6 +7,7 @@ export interface UserHookArgs {
|
|
|
7
7
|
export interface UserHookProps {
|
|
8
8
|
|
|
9
9
|
}
|
|
10
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/user/hook.md) untuk melihat dokumentasi*/
|
|
10
11
|
export default function m(props: UserHookProps): any {
|
|
11
12
|
return null
|
|
12
13
|
}
|
package/modules/user/index.tsx
CHANGED
|
@@ -24,6 +24,8 @@ import { useFonts } from 'expo-font';
|
|
|
24
24
|
import React, { useLayoutEffect } from 'react';
|
|
25
25
|
import { View } from 'react-native';
|
|
26
26
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
27
|
+
import { KeyboardProvider } from "react-native-keyboard-controller";
|
|
28
|
+
|
|
27
29
|
|
|
28
30
|
export interface UserIndexProps {
|
|
29
31
|
|
|
@@ -44,6 +46,8 @@ function getFontConfig() {
|
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
|
|
49
|
+
|
|
50
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/user/index.md) untuk melihat dokumentasi*/
|
|
47
51
|
export default function m(props: UserIndexProps): any {
|
|
48
52
|
moment().locale(LibLocale.state().get())
|
|
49
53
|
const [loading, setLoading] = useSafeState(true)
|
|
@@ -69,26 +73,28 @@ export default function m(props: UserIndexProps): any {
|
|
|
69
73
|
//esoftplay-chatting
|
|
70
74
|
|
|
71
75
|
return (
|
|
72
|
-
<
|
|
73
|
-
<
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
76
|
+
<KeyboardProvider>
|
|
77
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
78
|
+
<View style={{ flex: 1 }}>
|
|
79
|
+
<LibWorker />
|
|
80
|
+
{
|
|
81
|
+
loading ?
|
|
82
|
+
<UserLoading />
|
|
83
|
+
:
|
|
84
|
+
<>
|
|
85
|
+
<LibWorkloop />
|
|
86
|
+
<Navs />
|
|
87
|
+
<LibNet_status />
|
|
88
|
+
<LibDialog style={'default'} />
|
|
89
|
+
<LibImage />
|
|
90
|
+
<LibProgress />
|
|
91
|
+
<LibToast />
|
|
92
|
+
<UserHook />
|
|
93
|
+
</>
|
|
94
|
+
}
|
|
95
|
+
</View>
|
|
96
|
+
<View style={{ backgroundColor: LibStyle?.colorNavigationBar || 'white', height: LibStyle.isIphoneX ? 35 : 0 }} />
|
|
97
|
+
</GestureHandlerRootView>
|
|
98
|
+
</KeyboardProvider>
|
|
93
99
|
)
|
|
94
100
|
}
|
package/modules/user/loading.tsx
CHANGED
|
@@ -11,6 +11,7 @@ export interface UserLoadingArgs {
|
|
|
11
11
|
export interface UserLoadingProps {
|
|
12
12
|
|
|
13
13
|
}
|
|
14
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/user/loading.md) untuk melihat dokumentasi*/
|
|
14
15
|
export default function m(props: UserLoadingProps): any {
|
|
15
16
|
return <ImageBackground source={esp.assets('splash.gif') || esp.assets('splash.png')} style={{ flex: 1 }} />
|
|
16
17
|
}
|
|
@@ -28,6 +28,7 @@ const initState = {
|
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
const state = useGlobalState<any>(initState, { persistKey: "user_notification_data", isUserData: true, loadOnInit: true })
|
|
31
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/user/notification.md) untuk melihat dokumentasi*/
|
|
31
32
|
export default class m extends LibComponent<UserNotificationProps, UserNotificationState> {
|
|
32
33
|
|
|
33
34
|
static state(): useGlobalReturn<any> {
|
|
@@ -18,6 +18,7 @@ export interface UserNotification_itemProps {
|
|
|
18
18
|
updated: string,
|
|
19
19
|
user_id: number,
|
|
20
20
|
}
|
|
21
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/user/notification_item.md) untuk melihat dokumentasi*/
|
|
21
22
|
export default function m(props: UserNotification_itemProps): any {
|
|
22
23
|
const LibStyle = useRef(esp.mod("lib/style")).current
|
|
23
24
|
const LibUtils = useRef(esp.mod("lib/utils")).current
|
package/modules/user/routes.ts
CHANGED
|
@@ -4,13 +4,17 @@ import useGlobalState, { useGlobalReturn } from 'esoftplay/global';
|
|
|
4
4
|
|
|
5
5
|
const state = useGlobalState(undefined)
|
|
6
6
|
|
|
7
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/user/routes.md) untuk melihat dokumentasi*/
|
|
7
8
|
export default {
|
|
9
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/user/routes.md#state) untuk melihat dokumentasi*/
|
|
8
10
|
state(): useGlobalReturn<any> {
|
|
9
11
|
return state
|
|
10
12
|
},
|
|
13
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/user/routes.md#set) untuk melihat dokumentasi*/
|
|
11
14
|
set(routes: any): void {
|
|
12
15
|
state.set(routes)
|
|
13
16
|
},
|
|
17
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/modules/user/routes.md#getCurrentRouteName) untuk melihat dokumentasi*/
|
|
14
18
|
getCurrentRouteName(): string {
|
|
15
19
|
let lastIdx = state.get()?.routes?.length - 1
|
|
16
20
|
let currentName = state.get()?.routes?.[lastIdx]?.name
|
package/package.json
CHANGED
package/render.tsx
CHANGED
|
@@ -3,15 +3,25 @@
|
|
|
3
3
|
|
|
4
4
|
import { useEffect, useRef } from 'react';
|
|
5
5
|
import { Text } from 'react-native';
|
|
6
|
+
import Animated, { useAnimatedStyle, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';
|
|
6
7
|
|
|
8
|
+
|
|
9
|
+
const AnimatedText = Animated.createAnimatedComponent(Text)
|
|
7
10
|
export default function useRenderCounter(module: string): any {
|
|
8
11
|
const counter = useRef(1)
|
|
12
|
+
const value = useSharedValue(0)
|
|
9
13
|
|
|
10
14
|
useEffect(() => {
|
|
11
15
|
counter.current += 1
|
|
16
|
+
value.value = 1
|
|
17
|
+
value.value = withDelay(1000, withTiming(0, { duration: 500 }))
|
|
12
18
|
})
|
|
13
19
|
|
|
20
|
+
const style = useAnimatedStyle(() => ({
|
|
21
|
+
opacity: value.value
|
|
22
|
+
}))
|
|
23
|
+
|
|
14
24
|
return () => (
|
|
15
|
-
<
|
|
25
|
+
<AnimatedText pointerEvent={'none'} style={[{ position: 'absolute', fontSize: 10, zIndex: 999, color: 'white', backgroundColor: 'black', bottom: 0, left: 0 }, style]} >{module}: {counter.current}</AnimatedText>
|
|
16
26
|
)
|
|
17
27
|
}
|
package/timeout.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useEffect, useRef } from "react";
|
|
2
2
|
|
|
3
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/timeout.md#createTimeout) untuk melihat dokumentasi*/
|
|
3
4
|
export function createTimeout() {
|
|
4
5
|
let timeoutId: any = undefined;
|
|
5
6
|
function set(callback: Function, delay: number) {
|
|
@@ -20,6 +21,7 @@ export function createTimeout() {
|
|
|
20
21
|
return { set, clear };
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/timeout.md#useTimeout) untuk melihat dokumentasi*/
|
|
23
25
|
export function useTimeout() {
|
|
24
26
|
const smartTimeout = useRef(createTimeout());
|
|
25
27
|
|
|
@@ -31,6 +33,7 @@ export function useTimeout() {
|
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/timeout.md#createInterval) untuk melihat dokumentasi*/
|
|
34
37
|
export function createInterval() {
|
|
35
38
|
let timeoutId: any = undefined;
|
|
36
39
|
function set(callback: Function, delay: number) {
|
|
@@ -50,6 +53,7 @@ export function createInterval() {
|
|
|
50
53
|
return { set, clear };
|
|
51
54
|
}
|
|
52
55
|
|
|
56
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/timeout.md#useInterval) untuk melihat dokumentasi*/
|
|
53
57
|
export function useInterval() {
|
|
54
58
|
const smartInterval = useRef(createInterval());
|
|
55
59
|
|
|
@@ -60,6 +64,7 @@ export function useInterval() {
|
|
|
60
64
|
return smartInterval.current?.set;
|
|
61
65
|
}
|
|
62
66
|
|
|
67
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/timeout.md#createDebounce) untuk melihat dokumentasi*/
|
|
63
68
|
export function createDebounce() {
|
|
64
69
|
let timeoutId: any = undefined;
|
|
65
70
|
function set(callback: Function, delay: number) {
|
|
@@ -80,6 +85,7 @@ export function createDebounce() {
|
|
|
80
85
|
return { set, clear };
|
|
81
86
|
}
|
|
82
87
|
|
|
88
|
+
/** Klik [disini](https://github.com/dev-esoftplay/mobile-docs/blob/main/timeout.md#useDebounce) untuk melihat dokumentasi*/
|
|
83
89
|
export function useDebounce() {
|
|
84
90
|
const smartDebounce = useRef(createDebounce());
|
|
85
91
|
|