@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.
- package/README.md +1 -1
- package/package.json +3 -3
- package/src/commons/Action/ItemQuickAction.js +11 -2
- package/src/commons/Action/__test__/ItemQuickAction.test.js +11 -6
- package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +31 -20
- package/src/commons/ActionGroup/SmartTiviActionTemplate/SmartTiviActionTemplate.js +3 -2
- package/src/commons/ActionGroup/TwoButtonTemplate/index.js +0 -1
- package/src/commons/ActionGroup/__test__/NumberUpDownTemplate.test.js +45 -48
- package/src/commons/ActionGroup/__test__/index.test.js +2 -2
- package/src/commons/ConnectingProcess/index.js +11 -7
- package/src/commons/Device/ConnectedViewHeader.js +1 -1
- package/src/commons/Device/HistoryChart.js +3 -3
- package/src/commons/Device/ItemDevice.js +15 -11
- package/src/commons/Device/SonosSpeaker/index.js +1 -1
- package/src/commons/FieldTemplate/ScheduleField/index.js +2 -2
- package/src/commons/Header/HeaderCustom.js +2 -1
- package/src/commons/HorizontalPicker/index.js +2 -2
- package/src/commons/MediaPlayerDetail/Styles/MediaPlayerDetailStyles.js +0 -6
- package/src/commons/MediaPlayerDetail/index.js +19 -50
- package/src/commons/SubUnit/Favorites/index.js +2 -3
- package/src/commons/SubUnit/ShortDetail.js +1 -2
- package/src/commons/SubUnit/__test__/Item.test.js +0 -1
- package/src/commons/UnitSummary/ConfigHistoryChart/index.js +2 -13
- package/src/commons/UnitSummary/ConfigHistoryChart.js +22 -13
- package/src/commons/WheelDateTimePicker/index.js +2 -2
- package/src/configs/API.js +4 -13
- package/src/configs/Constants.js +13 -0
- package/src/context/actionType.ts +8 -0
- package/src/context/mockStore.ts +10 -0
- package/src/context/reducer.ts +38 -2
- package/src/hooks/Common/index.js +2 -0
- package/src/hooks/Common/useGGHomeDeviceConnected.js +16 -0
- package/src/hooks/Common/useGetIdUser.js +1 -5
- package/src/hooks/Common/useSensorsStatus.js +5 -8
- package/src/hooks/IoT/__test__/useGGHomeConnection.test.js +198 -0
- package/src/hooks/IoT/__test__/useRemoteControl.test.js +198 -0
- package/src/hooks/IoT/index.js +4 -0
- package/src/hooks/IoT/useGGHomeConnection.js +91 -0
- package/src/hooks/IoT/useRemoteControl.js +79 -0
- package/src/hooks/index.js +4 -0
- package/src/hooks/useReceiveNotifications.js +8 -4
- package/src/iot/Monitor.js +3 -2
- package/src/iot/RemoteControl/Bluetooth.js +1 -1
- package/src/iot/RemoteControl/GoogleHome.js +75 -49
- package/src/iot/RemoteControl/Internet.js +1 -1
- package/src/iot/RemoteControl/__test__/GoogleHome.test.js +90 -21
- package/src/iot/RemoteControl/__test__/Internet.test.js +4 -4
- package/src/iot/RemoteControl/__test__/LgThinq.test.js +5 -5
- package/src/iot/RemoteControl/index.js +52 -52
- package/src/screens/ActivityLog/hooks/__test__/index.test.js +3 -3
- package/src/screens/ActivityLog/hooks/index.js +1 -1
- package/src/screens/AddLocationMaps/index.js +5 -4
- package/src/screens/AddNewAction/SelectAction.js +8 -8
- package/src/screens/AddNewAction/SetupSensor.js +7 -7
- package/src/screens/AddNewAction/__test__/SelectAction.test.js +2 -2
- package/src/screens/AddNewDevice/ConnectingDevices.js +1 -1
- package/src/screens/AddNewDevice/__test__/ConnectingDevices.test.js +2 -2
- package/src/screens/AddNewDevice/hooks/ConnectDevices.js +1 -1
- package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +23 -17
- package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +3 -3
- package/src/screens/AddNewGateway/SetupGatewayWifi.js +1 -0
- package/src/screens/AllCamera/index.js +4 -4
- package/src/screens/Automate/MultiUnits.js +8 -8
- package/src/screens/Automate/index.js +3 -3
- package/src/screens/Device/EditDevice/__test__/EditDevice.test.js +4 -4
- package/src/screens/Device/EditDevice/index.js +2 -2
- package/src/screens/Device/__test__/detail.test.js +13 -5
- package/src/screens/Device/components/DetailHistoryChart.js +1 -1
- package/src/screens/Device/components/SensorConnectStatusViewHeader.js +1 -0
- package/src/screens/Device/components/SensorDisplayItem.js +5 -2
- package/src/screens/Device/detail.js +49 -16
- package/src/screens/Device/hooks/useDisconnectedDevice.js +4 -4
- package/src/screens/EditActionsList/index.js +1 -1
- package/src/screens/EmergencySetting/components/DropDownItem.js +2 -2
- package/src/screens/HanetCamera/Detail.js +1 -1
- package/src/screens/HanetCamera/__test__/Detail.test.js +2 -2
- package/src/screens/HanetCamera/components/RequestFaceIDPopup.js +3 -2
- package/src/screens/HanetCamera/hooks/useHanetCheckinData.js +11 -11
- package/src/screens/HanetCamera/hooks/useHanetPlaceMembers.js +11 -11
- package/src/screens/ManageAccess/hooks/index.js +7 -4
- package/src/screens/MoveToAnotherSubUnit/__test__/index.test.js +2 -2
- package/src/screens/MoveToAnotherSubUnit/index.js +1 -1
- package/src/screens/Notification/__test__/NotificationItem.test.js +4 -4
- package/src/screens/Notification/components/NotificationItem.js +17 -20
- package/src/screens/Notification/index.js +9 -2
- package/src/screens/PlayBackCamera/Timer.js +2 -2
- package/src/screens/PlayBackCamera/index.js +3 -3
- package/src/screens/ScanChipQR/hooks/index.js +15 -16
- package/src/screens/ScriptDetail/index.js +14 -10
- package/src/screens/SelectUnit/index.js +4 -2
- package/src/screens/SetSchedule/index.js +9 -9
- package/src/screens/Sharing/Components/SensorItem.js +10 -12
- package/src/screens/Sharing/SelectPermission.js +14 -6
- package/src/screens/SideMenuDetail/__test__/index.test.js +4 -4
- package/src/screens/SideMenuDetail/index.js +2 -3
- package/src/screens/SmartIr/components/GroupButtonByType/GroupButtonByType.js +3 -2
- package/src/screens/SubUnit/Detail.js +1 -2
- package/src/screens/SubUnit/ManageSubUnit.js +12 -7
- package/src/screens/SubUnit/__test__/Detail.test.js +1 -1
- package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +27 -1
- package/src/screens/SubUnit/hooks/__test__/useManageSubUnit.test.js +1 -1
- package/src/screens/SubUnit/hooks/useManageSubUnit.js +7 -7
- package/src/screens/Unit/ChooseLocation.js +6 -13
- package/src/screens/Unit/Detail.js +30 -75
- package/src/screens/Unit/SelectAddress.js +34 -21
- package/src/screens/Unit/SmartAccount.js +4 -4
- package/src/screens/Unit/Summaries.js +17 -1
- package/src/screens/Unit/__test__/CheckSendEmail.test.js +9 -1
- package/src/screens/Unit/__test__/Detail.test.js +16 -15
- package/src/screens/Unit/__test__/SelectAddress.test.js +72 -13
- package/src/screens/Unit/__test__/SmartAccount.test.js +1 -1
- package/src/screens/Unit/__test__/Summaries.test.js +100 -0
- package/src/screens/Unit/hook/useUnitConnectRemoteDevices.js +50 -0
- package/src/screens/Unit/styles.js +4 -0
- package/src/screens/UnitSummary/__test__/index.test.js +55 -1
- package/src/screens/UnitSummary/components/3PPowerConsumption/__test__/3PPowerConsumption.test.js +31 -2
- package/src/screens/UnitSummary/components/PowerConsumeHistoryChart/index.js +2 -13
- package/src/screens/UnitSummary/components/PowerConsumption/__test__/ItemPower.test.js +0 -1
- package/src/screens/UnitSummary/components/RunningDevices/__test__/index.test.js +11 -2
- package/src/screens/UnitSummary/components/RunningDevices/index.js +7 -10
- package/src/screens/UnitSummary/components/Temperature/index.js +4 -4
- package/src/screens/UnitSummary/index.js +15 -1
- package/src/utils/Apis/axios.js +16 -25
- package/src/utils/Converter/time.js +0 -18
- package/src/utils/I18n/translations/en.json +2 -1
- package/src/utils/I18n/translations/vi.json +3 -1
- package/src/utils/Permission/common.js +39 -0
- 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 {
|
|
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 {
|
|
27
|
-
import {
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 {
|
|
24
|
+
import {
|
|
25
|
+
TESTID,
|
|
26
|
+
MAP_INITIAL_REGION,
|
|
27
|
+
EOH_LOCATION,
|
|
28
|
+
} from '../../configs/Constants';
|
|
22
29
|
|
|
23
|
-
|
|
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 (
|
|
50
|
-
setInput(
|
|
51
|
-
if (
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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(
|
|
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
|
-
},
|
|
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(() =>
|
|
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.
|
|
57
|
+
const mockConnectGoogleHome = jest.fn();
|
|
58
|
+
jest.mock('../../../hooks/IoT', () => {
|
|
59
59
|
return {
|
|
60
|
-
...jest.requireActual('
|
|
61
|
-
|
|
62
|
-
|
|
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('
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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));
|