@eohjsc/react-native-smart-city 0.3.0 → 0.3.1

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 (128) hide show
  1. package/README.md +1 -1
  2. package/package.json +3 -3
  3. package/src/commons/Action/ItemQuickAction.js +11 -2
  4. package/src/commons/Action/__test__/ItemQuickAction.test.js +11 -6
  5. package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +31 -20
  6. package/src/commons/ActionGroup/SmartTiviActionTemplate/SmartTiviActionTemplate.js +3 -2
  7. package/src/commons/ActionGroup/TwoButtonTemplate/index.js +0 -1
  8. package/src/commons/ActionGroup/__test__/NumberUpDownTemplate.test.js +45 -48
  9. package/src/commons/ActionGroup/__test__/index.test.js +2 -2
  10. package/src/commons/ConnectingProcess/index.js +11 -7
  11. package/src/commons/Device/ConnectedViewHeader.js +1 -1
  12. package/src/commons/Device/HistoryChart.js +3 -3
  13. package/src/commons/Device/ItemDevice.js +15 -11
  14. package/src/commons/Device/SonosSpeaker/index.js +1 -1
  15. package/src/commons/FieldTemplate/ScheduleField/index.js +2 -2
  16. package/src/commons/Header/HeaderCustom.js +2 -1
  17. package/src/commons/HorizontalPicker/index.js +2 -2
  18. package/src/commons/MediaPlayerDetail/Styles/MediaPlayerDetailStyles.js +0 -6
  19. package/src/commons/MediaPlayerDetail/index.js +19 -50
  20. package/src/commons/SubUnit/Favorites/index.js +2 -3
  21. package/src/commons/SubUnit/ShortDetail.js +1 -2
  22. package/src/commons/SubUnit/__test__/Item.test.js +0 -1
  23. package/src/commons/UnitSummary/ConfigHistoryChart/index.js +2 -13
  24. package/src/commons/UnitSummary/ConfigHistoryChart.js +22 -13
  25. package/src/commons/WheelDateTimePicker/index.js +2 -2
  26. package/src/configs/API.js +4 -13
  27. package/src/configs/Constants.js +13 -0
  28. package/src/context/actionType.ts +8 -0
  29. package/src/context/mockStore.ts +10 -0
  30. package/src/context/reducer.ts +38 -2
  31. package/src/hooks/Common/index.js +2 -0
  32. package/src/hooks/Common/useGGHomeDeviceConnected.js +16 -0
  33. package/src/hooks/Common/useGetIdUser.js +1 -5
  34. package/src/hooks/Common/useSensorsStatus.js +5 -8
  35. package/src/hooks/IoT/__test__/useGGHomeConnection.test.js +198 -0
  36. package/src/hooks/IoT/__test__/useRemoteControl.test.js +198 -0
  37. package/src/hooks/IoT/index.js +4 -0
  38. package/src/hooks/IoT/useGGHomeConnection.js +91 -0
  39. package/src/hooks/IoT/useRemoteControl.js +79 -0
  40. package/src/hooks/index.js +4 -0
  41. package/src/hooks/useReceiveNotifications.js +8 -4
  42. package/src/iot/Monitor.js +3 -2
  43. package/src/iot/RemoteControl/Bluetooth.js +1 -1
  44. package/src/iot/RemoteControl/GoogleHome.js +75 -49
  45. package/src/iot/RemoteControl/Internet.js +1 -1
  46. package/src/iot/RemoteControl/__test__/GoogleHome.test.js +90 -21
  47. package/src/iot/RemoteControl/__test__/Internet.test.js +4 -4
  48. package/src/iot/RemoteControl/__test__/LgThinq.test.js +5 -5
  49. package/src/iot/RemoteControl/index.js +52 -52
  50. package/src/screens/ActivityLog/hooks/__test__/index.test.js +3 -3
  51. package/src/screens/ActivityLog/hooks/index.js +1 -1
  52. package/src/screens/AddLocationMaps/index.js +5 -4
  53. package/src/screens/AddNewAction/SelectAction.js +8 -8
  54. package/src/screens/AddNewAction/SetupSensor.js +7 -7
  55. package/src/screens/AddNewAction/__test__/SelectAction.test.js +2 -2
  56. package/src/screens/AddNewDevice/ConnectingDevices.js +1 -1
  57. package/src/screens/AddNewDevice/__test__/ConnectingDevices.test.js +2 -2
  58. package/src/screens/AddNewDevice/hooks/ConnectDevices.js +1 -1
  59. package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +23 -17
  60. package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +3 -3
  61. package/src/screens/AddNewGateway/SetupGatewayWifi.js +1 -0
  62. package/src/screens/AllCamera/index.js +4 -4
  63. package/src/screens/Automate/MultiUnits.js +8 -8
  64. package/src/screens/Automate/index.js +3 -3
  65. package/src/screens/Device/EditDevice/__test__/EditDevice.test.js +4 -4
  66. package/src/screens/Device/EditDevice/index.js +2 -2
  67. package/src/screens/Device/__test__/detail.test.js +13 -5
  68. package/src/screens/Device/components/DetailHistoryChart.js +1 -1
  69. package/src/screens/Device/components/SensorConnectStatusViewHeader.js +1 -0
  70. package/src/screens/Device/components/SensorDisplayItem.js +5 -2
  71. package/src/screens/Device/detail.js +49 -16
  72. package/src/screens/Device/hooks/useDisconnectedDevice.js +4 -4
  73. package/src/screens/EditActionsList/index.js +1 -1
  74. package/src/screens/EmergencySetting/components/DropDownItem.js +2 -2
  75. package/src/screens/HanetCamera/Detail.js +1 -1
  76. package/src/screens/HanetCamera/__test__/Detail.test.js +2 -2
  77. package/src/screens/HanetCamera/components/RequestFaceIDPopup.js +3 -2
  78. package/src/screens/HanetCamera/hooks/useHanetCheckinData.js +11 -11
  79. package/src/screens/HanetCamera/hooks/useHanetPlaceMembers.js +11 -11
  80. package/src/screens/ManageAccess/hooks/index.js +7 -4
  81. package/src/screens/MoveToAnotherSubUnit/__test__/index.test.js +2 -2
  82. package/src/screens/MoveToAnotherSubUnit/index.js +1 -1
  83. package/src/screens/Notification/__test__/NotificationItem.test.js +4 -4
  84. package/src/screens/Notification/components/NotificationItem.js +17 -20
  85. package/src/screens/Notification/index.js +9 -2
  86. package/src/screens/PlayBackCamera/Timer.js +2 -2
  87. package/src/screens/PlayBackCamera/index.js +3 -3
  88. package/src/screens/ScanChipQR/hooks/index.js +15 -16
  89. package/src/screens/ScriptDetail/index.js +14 -10
  90. package/src/screens/SelectUnit/index.js +4 -2
  91. package/src/screens/SetSchedule/index.js +9 -9
  92. package/src/screens/Sharing/Components/SensorItem.js +10 -12
  93. package/src/screens/Sharing/SelectPermission.js +14 -6
  94. package/src/screens/SideMenuDetail/__test__/index.test.js +4 -4
  95. package/src/screens/SideMenuDetail/index.js +2 -3
  96. package/src/screens/SmartIr/components/GroupButtonByType/GroupButtonByType.js +3 -2
  97. package/src/screens/SubUnit/Detail.js +1 -2
  98. package/src/screens/SubUnit/ManageSubUnit.js +12 -7
  99. package/src/screens/SubUnit/__test__/Detail.test.js +1 -1
  100. package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +27 -1
  101. package/src/screens/SubUnit/hooks/__test__/useManageSubUnit.test.js +1 -1
  102. package/src/screens/SubUnit/hooks/useManageSubUnit.js +7 -7
  103. package/src/screens/Unit/ChooseLocation.js +6 -13
  104. package/src/screens/Unit/Detail.js +30 -75
  105. package/src/screens/Unit/SelectAddress.js +34 -21
  106. package/src/screens/Unit/SmartAccount.js +4 -4
  107. package/src/screens/Unit/Summaries.js +17 -1
  108. package/src/screens/Unit/__test__/CheckSendEmail.test.js +9 -1
  109. package/src/screens/Unit/__test__/Detail.test.js +16 -15
  110. package/src/screens/Unit/__test__/SelectAddress.test.js +72 -13
  111. package/src/screens/Unit/__test__/SmartAccount.test.js +1 -1
  112. package/src/screens/Unit/__test__/Summaries.test.js +100 -0
  113. package/src/screens/Unit/hook/useUnitConnectRemoteDevices.js +50 -0
  114. package/src/screens/Unit/styles.js +4 -0
  115. package/src/screens/UnitSummary/__test__/index.test.js +55 -1
  116. package/src/screens/UnitSummary/components/3PPowerConsumption/__test__/3PPowerConsumption.test.js +31 -2
  117. package/src/screens/UnitSummary/components/PowerConsumeHistoryChart/index.js +2 -13
  118. package/src/screens/UnitSummary/components/PowerConsumption/__test__/ItemPower.test.js +0 -1
  119. package/src/screens/UnitSummary/components/RunningDevices/__test__/index.test.js +11 -2
  120. package/src/screens/UnitSummary/components/RunningDevices/index.js +7 -10
  121. package/src/screens/UnitSummary/components/Temperature/index.js +4 -4
  122. package/src/screens/UnitSummary/index.js +15 -1
  123. package/src/utils/Apis/axios.js +16 -25
  124. package/src/utils/Converter/time.js +0 -18
  125. package/src/utils/I18n/translations/en.json +2 -1
  126. package/src/utils/I18n/translations/vi.json +3 -1
  127. package/src/utils/Permission/common.js +39 -0
  128. package/src/utils/Utils.js +5 -1
