@momo-kits/foundation 0.109.2-beta.1 → 0.110.1-beta.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.
Files changed (37) hide show
  1. package/Application/BottomSheet.tsx +20 -5
  2. package/Application/BottomTab/BottomTabBar.tsx +13 -2
  3. package/Application/BottomTab/index.tsx +2 -2
  4. package/Application/Components/BottomSheetHelpCenter.tsx +45 -0
  5. package/Application/Components/HeaderAnimated.tsx +2 -1
  6. package/Application/Components/HeaderBackground.tsx +16 -9
  7. package/Application/Components/HeaderExtendHeader.tsx +52 -23
  8. package/Application/Components/HeaderLeft.tsx +20 -21
  9. package/Application/Components/HeaderRight.tsx +72 -34
  10. package/Application/Components/HeaderTitle.tsx +297 -32
  11. package/Application/Components/SearchHeader.tsx +9 -15
  12. package/Application/Localize.ts +1 -1
  13. package/Application/Navigation.ts +3 -1
  14. package/Application/NavigationContainer.tsx +80 -4
  15. package/Application/Navigator.ts +5 -5
  16. package/Application/StackScreen.tsx +26 -40
  17. package/Application/types.ts +11 -3
  18. package/Application/utils.tsx +2 -0
  19. package/Button/index.tsx +0 -2
  20. package/Input/Input.tsx +19 -12
  21. package/Input/InputDropDown.tsx +0 -2
  22. package/Input/InputMoney.tsx +10 -9
  23. package/Input/InputOTP.tsx +0 -2
  24. package/Input/InputSearch.tsx +7 -3
  25. package/Input/index.tsx +18 -3
  26. package/Input/styles.ts +1 -0
  27. package/Layout/Screen.tsx +2 -7
  28. package/Radio/index.tsx +2 -2
  29. package/Radio/styles.ts +4 -1
  30. package/Text/index.tsx +106 -36
  31. package/Title/index.tsx +19 -5
  32. package/Title/types.ts +6 -0
  33. package/code-scanner.js +1 -1
  34. package/package.json +1 -1
  35. package/publish.sh +0 -1
  36. package/verify.js +1 -1
  37. package/tsconfig.json +0 -24
@@ -20,6 +20,7 @@ import {Icon} from '../Icon';
20
20
  const BottomSheet: React.FC<BottomSheetParams> = props => {
21
21
  const {theme, navigator} = useContext(ApplicationContext);
22
22
  const heightDevice = Dimensions.get('screen').height;
23
+ const action = useRef<undefined | string>();
23
24
  const insets = useSafeAreaInsets();
24
25
  const {
25
26
  screen: Screen,
@@ -29,6 +30,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
29
30
  barrierDismissible = false,
30
31
  draggable = true,
31
32
  useBottomInset = true,
33
+ useKeyboardAvoidingView = true,
32
34
  keyboardVerticalOffset,
33
35
  }: BottomSheetParams = props.route.params;
34
36
  const pan = useRef(
@@ -53,6 +55,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
53
55
  },
54
56
  onPanResponderRelease: (_, gestureState) => {
55
57
  if (gestureState.dy > 100) {
58
+ action.current = 'gesture';
56
59
  onDismiss();
57
60
  } else {
58
61
  Animated.spring(pan, {
@@ -82,7 +85,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
82
85
  duration: 150,
83
86
  }).start();
84
87
  return () => {
85
- props.route.params?.onDismiss?.();
88
+ props.route.params?.onDismiss?.(action.current);
86
89
  };
87
90
  }, []);
88
91
 
@@ -150,7 +153,10 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
150
153
  )}
151
154
  <TouchableOpacity
152
155
  style={styles.iconButton}
153
- onPress={() => onDismiss(true)}>
156
+ onPress={() => {
157
+ action.current = 'icon_close';
158
+ onDismiss(true);
159
+ }}>
154
160
  <Icon source="navigation_close" />
155
161
  </TouchableOpacity>
156
162
  </View>
@@ -162,16 +168,25 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
162
168
  <Container
163
169
  transparent
164
170
  visible={true}
165
- onRequestClose={() => onDismiss()}
171
+ onRequestClose={() => {
172
+ onDismiss();
173
+ }}
166
174
  style={styles.overlay}>
