@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.
- package/package.json +1 -1
- package/src/commons/Action/ItemQuickAction.js +20 -52
- package/src/commons/Action/__test__/ItemQuickAction.test.js +73 -235
- package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/index.js +3 -3
- package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/ItemPasscode.js +3 -3
- package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/index.js +3 -3
- package/src/commons/ActionGroup/OnOffSmartLock/SetupGeneratePasscode/index.js +5 -5
- package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +1 -1
- package/src/commons/ActionGroup/__test__/OptionsDropdownTemplate.test.js +4 -3
- package/src/commons/AlertAction/index.js +1 -1
- package/src/commons/Auth/AccountItem.js +7 -1
- package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +1 -1
- package/src/commons/Dashboard/MyUnit/index.js +1 -1
- package/src/commons/Sharing/RowMember.js +15 -3
- package/src/commons/Sharing/WrapHeaderScrollable.js +4 -4
- package/src/configs/AccessibilityLabel.js +8 -0
- package/src/configs/Constants.js +1 -0
- package/src/iot/RemoteControl/Bluetooth.js +19 -3
- package/src/iot/RemoteControl/__test__/Bluetooth.test.js +39 -11
- package/src/navigations/UnitStack.js +2 -1
- package/src/screens/AQIGuide/index.js +6 -11
- package/src/screens/AddNewDevice/index.js +7 -23
- package/src/screens/AddNewGateway/AddNewGatewayStyles.js +3 -6
- package/src/screens/AddNewGateway/ConnectingWifiDevice.js +48 -23
- package/src/screens/AddNewGateway/ConnectingWifiGuide.js +15 -12
- package/src/screens/AddNewGateway/RenameNewDevices.js +36 -16
- package/src/screens/AddNewGateway/RenameNewDevicesStyles.js +0 -8
- package/src/screens/AddNewGateway/ScanGatewayQR.js +2 -2
- package/src/screens/AddNewGateway/ScanModbusQR.js +4 -1
- package/src/screens/AddNewGateway/ScanWifiDeviceQR.js +2 -2
- package/src/screens/AddNewGateway/SelectDeviceType.js +4 -4
- package/src/screens/AddNewGateway/ShareWifiPassword.js +8 -2
- package/src/screens/AddNewGateway/__test__/ConnectingWifiDevice.test.js +9 -1
- package/src/screens/AddNewGateway/__test__/ConnectingWifiGuide.test.js +1 -1
- package/src/screens/AddNewGateway/__test__/ScanGatewayQR.test.js +12 -0
- package/src/screens/AddNewGateway/__test__/SelectModbusGateway.test.js +2 -2
- package/src/screens/AddNewGateway/__test__/SelectZigbeeGateway.test.js +2 -2
- package/src/screens/AddNewGateway/index.js +4 -4
- package/src/screens/AddNewOneTap/AddNewOneTapStyles.js +2 -8
- package/src/screens/AddNewOneTap/index.js +3 -9
- package/src/screens/Device/detail.js +5 -2
- package/src/screens/Drawer/Drawer.test.js +51 -8
- package/src/screens/Drawer/index.js +7 -6
- package/src/screens/Explore/__test__/Explore.test.js +3 -3
- package/src/screens/Explore/index.js +4 -4
- package/src/screens/Sharing/Components/CheckBoxCustom.js +7 -2
- package/src/screens/Sharing/Components/TitleCheckBox.js +1 -0
- package/src/screens/Sharing/InfoMemberUnit.js +3 -0
- package/src/screens/Sharing/SelectPermission.js +4 -19
- package/src/screens/Sharing/SelectUser.js +9 -5
- package/src/screens/Sharing/Styles/SelectPermissionStyles.js +4 -8
- package/src/screens/SmartAccount/Connecting/index.js +3 -3
- package/src/screens/SmartAccount/Connecting/style.js +1 -1
- package/src/screens/SmartAccount/ListDevice/__test__/ListDevice.test.js +1 -3
- package/src/screens/SmartAccount/SuccessfullyConnected/__test__/SuccessfullyConnected.test.js +1 -4
- package/src/screens/SmartAccount/SuccessfullyConnected/index.js +3 -3
- package/src/screens/SmartAccount/SuccessfullyConnected/styles.js +1 -1
- package/src/screens/SubUnit/AddSubUnit.js +4 -10
- package/src/screens/SubUnit/AddSubUnitStyles.js +2 -2
- package/src/screens/SyncLGDevice/AddLGDevice.js +4 -4
- package/src/screens/SyncLGDevice/AddLGDeviceStyles.js +2 -0
- package/src/screens/Template/__test__/GatewayList.test.js +1 -1
- package/src/screens/Template/__test__/Information.test.js +1 -1
- package/src/screens/UVIndexGuide/index.js +13 -22
- package/src/screens/Unit/MyAllUnit/index.js +5 -3
- package/src/screens/Unit/components/MyAllUnit/__test__/MyAllUnit.test.js +3 -3
- package/src/screens/Unit/components/MyAllUnit/index.js +5 -3
- package/src/screens/Unit/components/MyUnitDevice/index.js +1 -1
- package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +39 -0
- package/src/screens/WaterQualityGuide/index.js +10 -4
- package/src/utils/Apis/axios.js +5 -0
- package/src/utils/__test__/Utils.test.js +115 -0
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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',
|
package/src/configs/Constants.js
CHANGED
|
@@ -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(
|
|
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 } =
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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 {
|
|
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
|
-
<
|
|
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
|
-
</
|
|
95
|
+
</View>
|
|
107
96
|
);
|
|
108
97
|
});
|
|
109
98
|
|
|
110
99
|
export default AddNewDevice;
|
|
111
100
|
|
|
112
101
|
const styles = StyleSheet.create({
|
|
113
|
-
|
|
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:
|
|
105
|
+
paddingTop: getStatusBarHeight() + 10,
|
|
122
106
|
},
|
|
123
107
|
txtHeader: {
|
|
124
108
|
marginTop: 16,
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import { StyleSheet
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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={
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
168
|
+
</View>
|
|
166
169
|
);
|
|
167
170
|
};
|
|
168
171
|
|