@eohjsc/react-native-smart-city 0.3.27 → 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.
Files changed (67) hide show
  1. package/index.js +2 -0
  2. package/package.json +1 -1
  3. package/src/Images/Common/device_icon.png +0 -0
  4. package/src/Images/DevMode/gateway.png +0 -0
  5. package/src/Images/DevMode/gateway@2x.png +0 -0
  6. package/src/Images/DevMode/gateway@3x.png +0 -0
  7. package/src/Images/DevMode/menu.png +0 -0
  8. package/src/Images/DevMode/menu@2x.png +0 -0
  9. package/src/Images/DevMode/menu@3x.png +0 -0
  10. package/src/Images/DevMode/search.png +0 -0
  11. package/src/Images/DevMode/search@2x.png +0 -0
  12. package/src/Images/DevMode/search@3x.png +0 -0
  13. package/src/Images/DevMode/smart.png +0 -0
  14. package/src/Images/DevMode/smart@2x.png +0 -0
  15. package/src/Images/DevMode/smart@3x.png +0 -0
  16. package/src/Images/DevMode/template.png +0 -0
  17. package/src/Images/DevMode/template@2x.png +0 -0
  18. package/src/Images/DevMode/template@3x.png +0 -0
  19. package/src/commons/CameraDevice/index.js +1 -2
  20. package/src/commons/ConnectingProcess/DeviceItem/DeviceItem.js +20 -12
  21. package/src/commons/ConnectingProcess/DeviceItem/DeviceItemStyles.js +2 -0
  22. package/src/commons/ConnectingProcess/__test__/DeviceItem.test.js +1 -1
  23. package/src/commons/ConnectingProcess/index.js +11 -0
  24. package/src/commons/Dashboard/MyUnit/index.js +1 -1
  25. package/src/commons/DevMode/Label.js +10 -0
  26. package/src/commons/DevMode/Search.js +20 -0
  27. package/src/commons/DevMode/Styles/LabelStyles.js +8 -0
  28. package/src/commons/DevMode/Styles/SearchStyles.js +21 -0
  29. package/src/commons/DevMode/index.js +3 -0
  30. package/src/commons/Form/TextInput.js +4 -0
  31. package/src/commons/MediaPlayerDetail/index.js +0 -20
  32. package/src/commons/Modal/index.js +1 -2
  33. package/src/commons/Tabbar/Styles/indexStyles.js +51 -0
  34. package/src/commons/Tabbar/index.js +110 -0
  35. package/src/configs/Colors.js +4 -0
  36. package/src/configs/Images.js +6 -0
  37. package/src/navigations/GatewayStack.js +23 -0
  38. package/src/navigations/Main.js +144 -0
  39. package/src/navigations/SmartStack.js +23 -0
  40. package/src/navigations/TemplateStack.js +23 -0
  41. package/src/screens/AllCamera/__test__/index.test.js +1 -8
  42. package/src/screens/AllCamera/index.js +0 -13
  43. package/src/screens/Device/hooks/__test__/useEmergencyButton.test.js +37 -0
  44. package/src/screens/Drawer/Drawer.test.js +24 -0
  45. package/src/screens/Drawer/index.js +198 -0
  46. package/src/screens/Gateway/__test__/index.test.js +16 -0
  47. package/src/screens/Gateway/index.js +8 -0
  48. package/src/screens/Smart/__test__/index.test.js +16 -0
  49. package/src/screens/Smart/index.js +8 -0
  50. package/src/screens/SubUnit/AddSubUnit.js +1 -1
  51. package/src/screens/SubUnit/EditSubUnit.js +4 -1
  52. package/src/screens/Template/Styles/indexStyles.js +51 -0
  53. package/src/screens/Template/__test__/index.test.js +16 -0
  54. package/src/screens/Template/index.js +84 -0
  55. package/src/screens/Unit/Detail.js +5 -27
  56. package/src/screens/Unit/Station/__test__/index.test.js +41 -0
  57. package/src/screens/Unit/__test__/Detail.test.js +1 -5
  58. package/src/utils/Converter/__test__/timer.test.js +99 -0
  59. package/src/utils/Functions/Search.js +17 -0
  60. package/src/utils/Functions/ShortEmail.js +4 -0
  61. package/src/utils/Functions/__test__/Search.test.js +6 -0
  62. package/src/utils/Functions/__test__/ShortEmail.test.js +6 -0
  63. package/src/utils/I18n/translations/en.json +11 -1
  64. package/src/utils/I18n/translations/vi.json +11 -1
  65. package/src/utils/Route/index.js +6 -0
  66. package/src/commons/Modal/ModalFullVideo.js +0 -48
  67. package/src/commons/Modal/Styles/ModalFullVideoStyles.js +0 -26
