@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.
@@ -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: 'red',
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
- isWhiteList ? '16_basic_home' : '16_navigation_close_circle'
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' : 'height'}>
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
- const lastElement = useRef<any>(null);
37
- const {screen: Component, options, initialParams} = props.route.params;
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: lastElement.current,
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 (__DEV__ && lastElement.current?.children?.current?.length > 0) {
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(lastElement.current?.children?.current)
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
- lastElement.current = data;
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
  },
@@ -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
  };
@@ -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 {
@@ -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
  };
@@ -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.6",
3
+ "version": "0.121.3-beta.8",
4
4
  "minimumDeployTarget": 32,
5
- "deploymentTarget": 121,
5
+ "deploymentTarget": 125,
6
6
  "description": "React Native Component Kits",
7
7
  "main": "index.ts",
8
8
  "scripts": {},