167
175
  <KeyboardAvoidingView
168
- behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
176
+ behavior={Platform.select({
177
+ ios: 'padding',
178
+ android: undefined,
179
+ })}
169
180
  keyboardVerticalOffset={keyboardVerticalOffset ?? -20}
181
+ enabled={useKeyboardAvoidingView}
170
182
  style={[Styles.flex, {justifyContent: 'flex-end'}]}>
171
183
  <TouchableOpacity
172
184
  style={Styles.flex}
173
185
  activeOpacity={1}
174
- onPress={() => onDismiss()}
186
+ onPress={() => {
187
+ action.current = 'touch';
188
+ onDismiss();
189
+ }}
175
190
  />
176
191
  <Animated.View style={{transform: pan.getTranslateTransform()}}>
177
192
  {renderHeader()}
@@ -16,7 +16,7 @@ import {
16
16
  View,
17
17
  } from 'react-native';
18
18
  import {EdgeInsets, useSafeAreaInsets} from 'react-native-safe-area-context';
19
- import {Radius} from '../../Consts';
19
+ import {Colors, Radius} from '../../Consts';
20
20
  import {Icon} from '../../Icon';
21
21
  import {Text} from '../../Text';
22
22
  import {FloatingButtonProps} from '../types';
@@ -207,7 +207,7 @@ export default function BottomTabBar({
207
207
  return (
208
208
  <Animated.View
209
209
  style={[
210
- styles.tabBar,
210
+ floatingButton ? styles.tabBarFloatingButton : styles.tabBar,
211
211
  {
212
212
  backgroundColor: theme.colors.background.surface,
213
213
  borderTopColor: theme.colors.border.default,
@@ -253,6 +253,17 @@ const styles = StyleSheet.create({
253
253
  borderTopWidth: StyleSheet.hairlineWidth,
254
254
  elevation: 8,
255
255
  },
256
+ tabBarFloatingButton: {
257
+ left: 0,
258
+ right: 0,
259
+ bottom: 0,
260
+ zIndex: 1,
261
+ shadowColor: Colors.black_20,
262
+ shadowOffset: {width: 0, height: -2},
263
+ shadowOpacity: 0.05,
264
+ shadowRadius: 3,
265
+ elevation: 8,
266
+ },
256
267
  floatingContainer: {
257
268
  position: 'absolute',
258
269
  alignItems: 'center',
@@ -7,7 +7,7 @@ import {EventArg} from '@react-navigation/core';
7
7
  import {useSafeAreaInsets} from 'react-native-safe-area-context';
8
8
  import {Colors} from '../../Consts';
9
9
  import {Icon} from '../../Icon';
10
- import {Text} from '../../Text';
10
+ import {exportFontFamily, Text} from '../../Text';
11
11
  import {ApplicationContext} from '../index';
12
12
  import StackScreen from '../StackScreen';
13
13
  import {BottomTabProps, NavigationScreenProps} from '../types';
@@ -146,7 +146,7 @@ const BottomTab: React.FC<BottomTabProps> = ({
146
146
  lineHeight: Platform.OS === 'android' ? 17 : 14,
147
147
  fontWeight: 'bold',
148
148
  alignSelf: 'center',
149
- fontFamily: `${theme.font}-Bold`,
149
+ fontFamily: exportFontFamily('bold'),
150
150
  left: isDot ? 8 : 4,
151
151
  top: isDot ? -2 : -6,
152
152
  backgroundColor: isNum ? Colors.red_03 : Colors.orange_03,
@@ -10,6 +10,7 @@ const ServiceItem: React.FC<any> = ({service}) => {
10
10
  const {title, description, icon, onPress} = service;
11
11
  const serviceTitle = translate?.(title);
12
12
  const serviceDescription = translate?.(description);
13
+
13
14
  return (
14
15
  <TouchableOpacity onPress={onPress} style={Styles.row}>
15
16
  <View style={styles.iconWrapper}>
@@ -35,6 +36,20 @@ const BottomSheetHelpCenter: React.FC<any> = ({onRequestClose}) => {
35
36
  const context = useContext<any>(MiniAppContext);
36
37
 
37
38
  const onPressFaq = () => {
39
+ const routes = navigator?.ref.current?.getRootState()?.routes || [];
40
+ const routesLength = routes.length;
41
+ let screenName = routes?.[0]?.params?.screen?.name;
42
+ if (routesLength > 1) {
43
+ screenName = routes[routesLength - 2]?.params?.screen?.name;
44
+ }
45
+
46
+ context?.autoTracking?.({
47
+ ...context,
48
+ componentName: 'TouchableOpacity',
49
+ componentId: 'bottomsheet_faq_item',
50
+ screenName: screenName,
51
+ });
52
+
38
53
  onRequestClose?.(() => {
39
54
  navigator?.maxApi?.startFeatureCode?.(
40
55
  'helpcenter_problemlevel1',
@@ -44,6 +59,20 @@ const BottomSheetHelpCenter: React.FC<any> = ({onRequestClose}) => {
44
59
  };
45
60
 
46
61
  const onPressChatbot = () => {
62
+ const routes = navigator?.ref.current?.getRootState()?.routes || [];
63
+ const routesLength = routes.length;
64
+ let screenName = routes?.[0]?.params?.screen?.name;
65
+ if (routesLength > 1) {
66
+ screenName = routes[routesLength - 2]?.params?.screen?.name;
67
+ }
68
+
69
+ context?.autoTracking?.({
70
+ ...context,
71
+ componentName: 'TouchableOpacity',
72
+ componentId: 'bottomsheet_chatbot_item',
73
+ screenName: screenName,
74
+ });
75
+
47
76
  onRequestClose?.(() => {
48
77
  navigator?.maxApi?.getDataObserver('CURRENT_SCREEN', (data: any) => {
49
78
  let screenName = data?.screenName;
@@ -61,6 +90,20 @@ const BottomSheetHelpCenter: React.FC<any> = ({onRequestClose}) => {
61
90
  };
62
91
 
63
92
  const onPressFeedback = () => {
93
+ const routes = navigator?.ref.current?.getRootState()?.routes || [];
94
+ const routesLength = routes.length;
95
+ let screenName = routes?.[0]?.params?.screen?.name;
96
+ if (routesLength > 1) {
97
+ screenName = routes[routesLength - 2]?.params?.screen?.name;
98
+ }
99
+
100
+ context?.autoTracking?.({
101
+ ...context,
102
+ componentName: 'TouchableOpacity',
103
+ componentId: 'bottomsheet_feedback_item',
104
+ screenName: screenName,
105
+ });
106
+
64
107
  onRequestClose?.(() => {
65
108
  navigator?.maxApi?.startFeatureCode?.('feedback', {
66
109
  forService: 'navigation',
@@ -71,6 +114,8 @@ const BottomSheetHelpCenter: React.FC<any> = ({onRequestClose}) => {
71
114
  appName: context?.name?.['en'],
72
115
  buildNumber: context?.buildNumber,
73
116
  },
117
+ newUi: true,
118
+ stepFeedback: 1,
74
119
  });
75
120
  });
76
121
  };
@@ -35,7 +35,8 @@ const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
35
35
  return (
36
36
  <Animated.View
37
37
  style={{
38
- height: 210,
38
+ width: '100%',
39
+ aspectRatio: 16 / 9,
39
40
  opacity: opacity,
40
41
  transform: [{scale}, {translateY}],
41
42
  }}>
@@ -13,15 +13,15 @@ const LinearGradientAnimated = Animated.createAnimatedComponent(LinearGradient);
13
13
  */
14
14
  const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
15
15
  image,
16
- animatedValue,
16
+ animatedValue = new Animated.Value(0),
17
17
  useGradient = true,
18
18
  useShadowHeader = true,
19
- gradientColor,
19
+ gradientColor: customGradientColor,
20
20
  headerBackground,
21
21
  }) => {
22
22
  const {theme} = useContext(ApplicationContext);
23
23
 
24
- const linearGradientColor = gradientColor ?? theme.colors.gradient;
24
+ const gradientColor = customGradientColor ?? theme.colors.gradient;
25
25
 
26
26
  let headerImage = headerBackground ?? theme.assets?.headerBackground;
27
27
  if (image === null) {
@@ -48,13 +48,21 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
48
48
  {
49
49
  backgroundColor: theme.colors.background.surface,
50
50
  opacity: opacityBackground,
51
+ overflow: 'hidden',
51
52
  },
52
- ]}
53
- />
53
+ ]}>
54
+ {theme?.assets?.headerBackground && (
55
+ <Image
56
+ style={styles.headerBackground}
57
+ source={{uri: theme?.assets?.headerBackground}}
58
+ loading={false}
59
+ />
60
+ )}
61
+ </Animated.View>
54
62
  <View style={styles.gradientContainer}>
55
- {useGradient && (
63
+ {useGradient && !!gradientColor && (
56
64
  <LinearGradientAnimated
57
- colors={[linearGradientColor, linearGradientColor + '00']}
65
+ colors={[gradientColor, gradientColor + '00']}
58
66
  style={[styles.extendedHeader, {opacity: opacityGradient}]}>
59
67
  {!!headerImage && (
60
68
  <Image
@@ -107,9 +115,8 @@ const styles = StyleSheet.create({
107
115
  },
108
116
  headerBackground: {
109
117
  width: '100%',
110
- height: undefined,
111
118
  position: 'absolute',
112
- aspectRatio: 375 / 154,
119
+ aspectRatio: 375 / 152,
113
120
  },
114
121
  dividerHeader: {
115
122
  borderBottomWidth: 1,
@@ -46,6 +46,7 @@ const HeaderExtendHeader: React.FC<{
46
46
  const gradientColor = customGradientColor ?? theme.colors.gradient;
47
47
  const headerBackground = customBackground ?? theme.assets?.headerBackground;
48
48
  const leftPosition = inputSearchProps?.leftPosition || BACK_WIDTH + 20;
49
+ const isIos = Platform.OS === 'ios';
49
50
 
50
51
  const opacityBackground = animatedValue?.interpolate({
51
52
  inputRange: [0, 52],
@@ -94,7 +95,9 @@ const HeaderExtendHeader: React.FC<{
94
95
  <Animated.View style={{height: height}} />
95
96
  <Animated.View
96
97
  style={[
97
- useShadowHeader ? styles.shadowHeader : styles.dividerHeader,
98
+ isIos && useShadowHeader
99
+ ? styles.shadowHeader
100
+ : styles.dividerHeader,
98
101
  {
99
102
  backgroundColor: theme.colors.background.surface,
100
103
  opacity: opacityBackground,
@@ -102,26 +105,36 @@ const HeaderExtendHeader: React.FC<{
102
105
  width: '100%',
103
106
  height: heightHeader,
104
107
  zIndex: 1,
108
+ overflow: 'hidden',
105
109
  },
106
- ]}
107
- />
110
+ ]}>
111
+ {headerBackground && (
112
+ <Image
113
+ style={styles.headerBackground}
114
+ source={{uri: headerBackground}}
115
+ loading={false}
116
+ />
117
+ )}
118
+ </Animated.View>
108
119
 
109
120
  <Animated.View
110
121
  style={[
111
122
  styles.headerBox,
112
123
  {height: headerType === 'extended' ? height : heightHeader},
113
124
  ]}>
114
- <LinearGradientAnimated
115
- colors={[gradientColor, gradientColor + '00']}
116
- style={[styles.extendedHeader, {opacity: opacityGradient}]}>
117
- {!!theme.assets?.headerBackground && (
118
- <Image
119
- style={styles.headerBackground}
120
- source={{uri: theme.assets?.headerBackground}}
121
- loading={false}
122
- />
123
- )}
124
- </LinearGradientAnimated>
125
+ {!!gradientColor && (
126
+ <LinearGradientAnimated
127
+ colors={[gradientColor, gradientColor + '00']}
128
+ style={[styles.extendedHeader, {opacity: opacityGradient}]}>
129
+ {!!theme.assets?.headerBackground && (
130
+ <Image
131
+ style={styles.headerBackground}
132
+ source={{uri: theme.assets?.headerBackground}}
133
+ loading={false}
134
+ />
135
+ )}
136
+ </LinearGradientAnimated>
137
+ )}
125
138
  </Animated.View>
126
139
 
127
140
  <Animated.View
@@ -172,20 +185,30 @@ const HeaderExtendHeader: React.FC<{
172
185
  height: heightHeader,
173
186
  backgroundColor: theme.colors.background.surface,
174
187
  opacity: opacityBackground,
188
+ overflow: 'hidden',
175
189
  },
176
- ]}
177
- />
178
- <LinearGradientAnimated
179
- colors={[gradientColor, gradientColor + '00']}
180
- style={[styles.extendedHeader, {opacity: opacityGradient}]}>
181
- {!!headerBackground && (
190
+ ]}>
191
+ {headerBackground && (
182
192
  <Image
183
193
  style={styles.headerBackground}
184
194
  source={{uri: headerBackground}}
185
195
  loading={false}
186
196
  />
187
197
  )}
188
- </LinearGradientAnimated>
198
+ </Animated.View>
199
+ {!!gradientColor && (
200
+ <LinearGradientAnimated
201
+ colors={[gradientColor, gradientColor + '00']}
202
+ style={[styles.extendedHeader, {opacity: opacityGradient}]}>
203
+ {!!headerBackground && (
204
+ <Image
205
+ style={styles.headerBackground}
206
+ source={{uri: headerBackground}}
207
+ loading={false}
208
+ />
209
+ )}
210
+ </LinearGradientAnimated>
211
+ )}
189
212
  <View style={{height: heightHeader}} />
190
213
  <Verified />
191
214
  </>
@@ -244,8 +267,14 @@ const styles = StyleSheet.create({
244
267
  shadowRadius: 10,
245
268
  },
246
269
  android: {
247
- borderBottomWidth: 1,
248
- borderColor: Colors.black_04,
270
+ shadowColor: Colors.black_17,
271
+ shadowOffset: {
272
+ width: 3,
273
+ height: 3,
274
+ },
275
+ shadowOpacity: 0.12,
276
+ shadowRadius: 10,
277
+ elevation: 10,
249
278
  },
250
279
  }),
251
280
  },
@@ -12,35 +12,21 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
12
12
  tintColor,
13
13
  preventBack,
14
14
  onPressLeftHeader,
15
+ onBackHandler,
15
16
  }) => {
16
17
  const context = useContext<any>(MiniAppContext);
17
18
  const {navigator} = useContext(ApplicationContext);
18
19
 
19
- useEffect(() => {
20
- const backHandler = BackHandler.addEventListener(
21
- 'hardwareBackPress',
22
- goBackSafe
23
- );
24
-
25
- return () => backHandler.remove();
26
- }, []);
27
-
28
20
  const goBackSafe = () => {
29
21
  const goBack = () => {
30
22
  const canGoBack = navigator?.ref?.current?.canGoBack?.();
31
23
  const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
32
- const params = {
24
+ context?.autoTracking?.({
33
25
  ...context,
34
- screen_name: currentRoute?.params?.screen?.name ?? currentRoute?.name,
35
- trigger_id: '111154000000000000',
36
- icon_name: 'back',
37
- };
38
- navigator?.maxApi?.showToastDebug?.({
39
- appId: `auto - ${context.appId}`,
40
- message: 'service_icon_clicked',
41
- params,
26
+ componentName: 'IconButton',
27
+ componentId: 'navigation_back',
28
+ screenName: currentRoute?.params?.screen?.name ?? currentRoute?.name,
42
29
  });
43
- navigator?.maxApi?.trackEvent?.('service_icon_clicked', params);
44
30
 
45
31
  if (canGoBack) {
46
32
  navigator?.ref?.current?.goBack?.();
@@ -49,7 +35,6 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
49
35
  } else {
50
36
  (global as any)?.miniAppApi?.dispatch?.('dismiss', context);
51
37
  }
52
- onPressLeftHeader?.();
53
38
  };
54
39
 
55
40
  if (preventBack) {
@@ -68,11 +53,25 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
68
53
  ),
69
54
  });
70
55
  } else {
71
- goBack();
56
+ onPressLeftHeader?.();
57
+ if (typeof onBackHandler === 'function') {
58
+ onBackHandler(goBack);
59
+ } else {
60
+ goBack();
61
+ }
72
62
  }
73
63
  return true;
74
64
  };
75
65
 
66
+ useEffect(() => {
67
+ const backHandler = BackHandler.addEventListener(
68
+ 'hardwareBackPress',
69
+ goBackSafe
70
+ );
71
+
72
+ return () => backHandler.remove();
73
+ }, [goBackSafe]);
74
+
76
75
  return (
77
76
  <View style={styles.headerLeft}>
78
77
  <NavigationButton
@@ -15,25 +15,16 @@ import {scaleSize, Text} from '../../Text';
15
15
  import {BottomSheetHelpCenter} from './BottomSheetHelpCenter';
16
16
  import {Image} from '../../Image';
17
17
 
18
- const WHITE_LIST = [
19
- 'vn.momo.appx',
20
- 'vn.momo.transactionhistory',
21
- 'vn.momo.promotionhub',
22
- ];
23
-
18
+ const DID_SYNC_NEW_HOME = 'did_sync_new_home';
24
19
  /**
25
20
  * main component for header right
26
21
  */
27
22
  const HeaderRight: React.FC<any> = props => {
28
23
  const {headerRight = {}} = props;
29
24
  const {useOnBoarding = false, buttonOnBoarding, onPress} = headerRight;
30
- const context = useContext<any>(MiniAppContext);
31
25
  const {translate} = useContext(ApplicationContext);
32
26
 
33
- if (
34
- WHITE_LIST.includes(context?.appId) &&
35
- typeof props.headerRight === 'function'
36
- ) {
27
+ if (typeof props.headerRight === 'function') {
37
28
  return props.headerRight(props);
38
29
  }
39
30
 
@@ -61,12 +52,13 @@ const HeaderRight: React.FC<any> = props => {
61
52
  const HeaderToolkitAction: React.FC<any> = ({
62
53
  tintColor,
63
54
  preventClose,
64
- useShortcut = true,
55
+ useShortcut = false,
65
56
  useMore = false,
66
57
  tools = [],
67
58
  }) => {
68
59
  const {navigator, translate} = useContext(ApplicationContext);
69
60
  const context = useContext<any>(MiniAppContext);
61
+ const appCode = navigator?.appCode ? navigator?.appCode : context?.code;
70
62
 
71
63
  const [isFavorite, setIsFavorite] = useState<boolean>(false);
72
64
  const [isLoading, setIsLoading] = useState(false);
@@ -74,11 +66,22 @@ const HeaderToolkitAction: React.FC<any> = ({
74
66
  useEffect(() => {
75
67
  if (useShortcut) {
76
68
  checkAppIsFavorite();
69
+
70
+ const favoriteObserver = navigator?.maxApi?.observer?.(
71
+ DID_SYNC_NEW_HOME,
72
+ (updatedData: any) => {
73
+ const status = updatedData?.items?.includes(appCode);
74
+ setIsFavorite(status);
75
+ }
76
+ );
77
+ return () => {
78
+ favoriteObserver?.remove?.();
79
+ };
77
80
  }
78
- }, []);
81
+ }, [useShortcut, context, appCode]);
79
82
 
80
83
  let buttonStyle: ViewStyle = {};
81
- if (tintColor === Colors.black_01) {
84
+ if (tintColor === Colors.black_01 || tintColor === 'white') {
82
85
  buttonStyle = {
83
86
  backgroundColor: '#00000099',
84
87
  borderColor: '#FFFFFF33',
@@ -88,22 +91,23 @@ const HeaderToolkitAction: React.FC<any> = ({
88
91
  /**
89
92
  * check app is favorite
90
93
  */
91
- const checkAppIsFavorite = () => {
92
- navigator?.maxApi?.dispatchFunction?.(
93
- 'isFavoriteApp',
94
- context?.app_code,
95
- (result: boolean) => {
96
- if (result !== isFavorite) {
97
- setIsFavorite(result);
98
- }
99
- }
100
- );
101
- };
94
+ const checkAppIsFavorite = () =>
95
+ navigator?.maxApi?.isFavoriteApp(appCode, (result: boolean) => {
96
+ setIsFavorite(result);
97
+ });
102
98
 
103
99
  /**
104
100
  * close navigation container
105
101
  */
106
102
  const onClose = () => {
103
+ const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
104
+ context?.autoTracking?.({
105
+ ...context,
106
+ componentName: 'IconButton',
107
+ componentId: 'navigation_close',
108
+ screenName: currentRoute?.params?.screen?.name ?? currentRoute?.name,
109
+ });
110
+
107
111
  if (preventClose) {
108
112
  navigator?.showModal({
109
113
  screen: () => (
@@ -132,13 +136,20 @@ const HeaderToolkitAction: React.FC<any> = ({
132
136
  * on press shortcut
133
137
  */
134
138
  const onPressShortcut = () => {
139
+ const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
140
+ context?.autoTracking?.({
141
+ ...context,
142
+ componentName: 'IconButton',
143
+ componentId: 'navigation_shortcut',
144
+ screenName: currentRoute?.params?.screen?.name ?? currentRoute?.name,
145
+ });
135
146
  setIsLoading(true);
136
- navigator?.maxApi?.dispatchFunction?.(
137
- 'onToolAction',
147
+ navigator?.maxApi?.onToolAction(
138
148
  {
139
149
  item: {
140
150
  key: 'onFavorite',
141
151
  },
152
+ code: appCode,
142
153
  },
143
154
  ({success}: {success: boolean}) => {
144
155
  if (success) {
@@ -157,6 +168,14 @@ const HeaderToolkitAction: React.FC<any> = ({
157
168
  const onPressHelpCenter = () => {
158
169
  const appName = translate?.(context?.name);
159
170
  const appDescription = translate?.(context?.description);
171
+ const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
172
+ context?.autoTracking?.({
173
+ ...context,
174
+ componentName: 'IconButton',
175
+ componentId: 'navigation_helpcenter',
176
+ screenName: currentRoute?.params?.screen?.name ?? currentRoute?.name,
177
+ });
178
+
160
179
  navigator?.showBottomSheet({
161
180
  options: {
162
181
  header: (
@@ -167,11 +186,13 @@ const HeaderToolkitAction: React.FC<any> = ({
167
186
  />
168
187
  <View>
169
188
  <Text typography={'label_default_medium'}>{appName}</Text>
170
- <Text
171
- typography={'description_default_regular'}
172
- color={Colors.black_12}>
173
- {appDescription}
174
- </Text>
189
+ {appDescription !== '{}' && (
190
+ <Text
191
+ typography={'description_default_regular'}
192
+ color={Colors.black_12}>
193
+ {appDescription}
194
+ </Text>
195
+ )}
175
196
  </View>
176
197
  </View>
177
198
  ),
@@ -185,7 +206,15 @@ const HeaderToolkitAction: React.FC<any> = ({
185
206
  * on press icon more
186
207
  */
187
208
  const onPressIconMore = () => {
188
- navigator?.maxApi?.dispatchFunction?.('showTools', tools, (key: string) => {
209
+ const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
210
+ context?.autoTracking?.({
211
+ ...context,
212
+ componentName: 'IconButton',
213
+ componentId: 'navigation_more',
214
+ screenName: currentRoute?.params?.screen?.name ?? currentRoute?.name,
215
+ });
216
+
217
+ navigator?.maxApi?.showTools(tools, appCode, (key: string) => {
189
218
  for (const group of tools) {
190
219
  const pressedTool = group?.items?.find?.(
191
220
  (tool: Tool) => tool?.key === key
@@ -215,7 +244,16 @@ const HeaderToolkitAction: React.FC<any> = ({
215
244
  (group: ToolGroup) => group?.items?.length === 1
216
245
  )?.items[0];
217
246
  iconShortcut = singleTool?.icon;
218
- shortcutOnPress = singleTool?.onPress;
247
+ shortcutOnPress = () => {
248
+ singleTool?.onPress?.();
249
+ const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
250
+ context?.autoTracking?.({
251
+ ...context,
252
+ componentName: 'IconButton',
253
+ componentId: 'navigation_shortcut',
254
+ screenName: currentRoute?.params?.screen?.name ?? currentRoute?.name,
255
+ });
256
+ };
219
257
  }
220
258
 
221
259
  const showBadge = tools.some((group: ToolGroup) =>