@eohjsc/react-native-smart-city 0.2.92 → 0.2.93
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/assets/images/Device/current-state.svg +3 -0
- package/assets/images/Device/door-state.svg +3 -0
- package/assets/images/Device/wind-strength.svg +12 -0
- package/package.json +1 -1
- package/src/commons/Action/ItemQuickAction.js +1 -0
- package/src/commons/Action/__test__/ItemQuickAction.test.js +49 -2
- package/src/commons/ActionGroup/OnOffTemplate/OnOffSimpleTemplateStyle.js +2 -1
- package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +31 -11
- package/src/commons/ActionGroup/OptionsDropdownActionTemplateStyle.js +5 -2
- package/src/commons/ActionGroup/TimerActionTemplate.js +14 -10
- package/src/commons/ActionGroup/TimerActionTemplateStyles.js +12 -0
- package/src/commons/ActionGroup/TwoButtonTemplate/TwoButtonTemplateStyles.js +55 -0
- package/src/commons/ActionGroup/TwoButtonTemplate/index.js +170 -0
- package/src/commons/ActionGroup/__test__/TimerActionTemplate.test.js +1 -1
- package/src/commons/ActionGroup/__test__/TwoButtonTemplate.test.js +112 -0
- package/src/commons/ActionGroup/index.js +3 -0
- package/src/commons/CameraDevice/index.js +6 -1
- package/src/commons/Device/HistoryChart.js +2 -2
- package/src/commons/Device/ItemDevice.js +3 -13
- package/src/commons/IconComponent/index.js +32 -26
- package/src/commons/MediaPlayerDetail/index.js +16 -4
- package/src/commons/SubUnit/Favorites/index.js +8 -7
- package/src/commons/SubUnit/__test__/Favorites.test.js +33 -35
- package/src/configs/API.js +4 -0
- package/src/configs/Constants.js +21 -0
- package/src/context/actionType.ts +17 -0
- package/src/context/mockStore.ts +18 -0
- package/src/context/reducer.ts +102 -0
- package/src/iot/RemoteControl/Bluetooth.js +2 -0
- package/src/iot/RemoteControl/GoogleHome.js +1 -0
- package/src/navigations/AutomateStack.js +16 -1
- package/src/navigations/UnitStack.js +27 -0
- package/src/screens/AddNewAction/Device/__test__/index.test.js +1 -1
- package/src/screens/AddNewAction/SelectAction.js +13 -15
- package/src/screens/AddNewAction/__test__/SelectAction.test.js +0 -7
- package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +2 -0
- package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +2 -0
- package/src/screens/AddNewGateway/PlugAndPlay/__test__/ConnectWifiWarning.test.js +9 -0
- package/src/screens/AddNewGateway/PlugAndPlay/__test__/GatewayWifiList.test.js +15 -0
- package/src/screens/AddNewGateway/SetupGatewayWifi.js +6 -1
- package/src/screens/AddNewGateway/__test__/SetupGateway.test.js +34 -0
- package/src/screens/AllCamera/index.js +1 -0
- package/src/screens/Automate/MultiUnits.js +9 -9
- package/src/screens/Automate/index.js +21 -20
- package/src/screens/Device/__test__/detail.test.js +119 -86
- package/src/screens/Device/detail.js +38 -51
- package/src/screens/Device/hooks/useFavoriteDevice.js +38 -0
- package/src/screens/EmergencyContacts/EmergencyContactsList.js +1 -1
- package/src/screens/EmergencyContacts/EmergencyContactsSelectContacts.js +41 -44
- package/src/screens/EmergencyContacts/__test__/EmergencyContactList.test.js +1 -0
- package/src/screens/EmergencyContacts/__test__/EmergencyContactsSelectContacts.test.js +18 -19
- package/src/screens/Notification/__test__/NotificationItem.test.js +64 -53
- package/src/screens/Notification/components/NotificationItem.js +13 -4
- package/src/screens/ScriptDetail/__test__/index.test.js +15 -4
- package/src/screens/ScriptDetail/hooks/useStarredScript.js +32 -0
- package/src/screens/ScriptDetail/index.js +11 -20
- package/src/screens/SharedUnit/__test__/TabHeader.test.js +5 -0
- package/src/screens/Sharing/SelectUser.js +3 -23
- package/src/screens/Sharing/__test__/SelectUser.test.js +12 -80
- package/src/screens/SmartIr/__test__/GroupButtonByType.test.js +33 -0
- package/src/screens/SmartIr/components/GroupButtonByType/GroupButtonByType.js +2 -0
- package/src/screens/Unit/ChooseLocation.js +5 -0
- package/src/screens/Unit/Detail.js +33 -37
- package/src/screens/Unit/ManageUnit.js +21 -20
- package/src/screens/Unit/ManageUnitStyles.js +1 -0
- package/src/screens/Unit/SelectAddress.js +8 -2
- package/src/screens/Unit/Summaries.js +12 -15
- package/src/screens/Unit/__test__/Detail.test.js +25 -0
- package/src/screens/Unit/components/__test__/Header.test.js +32 -0
- package/src/screens/Unit/hook/useFavorites.js +28 -0
- package/src/utils/Apis/axios.js +7 -2
- package/src/utils/I18n/translations/en.json +1 -4
- package/src/utils/I18n/translations/vi.json +1 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
2
|
import { TouchableOpacity, View } from 'react-native';
|
|
3
3
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
4
4
|
|
|
@@ -10,6 +10,8 @@ import { standardizeCameraScreenSize } from '../../utils/Utils';
|
|
|
10
10
|
import { Device } from '../../configs';
|
|
11
11
|
import { useNavigation } from '@react-navigation/native';
|
|
12
12
|
import Routes from '../../utils/Route';
|
|
13
|
+
import { SCContext } from '../../context';
|
|
14
|
+
import { Action } from '../../context/actionType';
|
|
13
15
|
|
|
14
16
|
const { standardizeWidth, standardizeHeight } = standardizeCameraScreenSize(
|
|
15
17
|
Device.screenWidth - 32
|
|
@@ -18,8 +20,10 @@ const { standardizeWidth, standardizeHeight } = standardizeCameraScreenSize(
|
|
|
18
20
|
const CameraDevice = ({ station, handleFullScreen, goToPlayBack }) => {
|
|
19
21
|
const t = useTranslations();
|
|
20
22
|
const { navigate } = useNavigation();
|
|
23
|
+
const { setAction } = useContext(SCContext);
|
|
21
24
|
|
|
22
25
|
const onPressViewAll = () => {
|
|
26
|
+
setAction(Action.CLOSE_ALL_CAMERA);
|
|
23
27
|
navigate(Routes.AllCamera, {
|
|
24
28
|
arrCameras: station?.camera_devices,
|
|
25
29
|
thumbnail: { uri: station?.background },
|
|
@@ -51,6 +55,7 @@ const CameraDevice = ({ station, handleFullScreen, goToPlayBack }) => {
|
|
|
51
55
|
]}
|
|
52
56
|
>
|
|
53
57
|
<MediaPlayerDetail
|
|
58
|
+
id={device.configuration.id}
|
|
54
59
|
uri={device.configuration.uri}
|
|
55
60
|
thumbnail={{
|
|
56
61
|
uri: station.background,
|
|
@@ -234,7 +234,7 @@ const HistoryChart = memo(
|
|
|
234
234
|
)}
|
|
235
235
|
<DateTimePickerModal
|
|
236
236
|
isVisible={eventPicker.showModalStart}
|
|
237
|
-
date={eventPicker.startTime.
|
|
237
|
+
date={eventPicker.startTime.toDate()}
|
|
238
238
|
mode={formatType || 'datetime'}
|
|
239
239
|
onConfirm={onConfirmStart}
|
|
240
240
|
onCancel={onCancel}
|
|
@@ -242,7 +242,7 @@ const HistoryChart = memo(
|
|
|
242
242
|
/>
|
|
243
243
|
<DateTimePickerModal
|
|
244
244
|
isVisible={eventPicker.showModalEnd}
|
|
245
|
-
date={eventPicker.endTime.
|
|
245
|
+
date={eventPicker.endTime.toDate()}
|
|
246
246
|
mode={formatType || 'datetime'}
|
|
247
247
|
onConfirm={onConfirmEnd}
|
|
248
248
|
onCancel={onCancel}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
View,
|
|
7
7
|
} from 'react-native';
|
|
8
8
|
import Routes from '../../utils/Route';
|
|
9
|
-
import {
|
|
9
|
+
import { IconOutline } from '@ant-design/icons-react-native';
|
|
10
10
|
import { useNavigation } from '@react-navigation/native';
|
|
11
11
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
12
12
|
import ItemQuickAction from '../../commons/Action/ItemQuickAction';
|
|
@@ -16,7 +16,7 @@ import { useSCContextSelector } from '../../context';
|
|
|
16
16
|
|
|
17
17
|
import { Colors } from '../../configs';
|
|
18
18
|
import { TESTID, DEVICE_TYPE, DEVICE_SIZE } from '../../configs/Constants';
|
|
19
|
-
import
|
|
19
|
+
import IconComponent from '../IconComponent';
|
|
20
20
|
|
|
21
21
|
const ItemDevice = memo(
|
|
22
22
|
({
|
|
@@ -33,7 +33,6 @@ const ItemDevice = memo(
|
|
|
33
33
|
}) => {
|
|
34
34
|
const t = useTranslations();
|
|
35
35
|
const navigation = useNavigation();
|
|
36
|
-
|
|
37
36
|
const isBluetoothEnabled = useSCContextSelector(
|
|
38
37
|
(state) => state.app.isBluetoothEnabled
|
|
39
38
|
);
|
|
@@ -51,15 +50,6 @@ const ItemDevice = memo(
|
|
|
51
50
|
});
|
|
52
51
|
}, [navigation, sensor, station, title, unit, isGGHomeConnected]);
|
|
53
52
|
|
|
54
|
-
const displayIconSensor = () => {
|
|
55
|
-
const iconKit = sensor.icon_kit;
|
|
56
|
-
return iconKit ? (
|
|
57
|
-
<FImage source={{ uri: iconKit }} style={styles.iconSensor} />
|
|
58
|
-
) : (
|
|
59
|
-
<IconFill name={svgMain} size={32} color={Colors.Red6} />
|
|
60
|
-
);
|
|
61
|
-
};
|
|
62
|
-
|
|
63
53
|
const isConnectedViaInternet =
|
|
64
54
|
status === undefined
|
|
65
55
|
? !serverDown && isNetworkConnected && sensor.is_connected
|
|
@@ -85,7 +75,7 @@ const ItemDevice = memo(
|
|
|
85
75
|
>
|
|
86
76
|
<View style={styles.boxIcon}>
|
|
87
77
|
<TouchableOpacity onPress={goToSensorDisplay}>
|
|
88
|
-
{
|
|
78
|
+
<IconComponent icon={sensor.icon} iconKit={sensor.icon_kit} />
|
|
89
79
|
</TouchableOpacity>
|
|
90
80
|
<ItemQuickAction sensor={sensor} unit={unit} />
|
|
91
81
|
</View>
|
|
@@ -3,6 +3,7 @@ import React, { memo } from 'react';
|
|
|
3
3
|
import { StyleSheet } from 'react-native';
|
|
4
4
|
import { Colors } from '../../configs';
|
|
5
5
|
import FImage from '../FImage';
|
|
6
|
+
import Text from '../Text';
|
|
6
7
|
|
|
7
8
|
// Priority: iconKit - icon - icon_outlined
|
|
8
9
|
const IconComponent = memo(
|
|
@@ -14,33 +15,38 @@ const IconComponent = memo(
|
|
|
14
15
|
size = 40,
|
|
15
16
|
style,
|
|
16
17
|
}) => {
|
|
17
|
-
let extraStyle = {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
let extraStyle = {
|
|
19
|
+
width: size,
|
|
20
|
+
height: size,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
if (iconKit) {
|
|
24
|
+
return (
|
|
25
|
+
<FImage
|
|
26
|
+
source={{ uri: iconKit }}
|
|
27
|
+
style={[styles.iconAction, extraStyle, style]}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
} else if (icon) {
|
|
31
|
+
return (
|
|
32
|
+
<IconFill
|
|
33
|
+
name={icon}
|
|
34
|
+
color={isSendingCommand ? Colors.TextGray : Colors.Green7}
|
|
35
|
+
size={24}
|
|
36
|
+
style={style}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
} else if (icon_outlined) {
|
|
40
|
+
return (
|
|
41
|
+
<IconOutline
|
|
42
|
+
name={icon_outlined}
|
|
43
|
+
color={isSendingCommand ? Colors.TextGray : Colors.Green7}
|
|
44
|
+
size={24}
|
|
45
|
+
style={style}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
23
48
|
}
|
|
24
|
-
return
|
|
25
|
-
<FImage
|
|
26
|
-
source={{ uri: iconKit }}
|
|
27
|
-
style={[styles.iconAction, extraStyle, style]}
|
|
28
|
-
/>
|
|
29
|
-
) : icon ? (
|
|
30
|
-
<IconFill
|
|
31
|
-
name={icon}
|
|
32
|
-
color={isSendingCommand ? Colors.TextGray : Colors.Green7}
|
|
33
|
-
size={24}
|
|
34
|
-
style={style}
|
|
35
|
-
/>
|
|
36
|
-
) : (
|
|
37
|
-
<IconOutline
|
|
38
|
-
name={icon_outlined}
|
|
39
|
-
color={isSendingCommand ? Colors.TextGray : Colors.Green7}
|
|
40
|
-
size={24}
|
|
41
|
-
style={style}
|
|
42
|
-
/>
|
|
43
|
-
);
|
|
49
|
+
return <Text />;
|
|
44
50
|
}
|
|
45
51
|
);
|
|
46
52
|
|
|
@@ -28,6 +28,7 @@ import { SCContext, useSCContextSelector } from '../../context';
|
|
|
28
28
|
import { Action } from '../../context/actionType';
|
|
29
29
|
|
|
30
30
|
const MediaPlayerDetail = ({
|
|
31
|
+
id,
|
|
31
32
|
uri,
|
|
32
33
|
cameraName,
|
|
33
34
|
thumbnail,
|
|
@@ -42,19 +43,23 @@ const MediaPlayerDetail = ({
|
|
|
42
43
|
height,
|
|
43
44
|
}) => {
|
|
44
45
|
const { setAction } = useContext(SCContext);
|
|
45
|
-
const isFirstOpenCamera = useSCContextSelector(
|
|
46
|
-
(state) => state.app
|
|
46
|
+
const { isFirstOpenCamera, camera_opened } = useSCContextSelector(
|
|
47
|
+
(state) => state.app
|
|
47
48
|
);
|
|
48
49
|
const t = useTranslations();
|
|
49
50
|
const [paused, setPaused] = useState(isPaused);
|
|
50
51
|
|
|
51
52
|
const onTapPause = useCallback(() => {
|
|
52
|
-
!isFirstOpenCamera
|
|
53
|
-
|
|
53
|
+
if (!isFirstOpenCamera) {
|
|
54
|
+
setPaused(false);
|
|
55
|
+
id && setAction(Action.CAMERA_STATUS_CHANGE, { id, status: true });
|
|
56
|
+
}
|
|
57
|
+
}, [id, isFirstOpenCamera, setAction]);
|
|
54
58
|
|
|
55
59
|
const onTapGoDetail = useCallback(() => {
|
|
56
60
|
if (!paused) {
|
|
57
61
|
setPaused(true);
|
|
62
|
+
id && setAction(Action.CAMERA_STATUS_CHANGE, { id, status: false });
|
|
58
63
|
} else {
|
|
59
64
|
goToPlayBack && goToPlayBack();
|
|
60
65
|
}
|
|
@@ -146,6 +151,13 @@ const MediaPlayerDetail = ({
|
|
|
146
151
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
147
152
|
}, [isFirstOpenCamera]);
|
|
148
153
|
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
if (id && !(camera_opened || []).some((item) => item === id)) {
|
|
156
|
+
setPaused(true);
|
|
157
|
+
}
|
|
158
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
159
|
+
}, [JSON.stringify(camera_opened), id]);
|
|
160
|
+
|
|
149
161
|
const source = !thumbnail || !thumbnail.uri ? Images.BgDevice : thumbnail;
|
|
150
162
|
return (
|
|
151
163
|
<View style={[styles.wrap, wrapStyles]}>
|
|
@@ -10,15 +10,16 @@ import ItemAddNew from '../../Device/ItemAddNew';
|
|
|
10
10
|
import styles from './styles';
|
|
11
11
|
|
|
12
12
|
const SubUnitFavorites = ({
|
|
13
|
-
unit,
|
|
14
13
|
isOwner,
|
|
15
|
-
|
|
14
|
+
unit,
|
|
15
|
+
favoriteDevices,
|
|
16
|
+
favoriteAutomates,
|
|
16
17
|
isGGHomeConnected,
|
|
17
18
|
wrapItemStyle,
|
|
18
19
|
}) => {
|
|
19
20
|
const t = useTranslations();
|
|
20
21
|
|
|
21
|
-
const { getStatus, serverDown } = useSensorsStatus(unit,
|
|
22
|
+
const { getStatus, serverDown } = useSensorsStatus(unit, favoriteDevices);
|
|
22
23
|
|
|
23
24
|
const handleOnAddNew = () => {
|
|
24
25
|
alert(t('feature_under_development'));
|
|
@@ -27,8 +28,8 @@ const SubUnitFavorites = ({
|
|
|
27
28
|
return (
|
|
28
29
|
<Section style={styles.noShadow}>
|
|
29
30
|
<View style={styles.boxDevices}>
|
|
30
|
-
{!!
|
|
31
|
-
|
|
31
|
+
{!!favoriteDevices &&
|
|
32
|
+
favoriteDevices.map((sensor, index) => (
|
|
32
33
|
<ItemDevice
|
|
33
34
|
key={`device-${sensor.id}`}
|
|
34
35
|
id={sensor.id}
|
|
@@ -47,8 +48,8 @@ const SubUnitFavorites = ({
|
|
|
47
48
|
wrapStyle={wrapItemStyle}
|
|
48
49
|
/>
|
|
49
50
|
))}
|
|
50
|
-
{!!
|
|
51
|
-
|
|
51
|
+
{!!favoriteAutomates &&
|
|
52
|
+
favoriteAutomates.map((automate) => (
|
|
52
53
|
<ItemOneTap
|
|
53
54
|
key={`automate-${automate.id}`}
|
|
54
55
|
isOwner={isOwner}
|
|
@@ -60,42 +60,40 @@ describe('test ShortDetail Subunit', () => {
|
|
|
60
60
|
user_id: 64,
|
|
61
61
|
},
|
|
62
62
|
isOwner: true,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
icon: 'caret-up',
|
|
69
|
-
id: 1,
|
|
70
|
-
key: '',
|
|
71
|
-
},
|
|
72
|
-
action2: null,
|
|
73
|
-
chip_id: 1,
|
|
74
|
-
description: null,
|
|
75
|
-
icon: '',
|
|
63
|
+
favoriteDevices: [
|
|
64
|
+
{
|
|
65
|
+
action: {
|
|
66
|
+
color: '#00979D',
|
|
67
|
+
icon: 'caret-up',
|
|
76
68
|
id: 1,
|
|
77
|
-
|
|
78
|
-
quick_action: null,
|
|
79
|
-
remote_control_options: {},
|
|
80
|
-
station: {},
|
|
81
|
-
status: null,
|
|
82
|
-
status2: null,
|
|
69
|
+
key: '',
|
|
83
70
|
},
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
71
|
+
action2: null,
|
|
72
|
+
chip_id: 1,
|
|
73
|
+
description: null,
|
|
74
|
+
icon: '',
|
|
75
|
+
id: 1,
|
|
76
|
+
name: 'People Counting',
|
|
77
|
+
quick_action: null,
|
|
78
|
+
remote_control_options: {},
|
|
79
|
+
station: {},
|
|
80
|
+
status: null,
|
|
81
|
+
status2: null,
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
favoriteAutomates: [
|
|
85
|
+
{
|
|
86
|
+
id: 1,
|
|
87
|
+
user: 6,
|
|
88
|
+
type: 'one_tap',
|
|
89
|
+
activate_at: '2021-09-17T05:30:00Z',
|
|
90
|
+
script: {
|
|
91
|
+
name: 'Joshua Ray',
|
|
92
|
+
icon: '',
|
|
93
|
+
icon_kit: '',
|
|
96
94
|
},
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
},
|
|
96
|
+
],
|
|
99
97
|
isGGHomeConnected: true,
|
|
100
98
|
};
|
|
101
99
|
});
|
|
@@ -108,8 +106,8 @@ describe('test ShortDetail Subunit', () => {
|
|
|
108
106
|
const devices = instance.findAllByType(ItemDevice);
|
|
109
107
|
const automates = instance.findAllByType(ItemOneTap);
|
|
110
108
|
const itemAddNew = instance.findAllByType(ItemAddNew);
|
|
111
|
-
expect(devices).toHaveLength(props.
|
|
112
|
-
expect(automates).toHaveLength(props.
|
|
109
|
+
expect(devices).toHaveLength(props.favoriteDevices.length);
|
|
110
|
+
expect(automates).toHaveLength(props.favoriteAutomates.length);
|
|
113
111
|
expect(itemAddNew).toHaveLength(1);
|
|
114
112
|
|
|
115
113
|
await act(async () => {
|
package/src/configs/API.js
CHANGED
|
@@ -39,6 +39,8 @@ const API = {
|
|
|
39
39
|
SCConfig.apiRoot + `/property_manager/units/${id}/add_gateway/`,
|
|
40
40
|
SENSORS_STATUS: (id) =>
|
|
41
41
|
SCConfig.apiRoot + `/property_manager/units/${id}/sensors_status/`,
|
|
42
|
+
FAVOURITE_DEVICES: (id) =>
|
|
43
|
+
SCConfig.apiRoot + `/property_manager/units/${id}/favourite_devices/`,
|
|
42
44
|
},
|
|
43
45
|
SUB_UNIT: {
|
|
44
46
|
REMOVE_SUB_UNIT: (unitId, id) =>
|
|
@@ -128,6 +130,8 @@ const API = {
|
|
|
128
130
|
SCConfig.apiRoot + '/property_manager/automate/multi_unit/',
|
|
129
131
|
ACTIVITY_LOG: (id) =>
|
|
130
132
|
SCConfig.apiRoot + `/property_manager/automate/${id}/logs/`,
|
|
133
|
+
STARRED_SCRIPTS: () =>
|
|
134
|
+
SCConfig.apiRoot + '/property_manager/automate/starred_scripts/',
|
|
131
135
|
},
|
|
132
136
|
GOOGLE_HOME: {
|
|
133
137
|
CHECK_SEND_EMAIL: () =>
|
package/src/configs/Constants.js
CHANGED
|
@@ -239,6 +239,26 @@ export const TESTID = {
|
|
|
239
239
|
CONTROL_BUTTON: 'CONTROL_BUTTON',
|
|
240
240
|
},
|
|
241
241
|
|
|
242
|
+
// ConnectWifiWarning
|
|
243
|
+
CONNECT_WIFI_WARNING: {
|
|
244
|
+
BUTTON_BOTTOM: 'BUTTON_BOTTOM',
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
// GatewayWifiList
|
|
248
|
+
GATEWAY_WIFI_LIST: {
|
|
249
|
+
BUTTON_POPUP: 'BUTTON_POPUP',
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
//SetupGatewaywifi
|
|
253
|
+
SET_UP_GATEWAY_WIFI: {
|
|
254
|
+
BUTTON_ALERT: 'BUTTON_ALERT',
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
//GroupButtonByType
|
|
258
|
+
GROUP_BUTTON_TYPE: {
|
|
259
|
+
BUTTON_BOTTOM: 'BUTTON_BOTTOM',
|
|
260
|
+
},
|
|
261
|
+
|
|
242
262
|
// sub unit
|
|
243
263
|
SUB_UNIT_FULL_CAMERA: 'SUB_UNIT_FULL_CAMERA',
|
|
244
264
|
SUB_UNIT_CAMERA_VIEW: 'SUB_UNIT_CAMERA_VIEW',
|
|
@@ -254,6 +274,7 @@ export const TESTID = {
|
|
|
254
274
|
// NavBar
|
|
255
275
|
NAVBAR_ICON_BARS: 'NAVBAR_ICON_BARS',
|
|
256
276
|
NAVBAR_MENU_ACTION_MORE: 'NAVBAR_MENU_ACTION_MORE',
|
|
277
|
+
NAVBAR_ON_SNAP_ITEM: 'NAVBAR_ON_SNAP_ITEM',
|
|
257
278
|
|
|
258
279
|
// device
|
|
259
280
|
HORIZONTAL_BAR_CHART: 'HORIZONTAL_BAR_CHART',
|
|
@@ -9,6 +9,14 @@ export const Action = {
|
|
|
9
9
|
IS_CONNECT_WIFI_GATEWAY: 'IS_CONNECT_WIFI_GATEWAY',
|
|
10
10
|
SET_BLUETOOTH_STATE: 'SET_BLUETOOTH_STATE',
|
|
11
11
|
SET_NETWORK_CONNECTED: 'SET_NETWORK_CONNECTED',
|
|
12
|
+
CAMERA_STATUS_CHANGE: 'CAMERA_STATUS_CHANGE',
|
|
13
|
+
CLOSE_ALL_CAMERA: 'CLOSE_ALL_CAMERA',
|
|
14
|
+
SET_FAVORITE_DEVICES: 'SET_FAVORITE_DEVICES',
|
|
15
|
+
ADD_DEVICE_TO_FAVORITES: 'ADD_DEVICE_TO_FAVORITES',
|
|
16
|
+
REMOVE_DEVICE_FROM_FAVORITES: 'REMOVE_DEVICE_FROM_FAVORITES',
|
|
17
|
+
SET_STARRED_SCRIPTS: 'SET_STARRED_SCRIPTS',
|
|
18
|
+
STAR_SCRIPT: 'STAR_SCRIPT',
|
|
19
|
+
UNSTAR_SCRIPT: 'UNSTAR_SCRIPT',
|
|
12
20
|
};
|
|
13
21
|
|
|
14
22
|
export type AuthData = {
|
|
@@ -40,6 +48,14 @@ export type ListAction = {
|
|
|
40
48
|
station_name: string;
|
|
41
49
|
}[];
|
|
42
50
|
|
|
51
|
+
export type UnitType = {
|
|
52
|
+
favoriteDeviceIds: [];
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export type AutomateType = {
|
|
56
|
+
starredScriptIds: [];
|
|
57
|
+
};
|
|
58
|
+
|
|
43
59
|
export type ActionType = keyof typeof Action;
|
|
44
60
|
|
|
45
61
|
export type ActionDataMap = {
|
|
@@ -56,4 +72,5 @@ export type AppType = {
|
|
|
56
72
|
isConnectWifiGateway: boolean;
|
|
57
73
|
isBluetoothEnabled: boolean;
|
|
58
74
|
isNetworkConnected: boolean;
|
|
75
|
+
camera_opened: any[];
|
|
59
76
|
};
|
package/src/context/mockStore.ts
CHANGED
|
@@ -25,6 +25,12 @@ export const mockDataStore: ContextData = {
|
|
|
25
25
|
barStyle: '',
|
|
26
26
|
},
|
|
27
27
|
listAction: [],
|
|
28
|
+
unit: {
|
|
29
|
+
favoriteDeviceIds: [],
|
|
30
|
+
},
|
|
31
|
+
automate: {
|
|
32
|
+
starredScriptIds: [],
|
|
33
|
+
},
|
|
28
34
|
};
|
|
29
35
|
|
|
30
36
|
export const mockSCStore = (data: ContextData): ContextData => {
|
|
@@ -53,5 +59,17 @@ export const mockSCStore = (data: ContextData): ContextData => {
|
|
|
53
59
|
isBluetoothEnabled: true,
|
|
54
60
|
isNetworkConnected: true,
|
|
55
61
|
},
|
|
62
|
+
unit: {
|
|
63
|
+
favoriteDeviceIds: [
|
|
64
|
+
...mockDataStore.unit.favoriteDeviceIds,
|
|
65
|
+
...(data?.unit?.favoriteDeviceIds || []),
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
automate: {
|
|
69
|
+
starredScriptIds: [
|
|
70
|
+
...mockDataStore.automate.starredScriptIds,
|
|
71
|
+
...(data?.automate?.starredScriptIds || []),
|
|
72
|
+
],
|
|
73
|
+
},
|
|
56
74
|
};
|
|
57
75
|
};
|
package/src/context/reducer.ts
CHANGED
|
@@ -7,8 +7,11 @@ import {
|
|
|
7
7
|
Action,
|
|
8
8
|
ListDevice,
|
|
9
9
|
ListAction,
|
|
10
|
+
UnitType,
|
|
11
|
+
AutomateType,
|
|
10
12
|
AppType,
|
|
11
13
|
} from './actionType';
|
|
14
|
+
import { uniq } from 'lodash';
|
|
12
15
|
|
|
13
16
|
export type ContextData = {
|
|
14
17
|
auth: AuthData;
|
|
@@ -16,6 +19,8 @@ export type ContextData = {
|
|
|
16
19
|
listDevice: ListDevice;
|
|
17
20
|
listAction: ListAction;
|
|
18
21
|
statusBar: StatusBar;
|
|
22
|
+
unit: UnitType;
|
|
23
|
+
automate: AutomateType;
|
|
19
24
|
app: AppType;
|
|
20
25
|
};
|
|
21
26
|
|
|
@@ -37,12 +42,19 @@ export const initialState = {
|
|
|
37
42
|
statusBar: {} as StatusBar,
|
|
38
43
|
listDevice: {} as ListDevice,
|
|
39
44
|
listAction: [] as ListAction,
|
|
45
|
+
unit: {
|
|
46
|
+
favoriteDeviceIds: [],
|
|
47
|
+
},
|
|
48
|
+
automate: {
|
|
49
|
+
starredScriptIds: [],
|
|
50
|
+
},
|
|
40
51
|
app: {
|
|
41
52
|
isFirstOpenCamera: true,
|
|
42
53
|
isLavidaSource: false,
|
|
43
54
|
isConnectWifiGateway: false,
|
|
44
55
|
isBluetoothEnabled: false,
|
|
45
56
|
isNetworkConnected: false,
|
|
57
|
+
camera_opened: [],
|
|
46
58
|
},
|
|
47
59
|
};
|
|
48
60
|
|
|
@@ -137,6 +149,96 @@ export const reducer = (currentState: ContextData, action: Action) => {
|
|
|
137
149
|
},
|
|
138
150
|
};
|
|
139
151
|
}
|
|
152
|
+
|
|
153
|
+
case Action.CAMERA_STATUS_CHANGE:
|
|
154
|
+
const { id, status } = payload;
|
|
155
|
+
const arrCameraTemp = currentState.app.camera_opened || [];
|
|
156
|
+
if (status) {
|
|
157
|
+
if (arrCameraTemp.length >= 4) {
|
|
158
|
+
arrCameraTemp.splice(0, 1);
|
|
159
|
+
}
|
|
160
|
+
arrCameraTemp.push(id);
|
|
161
|
+
} else {
|
|
162
|
+
const indexCameraRemoved = arrCameraTemp.findIndex(
|
|
163
|
+
(item) => item === id
|
|
164
|
+
);
|
|
165
|
+
arrCameraTemp.splice(indexCameraRemoved, 1);
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
...currentState,
|
|
169
|
+
app: {
|
|
170
|
+
...currentState.app,
|
|
171
|
+
camera_opened: arrCameraTemp,
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
case Action.CLOSE_ALL_CAMERA:
|
|
176
|
+
return {
|
|
177
|
+
...currentState,
|
|
178
|
+
app: {
|
|
179
|
+
...currentState.app,
|
|
180
|
+
camera_opened: [],
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
case Action.SET_FAVORITE_DEVICES:
|
|
185
|
+
return {
|
|
186
|
+
...currentState,
|
|
187
|
+
unit: {
|
|
188
|
+
...currentState.unit,
|
|
189
|
+
favoriteDeviceIds: payload,
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
case Action.ADD_DEVICE_TO_FAVORITES:
|
|
193
|
+
return {
|
|
194
|
+
...currentState,
|
|
195
|
+
unit: {
|
|
196
|
+
...currentState.unit,
|
|
197
|
+
favoriteDeviceIds: uniq(
|
|
198
|
+
currentState.unit.favoriteDeviceIds.concat(payload)
|
|
199
|
+
),
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
case Action.REMOVE_DEVICE_FROM_FAVORITES:
|
|
203
|
+
return {
|
|
204
|
+
...currentState,
|
|
205
|
+
unit: {
|
|
206
|
+
...currentState.unit,
|
|
207
|
+
favoriteDeviceIds: currentState.unit.favoriteDeviceIds.filter(
|
|
208
|
+
(id) => id !== payload
|
|
209
|
+
),
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
case Action.SET_STARRED_SCRIPTS:
|
|
214
|
+
return {
|
|
215
|
+
...currentState,
|
|
216
|
+
automate: {
|
|
217
|
+
...currentState.automate,
|
|
218
|
+
starredScriptIds: payload,
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
case Action.STAR_SCRIPT:
|
|
222
|
+
return {
|
|
223
|
+
...currentState,
|
|
224
|
+
automate: {
|
|
225
|
+
...currentState.automate,
|
|
226
|
+
starredScriptIds: uniq(
|
|
227
|
+
currentState.automate.starredScriptIds.concat(payload)
|
|
228
|
+
),
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
case Action.UNSTAR_SCRIPT:
|
|
232
|
+
return {
|
|
233
|
+
...currentState,
|
|
234
|
+
automate: {
|
|
235
|
+
...currentState.automate,
|
|
236
|
+
starredScriptIds: currentState.automate.starredScriptIds.filter(
|
|
237
|
+
(id) => id !== payload
|
|
238
|
+
),
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
|
|
140
242
|
default:
|
|
141
243
|
return currentState;
|
|
142
244
|
}
|
|
@@ -225,6 +225,7 @@ export async function sendCommandOverGoogleHome(sensor, action, data) {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
const { success } = await axiosPost(API.SENSOR.ACTIVITY_LOG(), {
|
|
228
|
+
sensor_id: sensor.id,
|
|
228
229
|
action_id: action.id,
|
|
229
230
|
message: 'Trigger by user action with google home',
|
|
230
231
|
});
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import React, { memo, useCallback } from 'react';
|
|
1
|
+
import React, { memo, useCallback, useEffect, useContext } from 'react';
|
|
2
2
|
import { TouchableOpacity } from 'react-native';
|
|
3
3
|
import { createStackNavigator } from '@react-navigation/stack';
|
|
4
4
|
import { useNavigation } from '@react-navigation/core';
|
|
5
5
|
import { Icon } from '@ant-design/react-native';
|
|
6
|
+
import { SCContext } from '../context';
|
|
7
|
+
import { Action } from '../context/actionType';
|
|
6
8
|
|
|
7
9
|
import Routes from '../utils/Route';
|
|
8
10
|
import { screenOptions } from './utils';
|
|
@@ -11,16 +13,29 @@ import { Colors, Theme } from '../configs';
|
|
|
11
13
|
import Automate from '../screens/Automate';
|
|
12
14
|
import MultiUnits from '../screens/Automate/MultiUnits';
|
|
13
15
|
|
|
16
|
+
import { axiosGet } from '../utils/Apis/axios';
|
|
17
|
+
import { API } from '../configs';
|
|
18
|
+
|
|
14
19
|
const Stack = createStackNavigator();
|
|
15
20
|
|
|
16
21
|
const AutomateStack = memo(() => {
|
|
17
22
|
const t = useTranslations();
|
|
18
23
|
const navigation = useNavigation();
|
|
24
|
+
const { setAction } = useContext(SCContext);
|
|
19
25
|
|
|
20
26
|
const toggleDrawer = useCallback(() => {
|
|
21
27
|
navigation.toggleDrawer();
|
|
22
28
|
}, [navigation]);
|
|
23
29
|
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const fetchStarredScripts = async () => {
|
|
32
|
+
const { success, data } = await axiosGet(API.AUTOMATE.STARRED_SCRIPTS());
|
|
33
|
+
success && setAction(Action.SET_STARRED_SCRIPTS, data);
|
|
34
|
+
};
|
|
35
|
+
fetchStarredScripts();
|
|
36
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
37
|
+
}, []);
|
|
38
|
+
|
|
24
39
|
return (
|
|
25
40
|
<Stack.Navigator
|
|
26
41
|
screenOptions={{
|