@eohjsc/react-native-smart-city 0.3.72 → 0.3.73
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/Images/ThreeButton/buttonCircleBig.png +0 -0
- package/src/Images/ThreeButton/buttonCircleSmall.png +0 -0
- package/src/commons/ActionGroup/ThreeButtonTemplate/__test__/ThreeButtonCircle.test.js +52 -0
- package/src/commons/ActionGroup/ThreeButtonTemplate/__test__/ThreeButtonDefault.test.js +52 -0
- package/src/commons/ActionGroup/{__test__ → ThreeButtonTemplate/__test__}/ThreeButtonTemplate.test.js +21 -8
- package/src/commons/ActionGroup/ThreeButtonTemplate/components/ThreeButtonCircle.js +103 -0
- package/src/commons/ActionGroup/ThreeButtonTemplate/components/ThreeButtonCircleStyles.js +31 -0
- package/src/commons/ActionGroup/ThreeButtonTemplate/components/ThreeButtonDefault.js +96 -0
- package/src/commons/ActionGroup/{ThreeButtonTemplateStyle.js → ThreeButtonTemplate/components/ThreeButtonDefaultStyles.js} +11 -34
- package/src/commons/ActionGroup/{ThreeButtonTemplate.js → ThreeButtonTemplate/index.js} +48 -51
- package/src/commons/ActionGroup/ThreeButtonTemplate/styles.js +27 -0
- package/src/configs/SCConfig.js +3 -0
- package/src/hooks/IoT/useBluetoothConnection.js +2 -1
- package/src/screens/AddLocationMaps/index.js +1 -1
- package/src/screens/AddNewGateway/ConnectingWifiGuide.js +4 -1
- package/src/screens/AllGateway/DetailConfigActionModbus/index.js +6 -4
- package/src/screens/AllGateway/GatewayConnectionMethods/__test__/index.test.js +4 -1
- package/src/screens/AllGateway/GatewayConnectionMethods/index.js +4 -2
- package/src/screens/AllGateway/GatewayInfo/__test__/index.test.js +2 -1
- package/src/screens/AllGateway/components/Information/__test__/index.test.js +2 -1
- package/src/screens/AllGateway/components/Information/index.js +4 -2
- package/src/screens/GuestInfo/index.js +2 -2
- package/src/screens/Sharing/InfoMemberUnit.js +2 -2
- package/src/screens/Unit/SelectAddress.js +1 -1
- package/src/utils/I18n/translations/en.json +13 -12
- package/src/utils/I18n/translations/vi.json +12 -11
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import renderer, { act } from 'react-test-renderer';
|
|
3
|
+
import { TouchableOpacity } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import { SCProvider } from '../../../../context';
|
|
6
|
+
import { mockSCStore } from '../../../../context/mockStore';
|
|
7
|
+
import ThreeButtonCircle from '../components/ThreeButtonCircle';
|
|
8
|
+
|
|
9
|
+
const mockOnButton1Press = jest.fn();
|
|
10
|
+
const mockOnButton2Press = jest.fn();
|
|
11
|
+
const mockOnButton3Press = jest.fn();
|
|
12
|
+
|
|
13
|
+
const wrapComponent = (props) => (
|
|
14
|
+
<SCProvider initState={mockSCStore({})}>
|
|
15
|
+
<ThreeButtonCircle {...props} />
|
|
16
|
+
</SCProvider>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
describe('Test ThreeButtonCircle', () => {
|
|
20
|
+
let props = {
|
|
21
|
+
icon1: 'icon1',
|
|
22
|
+
text1: 'text1',
|
|
23
|
+
icon2: 'icon2',
|
|
24
|
+
text2: 'text2',
|
|
25
|
+
icon3: 'icon3',
|
|
26
|
+
text3: 'text3',
|
|
27
|
+
onButton1Press: mockOnButton1Press,
|
|
28
|
+
onButton2Press: mockOnButton2Press,
|
|
29
|
+
onButton3Press: mockOnButton3Press,
|
|
30
|
+
};
|
|
31
|
+
let wrapper;
|
|
32
|
+
|
|
33
|
+
it('render ThreeButtonCircle', async () => {
|
|
34
|
+
await act(async () => {
|
|
35
|
+
wrapper = renderer.create(wrapComponent(props));
|
|
36
|
+
});
|
|
37
|
+
const instance = wrapper.root;
|
|
38
|
+
const touchableOpacities = instance.findAllByType(TouchableOpacity);
|
|
39
|
+
expect(touchableOpacities).toHaveLength(3);
|
|
40
|
+
});
|
|
41
|
+
it('render ThreeButtonCircle onPressButton', async () => {
|
|
42
|
+
await act(async () => {
|
|
43
|
+
wrapper = renderer.create(wrapComponent(props));
|
|
44
|
+
});
|
|
45
|
+
const instance = wrapper.root;
|
|
46
|
+
const touchableOpacities = instance.findAllByType(TouchableOpacity);
|
|
47
|
+
await act(async () => {
|
|
48
|
+
touchableOpacities[0].props.onPress();
|
|
49
|
+
});
|
|
50
|
+
expect(mockOnButton1Press).toBeCalled();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import renderer, { act } from 'react-test-renderer';
|
|
3
|
+
import { TouchableOpacity } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import { SCProvider } from '../../../../context';
|
|
6
|
+
import { mockSCStore } from '../../../../context/mockStore';
|
|
7
|
+
import ThreeButtonDefault from '../components/ThreeButtonDefault';
|
|
8
|
+
|
|
9
|
+
const mockOnButton1Press = jest.fn();
|
|
10
|
+
const mockOnButton2Press = jest.fn();
|
|
11
|
+
const mockOnButton3Press = jest.fn();
|
|
12
|
+
|
|
13
|
+
const wrapComponent = (props) => (
|
|
14
|
+
<SCProvider initState={mockSCStore({})}>
|
|
15
|
+
<ThreeButtonDefault {...props} />
|
|
16
|
+
</SCProvider>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
describe('Test ThreeButtonDefault', () => {
|
|
20
|
+
let props = {
|
|
21
|
+
icon1: 'icon1',
|
|
22
|
+
text1: 'text1',
|
|
23
|
+
icon2: 'icon2',
|
|
24
|
+
text2: 'text2',
|
|
25
|
+
icon3: 'icon3',
|
|
26
|
+
text3: 'text3',
|
|
27
|
+
onButton1Press: mockOnButton1Press,
|
|
28
|
+
onButton2Press: mockOnButton2Press,
|
|
29
|
+
onButton3Press: mockOnButton3Press,
|
|
30
|
+
};
|
|
31
|
+
let wrapper;
|
|
32
|
+
|
|
33
|
+
it('render ThreeButtonDefault', async () => {
|
|
34
|
+
await act(async () => {
|
|
35
|
+
wrapper = renderer.create(wrapComponent(props));
|
|
36
|
+
});
|
|
37
|
+
const instance = wrapper.root;
|
|
38
|
+
const touchableOpacities = instance.findAllByType(TouchableOpacity);
|
|
39
|
+
expect(touchableOpacities).toHaveLength(3);
|
|
40
|
+
});
|
|
41
|
+
it('render ThreeButtonDefault onPressButton', async () => {
|
|
42
|
+
await act(async () => {
|
|
43
|
+
wrapper = renderer.create(wrapComponent(props));
|
|
44
|
+
});
|
|
45
|
+
const instance = wrapper.root;
|
|
46
|
+
const touchableOpacities = instance.findAllByType(TouchableOpacity);
|
|
47
|
+
await act(async () => {
|
|
48
|
+
touchableOpacities[0].props.onPress();
|
|
49
|
+
});
|
|
50
|
+
expect(mockOnButton1Press).toBeCalled();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import renderer, { act } from 'react-test-renderer';
|
|
3
|
-
import { TouchableOpacity } from 'react-native';
|
|
4
3
|
|
|
5
|
-
import ThreeButtonTemplate from '
|
|
6
|
-
import { SCProvider } from '
|
|
7
|
-
import { mockSCStore } from '
|
|
4
|
+
import ThreeButtonTemplate from '..';
|
|
5
|
+
import { SCProvider } from '../../../../context';
|
|
6
|
+
import { mockSCStore } from '../../../../context/mockStore';
|
|
7
|
+
import ThreeButtonDefault from '../components/ThreeButtonDefault';
|
|
8
|
+
import ThreeButtonCircle from '../components/ThreeButtonCircle';
|
|
8
9
|
|
|
9
10
|
const wrapComponent = (actionGroup) => (
|
|
10
11
|
<SCProvider initState={mockSCStore({})}>
|
|
@@ -13,7 +14,7 @@ const wrapComponent = (actionGroup) => (
|
|
|
13
14
|
);
|
|
14
15
|
|
|
15
16
|
describe('Test ThreeButtonTemplate', () => {
|
|
16
|
-
|
|
17
|
+
let actionGroup = {
|
|
17
18
|
configuration: {
|
|
18
19
|
action1: '2b949045-8e03-4c07-a855-7794ade2e69c',
|
|
19
20
|
action1_data: {
|
|
@@ -61,12 +62,24 @@ describe('Test ThreeButtonTemplate', () => {
|
|
|
61
62
|
|
|
62
63
|
let wrapper;
|
|
63
64
|
|
|
64
|
-
it('render
|
|
65
|
+
it('render ThreeButtonDefault', async () => {
|
|
65
66
|
await act(async () => {
|
|
66
67
|
wrapper = renderer.create(wrapComponent(actionGroup));
|
|
67
68
|
});
|
|
68
69
|
const instance = wrapper.root;
|
|
69
|
-
const
|
|
70
|
-
expect(
|
|
70
|
+
const ThreeButtonDefaults = instance.findAllByType(ThreeButtonDefault);
|
|
71
|
+
expect(ThreeButtonDefaults).toHaveLength(1);
|
|
72
|
+
});
|
|
73
|
+
it('render ThreeButtonCircle', async () => {
|
|
74
|
+
const actionGroupCT = {
|
|
75
|
+
...actionGroup,
|
|
76
|
+
configuration: { ...actionGroup?.configuration, layout: 'circle' },
|
|
77
|
+
};
|
|
78
|
+
await act(async () => {
|
|
79
|
+
wrapper = renderer.create(wrapComponent(actionGroupCT));
|
|
80
|
+
});
|
|
81
|
+
const instance = wrapper.root;
|
|
82
|
+
const ThreeButtonCircles = instance.findAllByType(ThreeButtonCircle);
|
|
83
|
+
expect(ThreeButtonCircles).toHaveLength(1);
|
|
71
84
|
});
|
|
72
85
|
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import React, { memo, useMemo } from 'react';
|
|
2
|
+
import { TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import styles from './ThreeButtonCircleStyles';
|
|
4
|
+
import Text from '../../../Text';
|
|
5
|
+
import { AccessibilityLabel } from '../../../../configs/Constants';
|
|
6
|
+
import IconComponent from '../../../IconComponent';
|
|
7
|
+
import buttonCircleSmall from '../../../../Images/ThreeButton/buttonCircleSmall.png';
|
|
8
|
+
import buttonCircleBig from '../../../../Images/ThreeButton/buttonCircleBig.png';
|
|
9
|
+
import FImage from '../../../FImage';
|
|
10
|
+
|
|
11
|
+
const ThreeButtonCircle = memo(
|
|
12
|
+
({
|
|
13
|
+
icon1,
|
|
14
|
+
text1,
|
|
15
|
+
icon2,
|
|
16
|
+
text2,
|
|
17
|
+
icon3,
|
|
18
|
+
text3,
|
|
19
|
+
onButton1Press,
|
|
20
|
+
onButton2Press,
|
|
21
|
+
onButton3Press,
|
|
22
|
+
}) => {
|
|
23
|
+
const listButton = useMemo(() => {
|
|
24
|
+
return [
|
|
25
|
+
{
|
|
26
|
+
id: 1,
|
|
27
|
+
button: {
|
|
28
|
+
accessibilityLabel: AccessibilityLabel.BUTTON_CIRCLE_TEMPLATE_1,
|
|
29
|
+
onPress: onButton1Press,
|
|
30
|
+
},
|
|
31
|
+
fimage: {
|
|
32
|
+
source: buttonCircleSmall,
|
|
33
|
+
style: styles.iconSmall,
|
|
34
|
+
text: text1,
|
|
35
|
+
icon: icon1,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 2,
|
|
40
|
+
button: {
|
|
41
|
+
accessibilityLabel: AccessibilityLabel.BUTTON_CIRCLE_TEMPLATE_2,
|
|
42
|
+
onPress: onButton2Press,
|
|
43
|
+
},
|
|
44
|
+
fimage: {
|
|
45
|
+
source: buttonCircleBig,
|
|
46
|
+
style: styles.iconBig,
|
|
47
|
+
text: text2,
|
|
48
|
+
icon: icon2,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 3,
|
|
53
|
+
button: {
|
|
54
|
+
accessibilityLabel: AccessibilityLabel.BUTTON_CIRCLE_TEMPLATE_3,
|
|
55
|
+
onPress: onButton3Press,
|
|
56
|
+
},
|
|
57
|
+
fimage: {
|
|
58
|
+
source: buttonCircleSmall,
|
|
59
|
+
style: styles.iconSmall,
|
|
60
|
+
text: text3,
|
|
61
|
+
icon: icon3,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
}, [
|
|
66
|
+
icon1,
|
|
67
|
+
icon2,
|
|
68
|
+
icon3,
|
|
69
|
+
onButton1Press,
|
|
70
|
+
onButton2Press,
|
|
71
|
+
onButton3Press,
|
|
72
|
+
text1,
|
|
73
|
+
text2,
|
|
74
|
+
text3,
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<View style={styles.threeButtonCircle}>
|
|
79
|
+
{listButton.map((item, index) => {
|
|
80
|
+
return (
|
|
81
|
+
<TouchableOpacity
|
|
82
|
+
accessibilityLabel={item?.button?.accessibilityLabel}
|
|
83
|
+
onPress={item?.button?.onPress}
|
|
84
|
+
key={item?.id || index}
|
|
85
|
+
>
|
|
86
|
+
<View style={styles.buttonAction}>
|
|
87
|
+
<FImage
|
|
88
|
+
source={item?.fimage.source}
|
|
89
|
+
style={[styles.center, item?.fimage?.style]}
|
|
90
|
+
>
|
|
91
|
+
<IconComponent icon={item?.fimage?.icon} />
|
|
92
|
+
<Text style={styles.text}>{item?.fimage?.text}</Text>
|
|
93
|
+
</FImage>
|
|
94
|
+
</View>
|
|
95
|
+
</TouchableOpacity>
|
|
96
|
+
);
|
|
97
|
+
})}
|
|
98
|
+
</View>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
export default ThreeButtonCircle;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export default StyleSheet.create({
|
|
4
|
+
threeButtonCircle: {
|
|
5
|
+
flexDirection: 'row',
|
|
6
|
+
alignItems: 'center',
|
|
7
|
+
justifyContent: 'space-around',
|
|
8
|
+
},
|
|
9
|
+
iconSmall: {
|
|
10
|
+
height: 102,
|
|
11
|
+
width: 102,
|
|
12
|
+
marginBottom: 12,
|
|
13
|
+
},
|
|
14
|
+
iconBig: {
|
|
15
|
+
height: 170,
|
|
16
|
+
width: 170,
|
|
17
|
+
paddingBottom: 10,
|
|
18
|
+
},
|
|
19
|
+
center: {
|
|
20
|
+
justifyContent: 'center',
|
|
21
|
+
alignItems: 'center',
|
|
22
|
+
},
|
|
23
|
+
buttonAction: {
|
|
24
|
+
flex: 1,
|
|
25
|
+
aspectRatio: 1,
|
|
26
|
+
marginHorizontal: 4,
|
|
27
|
+
alignItems: 'center',
|
|
28
|
+
justifyContent: 'center',
|
|
29
|
+
resizeMode: 'contain',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import React, { memo, useMemo } from 'react';
|
|
2
|
+
import { TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import styles from './ThreeButtonDefaultStyles';
|
|
4
|
+
import Text from '../../../Text';
|
|
5
|
+
import { AccessibilityLabel } from '../../../../configs/Constants';
|
|
6
|
+
import IconComponent from '../../../IconComponent';
|
|
7
|
+
|
|
8
|
+
const ThreeButtonDefault = memo(
|
|
9
|
+
({
|
|
10
|
+
icon1,
|
|
11
|
+
text1,
|
|
12
|
+
icon2,
|
|
13
|
+
text2,
|
|
14
|
+
icon3,
|
|
15
|
+
text3,
|
|
16
|
+
onButton1Press,
|
|
17
|
+
onButton2Press,
|
|
18
|
+
onButton3Press,
|
|
19
|
+
}) => {
|
|
20
|
+
const Icon2CT = () => {
|
|
21
|
+
return icon2 === 'stop' ? (
|
|
22
|
+
<View style={styles.squareStop} />
|
|
23
|
+
) : (
|
|
24
|
+
<IconComponent icon={icon2} iconSize={30} />
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const listButton = useMemo(() => {
|
|
29
|
+
return [
|
|
30
|
+
{
|
|
31
|
+
id: 1,
|
|
32
|
+
button: {
|
|
33
|
+
accessibilityLabel: AccessibilityLabel.BUTTON_TEMPLATE_1,
|
|
34
|
+
onPress: onButton1Press,
|
|
35
|
+
},
|
|
36
|
+
icon: icon1,
|
|
37
|
+
text: text1,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 2,
|
|
41
|
+
button: {
|
|
42
|
+
accessibilityLabel: AccessibilityLabel.BUTTON_TEMPLATE_2,
|
|
43
|
+
onPress: onButton2Press,
|
|
44
|
+
},
|
|
45
|
+
icon: icon2,
|
|
46
|
+
text: text2,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 3,
|
|
50
|
+
button: {
|
|
51
|
+
accessibilityLabel: AccessibilityLabel.BUTTON_TEMPLATE_3,
|
|
52
|
+
onPress: onButton3Press,
|
|
53
|
+
},
|
|
54
|
+
icon: icon3,
|
|
55
|
+
text: text3,
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
}, [
|
|
59
|
+
icon1,
|
|
60
|
+
icon2,
|
|
61
|
+
icon3,
|
|
62
|
+
onButton1Press,
|
|
63
|
+
onButton2Press,
|
|
64
|
+
onButton3Press,
|
|
65
|
+
text1,
|
|
66
|
+
text2,
|
|
67
|
+
text3,
|
|
68
|
+
]);
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<View style={styles.threeButtonDefault}>
|
|
72
|
+
{listButton.map((item, index) => {
|
|
73
|
+
return (
|
|
74
|
+
<TouchableOpacity
|
|
75
|
+
accessibilityLabel={item?.button?.accessibilityLabel}
|
|
76
|
+
style={styles.buttonAction}
|
|
77
|
+
onPress={item?.button?.onPress}
|
|
78
|
+
key={item?.id || index}
|
|
79
|
+
>
|
|
80
|
+
<View style={styles.imageButton}>
|
|
81
|
+
{item?.id === 2 ? (
|
|
82
|
+
<Icon2CT />
|
|
83
|
+
) : (
|
|
84
|
+
<IconComponent icon={item?.icon} iconSize={30} />
|
|
85
|
+
)}
|
|
86
|
+
</View>
|
|
87
|
+
<Text style={styles.text}>{item?.text}</Text>
|
|
88
|
+
</TouchableOpacity>
|
|
89
|
+
);
|
|
90
|
+
})}
|
|
91
|
+
</View>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
export default ThreeButtonDefault;
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
|
-
import { Colors } from '
|
|
2
|
+
import { Colors } from '../../../../configs';
|
|
3
3
|
|
|
4
4
|
export default StyleSheet.create({
|
|
5
|
-
|
|
6
|
-
flex: 1,
|
|
7
|
-
marginBottom: 16,
|
|
8
|
-
},
|
|
9
|
-
threeButton: {
|
|
5
|
+
threeButtonDefault: {
|
|
10
6
|
flexDirection: 'row',
|
|
11
7
|
justifyContent: 'space-around',
|
|
12
8
|
padding: 16,
|
|
@@ -15,15 +11,7 @@ export default StyleSheet.create({
|
|
|
15
11
|
borderColor: Colors.Gray4,
|
|
16
12
|
borderRadius: 10,
|
|
17
13
|
},
|
|
18
|
-
|
|
19
|
-
height: 32,
|
|
20
|
-
marginBottom: 7,
|
|
21
|
-
},
|
|
22
|
-
text: {
|
|
23
|
-
fontSize: 14,
|
|
24
|
-
lineHeight: 22,
|
|
25
|
-
},
|
|
26
|
-
buttonActionDoor: {
|
|
14
|
+
buttonAction: {
|
|
27
15
|
flex: 1,
|
|
28
16
|
aspectRatio: 1,
|
|
29
17
|
marginHorizontal: 4,
|
|
@@ -34,6 +22,14 @@ export default StyleSheet.create({
|
|
|
34
22
|
borderColor: Colors.Gray3,
|
|
35
23
|
borderRadius: 10,
|
|
36
24
|
},
|
|
25
|
+
imageButton: {
|
|
26
|
+
height: 32,
|
|
27
|
+
marginBottom: 7,
|
|
28
|
+
},
|
|
29
|
+
text: {
|
|
30
|
+
fontSize: 14,
|
|
31
|
+
lineHeight: 22,
|
|
32
|
+
},
|
|
37
33
|
squareStop: {
|
|
38
34
|
marginHorizontal: 8,
|
|
39
35
|
marginVertical: 8,
|
|
@@ -44,23 +40,4 @@ export default StyleSheet.create({
|
|
|
44
40
|
backgroundColor: Colors.Primary,
|
|
45
41
|
borderRadius: 1,
|
|
46
42
|
},
|
|
47
|
-
lockSwitch: {
|
|
48
|
-
flexDirection: 'row',
|
|
49
|
-
justifyContent: 'space-between',
|
|
50
|
-
marginBottom: 7,
|
|
51
|
-
},
|
|
52
|
-
iconLock: {
|
|
53
|
-
paddingBottom: 7,
|
|
54
|
-
},
|
|
55
|
-
textLockDoor: {
|
|
56
|
-
paddingLeft: 12,
|
|
57
|
-
height: 24,
|
|
58
|
-
fontSize: 16,
|
|
59
|
-
lineHeight: 24,
|
|
60
|
-
},
|
|
61
|
-
lockDoor: {
|
|
62
|
-
flexDirection: 'row',
|
|
63
|
-
alignItems: 'flex-end',
|
|
64
|
-
paddingLeft: 5,
|
|
65
|
-
},
|
|
66
43
|
});
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import React, { memo, useCallback, useState } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import styles from './
|
|
4
|
-
import Text from '
|
|
5
|
-
import { AccessibilityLabel } from '
|
|
6
|
-
import { Colors } from '
|
|
7
|
-
import IconComponent from '
|
|
1
|
+
import React, { memo, useCallback, useState, useMemo } from 'react';
|
|
2
|
+
import { View, Switch } from 'react-native';
|
|
3
|
+
import styles from './styles';
|
|
4
|
+
import Text from '../../Text';
|
|
5
|
+
import { AccessibilityLabel } from '../../../configs/Constants';
|
|
6
|
+
import { Colors } from '../../../configs';
|
|
7
|
+
import IconComponent from '../../IconComponent';
|
|
8
|
+
import ThreeButtonCircle from './components/ThreeButtonCircle';
|
|
9
|
+
import ThreeButtonDefault from './components/ThreeButtonDefault';
|
|
8
10
|
|
|
9
11
|
const ThreeButtonTemplate = memo(({ actionGroup, doAction }) => {
|
|
10
12
|
const { configuration } = actionGroup;
|
|
@@ -25,15 +27,11 @@ const ThreeButtonTemplate = memo(({ actionGroup, doAction }) => {
|
|
|
25
27
|
icon_kit3_data,
|
|
26
28
|
text_door_lock,
|
|
27
29
|
is_display_lock,
|
|
30
|
+
layout,
|
|
28
31
|
} = configuration || {};
|
|
32
|
+
|
|
29
33
|
const [lock, setLock] = useState(false);
|
|
30
|
-
|
|
31
|
-
return icon === 'stop' ? (
|
|
32
|
-
<View style={styles.squareStop} />
|
|
33
|
-
) : (
|
|
34
|
-
<IconComponent icon={icon} iconSize={30} />
|
|
35
|
-
);
|
|
36
|
-
};
|
|
34
|
+
|
|
37
35
|
const onButton1Press = useCallback(() => {
|
|
38
36
|
doAction(action1_data, null);
|
|
39
37
|
}, [action1_data, doAction]);
|
|
@@ -84,45 +82,44 @@ const ThreeButtonTemplate = memo(({ actionGroup, doAction }) => {
|
|
|
84
82
|
);
|
|
85
83
|
};
|
|
86
84
|
|
|
85
|
+
const renderLayoutThreeButton = useMemo(() => {
|
|
86
|
+
const props = {
|
|
87
|
+
icon1: icon_kit1_data?.icon || icon1,
|
|
88
|
+
icon2: icon_kit2_data?.icon || icon2,
|
|
89
|
+
icon3: icon_kit3_data?.icon || icon3,
|
|
90
|
+
text1: text1,
|
|
91
|
+
text2: text2,
|
|
92
|
+
text3: text3,
|
|
93
|
+
onButton1Press: onButton1Press,
|
|
94
|
+
onButton2Press: onButton2Press,
|
|
95
|
+
onButton3Press: onButton3Press,
|
|
96
|
+
};
|
|
97
|
+
switch (layout) {
|
|
98
|
+
case 'circle': {
|
|
99
|
+
return <ThreeButtonCircle {...props} />;
|
|
100
|
+
}
|
|
101
|
+
default:
|
|
102
|
+
return <ThreeButtonDefault {...props} />;
|
|
103
|
+
}
|
|
104
|
+
}, [
|
|
105
|
+
icon1,
|
|
106
|
+
icon2,
|
|
107
|
+
icon3,
|
|
108
|
+
icon_kit1_data?.icon,
|
|
109
|
+
icon_kit2_data?.icon,
|
|
110
|
+
icon_kit3_data?.icon,
|
|
111
|
+
layout,
|
|
112
|
+
onButton1Press,
|
|
113
|
+
onButton2Press,
|
|
114
|
+
onButton3Press,
|
|
115
|
+
text1,
|
|
116
|
+
text2,
|
|
117
|
+
text3,
|
|
118
|
+
]);
|
|
119
|
+
|
|
87
120
|
return (
|
|
88
121
|
<View style={styles.wrap}>
|
|
89
|
-
|
|
90
|
-
<TouchableOpacity
|
|
91
|
-
accessibilityLabel={AccessibilityLabel.BUTTON_TEMPLATE_1}
|
|
92
|
-
style={styles.buttonActionDoor}
|
|
93
|
-
onPress={onButton1Press}
|
|
94
|
-
underlayColor={Colors.Gray2}
|
|
95
|
-
>
|
|
96
|
-
<View style={styles.imageButton}>
|
|
97
|
-
<IconComponent icon={icon_kit1_data?.icon || icon1} iconSize={30} />
|
|
98
|
-
</View>
|
|
99
|
-
<Text style={styles.text}>{text1}</Text>
|
|
100
|
-
</TouchableOpacity>
|
|
101
|
-
|
|
102
|
-
<TouchableOpacity
|
|
103
|
-
accessibilityLabel={AccessibilityLabel.BUTTON_TEMPLATE_2}
|
|
104
|
-
style={styles.buttonActionDoor}
|
|
105
|
-
onPress={onButton2Press}
|
|
106
|
-
underlayColor={Colors.Gray2}
|
|
107
|
-
>
|
|
108
|
-
<View style={styles.imageButton}>
|
|
109
|
-
{iconCustom(icon_kit2_data?.icon || icon2)}
|
|
110
|
-
</View>
|
|
111
|
-
<Text style={styles.text}>{text2}</Text>
|
|
112
|
-
</TouchableOpacity>
|
|
113
|
-
|
|
114
|
-
<TouchableOpacity
|
|
115
|
-
accessibilityLabel={AccessibilityLabel.BUTTON_TEMPLATE_3}
|
|
116
|
-
style={styles.buttonActionDoor}
|
|
117
|
-
onPress={onButton3Press}
|
|
118
|
-
underlayColor={Colors.Gray2}
|
|
119
|
-
>
|
|
120
|
-
<View style={styles.imageButton}>
|
|
121
|
-
<IconComponent icon={icon_kit3_data?.icon || icon3} iconSize={30} />
|
|
122
|
-
</View>
|
|
123
|
-
<Text style={styles.text}>{text3}</Text>
|
|
124
|
-
</TouchableOpacity>
|
|
125
|
-
</View>
|
|
122
|
+
{renderLayoutThreeButton}
|
|
126
123
|
<View style={styles.lockSwitch}>
|
|
127
124
|
{is_display_lock &&
|
|
128
125
|
itemLock(
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export default StyleSheet.create({
|
|
4
|
+
wrap: {
|
|
5
|
+
flex: 1,
|
|
6
|
+
marginBottom: 16,
|
|
7
|
+
},
|
|
8
|
+
lockSwitch: {
|
|
9
|
+
flexDirection: 'row',
|
|
10
|
+
justifyContent: 'space-between',
|
|
11
|
+
marginBottom: 7,
|
|
12
|
+
},
|
|
13
|
+
iconLock: {
|
|
14
|
+
paddingBottom: 7,
|
|
15
|
+
},
|
|
16
|
+
textLockDoor: {
|
|
17
|
+
paddingLeft: 12,
|
|
18
|
+
height: 24,
|
|
19
|
+
fontSize: 16,
|
|
20
|
+
lineHeight: 24,
|
|
21
|
+
},
|
|
22
|
+
lockDoor: {
|
|
23
|
+
flexDirection: 'row',
|
|
24
|
+
alignItems: 'flex-end',
|
|
25
|
+
paddingLeft: 5,
|
|
26
|
+
},
|
|
27
|
+
});
|
package/src/configs/SCConfig.js
CHANGED
|
@@ -99,6 +99,7 @@ const SCDefaultConfig = {
|
|
|
99
99
|
pusherAppCluster: 'ap1',
|
|
100
100
|
intervalWatchConfigTime: 30000,
|
|
101
101
|
setCurrentSensorDisplay: () => {},
|
|
102
|
+
appName: 'E-Ra',
|
|
102
103
|
};
|
|
103
104
|
|
|
104
105
|
export class SCConfig {
|
|
@@ -115,6 +116,7 @@ export class SCConfig {
|
|
|
115
116
|
static language = 'en';
|
|
116
117
|
static intervalWatchConfigTime = SCDefaultConfig.intervalWatchConfigTime;
|
|
117
118
|
static setCurrentSensorDisplay = SCDefaultConfig.setCurrentSensorDisplay;
|
|
119
|
+
static appName = SCDefaultConfig.appName;
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
export const initSCConfig = (config) => {
|
|
@@ -140,4 +142,5 @@ export const initSCConfig = (config) => {
|
|
|
140
142
|
config.intervalWatchConfigTime ?? SCDefaultConfig.intervalWatchConfigTime;
|
|
141
143
|
SCConfig.setCurrentSensorDisplay =
|
|
142
144
|
config.setCurrentSensorDisplay ?? SCDefaultConfig.setCurrentSensorDisplay;
|
|
145
|
+
SCConfig.appName = config.appName ?? SCDefaultConfig.appName;
|
|
143
146
|
};
|
|
@@ -6,6 +6,7 @@ import { scanBluetoothDevices } from '../../iot/RemoteControl/Bluetooth';
|
|
|
6
6
|
import Permissions from 'react-native-permissions';
|
|
7
7
|
import { OpenSetting } from '../../utils/Permission/common';
|
|
8
8
|
import { useTranslations } from '../Common/useTranslations';
|
|
9
|
+
import { SCConfig } from '../../configs';
|
|
9
10
|
|
|
10
11
|
const permissions = [
|
|
11
12
|
'android.permission.BLUETOOTH_CONNECT',
|
|
@@ -77,7 +78,7 @@ const useBluetoothConnection = (fnCallback) => {
|
|
|
77
78
|
if (blocked) {
|
|
78
79
|
OpenSetting(
|
|
79
80
|
t('bluetooth_rationale_title'),
|
|
80
|
-
t('bluetooth_rationale_message')
|
|
81
|
+
t('bluetooth_rationale_message', { appName: SCConfig.appName })
|
|
81
82
|
);
|
|
82
83
|
}
|
|
83
84
|
const granted = Object.values(results).every((result) =>
|
|
@@ -150,7 +150,7 @@ const AddLocationMaps = memo(() => {
|
|
|
150
150
|
permissionResult === RESULTS.BLOCKED &&
|
|
151
151
|
OpenSetting(
|
|
152
152
|
t('location_rationale_title'),
|
|
153
|
-
t('location_require_message')
|
|
153
|
+
t('location_require_message', { appName: SCConfig.appName })
|
|
154
154
|
);
|
|
155
155
|
} else if (error.code === GEOLOCATION_ERROR.POSITION_UNAVAILABLE) {
|
|
156
156
|
const locationEnabaled = await openPromptEnableLocation();
|
|
@@ -18,6 +18,7 @@ import AccessibilityLabel from '../../configs/AccessibilityLabel';
|
|
|
18
18
|
import LoadingCircle from '../../Images/Common/loading-circle.json';
|
|
19
19
|
import FullLoading from '../../commons/FullLoading';
|
|
20
20
|
import { useWifiManage } from './hooks/useWifiManage';
|
|
21
|
+
import { SCConfig } from '../../configs';
|
|
21
22
|
|
|
22
23
|
let intervalSend = null;
|
|
23
24
|
let socket;
|
|
@@ -196,7 +197,9 @@ const ConnectingWifiGuide = ({ route }) => {
|
|
|
196
197
|
<>
|
|
197
198
|
<View style={styles.guideContent}>
|
|
198
199
|
<InteractSmartphoneIcon width={94} height={94} />
|
|
199
|
-
<Text style={styles.txtContent}>
|
|
200
|
+
<Text style={styles.txtContent}>
|
|
201
|
+
{t('connect_wifi_asking', { appName: SCConfig.appName })}
|
|
202
|
+
</Text>
|
|
200
203
|
</View>
|
|
201
204
|
<BottomButtonView
|
|
202
205
|
style={styles.bottomButtonView}
|
|
@@ -4,11 +4,13 @@ import { useRoute, useNavigation } from '@react-navigation/native';
|
|
|
4
4
|
|
|
5
5
|
import DetailConfigAction from '../components/DetailConfigAction';
|
|
6
6
|
import DetailActionModbus from '../components/DetailActionModbus';
|
|
7
|
+
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
7
8
|
import { calculateLength, calculateStartAddress } from '../utils';
|
|
8
9
|
import Routes from '../../../utils/Route';
|
|
9
10
|
import styles from './styles';
|
|
10
11
|
|
|
11
12
|
const DetailConfigActionModbus = () => {
|
|
13
|
+
const t = useTranslations();
|
|
12
14
|
const { params = {} } = useRoute();
|
|
13
15
|
const { navigate } = useNavigation();
|
|
14
16
|
const {
|
|
@@ -46,7 +48,7 @@ const DetailConfigActionModbus = () => {
|
|
|
46
48
|
},
|
|
47
49
|
{
|
|
48
50
|
id: 2,
|
|
49
|
-
title: '
|
|
51
|
+
title: t('data_address'),
|
|
50
52
|
data: sa,
|
|
51
53
|
},
|
|
52
54
|
{
|
|
@@ -55,7 +57,7 @@ const DetailConfigActionModbus = () => {
|
|
|
55
57
|
data: len,
|
|
56
58
|
},
|
|
57
59
|
],
|
|
58
|
-
[itemActionConfig?.func, len, sa]
|
|
60
|
+
[itemActionConfig?.func, len, sa, t]
|
|
59
61
|
);
|
|
60
62
|
|
|
61
63
|
const listConfigWrite = useMemo(
|
|
@@ -67,7 +69,7 @@ const DetailConfigActionModbus = () => {
|
|
|
67
69
|
},
|
|
68
70
|
{
|
|
69
71
|
id: 2,
|
|
70
|
-
title: '
|
|
72
|
+
title: t('data_address'),
|
|
71
73
|
data: sa,
|
|
72
74
|
},
|
|
73
75
|
{
|
|
@@ -81,7 +83,7 @@ const DetailConfigActionModbus = () => {
|
|
|
81
83
|
data: itemActionConfig?.ex || '--',
|
|
82
84
|
},
|
|
83
85
|
],
|
|
84
|
-
[itemActionConfig?.ex, itemActionConfig?.func, len, sa]
|
|
86
|
+
[itemActionConfig?.ex, itemActionConfig?.func, len, sa, t]
|
|
85
87
|
);
|
|
86
88
|
|
|
87
89
|
const listAction = useMemo(
|
|
@@ -7,6 +7,7 @@ import { mockSCStore } from '../../../../context/mockStore';
|
|
|
7
7
|
import GatewayConnectionMethods from '..';
|
|
8
8
|
import { HeaderCustom } from '../../../../commons';
|
|
9
9
|
import { AccessibilityLabel } from '../../../../configs/Constants';
|
|
10
|
+
import { getTranslate } from '../../../../utils/I18n';
|
|
10
11
|
|
|
11
12
|
const wrapComponent = () => (
|
|
12
13
|
<SCProvider initState={mockSCStore({})}>
|
|
@@ -31,7 +32,9 @@ describe('Test GatewayConnectionMethods', () => {
|
|
|
31
32
|
|
|
32
33
|
expect(headerCustom).toHaveLength(1);
|
|
33
34
|
expect(text.props.children).toEqual(
|
|
34
|
-
'
|
|
35
|
+
getTranslate('en', 'visit_eoh_web_to_set_up_other_connection', {
|
|
36
|
+
appName: 'E-Ra',
|
|
37
|
+
})
|
|
35
38
|
);
|
|
36
39
|
expect(flatList).toHaveLength(1);
|
|
37
40
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useCallback, memo, useMemo } from 'react';
|
|
2
2
|
import { View, FlatList } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import { Colors } from '../../../configs';
|
|
4
|
+
import { Colors, SCConfig } from '../../../configs';
|
|
5
5
|
import t from '../../../hooks/Common/useTranslations';
|
|
6
6
|
import { Text, HeaderCustom } from '../../../commons';
|
|
7
7
|
import styles from './styles';
|
|
@@ -56,7 +56,9 @@ const GatewayConnectionMethods = () => {
|
|
|
56
56
|
AccessibilityLabel.GATEWAY_CONNECTION_METHODS_TEXT
|
|
57
57
|
}
|
|
58
58
|
>
|
|
59
|
-
{t('visit_eoh_web_to_set_up_other_connection'
|
|
59
|
+
{t('visit_eoh_web_to_set_up_other_connection', {
|
|
60
|
+
appName: SCConfig.appName,
|
|
61
|
+
})}
|
|
60
62
|
</Text>
|
|
61
63
|
<FlatList
|
|
62
64
|
contentContainerStyle={styles.contentContainerStyle}
|
|
@@ -14,6 +14,7 @@ import api from '../../../../utils/Apis/axios';
|
|
|
14
14
|
import GatewayInfo from '..';
|
|
15
15
|
import t from '../../../../hooks/Common/useTranslations';
|
|
16
16
|
import ModalPopupCT from '../../../../commons/ModalPopupCT';
|
|
17
|
+
import { SCConfig } from '../../../../configs';
|
|
17
18
|
|
|
18
19
|
const mockPop = jest.fn();
|
|
19
20
|
const mock = new MockAdapter(api.axiosInstance);
|
|
@@ -93,7 +94,7 @@ describe('Test GatewayInfo', () => {
|
|
|
93
94
|
const btnDelete = buttonDelete(instance);
|
|
94
95
|
expect(headerCustom).toHaveLength(1);
|
|
95
96
|
expect(alert.props.children[1].props.children.props.children).toEqual(
|
|
96
|
-
t('go_to_eoh_web_to_see_firmware')
|
|
97
|
+
t('go_to_eoh_web_to_see_firmware', { appName: SCConfig.appName })
|
|
97
98
|
);
|
|
98
99
|
expect(flatList).toHaveLength(1);
|
|
99
100
|
const textConnect = btnConnect.findAllByType(Text);
|
|
@@ -7,6 +7,7 @@ import { mockSCStore } from '../../../../../context/mockStore';
|
|
|
7
7
|
import { HeaderCustom } from '../../../../../commons';
|
|
8
8
|
import Information from '../../../components/Information';
|
|
9
9
|
import { AccessibilityLabel } from '../../../../../configs/Constants';
|
|
10
|
+
import { getTranslate } from '../../../../../utils/I18n';
|
|
10
11
|
|
|
11
12
|
const mockHandleDeleteGateway = jest.fn();
|
|
12
13
|
const mockHandleConnectionMethods = jest.fn();
|
|
@@ -51,7 +52,7 @@ describe('Test Information', () => {
|
|
|
51
52
|
expect(headerCustom).toHaveLength(1);
|
|
52
53
|
expect(flatList).toHaveLength(1);
|
|
53
54
|
expect(viewAlert.props.children[1].props.children.props.children).toEqual(
|
|
54
|
-
'
|
|
55
|
+
getTranslate('en', 'go_to_eoh_web_to_see_firmware', { appName: 'E-Ra' })
|
|
55
56
|
);
|
|
56
57
|
const buttonConnect = instance.findByProps({
|
|
57
58
|
accessibilityLabel:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useCallback, memo } from 'react';
|
|
2
2
|
import { TouchableOpacity, View, Image, FlatList } from 'react-native';
|
|
3
|
-
import { Colors } from '../../../../configs';
|
|
3
|
+
import { Colors, SCConfig } from '../../../../configs';
|
|
4
4
|
import t from '../../../../hooks/Common/useTranslations';
|
|
5
5
|
import { Text, HeaderCustom } from '../../../../commons';
|
|
6
6
|
import Images from '../../../../configs/Images';
|
|
@@ -51,7 +51,9 @@ const Information = ({
|
|
|
51
51
|
<Image source={Images.inforCode} />
|
|
52
52
|
<View style={styles.flex1}>
|
|
53
53
|
<Text type="H4" style={styles.marginLeft16}>
|
|
54
|
-
{t('go_to_eoh_web_to_see_firmware'
|
|
54
|
+
{t('go_to_eoh_web_to_see_firmware', {
|
|
55
|
+
appName: SCConfig.appName,
|
|
56
|
+
})}
|
|
55
57
|
</Text>
|
|
56
58
|
</View>
|
|
57
59
|
</View>
|
|
@@ -12,7 +12,7 @@ import Text from '../../commons/Text';
|
|
|
12
12
|
import { useBoolean } from '../../hooks/Common';
|
|
13
13
|
import { axiosGet, axiosPut } from '../../utils/Apis/axios';
|
|
14
14
|
|
|
15
|
-
import { API, Colors } from '../../configs';
|
|
15
|
+
import { API, Colors, SCConfig } from '../../configs';
|
|
16
16
|
import {
|
|
17
17
|
ACCESS_SCHEDULE_PROPERTIES,
|
|
18
18
|
typeMaps,
|
|
@@ -123,7 +123,7 @@ const GuestInfo = ({ route }) => {
|
|
|
123
123
|
)}
|
|
124
124
|
{guest?.id && (
|
|
125
125
|
<RowGuestInfo
|
|
126
|
-
textLeft={t('eoh_account_id')}
|
|
126
|
+
textLeft={t('eoh_account_id', { appName: SCConfig.appName })}
|
|
127
127
|
textRight={guest.id}
|
|
128
128
|
/>
|
|
129
129
|
)}
|
|
@@ -4,7 +4,7 @@ import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
|
4
4
|
import { CircleView } from '../../commons/CircleView';
|
|
5
5
|
import Text from '../../commons/Text';
|
|
6
6
|
import { shortEmailName } from '../../utils/Utils';
|
|
7
|
-
import { Colors, Images, API } from '../../configs';
|
|
7
|
+
import { Colors, Images, API, SCConfig } from '../../configs';
|
|
8
8
|
import { HeaderCustom } from '../../commons/Header';
|
|
9
9
|
import RowMemberInfo from '../GuestInfo/components/RowGuestInfo';
|
|
10
10
|
import { useIsOwnerOfUnit } from '../../hooks/Common';
|
|
@@ -203,7 +203,7 @@ const InfoMemberUnit = memo(({ route }) => {
|
|
|
203
203
|
)}
|
|
204
204
|
{memberInfo?.id && (
|
|
205
205
|
<RowMemberInfo
|
|
206
|
-
textLeft={t('eoh_account_id')}
|
|
206
|
+
textLeft={t('eoh_account_id', { appName: SCConfig.appName })}
|
|
207
207
|
textRight={memberInfo?.phone_number || memberInfo.id}
|
|
208
208
|
/>
|
|
209
209
|
)}
|
|
@@ -148,7 +148,7 @@ const SelectAddress = memo(({ route }) => {
|
|
|
148
148
|
permissionResult === RESULTS.BLOCKED &&
|
|
149
149
|
OpenSetting(
|
|
150
150
|
t('location_rationale_title'),
|
|
151
|
-
t('location_require_message')
|
|
151
|
+
t('location_require_message', { appName: SCConfig.appName })
|
|
152
152
|
);
|
|
153
153
|
} else if (error.code === GEOLOCATION_ERROR.POSITION_UNAVAILABLE) {
|
|
154
154
|
const locationEnabaled = await openPromptEnableLocation();
|
|
@@ -253,13 +253,13 @@
|
|
|
253
253
|
"popular_locations": "Popular locations",
|
|
254
254
|
"text_search_location_placeholder": "Search public areas, shops, restaurants,...",
|
|
255
255
|
"location_rationale_title": "Location Permission Required",
|
|
256
|
-
"location_rationale_message": "
|
|
256
|
+
"location_rationale_message": "{appName} only uses your location to display weather and air quality.",
|
|
257
257
|
"camera_rationale_title": "Camera Permission Required",
|
|
258
|
-
"camera_rationale_message": "
|
|
258
|
+
"camera_rationale_message": "{appName} only uses your camera to take photo",
|
|
259
259
|
"photo_rationale_title": "Photo Permission Required",
|
|
260
|
-
"photo_rationale_message": "
|
|
260
|
+
"photo_rationale_message": "{appName} only uses your photo to upload",
|
|
261
261
|
"bluetooth_rationale_title": "Bluetooth Permission Required",
|
|
262
|
-
"bluetooth_rationale_message": "
|
|
262
|
+
"bluetooth_rationale_message": "{appName} only uses Bluetooth to scan and control devices",
|
|
263
263
|
"recommendations": "Recommendations",
|
|
264
264
|
"Open windows for more fresh air": "Open windows for more fresh air",
|
|
265
265
|
"notify_new_version_title": "Update available",
|
|
@@ -624,7 +624,7 @@
|
|
|
624
624
|
"your_location_info": "Your location information:",
|
|
625
625
|
"text_send_now": "SEND NOW",
|
|
626
626
|
"text_no_charge_outside_parking_hour": "There is no charge outside these parking hour",
|
|
627
|
-
"notify_update_app": "A new
|
|
627
|
+
"notify_update_app": "A new {appName} update is now available. Please update to new version to continue using the app.",
|
|
628
628
|
"update_now": "Update now",
|
|
629
629
|
"removed_successfully": "Removed successfully!",
|
|
630
630
|
"spot_name": "Spot name",
|
|
@@ -736,7 +736,7 @@
|
|
|
736
736
|
"guests": "Guests",
|
|
737
737
|
"no_guest": "No guest",
|
|
738
738
|
"guest_info": "Guest Information",
|
|
739
|
-
"eoh_account_id": "
|
|
739
|
+
"eoh_account_id": "{appName} account ID",
|
|
740
740
|
"access_schedule": "Access Schedule",
|
|
741
741
|
"always": "Always",
|
|
742
742
|
"recurring": "Recurring",
|
|
@@ -903,7 +903,7 @@
|
|
|
903
903
|
"gateway_warning_content_3": "In the next steps, you will be instructed to connect to wifi for the device. ",
|
|
904
904
|
"gateway_warning_content_4": "To give you a good experience, you need to know the name and password of the wifi network and make sure the device is placed in a good location.",
|
|
905
905
|
"warning_beta_test_feature": "This feature is in beta test, not official yet",
|
|
906
|
-
"connecting_gateway_warning_1": "By continuing,
|
|
906
|
+
"connecting_gateway_warning_1": "By continuing, {appName} needs to connect to the device's wifi.",
|
|
907
907
|
"connecting_gateway_warning_2": "A message will appear asking you to connect.",
|
|
908
908
|
"remove_account": "Remove Account",
|
|
909
909
|
"brightness": "Brightness",
|
|
@@ -974,7 +974,7 @@
|
|
|
974
974
|
"This {name} was removed!" : "This {name} was removed!",
|
|
975
975
|
"camera_request_permission": "Camera request permission",
|
|
976
976
|
"camera_request_permission_des": "To use camera, please unlock camera permission",
|
|
977
|
-
"location_require_message": "
|
|
977
|
+
"location_require_message": "{appName} needs your location permission to get current location.",
|
|
978
978
|
"turn_on_location_service": "Turn on location service for your phone",
|
|
979
979
|
"turn_on_location_service_des": "To continue, let your device turn on location by turning on location service in Settings",
|
|
980
980
|
"detected": "Detected",
|
|
@@ -1021,7 +1021,7 @@
|
|
|
1021
1021
|
"device_connect_directly_to_the_gateway": "Device connected directly to the gateway",
|
|
1022
1022
|
"zigbee": "Zigbee",
|
|
1023
1023
|
"device_connect_remotely_to_the_gateway": "Device connected remotely to the gateway",
|
|
1024
|
-
"connect_wifi_asking": "By continuing,
|
|
1024
|
+
"connect_wifi_asking": "By continuing, {appName} needs to connect to the device's Wifi. A message will appear asking you to connect.",
|
|
1025
1025
|
"previous": "Previous",
|
|
1026
1026
|
"invalid_qr_code": "Invalid QR Code",
|
|
1027
1027
|
"invalid_qr_code_warning": "This device can't be added using a QR code",
|
|
@@ -1052,7 +1052,7 @@
|
|
|
1052
1052
|
"need_add_gateway_before_add_device": "You need to add a new Gateway before adding the device.",
|
|
1053
1053
|
"fail_to_discover_device_wifi": "Fail to discover device wifi",
|
|
1054
1054
|
"try_to_turn_on_device_or_try_again": "Try to turn on device or Try again",
|
|
1055
|
-
"go_to_eoh_web_to_see_firmware": "Go to
|
|
1055
|
+
"go_to_eoh_web_to_see_firmware": "Go to {appName} web to see firmware configuration",
|
|
1056
1056
|
"general_information":"General information",
|
|
1057
1057
|
"connection_methods": "Connection methods",
|
|
1058
1058
|
"delete_gateway":"Delete gateway",
|
|
@@ -1062,7 +1062,7 @@
|
|
|
1062
1062
|
"activate_date":"Activate date",
|
|
1063
1063
|
"warranty_expiration_date":"Warranty expiration date",
|
|
1064
1064
|
"firmware_version":"Firmware version",
|
|
1065
|
-
"visit_eoh_web_to_set_up_other_connection": "Visit
|
|
1065
|
+
"visit_eoh_web_to_set_up_other_connection": "Visit {appName} Web to set up other connection options.",
|
|
1066
1066
|
"delete_successfully":"Delete successfully!",
|
|
1067
1067
|
"reboot_successfully": "Reboot successfully!",
|
|
1068
1068
|
"message_delete_gateway": "This will fully remove Gateway with Info, Devices, Data Stream from the gateway.",
|
|
@@ -1114,5 +1114,6 @@
|
|
|
1114
1114
|
"default_value": "Default value",
|
|
1115
1115
|
"config_type": "Config type",
|
|
1116
1116
|
"pin": "PIN",
|
|
1117
|
-
"pin_mode": "PIN mode"
|
|
1117
|
+
"pin_mode": "PIN mode",
|
|
1118
|
+
"data_address": "Data address"
|
|
1118
1119
|
}
|
|
@@ -288,13 +288,13 @@
|
|
|
288
288
|
"popular_locations": "Địa điểm phổ biến",
|
|
289
289
|
"text_search_location_placeholder": "Tìm kiếm địa điểm công cộng, cửa hàng, nhà hàng,...",
|
|
290
290
|
"location_rationale_title": "Yêu cầu cho phép truy cập vị trí",
|
|
291
|
-
"location_rationale_message": "
|
|
291
|
+
"location_rationale_message": "{appName} chỉ sử dụng vị trí của bạn để hiển thị thông tin thời tiết và chất lượng không khí.",
|
|
292
292
|
"camera_rationale_title": "Yêu cầu cho phép truy cập máy ảnh",
|
|
293
|
-
"camera_rationale_message": "
|
|
293
|
+
"camera_rationale_message": "{appName} chỉ sử dụng máy ảnh của bạn",
|
|
294
294
|
"photo_rationale_title": "Yêu cầu cho phép truy cập ảnh",
|
|
295
|
-
"photo_rationale_message": "
|
|
295
|
+
"photo_rationale_message": "{appName} chỉ sử dụng thư viện ảnh để upload",
|
|
296
296
|
"bluetooth_rationale_title": "Yêu cầu cho phép sử dụng Bluetooth",
|
|
297
|
-
"bluetooth_rationale_message": "
|
|
297
|
+
"bluetooth_rationale_message": "{appName} sử dụng Bluetooth để quét và điều khiển thiết bị",
|
|
298
298
|
"recommendations": "Đề xuất",
|
|
299
299
|
"Open windows for more fresh air": "Mở cửa sổ để đưa không khí sạch vào nhà",
|
|
300
300
|
"notify_new_version_title": "Có bản cập nhật!",
|
|
@@ -742,7 +742,7 @@
|
|
|
742
742
|
"guests": "Những vị khách",
|
|
743
743
|
"no_guest": "Không có vị khách nào",
|
|
744
744
|
"guest_info": "Thông tin khách",
|
|
745
|
-
"eoh_account_id": "ID tài khoản
|
|
745
|
+
"eoh_account_id": "ID tài khoản {appName}",
|
|
746
746
|
"access_schedule": "Lịch truy cập",
|
|
747
747
|
"always": "Luôn luôn",
|
|
748
748
|
"recurring": "Tuần hoàn",
|
|
@@ -901,7 +901,7 @@
|
|
|
901
901
|
"gateway_warning_content_3": "Trong các bước tiếp theo, bạn sẽ được hướng dẫn kết nối wifi cho thiết bị. ",
|
|
902
902
|
"gateway_warning_content_4": "Bạn cần biết tên và mật khẩu của mạng wifi và đảm bảo thiết bị được đặt ở vị trí tốt.",
|
|
903
903
|
"warning_beta_test_feature": "Tính năng này đang ở giai đoạn beta test, chưa phải bản chính thức.",
|
|
904
|
-
"connecting_gateway_warning_1": "Bằng việc tiếp tục,
|
|
904
|
+
"connecting_gateway_warning_1": "Bằng việc tiếp tục, {appName} cần kết nối với Wifi của thiết bị.",
|
|
905
905
|
"connecting_gateway_warning_2": "Một thông báo sẽ hiện lên và yêu cầu bạn kết nối.",
|
|
906
906
|
"add_gateway_success": "Thêm gateway thành công",
|
|
907
907
|
"tap_to_add_new_schedule": "Nhấn + để thêm lịch trình mới",
|
|
@@ -973,7 +973,7 @@
|
|
|
973
973
|
"location_perm_denied": "Ứng dụng không cho phép truy cập vị trí.",
|
|
974
974
|
"camera_request_permission": "Quyền yêu cầu máy ảnh",
|
|
975
975
|
"camera_request_permission_des": "Để sử dụng máy ảnh, vui lòng mở khóa quyền đối với máy ảnh",
|
|
976
|
-
"location_require_message": "
|
|
976
|
+
"location_require_message": "{appName} cần quyền truy cập vị trí của bạn để lấy vị trí hiện tại.",
|
|
977
977
|
"turn_on_location_service": "Bật dịch vụ vị trí cho điện thoại của bạn",
|
|
978
978
|
"turn_on_location_service_des": "Để tiếp tục, bật dịch vụ vị trí cho điện thoại của bạn trong Cài Đặt",
|
|
979
979
|
"detected": "Phát hiện",
|
|
@@ -1019,7 +1019,7 @@
|
|
|
1019
1019
|
"device_connect_directly_to_the_gateway": "Thiết bị được kết nối trực tiếp với gateway",
|
|
1020
1020
|
"zigbee": "Zigbee",
|
|
1021
1021
|
"device_connect_remotely_to_the_gateway": "Thiết bị được kết nối từ xa với gateway",
|
|
1022
|
-
"connect_wifi_asking": "Bằng việc tiếp tục,
|
|
1022
|
+
"connect_wifi_asking": "Bằng việc tiếp tục, {appName} cần kết nối với Wifi của thiết bị. Một thông báo sẽ hiện lên và yêu cầu bạn kết nối.",
|
|
1023
1023
|
"previous": "Trước",
|
|
1024
1024
|
"invalid_qr_code": "Mã QR không hợp lệ",
|
|
1025
1025
|
"invalid_qr_code_warning": "Không thể thêm thiết bị bằng mã QR này",
|
|
@@ -1051,7 +1051,7 @@
|
|
|
1051
1051
|
"need_add_gateway_before_add_device": "Bạn cần thêm mới 1 Gateway trước khi thêm thiết bị.",
|
|
1052
1052
|
"fail_to_discover_device_wifi": "Không phát hiện được wifi của thiết bị",
|
|
1053
1053
|
"try_to_turn_on_device_or_try_again": "Thử bật thiết bị hoặc Thử lại",
|
|
1054
|
-
"go_to_eoh_web_to_see_firmware": "Vào web
|
|
1054
|
+
"go_to_eoh_web_to_see_firmware": "Vào web {appName} để xem cấu hình firmware",
|
|
1055
1055
|
"general_information":"Thông tin chung",
|
|
1056
1056
|
"connection_methods": "Các phương thức kết nối",
|
|
1057
1057
|
"delete_gateway":"Xoá cửa ngõ",
|
|
@@ -1061,7 +1061,7 @@
|
|
|
1061
1061
|
"activate_date":"Ngày kích hoạt",
|
|
1062
1062
|
"warranty_expiration_date":"Ngày hết hạn bảo hành",
|
|
1063
1063
|
"firmware_version":"Phiên bản phần mềm",
|
|
1064
|
-
"visit_eoh_web_to_set_up_other_connection": "Truy cập
|
|
1064
|
+
"visit_eoh_web_to_set_up_other_connection": "Truy cập {appName} Web để thiết lập các tùy chọn kết nối khác.",
|
|
1065
1065
|
"delete_successfully":"Xoá thành công!",
|
|
1066
1066
|
"reboot_successfully": "Khởi động lại thành công!",
|
|
1067
1067
|
"message_delete_gateway": "Thao tác này sẽ loại bỏ hoàn toàn Gateway với Thông tin, Thiết bị, Luồng dữ liệu khỏi cổng.",
|
|
@@ -1113,5 +1113,6 @@
|
|
|
1113
1113
|
"default_value": "Giá trị mặc định",
|
|
1114
1114
|
"config_type": "Loại cấu hình",
|
|
1115
1115
|
"pin": "PIN",
|
|
1116
|
-
"pin_mode": "Chế độ mã PIN"
|
|
1116
|
+
"pin_mode": "Chế độ mã PIN",
|
|
1117
|
+
"data_address": "Địa chỉ dữ liệu"
|
|
1117
1118
|
}
|