@@ -1,14 +1,15 @@
1
1
  import React, {
2
2
  useCallback,
3
- useContext,
4
3
  useEffect,
5
4
  useState,
6
5
  useRef,
6
+ useContext,
7
7
  } from 'react';
8
8
  import { AppState, RefreshControl, View } from 'react-native';
9
9
  import { useIsFocused } from '@react-navigation/native';
10
- import { useTranslations } from '../../hooks/Common/useTranslations';
10
+ import { VLCPlayer } from 'react-native-vlc-media-player';
11
11
 
12
+ import { useTranslations } from '../../hooks/Common/useTranslations';
12
13
  import styles from './styles';
13
14
  import AddMenu from './AddMenu';
14
15
  import MoreMenu from './MoreMenu';
@@ -23,10 +24,8 @@ import {
23
24
  usePopover,
24
25
  } from '../../hooks/Common';
25
26
  import { useFavorites } from './hook/useFavorites';
26
- import { scanBluetoothDevices } from '../../iot/RemoteControl/Bluetooth';
27
- import { googleHomeConnect } from '../../iot/RemoteControl/GoogleHome';
28
- import { axiosPost, fetchWithCache, axiosGet } from '../../utils/Apis/axios';
29
- import { lgThinqConnect } from '../../iot/RemoteControl/LG';
27
+ import { useUnitConnectRemoteDevices } from './hook/useUnitConnectRemoteDevices';
28
+ import { fetchWithCache, axiosGet } from '../../utils/Apis/axios';
30
29
  import ShortDetailSubUnit from '../../commons/SubUnit/ShortDetail';
