@eohjsc/react-native-smart-city 0.3.92 → 0.3.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 (68) hide show
  1. package/package.json +5 -1
  2. package/src/commons/ActionGroup/SliderRangeTemplate.js +2 -2
  3. package/src/commons/AlertAction/index.js +5 -0
  4. package/src/commons/BottomButtonView/index.js +22 -4
  5. package/src/commons/Button/index.js +5 -0
  6. package/src/commons/Device/ConnectedViewHeader.js +0 -1
  7. package/src/commons/Device/Emergency/EmergencyDetail.js +4 -2
  8. package/src/commons/Device/Emergency/__test__/EmergencyDetail.test.js +4 -2
  9. package/src/commons/Device/ProgressBar/index.js +3 -1
  10. package/src/commons/Device/ProgressBar/styles.js +1 -4
  11. package/src/commons/Device/WindSpeed/Anemometer/index.js +1 -1
  12. package/src/commons/Header/HeaderCustom.js +8 -18
  13. package/src/commons/SubUnit/OneTap/ItemOneTap.js +5 -48
  14. package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +6 -15
  15. package/src/commons/SubUnit/OneTap/index.js +3 -3
  16. package/src/commons/ViewButtonBottom/index.js +32 -4
  17. package/src/configs/API.js +3 -0
  18. package/src/configs/AccessibilityLabel.js +1 -0
  19. package/src/configs/BLE.js +1 -0
  20. package/src/context/actionType.ts +2 -1
  21. package/src/context/mockStore.ts +1 -0
  22. package/src/context/reducer.ts +12 -1
  23. package/src/hooks/Explore/useKeyboardAnimated.js +10 -4
  24. package/src/hooks/IoT/useBluetoothConnection.js +14 -26
  25. package/src/hooks/useMqtt.js +95 -0
  26. package/src/iot/Monitor.js +2 -1
  27. package/src/iot/RemoteControl/Bluetooth.js +56 -19
  28. package/src/iot/RemoteControl/__test__/Bluetooth.test.js +140 -0
  29. package/src/iot/mqtt.js +233 -0
  30. package/src/navigations/UnitStack.js +11 -3
  31. package/src/screens/AddLocationMaps/index.js +18 -16
  32. package/src/screens/AddLocationMaps/indexStyle.js +3 -0
  33. package/src/screens/Automate/AddNewAction/NewActionWrapper.js +3 -6
  34. package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +29 -29
  35. package/src/screens/Automate/AddNewAction/__test__/SetupSensor.test.js +45 -39
  36. package/src/screens/Automate/AddNewAutoSmart/AddAutomationTypeSmart.js +25 -0
  37. package/src/screens/{AddNewAutoSmart/index.js → Automate/AddNewAutoSmart/AddTypeSmart.js} +16 -51
  38. package/src/screens/Automate/AddNewAutoSmart/AddUnknownTypeSmart.js +29 -0
  39. package/src/screens/{AddNewAutoSmart → Automate/AddNewAutoSmart}/__test__/AddNewAutoSmart.test.js +11 -11
  40. package/src/screens/{AddNewAutoSmart → Automate/AddNewAutoSmart}/styles/AddNewAutoSmartStyles.js +1 -1
  41. package/src/screens/Automate/Components/InputNameStyles.js +1 -1
  42. package/src/screens/Automate/EditActionsList/__tests__/index.test.js +11 -25
  43. package/src/screens/Automate/EditActionsList/index.js +32 -33
  44. package/src/screens/Automate/MultiUnits.js +1 -1
  45. package/src/screens/Automate/ScriptDetail/__test__/index.test.js +42 -3
  46. package/src/screens/Automate/ScriptDetail/index.js +21 -7
  47. package/src/screens/Automate/__test__/MultiUnits.test.js +1 -1
  48. package/src/screens/Automate/__test__/index.test.js +1 -1
  49. package/src/screens/Automate/index.js +1 -1
  50. package/src/screens/Device/__test__/detail.test.js +1 -1
  51. package/src/screens/Device/__test__/mqttDetail.test.js +599 -0
  52. package/src/screens/Device/components/SensorDisplayItem.js +1 -7
  53. package/src/screens/Device/detail.js +64 -30
  54. package/src/screens/Device/hooks/useDeviceWatchConfigControl.js +13 -3
  55. package/src/screens/SelectUnit/__test__/index.test.js +8 -13
  56. package/src/screens/SmartAccount/__test__/SmartAccount.test.js +8 -4
  57. package/src/screens/SmartAccount/index.js +8 -9
  58. package/src/screens/SmartAccount/style.js +8 -7
  59. package/src/screens/Unit/Detail.js +4 -19
  60. package/src/screens/Unit/Summaries.js +6 -17
  61. package/src/screens/Unit/__test__/Summaries.test.js +2 -2
  62. package/src/utils/FactoryGateway.js +525 -0
  63. package/src/utils/I18n/translations/en.json +5 -1
  64. package/src/utils/I18n/translations/vi.json +5 -2
  65. package/src/utils/Route/index.js +2 -1
  66. package/src/utils/Utils.js +11 -0
  67. package/src/commons/Device/SensorConnectedStatus.js +0 -56
  68. package/src/commons/Device/__test__/SensorConnectedStatus.test.js +0 -29
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eohjsc/react-native-smart-city",
3
3
  "title": "React Native Smart Home",
