@eohjsc/react-native-smart-city 0.3.44 → 0.3.46

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 (72) hide show
  1. package/package.json +1 -1
  2. package/src/commons/Action/ItemQuickAction.js +20 -52
  3. package/src/commons/Action/__test__/ItemQuickAction.test.js +73 -235
  4. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/index.js +3 -3
  5. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/ItemPasscode.js +3 -3
  6. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/index.js +3 -3
  7. package/src/commons/ActionGroup/OnOffSmartLock/SetupGeneratePasscode/index.js +5 -5
  8. package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +1 -1
  9. package/src/commons/ActionGroup/__test__/OptionsDropdownTemplate.test.js +4 -3
  10. package/src/commons/AlertAction/index.js +1 -1
  11. package/src/commons/Auth/AccountItem.js +7 -1
  12. package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +1 -1
  13. package/src/commons/Dashboard/MyUnit/index.js +1 -1
  14. package/src/commons/Sharing/RowMember.js +15 -3
  15. package/src/commons/Sharing/WrapHeaderScrollable.js +4 -4
  16. package/src/configs/AccessibilityLabel.js +8 -0
  17. package/src/configs/Constants.js +1 -0
  18. package/src/iot/RemoteControl/Bluetooth.js +19 -3
  19. package/src/iot/RemoteControl/__test__/Bluetooth.test.js +39 -11
  20. package/src/navigations/UnitStack.js +2 -1
  21. package/src/screens/AQIGuide/index.js +6 -11
  22. package/src/screens/AddNewDevice/index.js +7 -23
  23. package/src/screens/AddNewGateway/AddNewGatewayStyles.js +3 -6
  24. package/src/screens/AddNewGateway/ConnectingWifiDevice.js +48 -23
  25. package/src/screens/AddNewGateway/ConnectingWifiGuide.js +15 -12
  26. package/src/screens/AddNewGateway/RenameNewDevices.js +36 -16
  27. package/src/screens/AddNewGateway/RenameNewDevicesStyles.js +0 -8
  28. package/src/screens/AddNewGateway/ScanGatewayQR.js +2 -2
  29. package/src/screens/AddNewGateway/ScanModbusQR.js +4 -1
  30. package/src/screens/AddNewGateway/ScanWifiDeviceQR.js +2 -2
  31. package/src/screens/AddNewGateway/SelectDeviceType.js +4 -4
  32. package/src/screens/AddNewGateway/ShareWifiPassword.js +8 -2
  33. package/src/screens/AddNewGateway/__test__/ConnectingWifiDevice.test.js +9 -1
  34. package/src/screens/AddNewGateway/__test__/ConnectingWifiGuide.test.js +1 -1
  35. package/src/screens/AddNewGateway/__test__/ScanGatewayQR.test.js +12 -0
  36. package/src/screens/AddNewGateway/__test__/SelectModbusGateway.test.js +2 -2
  37. package/src/screens/AddNewGateway/__test__/SelectZigbeeGateway.test.js +2 -2
  38. package/src/screens/AddNewGateway/index.js +4 -4
  39. package/src/screens/AddNewOneTap/AddNewOneTapStyles.js +2 -8
  40. package/src/screens/AddNewOneTap/index.js +3 -9
  41. package/src/screens/Device/detail.js +5 -2
  42. package/src/screens/Drawer/Drawer.test.js +51 -8
  43. package/src/screens/Drawer/index.js +7 -6
  44. package/src/screens/Explore/__test__/Explore.test.js +3 -3
  45. package/src/screens/Explore/index.js +4 -4
  46. package/src/screens/Sharing/Components/CheckBoxCustom.js +7 -2
  47. package/src/screens/Sharing/Components/TitleCheckBox.js +1 -0
  48. package/src/screens/Sharing/InfoMemberUnit.js +3 -0
  49. package/src/screens/Sharing/SelectPermission.js +4 -19
  50. package/src/screens/Sharing/SelectUser.js +9 -5
  51. package/src/screens/Sharing/Styles/SelectPermissionStyles.js +4 -8
  52. package/src/screens/SmartAccount/Connecting/index.js +3 -3
  53. package/src/screens/SmartAccount/Connecting/style.js +1 -1
  54. package/src/screens/SmartAccount/ListDevice/__test__/ListDevice.test.js +1 -3
  55. package/src/screens/SmartAccount/SuccessfullyConnected/__test__/SuccessfullyConnected.test.js +1 -4
  56. package/src/screens/SmartAccount/SuccessfullyConnected/index.js +3 -3
  57. package/src/screens/SmartAccount/SuccessfullyConnected/styles.js +1 -1
  58. package/src/screens/SubUnit/AddSubUnit.js +4 -10
  59. package/src/screens/SubUnit/AddSubUnitStyles.js +2 -2
  60. package/src/screens/SyncLGDevice/AddLGDevice.js +4 -4
  61. package/src/screens/SyncLGDevice/AddLGDeviceStyles.js +2 -0
  62. package/src/screens/Template/__test__/GatewayList.test.js +1 -1
  63. package/src/screens/Template/__test__/Information.test.js +1 -1
  64. package/src/screens/UVIndexGuide/index.js +13 -22
  65. package/src/screens/Unit/MyAllUnit/index.js +5 -3
  66. package/src/screens/Unit/components/MyAllUnit/__test__/MyAllUnit.test.js +3 -3
  67. package/src/screens/Unit/components/MyAllUnit/index.js +5 -3
  68. package/src/screens/Unit/components/MyUnitDevice/index.js +1 -1
  69. package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +39 -0
  70. package/src/screens/WaterQualityGuide/index.js +10 -4
  71. package/src/utils/Apis/axios.js +5 -0
  72. package/src/utils/__test__/Utils.test.js +115 -0
