@momo-kits/foundation 0.112.1-beta.8 → 0.112.1-doc.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 +47 -30
- package/Application/BottomTab/index.tsx +72 -58
- package/Application/Components/HeaderTitle.tsx +2 -2
- package/Application/NavigationContainer.tsx +166 -100
- package/Application/StackScreen.tsx +112 -61
- package/Application/index.ts +4 -2
- package/Application/types.ts +5 -0
- package/Application/utils.tsx +4 -3
- package/Button/index.tsx +11 -1
- package/Consts/colors+spacing+radius.ts +1 -31
- package/Icon/types.ts +1 -2
- package/Image/index.tsx +12 -2
- package/Layout/Screen.tsx +21 -24
- package/Layout/index.ts +2 -0
- package/Skeleton/index.tsx +42 -2
- package/Text/index.tsx +27 -21
- package/index.ts +0 -34
- package/package.json +13 -28
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import React, {useContext, useEffect, useRef, useState} from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import type {NavigationState} from '@react-navigation/routers';
|
|
3
|
+
import {
|
|
4
|
+
SafeAreaProvider,
|
|
5
|
+
useSafeAreaInsets,
|
|
6
|
+
} from 'react-native-safe-area-context';
|
|
3
7
|
import {
|
|
4
8
|
NavigationContainer as ReactNavigationContainer,
|
|
5
9
|
NavigationContainerRef,
|
|
10
|
+
NavigationIndependentTree,
|
|
6
11
|
} from '@react-navigation/native';
|
|
7
12
|
import {
|
|
8
13
|
createStackNavigator,
|
|
@@ -16,7 +21,7 @@ import {getDialogOptions, getModalOptions, getStackOptions} from './utils';
|
|
|
16
21
|
import {NavigationContainerProps} from './types';
|
|
17
22
|
import {ApplicationContext, MiniAppContext} from './index';
|
|
18
23
|
import Localize from './Localize';
|
|
19
|
-
import {defaultTheme
|
|
24
|
+
import {defaultTheme} from '../Consts';
|
|
20
25
|
|
|
21
26
|
const Stack = createStackNavigator();
|
|
22
27
|
|
|
@@ -29,12 +34,47 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
29
34
|
localize = new Localize({vi: {}, en: {}}),
|
|
30
35
|
}) => {
|
|
31
36
|
const context = useContext<any>(MiniAppContext);
|
|
32
|
-
|
|
37
|
+
return (
|
|
38
|
+
<SafeAreaProvider>
|
|
39
|
+
<MiniAppContext.Provider value={context}>
|
|
40
|
+
<Navigation
|
|
41
|
+
screen={screen}
|
|
42
|
+
theme={theme}
|
|
43
|
+
options={options}
|
|
44
|
+
maxApi={maxApi}
|
|
45
|
+
initialParams={initialParams}
|
|
46
|
+
localize={localize}
|
|
47
|
+
/>
|
|
48
|
+
</MiniAppContext.Provider>
|
|
49
|
+
</SafeAreaProvider>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const Navigation: React.FC<any> = ({
|
|
54
|
+
screen,
|
|
55
|
+
theme = defaultTheme,
|
|
56
|
+
options,
|
|
57
|
+
maxApi,
|
|
58
|
+
initialParams,
|
|
59
|
+
localize = new Localize({vi: {}, en: {}}),
|
|
60
|
+
}) => {
|
|
61
|
+
const context = useContext<any>(MiniAppContext);
|
|
62
|
+
const navigationRef = useRef<NavigationContainerRef<any>>(null);
|
|
33
63
|
const routes = useRef<any>();
|
|
34
64
|
const isReady = useRef(false);
|
|
35
65
|
const navigator = useRef(new Navigator(navigationRef, isReady));
|
|
36
66
|
const [showGrid, setShowGrid] = useState(false);
|
|
37
|
-
const
|
|
67
|
+
const insets = useSafeAreaInsets();
|
|
68
|
+
|
|
69
|
+
let headerBackground = context?.designConfig?.headerBar;
|
|
70
|
+
let headerGradient = theme.colors?.gradient;
|
|
71
|
+
|
|
72
|
+
if (theme.assets?.headerBackground) {
|
|
73
|
+
headerBackground = theme.assets?.headerBackground;
|
|
74
|
+
}
|
|
75
|
+
if (context?.designConfig?.headerGradient) {
|
|
76
|
+
headerGradient = context?.designConfig?.headerGradient;
|
|
77
|
+
}
|
|
38
78
|
|
|
39
79
|
/**
|
|
40
80
|
* inject data for navigator
|
|
@@ -50,7 +90,7 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
50
90
|
'onChangeGrid',
|
|
51
91
|
enable => {
|
|
52
92
|
setShowGrid(!!enable);
|
|
53
|
-
}
|
|
93
|
+
},
|
|
54
94
|
);
|
|
55
95
|
|
|
56
96
|
return () => {
|
|
@@ -58,6 +98,10 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
58
98
|
};
|
|
59
99
|
}, []);
|
|
60
100
|
|
|
101
|
+
/**
|
|
102
|
+
* translate context method
|
|
103
|
+
* @param data
|
|
104
|
+
*/
|
|
61
105
|
const translate = (data?: string | {vi: string; en: string}) => {
|
|
62
106
|
if (data && typeof data !== 'string') {
|
|
63
107
|
return localize?.translateData(data);
|
|
@@ -74,7 +118,7 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
74
118
|
const onScreenNavigated = (
|
|
75
119
|
preScreenName: string,
|
|
76
120
|
screenName: string,
|
|
77
|
-
action: string
|
|
121
|
+
action: string,
|
|
78
122
|
) => {
|
|
79
123
|
console.log(preScreenName, screenName, action);
|
|
80
124
|
context?.autoTracking?.({
|
|
@@ -86,9 +130,6 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
86
130
|
action,
|
|
87
131
|
});
|
|
88
132
|
|
|
89
|
-
/**
|
|
90
|
-
* debug toast
|
|
91
|
-
*/
|
|
92
133
|
maxApi?.showToastDebug?.({
|
|
93
134
|
appId: context.appId,
|
|
94
135
|
message: `${screenName} screen_navigated`,
|
|
@@ -96,104 +137,129 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
96
137
|
});
|
|
97
138
|
};
|
|
98
139
|
|
|
99
|
-
|
|
100
|
-
|
|
140
|
+
/**
|
|
141
|
+
* onStateChange
|
|
142
|
+
* @param state
|
|
143
|
+
*/
|
|
144
|
+
const onStateChange = (state: Readonly<NavigationState> | undefined) => {
|
|
145
|
+
const lastedRoute: any = state?.routes?.[state?.routes?.length - 1];
|
|
146
|
+
const oldRoute: any = routes.current?.[routes.current?.length - 1];
|
|
147
|
+
const lasted = lastedRoute?.params?.screen;
|
|
148
|
+
const previous = oldRoute?.params?.screen;
|
|
149
|
+
const preScreenName = previous?.name ?? previous?.type?.name;
|
|
150
|
+
const screenName = lasted?.name ?? lasted?.type?.name;
|
|
101
151
|
|
|
102
|
-
|
|
152
|
+
let action = 'push';
|
|
153
|
+
if (routes.current?.length > (state?.routes?.length ?? 0)) {
|
|
154
|
+
action = 'back';
|
|
155
|
+
}
|
|
156
|
+
onScreenNavigated(preScreenName, screenName, action);
|
|
157
|
+
maxApi?.setObserver('CURRENT_SCREEN', {screenName});
|
|
158
|
+
routes.current = state?.routes;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* onReady
|
|
163
|
+
*/
|
|
164
|
+
const onReady = () => {
|
|
165
|
+
isReady.current = true;
|
|
166
|
+
routes.current = navigationRef.current?.getRootState?.()?.routes;
|
|
167
|
+
maxApi?.getDataObserver('CURRENT_SCREEN', (data: any) => {
|
|
168
|
+
onScreenNavigated(data?.screenName, screen?.name, 'push');
|
|
169
|
+
maxApi?.setObserver('CURRENT_SCREEN', {
|
|
170
|
+
screenName: screen?.name,
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
};
|
|
103
174
|
|
|
104
175
|
return (
|
|
105
|
-
<
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
...
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
176
|
+
<ApplicationContext.Provider
|
|
177
|
+
value={{
|
|
178
|
+
navigator: navigator.current,
|
|
179
|
+
theme: {
|
|
180
|
+
...theme,
|
|
181
|
+
colors: {
|
|
182
|
+
...theme.colors,
|
|
183
|
+
gradient: headerGradient,
|
|
184
|
+
},
|
|
185
|
+
assets: {
|
|
186
|
+
...theme.assets,
|
|
187
|
+
headerBackground,
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
showGrid,
|
|
191
|
+
translate,
|
|
192
|
+
}}>
|
|
193
|
+
<NavigationIndependentTree>
|
|
194
|
+
<ReactNavigationContainer
|
|
195
|
+
theme={{
|
|
196
|
+
dark: false,
|
|
197
|
+
colors: {
|
|
198
|
+
primary: theme.colors.primary,
|
|
199
|
+
background: theme.colors.background.default,
|
|
200
|
+
card: theme.colors.background.surface,
|
|
201
|
+
text: theme.colors.text.default,
|
|
202
|
+
border: theme.colors.border.default,
|
|
203
|
+
notification: theme.colors.error.primary,
|
|
204
|
+
},
|
|
205
|
+
fonts: {
|
|
206
|
+
regular: {
|
|
207
|
+
fontFamily: 'SFProText',
|
|
208
|
+
fontWeight: '400',
|
|
119
209
|
},
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
210
|
+
medium: {
|
|
211
|
+
fontFamily: 'SFProText',
|
|
212
|
+
fontWeight: '400',
|
|
213
|
+
},
|
|
214
|
+
bold: {
|
|
215
|
+
fontFamily: 'SFProText',
|
|
216
|
+
fontWeight: '400',
|
|
217
|
+
},
|
|
218
|
+
heavy: {
|
|
219
|
+
fontFamily: 'SFProText',
|
|
220
|
+
fontWeight: '400',
|
|
123
221
|
},
|
|
124
222
|
},
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
223
|
+
}}
|
|
224
|
+
ref={navigationRef}
|
|
225
|
+
onReady={onReady}
|
|
226
|
+
onStateChange={onStateChange}>
|
|
227
|
+
<Stack.Navigator
|
|
228
|
+
initialRouteName="Stack"
|
|
229
|
+
screenOptions={{
|
|
230
|
+
headerMode: 'screen',
|
|
231
|
+
gestureEnabled: false,
|
|
232
|
+
headerTitleAlign: 'left',
|
|
233
|
+
headerTintColor: theme.colors.text.default,
|
|
234
|
+
headerStyle: {
|
|
235
|
+
height: 52 + insets.top,
|
|
138
236
|
},
|
|
139
|
-
}}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
onScreenNavigated(preScreenName, screenName, action);
|
|
166
|
-
maxApi?.setObserver('CURRENT_SCREEN', {screenName});
|
|
167
|
-
routes.current = state?.routes;
|
|
168
|
-
}}
|
|
169
|
-
independent={true}>
|
|
170
|
-
<Stack.Navigator initialRouteName="Stack" headerMode="screen">
|
|
171
|
-
<Stack.Screen
|
|
172
|
-
name="Stack"
|
|
173
|
-
component={StackScreen}
|
|
174
|
-
initialParams={{screen, initialParams}}
|
|
175
|
-
options={{
|
|
176
|
-
...getStackOptions(),
|
|
177
|
-
...(options as StackNavigationOptions),
|
|
178
|
-
}}
|
|
179
|
-
/>
|
|
180
|
-
<Stack.Screen
|
|
181
|
-
name="Dialog"
|
|
182
|
-
component={StackScreen}
|
|
183
|
-
options={getDialogOptions()}
|
|
184
|
-
initialParams={{screen}}
|
|
185
|
-
/>
|
|
186
|
-
<Stack.Screen
|
|
187
|
-
name="Modal"
|
|
188
|
-
component={ModalScreen}
|
|
189
|
-
options={getModalOptions()}
|
|
190
|
-
initialParams={{screen}}
|
|
191
|
-
/>
|
|
192
|
-
</Stack.Navigator>
|
|
193
|
-
</ReactNavigationContainer>
|
|
194
|
-
</ApplicationContext.Provider>
|
|
195
|
-
</MiniAppContext.Provider>
|
|
196
|
-
</SafeAreaProvider>
|
|
237
|
+
}}>
|
|
238
|
+
<Stack.Screen
|
|
239
|
+
name="Stack"
|
|
240
|
+
component={StackScreen}
|
|
241
|
+
initialParams={{screen, initialParams}}
|
|
242
|
+
options={{
|
|
243
|
+
...getStackOptions(),
|
|
244
|
+
...(options as StackNavigationOptions),
|
|
245
|
+
}}
|
|
246
|
+
/>
|
|
247
|
+
<Stack.Screen
|
|
248
|
+
name="Dialog"
|
|
249
|
+
component={StackScreen}
|
|
250
|
+
options={getDialogOptions()}
|
|
251
|
+
initialParams={{screen}}
|
|
252
|
+
/>
|
|
253
|
+
<Stack.Screen
|
|
254
|
+
name="Modal"
|
|
255
|
+
component={ModalScreen}
|
|
256
|
+
options={getModalOptions()}
|
|
257
|
+
initialParams={{screen}}
|
|
258
|
+
/>
|
|
259
|
+
</Stack.Navigator>
|
|
260
|
+
</ReactNavigationContainer>
|
|
261
|
+
</NavigationIndependentTree>
|
|
262
|
+
</ApplicationContext.Provider>
|
|
197
263
|
);
|
|
198
264
|
};
|
|
199
265
|
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
|
|
1
|
+
import React, {
|
|
2
|
+
useCallback,
|
|
3
|
+
useContext,
|
|
4
|
+
useEffect,
|
|
5
|
+
useLayoutEffect,
|
|
6
|
+
useRef,
|
|
7
|
+
} from 'react';
|
|
3
8
|
import {Alert, InteractionManager} from 'react-native';
|
|
4
|
-
import {
|
|
9
|
+
import {useHeaderHeight} from '@react-navigation/elements';
|
|
10
|
+
import {ScreenTrackingParams} from './types';
|
|
5
11
|
import Navigation from './Navigation';
|
|
6
12
|
import {ApplicationContext, MiniAppContext, ScreenContext} from './index';
|
|
7
13
|
import {GridSystem} from '../Layout';
|
|
14
|
+
import {version} from '../package.json';
|
|
8
15
|
|
|
9
16
|
const runAfterInteractions = InteractionManager.runAfterInteractions;
|
|
10
17
|
|
|
@@ -13,7 +20,7 @@ const runAfterInteractions = InteractionManager.runAfterInteractions;
|
|
|
13
20
|
* @param props
|
|
14
21
|
* @constructor
|
|
15
22
|
*/
|
|
16
|
-
const StackScreen: React.FC<
|
|
23
|
+
const StackScreen: React.FC<any> = props => {
|
|
17
24
|
const {showGrid, navigator} = useContext(ApplicationContext);
|
|
18
25
|
const tracking = useRef<any>({
|
|
19
26
|
timeoutLoad: undefined,
|
|
@@ -27,11 +34,14 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
27
34
|
releaseInteraction: undefined,
|
|
28
35
|
timeLoad: 0,
|
|
29
36
|
timeInteraction: 0,
|
|
37
|
+
widgets: [],
|
|
38
|
+
params: undefined,
|
|
30
39
|
});
|
|
40
|
+
const widgets = useRef<any>([]);
|
|
31
41
|
const context = useContext<any>(MiniAppContext);
|
|
32
42
|
const lastElement = useRef<any>(null);
|
|
33
43
|
const {screen: Component, options, initialParams} = props.route.params;
|
|
34
|
-
const navigation = new Navigation(props.navigation, context);
|
|
44
|
+
const navigation = useRef(new Navigation(props.navigation, context)).current;
|
|
35
45
|
const heightHeader = useHeaderHeight();
|
|
36
46
|
|
|
37
47
|
const data = {
|
|
@@ -52,56 +62,12 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
52
62
|
if (options) {
|
|
53
63
|
navigation.setOptions(options);
|
|
54
64
|
}
|
|
55
|
-
}, [options]);
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* tracking for screen
|
|
59
|
-
*/
|
|
60
|
-
useEffect(() => {
|
|
61
|
-
if (['Invalid', 'screen'].includes(screenName)) {
|
|
62
|
-
navigator?.maxApi?.showPopup?.('notice', {
|
|
63
|
-
title: 'Invalid screen name',
|
|
64
|
-
message:
|
|
65
|
-
'Your screen has not been rendered because Platform has not detected the screen name. Please migrate to support this feature.',
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const subscription = props.navigation?.addListener?.('focus', () => {
|
|
70
|
-
navigator?.maxApi?.of?.({screenName});
|
|
71
|
-
navigator?.maxApi?.setObserver('CURRENT_SCREEN', {screenName});
|
|
72
|
-
});
|
|
73
|
-
navigator?.maxApi?.startTraceScreenLoad?.(
|
|
74
|
-
screenName,
|
|
75
|
-
context,
|
|
76
|
-
(data: any) => {
|
|
77
|
-
tracking.current.traceIdLoad = data?.traceId;
|
|
78
|
-
}
|
|
79
|
-
);
|
|
80
|
-
navigator?.maxApi?.startTraceScreenInteraction?.(
|
|
81
|
-
screenName,
|
|
82
|
-
context,
|
|
83
|
-
(data: any) => {
|
|
84
|
-
tracking.current.traceIdInteraction = data?.traceId;
|
|
85
|
-
}
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
tracking.current.timeoutTracking = setTimeout(() => {
|
|
89
|
-
onScreenLoad();
|
|
90
|
-
onScreenInteraction();
|
|
91
|
-
}, 5000);
|
|
92
|
-
|
|
93
|
-
return () => {
|
|
94
|
-
onScreenLoad();
|
|
95
|
-
onScreenInteraction();
|
|
96
|
-
clearTimeout(tracking.current.timeoutTracking);
|
|
97
|
-
subscription?.();
|
|
98
|
-
};
|
|
99
|
-
}, []);
|
|
65
|
+
}, [navigation, options]);
|
|
100
66
|
|
|
101
67
|
/**
|
|
102
68
|
* tracking for screen load
|
|
103
69
|
*/
|
|
104
|
-
const onScreenLoad = () => {
|
|
70
|
+
const onScreenLoad = useCallback(() => {
|
|
105
71
|
if (!tracking.current?.releaseLoad) {
|
|
106
72
|
let timeLoad = tracking.current.timeLoad;
|
|
107
73
|
if (timeLoad === 0) {
|
|
@@ -114,11 +80,14 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
114
80
|
componentName: 'Screen',
|
|
115
81
|
state: 'load',
|
|
116
82
|
duration: timeLoad,
|
|
83
|
+
widgets: tracking.current.widgets,
|
|
84
|
+
params: tracking.current.params,
|
|
85
|
+
version: version,
|
|
117
86
|
});
|
|
118
87
|
navigator?.maxApi?.stopTrace?.(
|
|
119
88
|
tracking.current.traceIdLoad,
|
|
120
89
|
{value: timeLoad / 1000},
|
|
121
|
-
null
|
|
90
|
+
null,
|
|
122
91
|
);
|
|
123
92
|
tracking.current.releaseLoad = true;
|
|
124
93
|
|
|
@@ -136,16 +105,16 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
136
105
|
) {
|
|
137
106
|
Alert.alert(
|
|
138
107
|
`${screenName}- load ${timeLoad}ms`,
|
|
139
|
-
JSON.stringify(lastElement.current?.children?.current)
|
|
108
|
+
JSON.stringify(lastElement.current?.children?.current),
|
|
140
109
|
);
|
|
141
110
|
}
|
|
142
111
|
}
|
|
143
|
-
};
|
|
112
|
+
}, [context, navigator?.maxApi, screenName]);
|
|
144
113
|
|
|
145
114
|
/**
|
|
146
115
|
* tracking for screen load
|
|
147
116
|
*/
|
|
148
|
-
const onScreenInteraction = () => {
|
|
117
|
+
const onScreenInteraction = useCallback(() => {
|
|
149
118
|
if (!tracking.current?.releaseInteraction) {
|
|
150
119
|
let timeLoad = tracking.current.timeLoad;
|
|
151
120
|
if (timeLoad === 0) {
|
|
@@ -162,11 +131,13 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
162
131
|
state: 'interaction',
|
|
163
132
|
duration: tracking.current.timeInteraction - timeLoad,
|
|
164
133
|
totalDuration: tracking.current.timeInteraction,
|
|
134
|
+
params: tracking.current.params,
|
|
135
|
+
version: version,
|
|
165
136
|
});
|
|
166
137
|
navigator?.maxApi?.stopTrace?.(
|
|
167
138
|
tracking.current.traceIdInteraction,
|
|
168
139
|
{value: tracking.current.timeInteraction / 1000},
|
|
169
|
-
null
|
|
140
|
+
null,
|
|
170
141
|
);
|
|
171
142
|
tracking.current.releaseInteraction = true;
|
|
172
143
|
|
|
@@ -179,13 +150,88 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
179
150
|
type: 'ERROR',
|
|
180
151
|
});
|
|
181
152
|
}
|
|
182
|
-
};
|
|
153
|
+
}, [context, navigator?.maxApi, screenName]);
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* tracking for screen
|
|
157
|
+
*/
|
|
158
|
+
useEffect(() => {
|
|
159
|
+
if (['Invalid', 'screen'].includes(screenName)) {
|
|
160
|
+
navigator?.maxApi?.showPopup?.('notice', {
|
|
161
|
+
title: 'Invalid screen name',
|
|
162
|
+
message:
|
|
163
|
+
'Your screen has not been rendered because Platform has not detected the screen name. Please migrate to support this feature.',
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const subscription = props.navigation?.addListener?.('focus', () => {
|
|
168
|
+
navigator?.maxApi?.of?.({screenName});
|
|
169
|
+
navigator?.maxApi?.setObserver('CURRENT_SCREEN', {screenName});
|
|
170
|
+
});
|
|
171
|
+
navigator?.maxApi?.startTraceScreenLoad?.(
|
|
172
|
+
screenName,
|
|
173
|
+
context,
|
|
174
|
+
(item: any) => {
|
|
175
|
+
tracking.current.traceIdLoad = item?.traceId;
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
navigator?.maxApi?.startTraceScreenInteraction?.(
|
|
179
|
+
screenName,
|
|
180
|
+
context,
|
|
181
|
+
(item: any) => {
|
|
182
|
+
tracking.current.traceIdInteraction = item?.traceId;
|
|
183
|
+
},
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
tracking.current.timeoutTracking = setTimeout(() => {
|
|
187
|
+
onScreenLoad();
|
|
188
|
+
onScreenInteraction();
|
|
189
|
+
}, 5000);
|
|
190
|
+
|
|
191
|
+
return () => {
|
|
192
|
+
onScreenLoad();
|
|
193
|
+
onScreenInteraction();
|
|
194
|
+
subscription?.();
|
|
195
|
+
};
|
|
196
|
+
}, [
|
|
197
|
+
context,
|
|
198
|
+
navigator?.maxApi,
|
|
199
|
+
onScreenInteraction,
|
|
200
|
+
onScreenLoad,
|
|
201
|
+
props.navigation,
|
|
202
|
+
screenName,
|
|
203
|
+
]);
|
|
183
204
|
|
|
184
205
|
return (
|
|
185
206
|
<ScreenContext.Provider
|
|
186
207
|
value={{
|
|
187
208
|
screenName,
|
|
188
|
-
onElementLoad: (
|
|
209
|
+
onElementLoad: (item: any) => {
|
|
210
|
+
/**
|
|
211
|
+
* widget handle
|
|
212
|
+
*/
|
|
213
|
+
if (item?.componentName === 'Widget') {
|
|
214
|
+
const index = widgets.current.findIndex(
|
|
215
|
+
(e: any) => e.componentId === item.componentId,
|
|
216
|
+
);
|
|
217
|
+
const time = Date.now() - tracking.current.startTime;
|
|
218
|
+
if (index === -1) {
|
|
219
|
+
widgets.current.push({
|
|
220
|
+
componentId: item.componentId,
|
|
221
|
+
appId: item.params?.appId,
|
|
222
|
+
code: item.params?.code,
|
|
223
|
+
start: time,
|
|
224
|
+
});
|
|
225
|
+
} else {
|
|
226
|
+
const exist = widgets.current[index];
|
|
227
|
+
widgets.current[index] = {
|
|
228
|
+
...exist,
|
|
229
|
+
end: time,
|
|
230
|
+
duration: time - exist.start,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
189
235
|
/**
|
|
190
236
|
* tracking for element screen load
|
|
191
237
|
*/
|
|
@@ -200,14 +246,14 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
200
246
|
/**
|
|
201
247
|
* support for debug last element
|
|
202
248
|
*/
|
|
203
|
-
if (
|
|
204
|
-
lastElement.current =
|
|
249
|
+
if (item?.componentName) {
|
|
250
|
+
lastElement.current = item;
|
|
205
251
|
}
|
|
206
252
|
|
|
207
253
|
/**
|
|
208
254
|
* for stop tracking when user interaction
|
|
209
255
|
*/
|
|
210
|
-
if (
|
|
256
|
+
if (item?.interaction) {
|
|
211
257
|
onScreenLoad();
|
|
212
258
|
onScreenInteraction();
|
|
213
259
|
}
|
|
@@ -216,6 +262,8 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
216
262
|
*/
|
|
217
263
|
tracking.current.timeoutLoad = setTimeout(() => {
|
|
218
264
|
const time = tracking.current.endTime - tracking.current.startTime;
|
|
265
|
+
tracking.current.widgets = widgets.current;
|
|
266
|
+
|
|
219
267
|
if (tracking.current.timeLoad === 0) {
|
|
220
268
|
tracking.current.timeLoad = time;
|
|
221
269
|
}
|
|
@@ -224,6 +272,9 @@ const StackScreen: React.FC<ScreenParams> = props => {
|
|
|
224
272
|
onScreenInteraction();
|
|
225
273
|
}, 2000);
|
|
226
274
|
},
|
|
275
|
+
onSetParams: (data: ScreenTrackingParams) => {
|
|
276
|
+
tracking.current.params = data;
|
|
277
|
+
},
|
|
227
278
|
}}>
|
|
228
279
|
<Component heightHeader={heightHeader} {...data} />
|
|
229
280
|
{showGrid && <GridSystem />}
|
package/Application/index.ts
CHANGED
|
@@ -16,15 +16,17 @@ import {setAutomationID} from './utils';
|
|
|
16
16
|
const Context = createContext({});
|
|
17
17
|
const ApplicationContext = createContext(defaultContext);
|
|
18
18
|
|
|
19
|
-
const MiniAppContext = (Platform as any).MiniAppContext ??
|
|
20
|
-
const ScreenContext = (Platform as any).ScreenContext ??
|
|
19
|
+
const MiniAppContext = (Platform as any).MiniAppContext ?? Context;
|
|
20
|
+
const ScreenContext = (Platform as any).ScreenContext ?? Context;
|
|
21
21
|
const ComponentContext = (Platform as any).ComponentContext ?? Context;
|
|
22
|
+
const SkeletonContext = createContext({loading: false});
|
|
22
23
|
|
|
23
24
|
export {
|
|
24
25
|
ApplicationContext,
|
|
25
26
|
MiniAppContext,
|
|
26
27
|
ScreenContext,
|
|
27
28
|
ComponentContext,
|
|
29
|
+
SkeletonContext,
|
|
28
30
|
NavigationContainer,
|
|
29
31
|
Localize,
|
|
30
32
|
HeaderTitle,
|
package/Application/types.ts
CHANGED
|
@@ -117,6 +117,11 @@ export type ScreenParams = {
|
|
|
117
117
|
options?: NavigationOptions;
|
|
118
118
|
};
|
|
119
119
|
|
|
120
|
+
export type ScreenTrackingParams = {
|
|
121
|
+
value1?: any;
|
|
122
|
+
value2?: any;
|
|
123
|
+
};
|
|
124
|
+
|
|
120
125
|
export type ModalParams = {
|
|
121
126
|
[key: string]: any;
|
|
122
127
|
screen: React.ComponentType;
|
package/Application/utils.tsx
CHANGED
|
@@ -55,7 +55,8 @@ const getModalOptions = (): StackNavigationOptions => {
|
|
|
55
55
|
headerBackground: undefined,
|
|
56
56
|
cardStyle: {backgroundColor: 'transparent'},
|
|
57
57
|
cardOverlayEnabled: true,
|
|
58
|
-
|
|
58
|
+
animation: 'none',
|
|
59
|
+
presentation: 'transparentModal',
|
|
59
60
|
};
|
|
60
61
|
};
|
|
61
62
|
|
|
@@ -64,7 +65,7 @@ const getModalOptions = (): StackNavigationOptions => {
|
|
|
64
65
|
*/
|
|
65
66
|
const getOptions = (
|
|
66
67
|
params: NavigationOptions,
|
|
67
|
-
animatedValue?: Animated.Value
|
|
68
|
+
animatedValue?: Animated.Value,
|
|
68
69
|
) => {
|
|
69
70
|
let options: StackNavigationOptions = {};
|
|
70
71
|
|
|
@@ -126,7 +127,7 @@ const getOptions = (
|
|
|
126
127
|
|
|
127
128
|
const exportHeaderTitle = (
|
|
128
129
|
params: NavigationOptions,
|
|
129
|
-
animatedValue?: Animated.Value
|
|
130
|
+
animatedValue?: Animated.Value,
|
|
130
131
|
): StackNavigationOptions => {
|
|
131
132
|
if (typeof params.headerTitle === 'object') {
|
|
132
133
|
return {
|