4
- "version": "0.3.92",
4
+ "version": "0.3.93",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -129,6 +129,7 @@
129
129
  "@testing-library/react-hooks": "^6.0.0",
130
130
  "apisauce": "^2.1.5",
131
131
  "axios": "^0.19.2",
132
+ "base-64": "^1.0.0",
132
133
  "deprecated-react-native-prop-types": "^2.3.0",
133
134
  "dotenv": "^8.2.0",
134
135
  "google-libphonenumber": "^3.2.10",
@@ -143,8 +144,10 @@
143
144
  "patch-package": "^6.2.2",
144
145
  "pluralize": "^8.0.0",
145
146
  "postinstall": "^0.7.0",
147
+ "precompiled-mqtt": "^4.3.14-beta",
146
148
  "pusher-js": "^7.4.0",
147
149
  "pusher-js-auth": "^4.0.1",
150
+ "python-struct": "^1.1.3",
148
151
  "querystring": "^0.2.0",
149
152
  "react-content-loader": "^6.0.3",
150
153
  "react-dom": "^17.0.1",
@@ -161,6 +164,7 @@
161
164
  "react-native-calendars": "^1.1266.0",
162
165
  "react-native-chart-kit": "^6.5.0",
163
166
  "react-native-credit-card-input": "^0.4.1",
167
+ "react-native-crypto-aes-cbc": "^1.1.1",
164
168
  "react-native-dash": "^0.0.11",
165
169
  "react-native-deep-linking": "^2.2.0",
166
170
  "react-native-device-info": "^10.3.0",
@@ -77,8 +77,8 @@ const SliderRangeTemplate = memo(
77
77
  doAction(
78
78
  action_data,
79
79
  JSON.stringify({
80
- value_brness: parseInt(value),
81
- value: parseInt(value),
80
+ value_brness: parseInt(value, 10),
81
+ value: parseInt(value, 10),
82
82
  })
83
83
  );
84
84
  }, 300);
