@momo-kits/foundation 0.121.3-beta.6 → 0.121.3-beta.8
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 +24 -5
- package/Application/BottomTab/index.tsx +56 -4
- package/Application/Components/HeaderRight.tsx +7 -4
- package/Application/ModalScreen.tsx +1 -1
- package/Application/NavigationContainer.tsx +0 -107
- package/Application/StackScreen.tsx +139 -6
- package/Application/index.ts +4 -0
- package/Application/types.ts +2 -0
- package/Application/utils.tsx +3 -2
- package/Layout/TrackingScope.tsx +18 -0
- package/Layout/index.ts +2 -0
- package/Skeleton/index.tsx +7 -3
- package/package.json +2 -2
|
@@ -28,6 +28,7 @@ import {BottomSheetParams} from './types';
|
|
|
28
28
|
import {Colors, Radius, Spacing, Styles} from '../Consts';
|
|
29
29
|
import {Text} from '../Text';
|
|
30
30
|
import {Icon} from '../Icon';
|
|
31
|
+
import layoutStyles from '../Layout/styles';
|
|
31
32
|
|
|
32
33
|
const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
33
34
|
const {theme, navigator} = useContext(ApplicationContext);
|
|
@@ -50,7 +51,8 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
50
51
|
useKeyboardAvoidingView = true,
|
|
51
52
|
useScrollOverflow = false,
|
|
52
53
|
keyboardVerticalOffset,
|
|
53
|
-
useDivider,
|
|
54
|
+
useDivider = true,
|
|
55
|
+
footerComponent,
|
|
54
56
|
}: BottomSheetParams = props.route.params;
|
|
55
57
|
|
|
56
58
|
const customEasingOpen = Easing.bezier(0.05, 0.7, 0.1, 1);
|
|
@@ -218,7 +220,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
218
220
|
return (
|
|
219
221
|
<View
|
|
220
222
|
style={{
|
|
221
|
-
backgroundColor
|
|
223
|
+
backgroundColor,
|
|
222
224
|
borderTopLeftRadius: Radius.M,
|
|
223
225
|
borderTopRightRadius: Radius.M,
|
|
224
226
|
}}
|
|
@@ -312,10 +314,27 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
312
314
|
{...props.route.params}
|
|
313
315
|
onRequestClose={onRequestClose}
|
|
314
316
|
/>
|
|
315
|
-
{useBottomInset && (
|
|
316
|
-
<View style={{height: Math.min(insets.bottom, 21)}} />
|
|
317
|
-
)}
|
|
318
317
|
</Content>
|
|
318
|
+
{footerComponent && (
|
|
319
|
+
<View
|
|
320
|
+
style={[
|
|
321
|
+
layoutStyles.shadow,
|
|
322
|
+
{
|
|
323
|
+
paddingBottom: Spacing.S,
|
|
324
|
+
backgroundColor: theme.colors.background.surface,
|
|
325
|
+
},
|
|
326
|
+
]}>
|
|
327
|
+
{footerComponent}
|
|
328
|
+
</View>
|
|
329
|
+
)}
|
|
330
|
+
{useBottomInset && (
|
|
331
|
+
<View
|
|
332
|
+
style={{
|
|
333
|
+
height: Math.min(insets.bottom, 21),
|
|
334
|
+
backgroundColor: backgroundColor,
|
|
335
|
+
}}
|
|
336
|
+
/>
|
|
337
|
+
)}
|
|
319
338
|
</Animated.View>
|
|
320
339
|
</KeyboardAvoidingView>
|
|
321
340
|
</Container>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
|
|
2
2
|
import {NavigationContainer, useFocusEffect} from '@react-navigation/native';
|
|
3
3
|
import {createStackNavigator} from '@react-navigation/stack';
|
|
4
|
-
import React, {useContext, useEffect} from 'react';
|
|
4
|
+
import React, {useContext, useEffect, useRef} from 'react';
|
|
5
5
|
import {Animated, Platform, StatusBar} from 'react-native';
|
|
6
6
|
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
7
7
|
import {Colors} from '../../Consts';
|
|
8
8
|
import {Icon} from '../../Icon';
|
|
9
9
|
import {exportFontFamily, Text} from '../../Text';
|
|
10
|
-
import {ApplicationContext} from '../index';
|
|
10
|
+
import {ApplicationContext, MiniAppContext} from '../index';
|
|
11
11
|
import StackScreen from '../StackScreen';
|
|
12
12
|
import {BottomTabProps} from '../types';
|
|
13
13
|
import {getOptions, getStackOptions} from '../utils';
|
|
@@ -17,13 +17,16 @@ const Tab = createBottomTabNavigator();
|
|
|
17
17
|
const Stack = createStackNavigator();
|
|
18
18
|
|
|
19
19
|
const TabScreen: React.FC<any> = ({route, navigation}) => {
|
|
20
|
+
const {navigator} = useContext(ApplicationContext);
|
|
21
|
+
const context = useContext<any>(MiniAppContext);
|
|
20
22
|
const {nested, options, screen, initialParams} = route?.params;
|
|
21
23
|
const useAnimation = route?.params?.useAnimation ?? true;
|
|
22
24
|
|
|
23
25
|
const opacityValue = 0.3;
|
|
24
26
|
const scaleValue = 0.97;
|
|
25
|
-
const opacity = new Animated.Value(opacityValue);
|
|
26
|
-
const scale = new Animated.Value(scaleValue);
|
|
27
|
+
const opacity = useRef(new Animated.Value(opacityValue)).current;
|
|
28
|
+
const scale = useRef(new Animated.Value(scaleValue)).current;
|
|
29
|
+
const screenName = screen?.name || screen?.type?.name || 'Invalid';
|
|
27
30
|
|
|
28
31
|
useFocusEffect(
|
|
29
32
|
React.useCallback(() => {
|
|
@@ -39,6 +42,14 @@ const TabScreen: React.FC<any> = ({route, navigation}) => {
|
|
|
39
42
|
useNativeDriver: true,
|
|
40
43
|
}),
|
|
41
44
|
]).start();
|
|
45
|
+
|
|
46
|
+
setTimeout(() => {
|
|
47
|
+
navigator?.maxApi?.getDataObserver?.('current_screen', (data: any) => {
|
|
48
|
+
onScreenNavigated(data?.screenName, screenName);
|
|
49
|
+
navigator?.maxApi?.setObserver?.('current_screen', {screenName});
|
|
50
|
+
});
|
|
51
|
+
}, 100);
|
|
52
|
+
|
|
42
53
|
return () => {
|
|
43
54
|
if (navigation.getState().index !== route?.params.index) {
|
|
44
55
|
Animated.parallel([
|
|
@@ -58,6 +69,45 @@ const TabScreen: React.FC<any> = ({route, navigation}) => {
|
|
|
58
69
|
}, [navigation])
|
|
59
70
|
);
|
|
60
71
|
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
const onFocusApp = navigator?.maxApi?.listen?.('onFocusApp', () => {
|
|
74
|
+
if (navigation.isFocused()) {
|
|
75
|
+
navigator?.maxApi?.getDataObserver?.('current_screen', (data: any) => {
|
|
76
|
+
onScreenNavigated(data?.screenName, screenName);
|
|
77
|
+
navigator?.maxApi?.setObserver?.('current_screen', {screenName});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return () => {
|
|
83
|
+
onFocusApp?.();
|
|
84
|
+
};
|
|
85
|
+
}, []);
|
|
86
|
+
|
|
87
|
+
const onScreenNavigated = (preScreenName: string, screenName: string) => {
|
|
88
|
+
const data: any = {
|
|
89
|
+
preScreenName,
|
|
90
|
+
screenName,
|
|
91
|
+
componentName: 'Screen',
|
|
92
|
+
state: 'navigated',
|
|
93
|
+
action: 'push',
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
context?.autoTracking?.({
|
|
97
|
+
...context,
|
|
98
|
+
...data,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* debug toast
|
|
103
|
+
*/
|
|
104
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
105
|
+
appId: context.appId,
|
|
106
|
+
message: `${screenName} screen_navigated`,
|
|
107
|
+
type: 'ERROR',
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
|
|
61
111
|
let opacityStyle: undefined | Animated.Value = undefined;
|
|
62
112
|
let scaleStyle: number | Animated.Value = 1;
|
|
63
113
|
if (useAnimation) {
|
|
@@ -86,6 +136,7 @@ const TabScreen: React.FC<any> = ({route, navigation}) => {
|
|
|
86
136
|
screen,
|
|
87
137
|
options: stackOptions,
|
|
88
138
|
initialParams,
|
|
139
|
+
bottomTab: 'nested',
|
|
89
140
|
}}
|
|
90
141
|
options={{...getStackOptions()}}
|
|
91
142
|
/>
|
|
@@ -110,6 +161,7 @@ const TabScreen: React.FC<any> = ({route, navigation}) => {
|
|
|
110
161
|
screen,
|
|
111
162
|
options: stackOptions,
|
|
112
163
|
initialParams,
|
|
164
|
+
bottomTab: 'default',
|
|
113
165
|
}}
|
|
114
166
|
options={{...getStackOptions(), ...options}}
|
|
115
167
|
/>
|
|
@@ -55,6 +55,7 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
55
55
|
useShortcut = false,
|
|
56
56
|
useMore = false,
|
|
57
57
|
tools = [],
|
|
58
|
+
useCloseIcon = false,
|
|
58
59
|
}) => {
|
|
59
60
|
const {navigator} = useContext(ApplicationContext);
|
|
60
61
|
const context = useContext<any>(MiniAppContext);
|
|
@@ -104,14 +105,14 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
104
105
|
);
|
|
105
106
|
|
|
106
107
|
const onDismiss = () => {
|
|
107
|
-
if (isWhiteList) {
|
|
108
|
-
navigator?.maxApi?.dispatchFunction?.('dismissAll');
|
|
109
|
-
} else {
|
|
108
|
+
if (useCloseIcon && !isWhiteList) {
|
|
110
109
|
navigator?.maxApi?.dispatchFunction?.(
|
|
111
110
|
'dismiss',
|
|
112
111
|
navigator?.dismissData,
|
|
113
112
|
undefined
|
|
114
113
|
);
|
|
114
|
+
} else {
|
|
115
|
+
navigator?.maxApi?.dispatchFunction?.('dismissAll');
|
|
115
116
|
}
|
|
116
117
|
};
|
|
117
118
|
|
|
@@ -299,7 +300,9 @@ const HeaderToolkitAction: React.FC<any> = ({
|
|
|
299
300
|
<Icon
|
|
300
301
|
color={tintColor}
|
|
301
302
|
source={
|
|
302
|
-
|
|
303
|
+
useCloseIcon && !isWhiteList
|
|
304
|
+
? '16_navigation_close_circle'
|
|
305
|
+
: '16_basic_home'
|
|
303
306
|
}
|
|
304
307
|
size={20}
|
|
305
308
|
/>
|
|
@@ -96,7 +96,7 @@ const Modal: React.FC<ModalParams> = props => {
|
|
|
96
96
|
style={StyleSheet.absoluteFillObject}>
|
|
97
97
|
<KeyboardAvoidingView
|
|
98
98
|
style={Styles.flexCenter}
|
|
99
|
-
behavior={Platform.OS === 'ios' ? 'padding' :
|
|
99
|
+
behavior={Platform.OS === 'ios' ? 'padding' : undefined}>
|
|
100
100
|
<Pressable
|
|
101
101
|
style={StyleSheet.absoluteFillObject}
|
|
102
102
|
onPress={() => onDismiss(undefined, barrierDismissible)}>
|
|
@@ -30,7 +30,6 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
30
30
|
}) => {
|
|
31
31
|
const context = useContext<any>(MiniAppContext);
|
|
32
32
|
const navigationRef = useRef<NavigationContainerRef>(null);
|
|
33
|
-
const routes = useRef<any>(undefined);
|
|
34
33
|
const isReady = useRef(false);
|
|
35
34
|
const navigator = useRef(new Navigator(navigationRef, isReady));
|
|
36
35
|
const [showGrid, setShowGrid] = useState(false);
|
|
@@ -62,21 +61,8 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
62
61
|
}
|
|
63
62
|
);
|
|
64
63
|
|
|
65
|
-
const onFocusApp = maxApi?.listen?.('onFocusApp', () => {
|
|
66
|
-
const routes = navigationRef.current?.getRootState?.()?.routes;
|
|
67
|
-
const currentRoute: any = routes?.[routes?.length - 1];
|
|
68
|
-
const current = currentRoute?.params?.screen;
|
|
69
|
-
const screenName = current?.name ?? current?.type?.name;
|
|
70
|
-
|
|
71
|
-
maxApi?.getDataObserver?.('current_screen', (data: any) => {
|
|
72
|
-
onScreenNavigated(data?.screenName, screenName, 'push', 'Screen');
|
|
73
|
-
maxApi?.setObserver?.('current_screen', {screenName});
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
64
|
return () => {
|
|
78
65
|
subscription?.remove?.();
|
|
79
|
-
onFocusApp?.remove?.();
|
|
80
66
|
};
|
|
81
67
|
}, []);
|
|
82
68
|
|
|
@@ -87,49 +73,6 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
87
73
|
return localize?.translate(data as string);
|
|
88
74
|
};
|
|
89
75
|
|
|
90
|
-
/**
|
|
91
|
-
* navigation state route change handle
|
|
92
|
-
* @param preScreenName
|
|
93
|
-
* @param screenName
|
|
94
|
-
* @param action
|
|
95
|
-
* @param type
|
|
96
|
-
*/
|
|
97
|
-
const onScreenNavigated = (
|
|
98
|
-
preScreenName: string,
|
|
99
|
-
screenName: string,
|
|
100
|
-
action: string,
|
|
101
|
-
type: 'Screen' | 'Modal' | 'BottomSheet'
|
|
102
|
-
) => {
|
|
103
|
-
let data: any = {
|
|
104
|
-
preScreenName,
|
|
105
|
-
screenName,
|
|
106
|
-
componentName: type,
|
|
107
|
-
state: 'navigated',
|
|
108
|
-
};
|
|
109
|
-
if (type !== 'Screen') {
|
|
110
|
-
data = {
|
|
111
|
-
preScreenName,
|
|
112
|
-
screenName,
|
|
113
|
-
componentName: type,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
context?.autoTracking?.({
|
|
118
|
-
...context,
|
|
119
|
-
...data,
|
|
120
|
-
action,
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* debug toast
|
|
125
|
-
*/
|
|
126
|
-
maxApi?.showToastDebug?.({
|
|
127
|
-
appId: context.appId,
|
|
128
|
-
message: `${screenName} screen_navigated`,
|
|
129
|
-
type: 'ERROR',
|
|
130
|
-
});
|
|
131
|
-
};
|
|
132
|
-
|
|
133
76
|
navigator.current.setCurrentContext = setCurrentContext;
|
|
134
77
|
|
|
135
78
|
return (
|
|
@@ -171,56 +114,6 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
171
114
|
ref={navigationRef}
|
|
172
115
|
onReady={() => {
|
|
173
116
|
isReady.current = true;
|
|
174
|
-
routes.current = navigationRef.current?.getRootState?.()?.routes;
|
|
175
|
-
const screenName = screen?.name ?? (screen as any)?.type?.name;
|
|
176
|
-
maxApi?.getDataObserver?.('current_screen', (data: any) => {
|
|
177
|
-
onScreenNavigated(
|
|
178
|
-
data?.screenName,
|
|
179
|
-
screenName,
|
|
180
|
-
'push',
|
|
181
|
-
'Screen'
|
|
182
|
-
);
|
|
183
|
-
maxApi?.setObserver?.('current_screen', {screenName});
|
|
184
|
-
});
|
|
185
|
-
}}
|
|
186
|
-
onStateChange={state => {
|
|
187
|
-
const lastedRoute: any = state?.routes?.[state?.index];
|
|
188
|
-
const oldRoute: any =
|
|
189
|
-
routes.current?.[routes.current?.length - 1];
|
|
190
|
-
const lasted = lastedRoute?.params?.screen;
|
|
191
|
-
const previous = oldRoute?.params?.screen;
|
|
192
|
-
const preScreenName = previous?.name ?? previous?.type?.name;
|
|
193
|
-
const screenName = lasted?.name ?? lasted?.type?.name;
|
|
194
|
-
|
|
195
|
-
let action: string;
|
|
196
|
-
let type: 'Screen' | 'Modal' | 'BottomSheet';
|
|
197
|
-
|
|
198
|
-
if (lastedRoute?.name === 'Modal') {
|
|
199
|
-
type = 'Modal';
|
|
200
|
-
action = 'open';
|
|
201
|
-
if (lastedRoute?.params?.isBottomSheet) {
|
|
202
|
-
type = 'BottomSheet';
|
|
203
|
-
}
|
|
204
|
-
} else if (oldRoute?.name === 'Modal') {
|
|
205
|
-
action = 'close';
|
|
206
|
-
type = 'Modal';
|
|
207
|
-
if (oldRoute?.params?.isBottomSheet) {
|
|
208
|
-
type = 'BottomSheet';
|
|
209
|
-
}
|
|
210
|
-
} else {
|
|
211
|
-
type = 'Screen';
|
|
212
|
-
if (routes.current?.length > (state?.routes?.length ?? 0)) {
|
|
213
|
-
action = 'back';
|
|
214
|
-
} else {
|
|
215
|
-
action = 'push';
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
onScreenNavigated(preScreenName, screenName, action, type);
|
|
220
|
-
|
|
221
|
-
routes.current = state?.routes;
|
|
222
|
-
maxApi?.of?.({screenName});
|
|
223
|
-
maxApi?.setObserver?.('current_screen', {screenName});
|
|
224
117
|
}}
|
|
225
118
|
independent={true}>
|
|
226
119
|
<Stack.Navigator initialRouteName="Stack" headerMode="screen">
|
|
@@ -17,24 +17,36 @@ const runAfterInteractions = InteractionManager.runAfterInteractions;
|
|
|
17
17
|
const StackScreen: React.FC<ScreenParams> = props => {
|
|
18
18
|
const {showGrid, navigator} = useContext(ApplicationContext);
|
|
19
19
|
const tracking = useRef<any>({
|
|
20
|
+
mounted: false,
|
|
20
21
|
timeoutLoad: undefined,
|
|
21
22
|
timeoutInteraction: undefined,
|
|
22
23
|
timeoutTracking: undefined,
|
|
24
|
+
timeoutLoading: undefined,
|
|
23
25
|
startTime: Date.now(),
|
|
24
26
|
endTime: Date.now(),
|
|
25
27
|
traceIdLoad: undefined,
|
|
26
28
|
traceIdInteraction: undefined,
|
|
27
29
|
releaseLoad: undefined,
|
|
28
30
|
releaseInteraction: undefined,
|
|
31
|
+
releaseUserInteraction: undefined,
|
|
32
|
+
releaseLoading: false,
|
|
29
33
|
timeLoad: 0,
|
|
30
34
|
timeInteraction: 0,
|
|
35
|
+
timeStartLoading: 0,
|
|
36
|
+
timeEndLoading: 0,
|
|
31
37
|
widgets: [],
|
|
32
38
|
params: undefined,
|
|
39
|
+
lastElement: undefined,
|
|
33
40
|
});
|
|
34
41
|
const widgets = useRef<any>([]);
|
|
35
42
|
const context = useContext<any>(MiniAppContext);
|
|
36
|
-
|
|
37
|
-
const {
|
|
43
|
+
|
|
44
|
+
const {
|
|
45
|
+
screen: Component,
|
|
46
|
+
options,
|
|
47
|
+
initialParams,
|
|
48
|
+
bottomTab,
|
|
49
|
+
} = props.route.params;
|
|
38
50
|
const navigation = new Navigation(props.navigation, context);
|
|
39
51
|
const heightHeader = useHeaderHeight();
|
|
40
52
|
|
|
@@ -62,6 +74,8 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
62
74
|
* tracking for screen
|
|
63
75
|
*/
|
|
64
76
|
useEffect(() => {
|
|
77
|
+
let focusScreen: any;
|
|
78
|
+
let onFocusApp: any;
|
|
65
79
|
if (['Invalid', 'screen'].includes(screenName)) {
|
|
66
80
|
navigator?.maxApi?.showPopup?.('notice', {
|
|
67
81
|
title: 'Invalid screen name',
|
|
@@ -70,6 +84,26 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
70
84
|
});
|
|
71
85
|
}
|
|
72
86
|
|
|
87
|
+
if (!bottomTab) {
|
|
88
|
+
focusScreen = props.navigation.addListener('focus', () => {
|
|
89
|
+
navigator?.maxApi?.getDataObserver?.('current_screen', (data: any) => {
|
|
90
|
+
onScreenNavigated(data?.screenName, screenName);
|
|
91
|
+
navigator?.maxApi?.setObserver?.('current_screen', {screenName});
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
onFocusApp = navigator?.maxApi?.listen?.('onFocusApp', () => {
|
|
95
|
+
if (props.navigation.isFocused()) {
|
|
96
|
+
navigator?.maxApi?.getDataObserver?.(
|
|
97
|
+
'current_screen',
|
|
98
|
+
(data: any) => {
|
|
99
|
+
onScreenNavigated(data?.screenName, screenName);
|
|
100
|
+
navigator?.maxApi?.setObserver?.('current_screen', {screenName});
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
73
107
|
navigator?.maxApi?.startTraceScreenLoad?.(
|
|
74
108
|
screenName,
|
|
75
109
|
context,
|
|
@@ -93,10 +127,41 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
93
127
|
return () => {
|
|
94
128
|
onScreenLoad();
|
|
95
129
|
onScreenInteraction();
|
|
130
|
+
clearTimeout(tracking.current.timeoutLoad);
|
|
131
|
+
clearTimeout(tracking.current.timeoutInteraction);
|
|
96
132
|
clearTimeout(tracking.current.timeoutTracking);
|
|
133
|
+
clearTimeout(tracking.current.timeoutLoading);
|
|
134
|
+
focusScreen?.();
|
|
135
|
+
onFocusApp?.();
|
|
97
136
|
};
|
|
98
137
|
}, []);
|
|
99
138
|
|
|
139
|
+
const onScreenNavigated = (preScreenName: string, screenName: string) => {
|
|
140
|
+
const data: any = {
|
|
141
|
+
preScreenName,
|
|
142
|
+
screenName,
|
|
143
|
+
componentName: 'Screen',
|
|
144
|
+
state: 'navigated',
|
|
145
|
+
action: tracking.current?.mounted ? 'back' : 'push',
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
context?.autoTracking?.({
|
|
149
|
+
...context,
|
|
150
|
+
...data,
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
tracking.current.mounted = true;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* debug toast
|
|
157
|
+
*/
|
|
158
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
159
|
+
appId: context.appId,
|
|
160
|
+
message: `${screenName} screen_navigated`,
|
|
161
|
+
type: 'ERROR',
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
|
|
100
165
|
/**
|
|
101
166
|
* tracking for screen load
|
|
102
167
|
*/
|
|
@@ -116,7 +181,7 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
116
181
|
widgets: tracking.current.widgets,
|
|
117
182
|
params: tracking.current.params,
|
|
118
183
|
version: version,
|
|
119
|
-
lastElement:
|
|
184
|
+
lastElement: tracking.current.lastElement,
|
|
120
185
|
});
|
|
121
186
|
navigator?.maxApi?.stopTrace?.(
|
|
122
187
|
tracking.current.traceIdLoad,
|
|
@@ -133,10 +198,13 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
133
198
|
message: `${screenName} screen_load_time ${timeLoad}`,
|
|
134
199
|
type: 'ERROR',
|
|
135
200
|
});
|
|
136
|
-
if (
|
|
201
|
+
if (
|
|
202
|
+
__DEV__ &&
|
|
203
|
+
tracking.current.lastElement?.children?.current?.length > 0
|
|
204
|
+
) {
|
|
137
205
|
Alert.alert(
|
|
138
206
|
`${screenName}- load ${timeLoad}ms`,
|
|
139
|
-
JSON.stringify(
|
|
207
|
+
JSON.stringify(tracking.current.lastElement?.children?.current)
|
|
140
208
|
);
|
|
141
209
|
}
|
|
142
210
|
}
|
|
@@ -183,6 +251,49 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
183
251
|
}
|
|
184
252
|
};
|
|
185
253
|
|
|
254
|
+
/**
|
|
255
|
+
* tracking for first interaction by user
|
|
256
|
+
*/
|
|
257
|
+
const onFirstInteraction = (action: string) => {
|
|
258
|
+
if (!tracking.current?.releaseUserInteraction) {
|
|
259
|
+
const timeLoad = tracking.current.endTime - tracking.current.startTime;
|
|
260
|
+
context?.autoTracking?.({
|
|
261
|
+
...context,
|
|
262
|
+
screenName,
|
|
263
|
+
componentName: 'Screen',
|
|
264
|
+
state: 'interaction',
|
|
265
|
+
duration: timeLoad,
|
|
266
|
+
action,
|
|
267
|
+
});
|
|
268
|
+
tracking.current.releaseUserInteraction = true;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* debug
|
|
272
|
+
*/
|
|
273
|
+
navigator?.maxApi?.showToastDebug?.({
|
|
274
|
+
appId: context.appId,
|
|
275
|
+
message: `${screenName} user_interaction ${timeLoad}`,
|
|
276
|
+
type: 'ERROR',
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const onScreenLoading = () => {
|
|
282
|
+
if (!tracking.current?.releaseLoading) {
|
|
283
|
+
const timeLoad =
|
|
284
|
+
tracking.current.timeEndLoading - tracking.current.timeStartLoading;
|
|
285
|
+
context?.autoTracking?.({
|
|
286
|
+
...context,
|
|
287
|
+
screenName,
|
|
288
|
+
componentName: 'Screen',
|
|
289
|
+
state: 'loading',
|
|
290
|
+
duration: timeLoad,
|
|
291
|
+
loadingType: 'skeleton',
|
|
292
|
+
});
|
|
293
|
+
tracking.current.releaseLoading = true;
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
186
297
|
return (
|
|
187
298
|
<ScreenContext.Provider
|
|
188
299
|
value={{
|
|
@@ -213,6 +324,7 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
213
324
|
}
|
|
214
325
|
return;
|
|
215
326
|
}
|
|
327
|
+
|
|
216
328
|
/**
|
|
217
329
|
* tracking for element screen load
|
|
218
330
|
*/
|
|
@@ -228,7 +340,7 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
228
340
|
* support for debug last element
|
|
229
341
|
*/
|
|
230
342
|
if (data?.componentName) {
|
|
231
|
-
|
|
343
|
+
tracking.current.lastElement = data;
|
|
232
344
|
}
|
|
233
345
|
|
|
234
346
|
/**
|
|
@@ -237,6 +349,7 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
237
349
|
if (data?.interaction) {
|
|
238
350
|
onScreenLoad();
|
|
239
351
|
onScreenInteraction();
|
|
352
|
+
onFirstInteraction(data?.action);
|
|
240
353
|
}
|
|
241
354
|
/**
|
|
242
355
|
* timeout for handle tracking screen
|
|
@@ -253,6 +366,26 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
253
366
|
onScreenInteraction();
|
|
254
367
|
}, 2000);
|
|
255
368
|
},
|
|
369
|
+
onLoading: (loading: boolean) => {
|
|
370
|
+
if (loading && tracking.current.timeStartLoading === 0) {
|
|
371
|
+
tracking.current.timeStartLoading = Date.now();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* tracking for loading screen
|
|
376
|
+
*/
|
|
377
|
+
clearTimeout(tracking.current.timeoutLoading);
|
|
378
|
+
if (!loading) {
|
|
379
|
+
tracking.current.timeEndLoading = Date.now();
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* timeout for handle tracking screen
|
|
384
|
+
*/
|
|
385
|
+
tracking.current.timeoutLoading = setTimeout(() => {
|
|
386
|
+
onScreenLoading();
|
|
387
|
+
}, 2000);
|
|
388
|
+
},
|
|
256
389
|
onSetParams: (data: ScreenTrackingParams) => {
|
|
257
390
|
tracking.current.params = data;
|
|
258
391
|
},
|
package/Application/index.ts
CHANGED
|
@@ -21,6 +21,9 @@ const MiniAppContext = (Platform as any).MiniAppContext ?? Context;
|
|
|
21
21
|
const ScreenContext = (Platform as any).ScreenContext ?? Context;
|
|
22
22
|
const ComponentContext = (Platform as any).ComponentContext ?? Context;
|
|
23
23
|
const SkeletonContext = createContext({loading: false});
|
|
24
|
+
const TrackingScopeContext = createContext<{scopeName?: string}>({
|
|
25
|
+
scopeName: undefined,
|
|
26
|
+
});
|
|
24
27
|
|
|
25
28
|
export {
|
|
26
29
|
ApplicationContext,
|
|
@@ -39,4 +42,5 @@ export {
|
|
|
39
42
|
HeaderAnimated,
|
|
40
43
|
setAutomationID,
|
|
41
44
|
useComponentId,
|
|
45
|
+
TrackingScopeContext,
|
|
42
46
|
};
|
package/Application/types.ts
CHANGED
|
@@ -159,6 +159,7 @@ export type BottomSheetParams = {
|
|
|
159
159
|
keyboardVerticalOffset?: number;
|
|
160
160
|
useScrollOverflow?: boolean;
|
|
161
161
|
useDivider?: boolean;
|
|
162
|
+
footerComponent?: React.ReactNode;
|
|
162
163
|
};
|
|
163
164
|
|
|
164
165
|
export interface NavigationButtonProps extends TouchableOpacityProps {
|
|
@@ -192,6 +193,7 @@ export type HeaderRightToolkit = {
|
|
|
192
193
|
tools?: ToolGroup[];
|
|
193
194
|
preventClose?: PopupNotifyProps;
|
|
194
195
|
useMore?: boolean;
|
|
196
|
+
useCloseIcon?: boolean;
|
|
195
197
|
};
|
|
196
198
|
|
|
197
199
|
export interface HeaderBackProps extends NavigationButtonProps {
|
package/Application/utils.tsx
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {HeaderTitleProps, NavigationOptions} from './types';
|
|
14
14
|
import {Colors} from '../Consts';
|
|
15
15
|
import {Animated, Platform} from 'react-native';
|
|
16
|
-
import {MiniAppContext, ScreenContext} from './index';
|
|
16
|
+
import {MiniAppContext, ScreenContext, TrackingScopeContext} from './index';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* default options for stack screen
|
|
@@ -173,12 +173,13 @@ const setAutomationID = (accessibilityLabel = '') => {
|
|
|
173
173
|
const useComponentId = (componentName: string, accessibilityLabel?: string) => {
|
|
174
174
|
const app = useContext<any>(MiniAppContext);
|
|
175
175
|
const screen = useContext<any>(ScreenContext);
|
|
176
|
+
const {scopeName} = useContext<any>(TrackingScopeContext);
|
|
176
177
|
|
|
177
178
|
const componentId = useMemo(() => {
|
|
178
179
|
if (accessibilityLabel) {
|
|
179
180
|
return accessibilityLabel;
|
|
180
181
|
}
|
|
181
|
-
return `${app.appId}/${app.code}/${screen.screenName}/${componentName}`;
|
|
182
|
+
return `${app.appId}/${app.code}/${screen.screenName}/${scopeName}/${componentName}`;
|
|
182
183
|
}, [componentName, accessibilityLabel, app, screen]);
|
|
183
184
|
|
|
184
185
|
return {componentId};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {TrackingScopeContext} from '../Application';
|
|
3
|
+
|
|
4
|
+
const TrackingScope = ({
|
|
5
|
+
scopeName,
|
|
6
|
+
children,
|
|
7
|
+
}: {
|
|
8
|
+
scopeName: string;
|
|
9
|
+
children: any;
|
|
10
|
+
}) => {
|
|
11
|
+
return (
|
|
12
|
+
<TrackingScopeContext.Provider value={{scopeName}}>
|
|
13
|
+
{children}
|
|
14
|
+
</TrackingScopeContext.Provider>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export {TrackingScope};
|
package/Layout/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {GridContextProps} from './types';
|
|
|
7
7
|
import Item from './Item';
|
|
8
8
|
import ItemList from './ItemList';
|
|
9
9
|
import ItemSectionList from './ItemSectionList';
|
|
10
|
+
import {TrackingScope} from './TrackingScope';
|
|
10
11
|
|
|
11
12
|
const GridContext = createContext<GridContextProps>({
|
|
12
13
|
numberOfColumns: 12,
|
|
@@ -24,4 +25,5 @@ export {
|
|
|
24
25
|
Item,
|
|
25
26
|
ItemList,
|
|
26
27
|
ItemSectionList,
|
|
28
|
+
TrackingScope,
|
|
27
29
|
};
|
package/Skeleton/index.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {useEffect, useMemo, useRef, useState} from 'react';
|
|
1
|
+
import React, {useContext, useEffect, useMemo, useRef, useState} from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
4
|
Easing,
|
|
@@ -12,9 +12,10 @@ import LinearGradient from 'react-native-linear-gradient';
|
|
|
12
12
|
import {SkeletonTypes} from './types';
|
|
13
13
|
import {Colors, Styles} from '../Consts';
|
|
14
14
|
import styles from './styles';
|
|
15
|
-
import {SkeletonContext} from '../Application';
|
|
15
|
+
import {ScreenContext, SkeletonContext} from '../Application';
|
|
16
16
|
|
|
17
17
|
const Skeleton: React.FC<SkeletonTypes> = ({style}) => {
|
|
18
|
+
const screen = useContext<any>(ScreenContext);
|
|
18
19
|
const [width, setWidth] = useState(0);
|
|
19
20
|
const PRIMARY_COLOR = Colors.black_05;
|
|
20
21
|
const HIGHLIGHT_COLOR1 = Colors.black_05;
|
|
@@ -33,14 +34,16 @@ const Skeleton: React.FC<SkeletonTypes> = ({style}) => {
|
|
|
33
34
|
duration: 1000,
|
|
34
35
|
easing: Easing.linear,
|
|
35
36
|
useNativeDriver: Platform.OS !== 'web',
|
|
36
|
-
})
|
|
37
|
+
})
|
|
37
38
|
);
|
|
38
39
|
}, [beginShimmerPosition]);
|
|
39
40
|
|
|
40
41
|
useEffect(() => {
|
|
41
42
|
animatedValue.start();
|
|
43
|
+
screen?.onLoading?.(true);
|
|
42
44
|
return () => {
|
|
43
45
|
animatedValue.stop();
|
|
46
|
+
screen?.onLoading?.(false);
|
|
44
47
|
};
|
|
45
48
|
}, [animatedValue]);
|
|
46
49
|
|
|
@@ -49,6 +52,7 @@ const Skeleton: React.FC<SkeletonTypes> = ({style}) => {
|
|
|
49
52
|
setWidth(newWidth);
|
|
50
53
|
}
|
|
51
54
|
};
|
|
55
|
+
|
|
52
56
|
return (
|
|
53
57
|
<View style={[styles.container, style]}>
|
|
54
58
|
<View
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@momo-kits/foundation",
|
|
3
|
-
"version": "0.121.3-beta.
|
|
3
|
+
"version": "0.121.3-beta.8",
|
|
4
4
|
"minimumDeployTarget": 32,
|
|
5
|
-
"deploymentTarget":
|
|
5
|
+
"deploymentTarget": 125,
|
|
6
6
|
"description": "React Native Component Kits",
|
|
7
7
|
"main": "index.ts",
|
|
8
8
|
"scripts": {},
|