@eohjsc/react-native-smart-city 0.3.26 → 0.3.29

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 (108) 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/ActionGroup/CurtainButtonTemplate.js +1 -2
  20. package/src/commons/ActionGroup/OnOffTemplate/OnOffButtonTemplate.js +2 -0
  21. package/src/commons/ActionTemplate/CurtainAction.js +60 -0
  22. package/src/commons/ActionTemplate/CurtainActionStyles.js +11 -0
  23. package/src/commons/ActionTemplate/OnOffSmartLockAction.js +44 -0
  24. package/src/commons/ActionTemplate/OnOffSmartLockActionStyles.js +11 -0
  25. package/src/commons/ActionTemplate/index.js +18 -0
  26. package/src/commons/CameraDevice/index.js +1 -2
  27. package/src/commons/ConnectingProcess/DeviceItem/DeviceItem.js +20 -12
  28. package/src/commons/ConnectingProcess/DeviceItem/DeviceItemStyles.js +2 -0
  29. package/src/commons/ConnectingProcess/__test__/DeviceItem.test.js +1 -1
  30. package/src/commons/ConnectingProcess/index.js +11 -0
  31. package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +55 -5
  32. package/src/commons/Dashboard/MyUnit/index.js +59 -12
  33. package/src/commons/DevMode/Label.js +10 -0
  34. package/src/commons/DevMode/Search.js +20 -0
  35. package/src/commons/DevMode/Styles/LabelStyles.js +8 -0
  36. package/src/commons/DevMode/Styles/SearchStyles.js +21 -0
  37. package/src/commons/DevMode/index.js +3 -0
  38. package/src/commons/Device/ItemDevice.js +1 -0
  39. package/src/commons/Form/TextInput.js +4 -0
  40. package/src/commons/HeaderAni/index.js +1 -0
  41. package/src/commons/MediaPlayerDetail/index.js +0 -20
  42. package/src/commons/MenuActionMore/index.js +12 -4
  43. package/src/commons/Modal/index.js +1 -2
  44. package/src/commons/NavBar/index.js +12 -1
  45. package/src/commons/Popover/index.js +26 -0
  46. package/src/commons/SubUnit/ShortDetail.js +1 -0
  47. package/src/commons/SummaryItem/index.js +2 -1
  48. package/src/commons/Tabbar/Styles/indexStyles.js +51 -0
  49. package/src/commons/Tabbar/index.js +110 -0
  50. package/src/commons/Unit/HeaderUnit/index.js +2 -0
  51. package/src/commons/Unit/SharedUnit.js +1 -0
  52. package/src/commons/WrapParallaxScrollView/index.js +16 -2
  53. package/src/configs/Colors.js +4 -0
  54. package/src/configs/Constants.js +5 -0
  55. package/src/configs/Images.js +6 -0
  56. package/src/context/actionType.ts +2 -0
  57. package/src/context/reducer.ts +10 -0
  58. package/src/hooks/Common/useGGHomeDeviceConnected.js +9 -2
  59. package/src/hooks/Common/usePopover.js +0 -8
  60. package/src/hooks/IoT/useGGHomeConnection.js +0 -1
  61. package/src/navigations/GatewayStack.js +23 -0
  62. package/src/navigations/Main.js +144 -0
  63. package/src/navigations/SmartStack.js +23 -0
  64. package/src/navigations/TemplateStack.js +23 -0
  65. package/src/navigations/UnitStack.js +10 -2
  66. package/src/screens/AddNewAction/SelectAction.js +6 -1
  67. package/src/screens/AllCamera/__test__/index.test.js +1 -8
  68. package/src/screens/AllCamera/index.js +0 -13
  69. package/src/screens/Device/hooks/__test__/useEmergencyButton.test.js +37 -0
  70. package/src/screens/Drawer/Drawer.test.js +24 -0
  71. package/src/screens/Drawer/index.js +198 -0
  72. package/src/screens/Gateway/__test__/index.test.js +16 -0
  73. package/src/screens/Gateway/index.js +8 -0
  74. package/src/screens/Notification/__test__/NotificationItem.test.js +79 -85
  75. package/src/screens/Notification/components/NotificationItem.js +37 -220
  76. package/src/screens/ScriptDetail/__test__/index.test.js +39 -3
  77. package/src/screens/ScriptDetail/index.js +7 -10
  78. package/src/screens/Smart/__test__/index.test.js +16 -0
  79. package/src/screens/Smart/index.js +8 -0
  80. package/src/screens/SubUnit/AddSubUnit.js +1 -1
  81. package/src/screens/SubUnit/EditSubUnit.js +4 -1
  82. package/src/screens/Template/Styles/indexStyles.js +51 -0
  83. package/src/screens/Template/__test__/index.test.js +16 -0
  84. package/src/screens/Template/index.js +84 -0
  85. package/src/screens/Unit/Detail.js +10 -27
  86. package/src/screens/Unit/MoreMenu.js +16 -1
  87. package/src/screens/Unit/SmartAccount.js +7 -6
  88. package/src/screens/Unit/Station/__test__/index.test.js +41 -0
  89. package/src/screens/Unit/Station/index.js +0 -1
  90. package/src/screens/Unit/Summaries.js +14 -2
  91. package/src/screens/Unit/__test__/Detail.test.js +1 -5
  92. package/src/screens/Unit/components/Header/index.js +1 -1
  93. package/src/screens/Unit/components/MyUnitDevice/index.js +29 -12
  94. package/src/screens/Unit/components/__test__/Header.test.js +1 -1
  95. package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +2 -2
  96. package/src/screens/Unit/hook/useUnitConnectRemoteDevices.js +6 -5
  97. package/src/utils/Converter/__test__/timer.test.js +99 -0
  98. package/src/utils/Functions/Search.js +17 -0
  99. package/src/utils/Functions/ShortEmail.js +4 -0
  100. package/src/utils/Functions/__test__/Search.test.js +6 -0
  101. package/src/utils/Functions/__test__/ShortEmail.test.js +6 -0
  102. package/src/utils/I18n/translations/en.json +32 -42
  103. package/src/utils/I18n/translations/vi.json +32 -44
  104. package/src/utils/Route/index.js +6 -0
  105. package/src/commons/Modal/ModalFullVideo.js +0 -48
  106. package/src/commons/Modal/Styles/ModalFullVideoStyles.js +0 -26
  107. package/src/screens/Unit/components/MyUnit/index.js +0 -136
  108. package/src/screens/Unit/components/__test__/MyUnit.test.js +0 -35