@@ -80,6 +80,8 @@ const AlertAction = ({
80
80
  styleButtonLeft={boxLeftButtonStyle}
81
81
  styleButtonRight={boxRightButtonStyle}
82
82
  accessibilityLabelPrefix={accessibilityLabelPrefix}
83
+ wrapStyle={styles.wrapViewButtonStyle}
84
+ disableKeyBoardAnimated
83
85
  />
84
86
  </View>
85
87
  </Animated.View>
@@ -121,6 +123,9 @@ const styles = StyleSheet.create({
121
123
  descriptionText: {
122
124
  paddingHorizontal: 16,
123
125
  },
126
+ wrapViewButtonStyle: {
127
+ position: 'relative',
128
+ },
124
129
  });
125
130
 
126
131
  export default AlertAction;
@@ -1,7 +1,8 @@
1
- import React, { memo } from 'react';
2
- import { View, StyleSheet } from 'react-native';
1
+ import React, { memo, useState, useEffect } from 'react';
2
+ import { StyleSheet, Animated, Easing, Platform } from 'react-native';
3
3
 
4
4
  import { AccessibilityLabel } from '../../configs/Constants';
5
+ import useKeyboardAnimated from '../../hooks/Explore/useKeyboardAnimated';
5
6
  import Button from '../Button';
6
7
 
7
8
  const BottomButtonView = memo(
@@ -20,13 +21,28 @@ const BottomButtonView = memo(
20
21
  typeMain = 'primary',
21
22
  typeSecondary = 'cancel',
22
23
  accessibilityLabelPrefix = '',
24
+ disableBackgroundMainButton = false,
25
+ disableBackgroundSecondButton = false,
23
26
  }) => {
27
+ const transY = useKeyboardAnimated();
28
+ const [keyboardAnim] = useState(new Animated.Value(0));
29
+
30
+ useEffect(() => {
31
+ Animated.timing(keyboardAnim, {
32
+ toValue: transY,
33
+ duration: Platform.OS === 'ios' ? 220 : 0,
34
+ easing: Easing.linear(),
35
+ useNativeDriver: false,
36
+ }).start();
37
+ }, [keyboardAnim, transY]);
38
+
24
39
  return (
25
- <View
40
+ <Animated.View
26
41
  style={[
27
42
  typeMain === 'CardShadow'
28
43
  ? styleCustom.container1
29
44
  : styleCustom.container,
45
+ { bottom: keyboardAnim },
30
46
  rowButton && styleCustom.horizontalContainer,
31
47
  style,
32
48
  ]}
@@ -42,6 +58,7 @@ const BottomButtonView = memo(
42
58
  textType={textTypeMain}
43
59
  style={rowButton && styleCustom.buttonMainRow}
44
60
  accessibilityLabel={`${accessibilityLabelPrefix}${AccessibilityLabel.BOTTOM_VIEW_MAIN}`}
61
+ disableBackground={disableBackgroundMainButton}
45
62
  />
46
63
  )}
47
64
  {secondaryTitle && (
@@ -56,9 +73,10 @@ const BottomButtonView = memo(
56
73
  : styleCustom.buttonSecondaryColumn
57
74
  }
58
75
  accessibilityLabel={`${accessibilityLabelPrefix}${AccessibilityLabel.BOTTOM_VIEW_SECONDARY}`}
76
+ disableBackground={disableBackgroundSecondButton}
59
77
  />
60
78
  )}
61
- </View>
79
+ </Animated.View>
62
80
  );
63
81
  }
64
82
  );
@@ -133,6 +133,7 @@ export default ({
133
133
  textSemiBold = true,
134
134
  style,
135
135
  accessibilityLabel,
136
+ disableBackground = false,
136
137
  }) => {
137
138
  const styleButton = ButtonStyle[type];
138
139
  const textColor = TextColor[type];
@@ -153,6 +154,7 @@ export default ({
153
154
  isCardShadow && styles.buttonLeft,
154
155
  styleButton,
155
156
  style,
157
+ disableBackground && styles.disableBackground,
156
158
  ]}
157
159
  onPress={onPress}
158
160
  disabled={isDisabled}
@@ -202,4 +204,7 @@ const styles = StyleSheet.create({
202
204
  alignItems: 'flex-start',
203
205
  backgroundColor: Colors.Gray1,
204
206
  },
207
+ disableBackground: {
208
+ backgroundColor: Colors.Transparent,
209
+ },
205
210
  });
@@ -1,7 +1,6 @@
1
1
  import React, { memo } from 'react';
2
2
  import { StyleSheet, View } from 'react-native';
3
3
  import { IconOutline } from '@ant-design/icons-react-native';
4
-
5
4
  import { useTranslations } from '../../hooks/Common/useTranslations';
6
5
  import { Colors } from '../../configs';
7
6
  import Text from '../../commons/Text';
@@ -9,7 +9,6 @@ import { RowUser } from '../../RowUser';
9
9
  import { IconFill, IconOutline } from '@ant-design/icons-react-native';
10
10
  import { useEmeragencyContacts } from '../../../screens/EmergencyContacts/hook';
11
11
  import { useIsFocused } from '@react-navigation/native';
12
- import _ from 'lodash';
13
12
 
