@momo-kits/foundation 0.81.1-optimize.21 → 0.81.1-rc.0
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/Application/BottomSheet.tsx +27 -23
- package/Application/BottomTab/BottomTabBar.tsx +2 -2
- package/Application/BottomTab/index.tsx +2 -3
- package/Application/Components.tsx +288 -42
- package/Application/Localize.ts +44 -0
- package/Application/ModalScreen.tsx +2 -2
- package/Application/Navigation.ts +4 -18
- package/Application/NavigationContainer.tsx +10 -21
- package/Application/Navigator.ts +14 -16
- package/Application/StackScreen.tsx +211 -113
- package/Application/index.ts +5 -3
- package/Application/types.ts +30 -11
- package/Application/utils.tsx +60 -18
- package/Badge/BadgeDotAnimation.tsx +95 -0
- package/Badge/index.tsx +2 -1
- package/Badge/styles.ts +50 -6
- package/Button/index.tsx +0 -1
- package/Icon/types.ts +0 -1
- package/Input/Input.tsx +51 -17
- package/Input/InputDropDown.tsx +44 -47
- package/Input/InputMoney.tsx +56 -6
- package/Input/InputOTP.tsx +10 -6
- package/Input/InputSearch.tsx +259 -146
- package/Input/TextTyping.tsx +113 -0
- package/Input/common.tsx +29 -10
- package/Input/index.tsx +75 -74
- package/Input/styles.ts +43 -7
- package/Layout/FloatingButton.tsx +1 -1
- package/Layout/GridSystem.tsx +1 -1
- package/Layout/ItemList.tsx +3 -2
- package/Layout/Screen.tsx +174 -91
- package/Layout/styles.ts +0 -6
- package/Layout/types.ts +1 -1
- package/Pagination/PaginationScroll.tsx +2 -2
- package/Pagination/styles.ts +1 -1
- package/Popup/PopupNotify.tsx +3 -3
- package/Tag/index.tsx +9 -2
- package/Tag/styles.ts +3 -2
- package/Tag/types.ts +12 -0
- package/Title/index.tsx +6 -9
- package/Title/styles.ts +4 -4
- package/code-scanner.js +4 -4
- package/package.json +6 -5
- package/publish.sh +12 -22
- package/verify.js +36 -42
|
@@ -21,10 +21,10 @@ const ModalScreen: React.FC<any> = props => {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const Modal: React.FC<ModalParams> = props => {
|
|
24
|
-
const {
|
|
24
|
+
const {navigator} = useContext(ApplicationContext);
|
|
25
25
|
const {screen, barrierDismissible} = props.route.params;
|
|
26
26
|
const Component = useRef(screen).current;
|
|
27
|
-
const navigation = new Navigation(props.navigation
|
|
27
|
+
const navigation = new Navigation(props.navigation);
|
|
28
28
|
const params = {
|
|
29
29
|
...props.route.params,
|
|
30
30
|
navigation,
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import {NavigationProp} from '@react-navigation/native';
|
|
3
|
-
import {NavigationOptions
|
|
4
|
-
import {HeaderRightAction} from './index';
|
|
2
|
+
import {NavigationOptions} from './types';
|
|
5
3
|
import {getOptions} from './utils';
|
|
6
|
-
import {HeaderToolkitAction} from './Components';
|
|
7
4
|
|
|
8
5
|
class Navigation {
|
|
9
6
|
instance: NavigationProp<any>;
|
|
10
|
-
|
|
7
|
+
onHeaderRightChange?: (width: number) => void;
|
|
11
8
|
|
|
12
|
-
constructor(instance: any
|
|
9
|
+
constructor(instance: any) {
|
|
13
10
|
this.instance = instance;
|
|
14
|
-
this.theme = theme;
|
|
15
11
|
}
|
|
16
12
|
|
|
17
13
|
/**
|
|
@@ -19,16 +15,6 @@ class Navigation {
|
|
|
19
15
|
* @param params
|
|
20
16
|
*/
|
|
21
17
|
private filterParams = (params: NavigationOptions) => {
|
|
22
|
-
if (params.headerRight) {
|
|
23
|
-
const headerRight = params.headerRight?.({}) as React.ReactElement;
|
|
24
|
-
const type = headerRight?.type;
|
|
25
|
-
if (type !== HeaderRightAction && type !== HeaderToolkitAction) {
|
|
26
|
-
console.warn(
|
|
27
|
-
'headerRight contains element type of HeaderRightAction | HeaderToolkitAction, Please check again.',
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
18
|
if (params.headerLeft) {
|
|
33
19
|
console.warn('headerLeft not allow override render by design system!');
|
|
34
20
|
delete params.headerLeft;
|
|
@@ -42,7 +28,7 @@ class Navigation {
|
|
|
42
28
|
* @param params
|
|
43
29
|
*/
|
|
44
30
|
setOptions = (params: NavigationOptions) => {
|
|
45
|
-
params = getOptions(this.filterParams(params), this
|
|
31
|
+
params = getOptions(this.filterParams(params), this);
|
|
46
32
|
this.instance.setOptions(params);
|
|
47
33
|
};
|
|
48
34
|
}
|
|
@@ -10,9 +10,9 @@ import StackScreen from './StackScreen';
|
|
|
10
10
|
import ModalScreen from './ModalScreen';
|
|
11
11
|
import Navigator from './Navigator';
|
|
12
12
|
import {getDialogOptions, getModalOptions, getStackOptions} from './utils';
|
|
13
|
-
import {
|
|
13
|
+
import {NavigationContainerProps} from './types';
|
|
14
14
|
import {ApplicationContext} from './index';
|
|
15
|
-
import
|
|
15
|
+
import Localize from './Localize';
|
|
16
16
|
|
|
17
17
|
const Stack = createStackNavigator();
|
|
18
18
|
|
|
@@ -21,15 +21,18 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
21
21
|
theme,
|
|
22
22
|
options,
|
|
23
23
|
maxApi,
|
|
24
|
-
localization,
|
|
25
24
|
initialParams,
|
|
25
|
+
localize = new Localize({vi: {}, en: {}}),
|
|
26
26
|
}) => {
|
|
27
27
|
const navigationRef = useRef<NavigationContainerRef>(null);
|
|
28
28
|
const isReady = useRef(false);
|
|
29
29
|
const navigator = useRef(new Navigator(navigationRef, isReady));
|
|
30
30
|
const [showGrid, setShowGrid] = useState(false);
|
|
31
31
|
const config = useRef<any>();
|
|
32
|
-
|
|
32
|
+
/**
|
|
33
|
+
* inject data for navigator
|
|
34
|
+
*/
|
|
35
|
+
navigator.current.maxApi = maxApi;
|
|
33
36
|
/**
|
|
34
37
|
* handle mini language & listen change
|
|
35
38
|
* engine only shake to enable grid view
|
|
@@ -39,7 +42,7 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
39
42
|
'onChangeGrid',
|
|
40
43
|
enable => {
|
|
41
44
|
setShowGrid(!!enable);
|
|
42
|
-
}
|
|
45
|
+
}
|
|
43
46
|
);
|
|
44
47
|
|
|
45
48
|
return () => {
|
|
@@ -47,22 +50,8 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
47
50
|
};
|
|
48
51
|
}, []);
|
|
49
52
|
|
|
50
|
-
/**
|
|
51
|
-
* inject data for navigator
|
|
52
|
-
*/
|
|
53
|
-
navigator.current.maxApi = maxApi;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* translate
|
|
57
|
-
* @param key
|
|
58
|
-
*/
|
|
59
53
|
const translate = (key: string) => {
|
|
60
|
-
|
|
61
|
-
const mergedLocalization: LocalizationObject = {
|
|
62
|
-
vi: {...localization?.vi, ...kitLocalization.vi},
|
|
63
|
-
en: {...localization?.en, ...kitLocalization.en},
|
|
64
|
-
};
|
|
65
|
-
return mergedLocalization?.[language]?.[key] || key;
|
|
54
|
+
return localize?.translate(key);
|
|
66
55
|
};
|
|
67
56
|
|
|
68
57
|
return (
|
|
@@ -87,7 +76,7 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
87
76
|
notification: theme.colors.error.primary,
|
|
88
77
|
},
|
|
89
78
|
}}
|
|
90
|
-
ref={
|
|
79
|
+
ref={navigationRef}
|
|
91
80
|
onReady={() => {
|
|
92
81
|
isReady.current = true;
|
|
93
82
|
}}
|
package/Application/Navigator.ts
CHANGED
|
@@ -12,7 +12,7 @@ class Navigator {
|
|
|
12
12
|
toolkitConfig?: HeaderToolkitProps;
|
|
13
13
|
maxApi?: any;
|
|
14
14
|
dismissData?: any;
|
|
15
|
-
toolkitCallback?: (
|
|
15
|
+
toolkitCallback?: (key: string) => void;
|
|
16
16
|
|
|
17
17
|
constructor(navigation: any, isReady: any) {
|
|
18
18
|
this.ref = navigation;
|
|
@@ -25,7 +25,7 @@ class Navigator {
|
|
|
25
25
|
*/
|
|
26
26
|
push = (params: ScreenParams) => {
|
|
27
27
|
if (this.isReady.current) {
|
|
28
|
-
this.ref.current
|
|
28
|
+
this.ref.current?.dispatch?.(StackActions.push('Stack', params));
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
31
|
|
|
@@ -35,7 +35,7 @@ class Navigator {
|
|
|
35
35
|
*/
|
|
36
36
|
replace = (params: ScreenParams) => {
|
|
37
37
|
if (this.isReady.current) {
|
|
38
|
-
this.ref.current
|
|
38
|
+
this.ref.current?.dispatch?.(StackActions.replace('Stack', params));
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
@@ -44,7 +44,7 @@ class Navigator {
|
|
|
44
44
|
*/
|
|
45
45
|
pop = (count?: number) => {
|
|
46
46
|
if (this.isReady.current) {
|
|
47
|
-
this.ref.current
|
|
47
|
+
this.ref.current?.dispatch?.(StackActions.pop(count ?? 1));
|
|
48
48
|
}
|
|
49
49
|
};
|
|
50
50
|
|
|
@@ -54,7 +54,7 @@ class Navigator {
|
|
|
54
54
|
*/
|
|
55
55
|
present = (params: ScreenParams) => {
|
|
56
56
|
if (this.isReady.current) {
|
|
57
|
-
this.ref.current
|
|
57
|
+
this.ref.current?.dispatch?.(StackActions.push('Dialog', params));
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
60
|
|
|
@@ -64,7 +64,7 @@ class Navigator {
|
|
|
64
64
|
*/
|
|
65
65
|
showModal = (params: ModalParams) => {
|
|
66
66
|
if (this.isReady.current) {
|
|
67
|
-
this.ref.current
|
|
67
|
+
this.ref.current?.dispatch?.(StackActions.push('Modal', params));
|
|
68
68
|
}
|
|
69
69
|
};
|
|
70
70
|
|
|
@@ -74,11 +74,11 @@ class Navigator {
|
|
|
74
74
|
*/
|
|
75
75
|
showBottomSheet = (params: BottomSheetParams) => {
|
|
76
76
|
if (this.isReady.current) {
|
|
77
|
-
this.ref.current
|
|
77
|
+
this.ref.current?.dispatch?.(
|
|
78
78
|
StackActions.push('Modal', {
|
|
79
79
|
...params,
|
|
80
80
|
isBottomSheet: true,
|
|
81
|
-
})
|
|
81
|
+
})
|
|
82
82
|
);
|
|
83
83
|
}
|
|
84
84
|
};
|
|
@@ -88,7 +88,7 @@ class Navigator {
|
|
|
88
88
|
*/
|
|
89
89
|
popToTop = () => {
|
|
90
90
|
if (this.isReady.current) {
|
|
91
|
-
this.ref.current
|
|
91
|
+
this.ref.current?.dispatch?.(StackActions.popToTop());
|
|
92
92
|
}
|
|
93
93
|
};
|
|
94
94
|
|
|
@@ -99,11 +99,11 @@ class Navigator {
|
|
|
99
99
|
*/
|
|
100
100
|
navigate = (name: string, params: any) => {
|
|
101
101
|
if (this.isReady.current) {
|
|
102
|
-
this.ref.current
|
|
102
|
+
this.ref.current?.dispatch?.(
|
|
103
103
|
CommonActions.navigate({
|
|
104
104
|
name,
|
|
105
105
|
params,
|
|
106
|
-
})
|
|
106
|
+
})
|
|
107
107
|
);
|
|
108
108
|
}
|
|
109
109
|
};
|
|
@@ -114,7 +114,7 @@ class Navigator {
|
|
|
114
114
|
*/
|
|
115
115
|
reset = (params: ScreenParams) => {
|
|
116
116
|
if (this.isReady.current) {
|
|
117
|
-
this.ref.current
|
|
117
|
+
this.ref.current?.dispatch?.(
|
|
118
118
|
CommonActions.reset({
|
|
119
119
|
index: 0,
|
|
120
120
|
routes: [
|
|
@@ -124,7 +124,7 @@ class Navigator {
|
|
|
124
124
|
params,
|
|
125
125
|
},
|
|
126
126
|
],
|
|
127
|
-
})
|
|
127
|
+
})
|
|
128
128
|
);
|
|
129
129
|
}
|
|
130
130
|
};
|
|
@@ -141,9 +141,7 @@ class Navigator {
|
|
|
141
141
|
* set callback function for toolkit
|
|
142
142
|
* @param callback
|
|
143
143
|
*/
|
|
144
|
-
setToolkitCallback = (
|
|
145
|
-
callback: (item: {key: string; action: string}) => void,
|
|
146
|
-
) => {
|
|
144
|
+
setToolkitCallback = (callback: (key: string) => void) => {
|
|
147
145
|
this.toolkitCallback = callback;
|
|
148
146
|
};
|
|
149
147
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, {useContext, useEffect, useLayoutEffect, useRef} from 'react';
|
|
2
2
|
import {useHeaderHeight} from '@react-navigation/stack';
|
|
3
|
-
import {InteractionManager, Linking, View} from 'react-native';
|
|
3
|
+
import {Alert, InteractionManager, Linking, View} from 'react-native';
|
|
4
4
|
import {ScreenParams} from './types';
|
|
5
5
|
import Navigation from './Navigation';
|
|
6
6
|
import {ApplicationContext, MiniAppContext, ScreenContext} from './index';
|
|
@@ -8,103 +8,30 @@ import {GridSystem} from '../Layout';
|
|
|
8
8
|
import {Text} from '../Text';
|
|
9
9
|
import {Colors, Radius, Spacing} from '../Consts';
|
|
10
10
|
|
|
11
|
-
/**
|
|
12
|
-
* Empty screen for unvalidated screen name
|
|
13
|
-
* @constructor
|
|
14
|
-
*/
|
|
15
|
-
const EmptyScreen: React.FC = () => {
|
|
16
|
-
return (
|
|
17
|
-
<View
|
|
18
|
-
style={{
|
|
19
|
-
backgroundColor: Colors.black_01,
|
|
20
|
-
padding: Spacing.M,
|
|
21
|
-
borderRadius: Radius.M,
|
|
22
|
-
}}>
|
|
23
|
-
<Text typography={'header_m_bold'}>Unvalidated screen name</Text>
|
|
24
|
-
<Text
|
|
25
|
-
typography={'description_default_regular'}
|
|
26
|
-
style={{paddingVertical: Spacing.S}}>
|
|
27
|
-
Your screen has not been rendered because Platform has not detected the
|
|
28
|
-
screen name. Please migrate to support this feature.
|
|
29
|
-
</Text>
|
|
30
|
-
<Text typography={'header_default'} style={{width: '100%'}}>
|
|
31
|
-
Possible fixes:
|
|
32
|
-
</Text>
|
|
33
|
-
<View style={{marginLeft: Spacing.S}}>
|
|
34
|
-
<Text typography={'body_default_regular'}>1. Off webpack config</Text>
|
|
35
|
-
<Text typography={'body_default_regular'}>
|
|
36
|
-
2. Screen name refactoring
|
|
37
|
-
</Text>
|
|
38
|
-
<View style={{marginLeft: Spacing.S}}>
|
|
39
|
-
<Text
|
|
40
|
-
typography={'description_default_regular'}
|
|
41
|
-
style={{marginBottom: Spacing.S}}>
|
|
42
|
-
- Với các screen push/import dạng arrow function ={'>'} đổi thành
|
|
43
|
-
named function
|
|
44
|
-
</Text>
|
|
45
|
-
<Text
|
|
46
|
-
typography={'description_default_regular'}
|
|
47
|
-
style={{marginBottom: Spacing.S}}>
|
|
48
|
-
- Với các screen import dạng High Order Component ={'>'} rename
|
|
49
|
-
generic function thành named function
|
|
50
|
-
</Text>
|
|
51
|
-
<Text
|
|
52
|
-
typography={'description_default_regular'}
|
|
53
|
-
style={{marginBottom: Spacing.S}}>
|
|
54
|
-
- Với Tab Navigator, Platform sẽ lấy Tab Container làm screen name.
|
|
55
|
-
Trong trường hợp miniapp muốn track riêng action cho từng tab, tham
|
|
56
|
-
khảo theo docs
|
|
57
|
-
</Text>
|
|
58
|
-
</View>
|
|
59
|
-
</View>
|
|
60
|
-
<Text typography={'header_s_semibold'}>More information: </Text>
|
|
61
|
-
<Text
|
|
62
|
-
typography={'body_default_regular'}
|
|
63
|
-
color={Colors.blue_01}
|
|
64
|
-
onPress={() => {
|
|
65
|
-
Linking.openURL(
|
|
66
|
-
'https://gitlab.mservice.com.vn/momo-platform/mini-app/-/tree/vn.momo.uikits/dev/app'
|
|
67
|
-
);
|
|
68
|
-
}}>
|
|
69
|
-
Mini App: vn.momo.uikits/dev
|
|
70
|
-
</Text>
|
|
71
|
-
<Text
|
|
72
|
-
typography={'body_default_regular'}
|
|
73
|
-
color={Colors.blue_01}
|
|
74
|
-
onPress={() => {
|
|
75
|
-
Linking.openURL(
|
|
76
|
-
'https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing'
|
|
77
|
-
);
|
|
78
|
-
}}>
|
|
79
|
-
https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing
|
|
80
|
-
</Text>
|
|
81
|
-
</View>
|
|
82
|
-
);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
11
|
/**
|
|
86
12
|
* container for stack screen
|
|
87
13
|
* @param props
|
|
88
14
|
* @constructor
|
|
89
15
|
*/
|
|
90
16
|
const StackScreen: React.FC<ScreenParams> = props => {
|
|
91
|
-
const {
|
|
92
|
-
const
|
|
93
|
-
const endTime = useRef(Date.now());
|
|
94
|
-
const timeLoad = useRef(0);
|
|
95
|
-
const timeInteraction = useRef(0);
|
|
96
|
-
const timeoutLoad = useRef<any>();
|
|
97
|
-
const tracked = useRef<any>({
|
|
98
|
-
releaseLoad: undefined,
|
|
99
|
-
releaseInteraction: undefined,
|
|
17
|
+
const {showGrid, navigator} = useContext(ApplicationContext);
|
|
18
|
+
const tracking = useRef<any>({
|
|
100
19
|
timeoutLoad: undefined,
|
|
101
20
|
timeoutInteraction: undefined,
|
|
21
|
+
timeoutTracking: undefined,
|
|
22
|
+
startTime: Date.now(),
|
|
23
|
+
endTime: Date.now(),
|
|
24
|
+
traceIdLoad: undefined,
|
|
25
|
+
traceIdInteraction: undefined,
|
|
26
|
+
releaseLoad: undefined,
|
|
27
|
+
releaseInteraction: undefined,
|
|
28
|
+
timeLoad: 0,
|
|
29
|
+
timeInteraction: 0,
|
|
102
30
|
});
|
|
103
|
-
const interaction = useRef<any>();
|
|
104
|
-
const context = useContext<any>(MiniAppContext);
|
|
105
31
|
|
|
32
|
+
const context = useContext<any>(MiniAppContext);
|
|
106
33
|
const {screen: Component, options, initialParams} = props.route.params;
|
|
107
|
-
const navigation = new Navigation(props.navigation
|
|
34
|
+
const navigation = new Navigation(props.navigation);
|
|
108
35
|
const heightHeader = useHeaderHeight();
|
|
109
36
|
|
|
110
37
|
const data = {
|
|
@@ -117,14 +44,24 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
117
44
|
delete data.initialParams;
|
|
118
45
|
|
|
119
46
|
const screenName = Component?.name || Component?.type?.name || 'Invalid';
|
|
47
|
+
const routes = props.navigation.getState()?.routes || [];
|
|
120
48
|
|
|
121
49
|
/**
|
|
122
50
|
* set options for screen
|
|
123
51
|
*/
|
|
124
52
|
useLayoutEffect(() => {
|
|
53
|
+
let defaultOptions = {
|
|
54
|
+
headerRight: {
|
|
55
|
+
type: 'toolkit',
|
|
56
|
+
},
|
|
57
|
+
};
|
|
125
58
|
if (options) {
|
|
126
|
-
|
|
59
|
+
defaultOptions = {
|
|
60
|
+
...defaultOptions,
|
|
61
|
+
...options,
|
|
62
|
+
};
|
|
127
63
|
}
|
|
64
|
+
navigation.setOptions(defaultOptions);
|
|
128
65
|
}, [options]);
|
|
129
66
|
|
|
130
67
|
/**
|
|
@@ -137,17 +74,38 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
137
74
|
}, 300);
|
|
138
75
|
}
|
|
139
76
|
|
|
140
|
-
|
|
141
|
-
|
|
77
|
+
const subscription = props.navigation?.addListener?.('focus', () => {
|
|
78
|
+
navigator?.maxApi?.of?.({screenName});
|
|
79
|
+
navigator?.maxApi?.getDataObserver('CURRENT_SCREEN', (data: any) => {
|
|
80
|
+
let preScreenName = data?.screenName;
|
|
81
|
+
if (routes?.length > 1) {
|
|
82
|
+
const screen = routes?.[routes?.length - 2]?.params?.screen;
|
|
83
|
+
preScreenName = screen?.name || screen?.type?.name || 'Invalid';
|
|
84
|
+
}
|
|
85
|
+
onScreenNavigated(preScreenName);
|
|
86
|
+
navigator?.maxApi?.setObserver('CURRENT_SCREEN', {screenName});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
navigator?.maxApi?.startTraceScreenLoad?.(screenName, (data: any) => {
|
|
90
|
+
tracking.current.traceIdLoad = data?.traceId;
|
|
91
|
+
});
|
|
92
|
+
navigator?.maxApi?.startTraceScreenInteraction?.(
|
|
93
|
+
screenName,
|
|
94
|
+
(data: any) => {
|
|
95
|
+
tracking.current.traceIdInteraction = data?.traceId;
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
tracking.current.timeoutTracking = setTimeout(() => {
|
|
142
100
|
onScreenLoad();
|
|
143
|
-
}, 5000);
|
|
144
|
-
tracked.current.timeoutInteraction = setTimeout(() => {
|
|
145
101
|
onScreenInteraction();
|
|
146
102
|
}, 5000);
|
|
147
103
|
|
|
148
104
|
return () => {
|
|
149
105
|
onScreenLoad();
|
|
150
106
|
onScreenInteraction();
|
|
107
|
+
clearTimeout(tracking.current.timeoutTracking);
|
|
108
|
+
subscription?.();
|
|
151
109
|
};
|
|
152
110
|
}, []);
|
|
153
111
|
|
|
@@ -155,8 +113,12 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
155
113
|
* tracking for screen load
|
|
156
114
|
*/
|
|
157
115
|
const onScreenLoad = () => {
|
|
158
|
-
|
|
159
|
-
|
|
116
|
+
if (!tracking.current?.releaseLoad) {
|
|
117
|
+
if (tracking.current.timeLoad === 0) {
|
|
118
|
+
tracking.current.timeLoad =
|
|
119
|
+
tracking.current.endTime - tracking.current.startTime;
|
|
120
|
+
}
|
|
121
|
+
|
|
160
122
|
context.autoTracking?.({
|
|
161
123
|
appId: context.appId,
|
|
162
124
|
code: context.code,
|
|
@@ -164,13 +126,26 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
164
126
|
screenName,
|
|
165
127
|
componentName: 'Screen',
|
|
166
128
|
state: 'load',
|
|
167
|
-
duration:
|
|
129
|
+
duration: tracking.current.timeLoad,
|
|
168
130
|
});
|
|
131
|
+
navigator?.maxApi?.stopTrace?.(
|
|
132
|
+
tracking.current.traceIdLoad,
|
|
133
|
+
{value: tracking.current.timeLoad / 1000},
|
|
134
|
+
null
|
|
135
|
+
);
|
|
136
|
+
tracking.current.releaseLoad = true;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* debug
|
|
140
|
+
*/
|
|
169
141
|
navigator?.maxApi?.showToastDebug?.({
|
|
170
|
-
appId:
|
|
171
|
-
message: `${screenName} screen_load_time ${
|
|
142
|
+
appId: context.appId,
|
|
143
|
+
message: `${screenName} screen_load_time ${tracking.current.timeLoad}`,
|
|
144
|
+
type: 'ERROR',
|
|
172
145
|
});
|
|
173
|
-
|
|
146
|
+
if (tracking.current.timeLoad <= 0 && context.enableAutoId) {
|
|
147
|
+
Alert.alert(screenName, "Can't get screen load time");
|
|
148
|
+
}
|
|
174
149
|
}
|
|
175
150
|
};
|
|
176
151
|
|
|
@@ -178,8 +153,15 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
178
153
|
* tracking for screen load
|
|
179
154
|
*/
|
|
180
155
|
const onScreenInteraction = () => {
|
|
181
|
-
|
|
182
|
-
|
|
156
|
+
if (!tracking.current?.releaseInteraction) {
|
|
157
|
+
if (tracking.current.timeLoad === 0) {
|
|
158
|
+
tracking.current.timeLoad =
|
|
159
|
+
tracking.current.endTime - tracking.current.startTime;
|
|
160
|
+
}
|
|
161
|
+
if (tracking.current.timeInteraction === 0) {
|
|
162
|
+
tracking.current.timeInteraction = tracking.current.timeLoad;
|
|
163
|
+
}
|
|
164
|
+
|
|
183
165
|
context.autoTracking?.({
|
|
184
166
|
appId: context.appId,
|
|
185
167
|
code: context.code,
|
|
@@ -187,32 +169,74 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
187
169
|
screenName,
|
|
188
170
|
componentName: 'Screen',
|
|
189
171
|
state: 'interaction',
|
|
190
|
-
duration:
|
|
172
|
+
duration: tracking.current.timeInteraction - tracking.current.timeLoad,
|
|
173
|
+
totalDuration: tracking.current.timeInteraction,
|
|
191
174
|
});
|
|
175
|
+
navigator?.maxApi?.stopTrace?.(
|
|
176
|
+
tracking.current.traceIdInteraction,
|
|
177
|
+
{value: tracking.current.timeInteraction / 1000},
|
|
178
|
+
null
|
|
179
|
+
);
|
|
180
|
+
tracking.current.releaseInteraction = true;
|
|
192
181
|
|
|
182
|
+
/**
|
|
183
|
+
* debug toast
|
|
184
|
+
*/
|
|
193
185
|
navigator?.maxApi?.showToastDebug?.({
|
|
194
|
-
appId:
|
|
195
|
-
message: `${screenName} screen_interaction_time ${
|
|
186
|
+
appId: context.appId,
|
|
187
|
+
message: `${screenName} screen_interaction_time ${tracking.current.timeInteraction}`,
|
|
188
|
+
type: 'ERROR',
|
|
196
189
|
});
|
|
197
|
-
|
|
190
|
+
if (tracking.current.timeInteraction <= 0 && context.enableAutoId) {
|
|
191
|
+
Alert.alert(screenName, "Can't get screen interaction time");
|
|
192
|
+
}
|
|
198
193
|
}
|
|
199
194
|
};
|
|
200
195
|
|
|
196
|
+
/**
|
|
197
|
+
* tracking for screen navigated
|
|
198
|
+
*/
|
|
199
|
+
const onScreenNavigated = (preScreenName: string) => {
|
|
200
|
+
context.autoTracking?.({
|
|
201
|
+
appId: context.appId,
|
|
202
|
+
code: context.code,
|
|
203
|
+
buildNumber: context.buildNumber,
|
|
204
|
+
preScreenName,
|
|
205
|
+
screenName,
|
|
206
|
+
componentName: 'Screen',
|
|
207
|
+
state: 'navigated',
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* debug toast
|
|
212
|
+
*/
|
|
213
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
214
|
+
appId: context.appId,
|
|
215
|
+
message: `${screenName} screen_navigated`,
|
|
216
|
+
type: 'ERROR',
|
|
217
|
+
});
|
|
218
|
+
};
|
|
219
|
+
|
|
201
220
|
return (
|
|
202
221
|
<ScreenContext.Provider
|
|
203
222
|
value={{
|
|
204
223
|
screenName,
|
|
205
224
|
onElementLoad: () => {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
225
|
+
clearTimeout(tracking.current.timeoutLoad);
|
|
226
|
+
tracking.current.endTime = Date.now();
|
|
227
|
+
tracking.current.timeoutInteraction?.cancel?.();
|
|
228
|
+
tracking.current.timeoutInteraction =
|
|
229
|
+
InteractionManager.runAfterInteractions(() => {
|
|
230
|
+
tracking.current.timeInteraction =
|
|
231
|
+
Date.now() - tracking.current.startTime;
|
|
232
|
+
});
|
|
233
|
+
tracking.current.timeoutLoad = setTimeout(() => {
|
|
234
|
+
if (tracking.current.timeLoad === 0) {
|
|
235
|
+
tracking.current.timeLoad =
|
|
236
|
+
tracking.current.endTime - tracking.current.startTime;
|
|
215
237
|
}
|
|
238
|
+
onScreenLoad();
|
|
239
|
+
onScreenInteraction();
|
|
216
240
|
}, 2000);
|
|
217
241
|
},
|
|
218
242
|
}}>
|
|
@@ -227,4 +251,78 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
227
251
|
);
|
|
228
252
|
};
|
|
229
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Empty screen for unvalidated screen name
|
|
256
|
+
* @constructor
|
|
257
|
+
*/
|
|
258
|
+
const EmptyScreen: React.FC = () => {
|
|
259
|
+
return (
|
|
260
|
+
<View
|
|
261
|
+
style={{
|
|
262
|
+
backgroundColor: Colors.black_01,
|
|
263
|
+
padding: Spacing.M,
|
|
264
|
+
borderRadius: Radius.M,
|
|
265
|
+
}}>
|
|
266
|
+
<Text typography={'header_m_bold'}>Unvalidated screen name</Text>
|
|
267
|
+
<Text
|
|
268
|
+
typography={'description_default_regular'}
|
|
269
|
+
style={{paddingVertical: Spacing.S}}>
|
|
270
|
+
Your screen has not been rendered because Platform has not detected the
|
|
271
|
+
screen name. Please migrate to support this feature.
|
|
272
|
+
</Text>
|
|
273
|
+
<Text typography={'header_default'} style={{width: '100%'}}>
|
|
274
|
+
Possible fixes:
|
|
275
|
+
</Text>
|
|
276
|
+
<View style={{marginLeft: Spacing.S}}>
|
|
277
|
+
<Text typography={'body_default_regular'}>1. Off webpack config</Text>
|
|
278
|
+
<Text typography={'body_default_regular'}>
|
|
279
|
+
2. Screen name refactoring
|
|
280
|
+
</Text>
|
|
281
|
+
<View style={{marginLeft: Spacing.S}}>
|
|
282
|
+
<Text
|
|
283
|
+
typography={'description_default_regular'}
|
|
284
|
+
style={{marginBottom: Spacing.S}}>
|
|
285
|
+
- Với các screen push/import dạng arrow function ={'>'} đổi thành
|
|
286
|
+
named function
|
|
287
|
+
</Text>
|
|
288
|
+
<Text
|
|
289
|
+
typography={'description_default_regular'}
|
|
290
|
+
style={{marginBottom: Spacing.S}}>
|
|
291
|
+
- Với các screen import dạng High Order Component ={'>'} rename
|
|
292
|
+
generic function thành named function
|
|
293
|
+
</Text>
|
|
294
|
+
<Text
|
|
295
|
+
typography={'description_default_regular'}
|
|
296
|
+
style={{marginBottom: Spacing.S}}>
|
|
297
|
+
- Với Tab Navigator, Platform sẽ lấy Tab Container làm screen name.
|
|
298
|
+
Trong trường hợp miniapp muốn track riêng action cho từng tab, tham
|
|
299
|
+
khảo theo docs
|
|
300
|
+
</Text>
|
|
301
|
+
</View>
|
|
302
|
+
</View>
|
|
303
|
+
<Text typography={'header_s_semibold'}>More information: </Text>
|
|
304
|
+
<Text
|
|
305
|
+
typography={'body_default_regular'}
|
|
306
|
+
color={Colors.blue_01}
|
|
307
|
+
onPress={() => {
|
|
308
|
+
Linking.openURL(
|
|
309
|
+
'https://gitlab.mservice.com.vn/momo-platform/mini-app/-/tree/vn.momo.uikits/dev/app'
|
|
310
|
+
);
|
|
311
|
+
}}>
|
|
312
|
+
Mini App: vn.momo.uikits/dev
|
|
313
|
+
</Text>
|
|
314
|
+
<Text
|
|
315
|
+
typography={'body_default_regular'}
|
|
316
|
+
color={Colors.blue_01}
|
|
317
|
+
onPress={() => {
|
|
318
|
+
Linking.openURL(
|
|
319
|
+
'https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing'
|
|
320
|
+
);
|
|
321
|
+
}}>
|
|
322
|
+
https://docs.google.com/presentation/d/1bIFoh8gRXb6hsnGJz4O1Kxg4_oNikB1KuuEt2wULCDM/edit?usp=sharing
|
|
323
|
+
</Text>
|
|
324
|
+
</View>
|
|
325
|
+
);
|
|
326
|
+
};
|
|
327
|
+
|
|
230
328
|
export default StackScreen;
|