31
30
  import NavBar from '../../commons/NavBar';
32
31
  import WrapParallaxScrollView from '../../commons/WrapParallaxScrollView';
@@ -51,6 +50,7 @@ import PreventAccess from '../../commons/PreventAccess';
51
50
 
52
51
  const UnitDetail = ({ route }) => {
53
52
  const t = useTranslations();
53
+ const { setAction } = useContext(SCContext);
54
54
 
55
55
  const {
56
56
  unitId,
@@ -63,7 +63,6 @@ const UnitDetail = ({ route }) => {
63
63
  } = route.params;
64
64
 
65
65
  const isFocused = useIsFocused();
66
- const { stateData, setAction } = useContext(SCContext);
67
66
  const { navigate, goBack } = useNavigation();
68
67
  const RouterHardware = useCallback(
69
68
  (routeHardware) => () => {
@@ -76,15 +75,14 @@ const UnitDetail = ({ route }) => {
76
75
  isSuccessfullyConnected ? RouterHardware(Routes.Dashboard) : goBack
77
76
  );
78
77
  const user = useSCContextSelector((state) => state?.auth?.account?.user);
79
- const isLavidaSource = useSCContextSelector(
80
- (state) => state.app.isLavidaSource
78
+ const { isLavidaSource, isFirstOpenCamera } = useSCContextSelector(
79
+ (state) => state.app
81
80
  );
82
81
 
83
82
  const [unit, setUnit] = useState(unitData || { id: unitId });
84
83
  const [listMenuItem, setListMenuItem] = useState([]);
85
84
  const [listStation, setListStation] = useState([]);
86
85
  const [listAutomate, setListAutomate] = useState([]);
87
- const [isGGHomeConnected, setIsGGHomeConnected] = useState(false);
88
86
  const [station, setStation] = useState({});
89
87
  const [indexStation, setIndexStation] = useState(0);
90
88
  const [showAdd, setShowAdd, setHideAdd] = useBoolean();
@@ -191,61 +189,7 @@ const UnitDetail = ({ route }) => {
191
189
  };
192
190
  }, [fetchDetails]);
193
191
 
194
- const handleGoogleHomeConnect = useCallback(
195
- async (options) => {
196
- let isConnected = await googleHomeConnect(options); // this may wrong if have multiple connection
197
- setIsGGHomeConnected(isConnected);
198
- let chipId = options[0].chip_id;
199
- if (!isConnected) {
200
- setAction(Action.LIST_DEVICE_TYPES, {
201
- chipId: chipId,
202
- sentEmail: true,
203
- });
204
- await axiosPost(API.GOOGLE_HOME.CHECK_SEND_EMAIL(), {
205
- chip_id: chipId,
206
- is_connected: false,
207
- });
208
- } else if (isConnected && stateData?.listDevice[chipId]?.sentEmail) {
209
- setAction(Action.LIST_DEVICE_TYPES, {
210
- chipId: chipId,
211
- sentEmail: false,
212
- });
213
- await axiosPost(API.GOOGLE_HOME.CHECK_SEND_EMAIL(), {
214
- chip_id: chipId,
215
- is_connected: true,
216
- });
217
- }
218
- },
219
- // eslint-disable-next-line react-hooks/exhaustive-deps
220
- []
221
- );
222
-
223
- let isCalled = false;
224
-
225
- const handleLgThinqConnect = useCallback(async (options) => {
226
- if (isCalled) {
227
- return;
228
- }
229
- // eslint-disable-next-line react-hooks/exhaustive-deps
230
- isCalled = true;
231
- await lgThinqConnect(options);
232
- }, []);
233
-
234
- useEffect(() => {
235
- if (unit.remote_control_options) {
236
- if (unit.remote_control_options.bluetooth) {
237
- scanBluetoothDevices(unit.remote_control_options.bluetooth);
238
- }
239
- if (unit.remote_control_options.googlehome?.length) {
240
- handleGoogleHomeConnect(unit.remote_control_options.googlehome);
241
- }
242
- if (unit.remote_control_options.lg_thinq) {
243
- (async () => {
244
- await handleLgThinqConnect(unit.remote_control_options.lg_thinq);
245
- })();
246
- }
247
- }
248
- }, [handleGoogleHomeConnect, handleLgThinqConnect, unit]);
192
+ useUnitConnectRemoteDevices(unit);
249
193
 
250
194
  useEffect(() => {
251
195
  if (isFocused) {
@@ -264,7 +208,7 @@ const UnitDetail = ({ route }) => {
264
208
  setListMenuItem(listMenu);
265
209
  setListStation(listMenu.concat([{ text: '' }]));
266
210
  }
267
- }, [unit, indexStation, isGGHomeConnected]);
211
+ }, [unit, indexStation]);
268
212
 
269
213
  useEffect(() => {
270
214
  isOneTap && setIndexStation(1);
@@ -308,7 +252,6 @@ const UnitDetail = ({ route }) => {
308
252
  favoriteDevices={favoriteDevices}
309
253
  favoriteAutomates={favoriteAutomates}
310
254
  wrapItemStyle={styles.wrapItemStyle}
311
- isGGHomeConnected={isGGHomeConnected}
312
255
  />
313
256
  );
314
257
  }
@@ -330,13 +273,7 @@ const UnitDetail = ({ route }) => {
330
273
  />
331
274
  );
332
275
  } else if (station) {
333
- return (
334
- <ShortDetailSubUnit
335
- unit={unit}
336
- station={station}
337
- isGGHomeConnected={isGGHomeConnected}
338
- />
339
- );
276
+ return <ShortDetailSubUnit unit={unit} station={station} />;
340
277
  }
341
278
  };
342
279
 
@@ -353,6 +290,15 @@ const UnitDetail = ({ route }) => {
353
290
  return () => unwatchNotificationData(user);
354
291
  }, [user, onRefresh]);