package/index.js CHANGED
@@ -19,6 +19,7 @@ import MyUnit from './src/commons/Dashboard/MyUnit';
19
19
  import SharedUnit from './src/commons/Unit/SharedUnit';
20
20
  import { Action } from './src/context/actionType';
21
21
  import { withRemoteControl } from './src/hoc';
22
+ import DevModeStack from './src/navigations/Main';
22
23
 
23
24
  export {
24
25
  AddSubUnitStack,
@@ -44,4 +45,5 @@ export {
44
45
  SCWrapper,
45
46
  Action,
46
47
  withRemoteControl,
48
+ DevModeStack,
47
49
  };
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.27",
4
+ "version": "0.3.28",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -17,7 +17,7 @@ const { standardizeWidth, standardizeHeight } = standardizeCameraScreenSize(
17
17
  Device.screenWidth - 32
18
18
  );
19
19
 
20
- const CameraDevice = ({ station, handleFullScreen, goToPlayBack }) => {
20
+ const CameraDevice = ({ station, goToPlayBack }) => {
21
21
  const t = useTranslations();
22
22
  const { navigate } = useNavigation();
23
23
  const { setAction } = useContext(SCContext);
@@ -62,7 +62,6 @@ const CameraDevice = ({ station, handleFullScreen, goToPlayBack }) => {
62
62
  }}
63
63
  key={`camera-device-${device.id}`}
64
64
  cameraName={device.configuration.name}
65
- handleFullScreen={handleFullScreen}
66
65
  goToPlayBack={goToPlayBack(device, { uri: station?.background })}
67
66
  width={standardizeWidth}
68
67
  height={standardizeHeight}
@@ -3,18 +3,26 @@ import { View } from 'react-native';
3
3
  import styles from './DeviceItemStyles';
4
4
  import FImage from '../../FImage';
5
5
  import _TextInput from '../../Form/TextInput';
6
+ import Images from '../../../configs/Images';
6
7
 
7
- const DeviceItem = memo(({ icon, name, setNewName }) => {
8
- return (
9
- <View style={styles.container}>
10
- {!!icon && <FImage source={{ uri: icon }} style={styles.iconSensor} />}
11
- <_TextInput
12
- value={name}
13
- textInputStyle={styles.textItem}
14
- onChange={setNewName}
15
- />
16
- </View>
17
- );
18
- });
8
+ const DeviceItem = memo(
9
+ ({ icon, name, setNewName, handleSelectionChange, isSelection }) => {
10
+ return (
11
+ <View style={styles.container}>
12
+ <FImage
13
+ source={icon ? { uri: icon } : Images.deviceIcon}
14
+ style={styles.iconSensor}
15
+ />
16
+ <_TextInput
17
+ value={name}
18
+ textInputStyle={styles.textItem}
19
+ onChange={setNewName}
20
+ selection={isSelection && { start: 0, end: 0 }}
21
+ onSelectionChange={handleSelectionChange}
22
+ />
23
+ </View>
24
+ );
25
+ }
26
+ );
19
27
 
20
28
  export default DeviceItem;
@@ -20,6 +20,8 @@ export default StyleSheet.create({
20
20
  elevation: 6,
21
21
  paddingLeft: 30,
22
22
  paddingRight: 30,
23
+ display: 'flex',
24
+ alignItems: 'center',
23
25
  },
24
26
  iconSensor: {
25
27
  width: 32,
@@ -13,7 +13,7 @@ describe('Test DeviceItem button', () => {
13
13
  const instance = tree.root;
14
14
  const image = instance.findAllByType(FImage);
15
15
  const text = instance.findAllByType(_TextInput);
16
- expect(image).toHaveLength(0);
16
+ expect(image).toHaveLength(1);
17
17
  expect(text).toHaveLength(1);
18
18
  });
19
19
  });
@@ -20,6 +20,8 @@ const ConnectingSuccess = ({
20
20
  unit_name,
21
21
  newName,
22
22
  setNewName,
23
+ isSelection,
24
+ handleSelectionChange,
23
25
  }) => {
24
26
  const t = useTranslations();
25
27
  return (
@@ -37,6 +39,8 @@ const ConnectingSuccess = ({
37
39
  icon={sensor?.icon_kit}
38
40
  name={newName}
39
41
  setNewName={setNewName}
42
+ handleSelectionChange={handleSelectionChange}
43
+ isSelection={isSelection}
40
44
  />
41
45
  </View>
42
46
  );
@@ -61,6 +65,7 @@ const ConnectingProcess = ({ route }) => {
61
65
  const [sensor, setSensor] = useState(null);
62
66
  const user = useSCContextSelector((state) => state?.auth?.account?.user);
63
67
  const [newName, setNewName] = useState('');
68
+ const [isSelection, setIsSelection] = useState(true);
64
69
 
65
70
  const connectingDevice = useCallback(async () => {
66
71
  setIsLoading(true);
@@ -166,6 +171,10 @@ const ConnectingProcess = ({ route }) => {
166
171
  unit_id,
167
172
  ]);
168
173
 
174
+ const handleSelectionChange = useCallback(() => {
175
+ setIsSelection(false);
176
+ }, []);
177
+
169
178
  useEffect(() => {
170
179
  connectingDevice();
171
180
  }, [connectingDevice]);
@@ -185,6 +194,8 @@ const ConnectingProcess = ({ route }) => {
185
194
  unit_name={unit_name}
186
195
  newName={newName}
187
196
  setNewName={setNewName}
197
+ isSelection={isSelection}
198
+ handleSelectionChange={handleSelectionChange}
188
199
  />
189
200
  )}
190
201
  </View>
@@ -124,7 +124,7 @@ const MyUnit = () => {
124
124
  </View>
125
125
  );
126
126
  },
127
- [myUnits.length, goToDetail]
127
+ [myUnits, goToDetail]
128
128
  );
129
129
 
130
130
  return (
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { memo } from 'react';
3
+ import Text from '../Text';
4
+ import styles from './Styles/LabelStyles';
5
+
6
+ const Label = ({ name = '', style }) => {
7
+ return <Text style={[styles.label, style]}>{name}</Text>;
8
+ };
9
+
10
+ export default memo(Label);
@@ -0,0 +1,20 @@
1
+ import React, { memo } from 'react';
2
+ import { View, Image, TextInput } from 'react-native';
3
+ import { Images } from '../../configs';
4
+ import t from '../../hooks/Common/useTranslations';
5
+ import styles from './Styles/SearchStyles';
6
+
7
+ const Search = ({ onSearch }) => {
8
+ return (
9
+ <View style={styles.wrap}>
10
+ <Image source={Images.search} style={styles.icon} />
11
+ <TextInput
12
+ style={styles.textInput}
13
+ placeholder={t('what_are_you_looking_for')}
14
+ onChangeText={onSearch}
15
+ />
16
+ </View>
17
+ );
18
+ };
19
+
20
+ export default memo(Search);
@@ -0,0 +1,8 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ export default StyleSheet.create({
4
+ label: {
5
+ fontSize: 28,
6
+ fontWeight: 'bold',
7
+ },
8
+ });
@@ -0,0 +1,21 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { Colors } from '../../../configs';
3
+
4
+ export default StyleSheet.create({
5
+ wrap: {
6
+ borderRadius: 6,
7
+ borderWidth: 1,
8
+ borderColor: Colors.Neutral.Neutral3,
9
+ width: '100%',
10
+ flexDirection: 'row',
11
+ alignItems: 'center',
12
+ paddingHorizontal: 10,
13
+ marginVertical: 16,
14
+ },
15
+ icon: {},
16
+ textInput: {
17
+ flex: 1,
18
+ height: 36,
19
+ marginLeft: 5,
20
+ },
21
+ });
@@ -0,0 +1,3 @@
1
+ import Label from './Label';
2
+
3
+ export { Label };
@@ -27,6 +27,8 @@ const _TextInput = ({
27
27
  selectionColor,
28
28
  borderBottomOnly,
29
29
  testID,
30
+ selection,
31
+ onSelectionChange,
30
32
  }) => {
31
33
  const errorStyle = !!errorText && styles.errorWrap;
32
34
  return (
@@ -64,6 +66,8 @@ const _TextInput = ({
64
66
  multiline={multiline}
65
67
  selectionColor={selectionColor}
66
68
  {...(value ? { value } : {})}
69
+ selection={selection}
70
+ onSelectionChange={onSelectionChange}
67
71
  />
68
72
  {extraText && extraText}
69
73
  {!!errorText && <Text style={styles.errorText}>{errorText}</Text>}
@@ -7,7 +7,6 @@ import React, {
7
7
  useMemo,
8
8
  } from 'react';
9
9
  import {
10
- Image,
11
10
  View,
12
11
  StyleSheet,
13
12
  Text,
@@ -34,10 +33,8 @@ const MediaPlayerDetail = ({
34
33
  style,
35
34
  wrapStyles,
36
35
  amount,
37
- handleFullScreen,
38
36
  isPaused = true,
39
37
  goToPlayBack,
40
- isShowFullScreenIcon = false,
41
38
  width,
42
39
  height,
43
40
  }) => {
@@ -61,11 +58,6 @@ const MediaPlayerDetail = ({
61
58
  // eslint-disable-next-line react-hooks/exhaustive-deps
62
59
  }, [paused]);
63
60
 
64
- const onFullScreen = useCallback(() => {
65
- handleFullScreen && handleFullScreen({ uri, cameraName, thumbnail });
66
- // eslint-disable-next-line react-hooks/exhaustive-deps
67
- }, []);
68
-
69
61
  const getWidthHeight = useCallback(() => {
70
62
  let newWidth = 0,
71
63
  newHeight = 0;
@@ -207,18 +199,6 @@ const MediaPlayerDetail = ({
207
199
  {cameraName}
208
200
  </Text>
209
201
  )}
210
- {isShowFullScreenIcon && (
211
- <TouchableOpacity
212
- onPress={onFullScreen}
213
- style={[
214
- styles.iconFullScreen,
215
- (amount === 4 || amount === 6) && styles.iconFullScreen2,
216
- ]}
217
- testID={TESTID.SUB_UNIT_FULL_CAMERA}
218
- >
219
- <Image source={Images.fullscreen} />
220
- </TouchableOpacity>
221
- )}
222
202
  </View>
223
203
  );
224
204
  };
@@ -1,5 +1,4 @@
1
1
  import ModalCustom from './ModalCustom';
2
- import ModalFullVideo from './ModalFullVideo';
3
2
  import ModalBottom from './ModalBottom';
4
3
 
5
- export { ModalCustom, ModalFullVideo, ModalBottom };
4
+ export { ModalCustom, ModalBottom };
@@ -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);
@@ -133,4 +133,8 @@ export const Colors = {
133
133
  BlackTransparent16: 'rgba(0, 0, 0, 0.16)',
134
134
  WhiteTransparent8: 'rgba(255, 255, 255, 0.8)',
135
135
  BlueTransparent5: 'rgba(230, 247, 255, 0.5)',
136
+ Neutral: {
137
+ Neutral3: '#E6E6E6',
138
+ Neutral5: '#595959',
139
+ },
136
140
  };
@@ -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
  };
@@ -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;