@eohjsc/react-native-smart-city 0.3.84 → 0.3.86
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 -2
- package/src/Images/Common/logo.png +0 -0
- package/src/Images/Common/logo@2x.png +0 -0
- package/src/Images/Common/logo@3x.png +0 -0
- package/src/Images/Common/unit_default_background.png +0 -0
- package/src/Images/Common/unit_default_background@2x.png +0 -0
- package/src/Images/Common/unit_default_background@3x.png +0 -0
- package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/index.js +1 -1
- package/src/commons/ActionGroup/SliderRangeTemplate.js +7 -13
- package/src/commons/ActionGroup/SliderRangeTemplateStyles.js +0 -1
- package/src/commons/ActionGroup/__test__/SliderRangeTemplate.test.js +4 -4
- package/src/commons/ActionGroup/__test__/index.test.js +1 -1
- package/src/commons/Automate/__test__/ItemAutomate.test.js +25 -3
- package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +37 -0
- package/src/commons/Dashboard/MyUnit/index.js +25 -4
- package/src/commons/Device/ProgressBar/__test__/ProgressBar.test.js +1 -1
- package/src/commons/Device/ProgressBar/index.js +4 -2
- package/src/commons/Device/ProgressBar/styles.js +1 -0
- package/src/commons/Device/SonosSpeaker/__test__/SonosSpeaker.test.js +1 -1
- package/src/commons/Device/SonosSpeaker/index.js +1 -1
- package/src/commons/Device/WindSpeed/Anemometer/index.js +96 -14
- package/src/commons/Device/WindSpeed/__test__/Anemometer.test.js +89 -2
- package/src/commons/ModalPopupCT/index.js +21 -2
- package/src/commons/ModalPopupCT/styles.js +7 -0
- package/src/commons/WrapParallaxScrollView/index.js +5 -4
- package/src/configs/API.js +3 -2
- package/src/configs/AccessibilityLabel.js +3 -0
- package/src/configs/Constants.js +1 -0
- package/src/configs/Images.js +1 -0
- package/src/context/actionType.ts +3 -0
- package/src/context/mockStore.ts +1 -0
- package/src/context/reducer.ts +19 -0
- package/src/screens/AddNewAction/__test__/LoadingSelectAction.test.js +16 -0
- package/src/screens/AllGateway/DetailConfigActionInternal/__test__/index.test.js +179 -111
- package/src/screens/AllGateway/DetailConfigActionInternal/index.js +48 -50
- package/src/screens/AllGateway/DeviceInternalDetail/__test__/index.test.js +4 -0
- package/src/screens/AllGateway/DeviceInternalDetail/index.js +14 -1
- package/src/screens/AllGateway/GatewayConnectionMethods/__test__/index.test.js +25 -0
- package/src/screens/AllGateway/GatewayConnectionMethods/index.js +59 -35
- package/src/screens/AllGateway/GatewayInfo/__test__/index.test.js +14 -4
- package/src/screens/AllGateway/GatewayInfo/index.js +21 -2
- package/src/screens/AllGateway/components/Detail/__test__/index.test.js +28 -1
- package/src/screens/AllGateway/components/Detail/index.js +8 -2
- package/src/screens/AllGateway/components/Information/index.js +4 -1
- package/src/screens/AllGateway/components/TabPaneCT/styles.js +1 -1
- package/src/screens/ConfirmUnitDeletion/index.js +6 -2
- package/src/screens/Unit/ManageUnit.js +7 -3
- package/src/utils/I18n/translations/en.json +3 -0
- package/src/utils/I18n/translations/vi.json +3 -0
- package/src/utils/Utils.js +6 -0
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.86",
|
|
5
5
|
"description": "TODO",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"files": [
|
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
"@formatjs/intl-pluralrules": "^3.4.7",
|
|
109
109
|
"@invertase/react-native-apple-authentication": "^1.1.2",
|
|
110
110
|
"@messageformat/core": "^3.0.0",
|
|
111
|
+
"@miblanchard/react-native-slider": "^2.2.0",
|
|
111
112
|
"@react-native-clipboard/clipboard": "^1.11.1",
|
|
112
113
|
"@react-native-community/async-storage": "^1.12.1",
|
|
113
114
|
"@react-native-community/cameraroll": "^4.0.0",
|
|
@@ -179,6 +180,7 @@
|
|
|
179
180
|
"react-native-maps-directions": "^1.8.0",
|
|
180
181
|
"react-native-modal": "^11.5.6",
|
|
181
182
|
"react-native-modal-datetime-picker": "^8.9.3",
|
|
183
|
+
"react-native-new-snap-carousel": "^3.9.3",
|
|
182
184
|
"react-native-onesignal": "^4.3.1",
|
|
183
185
|
"react-native-pager-view": "^5.4.1",
|
|
184
186
|
"react-native-parallax-scroll-view": "^0.21.3",
|
|
@@ -190,7 +192,6 @@
|
|
|
190
192
|
"react-native-responsive-fontsize": "^0.5.1",
|
|
191
193
|
"react-native-safe-area-context": "^3.1.1",
|
|
192
194
|
"react-native-screens": "^2.9.0",
|
|
193
|
-
"react-native-snap-carousel": "4.0.0-beta.5",
|
|
194
195
|
"react-native-super-grid": "^4.0.3",
|
|
195
196
|
"react-native-svg": "^12.1.0",
|
|
196
197
|
"react-native-toast-message": "^2.1.1",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { memo, useCallback, useState } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
|
-
import Slider from '@react-native-
|
|
3
|
+
import { Slider } from '@miblanchard/react-native-slider';
|
|
4
4
|
import Text from '../../../Text';
|
|
5
5
|
import { HeaderCustom } from '../../../Header';
|
|
6
6
|
import ButtonWrapper from './ButtonWrapper';
|
|
@@ -5,7 +5,7 @@ import styles from './SliderRangeTemplateStyles';
|
|
|
5
5
|
import Text from '../Text';
|
|
6
6
|
import { Colors } from '../../configs';
|
|
7
7
|
import SvgBrightness from '../../../assets/images/brightness.svg';
|
|
8
|
-
import Slider from '@react-native-
|
|
8
|
+
import { Slider } from '@miblanchard/react-native-slider';
|
|
9
9
|
import { useConfigGlobalState } from '../../iot/states';
|
|
10
10
|
import { DEVICE_TYPE } from '../../configs/Constants';
|
|
11
11
|
|
|
@@ -17,14 +17,8 @@ const SliderRangeTemplate = memo(({ actionGroup = {}, doAction, sensor }) => {
|
|
|
17
17
|
const { config = undefined } = configuration;
|
|
18
18
|
|
|
19
19
|
const getPercent = useCallback(() => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const { value = 0 } = configValue;
|
|
23
|
-
if (value) {
|
|
24
|
-
return value;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return 0;
|
|
20
|
+
const { value } = configValues[config] || { value: 0 };
|
|
21
|
+
return value;
|
|
28
22
|
}, [config, configValues]);
|
|
29
23
|
|
|
30
24
|
const [valueBrightness, setValueBrightness] = useState(getPercent());
|
|
@@ -32,9 +26,10 @@ const SliderRangeTemplate = memo(({ actionGroup = {}, doAction, sensor }) => {
|
|
|
32
26
|
|
|
33
27
|
const onChangeBrightness = useCallback(
|
|
34
28
|
async (value) => {
|
|
29
|
+
const value_brness = value[0];
|
|
35
30
|
await doAction(
|
|
36
31
|
configuration?.action_data,
|
|
37
|
-
JSON.stringify({ value_brness:
|
|
32
|
+
JSON.stringify({ value_brness: value_brness, value: value_brness })
|
|
38
33
|
);
|
|
39
34
|
},
|
|
40
35
|
[configuration?.action_data, doAction]
|
|
@@ -45,8 +40,7 @@ const SliderRangeTemplate = memo(({ actionGroup = {}, doAction, sensor }) => {
|
|
|
45
40
|
}, [valueBrightness]);
|
|
46
41
|
|
|
47
42
|
useEffect(() => {
|
|
48
|
-
const
|
|
49
|
-
const { value = 0 } = configValue;
|
|
43
|
+
const { value } = configValues[config] || { value: 0 };
|
|
50
44
|
if (value && isFirstTime) {
|
|
51
45
|
setValueBrightness(value);
|
|
52
46
|
setIsFirstTime(false);
|
|
@@ -71,7 +65,7 @@ const SliderRangeTemplate = memo(({ actionGroup = {}, doAction, sensor }) => {
|
|
|
71
65
|
</View>
|
|
72
66
|
<View style={styles.RightBrightness}>
|
|
73
67
|
<Slider
|
|
74
|
-
|
|
68
|
+
containerStyle={styles.slider}
|
|
75
69
|
value={valueBrightness}
|
|
76
70
|
onSlidingComplete={onChangeBrightness}
|
|
77
71
|
onValueChange={setValueBrightness}
|
|
@@ -5,7 +5,7 @@ import SliderRangeTemplate from '../SliderRangeTemplate';
|
|
|
5
5
|
import { SCProvider } from '../../../context';
|
|
6
6
|
import { mockSCStore } from '../../../context/mockStore';
|
|
7
7
|
import { useConfigGlobalState } from '../../../iot/states';
|
|
8
|
-
import
|
|
8
|
+
import { Slider } from '@miblanchard/react-native-slider';
|
|
9
9
|
|
|
10
10
|
jest.mock('../../../iot/Monitor');
|
|
11
11
|
const mockDoAction = jest.fn();
|
|
@@ -55,10 +55,10 @@ describe('Test SliderRangeTemplate', () => {
|
|
|
55
55
|
wrapper = await create(wrapComponent(actionGroup, mockDoAction, sensor));
|
|
56
56
|
});
|
|
57
57
|
const instance = wrapper.root;
|
|
58
|
-
const silderRange = instance.findAllByType(
|
|
58
|
+
const silderRange = instance.findAllByType(Slider);
|
|
59
59
|
expect(silderRange).toHaveLength(1);
|
|
60
60
|
await act(async () => {
|
|
61
|
-
await silderRange[0].props.onSlidingComplete(50);
|
|
61
|
+
await silderRange[0].props.onSlidingComplete([50]);
|
|
62
62
|
});
|
|
63
63
|
expect(mockDoAction).toHaveBeenCalledWith(
|
|
64
64
|
action_data,
|
|
@@ -80,7 +80,7 @@ describe('Test SliderRangeTemplate', () => {
|
|
|
80
80
|
wrapper = await create(wrapComponent(actionGroup, mockDoAction, sensor));
|
|
81
81
|
});
|
|
82
82
|
const instance = wrapper.root;
|
|
83
|
-
const silderRange = instance.findByType(
|
|
83
|
+
const silderRange = instance.findByType(Slider);
|
|
84
84
|
expect(silderRange.props.value).toBe(50);
|
|
85
85
|
});
|
|
86
86
|
});
|
|
@@ -14,7 +14,7 @@ import Text from '../../Text';
|
|
|
14
14
|
import { AccessibilityLabel } from '../../../configs/Constants';
|
|
15
15
|
import { SCProvider } from '../../../context';
|
|
16
16
|
import { mockSCStore } from '../../../context/mockStore';
|
|
17
|
-
import Slider from '@react-native-
|
|
17
|
+
import { Slider } from '@miblanchard/react-native-slider';
|
|
18
18
|
import { WheelColorPicker } from '../ColorPickerTemplate';
|
|
19
19
|
import RadioCircle from '../../RadioCircle';
|
|
20
20
|
|
|
@@ -1,24 +1,46 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { act, create } from 'react-test-renderer';
|
|
3
|
+
import { TouchableOpacity } from 'react-native';
|
|
4
|
+
|
|
3
5
|
import { SCProvider } from '../../../context';
|
|
4
6
|
import { mockSCStore } from '../../../context/mockStore';
|
|
5
7
|
import Text from '../../Text';
|
|
6
8
|
import ItemAutomate from '../ItemAutomate';
|
|
7
9
|
|
|
8
|
-
const wrapComponent = (
|
|
10
|
+
const wrapComponent = (rest) => (
|
|
9
11
|
<SCProvider initState={mockSCStore({})}>
|
|
10
|
-
<ItemAutomate
|
|
12
|
+
<ItemAutomate {...rest} />
|
|
11
13
|
</SCProvider>
|
|
12
14
|
);
|
|
13
15
|
|
|
14
16
|
describe('Test ItemAutomate', () => {
|
|
15
17
|
let tree;
|
|
18
|
+
let defaultProps = {
|
|
19
|
+
type: 'one_tap',
|
|
20
|
+
};
|
|
16
21
|
it('Test render', async () => {
|
|
17
22
|
await act(async () => {
|
|
18
|
-
tree = await create(wrapComponent());
|
|
23
|
+
tree = await create(wrapComponent(defaultProps));
|
|
19
24
|
});
|
|
20
25
|
const instance = tree.root;
|
|
21
26
|
const texts = instance.findAllByType(Text);
|
|
22
27
|
expect(texts[0].props.children).toEqual('Launch One-Tap');
|
|
23
28
|
});
|
|
29
|
+
|
|
30
|
+
it('Test render TouchableOpacity', async () => {
|
|
31
|
+
const mockOnPress = jest.fn();
|
|
32
|
+
defaultProps = {
|
|
33
|
+
type: 'one_tap',
|
|
34
|
+
onPress: mockOnPress,
|
|
35
|
+
};
|
|
36
|
+
await act(async () => {
|
|
37
|
+
tree = await create(wrapComponent(defaultProps));
|
|
38
|
+
});
|
|
39
|
+
const instance = tree.root;
|
|
40
|
+
const touchableOpacities = instance.findAllByType(TouchableOpacity);
|
|
41
|
+
await act(async () => {
|
|
42
|
+
touchableOpacities[0].props.onPress();
|
|
43
|
+
});
|
|
44
|
+
expect(mockOnPress).toBeCalledTimes(1);
|
|
45
|
+
});
|
|
24
46
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import renderer, { act } from 'react-test-renderer';
|
|
3
3
|
import MockAdapter from 'axios-mock-adapter';
|
|
4
|
+
|
|
4
5
|
import MyUnit from '..';
|
|
5
6
|
import MyUnitDevice from '../../../../screens/Unit/components/MyUnitDevice';
|
|
6
7
|
import { AccessibilityLabel } from '../../../../configs/Constants';
|
|
@@ -8,12 +9,27 @@ import { SCProvider } from '../../../../context';
|
|
|
8
9
|
import { mockSCStore } from '../../../../context/mockStore';
|
|
9
10
|
import api from '../../../../utils/Apis/axios';
|
|
10
11
|
import { API } from '../../../../configs';
|
|
12
|
+
import Routes from '../../../../utils/Route';
|
|
13
|
+
import { Action } from '../../../../context/actionType';
|
|
11
14
|
|
|
12
15
|
const mock = new MockAdapter(api.axiosInstance);
|
|
13
16
|
|
|
14
17
|
const mockedNavigate = jest.fn();
|
|
15
18
|
const mockedDispatch = jest.fn();
|
|
16
19
|
|
|
20
|
+
const mockSetAction = jest.fn();
|
|
21
|
+
jest.mock('react', () => {
|
|
22
|
+
return {
|
|
23
|
+
...jest.requireActual('react'),
|
|
24
|
+
useContext: () => ({
|
|
25
|
+
stateData: mockSCStore({
|
|
26
|
+
app: { isDeleteUnitSuccessFully: true },
|
|
27
|
+
}),
|
|
28
|
+
setAction: mockSetAction,
|
|
29
|
+
}),
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
|
|
17
33
|
jest.mock('@react-navigation/native', () => {
|
|
18
34
|
return {
|
|
19
35
|
...jest.requireActual('@react-navigation/native'),
|
|
@@ -104,5 +120,26 @@ describe('Test MyUnit', () => {
|
|
|
104
120
|
const instance = tree.root;
|
|
105
121
|
const devices = instance.findAllByType(MyUnitDevice);
|
|
106
122
|
expect(devices).toHaveLength(2);
|
|
123
|
+
|
|
124
|
+
const button = instance.findByProps({
|
|
125
|
+
accessibilityLabel: `${AccessibilityLabel.MY_UNIT_GO_TO_DETAIL}-0`,
|
|
126
|
+
});
|
|
127
|
+
await act(async () => {
|
|
128
|
+
await button.props.onPress(data[0]);
|
|
129
|
+
});
|
|
130
|
+
expect(mockedNavigate).toBeCalledWith(Routes.UnitStack, {
|
|
131
|
+
params: { unitId: 1 },
|
|
132
|
+
screen: Routes.UnitDetail,
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('Test isDeleteUnitSuccessFully', async () => {
|
|
137
|
+
jest.useFakeTimers();
|
|
138
|
+
mock.onGet(API.UNIT.MY_UNITS()).replyOnce(200, data);
|
|
139
|
+
await act(async () => {
|
|
140
|
+
tree = await renderer.create(wrapComponent());
|
|
141
|
+
});
|
|
142
|
+
jest.runAllTimers();
|
|
143
|
+
expect(mockSetAction).toBeCalledWith(Action.RESET_DELETE_UNIT_ACTION);
|
|
107
144
|
});
|
|
108
145
|
});
|
|
@@ -5,8 +5,9 @@ import React, {
|
|
|
5
5
|
useState,
|
|
6
6
|
useContext,
|
|
7
7
|
useMemo,
|
|
8
|
+
useRef,
|
|
8
9
|
} from 'react';
|
|
9
|
-
import { View,
|
|
10
|
+
import { View, TouchableOpacity, Dimensions } from 'react-native';
|
|
10
11
|
import {
|
|
11
12
|
useNavigation,
|
|
12
13
|
useIsFocused,
|
|
@@ -23,7 +24,7 @@ import { Section } from '../../Section';
|
|
|
23
24
|
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
24
25
|
import { useUnitConnectRemoteDevices } from '../../../screens/Unit/hook/useUnitConnectRemoteDevices';
|
|
25
26
|
import { useWatchConfigs, useBluetoothConnection } from '../../../hooks/IoT';
|
|
26
|
-
import { SCContext } from '../../../context';
|
|
27
|
+
import { SCContext, useSCContextSelector } from '../../../context';
|
|
27
28
|
import { Action } from '../../../context/actionType';
|
|
28
29
|
|
|
29
30
|
import Carousel from 'react-native-new-snap-carousel';
|
|
@@ -32,18 +33,23 @@ import Routes from '../../../utils/Route';
|
|
|
32
33
|
import MyUnitDevice from '../../../screens/Unit/components/MyUnitDevice';
|
|
33
34
|
import { STORAGE_KEY } from '../../../utils/Storage';
|
|
34
35
|
import { preloadImagesFromUnits } from '../../../utils/Functions/preloadImages';
|
|
36
|
+
import FImage from '../../FImage';
|
|
35
37
|
|
|
36
38
|
let screenWidth = Dimensions.get('window').width;
|
|
37
39
|
|
|
38
40
|
const bleManager = new BleManager();
|
|
39
41
|
|
|
40
42
|
const MyUnit = ({ refreshing }) => {
|
|
43
|
+
const carouselRef = useRef();
|
|
41
44
|
const t = useTranslations();
|
|
42
45
|
const isFocused = useIsFocused();
|
|
43
46
|
const navigation = useNavigation();
|
|
44
47
|
const [myUnits, setMyUnits] = useState([]);
|
|
45
48
|
const [slideIndex, setSlideIndex] = useState(0);
|
|
46
49
|
const { setAction } = useContext(SCContext);
|
|
50
|
+
const isDeleteUnitSuccessFully = useSCContextSelector(
|
|
51
|
+
(state) => state.app.isDeleteUnitSuccessFully
|
|
52
|
+
);
|
|
47
53
|
|
|
48
54
|
const {
|
|
49
55
|
permissionsRequested: bluetoothPermRequested,
|
|
@@ -137,9 +143,13 @@ const MyUnit = ({ refreshing }) => {
|
|
|
137
143
|
accessibilityLabel={`${AccessibilityLabel.MY_UNIT_GO_TO_DETAIL}-${index}`}
|
|
138
144
|
>
|
|
139
145
|
<View style={styles.overlay} />
|
|
140
|
-
<
|
|
146
|
+
<FImage
|
|
141
147
|
style={styles.bgMyUnit}
|
|
142
|
-
source={
|
|
148
|
+
source={
|
|
149
|
+
item?.background
|
|
150
|
+
? { uri: item.background }
|
|
151
|
+
: Images.unitDefaultBackground
|
|
152
|
+
}
|
|
143
153
|
defaultSource={Images.BgUnit}
|
|
144
154
|
resizeMode="cover"
|
|
145
155
|
/>
|
|
@@ -159,6 +169,16 @@ const MyUnit = ({ refreshing }) => {
|
|
|
159
169
|
preloadImagesFromUnits(myUnits, STORAGE_KEY.IS_FIRST_TIME_LOAD_MY_UNITS);
|
|
160
170
|
}, [myUnits]);
|
|
161
171
|
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
if (isDeleteUnitSuccessFully) {
|
|
174
|
+
const to = setTimeout(() => {
|
|
175
|
+
carouselRef?.current?.snapToItem();
|
|
176
|
+
setAction(Action.RESET_DELETE_UNIT_ACTION);
|
|
177
|
+
}, 60);
|
|
178
|
+
return () => clearTimeout(to);
|
|
179
|
+
}
|
|
180
|
+
}, [isDeleteUnitSuccessFully, setAction]);
|
|
181
|
+
|
|
162
182
|
return (
|
|
163
183
|
<>
|
|
164
184
|
<Section style={styles.boxTxtMyUnit}>
|
|
@@ -168,6 +188,7 @@ const MyUnit = ({ refreshing }) => {
|
|
|
168
188
|
<View style={styles.container}>
|
|
169
189
|
{myUnits.length ? (
|
|
170
190
|
<Carousel
|
|
191
|
+
ref={carouselRef}
|
|
171
192
|
layout={'default'}
|
|
172
193
|
data={myUnits}
|
|
173
194
|
sliderWidth={screenWidth}
|
|
@@ -44,6 +44,6 @@ describe('Test ProgressBar', () => {
|
|
|
44
44
|
const texts = instance.findAllByType(Text);
|
|
45
45
|
expect(texts[0].props.children).toBe('Value bar');
|
|
46
46
|
expect(texts[1].props.children).toEqual(['Max value', ': ', 100]);
|
|
47
|
-
expect(texts[2].props.children).toEqual([10, '
|
|
47
|
+
expect(texts[2].props.children).toEqual([10, ' ', undefined]);
|
|
48
48
|
});
|
|
49
49
|
});
|
|
@@ -13,7 +13,7 @@ const ProgressBar = memo(({ data = [], item }) => {
|
|
|
13
13
|
const maxValue = useMemo(() => {
|
|
14
14
|
return Number(item?.configuration?.max_value) || 60;
|
|
15
15
|
}, [item?.configuration?.max_value]);
|
|
16
|
-
const value = data.length ? data[0]
|
|
16
|
+
const { value = 0, measure, unit } = data.length ? data[0] : {};
|
|
17
17
|
const percent = value / maxValue; // a number between 0 and 1
|
|
18
18
|
|
|
19
19
|
return (
|
|
@@ -36,7 +36,9 @@ const ProgressBar = memo(({ data = [], item }) => {
|
|
|
36
36
|
borderWidth={0}
|
|
37
37
|
borderRadius={10}
|
|
38
38
|
/>
|
|
39
|
-
<Text style={styles.textValue}>
|
|
39
|
+
<Text style={styles.textValue}>
|
|
40
|
+
{value} {unit || measure}
|
|
41
|
+
</Text>
|
|
40
42
|
</View>
|
|
41
43
|
</View>
|
|
42
44
|
);
|
|
@@ -6,7 +6,7 @@ import { mockSCStore } from '../../../../context/mockStore';
|
|
|
6
6
|
import Text from '../../../Text';
|
|
7
7
|
import SonosSpeaker from '..';
|
|
8
8
|
import { TouchableOpacity } from 'react-native';
|
|
9
|
-
import Slider from '@react-native-
|
|
9
|
+
import { Slider } from '@miblanchard/react-native-slider';
|
|
10
10
|
|
|
11
11
|
const wrapComponent = () => (
|
|
12
12
|
<SCProvider initState={mockSCStore({})}>
|
|
@@ -2,7 +2,7 @@ import React, { memo, useState } from 'react';
|
|
|
2
2
|
import { View, TouchableOpacity } from 'react-native';
|
|
3
3
|
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
4
4
|
import { Icon } from '@ant-design/react-native';
|
|
5
|
-
import Slider from '@react-native-
|
|
5
|
+
import { Slider } from '@miblanchard/react-native-slider';
|
|
6
6
|
|
|
7
7
|
import Text from '../../Text';
|
|
8
8
|
import { Colors } from '../../../configs';
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import React, { memo, useCallback, useMemo } from 'react';
|
|
1
|
+
import React, { memo, useCallback, useMemo, useState } from 'react';
|
|
2
2
|
import Svg, { Path, Text, Circle } from 'react-native-svg';
|
|
3
|
-
import { View, StyleSheet } from 'react-native';
|
|
3
|
+
import { View, StyleSheet, Text as ReactText } from 'react-native';
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
drawArc,
|
|
7
7
|
polarToCartesian,
|
|
8
8
|
} from '../../../UnitSummary/AirQuality/SegmentedRoundDisplay/helper';
|
|
9
9
|
import { Colors, Fonts } from '../../../../configs';
|
|
10
|
+
import AccessibilityLabel from '../../../../configs/AccessibilityLabel';
|
|
10
11
|
|
|
11
12
|
const { PI } = Math;
|
|
12
13
|
|
|
@@ -16,12 +17,13 @@ const Anemometer = memo(
|
|
|
16
17
|
width = 240,
|
|
17
18
|
size = 170,
|
|
18
19
|
strokeWidth = 16,
|
|
19
|
-
numberOfSection =
|
|
20
|
+
numberOfSection = 2,
|
|
20
21
|
startAngle = -45,
|
|
21
22
|
endAngle = 225,
|
|
22
23
|
txtColor = Colors.Gray8,
|
|
23
24
|
item,
|
|
24
25
|
}) => {
|
|
26
|
+
const [isShowToolTip, setIsShowToolTip] = useState(false);
|
|
25
27
|
const center = {
|
|
26
28
|
x: size / 2,
|
|
27
29
|
y: size / 2,
|
|
@@ -121,6 +123,38 @@ const Anemometer = memo(
|
|
|
121
123
|
txtColor,
|
|
122
124
|
]);
|
|
123
125
|
|
|
126
|
+
// eslint-disable-next-line no-shadow
|
|
127
|
+
const handleShowToolTip = (value) => () => setIsShowToolTip(value);
|
|
128
|
+
|
|
129
|
+
const valueSize = useMemo(() => {
|
|
130
|
+
if ([null, undefined, NaN].includes(value)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (value.toString().length < 4) {
|
|
134
|
+
return [56, 16];
|
|
135
|
+
}
|
|
136
|
+
if (value.toString().length < 7) {
|
|
137
|
+
return [35, 10];
|
|
138
|
+
}
|
|
139
|
+
if (value.toString().length < 10) {
|
|
140
|
+
return [26, 6];
|
|
141
|
+
}
|
|
142
|
+
return [20, 2];
|
|
143
|
+
}, [value]);
|
|
144
|
+
|
|
145
|
+
const toolTipTranslateX = useMemo(() => {
|
|
146
|
+
if (value.toString().length < 4) {
|
|
147
|
+
return -20;
|
|
148
|
+
}
|
|
149
|
+
if (value.toString().length < 6) {
|
|
150
|
+
return -30;
|
|
151
|
+
}
|
|
152
|
+
if (value.toString().length < 8) {
|
|
153
|
+
return -40;
|
|
154
|
+
}
|
|
155
|
+
return -50;
|
|
156
|
+
}, [value]);
|
|
157
|
+
|
|
124
158
|
return (
|
|
125
159
|
<View style={styles.standard}>
|
|
126
160
|
<View style={styles.wrapOffset}>
|
|
@@ -137,6 +171,41 @@ const Anemometer = memo(
|
|
|
137
171
|
/>
|
|
138
172
|
</Svg>
|
|
139
173
|
</View>
|
|
174
|
+
|
|
175
|
+
<View style={styles.textValue}>
|
|
176
|
+
<Svg width={width} height={width} {...viewBox}>
|
|
177
|
+
<Text
|
|
178
|
+
fill={Colors.Lime6}
|
|
179
|
+
fontSize={valueSize[0]}
|
|
180
|
+
fontWeight="bold"
|
|
181
|
+
x={width / 2}
|
|
182
|
+
y={width / 2 + valueSize[1]}
|
|
183
|
+
textAnchor="middle"
|
|
184
|
+
fontFamily={Fonts.Regular}
|
|
185
|
+
onPressIn={handleShowToolTip(true)}
|
|
186
|
+
onPressOut={handleShowToolTip(false)}
|
|
187
|
+
>
|
|
188
|
+
{value.toString().length > 10
|
|
189
|
+
? value.toString().substring(0, 10) + '...'
|
|
190
|
+
: value}
|
|
191
|
+
</Text>
|
|
192
|
+
</Svg>
|
|
193
|
+
{isShowToolTip && (
|
|
194
|
+
<View
|
|
195
|
+
style={{
|
|
196
|
+
...styles.toolTip,
|
|
197
|
+
top: width / 2 - 50,
|
|
198
|
+
left: width / 2,
|
|
199
|
+
transform: [{ translateX: toolTipTranslateX }],
|
|
200
|
+
}}
|
|
201
|
+
accessibilityLabel={AccessibilityLabel.WRAP_TOOL_TIP}
|
|
202
|
+
>
|
|
203
|
+
<ReactText style={styles.textToolTip}>{value}</ReactText>
|
|
204
|
+
<View style={styles.triangle} />
|
|
205
|
+
</View>
|
|
206
|
+
)}
|
|
207
|
+
</View>
|
|
208
|
+
|
|
140
209
|
<Svg width={width} height={width} {...viewBox}>
|
|
141
210
|
<Path
|
|
142
211
|
x={(width - size) / 2}
|
|
@@ -147,17 +216,6 @@ const Anemometer = memo(
|
|
|
147
216
|
{...{ d, strokeWidth }}
|
|
148
217
|
/>
|
|
149
218
|
{textAngles()}
|
|
150
|
-
<Text
|
|
151
|
-
fill={Colors.Lime6}
|
|
152
|
-
fontSize={48}
|
|
153
|
-
fontWeight="bold"
|
|
154
|
-
x={width / 2}
|
|
155
|
-
y={width / 2 + 16}
|
|
156
|
-
textAnchor="middle"
|
|
157
|
-
fontFamily={Fonts.Regular}
|
|
158
|
-
>
|
|
159
|
-
{value}
|
|
160
|
-
</Text>
|
|
161
219
|
<Text
|
|
162
220
|
fill={Colors.Gray8}
|
|
163
221
|
fontSize={16}
|
|
@@ -186,4 +244,28 @@ const styles = StyleSheet.create({
|
|
|
186
244
|
position: 'absolute',
|
|
187
245
|
zIndex: 2,
|
|
188
246
|
},
|
|
247
|
+
textValue: {
|
|
248
|
+
position: 'absolute',
|
|
249
|
+
zIndex: 4,
|
|
250
|
+
},
|
|
251
|
+
toolTip: {
|
|
252
|
+
position: 'absolute',
|
|
253
|
+
paddingHorizontal: 14,
|
|
254
|
+
backgroundColor: Colors.Black,
|
|
255
|
+
justifyContent: 'center',
|
|
256
|
+
alignItems: 'center',
|
|
257
|
+
borderRadius: 20,
|
|
258
|
+
},
|
|
259
|
+
textToolTip: {
|
|
260
|
+
color: Colors.White,
|
|
261
|
+
},
|
|
262
|
+
triangle: {
|
|
263
|
+
position: 'absolute',
|
|
264
|
+
bottom: -6,
|
|
265
|
+
borderTopWidth: 6,
|
|
266
|
+
borderRightWidth: 4,
|
|
267
|
+
borderLeftWidth: 4,
|
|
268
|
+
borderRightColor: Colors.TextTransparent,
|
|
269
|
+
borderLeftColor: Colors.TextTransparent,
|
|
270
|
+
},
|
|
189
271
|
});
|