@eohjsc/react-native-smart-city 0.3.23 → 0.3.26
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/ActionGroup/CurtainButtonTemplate.js +9 -17
- package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +6 -8
- package/src/commons/ActionGroup/OnOffSmartLock/OnOffSmartLock.js +3 -13
- package/src/commons/ActionGroup/OnOffTemplate/index.js +4 -23
- package/src/commons/ActionGroup/OneBigButtonTemplate.js +2 -3
- package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +2 -6
- package/src/commons/ActionGroup/SliderRangeTemplate.js +8 -10
- package/src/commons/ActionGroup/StatesGridActionTemplate.js +2 -14
- package/src/commons/ActionGroup/ThreeButtonTemplate.js +6 -9
- package/src/commons/ActionGroup/TwoButtonTemplate/index.js +6 -18
- package/src/commons/ActionGroup/__test__/CurtainButtonTemplate.test.js +3 -15
- package/src/commons/ActionGroup/__test__/NumberUpDownTemplate.test.js +1 -2
- package/src/commons/ActionGroup/__test__/OnOffSmartLock.test.js +2 -10
- package/src/commons/ActionGroup/__test__/OnOffTemplate.test.js +3 -15
- package/src/commons/ActionGroup/__test__/OneBigButtonTemplate.test.js +1 -1
- package/src/commons/ActionGroup/__test__/OptionsDropdownTemplate.test.js +3 -9
- package/src/commons/ActionGroup/__test__/StatesGridActionTemplate.test.js +1 -7
- package/src/commons/ActionGroup/__test__/TwoButtonTemplate.test.js +10 -2
- package/src/commons/ActionGroup/__test__/index.test.js +7 -17
- package/src/commons/ConnectingProcess/index.js +6 -25
- package/src/commons/Device/HistoryChart.js +8 -6
- package/src/commons/RowItem/styles.js +0 -1
- package/src/commons/SubUnit/ShortDetail.js +13 -1
- package/src/configs/API.js +1 -1
- package/src/configs/Constants.js +4 -0
- package/src/context/actionType.ts +1 -0
- package/src/context/reducer.ts +9 -0
- package/src/hooks/IoT/__test__/useRemoteControl.test.js +9 -11
- package/src/hooks/IoT/useRemoteControl.js +2 -3
- package/src/iot/RemoteControl/Internet.js +1 -8
- package/src/navigations/UnitStack.js +11 -0
- package/src/screens/Device/components/SensorDisplayItem.js +2 -2
- package/src/screens/Device/detail.js +0 -7
- package/src/screens/GuestInfo/index.js +11 -4
- package/src/screens/GuestInfo/styles/indexStyles.js +7 -0
- package/src/screens/ManageAccess/index.js +14 -5
- package/src/screens/ManageAccess/styles/ManageAccessStyles.js +9 -0
- package/src/screens/PlayBackCamera/Timer.js +3 -0
- package/src/screens/PlayBackCamera/__test__/index.test.js +8 -1
- package/src/screens/PlayBackCamera/index.js +86 -49
- package/src/screens/Unit/Detail.js +16 -10
- package/src/screens/Unit/components/MyUnitDevice/index.js +2 -1
- package/src/screens/Unit/components/__test__/AutomateScript.test.js +116 -0
|
@@ -13,13 +13,13 @@ import Text from '../../commons/Text';
|
|
|
13
13
|
import Timer from './Timer';
|
|
14
14
|
import { useStatusBarPreview } from '../../hooks/Common/useStatusBar';
|
|
15
15
|
import MediaPlayerFull from '../../commons/MediaPlayerDetail/MediaPlayerFull';
|
|
16
|
-
import { TESTID } from '../../configs/Constants';
|
|
16
|
+
import { DATE_TIME_FORMAT, TESTID } from '../../configs/Constants';
|
|
17
17
|
|
|
18
|
-
let dateTemp = moment().format(
|
|
18
|
+
let dateTemp = moment().format(DATE_TIME_FORMAT.YMD);
|
|
19
19
|
let isFirstTime = true;
|
|
20
20
|
|
|
21
21
|
const PlayBackCamera = () => {
|
|
22
|
-
const now = useMemo(() => moment().format(
|
|
22
|
+
const now = useMemo(() => moment().format(DATE_TIME_FORMAT.YMD), []);
|
|
23
23
|
const hourTemp = useMemo(() => moment().format('HH:mm:ss'), []);
|
|
24
24
|
const arrHourTemp = useMemo(() => hourTemp.split(':'), [hourTemp]);
|
|
25
25
|
const t = useTranslations();
|
|
@@ -33,7 +33,8 @@ const PlayBackCamera = () => {
|
|
|
33
33
|
s: arrHourTemp[2],
|
|
34
34
|
});
|
|
35
35
|
const [uri, setUri] = useState(item?.configuration?.uri);
|
|
36
|
-
const [
|
|
36
|
+
const [mainURI, setMainURI] = useState(uri);
|
|
37
|
+
const [paused, setPaused] = useState(false);
|
|
37
38
|
const onOpenDateModal = useCallback(() => {
|
|
38
39
|
setIsShowDate(true);
|
|
39
40
|
}, []);
|
|
@@ -49,19 +50,52 @@ const PlayBackCamera = () => {
|
|
|
49
50
|
}, [selected]);
|
|
50
51
|
|
|
51
52
|
const onAddDate = useCallback(() => {
|
|
53
|
+
setPaused(true);
|
|
52
54
|
if (selected !== now) {
|
|
53
|
-
const date = moment(selected).add(1, 'days').format(
|
|
55
|
+
const date = moment(selected).add(1, 'days').format(DATE_TIME_FORMAT.YMD);
|
|
54
56
|
setSelected(date);
|
|
55
57
|
dateTemp = date;
|
|
56
58
|
}
|
|
57
59
|
}, [selected, now]);
|
|
58
60
|
|
|
59
61
|
const onSubtractDate = useCallback(() => {
|
|
60
|
-
|
|
62
|
+
setPaused(true);
|
|
63
|
+
const date = moment(selected)
|
|
64
|
+
.subtract(1, 'days')
|
|
65
|
+
.format(DATE_TIME_FORMAT.YMD);
|
|
61
66
|
setSelected(date);
|
|
62
67
|
dateTemp = date;
|
|
63
68
|
}, [selected]);
|
|
64
69
|
|
|
70
|
+
const getHourWithTimeZone = useCallback(
|
|
71
|
+
// eslint-disable-next-line no-shadow
|
|
72
|
+
(hour) => {
|
|
73
|
+
const hourWithTimezone =
|
|
74
|
+
parseInt(hour, 10) + parseInt(item?.configuration?.time_zone || 0, 10);
|
|
75
|
+
return hourWithTimezone < 10 ? '0' + hourWithTimezone : hourWithTimezone;
|
|
76
|
+
},
|
|
77
|
+
[item?.configuration?.time_zone]
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const onScrollEndDrag = useCallback(() => {
|
|
81
|
+
setMainURI(uri);
|
|
82
|
+
setPaused(false);
|
|
83
|
+
}, [uri]);
|
|
84
|
+
|
|
85
|
+
const onDayPress = useCallback((day) => {
|
|
86
|
+
setPaused(true);
|
|
87
|
+
setSelected(day.dateString);
|
|
88
|
+
}, []);
|
|
89
|
+
|
|
90
|
+
const onPressArrowLeft = useCallback((subtractMonth) => {
|
|
91
|
+
setPaused(true);
|
|
92
|
+
subtractMonth && subtractMonth();
|
|
93
|
+
}, []);
|
|
94
|
+
|
|
95
|
+
const onPressArrowRight = useCallback((addMonth) => {
|
|
96
|
+
addMonth && addMonth();
|
|
97
|
+
}, []);
|
|
98
|
+
|
|
65
99
|
const onChangeValue = useCallback(
|
|
66
100
|
(value, selectedTime) => {
|
|
67
101
|
if (!isFirstTime) {
|
|
@@ -87,41 +121,53 @@ const PlayBackCamera = () => {
|
|
|
87
121
|
setUri(
|
|
88
122
|
`${playback.split('=')[0]}=${date[0]}${date[1]}${
|
|
89
123
|
date[2]
|
|
90
|
-
}T${h}${m}${s}Z`
|
|
124
|
+
}T${getHourWithTimeZone(h)}${m}${s}Z`
|
|
91
125
|
);
|
|
92
126
|
}
|
|
93
|
-
const to = setTimeout(() => {
|
|
94
|
-
setPaused(false);
|
|
95
|
-
clearTimeout(to);
|
|
96
|
-
}, 100);
|
|
97
127
|
}
|
|
98
128
|
},
|
|
99
|
-
[
|
|
129
|
+
[
|
|
130
|
+
arrHourTemp,
|
|
131
|
+
getHourWithTimeZone,
|
|
132
|
+
item?.configuration?.playback,
|
|
133
|
+
item?.configuration?.uri,
|
|
134
|
+
now,
|
|
135
|
+
]
|
|
100
136
|
);
|
|
101
137
|
|
|
138
|
+
const renderArrow = useCallback((direction) => {
|
|
139
|
+
return (
|
|
140
|
+
<Image
|
|
141
|
+
source={Images.arrowLeft}
|
|
142
|
+
style={[direction !== 'left' && styles.arrowRight]}
|
|
143
|
+
/>
|
|
144
|
+
);
|
|
145
|
+
}, []);
|
|
146
|
+
|
|
102
147
|
useEffect(() => {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
148
|
+
if (!isFirstTime) {
|
|
149
|
+
const date = selected.split('-');
|
|
150
|
+
const playback = item?.configuration?.playback || '';
|
|
151
|
+
if (
|
|
152
|
+
selected === now &&
|
|
153
|
+
parseInt(moment().format('HH:mm:ss'), 10) <=
|
|
154
|
+
parseInt(`${hour.h}:${hour.m}:${hour.s}`, 10)
|
|
155
|
+
) {
|
|
156
|
+
setMainURI(item?.configuration?.uri);
|
|
157
|
+
} else {
|
|
158
|
+
setMainURI(
|
|
159
|
+
`${playback.split('=')[0]}=${date[0]}${date[1]}${
|
|
160
|
+
date[2]
|
|
161
|
+
}T${getHourWithTimeZone(hour.h)}${hour.m}${hour.s}Z`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
const to = setTimeout(() => {
|
|
165
|
+
setPaused(false);
|
|
166
|
+
clearTimeout(to);
|
|
167
|
+
}, 100);
|
|
118
168
|
}
|
|
119
|
-
const to = setTimeout(() => {
|
|
120
|
-
setPaused(false);
|
|
121
|
-
clearTimeout(to);
|
|
122
|
-
}, 100);
|
|
123
169
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
124
|
-
}, [selected]);
|
|
170
|
+
}, [selected, getHourWithTimeZone]);
|
|
125
171
|
|
|
126
172
|
useEffect(() => {
|
|
127
173
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
@@ -136,7 +182,7 @@ const PlayBackCamera = () => {
|
|
|
136
182
|
clearTimeout(to);
|
|
137
183
|
}, 2000);
|
|
138
184
|
return () => {
|
|
139
|
-
dateTemp = moment().format(
|
|
185
|
+
dateTemp = moment().format(DATE_TIME_FORMAT.YMD);
|
|
140
186
|
isFirstTime = true;
|
|
141
187
|
};
|
|
142
188
|
}, []);
|
|
@@ -145,7 +191,7 @@ const PlayBackCamera = () => {
|
|
|
145
191
|
<View style={styles.wrap}>
|
|
146
192
|
<HeaderCustom title={t('video_detail')} />
|
|
147
193
|
<MediaPlayerFull
|
|
148
|
-
uri={
|
|
194
|
+
uri={mainURI}
|
|
149
195
|
isPaused={paused}
|
|
150
196
|
thumbnail={thumbnail}
|
|
151
197
|
isShowFullScreenIcon
|
|
@@ -207,6 +253,7 @@ const PlayBackCamera = () => {
|
|
|
207
253
|
indicatorHeight={40}
|
|
208
254
|
onChangeValue={onChangeValue}
|
|
209
255
|
selected={selected}
|
|
256
|
+
onScrollEndDrag={onScrollEndDrag}
|
|
210
257
|
/>
|
|
211
258
|
</View>
|
|
212
259
|
</View>
|
|
@@ -214,13 +261,10 @@ const PlayBackCamera = () => {
|
|
|
214
261
|
<ModalCustom isVisible={isShowDate} style={styles.modal}>
|
|
215
262
|
<View style={styles.wrapDate}>
|
|
216
263
|
<Calendar
|
|
217
|
-
onDayPress={
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
onMonthChange={(month) => {}}
|
|
222
|
-
onPressArrowLeft={(subtractMonth) => subtractMonth()}
|
|
223
|
-
onPressArrowRight={(addMonth) => addMonth()}
|
|
264
|
+
onDayPress={onDayPress}
|
|
265
|
+
maxDate={moment().format(DATE_TIME_FORMAT.YMD)}
|
|
266
|
+
onPressArrowLeft={onPressArrowLeft}
|
|
267
|
+
onPressArrowRight={onPressArrowRight}
|
|
224
268
|
markedDates={{
|
|
225
269
|
[selected]: {
|
|
226
270
|
selected: true,
|
|
@@ -230,14 +274,7 @@ const PlayBackCamera = () => {
|
|
|
230
274
|
},
|
|
231
275
|
}}
|
|
232
276
|
enableSwipeMonths={true}
|
|
233
|
-
renderArrow={
|
|
234
|
-
if (direction === 'left') {
|
|
235
|
-
return <Image source={Images.arrowLeft} />;
|
|
236
|
-
}
|
|
237
|
-
return (
|
|
238
|
-
<Image source={Images.arrowLeft} style={styles.arrowRight} />
|
|
239
|
-
);
|
|
240
|
-
}}
|
|
277
|
+
renderArrow={renderArrow}
|
|
241
278
|
headerStyle={styles.headerStyle}
|
|
242
279
|
/>
|
|
243
280
|
<View style={styles.viewSeparated} />
|
|
@@ -291,6 +291,21 @@ const UnitDetail = ({ route }) => {
|
|
|
291
291
|
navigate(isLavidaSource ? Routes.SmartHomeDashboard : Routes.Dashboard);
|
|
292
292
|
}, [isLavidaSource, navigate]);
|
|
293
293
|
|
|
294
|
+
const renderCamera = useMemo(() => {
|
|
295
|
+
return (
|
|
296
|
+
isFirstOpenCamera &&
|
|
297
|
+
isIOS && (
|
|
298
|
+
<MediaPlayerDetail
|
|
299
|
+
uri={Constants.URL_STREAM_CAMERA_DEMO}
|
|
300
|
+
isPaused={false}
|
|
301
|
+
width={1}
|
|
302
|
+
height={1}
|
|
303
|
+
style={styles.fakeCamera}
|
|
304
|
+
/>
|
|
305
|
+
)
|
|
306
|
+
);
|
|
307
|
+
}, [isFirstOpenCamera, isIOS]);
|
|
308
|
+
|
|
294
309
|
useEffect(() => {
|
|
295
310
|
watchNotificationData(user, onRefresh);
|
|
296
311
|
return () => unwatchNotificationData(user);
|
|
@@ -319,16 +334,7 @@ const UnitDetail = ({ route }) => {
|
|
|
319
334
|
hideRightPlus={!isOwner}
|
|
320
335
|
onBack={(isSuccessfullyConnected && Dashboard) || (routeName && onBack)}
|
|
321
336
|
>
|
|
322
|
-
{
|
|
323
|
-
{isFirstOpenCamera && isIOS && (
|
|
324
|
-
<MediaPlayerDetail
|
|
325
|
-
uri={Constants.URL_STREAM_CAMERA_DEMO}
|
|
326
|
-
isPaused={false}
|
|
327
|
-
width={1}
|
|
328
|
-
height={1}
|
|
329
|
-
style={styles.fakeCamera}
|
|
330
|
-
/>
|
|
331
|
-
)}
|
|
337
|
+
{renderCamera}
|
|
332
338
|
|
|
333
339
|
<View style={styles.container}>
|
|
334
340
|
<Summaries unit={unit} />
|
|
@@ -67,7 +67,7 @@ const styles = StyleSheet.create({
|
|
|
67
67
|
borderRadius: 16,
|
|
68
68
|
justifyContent: 'center',
|
|
69
69
|
alignItems: 'center',
|
|
70
|
-
marginLeft:
|
|
70
|
+
marginLeft: 5,
|
|
71
71
|
},
|
|
72
72
|
nameDevice: {
|
|
73
73
|
fontSize: 14,
|
|
@@ -81,6 +81,7 @@ const styles = StyleSheet.create({
|
|
|
81
81
|
roomDevicePart: {
|
|
82
82
|
fontSize: 12,
|
|
83
83
|
lineHeight: 20,
|
|
84
|
+
width: '100%',
|
|
84
85
|
},
|
|
85
86
|
rowCenter: {
|
|
86
87
|
flexDirection: 'row',
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TouchableWithoutFeedback, View } from 'react-native';
|
|
3
|
+
import { act, create } from 'react-test-renderer';
|
|
4
|
+
import { AUTOMATE_TYPE } from '../../../../configs/Constants';
|
|
5
|
+
import { SCProvider } from '../../../../context';
|
|
6
|
+
import { mockSCStore } from '../../../../context/mockStore';
|
|
7
|
+
import AutomateScript from '../AutomateScript';
|
|
8
|
+
|
|
9
|
+
const mockOnPress = jest.fn();
|
|
10
|
+
|
|
11
|
+
const wrapComponent = (isSelected, automate = 'automate') => (
|
|
12
|
+
<SCProvider initState={mockSCStore({})}>
|
|
13
|
+
<AutomateScript
|
|
14
|
+
automate={automate}
|
|
15
|
+
onPress={mockOnPress}
|
|
16
|
+
isSelected={isSelected}
|
|
17
|
+
/>
|
|
18
|
+
</SCProvider>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
describe('test AutomateScript screen', () => {
|
|
22
|
+
let tree,
|
|
23
|
+
automate = { type: '' };
|
|
24
|
+
it('Test isSelected=false', async () => {
|
|
25
|
+
await act(async () => {
|
|
26
|
+
tree = await create(wrapComponent(false, automate));
|
|
27
|
+
});
|
|
28
|
+
const instance = tree.root;
|
|
29
|
+
const TouchableWithoutFeedbacks = instance.findAllByType(
|
|
30
|
+
TouchableWithoutFeedback
|
|
31
|
+
);
|
|
32
|
+
await TouchableWithoutFeedbacks[0].props.onPress();
|
|
33
|
+
expect(mockOnPress).toBeCalledWith(automate);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('Test isSelected=true', async () => {
|
|
37
|
+
await act(async () => {
|
|
38
|
+
tree = await create(wrapComponent(true));
|
|
39
|
+
});
|
|
40
|
+
const instance = tree.root;
|
|
41
|
+
const Views = instance.findAllByType(View);
|
|
42
|
+
expect(Views[0].props.style).toEqual([
|
|
43
|
+
{
|
|
44
|
+
padding: 12,
|
|
45
|
+
borderRadius: 10,
|
|
46
|
+
shadowColor: '#303133',
|
|
47
|
+
shadowOffset: {
|
|
48
|
+
height: 2,
|
|
49
|
+
width: 0,
|
|
50
|
+
},
|
|
51
|
+
shadowOpacity: 0.1,
|
|
52
|
+
shadowRadius: 3,
|
|
53
|
+
elevation: 4,
|
|
54
|
+
width: 353,
|
|
55
|
+
height: 204.144578313253,
|
|
56
|
+
backgroundColor: '#FFFFFF',
|
|
57
|
+
justifyContent: 'space-between',
|
|
58
|
+
marginBottom: 8,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
borderColor: '#00979D',
|
|
62
|
+
borderWidth: 2,
|
|
63
|
+
},
|
|
64
|
+
]);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('Test render VALUE_CHANGE', async () => {
|
|
68
|
+
automate = { ...automate, type: AUTOMATE_TYPE.VALUE_CHANGE };
|
|
69
|
+
await act(async () => {
|
|
70
|
+
tree = await create(wrapComponent(true, automate));
|
|
71
|
+
});
|
|
72
|
+
const instance = tree.root;
|
|
73
|
+
const Views = instance.findAllByType(View);
|
|
74
|
+
expect(Views).toHaveLength(9);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('Test render ONE_TAP', async () => {
|
|
78
|
+
automate = { ...automate, type: AUTOMATE_TYPE.ONE_TAP };
|
|
79
|
+
await act(async () => {
|
|
80
|
+
tree = await create(wrapComponent(true, automate));
|
|
81
|
+
});
|
|
82
|
+
const instance = tree.root;
|
|
83
|
+
const Views = instance.findAllByType(View);
|
|
84
|
+
expect(Views).toHaveLength(9);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('Test render EVENT', async () => {
|
|
88
|
+
automate = { ...automate, type: AUTOMATE_TYPE.EVENT };
|
|
89
|
+
await act(async () => {
|
|
90
|
+
tree = await create(wrapComponent(true, automate));
|
|
91
|
+
});
|
|
92
|
+
const instance = tree.root;
|
|
93
|
+
const Views = instance.findAllByType(View);
|
|
94
|
+
expect(Views).toHaveLength(9);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('Test render SCHEDULE', async () => {
|
|
98
|
+
automate = { ...automate, type: AUTOMATE_TYPE.SCHEDULE };
|
|
99
|
+
await act(async () => {
|
|
100
|
+
tree = await create(wrapComponent(true, automate));
|
|
101
|
+
});
|
|
102
|
+
const instance = tree.root;
|
|
103
|
+
const Views = instance.findAllByType(View);
|
|
104
|
+
expect(Views).toHaveLength(9);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('Test render with iconKit', async () => {
|
|
108
|
+
automate = { ...automate, script: { icon_kit: 'iconKit' } };
|
|
109
|
+
await act(async () => {
|
|
110
|
+
tree = await create(wrapComponent(true, automate));
|
|
111
|
+
});
|
|
112
|
+
const instance = tree.root;
|
|
113
|
+
const Views = instance.findAllByType(View);
|
|
114
|
+
expect(Views).toHaveLength(10);
|
|
115
|
+
});
|
|
116
|
+
});
|