14
13
  const { standardizeHeight } = standardizeCameraScreenSize(
15
14
  Device.screenWidth + 86
@@ -17,6 +16,7 @@ const { standardizeHeight } = standardizeCameraScreenSize(
17
16
 
18
17
  const EmergencyDetail = memo(({ item }) => {
19
18
  const t = useTranslations();
19
+ const { uri, preview_uri } = item?.configuration?.camera;
20
20
  const groupId = item?.configuration?.device?.group?.id;
21
21
  const isFocused = useIsFocused();
22
22
  const { listContacts, getListContacts } = useEmeragencyContacts();
@@ -35,8 +35,10 @@ const EmergencyDetail = memo(({ item }) => {
35
35
  <View style={styles.first}>
36
36
  <Text type="H4">{t('camera')}</Text>
37
37
  <MediaPlayer
38
- uri={_.get(item, 'configuration.uri', '')}
38
+ uri={uri}
39
+ previewUri={preview_uri}
39
40
  style={styles.camera}
41
+ key={'camera-emergency'}
40
42
  />
41
43
  </View>
42
44
  <View style={styles.second}>
@@ -28,8 +28,10 @@ describe('Test EmergencyDetail', () => {
28
28
  it('create EmergencyDetail', async () => {
29
29
  const item = {
30
30
  configuration: {
31
- uri: '123',
32
- preview_uri: '123',
31
+ camera: {
32
+ uri: '123',
33
+ preview_uri: '123',
34
+ },
33
35
  device: {
34
36
  group: {
35
37
  id: 1,
@@ -28,7 +28,9 @@ const ProgressBar = memo(({ data = [], item }) => {
28
28
 
29
29
  <View style={styles.wrapProgressBar}>
30
30
  <Progress.Bar
31
- style={styles.processBar}
31
+ style={styles.progressBar}
32
+ width={null}
33
+ height={40}
32
34
  progress={percent}
33
35
  unfilledColor={Colors.Blue15}
34
36
  />
@@ -24,10 +24,8 @@ export default StyleSheet.create({
24
24
  fontWeight: 'bold',
25
25
  textTransform: 'uppercase',
26
26
  },
27
- processBar: {
27
+ progressBar: {
28
28
  flex: 1,
29
- width: '100%',
30
- height: 40,
31
29
  color: Colors.Blue16,
32
30
  borderWidth: 0,
33
31
  borderRadius: 10,
@@ -40,6 +38,5 @@ export default StyleSheet.create({
40
38
  },
41
39
  textValue: {
42
40
  marginLeft: 8,
43
- width: 45,
44
41
  },
45
42
  });
@@ -178,7 +178,7 @@ const Anemometer = memo(
178
178
  </View>
179
179
 
180
180
  <View style={styles.textValue}>
181
- {value && (
181
+ {!!value && (
182
182
  <Svg width={width} height={width} {...viewBox}>
183
183
  <Text
184
184
  fill={Colors.Lime6}
@@ -1,4 +1,4 @@
1
- import React, { memo, useCallback, useRef } from 'react';
1
+ import React, { useCallback, useRef } from 'react';
2
2
  import { View, Text, TouchableOpacity, Image } from 'react-native';
3
3
  import Images from '../../configs/Images';
4
4
  import { Colors } from '../../configs';
@@ -11,7 +11,6 @@ import { AccessibilityLabel } from '../../configs/Constants';
11
11
 
12
12
  const HeaderCustom = ({
13
13
  title = '',
14
- isShowAdd = false,
15
14
  isShowRight = false,
16
15
  onRefresh,
17
16
  showPopoverWithRef,
@@ -33,18 +32,18 @@ const HeaderCustom = ({
33
32
  const t = useTranslations();
34
33
  const { goBack } = useNavigation();
35
34
  const refMenuAction = useRef();
36
- const refAddAction = useRef();
37
- const handleAddAction = () => {};
38
35
  const handleShowMenuAction = () => showPopoverWithRef(refMenuAction);
39
36
  const handleGoback = () => {
40
- onGoBack && onGoBack();
41
- goBack();
37
+ if (onGoBack) {
38
+ onGoBack();
39
+ } else {
40
+ goBack();
41
+ }
42
42
  };
43
43
 
44
44
  const handleClose = useCallback(() => {
45
45
  onClose ? onClose() : notImplemented(t);
46
- // eslint-disable-next-line react-hooks/exhaustive-deps
47
- }, []);
46
+ }, [onClose, t]);
48
47
 
49
48
  return (
50
49
  <View
@@ -102,15 +101,6 @@ const HeaderCustom = ({
102
101
  </TouchableOpacity>
103
102
  </>
104
103
  )}
105
- {isShowAdd && (
106
- <TouchableOpacity
107
- style={styles.buttonAdd}
108
- onPress={handleAddAction}
109
- ref={refAddAction}
110
- >
111
- <Icon name={'plus'} size={27} color={Colors.Black} />
112
- </TouchableOpacity>
113
- )}
114
104
  {isShowClose && (
115
105
  <TouchableOpacity style={styles.buttonAdd} onPress={handleClose}>
116
106
  <Icon name={'close'} size={24} color={Colors.Black} />
@@ -122,4 +112,4 @@ const HeaderCustom = ({
122
112
  );
123
113
  };
124
114
 
125
- export default memo(HeaderCustom);
115
+ export default HeaderCustom;
@@ -1,4 +1,4 @@
1
- import React, { memo, useCallback, useMemo } from 'react';
1
+ import React, { memo, useCallback } from 'react';
2
2
  import { TouchableOpacity, TouchableWithoutFeedback, View } from 'react-native';
3
3
  import { IconOutline } from '@ant-design/icons-react-native';
4
4
  import moment from 'moment';
@@ -17,63 +17,20 @@ import { axiosPost } from '../../../utils/Apis/axios';
17
17
  import { useTranslations } from '../../../hooks/Common/useTranslations';
18
18
  import { useNavigation } from '@react-navigation/native';
19
19
  import Routes from '../../../utils/Route';
20
- import { useGetIdUser } from '../../../hooks/Common';
21
- import { AUTOMATE_TYPE, AccessibilityLabel } from '../../../configs/Constants';
20
+ import { AccessibilityLabel, AUTOMATE_TYPE } from '../../../configs/Constants';
22
21
 
23
22
  const ItemOneTap = memo(
24
23
  ({ isOwner, automate = {}, unit, wrapSyles, onPressItem }) => {
25
24
  const { navigate } = useNavigation();
26
- const {
27
- id,
28
- type,
29
- user,
30
- script,
31
- activate_at,
32
- condition,
33
- config,
34
- value,
35
- author = '',
36
- } = automate;
25
+ const { id, type, script, activate_at, author = '' } = automate;
37
26
  const t = useTranslations();
38
- const idUser = useGetIdUser();
39
-
40
- const textCondition = useMemo(() => {
41
- if (type === AUTOMATE_TYPE.VALUE_CHANGE) {
42
- let _condition;
43
- if (condition === '>') {
44
- _condition = 'higher_than';
45
- } else if (condition === '<') {
46
- _condition = 'lower_than';
47
- } else if (condition === '=') {
48
- _condition = 'equal';
49
- }
50
- return `${config} ${t(_condition)} ${value}`;
51
- }
52
- return null;
53
- }, [condition, config, t, type, value]);
54
27
 
55
28
  const goToDetail = useCallback(() => {
56
29
  navigate(Routes.ScriptDetail, {
57
30
  id,
58
- automate,
59
- name: script?.name,
60
- type: type,
61
- havePermission: isOwner || user === idUser,
62
- unit,
63
- textCondition,
31
+ preAutomate: automate,
64
32
  });
65
- }, [
66
- automate,
67
- isOwner,
68
- user,
69
- idUser,
70
- navigate,
71
- id,
72
- script,
73
- type,
74
- unit,
75
- textCondition,
76
- ]);
33
+ }, [automate, navigate, id]);
77
34
 
78
35
  const handleScriptAction = useCallback(async () => {
79
36
  const { success } = await axiosPost(API.AUTOMATE.ACTION_ONE_TAP(id));
@@ -61,6 +61,7 @@ describe('test Item', () => {
61
61
  beforeEach(() => {
62
62
  mockedNavigate.mockClear();
63
63
  });
64
+
64
65
  it('render SubUnitAutomate isOwner and handleOnAddNew', async () => {
65
66
  await act(async () => {
66
67
  tree = await create(wrapComponent(data));
@@ -78,7 +79,7 @@ describe('test Item', () => {
78
79
  await act(async () => {
79
80
  await item[0].props.onPress();
80
81
  });
81
- expect(mockedNavigate).toHaveBeenCalledWith(Routes.AddNewOneTap, {
82
+ expect(mockedNavigate).toHaveBeenCalledWith(Routes.ScenarioName, {
82
83
  automate: {
83
84
  type: 'one_tap',
84
85
  unit: undefined,
@@ -97,13 +98,8 @@ describe('test Item', () => {
97
98
  await goDetail[0].props.onPress();
98
99
  });
99
100
  expect(mockedNavigate).toHaveBeenCalledWith(Routes.ScriptDetail, {
100
- havePermission: true,
101
101
  id: 1,
102
- name: 'Joshua Ray',
103
- type: 'one_tap',
104
- unit: undefined,
105
- textCondition: null,
106
- automate: data.listAutomate[0].data[0],
102
+ preAutomate: data.listAutomate[0].data[0],
107
103
  });
108
104
 
109
105
  const handleScriptAction = instance.findAll(
@@ -189,13 +185,8 @@ describe('test Item', () => {
189
185
  await goDetail[0].props.onPress();
190
186
  });
191
187
  expect(mockedNavigate).toHaveBeenCalledWith(Routes.ScriptDetail, {
192
- havePermission: false,
193
188
  id: 1,
194
- name: 'Rain',
195
- type: 'value_change',
196
- unit: undefined,
197
- textCondition: 'Temperature higher than 29',
198
- automate: data.listAutomate[0].data[0],
189
+ preAutomate: data.listAutomate[0].data[0],
199
190
  });
200
191
  });
201
192
  it('render SubUnitAutomate script schedule and handleOnAddNew item automate', async () => {
@@ -237,8 +228,8 @@ describe('test Item', () => {
237
228
  await act(async () => {
238
229
  await item[0].props.onPress();
239
230
  });
240
- expect(mockedNavigate).toHaveBeenCalledWith(Routes.AddNewAutoSmart, {
241
- automate: { type: AUTOMATE_TYPE.VALUE_CHANGE, unit: undefined },
231
+ expect(mockedNavigate).toHaveBeenCalledWith(Routes.AddAutomationTypeSmart, {
232
+ automate: { unit: undefined },
242
233
  closeScreen: undefined,
243
234
  });
244
235
  mockedNavigate.mockClear();
@@ -22,10 +22,11 @@ const SubUnitAutomate = ({ isOwner, listAutomate, unit, wrapItemStyle }) => {
22
22
  const [automates, setAutomates] = useState(listAutomate[0]);
23
23
  const [indexAutomate, setIndexAutomate] = useState(0);
24
24
  const { name: currentScreen } = useRoute();
25
+
25
26
  const handleOnAddNew = () => {
26
27
  switch (automates.type) {
27
28
  case AUTOMATE_TABS.SCENARIO:
28
- navigate(Routes.AddNewOneTap, {
29
+ navigate(Routes.ScenarioName, {
29
30
  automate: {
30
31
  type: AUTOMATE_TYPE.ONE_TAP,
31
32
  unit: unit?.id,
@@ -34,9 +35,8 @@ const SubUnitAutomate = ({ isOwner, listAutomate, unit, wrapItemStyle }) => {
34
35
  });
35
36
  break;
36
37
  case AUTOMATE_TABS.AUTOMATION:
37
- navigate(Routes.AddNewAutoSmart, {
38
+ navigate(Routes.AddAutomationTypeSmart, {
38
39
  automate: {
39
- type: AUTOMATE_TYPE.VALUE_CHANGE,
40
40
  unit: unit?.id,
41
41
  },
42
42
  closeScreen: currentScreen,
@@ -1,10 +1,17 @@
1
- import React, { useMemo } from 'react';
2
- import { StyleSheet, TouchableOpacity, View } from 'react-native';
1
+ import React, { useMemo, useEffect, useState } from 'react';
2
+ import {
3
+ StyleSheet,
4
+ TouchableOpacity,
5
+ Animated,
6
+ Platform,
7
+ Easing,
8
+ } from 'react-native';
3
9
 
4
10
  import { Colors } from '../../configs';
5
11
  import Text from '../../commons/Text';
6
12
  import { AccessibilityLabel } from '../../configs/Constants';
7
13
  import withPreventDoubleClick from '../WithPreventDoubleClick';
14
+ import useKeyboardAnimated from '../../hooks/Explore/useKeyboardAnimated';
8
15
 
9
16
  const PreventDoubleTouch = withPreventDoubleClick(TouchableOpacity);
10
17
 
@@ -23,15 +30,34 @@ const ViewButtonBottom = ({
23
30
  styleButtonRight,
24
31
  accessibilityLabelPrefix = '',
25
32
  isPreventDoubleTouch = false,
33
+ wrapStyle,
34
+ disableKeyBoardAnimated = false,
26
35
  }) => {
27
36
  const useTwoButton = leftTitle && rightTitle;
37
+ const transY = useKeyboardAnimated();
38
+ const [keyboardAnim] = useState(new Animated.Value(0));
28
39
 
29
40
  const RightButtonView = useMemo(() => {
30
41
  return isPreventDoubleTouch ? PreventDoubleTouch : TouchableOpacity;
31
42
  }, [isPreventDoubleTouch]);
32
43
 
44
+ useEffect(() => {
45
+ Animated.timing(keyboardAnim, {
46
+ toValue: transY,
47
+ duration: Platform.OS === 'ios' ? 220 : 0,
48
+ easing: Easing.linear(),
49
+ useNativeDriver: false,
50
+ }).start();
51
+ }, [keyboardAnim, transY]);
52
+
33
53
  return (
34
- <View style={styles.container}>
54
+ <Animated.View
55
+ style={[
56
+ styles.container,
57
+ wrapStyle,
58
+ !disableKeyBoardAnimated && { bottom: keyboardAnim },
59
+ ]}
60
+ >
35
61
  {leftTitle && (
36
62
  <TouchableOpacity
37
63
  style={[
@@ -76,7 +102,7 @@ const ViewButtonBottom = ({
76
102
  </Text>
77
103
  </RightButtonView>
78
104
  )}
79
- </View>
105
+ </Animated.View>
80
106
  );
81
107
  };
82
108
 
@@ -85,6 +111,8 @@ const styles = StyleSheet.create({
85
111
  flexDirection: 'row',
86
112
  justifyContent: 'center',
87
113
  paddingHorizontal: 16,
114
+ position: 'absolute',
115
+ bottom: 0,
88
116
  },
89
117
  button: {
90
118
  paddingVertical: 24,
@@ -35,6 +35,8 @@ const API = {
35
35
  `/property_manager/units/${id}/star_automate_scripts/`,
36
36
  },
37
37
  SUB_UNIT: {
38
+ END_DEVICES_STATUS: (stationId) =>
39
+ `/property_manager/iot_dashboard/stations_v2/${stationId}/end_devices_status/`,
38
40
  REMOVE_SUB_UNIT: (unitId, id) =>
39
41
  `/property_manager/${unitId}/sub_units/${id}/`,
40
42
  CREATE_SUB_UNIT: (unitId) => `/property_manager/${unitId}/sub_units/`,
@@ -49,6 +51,7 @@ const API = {
49
51
  ACCEPT_NEW_DEVICE: (id) =>
50
52
  `/iot/modules/zigbee/chips/${id}/device_permit_to_join/`,
51
53
  },
54
+ JSON_CONFIGURATION: '/chip_manager/chips/json_configuration/',
52
55
  },
53
56
  DEVICE: {
54
57
  SENSOR_DETAIL: (id) => `/property_manager/devices/${id}/`,
@@ -238,6 +238,7 @@ export default {
238
238
  BUTTON_EDIT_SCRIPT_ACTION: 'BUTTON_EDIT_SCRIPT_ACTION',
239
239
  BUTTON_ADD_SCRIPT_ACTION: 'BUTTON_ADD_SCRIPT_ACTION',
240
240
  ICON_CLOSE: 'ICON_CLOSE',
241
+ ICON_MORE: 'ICON_MORE',
241
242
  ICON_ARROW_RIGHT: 'ICON_ARROW_RIGHT',
242
243
 
243
244
  // Parking input maunaly spot
@@ -6,4 +6,5 @@ export default {
6
6
  BLE_RESPONSE_OK: 'OK',
7
7
  BLE_RESPONSE_FAILED: 'FAILED',
8
8
  BLE_LISTER_RESPONSE_CONTROL: 'LISTER_RESPONSE_CONTROL',
9
+ BLE_REQUEST_ONE_TIME_CODE: 'cf153c1f-bc0d-11ed-afa1-0242ac120002',
9
10
  };
@@ -36,11 +36,11 @@ export const Action = {
36
36
  IS_CHECK_CLEAR_CACHE_UNITS: 'IS_CHECK_CLEAR_CACHE_UNITS',
37
37
  DELETE_UNIT_SUCCESSFULLY: 'DELETE_UNIT_SUCCESSFULLY',
38
38
  RESET_DELETE_UNIT_ACTION: 'RESET_DELETE_UNIT_ACTION',
39
- // NOTE: DEV MODE
40
39
  SET_WIDGET_DRAGGING: 'SET_WIDGET_DRAGGING',
41
40
  SET_IS_EDITING_TEMPLATE: 'SET_IS_EDITING_TEMPLATE',
42
41
  SET_IS_IN_EDIT_TEMPLATE_SCREEN: 'SET_IS_IN_EDIT_TEMPLATE_SCREEN',
43
42
  LOGOUT: 'LOGOUT',
43
+ SET_APP_STATE_CHANGE: 'SET_APP_STATE_CHANGE',
44
44
  };
45
45
 
46
46
  export type AuthData = {
@@ -101,6 +101,7 @@ export type AppType = {
101
101
  isLockWhenPickColor: boolean;
102
102
  isNeedUpdateCache: boolean;
103
103
  isDeleteUnitSuccessFully: boolean;
104
+ appState: string;
104
105
  };
105
106
 
106
107
  export type IoTType = {
@@ -92,6 +92,7 @@ export const mockSCStore = (data: ContextData): ContextData => {
92
92
  isConnectWifiGateway: false,
93
93
  isNetworkConnected: true,
94
94
  isLockWhenPickColor: false,
95
+ appState: 'active',
95
96
  ...data.app,
96
97
  },
97
98
  unit: {
@@ -16,6 +16,7 @@ import {
16
16
  } from './actionType';
17
17
  import _ from 'lodash';
18
18
  import { STORAGE_KEY, removeMultiple } from '../utils/Storage.js';
19
+ import { AppState } from 'react-native';
19
20
 
20
21
  export type ContextData = {
21
22
  auth: AuthData;
@@ -71,6 +72,7 @@ export const initialState = {
71
72
  isEmergencyPopupScreen: false,
72
73
  isNeedUpdateCache: false,
73
74
  isDeleteUnitSuccessFully: false,
75
+ appState: AppState.currentState,
74
76
  },
75
77
  iot: {
76
78
  bluetooth: {
@@ -394,7 +396,7 @@ export const reducer = (currentState: ContextData, action: Action) => {
394
396
  ...currentState.iot,
395
397
  internet: {
396
398
  ...currentState.iot.internet,
397
- statuses: newStatuses,
399
+ statuses: JSON.parse(JSON.stringify(newStatuses)),
398
400
  },
399
401
  },
400
402
  };
@@ -527,6 +529,15 @@ export const reducer = (currentState: ContextData, action: Action) => {
527
529
  },
528
530
  };
529
531
 
532
+ case Action.SET_APP_STATE_CHANGE:
533
+ return {
534
+ ...currentState,
535
+ app: {
536
+ ...currentState.app,
537
+ appState: payload,
538
+ },
539
+ };
540
+
530
541
  default:
531
542
  return currentState;
532
543
  }
@@ -18,11 +18,17 @@ const useKeyboardAnimated = (tabHeight = 0) => {
18
18
  );
19
19
 
20
20
  useEffect(() => {
21
- Keyboard.addListener('keyboard' + action + 'Hide', _keyboardWillHide);
22
- Keyboard.addListener('keyboard' + action + 'Show', _keyboardWillShow);
21
+ const keyboardDidHide = Keyboard.addListener(
22
+ 'keyboard' + action + 'Hide',
23
+ _keyboardWillHide
24
+ );
25
+ const keyboardDidShow = Keyboard.addListener(
26
+ 'keyboard' + action + 'Show',
27
+ _keyboardWillShow
28
+ );
23
29
  return () => {
24
- Keyboard.removeListener('keyboard' + action + 'Show', _keyboardWillShow);
25
- Keyboard.removeListener('keyboard' + action + 'Hide', _keyboardWillHide);
30
+ keyboardDidHide?.remove();
31
+ keyboardDidShow?.remove();
26
32
  };
27
33
  }, [_keyboardWillHide, _keyboardWillShow, tabHeight]);
28
34