@eohjsc/react-native-smart-city 0.4.76 → 0.4.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/commons/MediaPlayerDetail/__test__/MediaPlayerDetail.test.js +14 -3
- package/src/commons/MediaPlayerDetail/index.js +4 -1
- package/src/commons/SubUnit/DeviceTemplate/ConfigAndEvaluation/ConfigAndEvaluation.js +10 -2
- package/src/commons/SubUnit/DeviceTemplate/ConfigValue/ConfigValue.js +10 -2
- package/src/commons/SubUnit/DeviceTemplate/DeviceTemplate.js +2 -6
- package/src/commons/SubUnit/DeviceTemplate/EvaluationOverConfig/EvaluationOverConfig.js +10 -2
- package/src/commons/SubUnit/DeviceTemplate/styles/ConfigValueStyles.js +11 -0
- package/src/commons/SubUnit/ShortDetail.js +4 -5
- package/src/utils/I18n/translations/en.js +1 -0
- package/src/utils/I18n/translations/vi.js +1 -0
- package/src/utils/Validation.js +5 -0
package/package.json
CHANGED
|
@@ -5,11 +5,13 @@ import MediaPlayerDetail from '../index';
|
|
|
5
5
|
import PauseIcon from '../../../assets/images/Common/Pause.svg';
|
|
6
6
|
import { SCProvider } from '../../../context';
|
|
7
7
|
import { mockSCStore } from '../../../context/mockStore';
|
|
8
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
9
|
+
import { getTranslate } from '../../../utils/I18n';
|
|
8
10
|
|
|
9
|
-
const wrapComponent = () => (
|
|
11
|
+
const wrapComponent = (uri) => (
|
|
10
12
|
<SCProvider initState={mockSCStore({})}>
|
|
11
13
|
<MediaPlayerDetail
|
|
12
|
-
uri={
|
|
14
|
+
uri={uri}
|
|
13
15
|
key={'camera-1'}
|
|
14
16
|
thumbnail={{ uri: 'https://abc.com/image.png' }}
|
|
15
17
|
cameraName={'cameraName'}
|
|
@@ -19,10 +21,12 @@ const wrapComponent = () => (
|
|
|
19
21
|
|
|
20
22
|
describe('Test MediaPlayerDetail', () => {
|
|
21
23
|
let wrapper;
|
|
24
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
22
25
|
|
|
23
26
|
it('MediaPlayerDetail render when onTap setPause', async () => {
|
|
27
|
+
const uri = 'rtsp://admin:hd111111:1111111/Streaming/Channels/101/';
|
|
24
28
|
await act(async () => {
|
|
25
|
-
wrapper = await create(wrapComponent());
|
|
29
|
+
wrapper = await create(wrapComponent(uri));
|
|
26
30
|
});
|
|
27
31
|
const instance = wrapper.root;
|
|
28
32
|
const buttons = instance.findAllByType(TouchableOpacity);
|
|
@@ -44,4 +48,11 @@ describe('Test MediaPlayerDetail', () => {
|
|
|
44
48
|
expect(texts[1].child).toBeUndefined();
|
|
45
49
|
expect(pauseIcon.child).toBeUndefined();
|
|
46
50
|
});
|
|
51
|
+
it('MediaPlayerDetail uri wrong', async () => {
|
|
52
|
+
const uri = 'wrong://admin:hd111111:1111111/Streaming/Channels/101/';
|
|
53
|
+
await act(async () => {
|
|
54
|
+
wrapper = await create(wrapComponent(uri));
|
|
55
|
+
});
|
|
56
|
+
expect(spyToastError).toBeCalledWith(getTranslate('en', 'uri_invalid'));
|
|
57
|
+
});
|
|
47
58
|
});
|
|
@@ -24,6 +24,8 @@ import { AccessibilityLabel } from '../../configs/Constants';
|
|
|
24
24
|
import { SCContext, useSCContextSelector } from '../../context';
|
|
25
25
|
import { Action } from '../../context/actionType';
|
|
26
26
|
import VLCPlayer from 'react-native-vlc-media-player/VLCPlayer';
|
|
27
|
+
import { isValidURI } from '../../utils/Validation';
|
|
28
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
27
29
|
|
|
28
30
|
const MediaPlayerDetail = ({
|
|
29
31
|
id,
|
|
@@ -87,7 +89,8 @@ const MediaPlayerDetail = ({
|
|
|
87
89
|
}, [amount]);
|
|
88
90
|
|
|
89
91
|
const renderCamera = useMemo(() => {
|
|
90
|
-
if (!uri) {
|
|
92
|
+
if (!uri || !isValidURI(uri)) {
|
|
93
|
+
ToastBottomHelper.error(t('uri_invalid'));
|
|
91
94
|
return null;
|
|
92
95
|
}
|
|
93
96
|
return (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { memo } from 'react';
|
|
2
2
|
import styles from '../styles/ConfigValueStyles';
|
|
3
|
-
import { View } from 'react-native';
|
|
3
|
+
import { Platform, View } from 'react-native';
|
|
4
4
|
import Text from '../../../Text';
|
|
5
5
|
import LastUpdatedText from '../../../Device/LastUpdatedText';
|
|
6
6
|
import { EvaluationConfigWrapper } from '../EvaluationOverConfig/EvaluationOverConfig';
|
|
@@ -17,7 +17,15 @@ const ConfigAndEvaluationDisplay = memo(
|
|
|
17
17
|
<IconComponent icon={icon_kit || icon} />
|
|
18
18
|
</View>
|
|
19
19
|
<View style={styles.rowTop}>
|
|
20
|
-
<Text
|
|
20
|
+
<Text
|
|
21
|
+
numberOfLines={1}
|
|
22
|
+
semibold
|
|
23
|
+
style={
|
|
24
|
+
Platform.OS === 'ios' ? styles.iosStyle : styles.androidStyle
|
|
25
|
+
}
|
|
26
|
+
>
|
|
27
|
+
{stationItem?.configuration?.config_data?.name}
|
|
28
|
+
</Text>
|
|
21
29
|
</View>
|
|
22
30
|
<View style={styles.rowBottom}>
|
|
23
31
|
<Text style={styles.textValue} bold>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { memo, useMemo } from 'react';
|
|
2
2
|
import styles from '../styles/ConfigValueStyles';
|
|
3
|
-
import { View } from 'react-native';
|
|
3
|
+
import { Platform, View } from 'react-native';
|
|
4
4
|
import Text from '../../../Text';
|
|
5
5
|
import { useConfigGlobalState } from '../../../../iot/states';
|
|
6
6
|
import { useWatchConfigs } from '../../../../hooks/IoT';
|
|
@@ -25,7 +25,15 @@ const ConfigValue = ({ device, stationItem }) => {
|
|
|
25
25
|
<IconComponent icon={icon_kit || icon} />
|
|
26
26
|
</View>
|
|
27
27
|
<View style={styles.rowTop}>
|
|
28
|
-
<Text
|
|
28
|
+
<Text
|
|
29
|
+
numberOfLines={1}
|
|
30
|
+
semibold
|
|
31
|
+
style={
|
|
32
|
+
Platform.OS === 'ios' ? styles.iosStyle : styles.androidStyle
|
|
33
|
+
}
|
|
34
|
+
>
|
|
35
|
+
{stationItem?.configuration?.config_data?.name}
|
|
36
|
+
</Text>
|
|
29
37
|
</View>
|
|
30
38
|
<View style={styles.rowBottom}>
|
|
31
39
|
<Text style={styles.textValue} bold>
|
|
@@ -3,18 +3,14 @@ import { getTemplate } from './';
|
|
|
3
3
|
import ItemDeviceWrapper from '../../Device/ItemDeviceWrapper';
|
|
4
4
|
|
|
5
5
|
export const DeviceTemplate = memo(
|
|
6
|
-
({ device, stationItem, unit, station,
|
|
6
|
+
({ device, stationItem, unit, station, key }) => {
|
|
7
7
|
const Template = getTemplate(stationItem);
|
|
8
8
|
if (!Template) {
|
|
9
9
|
return null;
|
|
10
10
|
}
|
|
11
11
|
return (
|
|
12
12
|
<ItemDeviceWrapper device={device} unit={unit} station={station}>
|
|
13
|
-
<Template.Display
|
|
14
|
-
device={device}
|
|
15
|
-
stationItem={stationItem}
|
|
16
|
-
index={index}
|
|
17
|
-
/>
|
|
13
|
+
<Template.Display device={device} stationItem={stationItem} key={key} />
|
|
18
14
|
</ItemDeviceWrapper>
|
|
19
15
|
);
|
|
20
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { memo, useMemo } from 'react';
|
|
2
2
|
import styles from '../styles/ConfigValueStyles';
|
|
3
|
-
import { View } from 'react-native';
|
|
3
|
+
import { Platform, View } from 'react-native';
|
|
4
4
|
import Text from '../../../Text';
|
|
5
5
|
import { useConfigGlobalState } from '../../../../iot/states';
|
|
6
6
|
import {
|
|
@@ -54,7 +54,15 @@ const EvaluationOverConfigDisplay = memo(
|
|
|
54
54
|
<IconComponent icon={icon_kit || icon} />
|
|
55
55
|
</View>
|
|
56
56
|
<View style={styles.rowTop}>
|
|
57
|
-
<Text
|
|
57
|
+
<Text
|
|
58
|
+
numberOfLines={1}
|
|
59
|
+
semibold
|
|
60
|
+
style={
|
|
61
|
+
Platform.OS === 'ios' ? styles.iosStyle : styles.androidStyle
|
|
62
|
+
}
|
|
63
|
+
>
|
|
64
|
+
{stationItem?.configuration?.config_data?.name}
|
|
65
|
+
</Text>
|
|
58
66
|
</View>
|
|
59
67
|
|
|
60
68
|
<View style={styles.rowBottom}>
|
|
@@ -16,6 +16,7 @@ export default StyleSheet.create({
|
|
|
16
16
|
alignItems: 'center',
|
|
17
17
|
},
|
|
18
18
|
textValue: {
|
|
19
|
+
fontSize: 16,
|
|
19
20
|
marginTop: 6,
|
|
20
21
|
lineHeight: 16,
|
|
21
22
|
},
|
|
@@ -31,4 +32,14 @@ export default StyleSheet.create({
|
|
|
31
32
|
marginTop10: {
|
|
32
33
|
marginTop: 10,
|
|
33
34
|
},
|
|
35
|
+
iosStyle: {
|
|
36
|
+
fontSize: 14,
|
|
37
|
+
lineHeight: 22,
|
|
38
|
+
},
|
|
39
|
+
androidStyle: {
|
|
40
|
+
fontSize: 14,
|
|
41
|
+
lineHeight: 22,
|
|
42
|
+
includeFontPadding: false,
|
|
43
|
+
marginBottom: 8,
|
|
44
|
+
},
|
|
34
45
|
});
|
|
@@ -106,13 +106,12 @@ const ShortDetailSubUnit = ({ unit, station, isOwner }) => {
|
|
|
106
106
|
});
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
const renderSubUnitItem = (device, stationItem
|
|
109
|
+
const renderSubUnitItem = (device, stationItem) => {
|
|
110
110
|
return (
|
|
111
111
|
<DeviceTemplate
|
|
112
112
|
device={device}
|
|
113
113
|
stationItem={stationItem}
|
|
114
|
-
|
|
115
|
-
key={index}
|
|
114
|
+
key={`device-template-${stationItem.id}`}
|
|
116
115
|
unit={unit}
|
|
117
116
|
station={station}
|
|
118
117
|
/>
|
|
@@ -126,7 +125,7 @@ const ShortDetailSubUnit = ({ unit, station, isOwner }) => {
|
|
|
126
125
|
|
|
127
126
|
return station.devices
|
|
128
127
|
.map((device, index) => {
|
|
129
|
-
|
|
128
|
+
let displays = [];
|
|
130
129
|
if (device.device_type === DEVICE_TYPE.HANET) {
|
|
131
130
|
displays.push(
|
|
132
131
|
<ItemHanetDevice
|
|
@@ -157,7 +156,7 @@ const ShortDetailSubUnit = ({ unit, station, isOwner }) => {
|
|
|
157
156
|
/>
|
|
158
157
|
);
|
|
159
158
|
}
|
|
160
|
-
if (device.station_items) {
|
|
159
|
+
if (device.station_items?.length) {
|
|
161
160
|
displays.push(
|
|
162
161
|
...device.station_items.map(renderSubUnitItem.bind(device, device))
|
|
163
162
|
);
|
|
@@ -1446,5 +1446,6 @@ export default {
|
|
|
1446
1446
|
bellow_widget_is_not_configured: 'Bellow widget is not configured',
|
|
1447
1447
|
bellow_widget_is_wrongly_configured: 'Bellow widget is wrongly configured',
|
|
1448
1448
|
'customize...': 'Customize...',
|
|
1449
|
+
uri_invalid: 'URI invalid',
|
|
1449
1450
|
when_value_is: 'When value is',
|
|
1450
1451
|
};
|
|
@@ -1456,5 +1456,6 @@ export default {
|
|
|
1456
1456
|
bellow_widget_is_not_configured: 'Tiện ích bên dưới chưa được cấu hình',
|
|
1457
1457
|
bellow_widget_is_wrongly_configured: 'Tiện ích bên dưới được cấu hình sai',
|
|
1458
1458
|
'customize...': 'Tùy chỉnh...',
|
|
1459
|
+
uri_invalid: 'URI không hợp lệ',
|
|
1459
1460
|
when_value_is: 'Khi giá trị là',
|
|
1460
1461
|
};
|
package/src/utils/Validation.js
CHANGED
|
@@ -14,3 +14,8 @@ export const isValidPhoneNumberOrEmailAddress = (data) => {
|
|
|
14
14
|
|
|
15
15
|
export const isHTML = (string) =>
|
|
16
16
|
/<[a-z]+\d?(\s+[\w-]+=("[^"]*"|'[^']*'))*\s*\/?>|&#?\w+;/i.test(string);
|
|
17
|
+
|
|
18
|
+
export const isValidURI = (uri) => {
|
|
19
|
+
const uriRegex = /^(rtsp|http|https):\/\/[^\s/$.?#].[^\s]*$/;
|
|
20
|
+
return uriRegex.test(uri);
|
|
21
|
+
};
|