@momo-kits/foundation 0.92.2-tracking.4 → 0.92.2

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.
@@ -127,25 +127,26 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
127
127
 
128
128
  const goBackSafe = () => {
129
129
  const goBack = () => {
130
- const canGoBack = navigator?.ref?.current?.canGoBack?.();
131
- const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
132
- const params = {
133
- appId: context.appId,
134
- code: context.code,
135
- screen_name: currentRoute?.params?.screen?.name ?? currentRoute?.name,
136
- trigger_id: '111154000000000000',
137
- icon_name: 'back',
138
- };
139
- navigator?.maxApi?.showToastDebug?.({
140
- appId: `auto - ${context.appId}`,
141
- message: 'service_icon_clicked',
142
- params,
143
- });
144
- navigator?.maxApi?.trackEvent?.('service_icon_clicked', params);
130
+ const canGoBack = navigator?.ref.current?.canGoBack();
131
+ if (!canGoBack) {
132
+ const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
133
+ const params = {
134
+ ...context,
135
+ screen_name: currentRoute?.params?.screen?.name ?? currentRoute?.name,
136
+ trigger_id: '111154000000000000',
137
+ icon_name: 'back',
138
+ };
139
+ navigator?.maxApi?.showToastDebug?.({
140
+ appId: `auto - ${context.appId}`,
141
+ message: 'service_icon_clicked',
142
+ params,
143
+ });
144
+ navigator?.maxApi?.trackEvent?.('service_icon_clicked', params);
145
+ }
145
146
  if (canGoBack) {
146
- navigator?.ref?.current?.goBack?.();
147
+ navigator?.ref.current?.goBack();
147
148
  } else if (navigator?.maxApi) {
148
- navigator?.maxApi?.dismiss?.(navigator?.dismissData);
149
+ navigator?.maxApi?.dismiss(navigator.dismissData);
149
150
  } else {
150
151
  const currentTime = new Date().getTime();
151
152
  const requestId = `navigationBackPress#${currentTime}`;
@@ -1,4 +1,4 @@
1
- import React, {useEffect, useRef, useState} from 'react';
1
+ import React, {useContext, useEffect, useRef, useState} from 'react';
2
2
  import {SafeAreaProvider} from 'react-native-safe-area-context';
3
3
  import {
4
4
  NavigationContainer as ReactNavigationContainer,
@@ -15,6 +15,10 @@ import {LocalizationObject, NavigationContainerProps} from './types';
15
15
  import {ApplicationContext} from './index';
16
16
  import kitLocalization from '../Assets/language.json';
17
17
 
18
+ const {
19
+ MiniAppContext,
20
+ } = require('react-native/Libraries/Components/ScreenContext');
21
+
18
22
  /**
19
23
  * link for deprecated
20
24
  */
@@ -31,6 +35,7 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
31
35
  localization,
32
36
  initialParams,
33
37
  }) => {
38
+ const context = useContext<any>(MiniAppContext);
34
39
  const navigationRef = useRef<NavigationContainerRef>(null);
35
40
  const isReady = useRef(false);
36
41
  const navigator = useRef(new Navigator(navigationRef, isReady));
@@ -64,7 +69,7 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
64
69
  * @param key
65
70
  */
66
71
  const translate = (key: string) => {
67
- const language: 'vi' | 'en' = 'vi';
72
+ const language: 'vi' | 'en' = context?.language ?? 'vi';
68
73
  const mergedLocalization: LocalizationObject = {
69
74
  vi: {...localization?.vi, ...kitLocalization.vi},
70
75
  en: {...localization?.en, ...kitLocalization.en},
@@ -16,15 +16,8 @@ const StackScreen: React.FC<ScreenParams> = props => {
16
16
  const startTime = useRef(Date.now());
17
17
  const endTime = useRef(Date.now());
18
18
  const timeLoad = useRef(0);
19
- const timeInteraction = useRef(0);
20
- const timeoutLoad = useRef<any>();
21
- const tracked = useRef<any>({
22
- releaseLoad: undefined,
23
- releaseInteraction: undefined,
24
- timeoutLoad: undefined,
25
- timeoutInteraction: undefined,
26
- });
27
- const interaction = useRef<any>();
19
+ const timeout = useRef<any>();
20
+
28
21
  const context = useContext<any>(MiniAppContext);
29
22
 
30
23
  const {screen: Component, options, initialParams} = props.route.params;
@@ -48,6 +41,14 @@ const StackScreen: React.FC<ScreenParams> = props => {
48
41
  useLayoutEffect(() => {
49
42
  const host = (global as any).miniAppApi?.currentHost || {};
50
43
  host.screenName = screenName;
44
+ InteractionManager.runAfterInteractions(() => {
45
+ navigator?.maxApi?.showToastDebug?.({
46
+ appId: `auto - ${context.appId}`,
47
+ message: `${screenName} screen_interaction_time ${
48
+ Date.now() - startTime.current
49
+ }`,
50
+ });
51
+ });
51
52
  if (options) {
52
53
  navigation.setOptions(options);
53
54
  }
@@ -57,84 +58,73 @@ const StackScreen: React.FC<ScreenParams> = props => {
57
58
  * tracking for screen
58
59
  */
59
60
  useEffect(() => {
60
- if (__DEV__ && (!screenName || screenName == 'Invalid')) {
61
- Alert.alert('Design system', `Unvalidated screen name "${screenName}" !`);
61
+ if (__DEV__) {
62
+ if (!screenName || screenName === 'screen') {
63
+ Alert.alert(
64
+ 'Design system',
65
+ `Unvalidated screen name "${screenName}" !`,
66
+ );
67
+ }
62
68
  }
63
69
 
64
- tracked.current.timeoutLoad = setTimeout(() => {
65
- onScreenLoad();
66
- }, 5000);
67
- tracked.current.timeoutInteraction = setTimeout(() => {
68
- onScreenInteraction();
69
- }, 5000);
70
- return () => {
71
- onScreenLoad();
72
- onScreenInteraction();
70
+ const tracking = {
71
+ ...context,
72
+ screen_name: screenName,
73
73
  };
74
- }, []);
75
74
 
76
- /**
77
- * tracking for screen load
78
- */
79
- const onScreenLoad = () => {
80
- clearTimeout(tracked.current.timeoutLoad);
81
- if (!tracked.current?.releaseLoad) {
82
- navigator?.maxApi?.dispatchFunction?.('autoTracking', {
83
- appId: context.appId,
84
- code: context.code,
85
- screenName,
86
- componentName: 'Screen',
87
- state: 'load',
88
- time: timeLoad.current,
89
- });
90
- navigator?.maxApi?.showToastDebug?.({
91
- appId: `auto - ${context.appId}`,
92
- message: `${screenName} screen_load_time ${timeLoad.current}`,
93
- });
94
- tracked.current.releaseLoad = true;
75
+ const routes = props.navigation.getState()?.routes || [];
76
+ const routesLength = routes.length;
77
+ let pre_screen_name = '';
78
+ if (routesLength > 1) {
79
+ pre_screen_name = routes[routesLength - 2]?.params?.screen?.name;
95
80
  }
96
- };
97
81
 
98
- /**
99
- * tracking for screen load
100
- */
101
- const onScreenInteraction = () => {
102
- clearTimeout(tracked.current.timeoutInteraction);
103
- if (!tracked.current?.releaseInteraction) {
104
- navigator?.maxApi?.dispatchFunction?.('autoTracking', {
105
- appId: context.appId,
106
- code: context.code,
107
- screenName,
108
- componentName: 'Screen',
109
- state: 'interaction',
110
- time: timeInteraction.current,
111
- });
82
+ const params = {
83
+ ...tracking,
84
+ pre_screen_name,
85
+ trigger_id: '111378000000000000',
86
+ };
87
+ navigator?.maxApi?.trackEvent?.('service_frame_displayed', params);
88
+ navigator?.maxApi?.showToastDebug?.({
89
+ appId: `auto - ${context.appId}`,
90
+ message: `${screenName} service_frame_displayed`,
91
+ params,
92
+ });
112
93
 
94
+ return props.navigation.addListener('beforeRemove', () => {
95
+ const params = {
96
+ ...tracking,
97
+ trigger_id: '111154000000000000',
98
+ icon_name: 'back',
99
+ };
100
+ navigator?.maxApi?.trackEvent?.('service_icon_clicked', params);
113
101
  navigator?.maxApi?.showToastDebug?.({
114
102
  appId: `auto - ${context.appId}`,
115
- message: `${screenName} screen_interaction_time ${timeInteraction.current}`,
103
+ message: `${screenName} service_icon_clicked`,
104
+ params,
116
105
  });
117
- tracked.current.releaseInteraction = true;
118
- }
119
- };
106
+ });
107
+ }, []);
120
108
 
121
109
  return (
122
110
  <ScreenContext.Provider
123
111
  value={{
112
+ appId: context.appId,
113
+ code: context.code,
124
114
  screenName,
125
115
  autoTracking: (data: any) => {
126
116
  navigator?.maxApi?.dispatchFunction?.('autoTracking', data);
127
117
  },
128
118
  onElementLoad: () => {
129
119
  endTime.current = Date.now();
130
- interaction.current?.cancel?.();
131
- interaction.current = InteractionManager.runAfterInteractions(() => {
132
- timeInteraction.current = Date.now() - startTime.current;
133
- });
134
- clearTimeout(timeoutLoad.current);
135
- timeoutLoad.current = setTimeout(() => {
120
+ clearTimeout(timeout.current);
121
+ timeout.current = setTimeout(() => {
136
122
  if (timeLoad.current === 0) {
137
123
  timeLoad.current = endTime.current - startTime.current;
124
+ navigator?.maxApi?.showToastDebug?.({
125
+ appId: `auto - ${context.appId}`,
126
+ message: `${screenName} screen_load_time ${timeLoad.current}`,
127
+ });
138
128
  }
139
129
  }, 2000);
140
130
  },
@@ -142,8 +132,7 @@ const StackScreen: React.FC<ScreenParams> = props => {
142
132
  <Component
143
133
  heightHeader={heightHeader}
144
134
  {...data}
145
- onScreenLoad={onScreenLoad}
146
- onScreenInteraction={onScreenInteraction}
135
+ onScreenLoad={() => {}}
147
136
  />
148
137
  {showGrid && <GridSystem />}
149
138
  </ScreenContext.Provider>
package/Button/index.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import React, {FC, useContext, useState} from 'react';
1
+ import React, {FC, useContext} from 'react';
2
2
  import {
3
3
  Animated,
4
4
  StyleSheet,
@@ -14,10 +14,15 @@ import {Colors, Spacing} from '../Consts';
14
14
  import styles from './styles';
15
15
  import {Icon} from '../Icon';
16
16
  import {Loader} from '../Loader';
17
- import {formatComponentName} from '../Application/utils';
17
+ import {
18
+ cleanNameForTracking,
19
+ formatComponentName,
20
+ getAccessibilityID,
21
+ } from '../Application/utils';
18
22
 
19
23
  const {
20
- ComponentContext,
24
+ ScreenContext,
25
+ MiniAppContext,
21
26
  } = require('react-native/Libraries/Components/ScreenContext');
22
27
 
23
28
  const AnimationLinear = Animated.createAnimatedComponent(LinearGradient);
@@ -76,6 +81,8 @@ export interface ButtonProps extends TouchableOpacityProps {
76
81
  onPress: () => void;
77
82
 
78
83
  params?: any;
84
+
85
+ componentId?: string;
79
86
  }
80
87
 
81
88
  const Button: FC<ButtonProps> = ({
@@ -89,16 +96,14 @@ const Button: FC<ButtonProps> = ({
89
96
  title = 'Button',
90
97
  onPress,
91
98
  params,
99
+ componentId,
92
100
  accessibilityLabel,
93
101
  ...rest
94
102
  }) => {
95
103
  const {theme, config} = useContext(ApplicationContext);
104
+ const {appId, code} = useContext<any>(MiniAppContext);
96
105
  const {gradient, color} = config?.navigationBar?.buttonColors ?? {};
97
106
  let gradientPros;
98
- let state = 'enabled';
99
- if (loading) {
100
- state = 'loading';
101
- }
102
107
  if (gradient?.length > 0 && type == 'primary') {
103
108
  gradientPros = {
104
109
  colors: gradient,
@@ -107,6 +112,7 @@ const Button: FC<ButtonProps> = ({
107
112
  };
108
113
  }
109
114
 
115
+ const screenInfo = useContext<any>(ScreenContext);
110
116
  const getSizeStyle = () => {
111
117
  const styleSheet: {[key: string]: any} = styles;
112
118
  return styleSheet[size ?? 'small'];
@@ -304,18 +310,28 @@ const Button: FC<ButtonProps> = ({
304
310
  const activeOpacity = type === 'disabled' ? 0.75 : 0.5;
305
311
 
306
312
  return (
307
- <ComponentContext.Provider
313
+ <ScreenContext.Provider
308
314
  value={{
315
+ ...screenInfo,
309
316
  componentName: 'Button',
310
317
  params,
311
- state: state,
312
- componentId: accessibilityLabel,
318
+ state: loading
319
+ ? 'loading'
320
+ : type === 'disabled'
321
+ ? 'disabled'
322
+ : 'enabled',
323
+ componentId,
313
324
  componentValue: formatComponentName(title),
314
325
  action: 'click',
315
326
  }}>
316
327
  <TouchableOpacity
317
328
  {...rest}
318
- accessibilityLabel={accessibilityLabel}
329
+ {...getAccessibilityID(
330
+ `${appId}/${code}/${screenInfo.screenName}/btn_${cleanNameForTracking(
331
+ title,
332
+ )}`,
333
+ accessibilityLabel,
334
+ )}
319
335
  activeOpacity={activeOpacity}
320
336
  onPress={onPressButton}
321
337
  style={buttonStyle}>
@@ -327,7 +343,7 @@ const Button: FC<ButtonProps> = ({
327
343
  )}
328
344
  {gradientPros && <View style={styles.strokeView} />}
329
345
  </TouchableOpacity>
330
- </ComponentContext.Provider>
346
+ </ScreenContext.Provider>
331
347
  );
332
348
  };
333
349
 
@@ -5,23 +5,30 @@ import styles from './styles';
5
5
  import {ApplicationContext} from '../Application';
6
6
  import {Text} from '../Text';
7
7
  import {Icon} from '../Icon';
8
- import {formatNameLength} from '../Application/utils';
8
+ import {
9
+ cleanNameForTracking,
10
+ formatNameLength,
11
+ getAccessibilityID,
12
+ } from '../Application/utils';
9
13
 
10
14
  const {
11
- ComponentContext,
15
+ ScreenContext,
16
+ MiniAppContext,
12
17
  } = require('react-native/Libraries/Components/ScreenContext');
13
18
 
14
19
  const CheckBox: FC<CheckBoxProps> = ({
15
20
  value,
16
- disabled = false,
21
+ disabled,
17
22
  onChange,
18
23
  style,
19
24
  label,
20
25
  indeterminate,
21
26
  params,
22
- accessibilityLabel,
27
+ componentId,
23
28
  }) => {
29
+ const {appId, code} = useContext<any>(MiniAppContext);
24
30
  const {theme} = useContext(ApplicationContext);
31
+ const screenInfo = useContext<any>(ScreenContext);
25
32
  const haveValue = value || indeterminate;
26
33
  const iconSource = indeterminate ? 'ic_minus' : 'ic_checked';
27
34
  let borderColor = theme.colors.text.default;
@@ -41,19 +48,26 @@ const CheckBox: FC<CheckBoxProps> = ({
41
48
  }
42
49
  }
43
50
 
51
+ const accessibilityID = getAccessibilityID(
52
+ `${appId}/${code}/${screenInfo.screenName}/cbx_${cleanNameForTracking(
53
+ label,
54
+ )}_${indeterminate ? 'na' : value}`,
55
+ );
56
+
44
57
  return (
45
- <ComponentContext.Provider
58
+ <ScreenContext.Provider
46
59
  value={{
47
- componentName: 'CheckBox',
60
+ ...screenInfo,
61
+ componentName: 'Button',
48
62
  params,
49
63
  state: disabled ? 'disabled' : 'filled',
50
- componentId: accessibilityLabel,
64
+ componentId,
51
65
  action: 'click',
52
66
  componentLabel: formatNameLength(label || ''),
53
67
  componentValue: indeterminate ? 'indetermine' : value,
54
68
  }}>
55
69
  <TouchableOpacity
56
- accessibilityLabel={accessibilityLabel}
70
+ {...accessibilityID}
57
71
  activeOpacity={0.8}
58
72
  onPress={() => onChange?.(!value)}
59
73
  disabled={disabled}
@@ -73,8 +87,12 @@ const CheckBox: FC<CheckBoxProps> = ({
73
87
  </View>
74
88
  {!!label && <Text typography={'body_default_regular'}>{label}</Text>}
75
89
  </TouchableOpacity>
76
- </ComponentContext.Provider>
90
+ </ScreenContext.Provider>
77
91
  );
78
92
  };
79
93
 
94
+ CheckBox.defaultProps = {
95
+ disabled: false,
96
+ };
97
+
80
98
  export {CheckBox};
package/CheckBox/types.ts CHANGED
@@ -1,6 +1,6 @@
1
- import {TouchableOpacityProps, ViewStyle} from 'react-native';
1
+ import {ViewStyle} from 'react-native';
2
2
 
3
- export interface CheckBoxProps extends TouchableOpacityProps {
3
+ export type CheckBoxProps = {
4
4
  /**
5
5
  * Represents whether the CheckBox is currently checked (`true`) or unchecked (`false`).
6
6
  */
@@ -36,5 +36,7 @@ export interface CheckBoxProps extends TouchableOpacityProps {
36
36
  */
37
37
  style?: ViewStyle;
38
38
 
39
- params?: any;
40
- }
39
+ params?: any
40
+
41
+ componentId?: string
42
+ };
package/Icon/index.tsx CHANGED
@@ -5,12 +5,7 @@ import {IconProps} from './types';
5
5
  import {ApplicationContext} from '../Application';
6
6
  import {Image} from '../Image';
7
7
 
8
- const Icon: React.FC<IconProps> = ({
9
- source = 'ic_back',
10
- size = 24,
11
- color,
12
- style = {},
13
- }) => {
8
+ const Icon: React.FC<IconProps> = ({source, size, color, style = {}}) => {
14
9
  const {theme} = useContext(ApplicationContext);
15
10
 
16
11
  /**
@@ -25,8 +20,8 @@ const Icon: React.FC<IconProps> = ({
25
20
  };
26
21
 
27
22
  const tintColorProps = color !== null && {
28
- tintColor: color ?? theme.colors.text.default,
29
- };
23
+ tintColor: color ?? theme.colors.text.default
24
+ }
30
25
 
31
26
  return (
32
27
  <Image
@@ -38,4 +33,9 @@ const Icon: React.FC<IconProps> = ({
38
33
  );
39
34
  };
40
35
 
36
+ Icon.defaultProps = {
37
+ source: 'ic_back',
38
+ size: 24,
39
+ };
40
+
41
41
  export {Icon, IconSources, IconBankSources};
@@ -12,7 +12,7 @@ import styles from './styles';
12
12
  import {formatComponentName} from '../Application/utils';
13
13
 
14
14
  const {
15
- ComponentContext,
15
+ ScreenContext,
16
16
  } = require('react-native/Libraries/Components/ScreenContext');
17
17
 
18
18
  export interface IconButtonProps extends TouchableOpacityProps {
@@ -33,18 +33,21 @@ export interface IconButtonProps extends TouchableOpacityProps {
33
33
  size?: 'large' | 'small';
34
34
 
35
35
  params?: any;
36
+
37
+ componentId?: string;
36
38
  }
37
39
 
38
40
  const IconButton: React.FC<IconButtonProps> = ({
39
- type = 'primary',
41
+ type,
40
42
  icon,
41
43
  size,
42
44
  onPress,
43
45
  params,
44
- accessibilityLabel,
46
+ componentId,
45
47
  ...rest
46
48
  }) => {
47
49
  const {theme} = useContext(ApplicationContext);
50
+ const screenInfo = useContext<any>(ScreenContext);
48
51
 
49
52
  /**
50
53
  * get size icon button
@@ -130,25 +133,30 @@ const IconButton: React.FC<IconButtonProps> = ({
130
133
  const iconSize = size === 'small' ? 16 : 24;
131
134
 
132
135
  return (
133
- <ComponentContext.Provider
136
+ <ScreenContext.Provider
134
137
  value={{
138
+ ...screenInfo,
135
139
  componentName: 'IconButton',
136
140
  params,
137
141
  state: type === 'disabled' ? 'disabled' : 'enabled',
138
- componentId: accessibilityLabel,
142
+ componentId,
139
143
  componentValue: formatComponentName(icon),
140
144
  action: 'click',
141
145
  }}>
142
146
  <TouchableOpacity
143
147
  {...rest}
144
- accessibilityLabel={accessibilityLabel}
145
148
  activeOpacity={activeOpacity}
146
149
  onPress={onPressButton}
147
150
  style={buttonStyle}>
148
151
  <Icon size={iconSize} source={icon} color={getIconColor()} />
149
152
  </TouchableOpacity>
150
- </ComponentContext.Provider>
153
+ </ScreenContext.Provider>
151
154
  );
152
155
  };
153
156
 
157
+ IconButton.defaultProps = {
158
+ type: 'primary',
159
+ disabled: false,
160
+ };
161
+
154
162
  export {IconButton};
package/Image/index.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import React, {useContext, useEffect, useRef, useState} from 'react';
1
+ import React, {useContext, useRef, useState} from 'react';
2
2
  import {StyleSheet, View} from 'react-native';
3
3
  import FastImage, {Source} from 'react-native-fast-image';
4
4
  import styles from './styles';
@@ -9,34 +9,19 @@ import {Styles} from '../Consts';
9
9
  import {ImageProps} from './types';
10
10
  import {getAccessibilityID} from '../Application/utils';
11
11
 
12
- const {
13
- ComponentContext,
14
- } = require('react-native/Libraries/Components/ScreenContext');
15
-
16
12
  type Status = 'success' | 'loading' | 'error';
17
13
 
18
14
  const Image: React.FC<ImageProps> = ({
19
15
  style,
20
16
  source,
21
- loading = true,
17
+ loading,
22
18
  children,
23
- accessibilityLabel,
24
19
  ...rest
25
20
  }) => {
26
21
  const {theme} = useContext(ApplicationContext);
27
- const component = useContext<any>(ComponentContext);
28
22
  const error = useRef(false);
29
23
  const [status, setStatus] = useState<Status>('success');
30
24
 
31
- const id = getAccessibilityID(
32
- `img|${(source as Source).uri}`,
33
- accessibilityLabel,
34
- );
35
-
36
- useEffect(() => {
37
- component?.addChild?.(id.testID || id.accessibilityLabel);
38
- }, []);
39
-
40
25
  /**
41
26
  * render content loading | fail | rendered
42
27
  */
@@ -60,7 +45,7 @@ const Image: React.FC<ImageProps> = ({
60
45
  return (
61
46
  <FastImage
62
47
  {...rest}
63
- {...id}
48
+ {...getAccessibilityID(`img|${(source as Source).uri}`)}
64
49
  source={source}
65
50
  style={[styles.container, style]}
66
51
  onProgress={() => {
@@ -92,4 +77,8 @@ const Image: React.FC<ImageProps> = ({
92
77
  );
93
78
  };
94
79
 
80
+ Image.defaultProps = {
81
+ loading: true,
82
+ };
83
+
95
84
  export {Image};
package/Image/types.ts CHANGED
@@ -2,5 +2,4 @@ import {FastImageProps} from 'react-native-fast-image';
2
2
 
3
3
  export interface ImageProps extends FastImageProps {
4
4
  loading?: boolean;
5
- accessibilityLabel?: string;
6
5
  }