@eohjsc/react-native-smart-city 0.3.2 → 0.3.5
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 +3 -1
- package/react-native-smart-city.podspec +1 -1
- package/src/commons/ActionGroup/ColorPickerTemplate.js +36 -23
- package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +21 -6
- package/src/commons/ActionGroup/OnOffTemplate/OnOffButtonTemplate.js +8 -2
- package/src/commons/ActionGroup/SliderRangeTemplate.js +5 -1
- package/src/commons/ActionGroup/__test__/NumberUpDownTemplate.test.js +43 -3
- package/src/commons/ActionGroup/__test__/index.test.js +4 -7
- package/src/commons/ConnectingProcess/index.js +3 -0
- package/src/commons/Device/ItemDevice.js +4 -1
- package/src/commons/Device/WaterQualitySensor/QualityIndicatorsItem.js +7 -2
- package/src/commons/Form/CurrencyInput.js +15 -1
- package/src/commons/Form/TextInputPassword.js +1 -1
- package/src/commons/HeaderAni/index.js +6 -1
- package/src/commons/MediaPlayerDetail/index.js +11 -2
- package/src/commons/Sharing/MemberList.js +10 -2
- package/src/commons/Sharing/WrapHeaderScrollable.js +2 -0
- package/src/commons/SubUnit/__test__/ShortDetail.test.js +1 -1
- package/src/configs/Constants.js +19 -0
- package/src/configs/SCConfig.js +2 -0
- package/src/navigations/UnitStack.js +3 -20
- package/src/navigations/UnitStackStyles.js +21 -0
- package/src/screens/AddNewDevice/__test__/AddNewDevice.test.js +8 -1
- package/src/screens/AddNewDevice/__test__/ConnectingDevices.test.js +1 -1
- package/src/screens/Device/EditDevice/index.js +15 -13
- package/src/screens/SubUnit/AddSubUnit.js +23 -17
- package/src/screens/SubUnit/EditSubUnit.js +15 -13
- package/src/screens/SubUnit/__test__/AddSubUnit.test.js +9 -23
- package/src/screens/SyncLGDevice/__test__/AddLGDevice.test.js +8 -1
- package/src/screens/Unit/SelectAddress.js +7 -1
- package/src/screens/Unit/Station/index.js +3 -0
- package/src/screens/Unit/__test__/SelectAddress.test.js +80 -3
- package/src/screens/Unit/components/MyUnitDevice/index.js +4 -4
- package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +2 -2
- package/src/utils/Apis/axios.js +9 -1
- package/src/utils/I18n/translations/en.json +3 -1
- package/src/utils/I18n/translations/vi.json +3 -1
- package/src/utils/Setting/Location.js +30 -0
- package/src/utils/__test__/Utils.test.js +12 -0
- package/src/commons/ActionGroup/__test__/NumberUpDownTemplateWithNullConfigValue.test.js +0 -60
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.
|
|
4
|
+
"version": "0.3.05",
|
|
5
5
|
"description": "TODO",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"files": [
|
|
@@ -146,6 +146,8 @@
|
|
|
146
146
|
"react-hooks-global-state": "^1.0.1",
|
|
147
147
|
"react-i18next": "^11.8.12",
|
|
148
148
|
"react-native-alert-async": "^1.0.5",
|
|
149
|
+
"react-native-android-keyboard-adjust": "^1.2.0",
|
|
150
|
+
"react-native-android-location-enabler": "^1.2.2",
|
|
149
151
|
"react-native-android-wifi": "^0.0.41",
|
|
150
152
|
"react-native-appearance": "^0.3.4",
|
|
151
153
|
"react-native-base64": "^0.1.0",
|
|
@@ -1,38 +1,51 @@
|
|
|
1
|
-
import React, { memo,
|
|
1
|
+
import React, { memo, useState, useEffect } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import styles from './ColorPickerTemplateStyles';
|
|
4
4
|
import ColorPicker from 'react-native-wheel-color-picker';
|
|
5
5
|
import { watchMultiConfigs } from '../../iot/Monitor';
|
|
6
6
|
import { useConfigGlobalState } from '../../iot/states';
|
|
7
7
|
|
|
8
|
+
let isFirstTime = true;
|
|
9
|
+
|
|
10
|
+
const WheelColorPicker = ({ valueColor, onChangeColor }) => {
|
|
11
|
+
return (
|
|
12
|
+
<ColorPicker
|
|
13
|
+
style={styles.colorPicker}
|
|
14
|
+
sliderHidden={true}
|
|
15
|
+
swatches={false}
|
|
16
|
+
color={valueColor}
|
|
17
|
+
onColorChangeComplete={onChangeColor}
|
|
18
|
+
thumbSize={16}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
8
23
|
const ColorPickerTemplate = memo(({ actionGroup, doAction, sensor }) => {
|
|
9
24
|
const { configuration } = actionGroup;
|
|
10
25
|
const [valueColorComplete, setValueColorComplete] = useState('');
|
|
11
|
-
const [isFirstColor, setIsFirstColor] = useState(false);
|
|
12
26
|
const [configValues] = useConfigGlobalState('configValues');
|
|
13
27
|
|
|
14
|
-
const onChangeColor =
|
|
15
|
-
(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
28
|
+
const onChangeColor = (color) => {
|
|
29
|
+
const to = setTimeout(() => {
|
|
30
|
+
isFirstTime = false;
|
|
31
|
+
clearTimeout(to);
|
|
32
|
+
}, 1000);
|
|
33
|
+
|
|
34
|
+
!isFirstTime &&
|
|
20
35
|
doAction(
|
|
21
36
|
configuration?.action_color_data,
|
|
22
37
|
JSON.stringify({ value: color })
|
|
23
38
|
);
|
|
24
|
-
|
|
25
|
-
[configuration?.action_color_data, doAction, isFirstColor]
|
|
26
|
-
);
|
|
27
|
-
const valueColor = useMemo(() => {
|
|
28
|
-
return valueColorComplete || '';
|
|
29
|
-
}, [valueColorComplete]);
|
|
39
|
+
};
|
|
30
40
|
|
|
31
41
|
useEffect(() => {
|
|
32
42
|
const { config } = configuration;
|
|
33
43
|
const configValue = configValues[config];
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
if (configValue && isFirstTime) {
|
|
45
|
+
setValueColorComplete(`#${configValue?.toString(16)}`);
|
|
46
|
+
}
|
|
47
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
48
|
+
}, [configValues]);
|
|
36
49
|
|
|
37
50
|
useEffect(() => {
|
|
38
51
|
if (sensor?.is_managed_by_backend && sensor.device_type !== 'GOOGLE_HOME') {
|
|
@@ -40,15 +53,15 @@ const ColorPickerTemplate = memo(({ actionGroup, doAction, sensor }) => {
|
|
|
40
53
|
}
|
|
41
54
|
}, [sensor, configuration.config]);
|
|
42
55
|
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
return () => (isFirstTime = true);
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
43
60
|
return (
|
|
44
61
|
<View style={styles.viewPickColor}>
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
swatches={false}
|
|
49
|
-
color={valueColor}
|
|
50
|
-
onColorChangeComplete={onChangeColor}
|
|
51
|
-
thumbSize={16}
|
|
62
|
+
<WheelColorPicker
|
|
63
|
+
valueColor={valueColorComplete}
|
|
64
|
+
onChangeColor={onChangeColor}
|
|
52
65
|
/>
|
|
53
66
|
</View>
|
|
54
67
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
|
-
import { View, TouchableOpacity } from 'react-native';
|
|
2
|
+
import { View, TouchableOpacity, ActivityIndicator } from 'react-native';
|
|
3
3
|
import { IconOutline } from '@ant-design/icons-react-native';
|
|
4
4
|
import { Colors } from '../../configs';
|
|
5
5
|
|
|
@@ -7,7 +7,7 @@ import Text from '../Text';
|
|
|
7
7
|
import { useConfigGlobalState } from '../../iot/states';
|
|
8
8
|
import styles from './NumberUpDownActionTemplateStyle';
|
|
9
9
|
import { watchMultiConfigs } from '../../iot/Monitor';
|
|
10
|
-
import { TESTID } from '../../configs/Constants';
|
|
10
|
+
import { DEVICE_TYPE, TESTID } from '../../configs/Constants';
|
|
11
11
|
|
|
12
12
|
const NumberUpDownActionTemplate = ({ actionGroup, doAction, sensor }) => {
|
|
13
13
|
const { configuration, title } = actionGroup;
|
|
@@ -25,6 +25,19 @@ const NumberUpDownActionTemplate = ({ actionGroup, doAction, sensor }) => {
|
|
|
25
25
|
const [value, setValue] = useState();
|
|
26
26
|
const valueDefault = 28;
|
|
27
27
|
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (
|
|
33
|
+
!!config &&
|
|
34
|
+
sensor?.is_managed_by_backend &&
|
|
35
|
+
sensor.device_type !== 'GOOGLE_HOME'
|
|
36
|
+
) {
|
|
37
|
+
watchMultiConfigs([config]);
|
|
38
|
+
}
|
|
39
|
+
}, [sensor, config]);
|
|
40
|
+
|
|
28
41
|
useEffect(() => {
|
|
29
42
|
if (!config) {
|
|
30
43
|
setValue(valueDefault);
|
|
@@ -34,11 +47,9 @@ const NumberUpDownActionTemplate = ({ actionGroup, doAction, sensor }) => {
|
|
|
34
47
|
const configValue = configValues[config];
|
|
35
48
|
if (configValue !== null && configValue !== undefined) {
|
|
36
49
|
setValue(configValue);
|
|
37
|
-
} else {
|
|
38
|
-
setValue(valueDefault);
|
|
39
50
|
}
|
|
40
51
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
41
|
-
}, []);
|
|
52
|
+
}, [JSON.stringify(configValues)]);
|
|
42
53
|
|
|
43
54
|
const doActionAndWatchConfig = useCallback(
|
|
44
55
|
async (actionData, actionValue, actionName) => {
|
|
@@ -113,7 +124,11 @@ const NumberUpDownActionTemplate = ({ actionGroup, doAction, sensor }) => {
|
|
|
113
124
|
</TouchableOpacity>
|
|
114
125
|
|
|
115
126
|
<Text testID={'abcd'} type="H2">
|
|
116
|
-
{
|
|
127
|
+
{value !== undefined ? (
|
|
128
|
+
text_format.replace('{number}', value)
|
|
129
|
+
) : (
|
|
130
|
+
<ActivityIndicator />
|
|
131
|
+
)}
|
|
117
132
|
</Text>
|
|
118
133
|
|
|
119
134
|
<TouchableOpacity
|
|
@@ -5,15 +5,20 @@ import React, { memo } from 'react';
|
|
|
5
5
|
import { TouchableOpacity, View } from 'react-native';
|
|
6
6
|
import { Colors } from '../../../configs';
|
|
7
7
|
import styles from './OnOffButtonTemplateStyle';
|
|
8
|
+
import { TESTID } from '../../../configs/Constants';
|
|
8
9
|
|
|
9
10
|
const OnOffButtonTemplate = memo(
|
|
10
11
|
({ isOn, triggerAction, actionGroup, isLight = false }) => {
|
|
11
|
-
const { configuration } = actionGroup;
|
|
12
|
+
const { configuration, id } = actionGroup;
|
|
12
13
|
|
|
13
14
|
return (
|
|
14
15
|
<>
|
|
15
16
|
<View style={styles.barrierControlContainer}>
|
|
16
|
-
<TouchableOpacity
|
|
17
|
+
<TouchableOpacity
|
|
18
|
+
style={styles.bigCircle}
|
|
19
|
+
onPress={triggerAction}
|
|
20
|
+
testID={`${TESTID.ON_OFF_BUTTON}-${id}`}
|
|
21
|
+
>
|
|
17
22
|
<View style={styles.smallCircle}>
|
|
18
23
|
<Icon
|
|
19
24
|
name={isOn ? configuration.icon_on : configuration.icon_off}
|
|
@@ -25,6 +30,7 @@ const OnOffButtonTemplate = memo(
|
|
|
25
30
|
styles.textBig,
|
|
26
31
|
{ color: isOn ? Colors.Gray8 : Colors.Gray6 },
|
|
27
32
|
]}
|
|
33
|
+
testID={`${TESTID.SENSOR_STATUS}-${id}`}
|
|
28
34
|
>
|
|
29
35
|
{isOn ? configuration.text_on : configuration.text_off}
|
|
30
36
|
</Text>
|
|
@@ -33,7 +33,11 @@ const SliderRangeTemplate = memo(({ actionGroup, doAction, sensor }) => {
|
|
|
33
33
|
useEffect(() => {
|
|
34
34
|
const { config } = configuration;
|
|
35
35
|
const configValue = configValues[config];
|
|
36
|
-
|
|
36
|
+
let valueTemp = configValue;
|
|
37
|
+
if (configValue > 0) {
|
|
38
|
+
valueTemp = Math.round((configValue / 254) * 100);
|
|
39
|
+
}
|
|
40
|
+
setValueBrightness(valueTemp);
|
|
37
41
|
}, [configuration.config, configValues, configuration]);
|
|
38
42
|
|
|
39
43
|
useEffect(() => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { TouchableOpacity } from 'react-native';
|
|
2
|
+
import { ActivityIndicator, TouchableOpacity } from 'react-native';
|
|
3
3
|
import { act, create } from 'react-test-renderer';
|
|
4
4
|
import Text from '../../../commons/Text';
|
|
5
|
-
import { TESTID } from '../../../configs/Constants';
|
|
5
|
+
import { DEVICE_TYPE, TESTID } from '../../../configs/Constants';
|
|
6
6
|
import { watchMultiConfigs } from '../../../iot/Monitor';
|
|
7
7
|
import NumberUpDownActionTemplate from '../NumberUpDownActionTemplate';
|
|
8
8
|
|
|
@@ -48,7 +48,10 @@ describe('Test NumberUpDownActionTemplate', () => {
|
|
|
48
48
|
<NumberUpDownActionTemplate
|
|
49
49
|
actionGroup={actionGroup}
|
|
50
50
|
doAction={mockDoAction}
|
|
51
|
-
sensor={{
|
|
51
|
+
sensor={{
|
|
52
|
+
is_managed_by_backend: true,
|
|
53
|
+
device_type: DEVICE_TYPE.LG_THINQ,
|
|
54
|
+
}}
|
|
52
55
|
/>
|
|
53
56
|
);
|
|
54
57
|
});
|
|
@@ -288,4 +291,41 @@ describe('Test NumberUpDownActionTemplate', () => {
|
|
|
288
291
|
const text = instance.findByType(Text);
|
|
289
292
|
expect(text.props.children).toEqual('25 *C');
|
|
290
293
|
});
|
|
294
|
+
test('render template have title', async () => {
|
|
295
|
+
const mockDoAction = jest.fn();
|
|
296
|
+
actionGroup.title = 'title';
|
|
297
|
+
await act(async () => {
|
|
298
|
+
wrapper = await create(
|
|
299
|
+
<NumberUpDownActionTemplate
|
|
300
|
+
actionGroup={actionGroup}
|
|
301
|
+
doAction={mockDoAction}
|
|
302
|
+
sensor={{
|
|
303
|
+
is_managed_by_backend: true,
|
|
304
|
+
device_type: DEVICE_TYPE.LG_THINQ,
|
|
305
|
+
}}
|
|
306
|
+
/>
|
|
307
|
+
);
|
|
308
|
+
});
|
|
309
|
+
const instance = wrapper.root;
|
|
310
|
+
const text = instance.findAllByType(Text);
|
|
311
|
+
expect(text).toHaveLength(2);
|
|
312
|
+
});
|
|
313
|
+
test('render template watch config not exits', async () => {
|
|
314
|
+
const mockDoAction = jest.fn();
|
|
315
|
+
actionGroup.configuration.config = 100;
|
|
316
|
+
await act(async () => {
|
|
317
|
+
wrapper = await create(
|
|
318
|
+
<NumberUpDownActionTemplate
|
|
319
|
+
actionGroup={actionGroup}
|
|
320
|
+
doAction={mockDoAction}
|
|
321
|
+
sensor={{
|
|
322
|
+
is_managed_by_backend: true,
|
|
323
|
+
}}
|
|
324
|
+
/>
|
|
325
|
+
);
|
|
326
|
+
});
|
|
327
|
+
const instance = wrapper.root;
|
|
328
|
+
const text = instance.findAllByType(ActivityIndicator);
|
|
329
|
+
expect(text).toHaveLength(1);
|
|
330
|
+
});
|
|
291
331
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { TouchableOpacity, Switch } from 'react-native';
|
|
2
|
+
import { TouchableOpacity, Switch, ActivityIndicator } from 'react-native';
|
|
3
3
|
import renderer, { act } from 'react-test-renderer';
|
|
4
4
|
import DateTimePickerModal from 'react-native-modal-datetime-picker';
|
|
5
5
|
import moment from 'moment';
|
|
@@ -344,7 +344,7 @@ describe('Test ActionGroup', () => {
|
|
|
344
344
|
expect(mockDoAction).toHaveBeenCalledTimes(1);
|
|
345
345
|
});
|
|
346
346
|
|
|
347
|
-
test('render ActionGroup NumberUpDownActionTemplate', async () => {
|
|
347
|
+
test('render ActionGroup NumberUpDownActionTemplate watch config value null', async () => {
|
|
348
348
|
const mockDoAction = jest.fn();
|
|
349
349
|
const actionGroup = {
|
|
350
350
|
template: 'NumberUpDownActionTemplate',
|
|
@@ -362,11 +362,8 @@ describe('Test ActionGroup', () => {
|
|
|
362
362
|
);
|
|
363
363
|
});
|
|
364
364
|
const instance = wrapper.root;
|
|
365
|
-
const
|
|
366
|
-
expect(
|
|
367
|
-
|
|
368
|
-
const touchs = instance.findAllByType(TouchableOpacity);
|
|
369
|
-
expect(touchs).toHaveLength(2);
|
|
365
|
+
const activity = instance.findAllByType(ActivityIndicator);
|
|
366
|
+
expect(activity.length).toEqual(1);
|
|
370
367
|
});
|
|
371
368
|
|
|
372
369
|
test('render ActionGroup StatesGridActionTemplate', async () => {
|
|
@@ -45,6 +45,7 @@ const ConnectingProcess = ({ route }) => {
|
|
|
45
45
|
);
|
|
46
46
|
if (success) {
|
|
47
47
|
setSensor(data);
|
|
48
|
+
setNewName(data?.name);
|
|
48
49
|
} else {
|
|
49
50
|
ToastBottomHelper.error(JSON.stringify(data));
|
|
50
51
|
goBack();
|
|
@@ -64,6 +65,7 @@ const ConnectingProcess = ({ route }) => {
|
|
|
64
65
|
});
|
|
65
66
|
if (success) {
|
|
66
67
|
setSensor(data);
|
|
68
|
+
setNewName(data?.name);
|
|
67
69
|
} else {
|
|
68
70
|
ToastBottomHelper.error(JSON.stringify(data));
|
|
69
71
|
goBack();
|
|
@@ -80,6 +82,7 @@ const ConnectingProcess = ({ route }) => {
|
|
|
80
82
|
);
|
|
81
83
|
if (success) {
|
|
82
84
|
setSensor({ name: gateway?.model });
|
|
85
|
+
setNewName(gateway?.model);
|
|
83
86
|
} else {
|
|
84
87
|
ToastBottomHelper.error(JSON.stringify(data));
|
|
85
88
|
goBack();
|
|
@@ -72,7 +72,10 @@ const ItemDevice = memo(
|
|
|
72
72
|
const textConnected = isConnected ? t('connected') : t('disconnected');
|
|
73
73
|
|
|
74
74
|
return (
|
|
75
|
-
<TouchableWithoutFeedback
|
|
75
|
+
<TouchableWithoutFeedback
|
|
76
|
+
onPress={goToSensorDisplay}
|
|
77
|
+
testID={`${TESTID.SENSOR_NAME}-${sensor?.id}`}
|
|
78
|
+
>
|
|
76
79
|
<View
|
|
77
80
|
style={[styles.container, wrapStyle, { borderColor }]}
|
|
78
81
|
testID={TESTID.SUB_UNIT_DEVICES}
|
|
@@ -37,7 +37,7 @@ const QualityIndicatorItem = memo(
|
|
|
37
37
|
>
|
|
38
38
|
<IconOutline
|
|
39
39
|
name={'info-circle'}
|
|
40
|
-
size={
|
|
40
|
+
size={18}
|
|
41
41
|
color={Colors.Gray8}
|
|
42
42
|
/>
|
|
43
43
|
</TouchableOpacity>
|
|
@@ -92,6 +92,11 @@ const styles = StyleSheet.create({
|
|
|
92
92
|
marginTop: 8,
|
|
93
93
|
},
|
|
94
94
|
iconInfo: {
|
|
95
|
-
|
|
95
|
+
width: 40,
|
|
96
|
+
height: 40,
|
|
97
|
+
justifyContent: 'center',
|
|
98
|
+
alignItems: 'center',
|
|
99
|
+
marginRight: -10,
|
|
100
|
+
marginTop: -2,
|
|
96
101
|
},
|
|
97
102
|
});
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
useState,
|
|
3
|
+
useRef,
|
|
4
|
+
useCallback,
|
|
5
|
+
useMemo,
|
|
6
|
+
useEffect,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import {
|
|
3
9
|
View,
|
|
4
10
|
TextInput,
|
|
@@ -6,6 +12,7 @@ import {
|
|
|
6
12
|
TouchableWithoutFeedback,
|
|
7
13
|
Platform,
|
|
8
14
|
} from 'react-native';
|
|
15
|
+
import AndroidKeyboardAdjust from 'react-native-android-keyboard-adjust';
|
|
9
16
|
import Text from '../Text';
|
|
10
17
|
import { Colors } from '../../configs';
|
|
11
18
|
|
|
@@ -125,6 +132,13 @@ const CurrencyInput = ({
|
|
|
125
132
|
return textInputValue.toString().length < 2 ? -12 : 0;
|
|
126
133
|
}, [textInputValue]);
|
|
127
134
|
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
const isAndroid = Platform.OS === 'android';
|
|
137
|
+
isAndroid && AndroidKeyboardAdjust.setAdjustResize();
|
|
138
|
+
|
|
139
|
+
return () => isAndroid && AndroidKeyboardAdjust.setAdjustPan();
|
|
140
|
+
}, []);
|
|
141
|
+
|
|
128
142
|
return (
|
|
129
143
|
<TouchableWithoutFeedback onPress={focusInput}>
|
|
130
144
|
<View style={styles.wrap}>
|
|
@@ -6,6 +6,7 @@ import { getStatusBarHeight } from 'react-native-iphone-x-helper';
|
|
|
6
6
|
|
|
7
7
|
import Text from '../../commons/Text';
|
|
8
8
|
import { Colors, Constants } from '../../configs';
|
|
9
|
+
import { TESTID } from '../../configs/Constants';
|
|
9
10
|
|
|
10
11
|
const screenHeight = Constants.height;
|
|
11
12
|
const default_height = 44;
|
|
@@ -89,7 +90,11 @@ const HeaderAni = memo(
|
|
|
89
90
|
},
|
|
90
91
|
]}
|
|
91
92
|
>
|
|
92
|
-
<TouchableOpacity
|
|
93
|
+
<TouchableOpacity
|
|
94
|
+
style={styles.btnBack}
|
|
95
|
+
onPress={onPressLeft}
|
|
96
|
+
testID={TESTID.ICON_BACK}
|
|
97
|
+
>
|
|
93
98
|
<Icon name={'left'} size={27} color={Colors.Gray9} />
|
|
94
99
|
</TouchableOpacity>
|
|
95
100
|
<View styles={styles.wrapRightComponent}>{rightComponent}</View>
|
|
@@ -6,7 +6,14 @@ import React, {
|
|
|
6
6
|
useContext,
|
|
7
7
|
useMemo,
|
|
8
8
|
} from 'react';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
Image,
|
|
11
|
+
View,
|
|
12
|
+
StyleSheet,
|
|
13
|
+
Text,
|
|
14
|
+
TouchableOpacity,
|
|
15
|
+
Platform,
|
|
16
|
+
} from 'react-native';
|
|
10
17
|
import { VLCPlayer } from 'react-native-vlc-media-player';
|
|
11
18
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
12
19
|
|
|
@@ -68,7 +75,9 @@ const MediaPlayerDetail = ({
|
|
|
68
75
|
newHeight = 224;
|
|
69
76
|
break;
|
|
70
77
|
case 4:
|
|
71
|
-
newWidth =
|
|
78
|
+
newWidth =
|
|
79
|
+
Constants.width /
|
|
80
|
+
(Platform.OS === 'ios' && Constants.width < 400 ? 1.5 : 2);
|
|
72
81
|
newHeight = 112;
|
|
73
82
|
break;
|
|
74
83
|
case 6:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { memo } from 'react';
|
|
2
2
|
import { View, StyleSheet } from 'react-native';
|
|
3
3
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
4
|
-
import { Colors } from '../../configs';
|
|
4
|
+
import { Colors, Constants } from '../../configs';
|
|
5
5
|
import Text from '../../commons/Text';
|
|
6
6
|
import RowMember from './RowMember';
|
|
7
7
|
|
|
@@ -26,7 +26,9 @@ const MemberList = ({
|
|
|
26
26
|
/>
|
|
27
27
|
))}
|
|
28
28
|
{!dataMember.length && (
|
|
29
|
-
<
|
|
29
|
+
<View style={styles.viewEmpty}>
|
|
30
|
+
<Text style={styles.textCenter}>{t('no_member')}</Text>
|
|
31
|
+
</View>
|
|
30
32
|
)}
|
|
31
33
|
</View>
|
|
32
34
|
);
|
|
@@ -37,4 +39,10 @@ const styles = StyleSheet.create({
|
|
|
37
39
|
box: {
|
|
38
40
|
backgroundColor: Colors.White,
|
|
39
41
|
},
|
|
42
|
+
viewEmpty: {
|
|
43
|
+
justifyContent: 'center',
|
|
44
|
+
alignItems: 'center',
|
|
45
|
+
height: Constants.height - 200,
|
|
46
|
+
backgroundColor: Colors.White,
|
|
47
|
+
},
|
|
40
48
|
});
|
|
@@ -13,6 +13,7 @@ import { isIphoneX } from 'react-native-iphone-x-helper';
|
|
|
13
13
|
import { Colors, Theme } from '../../configs';
|
|
14
14
|
import HeaderAni, { heightHeader } from '../../commons/HeaderAni';
|
|
15
15
|
import Text from '../../commons/Text';
|
|
16
|
+
import { TESTID } from '../../configs/Constants';
|
|
16
17
|
|
|
17
18
|
const WrapHeaderScrollable = ({
|
|
18
19
|
children,
|
|
@@ -59,6 +60,7 @@ const WrapHeaderScrollable = ({
|
|
|
59
60
|
onLeft={onGoBack}
|
|
60
61
|
/>
|
|
61
62
|
<Animated.ScrollView
|
|
63
|
+
testID={TESTID.ANIMATED_SCROLL}
|
|
62
64
|
scrollEventThrottle={16}
|
|
63
65
|
onScroll={Animated.event(
|
|
64
66
|
[{ nativeEvent: { contentOffset: { y: animatedScrollYValue } } }],
|
|
@@ -151,7 +151,7 @@ describe('test ShortDetail Subunit', () => {
|
|
|
151
151
|
(item) =>
|
|
152
152
|
item.props.testID === TESTID.SUB_UNIT_DEVICES && item.type === View
|
|
153
153
|
);
|
|
154
|
-
expect(itemDevice.length).toBe(
|
|
154
|
+
expect(itemDevice.length).toBe(0);
|
|
155
155
|
});
|
|
156
156
|
|
|
157
157
|
test('render ShortDetail add new device', async () => {
|
package/src/configs/Constants.js
CHANGED
|
@@ -288,6 +288,8 @@ export const TESTID = {
|
|
|
288
288
|
SUB_UNIT_TEXT_DROPDOWN: 'SUB_UNIT_TEXT_DROPDOWN',
|
|
289
289
|
SUB_UNIT_GO_DETAIL: 'SUB_UNIT_GO_DETAIL',
|
|
290
290
|
VIEW_SUB_UNIT_AUTOMATE: 'VIEW_SUB_UNIT_AUTOMATE',
|
|
291
|
+
SUB_UNIT_NAME: 'SUB_UNIT_NAME',
|
|
292
|
+
ANIMATED_SCROLL: 'ANIMATED_SCROLL',
|
|
291
293
|
ADD_SUB_UNIT: 'ADD_SUB_UNIT',
|
|
292
294
|
|
|
293
295
|
// NavBar
|
|
@@ -392,6 +394,7 @@ export const TESTID = {
|
|
|
392
394
|
ITEM_TEXT_ERROR: 'ITEM_TEXT_ERROR',
|
|
393
395
|
SEARCH_BAR_INPUT: 'SEARCH_BAR_INPUT',
|
|
394
396
|
GO_DETAIL: 'GO_DETAIL',
|
|
397
|
+
NAV_LIST: 'NAV_LIST',
|
|
395
398
|
|
|
396
399
|
// Automate
|
|
397
400
|
AUTOMATE_SCRIPT_ACTION: 'AUTOMATE_SCRIPT_ACTION',
|
|
@@ -447,8 +450,13 @@ export const TESTID = {
|
|
|
447
450
|
ITEM_QUICK_ACTION_PRESS: 'ITEM_QUICK_ACTION_PRESS',
|
|
448
451
|
TIME_COUNT_DOWN_TEXT: 'TIME_COUNT_DOWN_TEXT',
|
|
449
452
|
ACTION_ITEM: 'ACTION_ITEM',
|
|
453
|
+
|
|
450
454
|
// Sensor Item
|
|
451
455
|
TEXT_SENSOR_ITEM: 'TEXT_SENSOR_ITEM',
|
|
456
|
+
SENSOR_NAME: 'SENSOR_NAME',
|
|
457
|
+
ON_OFF_BUTTON: 'ON_OFF_BUTTON',
|
|
458
|
+
SENSOR_STATUS: 'SENSOR_STATUS',
|
|
459
|
+
ICON_BACK: 'ICON_BACK',
|
|
452
460
|
|
|
453
461
|
// DeviceInfo
|
|
454
462
|
DEVICE_INFO_BATTERY: 'DEVICE_INFO_BATTERY',
|
|
@@ -564,6 +572,7 @@ export const TESTID = {
|
|
|
564
572
|
ICON_ADD_STAR_SHARED_UNIT: 'ICON_ADD_STAR_SHARED_UNIT',
|
|
565
573
|
TOUCH_SHARED_UNIT: 'TOUCH_SHARED_UNIT',
|
|
566
574
|
SHARED_UNIT_OWN_BY: 'SHARED_UNIT_OWN_BY',
|
|
575
|
+
ICON_UNIT: 'ICON_UNIT',
|
|
567
576
|
|
|
568
577
|
// Select subunit
|
|
569
578
|
|
|
@@ -809,3 +818,13 @@ export const SENSOR_TYPE = {
|
|
|
809
818
|
SOS: 'sos',
|
|
810
819
|
FILTER_WATER: 'filter_water',
|
|
811
820
|
};
|
|
821
|
+
|
|
822
|
+
export const PROBLEM_CODE = {
|
|
823
|
+
CLIENT_ERROR: 'CLIENT_ERROR',
|
|
824
|
+
SERVER_ERROR: 'SERVER_ERROR',
|
|
825
|
+
TIMEOUT_ERROR: 'TIMEOUT_ERROR',
|
|
826
|
+
CONNECTION_ERROR: 'CONNECTION_ERROR',
|
|
827
|
+
NETWORK_ERROR: 'NETWORK_ERROR',
|
|
828
|
+
UNKNOWN_ERROR: 'UNKNOWN_ERROR',
|
|
829
|
+
CANCEL_ERROR: 'CANCEL_ERROR',
|
|
830
|
+
};
|
package/src/configs/SCConfig.js
CHANGED
|
@@ -107,11 +107,13 @@ export class SCConfig {
|
|
|
107
107
|
static VCONNEX_REDIRECT_URI_APP = SCDefaultConfig.VCONNEX_REDIRECT_URI_APP;
|
|
108
108
|
static pusherAppKey = SCDefaultConfig.pusherAppKey;
|
|
109
109
|
static pusherAppCluste = SCDefaultConfig.pusherAppCluster;
|
|
110
|
+
static language = 'en';
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
export const initSCConfig = (config) => {
|
|
113
114
|
api.setBaseURL(config.apiRoot ?? SCDefaultConfig.apiRoot);
|
|
114
115
|
LocaleConfig.defaultLocale = config.language;
|
|
116
|
+
SCConfig.language = config.language ?? SCConfig.language;
|
|
115
117
|
SCConfig.apiRoot = config.apiRoot ?? SCDefaultConfig.apiRoot;
|
|
116
118
|
SCConfig.GOOGLE_MAP_API_KEY =
|
|
117
119
|
config.GOOGLE_MAP_API_KEY ?? SCDefaultConfig.GOOGLE_MAP_API_KEY;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { memo, useContext, useEffect } from 'react';
|
|
2
|
-
import { View
|
|
2
|
+
import { View } from 'react-native';
|
|
3
3
|
import { IconOutline } from '@ant-design/icons-react-native';
|
|
4
4
|
import { createStackNavigator } from '@react-navigation/stack';
|
|
5
5
|
import { BleManager } from 'react-native-ble-plx';
|
|
@@ -52,10 +52,10 @@ import ConfirmUnitDeletion from '../screens/ConfirmUnitDeletion';
|
|
|
52
52
|
import InfoMemberUnit from '../screens/Sharing/InfoMemberUnit';
|
|
53
53
|
import EnterPassword from '../screens/EnterPassword';
|
|
54
54
|
import { HanetCameraStack } from './HanetCameraStack';
|
|
55
|
-
|
|
56
55
|
import { axiosGet } from '../utils/Apis/axios';
|
|
57
56
|
import { API } from '../configs';
|
|
58
57
|
import SideMenuDetail from '../screens/SideMenuDetail';
|
|
58
|
+
import { styles } from './UnitStackStyles';
|
|
59
59
|
|
|
60
60
|
const Stack = createStackNavigator();
|
|
61
61
|
|
|
@@ -173,12 +173,9 @@ export const UnitStack = memo((props) => {
|
|
|
173
173
|
component={ChooseLocation}
|
|
174
174
|
options={{
|
|
175
175
|
headerShown: true,
|
|
176
|
-
headerTitleStyle: {
|
|
177
|
-
...styles.headerLocation,
|
|
178
|
-
},
|
|
179
176
|
headerTitle: () => (
|
|
180
177
|
<View style={styles.headerLocation}>
|
|
181
|
-
<Text
|
|
178
|
+
<Text color={Colors.Gray9} style={styles.headerTitle} bold>
|
|
182
179
|
{t('choose_on_map')}
|
|
183
180
|
</Text>
|
|
184
181
|
|
|
@@ -406,17 +403,3 @@ export const UnitStack = memo((props) => {
|
|
|
406
403
|
</Stack.Navigator>
|
|
407
404
|
);
|
|
408
405
|
});
|
|
409
|
-
|
|
410
|
-
const styles = StyleSheet.create({
|
|
411
|
-
icLeft: {
|
|
412
|
-
marginLeft: Device.isIOS ? 8 : 0,
|
|
413
|
-
},
|
|
414
|
-
headerLocation: {
|
|
415
|
-
alignItems: 'center',
|
|
416
|
-
justifyContent: 'center',
|
|
417
|
-
},
|
|
418
|
-
headerContent: {
|
|
419
|
-
textAlign: 'center',
|
|
420
|
-
paddingBottom: 8,
|
|
421
|
-
},
|
|
422
|
-
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { Device } from '../configs';
|
|
3
|
+
|
|
4
|
+
export const styles = StyleSheet.create({
|
|
5
|
+
icLeft: {
|
|
6
|
+
marginLeft: Device.isIOS ? 8 : 0,
|
|
7
|
+
},
|
|
8
|
+
headerLocation: {
|
|
9
|
+
alignItems: 'center',
|
|
10
|
+
justifyContent: 'center',
|
|
11
|
+
width: 290,
|
|
12
|
+
},
|
|
13
|
+
headerTitle: {
|
|
14
|
+
fontSize: 20,
|
|
15
|
+
lineHeight: 28,
|
|
16
|
+
},
|
|
17
|
+
headerContent: {
|
|
18
|
+
textAlign: 'center',
|
|
19
|
+
paddingBottom: 4,
|
|
20
|
+
},
|
|
21
|
+
});
|