@eohjsc/react-native-smart-city 0.3.0 → 0.3.3
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 +4 -4
- package/react-native-smart-city.podspec +1 -0
- 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/DeviceItem/DeviceItem.js +7 -3
- package/src/commons/ConnectingProcess/DeviceItem/DeviceItemStyles.js +8 -11
- package/src/commons/ConnectingProcess/__test__/DeviceItem.test.js +3 -2
- package/src/commons/ConnectingProcess/index.js +71 -24
- 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 +24 -55
- package/src/commons/SubUnit/Favorites/index.js +2 -3
- package/src/commons/SubUnit/ShortDetail.js +25 -9
- package/src/commons/SubUnit/__test__/Item.test.js +0 -1
- package/src/commons/SubUnit/__test__/ShortDetail.test.js +8 -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 +7 -12
- 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 +4 -4
- 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 +9 -5
- 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/components/WaterQuality/Item/index.js +10 -2
- 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 +4 -1
- package/src/utils/I18n/translations/vi.json +5 -1
- package/src/utils/Permission/common.js +67 -0
- package/src/utils/Utils.js +5 -1
|
@@ -59,7 +59,7 @@ describe('Test SideMenuDetail', () => {
|
|
|
59
59
|
expect(popup.props.isVisible).toBeFalsy();
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
const
|
|
62
|
+
const enterPasscode = async (instance) => {
|
|
63
63
|
const inputPasscode = instance.find(
|
|
64
64
|
(item) => item.props.testID === TESTID.PASSCODE_FIELD
|
|
65
65
|
);
|
|
@@ -124,12 +124,12 @@ describe('Test SideMenuDetail', () => {
|
|
|
124
124
|
};
|
|
125
125
|
|
|
126
126
|
mock
|
|
127
|
-
.onGet(API.
|
|
127
|
+
.onGet(API.DEVICE.SIDE_MENU_DETAIL(1, 1))
|
|
128
128
|
.reply(200, response_side_menu.data);
|
|
129
129
|
mock
|
|
130
130
|
.onGet(API.SHARE.UNITS_MEMBERS(1))
|
|
131
131
|
.reply(200, response_unit_members.data);
|
|
132
|
-
mock.onPost(API.
|
|
132
|
+
mock.onPost(API.DEVICE.TRIGGER_ACTION(1)).reply(200, []);
|
|
133
133
|
|
|
134
134
|
const route = {
|
|
135
135
|
params: {
|
|
@@ -147,7 +147,7 @@ describe('Test SideMenuDetail', () => {
|
|
|
147
147
|
await onPressSubmitData(instance);
|
|
148
148
|
expect(spyToastError).toBeCalled();
|
|
149
149
|
|
|
150
|
-
await
|
|
150
|
+
await enterPasscode(instance);
|
|
151
151
|
await onPressSubmitData(instance);
|
|
152
152
|
expect(spyToastSuccess).toBeCalled();
|
|
153
153
|
});
|
|
@@ -61,7 +61,6 @@ const SideMenuDetail = memo(({ route }) => {
|
|
|
61
61
|
return null;
|
|
62
62
|
}
|
|
63
63
|
},
|
|
64
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
65
64
|
[unit, dataForm]
|
|
66
65
|
);
|
|
67
66
|
|
|
@@ -88,7 +87,7 @@ const SideMenuDetail = memo(({ route }) => {
|
|
|
88
87
|
|
|
89
88
|
data.action_zigbee = actionZigbee;
|
|
90
89
|
|
|
91
|
-
const { success } = await axiosPost(API.
|
|
90
|
+
const { success } = await axiosPost(API.DEVICE.TRIGGER_ACTION(sensor.id), {
|
|
92
91
|
key: sideMenu.action,
|
|
93
92
|
data,
|
|
94
93
|
source: 'smart_lock',
|
|
@@ -105,7 +104,7 @@ const SideMenuDetail = memo(({ route }) => {
|
|
|
105
104
|
|
|
106
105
|
const fetchSideMenuDetail = useCallback(async () => {
|
|
107
106
|
const { success, data } = await axiosGet(
|
|
108
|
-
API.
|
|
107
|
+
API.DEVICE.SIDE_MENU_DETAIL(sensor.id, side_menu.id)
|
|
109
108
|
);
|
|
110
109
|
if (success) {
|
|
111
110
|
setSideMenu(data);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { memo, useCallback, useState, useMemo } from 'react';
|
|
2
|
-
import { View, TouchableOpacity
|
|
2
|
+
import { View, TouchableOpacity } from 'react-native';
|
|
3
3
|
import WrapHeaderScrollable from '../../../../commons/Sharing/WrapHeaderScrollable';
|
|
4
4
|
import { useTranslations } from '../../../../hooks/Common/useTranslations';
|
|
5
5
|
import SmartTiviActionTemplate from '../../../../commons/ActionGroup/SmartTiviActionTemplate/SmartTiviActionTemplate';
|
|
@@ -14,6 +14,7 @@ import { Remote, SmartIr, Union } from '../../../../Images/SmartIr';
|
|
|
14
14
|
|
|
15
15
|
import styles from './GroupButtonByTypeStyles';
|
|
16
16
|
import { TESTID } from '../../../../configs/Constants';
|
|
17
|
+
import { notImplemented } from '../../../../utils/Utils';
|
|
17
18
|
|
|
18
19
|
const GroupButtonByType = memo(({ route }) => {
|
|
19
20
|
const t = useTranslations();
|
|
@@ -38,7 +39,7 @@ const GroupButtonByType = memo(({ route }) => {
|
|
|
38
39
|
case 'reload':
|
|
39
40
|
case 'more':
|
|
40
41
|
case 'done':
|
|
41
|
-
return
|
|
42
|
+
return notImplemented(t);
|
|
42
43
|
default:
|
|
43
44
|
return <></>;
|
|
44
45
|
}
|
|
@@ -16,7 +16,7 @@ import styles from './DetailStyles';
|
|
|
16
16
|
|
|
17
17
|
const SubUnitDetail = ({ route }) => {
|
|
18
18
|
const t = useTranslations();
|
|
19
|
-
const { unit, station
|
|
19
|
+
const { unit, station } = route.params;
|
|
20
20
|
const language = useSCContextSelector((state) => state.language);
|
|
21
21
|
const navigation = useNavigation();
|
|
22
22
|
const { childRef, showingPopover, showPopoverWithRef, hidePopover } =
|
|
@@ -125,7 +125,6 @@ const SubUnitDetail = ({ route }) => {
|
|
|
125
125
|
sensor={item}
|
|
126
126
|
unit={unit}
|
|
127
127
|
station={station}
|
|
128
|
-
isGGHomeConnected={isGGHomeConnected}
|
|
129
128
|
/>
|
|
130
129
|
);
|
|
131
130
|
})}
|
|
@@ -20,13 +20,14 @@ import Routes from '../../utils/Route';
|
|
|
20
20
|
import { RowItem } from '../../commons/RowItem';
|
|
21
21
|
import NoSubUnitImage from '../../../assets/images/Illustrations.svg';
|
|
22
22
|
import useManageSubUnit from './hooks/useManageSubUnit';
|
|
23
|
+
import { TESTID } from '../../configs/Constants';
|
|
23
24
|
|
|
24
25
|
const ManageSubUnit = memo((props) => {
|
|
25
26
|
const t = useTranslations();
|
|
26
27
|
const { unit } = props.route.params;
|
|
27
28
|
const navigation = useNavigation();
|
|
28
29
|
const isFocused = useIsFocused();
|
|
29
|
-
const {
|
|
30
|
+
const { stations, isRefresh, isLoading, onRefresh } = useManageSubUnit(unit);
|
|
30
31
|
|
|
31
32
|
const addSubUnit = useCallback(() => {
|
|
32
33
|
navigation.navigate(Routes.AddSubUnitStack, {
|
|
@@ -35,7 +36,7 @@ const ManageSubUnit = memo((props) => {
|
|
|
35
36
|
});
|
|
36
37
|
}, [navigation, unit]);
|
|
37
38
|
|
|
38
|
-
const goToEditSubUnit = (station
|
|
39
|
+
const goToEditSubUnit = (station) => {
|
|
39
40
|
navigation.navigate(Routes.UnitStack, {
|
|
40
41
|
screen: Routes.EditSubUnit,
|
|
41
42
|
params: {
|
|
@@ -48,7 +49,11 @@ const ManageSubUnit = memo((props) => {
|
|
|
48
49
|
const rightComponent = useMemo(
|
|
49
50
|
() => (
|
|
50
51
|
<View style={styles.rightComponent}>
|
|
51
|
-
<TouchableOpacity
|
|
52
|
+
<TouchableOpacity
|
|
53
|
+
testID={TESTID.ADD_SUB_UNIT}
|
|
54
|
+
onPress={addSubUnit}
|
|
55
|
+
style={styles.headerButton}
|
|
56
|
+
>
|
|
52
57
|
<Icon name={'plus'} size={27} color={Colors.Black} />
|
|
53
58
|
</TouchableOpacity>
|
|
54
59
|
<TouchableOpacity
|
|
@@ -84,8 +89,8 @@ const ManageSubUnit = memo((props) => {
|
|
|
84
89
|
scrollIndicatorInsets={{ right: 1 }}
|
|
85
90
|
>
|
|
86
91
|
<View>
|
|
87
|
-
{!!
|
|
88
|
-
|
|
92
|
+
{!!stations.length &&
|
|
93
|
+
stations.map((item, index) => {
|
|
89
94
|
return (
|
|
90
95
|
<RowItem
|
|
91
96
|
type={'noneBG'}
|
|
@@ -100,7 +105,7 @@ const ManageSubUnit = memo((props) => {
|
|
|
100
105
|
}
|
|
101
106
|
text={item.name}
|
|
102
107
|
subtext={`${
|
|
103
|
-
item.
|
|
108
|
+
item.devices ? item.devices.length : '0'
|
|
104
109
|
} devices`}
|
|
105
110
|
onPress={() => goToEditSubUnit(item, unit)}
|
|
106
111
|
rightComponent={
|
|
@@ -113,7 +118,7 @@ const ManageSubUnit = memo((props) => {
|
|
|
113
118
|
/>
|
|
114
119
|
);
|
|
115
120
|
})}
|
|
116
|
-
{!
|
|
121
|
+
{!stations.length && !isRefresh && !isLoading && (
|
|
117
122
|
<View style={styles.NoSubUnit}>
|
|
118
123
|
<NoSubUnitImage />
|
|
119
124
|
<Text semibold type="H4" center>
|
|
@@ -138,7 +138,7 @@ describe('Test SubUnitDetail', () => {
|
|
|
138
138
|
expect(mockedDangerouslyGetStatePop).toHaveBeenCalledWith(2);
|
|
139
139
|
});
|
|
140
140
|
|
|
141
|
-
test
|
|
141
|
+
test('click Menu ActionMore', async () => {
|
|
142
142
|
mockedDangerouslyGetState.mockImplementation(() => ({
|
|
143
143
|
routes: [
|
|
144
144
|
{ name: 'route 1' },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import { ScrollView } from 'react-native';
|
|
2
|
+
import { ScrollView, TouchableOpacity } from 'react-native';
|
|
3
3
|
import { create } from 'react-test-renderer';
|
|
4
4
|
import { act } from '@testing-library/react-hooks';
|
|
5
5
|
import ManageSubUnit from '../ManageSubUnit';
|
|
@@ -7,6 +7,7 @@ import { SCProvider } from '../../../context';
|
|
|
7
7
|
import { mockSCStore } from '../../../context/mockStore';
|
|
8
8
|
import { RowItem } from '../../../commons/RowItem';
|
|
9
9
|
import Routes from '../../../utils/Route';
|
|
10
|
+
import { TESTID } from '../../../configs/Constants';
|
|
10
11
|
|
|
11
12
|
const mockSetState = jest.fn();
|
|
12
13
|
|
|
@@ -76,4 +77,29 @@ describe('Test ManageSubUnit', () => {
|
|
|
76
77
|
screen: 'EditSubUnit',
|
|
77
78
|
});
|
|
78
79
|
});
|
|
80
|
+
it('ManageSubUnit add sub unit', async () => {
|
|
81
|
+
let route = {
|
|
82
|
+
params: { unit: { id: 1, name: 'unit 1' } },
|
|
83
|
+
};
|
|
84
|
+
await act(() => {
|
|
85
|
+
tree = create(wrapComponent(route));
|
|
86
|
+
});
|
|
87
|
+
const instance = tree.root;
|
|
88
|
+
const buttonAddSubUnit = instance.find(
|
|
89
|
+
(el) =>
|
|
90
|
+
el.props.testID === TESTID.ADD_SUB_UNIT && el.type === TouchableOpacity
|
|
91
|
+
);
|
|
92
|
+
act(() => {
|
|
93
|
+
buttonAddSubUnit.props.onPress();
|
|
94
|
+
});
|
|
95
|
+
expect(mockedNavigate).toHaveBeenCalledWith(Routes.AddSubUnitStack, {
|
|
96
|
+
params: {
|
|
97
|
+
unit: {
|
|
98
|
+
id: 1,
|
|
99
|
+
name: 'unit 1',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
screen: Routes.AddSubUnit,
|
|
103
|
+
});
|
|
104
|
+
});
|
|
79
105
|
});
|
|
@@ -30,7 +30,7 @@ describe('Test Manage Access', () => {
|
|
|
30
30
|
|
|
31
31
|
it('Test init', () => {
|
|
32
32
|
const { result } = renderHook(() => useManageSubUnit(unit));
|
|
33
|
-
expect(result.current.
|
|
33
|
+
expect(result.current.stations).toEqual([]);
|
|
34
34
|
expect(result.current.isLoading).toBeFalsy();
|
|
35
35
|
expect(result.current.isRefreshing).toBeFalsy();
|
|
36
36
|
});
|
|
@@ -3,11 +3,11 @@ import { axiosGet } from '../../../utils/Apis/axios';
|
|
|
3
3
|
import API from '../../../configs/API';
|
|
4
4
|
|
|
5
5
|
export default (unit) => {
|
|
6
|
-
const [
|
|
6
|
+
const [stations, setStations] = useState([]);
|
|
7
7
|
const [isLoading, setIsLoading] = useState(false);
|
|
8
8
|
const [isRefresh, setRefresh] = useState(false);
|
|
9
9
|
|
|
10
|
-
const fetchData = useCallback(async (
|
|
10
|
+
const fetchData = useCallback(async () => {
|
|
11
11
|
setIsLoading(true);
|
|
12
12
|
const { success, data } = await axiosGet(
|
|
13
13
|
API.UNIT.UNIT_DETAIL(unit?.id),
|
|
@@ -15,19 +15,19 @@ export default (unit) => {
|
|
|
15
15
|
true
|
|
16
16
|
);
|
|
17
17
|
if (success) {
|
|
18
|
-
|
|
18
|
+
setStations(data?.stations);
|
|
19
19
|
}
|
|
20
20
|
setIsLoading(false);
|
|
21
|
-
}, []);
|
|
21
|
+
}, [unit]);
|
|
22
22
|
|
|
23
23
|
const onRefresh = useCallback(async () => {
|
|
24
24
|
setRefresh(true);
|
|
25
|
-
await fetchData(
|
|
25
|
+
await fetchData();
|
|
26
26
|
setRefresh(false);
|
|
27
|
-
}, [
|
|
27
|
+
}, [fetchData]);
|
|
28
28
|
|
|
29
29
|
return {
|
|
30
|
-
|
|
30
|
+
stations,
|
|
31
31
|
isRefresh,
|
|
32
32
|
onRefresh,
|
|
33
33
|
isLoading,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable react-hooks/exhaustive-deps */
|
|
2
1
|
import React, { memo, useCallback, useRef, useState } from 'react';
|
|
3
2
|
import { View } from 'react-native';
|
|
4
3
|
import MapView, { PROVIDER_GOOGLE } from 'react-native-maps';
|
|
@@ -8,20 +7,13 @@ import BottomButtonView from '../../commons/BottomButtonView';
|
|
|
8
7
|
import { FullLoading } from '../../commons';
|
|
9
8
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
10
9
|
|
|
11
|
-
navigator.geolocation = require('@react-native-community/geolocation');
|
|
12
|
-
|
|
13
10
|
import styles from './ChooseLocationStyles';
|
|
14
11
|
import { API } from '../../configs';
|
|
15
12
|
import { axiosGet } from '../../utils/Apis/axios';
|
|
16
13
|
import { SCConfig } from '../../configs';
|
|
14
|
+
import { MAP_INITIAL_REGION, EOH_LOCATION } from '../../configs/Constants';
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
latitudeDelta: 0.0922,
|
|
20
|
-
longitudeDelta: 0.0421,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const DEFAULT_LATITUDE = 10.7974046; // EoH center
|
|
24
|
-
const DEFAULT_LONGITUDE = 106.7035663;
|
|
16
|
+
navigator.geolocation = require('@react-native-community/geolocation');
|
|
25
17
|
|
|
26
18
|
const ChooseLocation = memo(({ route }) => {
|
|
27
19
|
const t = useTranslations();
|
|
@@ -76,9 +68,10 @@ const ChooseLocation = memo(({ route }) => {
|
|
|
76
68
|
provider={PROVIDER_GOOGLE}
|
|
77
69
|
style={styles.mapView}
|
|
78
70
|
initialRegion={{
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
latitude: location?.latitude || EOH_LOCATION.LAT,
|
|
72
|
+
longitude: location?.longitude || EOH_LOCATION.LNG,
|
|
73
|
+
latitudeDelta: MAP_INITIAL_REGION.LAT,
|
|
74
|
+
longitudeDelta: MAP_INITIAL_REGION.LNG,
|
|
82
75
|
}}
|
|
83
76
|
followUserLocation={true}
|
|
84
77
|
onRegionChangeComplete={onRegionChange}
|
|
@@ -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();
|