@@ -103,7 +103,6 @@ describe('Test ScriptDetail', () => {
103
103
 
104
104
  await act(async () => {
105
105
  await menu.props.onItemClick(rename);
106
- await menu.props.hideComplete();
107
106
  });
108
107
  expect(menu.props.isVisible).toBeFalsy();
109
108
  expect(alertAction.props.visible).toBeTruthy();
@@ -130,7 +129,6 @@ describe('Test ScriptDetail', () => {
130
129
 
131
130
  await act(async () => {
132
131
  await menu.props.onItemClick(rename);
133
- await menu.props.hideComplete();
134
132
  });
135
133
  expect(menu.props.isVisible).toBeFalsy();
136
134
  expect(alertAction.props.visible).toBeTruthy();
@@ -154,7 +152,6 @@ describe('Test ScriptDetail', () => {
154
152
 
155
153
  await act(async () => {
156
154
  await menu.props.onItemClick(deleteItem);
157
- await menu.props.hideComplete();
158
155
  });
159
156
  expect(alertAction.props.visible).toBeTruthy();
160
157
  mock.onDelete(API.AUTOMATE.SCRIPT(1)).reply(204);
@@ -358,4 +355,43 @@ describe('Test ScriptDetail', () => {
358
355
  'Light Value lower than 3'
359
356
  );
360
357
  });
358
+
359
+ test('Test render textCondition schedule repeat everyday', async () => {
360
+ route.params = {
361
+ ...route.params,
362
+ type: AUTOMATE_TYPE.SCHEDULE,
363
+ automate: {
364
+ repeat: 'every_day',
365
+ date_repeat: '2022-01-02',
366
+ time_repeat: '19:00:00',
367
+ },
368
+ };
369
+ await act(() => {
370
+ tree = create(wrapComponent(route));
371
+ });
372
+ const instance = tree.root;
373
+ const itemAutomate = instance.findByType(ItemAutomate);
374
+ expect(itemAutomate.props.textCondition).toEqual('Every day at 19:00');
375
+ });
376
+
377
+ test('Test render textCondition schedule repeat weekday', async () => {
378
+ route.params = {
379
+ ...route.params,
380
+ type: AUTOMATE_TYPE.SCHEDULE,
381
+ automate: {
382
+ repeat: 'every_week',
383
+ date_repeat: '2022-01-02',
384
+ time_repeat: '19:00:00',
385
+ weekday_repeat: ['1', '2', '4', '6'],
386
+ },
387
+ };
388
+ await act(() => {
389
+ tree = create(wrapComponent(route));
390
+ });
391
+ const instance = tree.root;
392
+ const itemAutomate = instance.findByType(ItemAutomate);
393
+ expect(itemAutomate.props.textCondition).toEqual(
394
+ 'Mon, Tue, Thu, Sat at 19:00'
395
+ );
396
+ });
361
397
  });
@@ -43,6 +43,7 @@ import { popAction } from '../../navigations/utils';
43
43
  import { TESTID } from '../../configs/Constants';
44
44
  import useKeyboardAnimated from '../../hooks/Explore/useKeyboardAnimated';
45
45
  import { REPEAT_OPTIONS } from '../SetSchedule/components/RepeatOptionsPopup';
46
+ import { useSCContextSelector } from '../../context';
46
47
 
47
48
  const PreventDoubleTouch = withPreventDoubleClick(TouchableOpacity);
48
49
 
@@ -50,14 +51,8 @@ const ScriptDetail = ({ route }) => {
50
51
  const { navigate, goBack, dispatch } = useNavigation();
51
52
  const { params = {} } = route;
52
53
  const refMenuAction = useRef();
53
- const {
54
- childRef,
55
- showingPopover,
56
- showPopoverWithRef,
57
- hidePopover,
58
- hidingPopoverComplete,
59
- hidePopoverComplete,
60
- } = usePopover();
54
+ const { childRef, showingPopover, showPopoverWithRef, hidePopover } =
55
+ usePopover();
61
56
  const t = useTranslations();
62
57
  const {
63
58
  id,
@@ -84,6 +79,9 @@ const ScriptDetail = ({ route }) => {
84
79
  const [data, setData] = useState([]);
85
80
 
86
81
  const { isStarred, starScript, unstarScript } = useStarredScript(automate);
82
+ const popoverAnimating = useSCContextSelector(
83
+ (state) => state.app.popoverAnimating
84
+ );
87
85
 
88
86
  const [transY] = useKeyboardAnimated(-16);
89
87
  const animatedStyle = Platform.select({
@@ -483,7 +481,6 @@ const ScriptDetail = ({ route }) => {
483
481
  <MenuActionMore
484
482
  isVisible={showingPopover}
485
483
  hideMore={hidePopover}
486
- hideComplete={hidePopoverComplete}
487
484
  listMenuItem={listMenuItem}
488
485
  childRef={childRef}
489
486
  onItemClick={onItemClick}
@@ -491,7 +488,7 @@ const ScriptDetail = ({ route }) => {
491
488
  wrapStyle={styles.wrapStyle}
492
489
  />
493
490
  <AlertAction
494
- visible={stateAlertAction.visible && hidingPopoverComplete}
491
+ visible={stateAlertAction.visible && !popoverAnimating}
495
492
  hideModal={hideAlertAction}
496
493
  title={stateAlertAction.title}
497
494
  message={stateAlertAction.message}
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+ import { act, create } from 'react-test-renderer';
4
+ import Smart from '..';
5
+
6
+ describe('Test Template screen', () => {
7
+ let tree;
8
+ it('Test render', async () => {
9
+ await act(async () => {
10
+ tree = await create(<Smart />);
11
+ });
12
+ const instance = tree.root;
13
+ const Views = instance.findAllByType(View);
14
+ expect(Views).toHaveLength(1);
15
+ });
16
+ });
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+
4
+ const Smart = () => {
5
+ return <View />;
6
+ };
7
+
8
+ export default Smart;
@@ -42,7 +42,6 @@ const AddSubUnit = ({ route }) => {
42
42
  setRoomName('');
43
43
  setWallpaper('');
44
44
  setImageUrl('');
45
- awaitCreate.current = false;
46
45
  };
47
46
 
48
47
  const goDone = useCallback(async () => {
@@ -186,6 +185,7 @@ const AddSubUnit = ({ route }) => {
186
185
  wrapStyle={styles.textInput}
187
186
  selectionColor={Colors.Primary}
188
187
  value={roomName}
188
+ maxLength={50}
189
189
  />
190
190
 
191
191
  {isAddUnit && (
@@ -64,7 +64,10 @@ const EditSubUnit = ({ route }) => {
64
64
  navigation.pop(2);
65
65
  break;
66
66
  default:
67
- navigation.pop(3);
67
+ navigation.navigate(Routes.UnitDetail, {
68
+ isEditSubUnit: true,
69
+ isAddSubUnit: false,
70
+ });
68
71
  }
69
72
  }, [navigation]);
70
73
 
@@ -0,0 +1,51 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { Colors, Constants } from '../../../configs';
3
+
4
+ export default StyleSheet.create({
5
+ wrap: {
6
+ flex: 1,
7
+ backgroundColor: Colors.White,
8
+ padding: 16,
9
+ },
10
+ wrapEmpty: {
11
+ flex: 1,
12
+ justifyContent: 'center',
13
+ alignItems: 'center',
14
+ marginTop: -100,
15
+ },
16
+ textEmpty1: {
17
+ fontSize: 20,
18
+ fontWeight: 'bold',
19
+ },
20
+ textEmpty2: {
21
+ fontSize: 14,
22
+ fontWeight: '400',
23
+ color: Colors.Neutral.Neutral5,
24
+ marginTop: 7,
25
+ },
26
+ contentContainerStyle: {
27
+ flex: 1,
28
+ },
29
+ item: {
30
+ width: (Constants.width - 42) / 2,
31
+ height: 128,
32
+ borderRadius: 8,
33
+ borderWidth: 1,
34
+ borderColor: Colors.Neutral.Neutral3,
35
+ marginBottom: 16,
36
+ justifyContent: 'space-around',
37
+ alignItems: 'center',
38
+ },
39
+ oddItem: {
40
+ marginRight: 10,
41
+ },
42
+ nameItem: {
43
+ fontSize: 14,
44
+ fontWeight: 'bold',
45
+ },
46
+ countItem: {
47
+ fontSize: 12,
48
+ fontWeight: 400,
49
+ color: Colors.Neutral.Neutral5,
50
+ },
51
+ });
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { FlatList } from 'react-native';
3
+ import { act, create } from 'react-test-renderer';
4
+ import Template from '..';
5
+
6
+ describe('Test Template screen', () => {
7
+ let tree;
8
+ it('Test render', async () => {
9
+ await act(async () => {
10
+ tree = await create(<Template />);
11
+ });
12
+ const instance = tree.root;
13
+ const FlatLists = instance.findAllByType(FlatList);
14
+ expect(FlatLists).toHaveLength(1);
15
+ });
16
+ });
@@ -0,0 +1,84 @@
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
+ import {
3
+ View,
4
+ TouchableWithoutFeedback,
5
+ Keyboard,
6
+ FlatList,
7
+ } from 'react-native';
8
+ import { Label } from '../../commons/DevMode';
9
+ import Search from '../../commons/DevMode/Search';
10
+ import Text from '../../commons/Text';
11
+ import t from '../../hooks/Common/useTranslations';
12
+ import { convertToSlug } from '../../utils/Functions/Search';
13
+ import styles from './Styles/indexStyles';
14
+
15
+ const arrTemplates = [
16
+ {
17
+ id: 1,
18
+ name: 'Template name 1',
19
+ count: 2,
20
+ },
21
+ {
22
+ id: 2,
23
+ name: 'Template name 2',
24
+ },
25
+ {
26
+ id: 3,
27
+ name: 'Template name 3',
28
+ },
29
+ ];
30
+
31
+ const Template = () => {
32
+ const [data, setData] = useState(arrTemplates);
33
+
34
+ const onSearch = useCallback((value) => {
35
+ if (value === '') {
36
+ setData(arrTemplates);
37
+ return;
38
+ }
39
+ const dataTemp = arrTemplates.filter((item) =>
40
+ convertToSlug(item?.name).includes(convertToSlug(value))
41
+ );
42
+ setData(dataTemp);
43
+ }, []);
44
+
45
+ const renderListEmptyComponent = useMemo(() => {
46
+ return (
47
+ <View style={styles.wrapEmpty}>
48
+ <Text style={styles.textEmpty1}>{t('no_template_yet')}</Text>
49
+ <Text style={styles.textEmpty2}>{t('add_your_template')}</Text>
50
+ </View>
51
+ );
52
+ }, []);
53
+
54
+ const renderItem = ({ item, index }) => {
55
+ return (
56
+ <View style={[styles.item, index % 2 === 0 && styles.oddItem]}>
57
+ <Text style={styles.nameItem}>{item?.name}</Text>
58
+ <Text style={styles.countItem}>{`${
59
+ item?.count > 0 ? item?.count : t('no')
60
+ } ${t('gateways').toLowerCase()}`}</Text>
61
+ </View>
62
+ );
63
+ };
64
+
65
+ return (
66
+ <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
67
+ <View style={styles.wrap}>
68
+ <Label name={t('template')} />
69
+ <Search onSearch={onSearch} />
70
+ <FlatList
71
+ contentContainerStyle={styles.contentContainerStyle}
72
+ keyExtractor={(item) => item?.id}
73
+ data={data}
74
+ renderItem={renderItem}
75
+ extraData={data}
76
+ ListEmptyComponent={renderListEmptyComponent}
77
+ numColumns={2}
78
+ />
79
+ </View>
80
+ </TouchableWithoutFeedback>
81
+ );
82
+ };
83
+
84
+ export default Template;
@@ -33,7 +33,6 @@ import WrapParallaxScrollView from '../../commons/WrapParallaxScrollView';
33
33
  import { SCContext, useSCContextSelector } from '../../context';
34
34
  import { Action } from '../../context/actionType';
35
35
  import CameraDevice from '../../commons/CameraDevice';
36
- import { ModalFullVideo } from '../../commons/Modal';
37
36
  import { useNavigation } from '@react-navigation/native';
38
37
  import Routes from '../../utils/Route';
39
38
  import SubUnitAutomate from '../../commons/SubUnit/OneTap';
@@ -63,6 +62,7 @@ const UnitDetail = ({ route }) => {
63
62
  routeName,
64
63
  stationId,
65
64
  isAddSubUnit,
65
+ isEditSubUnit,
66
66
  isSuccessfullyConnected,
67
67
  } = route.params;
68
68
 
@@ -92,8 +92,6 @@ const UnitDetail = ({ route }) => {
92
92
  const [showAdd, setShowAdd, setHideAdd] = useBoolean();
93
93
  const [showPreventAccess, setShowPreventAccess, setHidePreventAccess] =
94
94
  useBoolean(false);
95
- const [isFullScreen, setIsFullScreen] = useState(false);
96
- const [dataFullScreen, setDataFullScreen] = useState();
97
95
  const appState = useRef(AppState.currentState);
98
96
 
99
97
  const { childRef, showingPopover, showPopoverWithRef, hidePopover } =
@@ -105,15 +103,6 @@ const UnitDetail = ({ route }) => {
105
103
  listAutomate
106
104
  );
107
105
 
108
- const handleFullScreen = (data) => {
109
- setIsFullScreen(!isFullScreen);
110
- setDataFullScreen(data);
111
- };
112
-
113
- const onClose = useCallback(() => {
114
- setIsFullScreen(false);
115
- }, []);
116
-
117
106
  const prepareData = useCallback(
118
107
  (rawUnitData) => {
119
108
  rawUnitData.stations.unshift({
@@ -217,8 +206,9 @@ const UnitDetail = ({ route }) => {
217
206
  }, [unit, indexStation]);
218
207
 
219
208
  useEffect(() => {
209
+ isEditSubUnit && setIndexStation(0);
220
210
  isOneTap && setIndexStation(1);
221
- }, [isOneTap]);
211
+ }, [isEditSubUnit, isOneTap]);
222
212
 
223
213
  useEffect(() => {
224
214
  if (listMenuItem.length && isAddSubUnit) {
@@ -227,7 +217,7 @@ const UnitDetail = ({ route }) => {
227
217
  }, [listMenuItem.length, isAddSubUnit]);
228
218
 
229
219
  useEffect(() => {
230
- if (listMenuItem.length && stationId) {
220
+ if (!isEditSubUnit && listMenuItem.length && stationId) {
231
221
  const getStationCurrent = listMenuItem.filter(
232
222
  (item) => item?.station.id === stationId
233
223
  );
@@ -262,13 +252,7 @@ const UnitDetail = ({ route }) => {
262
252
  );
263
253
  }
264
254
  if (station?.camera_devices) {
265
- return (
266
- <CameraDevice
267
- station={station}
268
- handleFullScreen={handleFullScreen}
269
- goToPlayBack={goToPlayBack}
270
- />
271
- );
255
+ return <CameraDevice station={station} goToPlayBack={goToPlayBack} />;
272
256
  } else if (station?.isOneTap) {
273
257
  return (
274
258
  <SubUnitAutomate
@@ -333,6 +317,8 @@ const UnitDetail = ({ route }) => {
333
317
  onMore={showPopoverWithRef}
334
318
  hideRightPlus={!isOwner}
335
319
  onBack={(isSuccessfullyConnected && Dashboard) || (routeName && onBack)}
320
+ accessibilityLabel={TESTID.UNIT_DETAIL_PARALLAX_SCROLLVIEW}
321
+ idButtonMore={TESTID.UNIT_DETAIL_PARALLAX_BUTTON_MORE}
336
322
  >
337
323
  {renderCamera}
338
324
 
@@ -344,6 +330,7 @@ const UnitDetail = ({ route }) => {
344
330
  listMenuItem={listMenuItem}
345
331
  onSnapToItem={onSnapToItem}
346
332
  indexStation={indexStation}
333
+ idLabelScrollView={TESTID.NAV_LIST}
347
334
  />
348
335
  {renderDetailSubUnit()}
349
336
  {!!unit.can_add && unit.stations.length === 0 && (
@@ -364,12 +351,8 @@ const UnitDetail = ({ route }) => {
364
351
  isOwner={isOwner}
365
352
  childRef={childRef}
366
353
  showingPopover={showingPopover}
367
- />
368
- <ModalFullVideo
369
- isVisible={isFullScreen}
370
- data={dataFullScreen}
371
- modalStyles={styles.modal}
372
- onClose={onClose}
354
+ idLabelPopover={TESTID.UNIT_DETAIL_POPUP_MORE}
355
+ idLabelItem={TESTID.UNIT_DETAIL_POPUP_MORE_ITEM}
373
356
  />
374
357
  <PreventAccess
375
358
  visible={showPreventAccess}
@@ -5,7 +5,16 @@ import { useNavigation } from '@react-navigation/native';
5
5
  import { MenuActionMore } from '../../commons';
6
6
 
7
7
  const MoreMenu = memo(
8
- ({ unit, isOwner, hidePopover, childRef, showingPopover }) => {
8
+ ({
9
+ unit,
10
+ isOwner,
11
+ hidePopover,
12
+ childRef,
13
+ showingPopover,
14
+ idLabelPopover,
15
+ idLabelScrollView,
16
+ idLabelItem,
17
+ }) => {
9
18
  const t = useTranslations();
10
19
  const navigation = useNavigation();
11
20
 
@@ -19,16 +28,19 @@ const MoreMenu = memo(
19
28
 
20
29
  const listMenuItem = useMemo(() => {
21
30
  const RouteManageUnit = {
31
+ id: 1,
22
32
  route: Routes.ManageUnit,
23
33
  text: t('manage_unit'),
24
34
  data: { unitId: unit.id, unit },
25
35
  };
26
36
  const RouteUnitMemberList = {
37
+ id: 2,
27
38
  route: Routes.UnitMemberList,
28
39
  text: t('members'),
29
40
  data: { unitId: unit.id, unit },
30
41
  };
31
42
  const ListSmartAccount = {
43
+ id: 3,
32
44
  route: Routes.ListSmartAccount,
33
45
  text: t('smart_account'),
34
46
  data: { unitId: unit.id, unit },
@@ -45,6 +57,9 @@ const MoreMenu = memo(
45
57
  listMenuItem={listMenuItem}
46
58
  childRef={childRef}
47
59
  onItemClick={onItemClick}
60
+ idLabelPopover={idLabelPopover}
61
+ idLabelScrollView={idLabelScrollView}
62
+ idLabelItem={idLabelItem}
48
63
  />
49
64
  );
50
65
  }
@@ -14,11 +14,12 @@ import Routes from '../../utils/Route';
14
14
  import { useNavigation } from '@react-navigation/native';
15
15
  import { axiosDelete, axiosGet } from '../../utils/Apis/axios';
16
16
  import { SmartAccountItem } from './SmartAccountItem';
17
- import { usePopover, useBoolean } from '../../hooks/Common';
17
+ import { usePopover } from '../../hooks/Common';
18
18
  import { MenuActionMore, AlertAction, FullLoading } from '../../commons';
19
19
  import { useTranslations } from '../../hooks/Common/useTranslations';
20
20
  import { useStateAlertRemove } from '../Unit/hook/useStateAlertRemove';
21
21
  import { ToastBottomHelper } from '../../utils/Utils';
22
+ import { useSCContextSelector } from '../../context';
22
23
 
23
24
  const ListSmartAccount = ({ route }) => {
24
25
  const { unitId } = route?.params || {};
@@ -27,6 +28,9 @@ const ListSmartAccount = ({ route }) => {
27
28
  const smartAccountRef = useRef(null);
28
29
  const { navigate } = useNavigation();
29
30
  const [loadingRemoveItem, setLoadingRemoveItem] = useState(false);
31
+ const popoverAnimating = useSCContextSelector(
32
+ (state) => state.app.popoverAnimating
33
+ );
30
34
 
31
35
  const getAllSmartAccounts = useCallback(async () => {
32
36
  const { success, data: accountData } = await axiosGet(
@@ -39,7 +43,6 @@ const ListSmartAccount = ({ route }) => {
39
43
 
40
44
  const { childRef, showingPopover, showPopoverWithRef, hidePopover } =
41
45
  usePopover();
42
- const [lockShowing, acquireLockShowing, releaseLockShowing] = useBoolean();
43
46
  const { stateAlertRemove, onShowRemoveAlert, hideAlertAction } =
44
47
  useStateAlertRemove();
45
48
 
@@ -62,11 +65,10 @@ const ListSmartAccount = ({ route }) => {
62
65
  return;
63
66
  }
64
67
  if (item.action === 'remove') {
65
- acquireLockShowing();
66
68
  onShowRemoveAlert(smartAccountRef.current.brand)();
67
69
  }
68
70
  },
69
- [acquireLockShowing, onShowRemoveAlert]
71
+ [onShowRemoveAlert]
70
72
  );
71
73
 
72
74
  const deleteSmartAccount = useCallback(async () => {
@@ -124,7 +126,7 @@ const ListSmartAccount = ({ route }) => {
124
126
  })}
125
127
  </View>
126
128
  <AlertAction
127
- visible={stateAlertRemove.visible && !lockShowing}
129
+ visible={stateAlertRemove.visible && !popoverAnimating}
128
130
  hideModal={hideAlertAction}
129
131
  title={stateAlertRemove.title}
130
132
  message={stateAlertRemove.message}
@@ -142,7 +144,6 @@ const ListSmartAccount = ({ route }) => {
142
144
  listMenuItem={listMenuItem}
143
145
  childRef={childRef}
144
146
  onItemClick={onItemClick}
145
- hideComplete={releaseLockShowing}
146
147
  />
147
148
  </WrapHeaderScrollable>
148
149
  {loadingRemoveItem && <FullLoading />}
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import { FlatList } from 'react-native';
3
+ import { act, create } from 'react-test-renderer';
4
+ import Station from '..';
5
+ import { SCProvider } from '../../../../context';
6
+ import { mockSCStore } from '../../../../context/mockStore';
7
+
8
+ const mockOnSnapToItem = jest.fn();
9
+
10
+ const wrapComponent = (route) => (
11
+ <SCProvider initState={mockSCStore({})}>
12
+ <Station
13
+ listStation={[{ id: 1, station: { id: 1 }, text: 'station1' }]}
14
+ onSnapToItem={mockOnSnapToItem}
15
+ indexStation={1}
16
+ />
17
+ </SCProvider>
18
+ );
19
+
20
+ describe('Test Station', async () => {
21
+ let tree;
22
+ let route = {
23
+ unitId: 1,
24
+ unitData: {
25
+ id: 1,
26
+ },
27
+ isOneTap: false,
28
+ routeName: 'Test',
29
+ stationId: 1,
30
+ isAddSubUnit: false,
31
+ isSuccessfullyConnected: false,
32
+ };
33
+ it('Test render', async () => {
34
+ await act(async () => {
35
+ tree = create(wrapComponent(route));
36
+ });
37
+ const instance = tree.root;
38
+ const FlatLists = instance.findAllByType(FlatList);
39
+ expect(FlatLists).toHaveLength(1);
40
+ });
41
+ });
@@ -73,7 +73,6 @@ const Station = ({ listStation = [], onSnapToItem, indexStation }) => {
73
73
  renderItem={renderItem}
74
74
  showsHorizontalScrollIndicator={false}
75
75
  scrollIndicatorInsets={{ right: 1 }}
76
- testID={TESTID.NAV_LIST}
77
76
  />
78
77
  </View>
79
78
  );
@@ -6,6 +6,8 @@ import { useIsFocused, useNavigation } from '@react-navigation/native';
6
6
  import { axiosGet } from '../../utils/Apis/axios';
7
7
  import { API } from '../../configs';
8
8
  import { useReceiveNotifications } from '../../hooks';
9
+ import { TESTID } from '../../configs/Constants';
10
+ import { useSCContextSelector } from '../../context';
9
11
 
10
12
  const Summaries = memo(({ unit }) => {
11
13
  const [unitSummaries, setUnitSummaries] = useState([]);
@@ -14,6 +16,9 @@ const Summaries = memo(({ unit }) => {
14
16
  const isFocused = useIsFocused();
15
17
  const navigation = useNavigation();
16
18
  const appState = useRef(AppState.currentState);
19
+ const popoverAnimating = useSCContextSelector(
20
+ (state) => state.app.popoverAnimating
21
+ );
17
22
 
18
23
  const fetchUnitSummary = useCallback(async () => {
19
24
  if (!unit.id) {
@@ -33,6 +38,9 @@ const Summaries = memo(({ unit }) => {
33
38
 
34
39
  const goToSummary = useCallback(
35
40
  (summary) => {
41
+ if (popoverAnimating) {
42
+ return;
43
+ }
36
44
  navigation.navigate(Routes.UnitSummary, {
37
45
  summaryId: summary.id,
38
46
  unitId: unit.id,
@@ -40,7 +48,7 @@ const Summaries = memo(({ unit }) => {
40
48
  unitData: unit,
41
49
  });
42
50
  },
43
- [navigation, unit]
51
+ [navigation, popoverAnimating, unit]
44
52
  );
45
53
 
46
54
  const continuousFetchSummary = useCallback(async () => {
@@ -101,7 +109,11 @@ const Summaries = memo(({ unit }) => {
101
109
  return (
102
110
  <>
103
111
  {!unitSummaries || !unitSummaries.length ? null : (
104
- <ScrollView horizontal={true} scrollIndicatorInsets={{ right: 1 }}>
112
+ <ScrollView
113
+ horizontal={true}
114
+ scrollIndicatorInsets={{ right: 1 }}
115
+ accessibilityLabel={TESTID.UNIT_DETAIL_UNIT_SUMMARY_VIEW}
116
+ >
105
117
  {unitSummaries.map((item, index) => (
106
118
  <SummaryItem key={index} item={item} goToSummary={goToSummary} />
107
119
  ))}
@@ -12,7 +12,6 @@ import { TESTID } from '../../../configs/Constants';
12
12
  import { SCProvider } from '../../../context';
13
13
  import { mockSCStore } from '../../../context/mockStore';
14
14
  import CameraDevice from '../../../commons/CameraDevice';
15
- import { ModalFullVideo } from '../../../commons/Modal';
16
15
  import SubUnitFavorites from '../../../commons/SubUnit/Favorites';
17
16
  import api from '../../../utils/Apis/axios';
18
17
  import PreventAccess from '../../../commons/PreventAccess';
@@ -352,11 +351,7 @@ describe('Test UnitDetail', () => {
352
351
  el.props.testID === TESTID.SUB_UNIT_FULL_CAMERA &&
353
352
  el.type === TouchableOpacity
354
353
  );
355
-
356
354
  expect(fullCamera).toHaveLength(0);
357
- const fullView = instance.findAllByType(ModalFullVideo);
358
- expect(fullView).toHaveLength(1);
359
- expect(fullView[0].props.isVisible).toEqual(false);
360
355
  });
361
356
 
362
357
  test('onPress subunit camera devices', async () => {
@@ -438,6 +433,7 @@ describe('Test UnitDetail', () => {
438
433
  };
439
434
  route.params.isAddSubUnit = true;
440
435
  route.params.unitData = unitData;
436
+ route.params.isSuccessfullyConnected = false;
441
437
  await act(async () => {
442
438
  tree = await renderer.create(wrapComponent(route, account));
443
439
  });
@@ -1,6 +1,6 @@
1
1
  import React, { useRef, useState } from 'react';
2
2
  import { Dimensions, View, TouchableOpacity, StyleSheet } from 'react-native';
3
- import Popover from 'react-native-popover-view';
3
+ import Popover from '../../../../commons/Popover';
4
4
  import { IconOutline } from '@ant-design/icons-react-native';
5
5
  import { useTranslations } from '../../../../hooks/Common/useTranslations';
6
6