@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.
Files changed (73) hide show
  1. package/assets/images/Device/current-state.svg +3 -0
  2. package/assets/images/Device/door-state.svg +3 -0
  3. package/assets/images/Device/wind-strength.svg +12 -0
  4. package/package.json +1 -1
  5. package/src/commons/Action/ItemQuickAction.js +1 -0
  6. package/src/commons/Action/__test__/ItemQuickAction.test.js +49 -2
  7. package/src/commons/ActionGroup/OnOffTemplate/OnOffSimpleTemplateStyle.js +2 -1
  8. package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +31 -11
  9. package/src/commons/ActionGroup/OptionsDropdownActionTemplateStyle.js +5 -2
  10. package/src/commons/ActionGroup/TimerActionTemplate.js +14 -10
  11. package/src/commons/ActionGroup/TimerActionTemplateStyles.js +12 -0
  12. package/src/commons/ActionGroup/TwoButtonTemplate/TwoButtonTemplateStyles.js +55 -0
  13. package/src/commons/ActionGroup/TwoButtonTemplate/index.js +170 -0
  14. package/src/commons/ActionGroup/__test__/TimerActionTemplate.test.js +1 -1
  15. package/src/commons/ActionGroup/__test__/TwoButtonTemplate.test.js +112 -0
  16. package/src/commons/ActionGroup/index.js +3 -0
  17. package/src/commons/CameraDevice/index.js +6 -1
  18. package/src/commons/Device/HistoryChart.js +2 -2
  19. package/src/commons/Device/ItemDevice.js +3 -13
  20. package/src/commons/IconComponent/index.js +32 -26
  21. package/src/commons/MediaPlayerDetail/index.js +16 -4
  22. package/src/commons/SubUnit/Favorites/index.js +8 -7
  23. package/src/commons/SubUnit/__test__/Favorites.test.js +33 -35
  24. package/src/configs/API.js +4 -0
  25. package/src/configs/Constants.js +21 -0
  26. package/src/context/actionType.ts +17 -0
  27. package/src/context/mockStore.ts +18 -0
  28. package/src/context/reducer.ts +102 -0
  29. package/src/iot/RemoteControl/Bluetooth.js +2 -0
  30. package/src/iot/RemoteControl/GoogleHome.js +1 -0
  31. package/src/navigations/AutomateStack.js +16 -1
  32. package/src/navigations/UnitStack.js +27 -0
  33. package/src/screens/AddNewAction/Device/__test__/index.test.js +1 -1
  34. package/src/screens/AddNewAction/SelectAction.js +13 -15
  35. package/src/screens/AddNewAction/__test__/SelectAction.test.js +0 -7
  36. package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +2 -0
  37. package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +2 -0
  38. package/src/screens/AddNewGateway/PlugAndPlay/__test__/ConnectWifiWarning.test.js +9 -0
  39. package/src/screens/AddNewGateway/PlugAndPlay/__test__/GatewayWifiList.test.js +15 -0
  40. package/src/screens/AddNewGateway/SetupGatewayWifi.js +6 -1
  41. package/src/screens/AddNewGateway/__test__/SetupGateway.test.js +34 -0
  42. package/src/screens/AllCamera/index.js +1 -0
  43. package/src/screens/Automate/MultiUnits.js +9 -9
  44. package/src/screens/Automate/index.js +21 -20
  45. package/src/screens/Device/__test__/detail.test.js +119 -86
  46. package/src/screens/Device/detail.js +38 -51
  47. package/src/screens/Device/hooks/useFavoriteDevice.js +38 -0
  48. package/src/screens/EmergencyContacts/EmergencyContactsList.js +1 -1
  49. package/src/screens/EmergencyContacts/EmergencyContactsSelectContacts.js +41 -44
  50. package/src/screens/EmergencyContacts/__test__/EmergencyContactList.test.js +1 -0
  51. package/src/screens/EmergencyContacts/__test__/EmergencyContactsSelectContacts.test.js +18 -19
  52. package/src/screens/Notification/__test__/NotificationItem.test.js +64 -53
  53. package/src/screens/Notification/components/NotificationItem.js +13 -4
  54. package/src/screens/ScriptDetail/__test__/index.test.js +15 -4
  55. package/src/screens/ScriptDetail/hooks/useStarredScript.js +32 -0
  56. package/src/screens/ScriptDetail/index.js +11 -20
  57. package/src/screens/SharedUnit/__test__/TabHeader.test.js +5 -0
  58. package/src/screens/Sharing/SelectUser.js +3 -23
  59. package/src/screens/Sharing/__test__/SelectUser.test.js +12 -80
  60. package/src/screens/SmartIr/__test__/GroupButtonByType.test.js +33 -0
  61. package/src/screens/SmartIr/components/GroupButtonByType/GroupButtonByType.js +2 -0
  62. package/src/screens/Unit/ChooseLocation.js +5 -0
  63. package/src/screens/Unit/Detail.js +33 -37
  64. package/src/screens/Unit/ManageUnit.js +21 -20
  65. package/src/screens/Unit/ManageUnitStyles.js +1 -0
  66. package/src/screens/Unit/SelectAddress.js +8 -2
  67. package/src/screens/Unit/Summaries.js +12 -15
  68. package/src/screens/Unit/__test__/Detail.test.js +25 -0
  69. package/src/screens/Unit/components/__test__/Header.test.js +32 -0
  70. package/src/screens/Unit/hook/useFavorites.js +28 -0
  71. package/src/utils/Apis/axios.js +7 -2
  72. package/src/utils/I18n/translations/en.json +1 -4
  73. 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.utc().toDate()}
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.utc().toDate()}
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 { IconFill, IconOutline } from '@ant-design/icons-react-native';
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 FImage from '../../commons/FImage';
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
- {displayIconSensor()}
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
- if (size) {
19
- extraStyle = {
20
- width: size,
21
- height: size,
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 iconKit ? (
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.isFirstOpenCamera
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 && setPaused(false);
53
- }, [isFirstOpenCamera]);
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
- favorites,
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, favorites?.devices);
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
- {!!favorites.devices &&
31
- favorites.devices.map((sensor, index) => (
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
- {!!favorites.automates &&
51
- favorites.automates.map((automate) => (
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
- favorites: {
64
- devices: [
65
- {
66
- action: {
67
- color: '#00979D',
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
- name: 'People Counting',
78
- quick_action: null,
79
- remote_control_options: {},
80
- station: {},
81
- status: null,
82
- status2: null,
69
+ key: '',
83
70
  },
84
- ],
85
- automates: [
86
- {
87
- id: 1,
88
- user: 6,
89
- type: 'one_tap',
90
- activate_at: '2021-09-17T05:30:00Z',
91
- script: {
92
- name: 'Joshua Ray',
93
- icon: '',
94
- icon_kit: '',
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.favorites.devices.length);
112
- expect(automates).toHaveLength(props.favorites.automates.length);
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 () => {
@@ -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: () =>
@@ -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
  };
@@ -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
  };
@@ -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
  }
@@ -103,7 +103,9 @@ export const sendCommandOverBluetooth = async (
103
103
  command: action.key,
104
104
  password: bluetooth ? bluetooth.password : '',
105
105
  data,
106
+ sensor: sensor.id,
106
107
  user: userID,
108
+ sensorId: sensor.id,
107
109
  });
108
110
  return result;
109
111
  };
@@ -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={{