@eohjsc/react-native-smart-city 0.3.27 → 0.3.30

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 (118) hide show
  1. package/index.js +2 -0
  2. package/package.json +1 -1
  3. package/src/Images/Common/device_icon.png +0 -0
  4. package/src/Images/DevMode/gateway.png +0 -0
  5. package/src/Images/DevMode/gateway@2x.png +0 -0
  6. package/src/Images/DevMode/gateway@3x.png +0 -0
  7. package/src/Images/DevMode/menu.png +0 -0
  8. package/src/Images/DevMode/menu@2x.png +0 -0
  9. package/src/Images/DevMode/menu@3x.png +0 -0
  10. package/src/Images/DevMode/search.png +0 -0
  11. package/src/Images/DevMode/search@2x.png +0 -0
  12. package/src/Images/DevMode/search@3x.png +0 -0
  13. package/src/Images/DevMode/smart.png +0 -0
  14. package/src/Images/DevMode/smart@2x.png +0 -0
  15. package/src/Images/DevMode/smart@3x.png +0 -0
  16. package/src/Images/DevMode/template.png +0 -0
  17. package/src/Images/DevMode/template@2x.png +0 -0
  18. package/src/Images/DevMode/template@3x.png +0 -0
  19. package/src/commons/Action/ItemQuickAction.js +1 -0
  20. package/src/commons/ActionGroup/CurtainButtonTemplate.js +1 -2
  21. package/src/commons/ActionGroup/OnOffTemplate/OnOffButtonTemplate.js +2 -0
  22. package/src/commons/ActionGroup/SliderRangeTemplate.js +22 -14
  23. package/src/commons/ActionTemplate/CurtainAction.js +60 -0
  24. package/src/commons/ActionTemplate/CurtainActionStyles.js +11 -0
  25. package/src/commons/ActionTemplate/OnOffSmartLockAction.js +44 -0
  26. package/src/commons/ActionTemplate/OnOffSmartLockActionStyles.js +11 -0
  27. package/src/commons/ActionTemplate/index.js +18 -0
  28. package/src/commons/BottomButtonView/index.js +1 -0
  29. package/src/commons/Button/index.js +2 -0
  30. package/src/commons/CameraDevice/index.js +1 -2
  31. package/src/commons/ConnectingProcess/DeviceItem/DeviceItem.js +20 -12
  32. package/src/commons/ConnectingProcess/DeviceItem/DeviceItemStyles.js +2 -0
  33. package/src/commons/ConnectingProcess/__test__/DeviceItem.test.js +1 -1
  34. package/src/commons/ConnectingProcess/index.js +11 -0
  35. package/src/commons/Dashboard/MyUnit/index.js +1 -1
  36. package/src/commons/DevMode/Label.js +10 -0
  37. package/src/commons/DevMode/Search.js +20 -0
  38. package/src/commons/DevMode/Styles/LabelStyles.js +8 -0
  39. package/src/commons/DevMode/Styles/SearchStyles.js +21 -0
  40. package/src/commons/DevMode/index.js +3 -0
  41. package/src/commons/Device/ItemAddNew/index.js +5 -1
  42. package/src/commons/Device/ItemDevice.js +12 -9
  43. package/src/commons/Form/TextInput.js +4 -0
  44. package/src/commons/HeaderAni/index.js +1 -0
  45. package/src/commons/MediaPlayerDetail/index.js +0 -20
  46. package/src/commons/MenuActionMore/index.js +11 -1
  47. package/src/commons/Modal/index.js +1 -2
  48. package/src/commons/NavBar/index.js +13 -1
  49. package/src/commons/Popover/index.js +7 -6
  50. package/src/commons/SubUnit/OneTap/ItemOneTap.js +4 -1
  51. package/src/commons/SubUnit/ShortDetail.js +1 -0
  52. package/src/commons/SummaryItem/index.js +2 -1
  53. package/src/commons/Tabbar/Styles/indexStyles.js +51 -0
  54. package/src/commons/Tabbar/index.js +110 -0
  55. package/src/commons/Unit/HeaderUnit/index.js +2 -0
  56. package/src/commons/Unit/SharedUnit.js +1 -0
  57. package/src/commons/WrapParallaxScrollView/index.js +16 -2
  58. package/src/configs/Colors.js +4 -0
  59. package/src/configs/Constants.js +16 -0
  60. package/src/configs/Images.js +6 -0
  61. package/src/hooks/Common/useDevicesStatus.js +1 -1
  62. package/src/hooks/IoT/useValueEvaluation.js +10 -19
  63. package/src/iot/RemoteControl/GoogleHome.js +6 -6
  64. package/src/navigations/GatewayStack.js +23 -0
  65. package/src/navigations/Main.js +144 -0
  66. package/src/navigations/SmartStack.js +23 -0
  67. package/src/navigations/TemplateStack.js +23 -0
  68. package/src/navigations/UnitStack.js +5 -8
  69. package/src/screens/AddNewAction/Device/index.js +5 -1
  70. package/src/screens/AddNewAction/SelectAction.js +36 -15
  71. package/src/screens/AddNewAction/__test__/SelectAction.test.js +1 -0
  72. package/src/screens/AddNewAutoSmart/index.js +2 -0
  73. package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +13 -1
  74. package/src/screens/AllCamera/__test__/index.test.js +1 -8
  75. package/src/screens/AllCamera/index.js +0 -13
  76. package/src/screens/Device/components/SensorConnectStatusViewHeader.js +10 -11
  77. package/src/screens/Device/detail.js +35 -16
  78. package/src/screens/Device/hooks/__test__/useEmergencyButton.test.js +37 -0
  79. package/src/screens/Device/hooks/useFavoriteDevice.js +4 -2
  80. package/src/screens/Drawer/Drawer.test.js +24 -0
  81. package/src/screens/Drawer/index.js +198 -0
  82. package/src/screens/EmergencyContacts/EmergencyContactsAddNew.js +3 -3
  83. package/src/screens/EmergencyContacts/EmergencyContactsSelectContacts.js +4 -7
  84. package/src/screens/Gateway/__test__/index.test.js +16 -0
  85. package/src/screens/Gateway/index.js +8 -0
  86. package/src/screens/Notification/__test__/NotificationItem.test.js +74 -104
  87. package/src/screens/Notification/components/NotificationItem.js +40 -239
  88. package/src/screens/ScriptDetail/__test__/index.test.js +40 -1
  89. package/src/screens/ScriptDetail/index.js +2 -1
  90. package/src/screens/Sharing/Components/SensorItem.js +4 -1
  91. package/src/screens/Sharing/Components/Styles/SensorItemStyles.js +4 -0
  92. package/src/screens/Sharing/Components/Styles/TitleCheckBoxStyles.js +4 -0
  93. package/src/screens/Sharing/Components/TitleCheckBox.js +17 -8
  94. package/src/screens/Smart/__test__/index.test.js +16 -0
  95. package/src/screens/Smart/index.js +8 -0
  96. package/src/screens/SubUnit/AddSubUnit.js +1 -1
  97. package/src/screens/SubUnit/EditSubUnit.js +4 -1
  98. package/src/screens/Template/Styles/indexStyles.js +51 -0
  99. package/src/screens/Template/__test__/index.test.js +16 -0
  100. package/src/screens/Template/index.js +84 -0
  101. package/src/screens/Unit/Detail.js +16 -28
  102. package/src/screens/Unit/MoreMenu.js +16 -1
  103. package/src/screens/Unit/SelectAddToFavorites.js +11 -1
  104. package/src/screens/Unit/Station/__test__/index.test.js +41 -0
  105. package/src/screens/Unit/Station/index.js +0 -1
  106. package/src/screens/Unit/Summaries.js +6 -1
  107. package/src/screens/Unit/__test__/Detail.test.js +1 -5
  108. package/src/screens/Unit/components/AutomateScript/index.js +5 -2
  109. package/src/utils/Converter/__test__/timer.test.js +99 -0
  110. package/src/utils/Functions/Search.js +17 -0
  111. package/src/utils/Functions/ShortEmail.js +4 -0
  112. package/src/utils/Functions/__test__/Search.test.js +6 -0
  113. package/src/utils/Functions/__test__/ShortEmail.test.js +6 -0
  114. package/src/utils/I18n/translations/en.json +37 -42
  115. package/src/utils/I18n/translations/vi.json +37 -44
  116. package/src/utils/Route/index.js +6 -0
  117. package/src/commons/Modal/ModalFullVideo.js +0 -48
  118. package/src/commons/Modal/Styles/ModalFullVideoStyles.js +0 -26