@@ -22,7 +22,7 @@ const AlertAction = ({
22
22
  accessibilityLabelPrefix = '',
23
23
  boxLeftButtonStyle,
24
24
  boxRightButtonStyle,
25
- transY,
25
+ transY = 0,
26
26
  }) => {
27
27
  const [keyboardAnim] = useState(new Animated.Value(0));
28
28
 
@@ -4,6 +4,7 @@ import { View, StyleSheet, Text } from 'react-native';
4
4
  import { Colors } from '../../configs';
5
5
  import { shortEmailName } from '../../utils/Utils';
6
6
  import Avatar from '../../../assets/images/avatar.svg';
7
+ import AccessibilityLabel from '../../configs/AccessibilityLabel';
7
8
 
8
9
  const AccountItem = ({ account }) => {
9
10
  return (
@@ -20,7 +21,12 @@ const AccountItem = ({ account }) => {
20
21
  )}
21
22
 
22
23
  {account?.phone_number && (
23
- <Text style={{ color: Colors.Gray8 }}>{account?.phone_number}</Text>
24
+ <Text
25
+ style={{ color: Colors.Gray8 }}
26
+ accessibilityLabel={AccessibilityLabel.TEXT_PHONE_NUMBER_ITEM}
27
+ >
28
+ {account?.phone_number}
29
+ </Text>
24
30
  )}
25
31
  </View>
26
32
  </View>
@@ -78,7 +78,7 @@ describe('Test MyUnit', () => {
78
78
  const goToDetail = instance.findAll(
79
79
  (item) =>
80
80
  item.props.accessibilityLabel ===
81
- AccessibilityLabel.MY_UNIT_GO_TO_DETAIL
81
+ `${AccessibilityLabel.MY_UNIT_GO_TO_DETAIL}-${item?.id}`
82
82
  );
83
83
  const textNoUnit = instance.findAll(
84
84
  (item) =>
@@ -107,7 +107,7 @@ const MyUnit = () => {
107
107
  onPress={() => goToDetail(item)}
108
108
  style={styles.btnItem}
109
109
  activeOpacity={0.75}
110
- accessibilityLabel={AccessibilityLabel.MY_UNIT_GO_TO_DETAIL}
110
+ accessibilityLabel={`${AccessibilityLabel.MY_UNIT_GO_TO_DETAIL}-${index}`}
111
111
  >
112
112
  <View style={styles.overlay} />
113
113
  <Image
@@ -1,11 +1,12 @@
1
1
  import React, { memo, useMemo } from 'react';
2
2
  import { StyleSheet, View, TouchableOpacity, Image } from 'react-native';
3
+ import { useNavigation } from '@react-navigation/native';
3
4
  import { useTranslations } from '../../hooks/Common/useTranslations';
4
5
  import { Colors } from '../../configs';
5
6
  import Text from '../../commons/Text';
6
7
  import { shortEmailName } from '../../utils/Utils';
7
8
  import { CircleView } from '../CircleView';
8
- import { useNavigation } from '@react-navigation/native';
9
+ import AccessibilityLabel from '../../configs/AccessibilityLabel';
9
10
  import Routes from '../../utils/Route';
10
11
 
11
12
  const arrColor = [
@@ -65,7 +66,11 @@ const RowMember = memo(
65
66
  };
66
67
  return (
67
68
  <View style={styles.rowContainer}>
68
- <TouchableOpacity onPress={onPressInfo} disabled={type === 'disable'}>
69
+ <TouchableOpacity
70
+ onPress={onPressInfo}
71
+ disabled={type === 'disable'}
72
+ accessibilityLabel={`${AccessibilityLabel.SELECT_MEMBER_UNIT}-${member?.id}`}
73
+ >
69
74
  <View style={styles.Border}>
70
75
  {!!leftIcon && (
71
76
  <View style={styles.paddingLeft16}>
@@ -86,7 +91,14 @@ const RowMember = memo(
86
91
  {member?.name || shortEmailName(member?.email) || ''}
87
92
  </Text>
88
93
  {member?.phone_number && (
89
- <Text style={styles.status}> {member?.phone_number}</Text>
94
+ <Text
95
+ style={styles.status}
96
+ accessibilityLabel={
97
+ AccessibilityLabel.TEXT_PHONE_NUMBER_UNIT_MEMBER
98
+ }
99
+ >
100
+ {member?.phone_number}
101
+ </Text>
90
102
  )}
91
103
  </View>
92
104
  {!!rightComponent && (
@@ -4,11 +4,10 @@ import {
4
4
  StyleSheet,
5
5
  Animated,
6
6
  View,
7
- SafeAreaView,
8
7
  Platform,
9
8
  } from 'react-native';
10
9
  import { ActivityIndicator } from '@ant-design/react-native';
11
- import { isIphoneX } from 'react-native-iphone-x-helper';
10
+ import { getStatusBarHeight, isIphoneX } from 'react-native-iphone-x-helper';
12
11
 
13
12
  import { Colors, Theme } from '../../configs';
14
13
  import HeaderAni, { heightHeader } from '../../commons/HeaderAni';
@@ -50,7 +49,7 @@ const WrapHeaderScrollable = ({
50
49
  );
51
50
 
52
51
  return (
53
- <SafeAreaView style={[styles.container, headerAniStyle]}>
52
+ <View style={[styles.container, headerAniStyle]}>
54
53
  <HeaderAni
55
54
  scrollY={animatedScrollYValue}
56
55
  contentHeight={contentHeight}
@@ -104,7 +103,7 @@ const WrapHeaderScrollable = ({
104
103
  </View>
105
104
  )}
106
105
  </Animated.ScrollView>
107
- </SafeAreaView>
106
+ </View>
108
107
  );
109
108
  };
110
109
 
@@ -113,6 +112,7 @@ export default memo(WrapHeaderScrollable);
113
112
  const styles = StyleSheet.create({
114
113
  container: {
115
114
  flex: 1,
115
+ paddingTop: getStatusBarHeight() + 10,
116
116
  },
117
117
  scrollView: {
118
118
  flex: 1,
@@ -49,6 +49,9 @@ export default {
49
49
  //member list
50
50
  SHARING_MEMBER: 'SHARING_MEMBER',
51
51
  REMOVE_MEMBER: 'REMOVE_MEMBER',
52
+ CHECK_BOX_CUSTOM: 'CHECK_BOX_CUSTOM',
53
+ TEXT_PHONE_NUMBER_ITEM: 'TEXT_PHONE_NUMBER_ITEM',
54
+ TEXT_PHONE_NUMBER_UNIT_MEMBER: 'TEXT_PHONE_NUMBER_UNIT_MEMBER',
52
55
 
53
56
  // SmartTiviTemplate
54
57
  SMART_TIVI_TEMPLATE: {
@@ -417,6 +420,7 @@ export default {
417
420
  SELECT_UNIT_NAME: 'SELECT_UNIT_NAME',
418
421
  SELECT_UNIT_RADIO_BUTTON: 'SELECT_UNIT_RADIO_BUTTON',
419
422
  SELECT_UNIT_SELECT: 'SELECT_UNIT_SELECT',
423
+ SELECT_MEMBER_UNIT: 'SELECT_MEMBER_UNIT',
420
424
 
421
425
  // select wifi
422
426
  SELECT_WIFI: 'SELECT_WIFI',
@@ -434,6 +438,8 @@ export default {
434
438
  BUTTON_ADD_AUTO_SMART: 'BUTTON_ADD_AUTO_SMART',
435
439
  BUTTON_CONNECT_WIFI: 'BUTTON_CONNECT_WIFI',
436
440
  BUTTON_BOTTOM_SMART_ACCOUNT: 'BUTTON_BOTTOM_SMART_ACCOUNT',
441
+ BUTTON_ADD_MEMBER: 'BUTTON_ADD_MEMBER',
442
+ BUTTON_REMOVE_MEMBER: 'BUTTON_REMOVE_MEMBER',
437
443
  },
438
444
 
439
445
  TERM_AND_POLICY_TITLE: 'TERM_AND_POLICY_TITLE',
@@ -456,6 +462,8 @@ export default {
456
462
  // Select User
457
463
  SELECT_USER_ADD_USER_TITLE: 'SELECT_USER_ADD_USER_TITLE',
458
464
  SELECT_USER_ADD_USER_SUB_TITLE: 'SELECT_USER_ADD_USER_SUB_TITLE',
465
+ INPUT_PHONE_NUMBER_OR_EMAIL: 'INPUT_PHONE_NUMBER_OR_EMAIL',
466
+ INVITE_PHONE_NUMBER: 'INVITE_PHONE_NUMBER',
459
467
  // Connected device
460
468
  CONNECTED_DEVICE_SUCCESS: 'CONNECTED_DEVICE_SUCCESS',
461
469
  CONNECTED_DEVICE_UNIT_NAME: 'CONNECTED_DEVICE_UNIT_NAME',
@@ -269,6 +269,7 @@ export const PROBLEM_CODE = {
269
269
  NETWORK_ERROR: 'NETWORK_ERROR',
270
270
  UNKNOWN_ERROR: 'UNKNOWN_ERROR',
271
271
  CANCEL_ERROR: 'CANCEL_ERROR',
272
+ ADDRESS_CHANGING: 'Please wait 30s for changing address.',
272
273
  };
273
274
 
274
275
  export const DATE_TIME_FORMAT = {
@@ -4,11 +4,23 @@ import t from '../../hooks/Common/useTranslations';
4
4
  import base64 from 'react-native-base64';
5
5
  import { BleManager } from 'react-native-ble-plx';
6
6
  import { ToastBottomHelper } from '../../utils/Utils';
7
+ import { PermissionsAndroid } from 'react-native';
7
8
 
8
9
  const bluetoothDevices = {};
9
10
  const needToScanDevices = [];
10
11
  const bleManager = new BleManager();
11
12
 
13
+ export const requestBluetoothPermissions = async () => {
14
+ const results = await PermissionsAndroid.requestMultiple([
15
+ 'android.permission.BLUETOOTH_CONNECT',
16
+ 'android.permission.BLUETOOTH_SCAN',
17
+ 'android.permission.BLUETOOTH_ADVERTISE',
18
+ ]);
19
+ return Object.values(results).every(
20
+ (result) => result === PermissionsAndroid.RESULTS.GRANTED
21
+ );
22
+ };
23
+
12
24
  export const SEND_COMMAND_OVER_BLUETOOTH_FAIL =
13
25
  'SEND_COMMAND_OVER_BLUETOOTH_FAIL';
14
26
 
@@ -22,17 +34,21 @@ export const clearFoundDevices = () => {
22
34
  }
23
35
  };
24
36
 
25
- export const scanBluetoothDevices = (names, onDeviceFound) => {
37
+ export const scanBluetoothDevices = async (names, onDeviceFound) => {
26
38
  names.map((name) => {
27
39
  if (bluetoothDevices[name]) {
28
40
  return;
29
41
  }
30
42
  needToScanDevices.push(name);
31
43
  });
32
- realScanBluetoothDevices(onDeviceFound);
44
+ await realScanBluetoothDevices(onDeviceFound);
33
45
  };
34
46
 
35
- export const realScanBluetoothDevices = (onDeviceFound) => {
47
+ export const realScanBluetoothDevices = async (onDeviceFound) => {
48
+ const permissionsGranted = await requestBluetoothPermissions();
49
+ if (!permissionsGranted) {
50
+ return;
51
+ }
36
52
  if (!needToScanDevices.length) {
37
53
  return;
38
54
  }
@@ -12,6 +12,20 @@ const bleManager = new BleManager();
12
12
 
13
13
  const mockOnDeviceFound = jest.fn();
14
14
 
15
+ const mockRequestMultiplePerms = jest.fn();
16
+
17
+ jest.mock(
18
+ 'react-native/Libraries/PermissionsAndroid/PermissionsAndroid',
19
+ () => {
20
+ return {
21
+ ...jest.requireActual(
22
+ 'react-native/Libraries/PermissionsAndroid/PermissionsAndroid'
23
+ ),
24
+ requestMultiple: mockRequestMultiplePerms,
25
+ };
26
+ }
27
+ );
28
+
15
29
  describe('Test IOT Bluetooth', () => {
16
30
  beforeEach(() => {
17
31
  mockOnDeviceFound.mockClear();
@@ -19,6 +33,9 @@ describe('Test IOT Bluetooth', () => {
19
33
  bleManager.stopDeviceScan.mockClear();
20
34
  clearNeedToScanDevices();
21
35
  clearFoundDevices();
36
+ mockRequestMultiplePerms.mockImplementation(async (perms) =>
37
+ perms.map(() => 'granted')
38
+ );
22
39
  });
23
40
 
24
41
  afterEach(() => {
@@ -27,13 +44,21 @@ describe('Test IOT Bluetooth', () => {
27
44
  });
28
45
 
29
46
  test('Scan bluetooth device will init hardware scan', async () => {
30
- scanBluetoothDevices(['123456'], mockOnDeviceFound);
47
+ await scanBluetoothDevices(['123456'], mockOnDeviceFound);
31
48
  expect(bleManager.startDeviceScan).toBeCalled();
32
49
  });
33
50
 
51
+ test('Scan bluetooth device not scan without permissions', async () => {
52
+ mockRequestMultiplePerms.mockImplementation(async (perms) =>
53
+ perms.map(() => 'denied')
54
+ );
55
+ await scanBluetoothDevices(['123456'], mockOnDeviceFound);
56
+ expect(bleManager.startDeviceScan).not.toBeCalled();
57
+ });
58
+
34
59
  test('When look for bluetooth name, hardware will auto stop after period of time', async () => {
35
60
  jest.useFakeTimers();
36
- scanBluetoothDevices(['123456'], mockOnDeviceFound);
61
+ await scanBluetoothDevices(['123456'], mockOnDeviceFound);
37
62
  jest.runAllTimers();
38
63
  expect(bleManager.stopDeviceScan).toBeCalled();
39
64
  });
@@ -48,7 +73,7 @@ describe('Test IOT Bluetooth', () => {
48
73
  }
49
74
  );
50
75
 
51
- scanBluetoothDevices([device.localName], mockOnDeviceFound);
76
+ await scanBluetoothDevices([device.localName], mockOnDeviceFound);
52
77
  expect(mockOnDeviceFound).toBeCalledWith(device.localName, device);
53
78
  });
54
79
 
@@ -63,7 +88,7 @@ describe('Test IOT Bluetooth', () => {
63
88
  }
64
89
  );
65
90
 
66
- scanBluetoothDevices([device.name], mockOnDeviceFound);
91
+ await scanBluetoothDevices([device.name], mockOnDeviceFound);
67
92
  expect(mockOnDeviceFound).not.toBeCalled();
68
93
  });
69
94
 
@@ -78,7 +103,7 @@ describe('Test IOT Bluetooth', () => {
78
103
  }
79
104
  );
80
105
 
81
- scanBluetoothDevices([device.name + 'x'], mockOnDeviceFound);
106
+ await scanBluetoothDevices([device.name + 'x'], mockOnDeviceFound);
82
107
  expect(mockOnDeviceFound).not.toBeCalled();
83
108
  });
84
109
 
@@ -91,7 +116,10 @@ describe('Test IOT Bluetooth', () => {
91
116
  listener(null, device);
92
117
  }
93
118
  );
94
- scanBluetoothDevices([device.name, device.name + 'x'], mockOnDeviceFound);
119
+ await scanBluetoothDevices(
120
+ [device.name, device.name + 'x'],
121
+ mockOnDeviceFound
122
+ );
95
123
  expect(bleManager.stopDeviceScan).not.toBeCalled();
96
124
  });
97
125
 
@@ -104,7 +132,7 @@ describe('Test IOT Bluetooth', () => {
104
132
  listener(null, device);
105
133
  }
106
134
  );
107
- scanBluetoothDevices([device.name], mockOnDeviceFound);
135
+ await scanBluetoothDevices([device.name], mockOnDeviceFound);
108
136
  expect(bleManager.stopDeviceScan).toBeCalled();
109
137
  });
110
138
 
@@ -117,12 +145,12 @@ describe('Test IOT Bluetooth', () => {
117
145
  listener(null, device);
118
146
  }
119
147
  );
120
- scanBluetoothDevices([device.name], mockOnDeviceFound);
148
+ await scanBluetoothDevices([device.name], mockOnDeviceFound);
121
149
  expect(bleManager.startDeviceScan).toBeCalled();
122
150
 
123
151
  bleManager.startDeviceScan.mockClear();
124
152
 
125
- scanBluetoothDevices([device.name], mockOnDeviceFound);
153
+ await scanBluetoothDevices([device.name], mockOnDeviceFound);
126
154
  expect(bleManager.startDeviceScan).not.toBeCalled();
127
155
  });
128
156
 
@@ -159,7 +187,7 @@ describe('Test IOT Bluetooth', () => {
159
187
  listener(null, device);
160
188
  }
161
189
  );
162
- scanBluetoothDevices([device.name], mockOnDeviceFound);
190
+ await scanBluetoothDevices([device.name], mockOnDeviceFound);
163
191
 
164
192
  await sendCommandBluetoothFail({
165
193
  remote_control_options: {
@@ -186,7 +214,7 @@ describe('Test IOT Bluetooth', () => {
186
214
  listener(null, device);
187
215
  }
188
216
  );
189
- scanBluetoothDevices([device.name], mockOnDeviceFound);
217
+ await scanBluetoothDevices([device.name], mockOnDeviceFound);
190
218
 
191
219
  await sendCommandOverBluetooth(
192
220
  {
@@ -71,7 +71,8 @@ export const UnitStack = memo((props) => {
71
71
  const t = useTranslations();
72
72
  const { setAction } = useContext(SCContext);
73
73
  const { route } = props;
74
- const { unitId, unitData, isSuccessfullyConnected } = route?.params?.params;
74
+ const { unitId, unitData, isSuccessfullyConnected } =
75
+ route?.params?.params || {};
75
76
 
76
77
  useEffect(() => {
77
78
  const unsubscribe = NetInfo.addEventListener((state) => {
@@ -1,17 +1,11 @@
1
1
  import React, { memo, useMemo } from 'react';
2
- import {
3
- View,
4
- ScrollView,
5
- StyleSheet,
6
- TouchableOpacity,
7
- SafeAreaView,
8
- } from 'react-native';
9
- import { useTranslations } from '../../hooks/Common/useTranslations';
2
+ import { View, ScrollView, StyleSheet, TouchableOpacity } from 'react-native';
3
+ import { getStatusBarHeight } from 'react-native-iphone-x-helper';
10
4
 
5
+ import { useTranslations } from '../../hooks/Common/useTranslations';
11
6
  import { Colors, Theme } from '../../configs';
12
7
  import useTitleHeader from '../../hooks/Common/useTitleHeader';
13
8
  import { AccessibilityLabel } from '../../configs/Constants';
14
-
15
9
  import Text from '../../commons/Text';
16
10
  import SvgSmile from '../../../assets/images/Feeling/smile.svg';
17
11
  import SvgMeh from '../../../assets/images/Feeling/meh.svg';
@@ -82,7 +76,7 @@ const AQIGuide = memo(() => {
82
76
  const { titles, uvIndex } = data;
83
77
 
84
78
  return (
85
- <SafeAreaView style={styles.container}>
79
+ <View style={styles.container}>
86
80
  <ScrollView style={styles.container} scrollIndicatorInsets={{ right: 1 }}>
87
81
  {titles.map((item, index) => {
88
82
  const { title, des } = item;
@@ -142,7 +136,7 @@ const AQIGuide = memo(() => {
142
136
  );
143
137
  })}
144
138
  </ScrollView>
145
- </SafeAreaView>
139
+ </View>
146
140
  );
147
141
  });
148
142
 
@@ -152,6 +146,7 @@ const styles = StyleSheet.create({
152
146
  container: {
153
147
  flex: 1,
154
148
  backgroundColor: Theme.color.backgroundColor,
149
+ paddingTop: getStatusBarHeight() + 10,
155
150
  },
156
151
  titles: {
157
152
  marginHorizontal: 16,
@@ -1,14 +1,9 @@
1
1
  import React, { memo, useCallback, useEffect, useState } from 'react';
2
- import {
3
- ScrollView,
4
- StyleSheet,
5
- SafeAreaView,
6
- StatusBar,
7
- Platform,
8
- } from 'react-native';
2
+ import { ScrollView, StyleSheet, View } from 'react-native';
9
3
  import { useNavigation } from '@react-navigation/native';
10
- import { useTranslations } from '../../hooks/Common/useTranslations';
4
+ import { getStatusBarHeight } from 'react-native-iphone-x-helper';
11
5
 
6
+ import { useTranslations } from '../../hooks/Common/useTranslations';
12
7
  import { API, Colors } from '../../configs';
13
8
  import { Section, ViewButtonBottom } from '../../commons'; //components/Common
14
9
  import Text from '../../commons/Text';
@@ -62,13 +57,7 @@ const AddNewDevice = memo(({ route }) => {
62
57
  };
63
58
 
64
59
  return (
65
- <SafeAreaView
66
- style={
67
- Platform.OS === 'android'
68
- ? styles.containerAndroid
69
- : styles.containerIOS
70
- }
71
- >
60
+ <View style={styles.wrap}>
72
61
  <Text
73
62
  accessibilityLabel={AccessibilityLabel.ADD_NEW_DEVICE_ADD}
74
63
  semibold
@@ -103,22 +92,17 @@ const AddNewDevice = memo(({ route }) => {
103
92
  rightDisabled={stationId === -1}
104
93
  onRightClick={onRight}
105
94
  />
106
- </SafeAreaView>
95
+ </View>
107
96
  );
108
97
  });
109
98
 
110
99
  export default AddNewDevice;
111
100
 
112
101
  const styles = StyleSheet.create({
113
- containerAndroid: {
114
- flex: 1,
115
- backgroundColor: Colors.Gray2,
116
- paddingTop: StatusBar.currentHeight,
117
- },
118
- containerIOS: {
102
+ wrap: {
119
103
  flex: 1,
120
104
  backgroundColor: Colors.Gray2,
121
- paddingTop: 0,
105
+ paddingTop: getStatusBarHeight() + 10,
122
106
  },
123
107
  txtHeader: {
124
108
  marginTop: 16,
@@ -1,15 +1,12 @@
1
- import { StyleSheet, StatusBar, Platform } from 'react-native';
1
+ import { StyleSheet } from 'react-native';
2
+ import { getStatusBarHeight } from 'react-native-iphone-x-helper';
2
3
  import { Colors } from '../../configs';
3
4
 
4
5
  export default StyleSheet.create({
5
6
  wrap: {
6
7
  flex: 1,
7
8
  backgroundColor: Colors.Gray2,
8
- ...Platform.select({
9
- android: {
10
- paddingTop: StatusBar.currentHeight,
11
- },
12
- }),
9
+ paddingTop: getStatusBarHeight() + 10,
13
10
  },
14
11
  textHeader: {
15
12
  marginTop: 16,
@@ -1,18 +1,24 @@
1
- import { useNavigation } from '@react-navigation/native';
2
- import React, { useCallback, useState } from 'react';
1
+ import React, { useCallback, useEffect, useState } from 'react';
3
2
  import { Alert } from 'react-native';
3
+ import NetInfo from '@react-native-community/netinfo';
4
+ import { useNavigation } from '@react-navigation/native';
5
+
4
6
  import API from '../../configs/API';
5
7
  import { useTranslations } from '../../hooks/Common/useTranslations';
6
8
  import { axiosPost } from '../../utils/Apis/axios';
7
9
  import ConnectingDevice from './ConnectingDevice';
8
10
 
11
+ let isCallingAPI = false;
12
+
9
13
  const ConnectingWifiDevice = ({ route }) => {
10
14
  const t = useTranslations();
11
15
  const { unitId, subUnit, gateway, selectedWifi, qrData, addDeviceType } =
12
16
  route?.params || {};
13
- const [chipId, setChipId] = useState(null);
14
17
  const { goBack } = useNavigation();
15
18
 
19
+ const [chipId, setChipId] = useState(null);
20
+ const [channelName, setChannelName] = useState();
21
+
16
22
  const addingWifiDeviceFail = useCallback(
17
23
  (message) => {
18
24
  Alert.alert(t('fail_add_wifi_device'), message, [
@@ -26,27 +32,32 @@ const ConnectingWifiDevice = ({ route }) => {
26
32
  );
27
33
 
28
34
  const onReady = useCallback(
35
+ // eslint-disable-next-line no-shadow
29
36
  (channelName) => {
30
- const timeout = setTimeout(async () => {
31
- const { success, problem, data } = await axiosPost(
32
- API.UNIT.CHIP_SCAN(unitId),
33
- {
34
- imei: gateway?.imei,
35
- secret: qrData?.secret,
36
- name: gateway?.model,
37
- station: subUnit?.id,
38
- wifi_ssid: selectedWifi.ssid, // for storing
39
- wifi_pass: selectedWifi.password, // for storing
40
- channel_name: channelName,
37
+ if (!isCallingAPI) {
38
+ isCallingAPI = true;
39
+ const timeout = setTimeout(async () => {
40
+ const { success, problem, data } = await axiosPost(
41
+ API.UNIT.CHIP_SCAN(unitId),
42
+ {
43
+ imei: gateway?.imei,
44
+ secret: qrData?.secret,
45
+ name: gateway?.model,
46
+ station: subUnit?.id,
47
+ wifi_ssid: selectedWifi.ssid, // for storing
48
+ wifi_pass: selectedWifi.password, // for storing
49
+ channel_name: channelName,
50
+ }
51
+ );
52
+ if (!success) {
53
+ addingWifiDeviceFail(JSON.stringify(problem || data));
54
+ } else {
55
+ setChipId(data.id);
41
56
  }
42
- );
43
- if (!success) {
44
- addingWifiDeviceFail(JSON.stringify(problem || data));
45
- return;
46
- }
47
- setChipId(data.id);
48
- clearTimeout(timeout);
49
- }, 2000);
57
+ clearTimeout(timeout);
58
+ isCallingAPI = false;
59
+ }, 2000);
60
+ }
50
61
  },
51
62
  [
52
63
  gateway,
@@ -58,12 +69,26 @@ const ConnectingWifiDevice = ({ route }) => {
58
69
  ]
59
70
  );
60
71
 
72
+ useEffect(() => {
73
+ const unsubscribe = NetInfo.addEventListener((state) => {
74
+ if (
75
+ state.isConnected &&
76
+ state.details?.ssid === selectedWifi.ssid &&
77
+ channelName
78
+ ) {
79
+ onReady(channelName);
80
+ }
81
+ });
82
+ return () => unsubscribe && unsubscribe();
83
+ // eslint-disable-next-line react-hooks/exhaustive-deps
84
+ }, [selectedWifi.ssid, channelName]);
85
+
61
86
  return (
62
87
  <ConnectingDevice
63
88
  title={t('connect_device')}
64
89
  fail={addingWifiDeviceFail}
65
90
  initState={t('connecting_to_device')}
66
- onReady={onReady}
91
+ onReady={setChannelName}
67
92
  unitId={unitId}
68
93
  subUnit={subUnit}
69
94
  chipId={chipId}
@@ -1,12 +1,6 @@
1
1
  import React, { useCallback, useEffect, useState } from 'react';
2
2
  import WifiManager from 'react-native-wifi-reborn';
3
- import {
4
- ActivityIndicator,
5
- Alert,
6
- Platform,
7
- SafeAreaView,
8
- View,
9
- } from 'react-native';
3
+ import { ActivityIndicator, Alert, Platform, View } from 'react-native';
10
4
  import { useNavigation } from '@react-navigation/native';
11
5
  import _ from 'lodash';
12
6
  import dgram from 'react-native-udp';
@@ -21,6 +15,9 @@ import styles from './ConnectingWifiGuideStyles';
21
15
  import BottomButtonView from '../../commons/BottomButtonView';
22
16
  import AccessibilityLabel from '../../configs/AccessibilityLabel';
23
17
 
18
+ let intervalSend = null;
19
+ let socket;
20
+
24
21
  const ConnectingWifiGuide = ({ route }) => {
25
22
  const t = useTranslations();
26
23
  const { qrData, unitId, subUnit, addDeviceType } = route?.params || {};
@@ -91,9 +88,10 @@ const ConnectingWifiGuide = ({ route }) => {
91
88
  }
92
89
  }
93
90
 
94
- let intervalSend = null;
95
- const socket = dgram.createSocket({ type: 'udp4' });
96
- socket.bind(54321);
91
+ if (!socket) {
92
+ socket = dgram.createSocket({ type: 'udp4' });
93
+ socket.bind(54321);
94
+ }
97
95
 
98
96
  socket.on('message', (msg, rinfo) => {
99
97
  const data = JSON.parse(msg.toString());
@@ -102,6 +100,7 @@ const ConnectingWifiGuide = ({ route }) => {
102
100
  setCurrentState(0);
103
101
  clearInterval(intervalSend);
104
102
  socket.close();
103
+ socket = null;
105
104
  }
106
105
  });
107
106
 
@@ -109,6 +108,10 @@ const ConnectingWifiGuide = ({ route }) => {
109
108
  ToastBottomHelper.error(t('fail_trigger_scan_wifi_on_device'));
110
109
  });
111
110
 
111
+ if (intervalSend) {
112
+ clearInterval(intervalSend);
113
+ }
114
+
112
115
  intervalSend = setInterval(() => {
113
116
  socket.send(
114
117
  JSON.stringify({ type: 'scan', data: { wifi: '' } }),
@@ -134,7 +137,7 @@ const ConnectingWifiGuide = ({ route }) => {
134
137
  }, [addDeviceType, navigate, qrData, subUnit, unitId, wifiList]);
135
138
 
136
139
  return (
137
- <SafeAreaView style={styles.container}>
140
+ <View style={styles.container}>
138
141
  <HeaderCustom title={t('scan_qr_code')} isShowSeparator />
139
142
  <View
140
143
  style={{
@@ -162,7 +165,7 @@ const ConnectingWifiGuide = ({ route }) => {
162
165
  <ActivityIndicator size="large" />
163
166
  )}
164
167
  </View>
165
- </SafeAreaView>
168
+ </View>
166
169
  );
167
170
  };
168
171