@eohjsc/react-native-smart-city 0.3.25 → 0.3.28
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/index.js +2 -0
- package/package.json +1 -1
- package/src/Images/Common/device_icon.png +0 -0
- package/src/Images/DevMode/gateway.png +0 -0
- package/src/Images/DevMode/gateway@2x.png +0 -0
- package/src/Images/DevMode/gateway@3x.png +0 -0
- package/src/Images/DevMode/menu.png +0 -0
- package/src/Images/DevMode/menu@2x.png +0 -0
- package/src/Images/DevMode/menu@3x.png +0 -0
- package/src/Images/DevMode/search.png +0 -0
- package/src/Images/DevMode/search@2x.png +0 -0
- package/src/Images/DevMode/search@3x.png +0 -0
- package/src/Images/DevMode/smart.png +0 -0
- package/src/Images/DevMode/smart@2x.png +0 -0
- package/src/Images/DevMode/smart@3x.png +0 -0
- package/src/Images/DevMode/template.png +0 -0
- package/src/Images/DevMode/template@2x.png +0 -0
- package/src/Images/DevMode/template@3x.png +0 -0
- package/src/commons/ActionGroup/SliderRangeTemplate.js +7 -7
- package/src/commons/CameraDevice/index.js +1 -2
- package/src/commons/ConnectingProcess/DeviceItem/DeviceItem.js +20 -12
- package/src/commons/ConnectingProcess/DeviceItem/DeviceItemStyles.js +2 -0
- package/src/commons/ConnectingProcess/__test__/DeviceItem.test.js +1 -1
- package/src/commons/ConnectingProcess/index.js +11 -0
- package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +55 -5
- package/src/commons/Dashboard/MyUnit/index.js +59 -12
- package/src/commons/DevMode/Label.js +10 -0
- package/src/commons/DevMode/Search.js +20 -0
- package/src/commons/DevMode/Styles/LabelStyles.js +8 -0
- package/src/commons/DevMode/Styles/SearchStyles.js +21 -0
- package/src/commons/DevMode/index.js +3 -0
- package/src/commons/Form/TextInput.js +4 -0
- package/src/commons/MediaPlayerDetail/index.js +0 -20
- package/src/commons/MenuActionMore/index.js +1 -3
- package/src/commons/Modal/index.js +1 -2
- package/src/commons/Popover/index.js +26 -0
- package/src/commons/Tabbar/Styles/indexStyles.js +51 -0
- package/src/commons/Tabbar/index.js +110 -0
- package/src/configs/Colors.js +4 -0
- package/src/configs/Images.js +6 -0
- package/src/context/actionType.ts +2 -0
- package/src/context/reducer.ts +10 -0
- package/src/hooks/Common/useGGHomeDeviceConnected.js +9 -2
- package/src/hooks/Common/usePopover.js +0 -8
- package/src/hooks/IoT/useGGHomeConnection.js +0 -1
- package/src/navigations/GatewayStack.js +23 -0
- package/src/navigations/Main.js +144 -0
- package/src/navigations/SmartStack.js +23 -0
- package/src/navigations/TemplateStack.js +23 -0
- package/src/navigations/UnitStack.js +10 -2
- package/src/screens/AllCamera/__test__/index.test.js +1 -8
- package/src/screens/AllCamera/index.js +0 -13
- package/src/screens/Device/hooks/__test__/useEmergencyButton.test.js +37 -0
- package/src/screens/Drawer/Drawer.test.js +24 -0
- package/src/screens/Drawer/index.js +198 -0
- package/src/screens/Gateway/__test__/index.test.js +16 -0
- package/src/screens/Gateway/index.js +8 -0
- 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/ScriptDetail/__test__/index.test.js +0 -3
- package/src/screens/ScriptDetail/index.js +7 -10
- package/src/screens/Smart/__test__/index.test.js +16 -0
- package/src/screens/Smart/index.js +8 -0
- package/src/screens/SubUnit/AddSubUnit.js +1 -1
- package/src/screens/SubUnit/EditSubUnit.js +4 -1
- package/src/screens/Template/Styles/indexStyles.js +51 -0
- package/src/screens/Template/__test__/index.test.js +16 -0
- package/src/screens/Template/index.js +84 -0
- package/src/screens/Unit/Detail.js +5 -27
- package/src/screens/Unit/SmartAccount.js +7 -6
- package/src/screens/Unit/Station/__test__/index.test.js +41 -0
- package/src/screens/Unit/Summaries.js +8 -1
- package/src/screens/Unit/__test__/Detail.test.js +1 -5
- package/src/screens/Unit/components/Header/index.js +1 -1
- package/src/screens/Unit/components/MyUnitDevice/index.js +29 -12
- package/src/screens/Unit/components/__test__/Header.test.js +1 -1
- package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +2 -2
- package/src/screens/Unit/hook/useUnitConnectRemoteDevices.js +6 -5
- package/src/utils/Converter/__test__/timer.test.js +99 -0
- package/src/utils/Functions/Search.js +17 -0
- package/src/utils/Functions/ShortEmail.js +4 -0
- package/src/utils/Functions/__test__/Search.test.js +6 -0
- package/src/utils/Functions/__test__/ShortEmail.test.js +6 -0
- package/src/utils/I18n/translations/en.json +11 -1
- package/src/utils/I18n/translations/vi.json +11 -1
- package/src/utils/Route/index.js +6 -0
- package/src/commons/Modal/ModalFullVideo.js +0 -48
- package/src/commons/Modal/Styles/ModalFullVideoStyles.js +0 -26
- package/src/screens/Unit/components/MyUnit/index.js +0 -136
- package/src/screens/Unit/components/__test__/MyUnit.test.js +0 -35
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { isIphoneX } from 'react-native-iphone-x-helper';
|
|
3
|
+
import { Colors } from '../../../configs';
|
|
4
|
+
|
|
5
|
+
const widthBadge = 20;
|
|
6
|
+
export default StyleSheet.create({
|
|
7
|
+
wrap: {
|
|
8
|
+
flexDirection: 'row',
|
|
9
|
+
height: 70,
|
|
10
|
+
backgroundColor: Colors.White,
|
|
11
|
+
paddingHorizontal: 10,
|
|
12
|
+
borderTopWidth: 1,
|
|
13
|
+
borderColor: Colors.Gray4,
|
|
14
|
+
},
|
|
15
|
+
label: {
|
|
16
|
+
textAlign: 'center',
|
|
17
|
+
fontSize: 12,
|
|
18
|
+
marginTop: 10,
|
|
19
|
+
marginBottom: isIphoneX() ? 10 : 0,
|
|
20
|
+
},
|
|
21
|
+
wrapTab: {
|
|
22
|
+
flex: 1,
|
|
23
|
+
justifyContent: 'center',
|
|
24
|
+
alignItems: 'center',
|
|
25
|
+
},
|
|
26
|
+
icon: {
|
|
27
|
+
marginBottom: -8,
|
|
28
|
+
},
|
|
29
|
+
wrapIcon: {
|
|
30
|
+
position: 'relative',
|
|
31
|
+
},
|
|
32
|
+
badgeCount: {
|
|
33
|
+
width: widthBadge,
|
|
34
|
+
height: 20,
|
|
35
|
+
flexDirection: 'row',
|
|
36
|
+
justifyContent: 'center',
|
|
37
|
+
alignItems: 'center',
|
|
38
|
+
backgroundColor: Colors.Red,
|
|
39
|
+
borderRadius: widthBadge / 2,
|
|
40
|
+
position: 'absolute',
|
|
41
|
+
top: -8,
|
|
42
|
+
right: -8,
|
|
43
|
+
},
|
|
44
|
+
txtBadge: {
|
|
45
|
+
color: Colors.White,
|
|
46
|
+
fontSize: 12,
|
|
47
|
+
},
|
|
48
|
+
iconActive: {
|
|
49
|
+
tintColor: Colors.Primary,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import React, { memo, useEffect } from 'react';
|
|
2
|
+
import { Animated, View, Text, TouchableOpacity, Image } from 'react-native';
|
|
3
|
+
import Routes from '../../utils/Route';
|
|
4
|
+
import { Colors } from '../../configs/Colors';
|
|
5
|
+
import { Constants } from '../../configs/Constants';
|
|
6
|
+
import styles from './Styles/indexStyles';
|
|
7
|
+
import { Images } from '../../configs';
|
|
8
|
+
|
|
9
|
+
export const getTabBarIcon = (routeName) => {
|
|
10
|
+
switch (routeName) {
|
|
11
|
+
case Routes.TemplateStack:
|
|
12
|
+
return Images.template;
|
|
13
|
+
case Routes.GatewayStack:
|
|
14
|
+
return Images.gateway;
|
|
15
|
+
case Routes.SmartStack:
|
|
16
|
+
return Images.smart;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const getWidth = () => (Constants.width - 12) / 3;
|
|
21
|
+
|
|
22
|
+
const TabBarItem = ({
|
|
23
|
+
descriptor,
|
|
24
|
+
route,
|
|
25
|
+
index,
|
|
26
|
+
isFocused,
|
|
27
|
+
navigation,
|
|
28
|
+
notificationNumber,
|
|
29
|
+
updateLastSeen,
|
|
30
|
+
}) => {
|
|
31
|
+
const { options } = descriptor;
|
|
32
|
+
const label =
|
|
33
|
+
options.tabBarLabel !== undefined
|
|
34
|
+
? options.tabBarLabel
|
|
35
|
+
: options.title !== undefined
|
|
36
|
+
? options.title
|
|
37
|
+
: route.name;
|
|
38
|
+
const color = isFocused ? Colors.Primary : Colors.Black;
|
|
39
|
+
|
|
40
|
+
const onPress = () => {
|
|
41
|
+
const event = navigation.emit({
|
|
42
|
+
type: 'tabPress',
|
|
43
|
+
target: route.key,
|
|
44
|
+
canPreventDefault: true,
|
|
45
|
+
});
|
|
46
|
+
if (!isFocused && !event.defaultPrevented) {
|
|
47
|
+
navigation.navigate({
|
|
48
|
+
name: route.name,
|
|
49
|
+
merge: true,
|
|
50
|
+
params: { isMainSource: options.isMainSource },
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (isFocused) {
|
|
57
|
+
Animated.spring(options.tabOffSetValue, {
|
|
58
|
+
toValue: getWidth() * index,
|
|
59
|
+
useNativeDriver: true,
|
|
60
|
+
}).start();
|
|
61
|
+
}
|
|
62
|
+
}, [isFocused, index, options.tabOffSetValue]);
|
|
63
|
+
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (isFocused) {
|
|
66
|
+
if (route.name === Routes.NotificationStack) {
|
|
67
|
+
updateLastSeen && updateLastSeen();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}, [isFocused, route.name, updateLastSeen]);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<TouchableOpacity onPress={onPress} style={styles.wrapTab}>
|
|
74
|
+
<View style={styles.wrapIcon}>
|
|
75
|
+
<Image
|
|
76
|
+
style={[styles.icon, isFocused && styles.iconActive]}
|
|
77
|
+
source={getTabBarIcon(route.name)}
|
|
78
|
+
/>
|
|
79
|
+
{route.name === Routes.NotificationStack && notificationNumber > 0 && (
|
|
80
|
+
<View style={styles.badgeCount}>
|
|
81
|
+
<Text style={styles.txtBadge}>
|
|
82
|
+
{notificationNumber < 9 ? notificationNumber : '9+'}
|
|
83
|
+
</Text>
|
|
84
|
+
</View>
|
|
85
|
+
)}
|
|
86
|
+
</View>
|
|
87
|
+
|
|
88
|
+
<Text style={[styles.label, { color }]}>{label}</Text>
|
|
89
|
+
</TouchableOpacity>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const TabBar = ({ state, descriptors, navigation }) => {
|
|
94
|
+
return (
|
|
95
|
+
<View style={styles.wrap}>
|
|
96
|
+
{state.routes.map((route, index) => (
|
|
97
|
+
<TabBarItem
|
|
98
|
+
key={index}
|
|
99
|
+
descriptor={descriptors[route.key]}
|
|
100
|
+
route={route}
|
|
101
|
+
index={index}
|
|
102
|
+
isFocused={state.index === index}
|
|
103
|
+
navigation={navigation}
|
|
104
|
+
/>
|
|
105
|
+
))}
|
|
106
|
+
</View>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export default memo(TabBar);
|
package/src/configs/Colors.js
CHANGED
package/src/configs/Images.js
CHANGED
|
@@ -13,4 +13,10 @@ export default {
|
|
|
13
13
|
shadowButton: require('../Images/Common/shadowButton.png'),
|
|
14
14
|
eye: require('../Images/Common/eye.png'),
|
|
15
15
|
eyeClosed: require('../Images/Common/eye-closed.png'),
|
|
16
|
+
deviceIcon: require('../Images/Common/device_icon.png'),
|
|
17
|
+
template: require('../Images/DevMode/template.png'),
|
|
18
|
+
smart: require('../Images/DevMode/smart.png'),
|
|
19
|
+
gateway: require('../Images/DevMode/gateway.png'),
|
|
20
|
+
menu: require('../Images/DevMode/menu.png'),
|
|
21
|
+
search: require('../Images/DevMode/search.png'),
|
|
16
22
|
};
|
|
@@ -23,6 +23,7 @@ export const Action = {
|
|
|
23
23
|
NEED_UPDATE_VALUE_EVALUATIONS: 'NEED_UPDATE_VALUE_EVALUATIONS',
|
|
24
24
|
ON_RECEIVE_NOTIFICATION: 'ON_RECEIVE_NOTIFICATION',
|
|
25
25
|
SET_DEVICES_STATUS: 'SET_DEVICES_STATUS',
|
|
26
|
+
SET_POPOVER_ANIMATING: 'SET_POPOVER_ANIMATING',
|
|
26
27
|
};
|
|
27
28
|
|
|
28
29
|
export type AuthData = {
|
|
@@ -80,6 +81,7 @@ export type AppType = {
|
|
|
80
81
|
isNetworkConnected: boolean;
|
|
81
82
|
camera_opened: any[];
|
|
82
83
|
notificationData: any;
|
|
84
|
+
popoverAnimating: boolean;
|
|
83
85
|
};
|
|
84
86
|
|
|
85
87
|
export type IoTType = {
|
package/src/context/reducer.ts
CHANGED
|
@@ -60,6 +60,7 @@ export const initialState = {
|
|
|
60
60
|
isNetworkConnected: false,
|
|
61
61
|
camera_opened: [],
|
|
62
62
|
notificationData: null,
|
|
63
|
+
popoverAnimating: false,
|
|
63
64
|
},
|
|
64
65
|
iot: {
|
|
65
66
|
googlehome: {
|
|
@@ -342,6 +343,15 @@ export const reducer = (currentState: ContextData, action: Action) => {
|
|
|
342
343
|
},
|
|
343
344
|
};
|
|
344
345
|
|
|
346
|
+
case Action.SET_POPOVER_ANIMATING:
|
|
347
|
+
return {
|
|
348
|
+
...currentState,
|
|
349
|
+
app: {
|
|
350
|
+
...currentState.app,
|
|
351
|
+
popoverAnimating: payload,
|
|
352
|
+
},
|
|
353
|
+
};
|
|
354
|
+
|
|
345
355
|
default:
|
|
346
356
|
return currentState;
|
|
347
357
|
}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { useSCContextSelector } from '../../context';
|
|
2
2
|
|
|
3
3
|
const useGGHomeDeviceConnected = (device) => {
|
|
4
|
-
const
|
|
4
|
+
const connections = useSCContextSelector(
|
|
5
|
+
(state) => state.iot.googlehome.connections
|
|
6
|
+
);
|
|
7
|
+
const isNetworkConnected = useSCContextSelector(
|
|
8
|
+
(state) => state.app.isNetworkConnected
|
|
9
|
+
);
|
|
5
10
|
|
|
6
|
-
const isConnecting =
|
|
11
|
+
const isConnecting =
|
|
12
|
+
isNetworkConnected && !!device?.chip_id && !(device.chip_id in connections);
|
|
7
13
|
|
|
8
14
|
const isConnected =
|
|
15
|
+
isNetworkConnected &&
|
|
9
16
|
!!device?.chip_id &&
|
|
10
17
|
device.chip_id in connections &&
|
|
11
18
|
!!connections[device.chip_id];
|
|
@@ -2,14 +2,12 @@ import { useCallback, useState, useRef } from 'react';
|
|
|
2
2
|
|
|
3
3
|
const usePopover = () => {
|
|
4
4
|
const [showingPopover, setShowingPopover] = useState(false);
|
|
5
|
-
const [hidingPopoverComplete, setHidingPopoverComplete] = useState(true);
|
|
6
5
|
const childRef = useRef(null);
|
|
7
6
|
|
|
8
7
|
const showPopoverWithRef = useCallback(
|
|
9
8
|
(ref) => {
|
|
10
9
|
childRef.current = ref.current;
|
|
11
10
|
setShowingPopover(true);
|
|
12
|
-
setHidingPopoverComplete(false);
|
|
13
11
|
},
|
|
14
12
|
[childRef]
|
|
15
13
|
);
|
|
@@ -19,17 +17,11 @@ const usePopover = () => {
|
|
|
19
17
|
setShowingPopover(false);
|
|
20
18
|
}, [childRef]);
|
|
21
19
|
|
|
22
|
-
const hidePopoverComplete = useCallback(() => {
|
|
23
|
-
setHidingPopoverComplete(true);
|
|
24
|
-
}, []);
|
|
25
|
-
|
|
26
20
|
return {
|
|
27
21
|
childRef,
|
|
28
22
|
showingPopover,
|
|
29
23
|
showPopoverWithRef,
|
|
30
24
|
hidePopover,
|
|
31
|
-
hidingPopoverComplete,
|
|
32
|
-
hidePopoverComplete,
|
|
33
25
|
};
|
|
34
26
|
};
|
|
35
27
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
|
+
import { createStackNavigator } from '@react-navigation/stack';
|
|
3
|
+
|
|
4
|
+
import Routes from '../utils/Route';
|
|
5
|
+
import { screenOptions } from './utils';
|
|
6
|
+
import Gateway from '../screens/Gateway';
|
|
7
|
+
|
|
8
|
+
const Stack = createStackNavigator();
|
|
9
|
+
|
|
10
|
+
const GatewayStack = memo(() => {
|
|
11
|
+
return (
|
|
12
|
+
<Stack.Navigator
|
|
13
|
+
screenOptions={{
|
|
14
|
+
...screenOptions,
|
|
15
|
+
headerShown: false,
|
|
16
|
+
}}
|
|
17
|
+
>
|
|
18
|
+
<Stack.Screen name={Routes.Gateway} component={Gateway} />
|
|
19
|
+
</Stack.Navigator>
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default GatewayStack;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import React, { useMemo, useRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Animated,
|
|
4
|
+
View,
|
|
5
|
+
TouchableOpacity,
|
|
6
|
+
StyleSheet,
|
|
7
|
+
Image,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
|
10
|
+
import { createDrawerNavigator } from '@react-navigation/drawer';
|
|
11
|
+
import { useNavigation } from '@react-navigation/native';
|
|
12
|
+
import { getStatusBarHeight } from 'react-native-iphone-x-helper';
|
|
13
|
+
|
|
14
|
+
import Tabbar from '../commons/Tabbar';
|
|
15
|
+
import { Colors, Constants, Images } from '../configs';
|
|
16
|
+
import t from '../hooks/Common/useTranslations';
|
|
17
|
+
import Routes from '../utils/Route';
|
|
18
|
+
import GatewayStack from './GatewayStack';
|
|
19
|
+
import SmartStack from './SmartStack';
|
|
20
|
+
import TemplateStack from './TemplateStack';
|
|
21
|
+
import DrawerContainer from '../screens/Drawer';
|
|
22
|
+
import { TESTID } from '../configs/Constants';
|
|
23
|
+
import Text from '../commons/Text';
|
|
24
|
+
|
|
25
|
+
const Tab = createBottomTabNavigator();
|
|
26
|
+
const Drawer = createDrawerNavigator();
|
|
27
|
+
|
|
28
|
+
const getWidth = () => {
|
|
29
|
+
const Width = Constants.width - 12;
|
|
30
|
+
return Width / 3;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const MainDevMode = () => {
|
|
34
|
+
const navigation = useNavigation();
|
|
35
|
+
|
|
36
|
+
const listTabName = useMemo(
|
|
37
|
+
() => [
|
|
38
|
+
{
|
|
39
|
+
name: Routes.TemplateStack,
|
|
40
|
+
tabBarLabel: t('templates'),
|
|
41
|
+
component: TemplateStack,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: Routes.GatewayStack,
|
|
45
|
+
tabBarLabel: t('gateways'),
|
|
46
|
+
component: GatewayStack,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: Routes.SmartStack,
|
|
50
|
+
tabBarLabel: t('smart'),
|
|
51
|
+
component: SmartStack,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
[]
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const tabOffSetValue = useRef(new Animated.Value(0)).current;
|
|
58
|
+
|
|
59
|
+
const Header = () => {
|
|
60
|
+
return (
|
|
61
|
+
<View style={styles.wrapHeader}>
|
|
62
|
+
<TouchableOpacity
|
|
63
|
+
style={styles.btnMenu}
|
|
64
|
+
onPress={() => navigation.toggleDrawer()}
|
|
65
|
+
testID={TESTID.BURGER_MENU_ICON}
|
|
66
|
+
>
|
|
67
|
+
<Image source={Images.menu} style={styles.menu} />
|
|
68
|
+
</TouchableOpacity>
|
|
69
|
+
<Text style={styles.textHeader}>{t('developer_mode')}</Text>
|
|
70
|
+
</View>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<>
|
|
76
|
+
<Header />
|
|
77
|
+
<Tab.Navigator tabBar={(props) => <Tabbar {...props} />}>
|
|
78
|
+
{listTabName.map((item) => (
|
|
79
|
+
<Tab.Screen
|
|
80
|
+
name={item.name}
|
|
81
|
+
component={item.component}
|
|
82
|
+
options={{
|
|
83
|
+
tabBarLabel: item.tabBarLabel,
|
|
84
|
+
tabOffSetValue,
|
|
85
|
+
}}
|
|
86
|
+
/>
|
|
87
|
+
))}
|
|
88
|
+
</Tab.Navigator>
|
|
89
|
+
<Animated.View
|
|
90
|
+
// eslint-disable-next-line react-native/no-inline-styles
|
|
91
|
+
style={{
|
|
92
|
+
width: getWidth() - 4,
|
|
93
|
+
transform: [{ translateX: tabOffSetValue }],
|
|
94
|
+
height: 2,
|
|
95
|
+
backgroundColor: Colors.Primary,
|
|
96
|
+
position: 'absolute',
|
|
97
|
+
bottom: 70,
|
|
98
|
+
left: 8,
|
|
99
|
+
borderRadius: 1,
|
|
100
|
+
}}
|
|
101
|
+
/>
|
|
102
|
+
</>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const DevModeStack = () => {
|
|
107
|
+
return (
|
|
108
|
+
<Drawer.Navigator
|
|
109
|
+
backBehavior="none"
|
|
110
|
+
drawerContent={(props) => <DrawerContainer {...props} />}
|
|
111
|
+
drawerStyle={{ paddingTop: getStatusBarHeight() }}
|
|
112
|
+
>
|
|
113
|
+
<Drawer.Screen name={Routes.DrawerMain} component={MainDevMode} />
|
|
114
|
+
</Drawer.Navigator>
|
|
115
|
+
);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export default DevModeStack;
|
|
119
|
+
|
|
120
|
+
const styles = StyleSheet.create({
|
|
121
|
+
btnMenu: {
|
|
122
|
+
width: 40,
|
|
123
|
+
height: 40,
|
|
124
|
+
justifyContent: 'center',
|
|
125
|
+
alignItems: 'center',
|
|
126
|
+
marginLeft: 10,
|
|
127
|
+
},
|
|
128
|
+
wrapHeader: {
|
|
129
|
+
height: 100,
|
|
130
|
+
paddingTop: getStatusBarHeight(),
|
|
131
|
+
flexDirection: 'row',
|
|
132
|
+
alignItems: 'center',
|
|
133
|
+
backgroundColor: Colors.Gray2,
|
|
134
|
+
},
|
|
135
|
+
textHeader: {
|
|
136
|
+
fontSize: 20,
|
|
137
|
+
fontWeight: 'bold',
|
|
138
|
+
color: Colors.Gray9,
|
|
139
|
+
},
|
|
140
|
+
menu: {
|
|
141
|
+
width: 24,
|
|
142
|
+
height: 24,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
|
+
import { createStackNavigator } from '@react-navigation/stack';
|
|
3
|
+
|
|
4
|
+
import Routes from '../utils/Route';
|
|
5
|
+
import { screenOptions } from './utils';
|
|
6
|
+
import Smart from '../screens/Smart';
|
|
7
|
+
|
|
8
|
+
const Stack = createStackNavigator();
|
|
9
|
+
|
|
10
|
+
const SmartStack = memo(() => {
|
|
11
|
+
return (
|
|
12
|
+
<Stack.Navigator
|
|
13
|
+
screenOptions={{
|
|
14
|
+
...screenOptions,
|
|
15
|
+
headerShown: false,
|
|
16
|
+
}}
|
|
17
|
+
>
|
|
18
|
+
<Stack.Screen name={Routes.Smart} component={Smart} />
|
|
19
|
+
</Stack.Navigator>
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default SmartStack;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
|
+
import { createStackNavigator } from '@react-navigation/stack';
|
|
3
|
+
|
|
4
|
+
import Routes from '../utils/Route';
|
|
5
|
+
import { screenOptions } from './utils';
|
|
6
|
+
import Template from '../screens/Template';
|
|
7
|
+
|
|
8
|
+
const Stack = createStackNavigator();
|
|
9
|
+
|
|
10
|
+
const TemplateStack = memo(() => {
|
|
11
|
+
return (
|
|
12
|
+
<Stack.Navigator
|
|
13
|
+
screenOptions={{
|
|
14
|
+
...screenOptions,
|
|
15
|
+
headerShown: false,
|
|
16
|
+
}}
|
|
17
|
+
>
|
|
18
|
+
<Stack.Screen name={Routes.Template} component={Template} />
|
|
19
|
+
</Stack.Navigator>
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default TemplateStack;
|
|
@@ -93,7 +93,11 @@ export const UnitStack = memo((props) => {
|
|
|
93
93
|
if (!id) {
|
|
94
94
|
return;
|
|
95
95
|
}
|
|
96
|
-
const { success, data } = await axiosGet(
|
|
96
|
+
const { success, data } = await axiosGet(
|
|
97
|
+
API.UNIT.FAVOURITE_DEVICES(id),
|
|
98
|
+
{},
|
|
99
|
+
true
|
|
100
|
+
);
|
|
97
101
|
success && setAction(Action.SET_FAVORITE_DEVICES, data);
|
|
98
102
|
};
|
|
99
103
|
fetchFavoriteDevices();
|
|
@@ -102,7 +106,11 @@ export const UnitStack = memo((props) => {
|
|
|
102
106
|
|
|
103
107
|
useEffect(() => {
|
|
104
108
|
const fetchStarredScripts = async () => {
|
|
105
|
-
const { success, data } = await axiosGet(
|
|
109
|
+
const { success, data } = await axiosGet(
|
|
110
|
+
API.AUTOMATE.STARRED_SCRIPTS(),
|
|
111
|
+
{},
|
|
112
|
+
true
|
|
113
|
+
);
|
|
106
114
|
success && setAction(Action.SET_STARRED_SCRIPTS, data);
|
|
107
115
|
};
|
|
108
116
|
fetchStarredScripts();
|
|
@@ -4,7 +4,6 @@ import AllCamera from '..';
|
|
|
4
4
|
import { act, create } from 'react-test-renderer';
|
|
5
5
|
import { SCProvider } from '../../../context';
|
|
6
6
|
import { mockSCStore } from '../../../context/mockStore';
|
|
7
|
-
import { ModalFullVideo } from '../../../commons/Modal';
|
|
8
7
|
import Carousel from 'react-native-snap-carousel';
|
|
9
8
|
|
|
10
9
|
const arrCameras = [
|
|
@@ -90,13 +89,7 @@ describe('Test AllCamera screen', () => {
|
|
|
90
89
|
});
|
|
91
90
|
const instance = tree.root;
|
|
92
91
|
const TouchableOpacities = instance.findAllByType(TouchableOpacity);
|
|
93
|
-
expect(TouchableOpacities).toHaveLength(
|
|
94
|
-
const ModalFullVideos = instance.findAllByType(ModalFullVideo);
|
|
95
|
-
expect(ModalFullVideos).toHaveLength(1);
|
|
96
|
-
act(() => {
|
|
97
|
-
ModalFullVideos[0].props.onClose();
|
|
98
|
-
});
|
|
99
|
-
expect(mockSetState).toBeCalledWith(false);
|
|
92
|
+
expect(TouchableOpacities).toHaveLength(8);
|
|
100
93
|
const Carousels = instance.findAllByType(Carousel);
|
|
101
94
|
expect(Carousels).toHaveLength(1);
|
|
102
95
|
});
|
|
@@ -17,7 +17,6 @@ import { HeaderCustom } from '../../commons/Header';
|
|
|
17
17
|
import MediaPlayerDetail from '../../commons/MediaPlayerDetail';
|
|
18
18
|
import { Constants, normalize } from '../../configs/Constants';
|
|
19
19
|
import styles from './Styles/index';
|
|
20
|
-
import { ModalFullVideo } from '../../commons/Modal';
|
|
21
20
|
import Routes from '../../utils/Route';
|
|
22
21
|
|
|
23
22
|
const AllCamera = () => {
|
|
@@ -32,12 +31,10 @@ const AllCamera = () => {
|
|
|
32
31
|
const [activeCamera, setActiveCamera] = useState(data[0]);
|
|
33
32
|
const [currentPage, setCurrentPage] = useState(1);
|
|
34
33
|
const [isFullScreen, setIsFullScreen] = useState(false);
|
|
35
|
-
const [dataFullScreen, setDataFullScreen] = useState();
|
|
36
34
|
|
|
37
35
|
const handleFullScreen = useCallback(
|
|
38
36
|
(dataFullscreen) => {
|
|
39
37
|
setIsFullScreen(!isFullScreen);
|
|
40
|
-
setDataFullScreen(dataFullscreen);
|
|
41
38
|
},
|
|
42
39
|
[isFullScreen]
|
|
43
40
|
);
|
|
@@ -69,10 +66,6 @@ const AllCamera = () => {
|
|
|
69
66
|
[data]
|
|
70
67
|
);
|
|
71
68
|
|
|
72
|
-
const onClose = () => {
|
|
73
|
-
setIsFullScreen(false);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
69
|
const goToPlayBack = useCallback(
|
|
77
70
|
(item, itemThumbnail) => () => {
|
|
78
71
|
navigate(Routes.PlaybackCamera, { item, thumbnail: itemThumbnail });
|
|
@@ -249,12 +242,6 @@ const AllCamera = () => {
|
|
|
249
242
|
{renderAmount}
|
|
250
243
|
</View>
|
|
251
244
|
</View>
|
|
252
|
-
<ModalFullVideo
|
|
253
|
-
isVisible={isFullScreen}
|
|
254
|
-
data={dataFullScreen}
|
|
255
|
-
modalStyles={styles.modal}
|
|
256
|
-
onClose={onClose}
|
|
257
|
-
/>
|
|
258
245
|
</>
|
|
259
246
|
);
|
|
260
247
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react-hooks';
|
|
2
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
3
|
+
import { API } from '../../../../configs';
|
|
4
|
+
import api from '../../../../utils/Apis/axios';
|
|
5
|
+
import { useEmergencyButton } from '../useEmergencyButton';
|
|
6
|
+
|
|
7
|
+
const mockFetchDataDeviceDetail = jest.fn();
|
|
8
|
+
const mockAcquireLockShowing = jest.fn();
|
|
9
|
+
|
|
10
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
11
|
+
|
|
12
|
+
describe('Test useEmergencyButton', () => {
|
|
13
|
+
it('Test render', async () => {
|
|
14
|
+
const { result } = renderHook(() =>
|
|
15
|
+
useEmergencyButton(mockFetchDataDeviceDetail, mockAcquireLockShowing)
|
|
16
|
+
);
|
|
17
|
+
jest.useFakeTimers();
|
|
18
|
+
await result.current.onCancelConfirmAlert();
|
|
19
|
+
expect(result.current.showAlertConfirm).toBe(false);
|
|
20
|
+
jest.runAllTimers();
|
|
21
|
+
await result.current.onEmergencyButtonPress();
|
|
22
|
+
mock.onPost(API.EMERGENCY_BUTTON.SEND_ALERT()).reply(200);
|
|
23
|
+
await result.current.onSendNowAlert();
|
|
24
|
+
expect(result.current.showAlertConfirm).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('Test send alert fail', async () => {
|
|
28
|
+
mock.onPost(API.EMERGENCY_BUTTON.SEND_ALERT()).reply(400);
|
|
29
|
+
const { result } = renderHook(() =>
|
|
30
|
+
useEmergencyButton(mockFetchDataDeviceDetail, mockAcquireLockShowing)
|
|
31
|
+
);
|
|
32
|
+
await result.current.onSendNowAlert();
|
|
33
|
+
await result.current.onCloseAlertSent();
|
|
34
|
+
await result.current.onViewDetails();
|
|
35
|
+
expect(result.current.showAlertConfirm).toBe(false);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SafeAreaView } from 'react-native';
|
|
3
|
+
import renderer, { act } from 'react-test-renderer';
|
|
4
|
+
import { SCProvider } from '../../context';
|
|
5
|
+
import { mockSCStore } from '../../context/mockStore';
|
|
6
|
+
import Drawer from './index';
|
|
7
|
+
|
|
8
|
+
const wrapComponent = () => (
|
|
9
|
+
<SCProvider initState={mockSCStore({})}>
|
|
10
|
+
<Drawer navigation={jest.fn()} />
|
|
11
|
+
</SCProvider>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
describe('Drawer', () => {
|
|
15
|
+
let tree;
|
|
16
|
+
test('drawer snapshot', async () => {
|
|
17
|
+
await act(async () => {
|
|
18
|
+
tree = await renderer.create(wrapComponent());
|
|
19
|
+
});
|
|
20
|
+
const instance = tree.root;
|
|
21
|
+
const safeView = instance.findAllByType(SafeAreaView);
|
|
22
|
+
expect(safeView).toHaveLength(1);
|
|
23
|
+
});
|
|
24
|
+
});
|