@@ -27,6 +27,8 @@ const _TextInput = ({
27
27
  selectionColor,
28
28
  borderBottomOnly,
29
29
  testID,
30
+ selection,
31
+ onSelectionChange,
30
32
  }) => {
31
33
  const errorStyle = !!errorText && styles.errorWrap;
32
34
  return (
@@ -64,6 +66,8 @@ const _TextInput = ({
64
66
  multiline={multiline}
65
67
  selectionColor={selectionColor}
66
68
  {...(value ? { value } : {})}
69
+ selection={selection}
70
+ onSelectionChange={onSelectionChange}
67
71
  />
68
72
  {extraText && extraText}
69
73
  {!!errorText && <Text style={styles.errorText}>{errorText}</Text>}
@@ -94,6 +94,7 @@ const HeaderAni = memo(
94
94
  style={styles.btnBack}
95
95
  onPress={onPressLeft}
96
96
  testID={TESTID.ICON_BACK}
97
+ accessibilityLabel={TESTID.ICON_BACK}
97
98
  >
98
99
  <Icon name={'left'} size={27} color={Colors.Gray9} />
99
100
  </TouchableOpacity>
@@ -7,7 +7,6 @@ import React, {
7
7
  useMemo,
8
8
  } from 'react';
9
9
  import {
10
- Image,
11
10
  View,
12
11
  StyleSheet,
13
12
  Text,
@@ -34,10 +33,8 @@ const MediaPlayerDetail = ({
34
33
  style,
35
34
  wrapStyles,
36
35
  amount,
37
- handleFullScreen,
38
36
  isPaused = true,
39
37
  goToPlayBack,
40
- isShowFullScreenIcon = false,
41
38
  width,
42
39
  height,
43
40
  }) => {
@@ -61,11 +58,6 @@ const MediaPlayerDetail = ({
61
58
  // eslint-disable-next-line react-hooks/exhaustive-deps
62
59
  }, [paused]);
63
60
 
64
- const onFullScreen = useCallback(() => {
65
- handleFullScreen && handleFullScreen({ uri, cameraName, thumbnail });
66
- // eslint-disable-next-line react-hooks/exhaustive-deps
67
- }, []);
68
-
69
61
  const getWidthHeight = useCallback(() => {
70
62
  let newWidth = 0,
71
63
  newHeight = 0;
@@ -207,18 +199,6 @@ const MediaPlayerDetail = ({
207
199
  {cameraName}
208
200
  </Text>
209
201
  )}
210
- {isShowFullScreenIcon && (
211
- <TouchableOpacity
212
- onPress={onFullScreen}
213
- style={[
214
- styles.iconFullScreen,
215
- (amount === 4 || amount === 6) && styles.iconFullScreen2,
216
- ]}
217
- testID={TESTID.SUB_UNIT_FULL_CAMERA}
218
- >
219
- <Image source={Images.fullscreen} />
220
- </TouchableOpacity>
221
- )}
222
202
  </View>
223
203
  );
224
204
  };
@@ -17,6 +17,9 @@ const MenuActionMore = memo(
17
17
  onItemClick,
18
18
  wrapStyle,
19
19
  isTextCenter = true,
20
+ idLabelPopover,
21
+ idLabelScrollView,
22
+ idLabelItem = TESTID.SUB_UNIT_NAME,
20
23
  }) => {
21
24
  const [isDisable, setIsDisable] = useState(false);
22
25
  const onPress = useCallback(
@@ -47,8 +50,12 @@ const MenuActionMore = memo(
47
50
  onRequestClose={hideMore}
48
51
  isVisible={isVisible}
49
52
  arrowStyle={styles.wrap}
53
+ accessibilityLabel={idLabelPopover}
50
54
  >
51
- <ScrollView scrollIndicatorInsets={{ right: 1 }}>
55
+ <ScrollView
56
+ scrollIndicatorInsets={{ right: 1 }}
57
+ accessibilityLabel={idLabelScrollView}
58
+ >
52
59
  {listMenuItem.map((item, index) => {
53
60
  return (
54
61
  <TouchableOpacity
@@ -59,6 +66,9 @@ const MenuActionMore = memo(
59
66
  onPress={onPress(item, index)}
60
67
  key={index}
61
68
  testID={TESTID.TOUCHABLE_ACTION_ADD_MORE}
69
+ accessibilityLabel={`${idLabelItem}-${
70
+ (item?.route ? item?.id : item?.station?.id) || index
71
+ }`}
62
72
  disabled={isDisable}
63
73
  >
64
74
  <Text style={styles.modalHeaderText}>{item.text}</Text>
@@ -1,5 +1,4 @@
1
1
  import ModalCustom from './ModalCustom';
2
- import ModalFullVideo from './ModalFullVideo';
3
2
  import ModalBottom from './ModalBottom';
4
3
 
5
- export { ModalCustom, ModalFullVideo, ModalBottom };
4
+ export { ModalCustom, ModalBottom };
@@ -10,7 +10,16 @@ import Station from '../../screens/Unit/Station';
10
10
  import MenuActionMore from '../MenuActionMore';
11
11
 
12
12
  const NavBar = memo(
13
- ({ listMenuItem, listStation, onSnapToItem, indexStation, style }) => {
13
+ ({
14
+ listMenuItem,
15
+ listStation,
16
+ onSnapToItem,
17
+ indexStation,
18
+ style,
19
+ idLabelScrollView,
20
+ idLabelItem,
21
+ idLabelIconBars,
22
+ }) => {
14
23
  const { childRef, showingPopover, showPopoverWithRef, hidePopover } =
15
24
  usePopover();
16
25
  const refMenuAction = useRef();
@@ -31,6 +40,7 @@ const NavBar = memo(
31
40
  onPress={handleShowMenuAction}
32
41
  ref={refMenuAction}
33
42
  testID={TESTID.NAVBAR_ICON_BARS}
43
+ accessibilityLabel={idLabelIconBars}
34
44
  >
35
45
  <Icon name={'bars'} size={19} color={Colors.Black} />
36
46
  </TouchableOpacity>
@@ -44,6 +54,8 @@ const NavBar = memo(
44
54
  isTextCenter={false}
45
55
  testID={TESTID.NAVBAR_MENU_ACTION_MORE}
46
56
  wrapStyle={styles.wrapStyle}
57
+ idLabelScrollView={idLabelScrollView}
58
+ idLabelItem={idLabelItem}
47
59
  />
48
60
  </>
49
61
  );
@@ -3,22 +3,23 @@ import Popover from 'react-native-popover-view';
3
3
  import { SCContext } from '../../context';
4
4
  import { Action } from '../../context/actionType';
5
5
 
6
- const PopoverComponent = (props) => {
6
+ const PopoverComponent = ({ onRequestClose, ...restProps }) => {
7
7
  const { setAction } = useContext(SCContext);
8
8
 
9
- const onCloseStart = () => {
9
+ const _onRequestClose = () => {
10
10
  setAction(Action.SET_POPOVER_ANIMATING, true);
11
+ onRequestClose && onRequestClose();
11
12
  };
12
13
 
13
- const onCloseComplete = () => {
14
+ const _onCloseComplete = () => {
14
15
  setAction(Action.SET_POPOVER_ANIMATING, false);
15
16
  };
16
17
 
17
18
  return (
18
19
  <Popover
19
- onCloseStart={onCloseStart}
20
- onCloseComplete={onCloseComplete}
21
- {...props}
20
+ onRequestClose={_onRequestClose}
21
+ onCloseComplete={_onCloseComplete}
22
+ {...restProps}
22
23
  />
23
24
  );
24
25
  };
@@ -103,7 +103,10 @@ const ItemOneTap = memo(
103
103
  ? timeDifference(new Date(), moment(activate_at), true)
104
104
  : null;
105
105
  return (
106
- <TouchableWithoutFeedback onPress={onPressItem || goToDetail}>
106
+ <TouchableWithoutFeedback
107
+ onPress={onPressItem || goToDetail}
108
+ accessibilityLabel={`${TESTID.AUTOMATE_SCRIPT_NAME}-${id}`}
109
+ >
107
110
  <View style={[styles.container, wrapSyles]}>
108
111
  <View style={styles.boxIcon}>
109
112
  {displayIcon()}
@@ -71,6 +71,7 @@ const ShortDetailSubUnit = ({ unit, station }) => {
71
71
  },
72
72
  ]}
73
73
  testID={TESTID.SUB_UNIT_CAMERA_VIEW}
74
+ accessibilityLabel={`${TESTID.SUB_UNIT_CAMERA_VIEW}-${station?.id}`}
74
75
  >
75
76
  <MediaPlayerDetail
76
77
  uri={station.camera.uri}
@@ -9,6 +9,7 @@ import Temperature from '../../../assets/images/Temperature.svg';
9
9
  import UVIndex from '../../../assets/images/UVIndex.svg';
10
10
  import WaterQuality from '../../../assets/images/WaterQuality.svg';
11
11
  import Device from '../../../assets/images/Device.svg';
12
+ import { TESTID } from '../../configs/Constants';
12
13
 
13
14
  const SummaryItem = memo(({ item, goToSummary }) => {
14
15
  const Icon = (() => {
@@ -29,11 +30,11 @@ const SummaryItem = memo(({ item, goToSummary }) => {
29
30
  return Device; /* istanbul ignore next */
30
31
  }
31
32
  })();
32
-
33
33
  return (
34
34
  <TouchableOpacity
35
35
  onPress={() => goToSummary(item)}
36
36
  style={styles.wrapSummaryItem}
37
+ accessibilityLabel={`${TESTID.UNIT_DETAIL_UNIT_SUMMARY_ITEM}-${item?.id}`}
37
38
  >
38
39
  <View style={styles.summaryItem}>
39
40
  <Icon />
@@ -0,0 +1,51 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { isIphoneX } from 'react-native-iphone-x-helper';
3
+ import { Colors } from '../../../configs';
4
+
5
+ const widthBadge = 20;
6
+ export default StyleSheet.create({
7
+ wrap: {
8
+ flexDirection: 'row',
9
+ height: 70,
10
+ backgroundColor: Colors.White,
11
+ paddingHorizontal: 10,
12
+ borderTopWidth: 1,
13
+ borderColor: Colors.Gray4,
14
+ },
15
+ label: {
16
+ textAlign: 'center',
17
+ fontSize: 12,
18
+ marginTop: 10,
19
+ marginBottom: isIphoneX() ? 10 : 0,
20
+ },
21
+ wrapTab: {
22
+ flex: 1,
23
+ justifyContent: 'center',
24
+ alignItems: 'center',
25
+ },
26
+ icon: {
27
+ marginBottom: -8,
28
+ },
29
+ wrapIcon: {
30
+ position: 'relative',
31
+ },
32
+ badgeCount: {
33
+ width: widthBadge,
34
+ height: 20,
35
+ flexDirection: 'row',
36
+ justifyContent: 'center',
37
+ alignItems: 'center',
38
+ backgroundColor: Colors.Red,
39
+ borderRadius: widthBadge / 2,
40
+ position: 'absolute',
41
+ top: -8,
42
+ right: -8,
43
+ },
44
+ txtBadge: {
45
+ color: Colors.White,
46
+ fontSize: 12,
47
+ },
48
+ iconActive: {
49
+ tintColor: Colors.Primary,
50
+ },
51
+ });
@@ -0,0 +1,110 @@
1
+ import React, { memo, useEffect } from 'react';
2
+ import { Animated, View, Text, TouchableOpacity, Image } from 'react-native';
3
+ import Routes from '../../utils/Route';
4
+ import { Colors } from '../../configs/Colors';
5
+ import { Constants } from '../../configs/Constants';
6
+ import styles from './Styles/indexStyles';
7
+ import { Images } from '../../configs';
8
+
9
+ export const getTabBarIcon = (routeName) => {
10
+ switch (routeName) {
11
+ case Routes.TemplateStack:
12
+ return Images.template;
13
+ case Routes.GatewayStack:
14
+ return Images.gateway;
15
+ case Routes.SmartStack:
16
+ return Images.smart;
17
+ }
18
+ };
19
+
20
+ const getWidth = () => (Constants.width - 12) / 3;
21
+
22
+ const TabBarItem = ({
23
+ descriptor,
24
+ route,
25
+ index,
26
+ isFocused,
27
+ navigation,
28
+ notificationNumber,
29
+ updateLastSeen,
30
+ }) => {
31
+ const { options } = descriptor;
32
+ const label =
33
+ options.tabBarLabel !== undefined
34
+ ? options.tabBarLabel
35
+ : options.title !== undefined
36
+ ? options.title
37
+ : route.name;
38
+ const color = isFocused ? Colors.Primary : Colors.Black;
39
+
40
+ const onPress = () => {
41
+ const event = navigation.emit({
42
+ type: 'tabPress',
43
+ target: route.key,
44
+ canPreventDefault: true,
45
+ });
46
+ if (!isFocused && !event.defaultPrevented) {
47
+ navigation.navigate({
48
+ name: route.name,
49
+ merge: true,
50
+ params: { isMainSource: options.isMainSource },
51
+ });
52
+ }
53
+ };
54
+
55
+ useEffect(() => {
56
+ if (isFocused) {
57
+ Animated.spring(options.tabOffSetValue, {
58
+ toValue: getWidth() * index,
59
+ useNativeDriver: true,
60
+ }).start();
61
+ }
62
+ }, [isFocused, index, options.tabOffSetValue]);
63
+
64
+ useEffect(() => {
65
+ if (isFocused) {
66
+ if (route.name === Routes.NotificationStack) {
67
+ updateLastSeen && updateLastSeen();
68
+ }
69
+ }
70
+ }, [isFocused, route.name, updateLastSeen]);
71
+
72
+ return (
73
+ <TouchableOpacity onPress={onPress} style={styles.wrapTab}>
74
+ <View style={styles.wrapIcon}>
75
+ <Image
76
+ style={[styles.icon, isFocused && styles.iconActive]}
77
+ source={getTabBarIcon(route.name)}
78
+ />
79
+ {route.name === Routes.NotificationStack && notificationNumber > 0 && (
80
+ <View style={styles.badgeCount}>
81
+ <Text style={styles.txtBadge}>
82
+ {notificationNumber < 9 ? notificationNumber : '9+'}
83
+ </Text>
84
+ </View>
85
+ )}
86
+ </View>
87
+
88
+ <Text style={[styles.label, { color }]}>{label}</Text>
89
+ </TouchableOpacity>
90
+ );
91
+ };
92
+
93
+ const TabBar = ({ state, descriptors, navigation }) => {
94
+ return (
95
+ <View style={styles.wrap}>
96
+ {state.routes.map((route, index) => (
97
+ <TabBarItem
98
+ key={index}
99
+ descriptor={descriptors[route.key]}
100
+ route={route}
101
+ index={index}
102
+ isFocused={state.index === index}
103
+ navigation={navigation}
104
+ />
105
+ ))}
106
+ </View>
107
+ );
108
+ };
109
+
110
+ export default memo(TabBar);
@@ -19,6 +19,7 @@ const HeaderUnit = memo(
19
19
  hideRightPlus,
20
20
  styleBoxTitle,
21
21
  bottomBorder,
22
+ idButtonMore,
22
23
  }) => {
23
24
  const { goBack } = useNavigation();
24
25
  const buttonMoreRef = useRef(null);
@@ -80,6 +81,7 @@ const HeaderUnit = memo(
80
81
  style={styles.btnMore}
81
82
  onPress={onPressMore}
82
83
  ref={buttonMoreRef}
84
+ accessibilityLabel={idButtonMore}
83
85
  >
84
86
  <Icon
85
87
  name={'more'}
@@ -68,6 +68,7 @@ const SharedUnit = ({
68
68
  key={item.id.toString()}
69
69
  onPress={goToDetail}
70
70
  testID={`${TESTID.TOUCH_SHARED_UNIT}-${item.id}`}
71
+ accessibilityLabel={`${TESTID.TOUCH_SHARED_UNIT}-${item.id}`}
71
72
  >
72
73
  <Image
73
74
  source={{ uri: unit.icon }}
@@ -21,6 +21,8 @@ const WrapParallaxScrollView = ({
21
21
  hideRight,
22
22
  hideRightPlus,
23
23
  contentBackground,
24
+ accessibilityLabel,
25
+ idButtonMore,
24
26
  }) => {
25
27
  const renderForeground = useCallback(
26
28
  () => (
@@ -32,6 +34,7 @@ const WrapParallaxScrollView = ({
32
34
  onMore={onMore}
33
35
  hideRight={hideRight}
34
36
  hideRightPlus={hideRightPlus}
37
+ idButtonMore={idButtonMore}
35
38
  />
36
39
  <Text semibold style={styles.nameUnit}>
37
40
  {title}
@@ -39,7 +42,16 @@ const WrapParallaxScrollView = ({
39
42
  {contentBackground}
40
43
  </View>
41
44
  ),
42
- [onBack, onAdd, onMore, title, hideRight, hideRightPlus, contentBackground]
45
+ [
46
+ onBack,
47
+ onAdd,
48
+ onMore,
49
+ hideRight,
50
+ hideRightPlus,
51
+ idButtonMore,
52
+ title,
53
+ contentBackground,
54
+ ]
43
55
  );
44
56
  const renderBackground = useCallback(
45
57
  () => (
@@ -68,10 +80,11 @@ const WrapParallaxScrollView = ({
68
80
  onMore={onMore}
69
81
  hideRight={hideRight}
70
82
  hideRightPlus={hideRightPlus}
83
+ idButtonMore={idButtonMore}
71
84
  />
72
85
  </View>
73
86
  ),
74
- [title, onBack, onAdd, onMore, hideRight, hideRightPlus]
87
+ [title, onBack, onAdd, onMore, hideRight, hideRightPlus, idButtonMore]
75
88
  );
76
89
  return (
77
90
  <ParallaxScrollView
@@ -83,6 +96,7 @@ const WrapParallaxScrollView = ({
83
96
  backgroundColor={Colors.White}
84
97
  refreshControl={refreshControl}
85
98
  showsVerticalScrollIndicator={false}
99
+ accessibilityLabel={accessibilityLabel}
86
100
  >
87
101
  {children}
88
102
  </ParallaxScrollView>
@@ -133,4 +133,8 @@ export const Colors = {
133
133
  BlackTransparent16: 'rgba(0, 0, 0, 0.16)',
134
134
  WhiteTransparent8: 'rgba(255, 255, 255, 0.8)',
135
135
  BlueTransparent5: 'rgba(230, 247, 255, 0.5)',
136
+ Neutral: {
137
+ Neutral3: '#E6E6E6',
138
+ Neutral5: '#595959',
139
+ },
136
140
  };
@@ -313,11 +313,13 @@ export const TESTID = {
313
313
  SUB_UNIT_GO_DETAIL: 'SUB_UNIT_GO_DETAIL',
314
314
  VIEW_SUB_UNIT_AUTOMATE: 'VIEW_SUB_UNIT_AUTOMATE',
315
315
  SUB_UNIT_NAME: 'SUB_UNIT_NAME',
316
+ SUB_UNIT_FAVORITES: 'SUB_UNIT_FAVORITES',
316
317
  ANIMATED_SCROLL: 'ANIMATED_SCROLL',
317
318
  ADD_SUB_UNIT: 'ADD_SUB_UNIT',
318
319
 
319
320
  // NavBar
320
321
  NAVBAR_ICON_BARS: 'NAVBAR_ICON_BARS',
322
+ NAVBAR_ICON_BARS_ADD_FAVORITES: 'NAVBAR_ICON_BARS_ADD_FAVORITES',
321
323
  NAVBAR_MENU_ACTION_MORE: 'NAVBAR_MENU_ACTION_MORE',
322
324
  NAVBAR_ON_SNAP_ITEM: 'NAVBAR_ON_SNAP_ITEM',
323
325
 
@@ -400,6 +402,11 @@ export const TESTID = {
400
402
  //Unit Detail
401
403
  UNIT_DETAIL_STATION_LIST: 'UNIT_DETAIL_STATION_LIST',
402
404
  UNIT_DETAIL_UNIT_SUMMARY_VIEW: 'UNIT_DETAIL_UNIT_SUMMARY_VIEW',
405
+ UNIT_DETAIL_UNIT_SUMMARY_ITEM: 'UNIT_DETAIL_UNIT_SUMMARY_ITEM',
406
+ UNIT_DETAIL_PARALLAX_SCROLLVIEW: 'UNIT_DETAIL_PARALLAX_SCROLLVIEW',
407
+ UNIT_DETAIL_PARALLAX_BUTTON_MORE: 'UNIT_DETAIL_PARALLAX_BUTTON_MORE',
408
+ UNIT_DETAIL_POPUP_MORE: 'UNIT_DETAIL_POPUP_MORE',
409
+ UNIT_DETAIL_POPUP_MORE_ITEM: 'UNIT_DETAIL_POPUP_MORE_ITEM',
403
410
 
404
411
  ON_CHECK_SPOT_NUMBER: 'ON_CHECK_SPOT_NUMBER',
405
412
  ON_BOOK_NOW: 'ON_BOOK_NOW',
@@ -422,6 +429,7 @@ export const TESTID = {
422
429
 
423
430
  // Automate
424
431
  AUTOMATE_SCRIPT_ACTION: 'AUTOMATE_SCRIPT_ACTION',
432
+ AUTOMATE_SCRIPT_NAME: 'AUTOMATE_SCRIPT_NAME',
425
433
  NAME_YOUR_BUTTON: 'NAME_YOUR_BUTTON',
426
434
  BUTTON_ACTIVATE_ONE_TAP: 'BUTTON_ACTIVATE_ONE_TAP',
427
435
  BUTTON_EDIT_SCRIPT_ACTION: 'BUTTON_EDIT_SCRIPT_ACTION',
@@ -439,6 +447,7 @@ export const TESTID = {
439
447
 
440
448
  // Header Device
441
449
  HEADER_DEVICE_BUTTON_STAR: 'HEADER_DEVICE_BUTTON_STAR',
450
+ HEADER_SCRIPT_DETAIL_BUTTON_STAR: 'HEADER_SCRIPT_DETAIL_BUTTON_STAR',
442
451
  HEADER_DEVICE_BUTTON_MORE: 'HEADER_DEVICE_BUTTON_MORE',
443
452
 
444
453
  // EMERGENCY BUTTON
@@ -661,6 +670,13 @@ export const TESTID = {
661
670
  ADD_NEW_DEVICE_ADD: 'ADD_NEW_DEVICE_ADD',
662
671
  ADD_NEW_DEVICE_THEN_SELECT: 'ADD_NEW_DEVICE_THEN_SELECT',
663
672
 
673
+ // Add Favorites
674
+ TOUCH_ADD_NEW_FAVORITES: 'TOUCH_ADD_NEW_FAVORITES',
675
+ LIST_FAVORITES: 'LIST_FAVORITES',
676
+ TOUCHABLE_ACTION_ADD_ITEM_FAVORITE: 'TOUCHABLE_ACTION_ADD_ITEM_FAVORITE',
677
+ TOUCHABLE_ACTION_ADD_ITEM_AUTOMATE_FAVORITE:
678
+ 'TOUCHABLE_ACTION_ADD_ITEM_AUTOMATE_FAVORITE',
679
+
664
680
  // Setup gateway wifi
665
681
  SETUP_GATEWAY_WIFI_TITLE: 'SETUP_GATEWAY_WIFI_TITLE',
666
682
  SETUP_GATEWAY_WIFI_PLEASE_SELECT_A_WIFI: 'SETUP_GATEWAY_PLEASE_SELECT_A_WIFI',
@@ -13,4 +13,10 @@ export default {
13
13
  shadowButton: require('../Images/Common/shadowButton.png'),
14
14
  eye: require('../Images/Common/eye.png'),
15
15
  eyeClosed: require('../Images/Common/eye-closed.png'),
16
+ deviceIcon: require('../Images/Common/device_icon.png'),
17
+ template: require('../Images/DevMode/template.png'),
18
+ smart: require('../Images/DevMode/smart.png'),
19
+ gateway: require('../Images/DevMode/gateway.png'),
20
+ menu: require('../Images/DevMode/menu.png'),
21
+ search: require('../Images/DevMode/search.png'),
16
22
  };
@@ -27,7 +27,7 @@ const useDevicesStatus = (unit, devices) => {
27
27
  if (success) {
28
28
  setAction(Action.SET_DEVICES_STATUS, data);
29
29
  }
30
- timeoutId = setTimeout(() => getDevicesStatus(_unit, _devices), 5000);
30
+ timeoutId = setTimeout(() => getDevicesStatus(_unit, _devices), 10000);
31
31
  // eslint-disable-next-line react-hooks/exhaustive-deps
32
32
  }, []);
33
33
 
@@ -1,4 +1,4 @@
1
- import { useCallback, useContext, useEffect, useState } from 'react';
1
+ import { useCallback, useContext, useEffect } from 'react';
2
2
  import { API } from '../../configs';
3
3
  import { SCContext, useSCContextSelector } from '../../context';
4
4
  import { Action } from '../../context/actionType';
@@ -6,14 +6,15 @@ import { axiosGet } from '../../utils/Apis/axios';
6
6
 
7
7
  const useValueEvaluations = (unitId) => {
8
8
  const { setAction } = useContext(SCContext);
9
- const [fetching, setFetching] = useState(false);
9
+ const fetchedValueEvaluationUnits = useSCContextSelector((state) => {
10
+ return state.fetchedValueEvaluationUnits || [];
11
+ });
10
12
 
11
13
  const fetchConfigValueEvaluations = useCallback(
12
14
  async (page = 1) => {
13
- if (!unitId) {
15
+ if (!unitId || fetchedValueEvaluationUnits.indexOf(unitId) !== -1) {
14
16
  return;
15
17
  }
16
- setFetching(true);
17
18
  const params = new URLSearchParams();
18
19
  params.append('config__end_device__station__unit', unitId);
19
20
  params.append('page', page);
@@ -34,25 +35,15 @@ const useValueEvaluations = (unitId) => {
34
35
  data: [],
35
36
  });
36
37
  }
37
- setFetching(false);
38
38
  },
39
- [unitId, setAction]
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps
40
+ [unitId, fetchedValueEvaluationUnits]
40
41
  );
41
42
 
42
- const fetchedValueEvaluationUnits = useSCContextSelector((state) => {
43
- return state.fetchedValueEvaluationUnits || [];
44
- });
45
-
46
43
  useEffect(() => {
47
- if (!fetching && !(fetchedValueEvaluationUnits.indexOf(unitId) !== -1)) {
48
- fetchConfigValueEvaluations();
49
- }
50
- }, [
51
- unitId,
52
- fetching,
53
- fetchConfigValueEvaluations,
54
- fetchedValueEvaluationUnits,
55
- ]);
44
+ fetchConfigValueEvaluations();
45
+ // eslint-disable-next-line react-hooks/exhaustive-deps
46
+ }, [unitId]);
56
47
  };
57
48
 
58
49
  export default useValueEvaluations;
@@ -127,12 +127,6 @@ export const googleHomeConnect = async (
127
127
  for (let i = 0; i < options.length; i++) {
128
128
  const option = options[i];
129
129
 
130
- if (option.chip_id in oldConnections && !!oldConnections[option.chip_id]) {
131
- connections[option.chip_id] = oldConnections[option.chip_id];
132
- continue;
133
- }
134
- connections[option.chip_id] = 0; // connecting
135
-
136
130
  option.config_maps.forEach((configMap) => {
137
131
  if (option.text_maps) {
138
132
  textMaps[configMap.entity_id] = option.text_maps;
@@ -156,6 +150,12 @@ export const googleHomeConnect = async (
156
150
  }
157
151
  });
158
152
 
153
+ if (option.chip_id in oldConnections && !!oldConnections[option.chip_id]) {
154
+ connections[option.chip_id] = oldConnections[option.chip_id];
155
+ continue;
156
+ }
157
+ connections[option.chip_id] = 0; // connecting
158
+
159
159
  try {
160
160
  let auth = new Auth(option.auth);
161
161
  const connection = await createConnection({ auth });
@@ -0,0 +1,23 @@
1
+ import React, { memo } from 'react';
2
+ import { createStackNavigator } from '@react-navigation/stack';
3
+
4
+ import Routes from '../utils/Route';
5
+ import { screenOptions } from './utils';
6
+ import Gateway from '../screens/Gateway';
7
+
8
+ const Stack = createStackNavigator();
9
+
10
+ const GatewayStack = memo(() => {
11
+ return (
12
+ <Stack.Navigator
13
+ screenOptions={{
14
+ ...screenOptions,
15
+ headerShown: false,
16
+ }}
17
+ >
18
+ <Stack.Screen name={Routes.Gateway} component={Gateway} />
19
+ </Stack.Navigator>
20
+ );
21
+ });
22
+
23
+ export default GatewayStack;