355
292
 
293
+ useEffect(() => {
294
+ if (isFirstOpenCamera) {
295
+ const to = setTimeout(() => {
296
+ setAction(Action.IS_FIRST_OPEN_CAMERA, false);
297
+ clearTimeout(to);
298
+ }, 5000);
299
+ }
300
+ }, [isFirstOpenCamera, setAction]);
301
+
356
302
  return (
357
303
  <WrapParallaxScrollView
358
304
  uriImg={unit.background}
@@ -367,6 +313,16 @@ const UnitDetail = ({ route }) => {
367
313
  hideRightPlus={!isOwner}
368
314
  onBack={(isSuccessfullyConnected && Dashboard) || (routeName && onBack)}
369
315
  >
316
+ {/* NOTE: This is a trick to fix camera not full screen on first open app */}
317
+ {isFirstOpenCamera && (
318
+ <VLCPlayer
319
+ source={{
320
+ uri: 'rtsp://admin:Eoh@2020@101.99.33.220:30554/main',
321
+ }}
322
+ style={styles.camera}
323
+ />
324
+ )}
325
+
370
326
  <View style={styles.container}>
371
327
  <Summaries unit={unit} />
372
328
  <NavBar
@@ -383,7 +339,6 @@ const UnitDetail = ({ route }) => {
383
339
  </View>
384
340
  )}
385
341
  </View>
386
-
387
342
  <AddMenu
388
343
  unit={unit}
389
344
  afterItemClick={hidePopover}
@@ -1,9 +1,9 @@
1
- /* eslint-disable react-hooks/exhaustive-deps */
2
1
  import React, { memo, useCallback, useEffect, useRef, useState } from 'react';
3
2
  import { TouchableOpacity, View, ScrollView } from 'react-native';
4
3
  import MapView, { Marker, Circle, PROVIDER_GOOGLE } from 'react-native-maps';
5
4
  import { useNavigation } from '@react-navigation/native';
6
5
  import { IconOutline, IconFill } from '@ant-design/icons-react-native';
6
+ import { check, RESULTS } from 'react-native-permissions';
7
7
 
8
8
  import BottomButtonView from '../../commons/BottomButtonView';
9
9
  import SearchBarLocation from '../../commons/SearchLocation';
@@ -11,22 +11,23 @@ import RowLocation from '../../commons/SearchLocation/RowLocation';
11
11
  import Text from '../../commons/Text';
12
12
  import { FullLoading } from '../../commons';
13
13
  import { useTranslations } from '../../hooks/Common/useTranslations';
14
-
15
- navigator.geolocation = require('@react-native-community/geolocation');
14
+ import {
15
+ GEOLOCATION_ERROR,
16
+ keyPermission,
17
+ OpenSetting,
18
+ } from '../../utils/Permission/common';
16
19
 
17
20
  import styles from './SelectAddressStyles';
18
21
  import { API, Colors, SCConfig } from '../../configs';
19
22
  import { axiosGet } from '../../utils/Apis/axios';
20
23
  import Routes from '../../utils/Route';
21
- import { TESTID } from '../../configs/Constants';
24
+ import {
25
+ TESTID,
26
+ MAP_INITIAL_REGION,
27
+ EOH_LOCATION,
28
+ } from '../../configs/Constants';
22
29
 
23
- const initialRegion = {
24
- latitudeDelta: 0.0922,
25
- longitudeDelta: 0.0421,
26
- };
27
-
28
- const DEFAULT_LATITUDE = 10.7974046; // EoH center
29
- const DEFAULT_LONGITUDE = 106.7035663;
30
+ navigator.geolocation = require('@react-native-community/geolocation');
30
31
 
31
32
  const SelectAddress = memo(({ route }) => {
32
33
  const t = useTranslations();
@@ -46,9 +47,9 @@ const SelectAddress = memo(({ route }) => {
46
47
  goBack();
47
48
  }, [goBack, updateLocation, searchedLocation]);
48
49
 
49
- const onTextInput = useCallback(async (input) => {
50
- setInput(input);
51
- if (input === '') {
50
+ const onTextInput = useCallback(async (value) => {
51
+ setInput(value);
52
+ if (value === '') {
52
53
  setSearchData([]);
53
54
  setSearchedLocation(null);
54
55
  return;
@@ -56,7 +57,7 @@ const SelectAddress = memo(({ route }) => {
56
57
  try {
57
58
  const config = {
58
59
  params: {
59
- input: input,
60
+ input: value,
60
61
  key: SCConfig.GOOGLE_MAP_API_KEY,
61
62
  sessiontoken: 123456324,
62
63
  strictBounds: false,
@@ -71,6 +72,7 @@ const SelectAddress = memo(({ route }) => {
71
72
  if (success) {
72
73
  setSearchData(data.predictions);
73
74
  }
75
+ // eslint-disable-next-line no-empty
74
76
  } catch (error) {}
75
77
  }, []);
76
78
 
@@ -83,7 +85,8 @@ const SelectAddress = memo(({ route }) => {
83
85
  {
84
86
  latitude: lat,
85
87
  longitude: lng,
86
- ...initialRegion,
88
+ latitudeDelta: MAP_INITIAL_REGION.LAT,
89
+ longitudeDelta: MAP_INITIAL_REGION.LNG,
87
90
  },
88
91
  600
89
92
  );
@@ -140,10 +143,19 @@ const SelectAddress = memo(({ route }) => {
140
143
  setLoading(false);
141
144
  },
142
145
  // eslint-disable-next-line promise/prefer-await-to-callbacks
143
- (error) => {}
146
+ async (error) => {
147
+ if (error.code === GEOLOCATION_ERROR.PERMISSION_DENIED) {
148
+ const permissionResult = await check(keyPermission.LOCATION);
149
+ permissionResult === RESULTS.BLOCKED &&
150
+ OpenSetting(
151
+ t('location_rationale_title'),
152
+ t('location_require_message')
153
+ );
154
+ }
155
+ }
144
156
  // { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 } enable on emulator
145
157
  );
146
- }, []);
158
+ }, [t]);
147
159
 
148
160
  const chooseOnMap = useCallback(() => {
149
161
  navigate(Routes.ChooseLocation, {
@@ -202,9 +214,10 @@ const SelectAddress = memo(({ route }) => {
202
214
  provider={PROVIDER_GOOGLE}
203
215
  style={styles.mapView}
204
216
  initialRegion={{
205
- ...initialRegion,
206
- latitude: DEFAULT_LATITUDE,
207
- longitude: DEFAULT_LONGITUDE,
217
+ latitude: EOH_LOCATION.LAT,
218
+ longitude: EOH_LOCATION.LNG,
219
+ latitudeDelta: MAP_INITIAL_REGION.LAT,
220
+ longitudeDelta: MAP_INITIAL_REGION.LNG,
208
221
  }}
209
222
  followUserLocation={true}
210
223
  >
@@ -29,13 +29,13 @@ const ListSmartAccount = ({ route }) => {
29
29
  const [loadingRemoveItem, setLoadingRemoveItem] = useState(false);
30
30
 
31
31
  const getAllSmartAccounts = useCallback(async () => {
32
- const { success, data } = await axiosGet(
33
- API.SMART_ACCOUNT.LIST_SMART_ACCOUNT()
32
+ const { success, data: accountData } = await axiosGet(
33
+ API.SMART_ACCOUNT.LIST_SMART_ACCOUNT(unitId)
34
34
  );
35
35
  if (success) {
36
- setData(data);
36
+ setData(accountData);
37
37
  }
38
- }, []);
38
+ }, [unitId]);
39
39
 
40
40
  const { childRef, showingPopover, showPopoverWithRef, hidePopover } =
41
41
  usePopover();
@@ -5,6 +5,7 @@ import Routes from '../../utils/Route';
5
5
  import { useIsFocused, useNavigation } from '@react-navigation/native';
6
6
  import { axiosGet } from '../../utils/Apis/axios';
7
7
  import { API } from '../../configs';
8
+ import { useReceiveNotifications } from '../../hooks';
8
9
 
9
10
  const Summaries = memo(({ unit }) => {
10
11
  const [unitSummaries, setUnitSummaries] = useState([]);
@@ -33,6 +34,8 @@ const Summaries = memo(({ unit }) => {
33
34
  const goToSummary = useCallback(
34
35
  (summary) => {
35
36
  navigation.navigate(Routes.UnitSummary, {
37
+ summaryId: summary.id,
38
+ unitId: unit.id,
36
39
  summaryData: summary,
37
40
  unitData: unit,
38
41
  });
@@ -50,7 +53,7 @@ const Summaries = memo(({ unit }) => {
50
53
  if (success) {
51
54
  localState.timeoutId = setTimeout(() => {
52
55
  continuousFetchSummary();
53
- }, 5000);
56
+ }, 10000);
54
57
  }
55
58
  }, [localState, fetchUnitSummary]);
56
59
 
@@ -82,6 +85,19 @@ const Summaries = memo(({ unit }) => {
82
85
  };
83
86
  }, [localState, continuousFetchSummary, isFocused]);
84
87
 
88
+ const { dataNotification } = useReceiveNotifications();
89
+
90
+ useEffect(() => {
91
+ if (dataNotification) {
92
+ const { params = {} } = dataNotification;
93
+ const { summary_id } = params;
94
+ if (summary_id) {
95
+ fetchUnitSummary();
96
+ }
97
+ }
98
+ // eslint-disable-next-line react-hooks/exhaustive-deps
99
+ }, [dataNotification]);
100
+
85
101
  return (
86
102
  <>
87
103
  {!unitSummaries || !unitSummaries.length ? null : (
@@ -24,7 +24,9 @@ jest.mock('react-redux', () => ({
24
24
 
25
25
  jest.mock('../../../iot/RemoteControl/GoogleHome', () => ({
26
26
  ...jest.requireActual('../../../iot/RemoteControl/GoogleHome'),
27
- googleHomeConnect: jest.fn(() => false),
27
+ googleHomeConnect: jest.fn(async () => ({
28
+ [1]: {},
29
+ })),
28
30
  }));
29
31
 
30
32
  jest.mock('@react-native-community/netinfo', () => {
@@ -37,6 +39,12 @@ jest.mock('@react-native-community/netinfo', () => {
37
39
  };
38
40
  });
39
41
 
42
+ jest.mock('react-native-onesignal', () => {
43
+ return {
44
+ setNotificationWillShowInForegroundHandler: jest.fn(),
45
+ };
46
+ });
47
+
40
48
  const wrapComponent = (route, unitData, account) => (
41
49
  <SCProvider initState={mockSCStore({})}>
42
50
  <UnitDetail
@@ -2,7 +2,6 @@ import React from 'react';
2
2
  import { TouchableOpacity, View } from 'react-native';
3
3
  import MockAdapter from 'axios-mock-adapter';
4
4
  import renderer, { act } from 'react-test-renderer';
5
- import { createConnection, getStates } from 'home-assistant-js-websocket';
6
5
  import ParallaxScrollView from '../../../libs/react-native-parallax-scroll-view';
7
6
  import { BleManager } from 'react-native-ble-plx';
8
7
  import { useIsFocused } from '@react-navigation/native';
@@ -55,11 +54,19 @@ jest.mock('@react-navigation/native', () => {
55
54
  };
56
55
  });
57
56
 
58
- jest.mock('home-assistant-js-websocket', () => {
57
+ const mockConnectGoogleHome = jest.fn();
58
+ jest.mock('../../../hooks/IoT', () => {
59
59
  return {
60
- ...jest.requireActual('home-assistant-js-websocket'),
61
- createConnection: jest.fn(),
62
- getStates: jest.fn(),
60
+ ...jest.requireActual('../../../hooks/IoT'),
61
+ useGGHomeConnection: () => ({
62
+ connectGoogleHome: mockConnectGoogleHome,
63
+ }),
64
+ };
65
+ });
66
+
67
+ jest.mock('react-native-onesignal', () => {
68
+ return {
69
+ setNotificationWillShowInForegroundHandler: jest.fn(),
63
70
  };
64
71
  });
65
72
 
@@ -197,21 +204,12 @@ describe('Test UnitDetail', () => {
197
204
  ],
198
205
  },
199
206
  };
200
- jest.useFakeTimers();
201
-
202
- createConnection.mockImplementation(async () => ({
203
- subscribeEvents: jest.fn(),
204
- addEventListener: jest.fn(),
205
- }));
206
-
207
207
  await act(async () => {
208
208
  renderer.create(
209
209
  wrapComponent({ params: { ...route.params, unitData } }, account)
210
210
  );
211
211
  });
212
-
213
- expect(createConnection).toHaveBeenCalled();
214
- expect(getStates).toHaveBeenCalled();
212
+ expect(mockConnectGoogleHome).toBeCalled();
215
213
  });
216
214
 
217
215
  test('when unit has bluetooth action then scan for devices', async () => {
@@ -361,6 +359,7 @@ describe('Test UnitDetail', () => {
361
359
  expect(fullView).toHaveLength(1);
362
360
  expect(fullView[0].props.isVisible).toEqual(false);
363
361
  });
362
+
364
363
  test('onPress subunit camera devices', async () => {
365
364
  const unitData = {
366
365
  stations: [
@@ -405,6 +404,7 @@ describe('Test UnitDetail', () => {
405
404
  });
406
405
  expect(mockedNavigate).not.toHaveBeenCalled();
407
406
  });
407
+
408
408
  test('render subunit favorites', async () => {
409
409
  const unitData = {
410
410
  stations: [
@@ -423,6 +423,7 @@ describe('Test UnitDetail', () => {
423
423
  const favorites = instance.findAllByType(SubUnitFavorites);
424
424
  expect(favorites).toHaveLength(1);
425
425
  });
426
+
426
427
  test('render navbar', async () => {
427
428
  mock.onGet(API.UNIT.UNIT_DETAIL(1)).reply(200, {
428
429
  stations: [],
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { act, create } from 'react-test-renderer';
3
3
  import MockAdapter from 'axios-mock-adapter';
4
+ import RNP from 'react-native-permissions';
4
5
 
5
6
  import { SCProvider } from '../../../context';
6
7
  import { mockSCStore } from '../../../context/mockStore';
@@ -11,6 +12,11 @@ import BottomButtonView from '../../../commons/BottomButtonView';
11
12
  import { API } from '../../../configs';
12
13
  import { TESTID } from '../../../configs/Constants';
13
14
  import api from '../../../utils/Apis/axios';
15
+ import {
16
+ GEOLOCATION_ERROR,
17
+ OpenSetting,
18
+ } from '../../../utils/Permission/common';
19
+ import { RESULTS } from 'react-native-permissions';
14
20
 
15
21
  const wrapComponent = (route) => (
16
22
  <SCProvider initState={mockSCStore({})}>
@@ -56,18 +62,23 @@ jest.mock('react-native-maps', () => {
56
62
  };
57
63
  });
58
64
 
59
- jest.mock('@react-native-community/geolocation', () => {
60
- const position = {
61
- coords: {
62
- latitude: 100,
63
- longitude: 100,
64
- },
65
- };
66
- return {
67
- getCurrentPosition: (onSuccess, onError, options) => {
68
- onSuccess(position);
69
- },
70
- };
65
+ jest.mock('../../../utils/Permission/common');
66
+
67
+ const position = {
68
+ coords: {
69
+ latitude: 100,
70
+ longitude: 100,
71
+ },
72
+ };
73
+ const mockGeolocation = {
74
+ getCurrentPosition: (onSuccess, onError, options) => {
75
+ onSuccess(position);
76
+ },
77
+ };
78
+ global.navigator.geolocation = mockGeolocation;
79
+
80
+ jest.mock('react-native-permissions', () => {
81
+ return require('react-native-permissions/mock');
71
82
  });
72
83
 
73
84
  describe('Test SelectAddress', () => {
@@ -76,6 +87,7 @@ describe('Test SelectAddress', () => {
76
87
  const mockUpdateLocation = jest.fn();
77
88
 
78
89
  beforeAll(() => {
90
+ RNP.check.mockClear();
79
91
  route = {
80
92
  params: {
81
93
  updateLocation: mockUpdateLocation,
@@ -141,7 +153,7 @@ describe('Test SelectAddress', () => {
141
153
  expect(mockGoBack).toBeCalled();
142
154
  });
143
155
 
144
- test('test get current location', async () => {
156
+ test('test get current location success', async () => {
145
157
  await act(async () => {
146
158
  tree = await create(wrapComponent(route));
147
159
  });
@@ -174,6 +186,53 @@ describe('Test SelectAddress', () => {
174
186
  });
175
187
  });
176
188
 
189
+ test('test get current location failed permission denied', async () => {
190
+ await act(async () => {
191
+ tree = await create(wrapComponent(route));
192
+ });
193
+ const instance = tree.root;
194
+ const button = instance.find(
195
+ (el) => el.props.testID === TESTID.BUTTON_YOUR_LOCATION
196
+ );
197
+
198
+ global.navigator.geolocation = {
199
+ getCurrentPosition: (onSuccess, onError, options) => {
200
+ onError({ code: GEOLOCATION_ERROR.PERMISSION_DENIED });
201
+ },
202
+ };
203
+ RNP.check.mockImplementationOnce(() => RESULTS.BLOCKED);
204
+ OpenSetting.mockImplementationOnce(() => {});
205
+
206
+ await act(async () => {
207
+ await button.props.onPress();
208
+ });
209
+ OpenSetting.mockClear();
210
+ });
211
+
212
+ test('test get current failed error not handle', async () => {
213
+ await act(async () => {
214
+ tree = await create(wrapComponent(route));
215
+ });
216
+ const instance = tree.root;
217
+ const button = instance.find(
218
+ (el) => el.props.testID === TESTID.BUTTON_YOUR_LOCATION
219
+ );
220
+
221
+ global.navigator.geolocation = {
222
+ getCurrentPosition: (onSuccess, onError, options) => {
223
+ onError({ code: GEOLOCATION_ERROR.TIMEOUT });
224
+ },
225
+ };
226
+ RNP.check.mockImplementationOnce(() => RESULTS.DENIED);
227
+ OpenSetting.mockImplementationOnce(() => {});
228
+
229
+ await act(async () => {
230
+ await button.props.onPress();
231
+ });
232
+ expect(OpenSetting).toBeCalledTimes(0);
233
+ OpenSetting.mockClear();
234
+ });
235
+
177
236
  test('test choose on map', async () => {
178
237
  await act(async () => {
179
238
  tree = await create(wrapComponent(route));
@@ -69,7 +69,7 @@ describe('Test SmartAccount', () => {
69
69
  ],
70
70
  };
71
71
  mock
72
- .onGet(API.SMART_ACCOUNT.LIST_SMART_ACCOUNT())
72
+ .onGet(API.SMART_ACCOUNT.LIST_SMART_ACCOUNT(1))
73
73
  .reply(response.status, response.data);
74
74
  await act(async () => {
75
75
  tree = await renderer.create(wrapComponent(route));