@eohjsc/react-native-smart-city 0.3.2 → 0.3.5

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 (40) hide show
  1. package/package.json +3 -1
  2. package/react-native-smart-city.podspec +1 -1
  3. package/src/commons/ActionGroup/ColorPickerTemplate.js +36 -23
  4. package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +21 -6
  5. package/src/commons/ActionGroup/OnOffTemplate/OnOffButtonTemplate.js +8 -2
  6. package/src/commons/ActionGroup/SliderRangeTemplate.js +5 -1
  7. package/src/commons/ActionGroup/__test__/NumberUpDownTemplate.test.js +43 -3
  8. package/src/commons/ActionGroup/__test__/index.test.js +4 -7
  9. package/src/commons/ConnectingProcess/index.js +3 -0
  10. package/src/commons/Device/ItemDevice.js +4 -1
  11. package/src/commons/Device/WaterQualitySensor/QualityIndicatorsItem.js +7 -2
  12. package/src/commons/Form/CurrencyInput.js +15 -1
  13. package/src/commons/Form/TextInputPassword.js +1 -1
  14. package/src/commons/HeaderAni/index.js +6 -1
  15. package/src/commons/MediaPlayerDetail/index.js +11 -2
  16. package/src/commons/Sharing/MemberList.js +10 -2
  17. package/src/commons/Sharing/WrapHeaderScrollable.js +2 -0
  18. package/src/commons/SubUnit/__test__/ShortDetail.test.js +1 -1
  19. package/src/configs/Constants.js +19 -0
  20. package/src/configs/SCConfig.js +2 -0
  21. package/src/navigations/UnitStack.js +3 -20
  22. package/src/navigations/UnitStackStyles.js +21 -0
  23. package/src/screens/AddNewDevice/__test__/AddNewDevice.test.js +8 -1
  24. package/src/screens/AddNewDevice/__test__/ConnectingDevices.test.js +1 -1
  25. package/src/screens/Device/EditDevice/index.js +15 -13
  26. package/src/screens/SubUnit/AddSubUnit.js +23 -17
  27. package/src/screens/SubUnit/EditSubUnit.js +15 -13
  28. package/src/screens/SubUnit/__test__/AddSubUnit.test.js +9 -23
  29. package/src/screens/SyncLGDevice/__test__/AddLGDevice.test.js +8 -1
  30. package/src/screens/Unit/SelectAddress.js +7 -1
  31. package/src/screens/Unit/Station/index.js +3 -0
  32. package/src/screens/Unit/__test__/SelectAddress.test.js +80 -3
  33. package/src/screens/Unit/components/MyUnitDevice/index.js +4 -4
  34. package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +2 -2
  35. package/src/utils/Apis/axios.js +9 -1
  36. package/src/utils/I18n/translations/en.json +3 -1
  37. package/src/utils/I18n/translations/vi.json +3 -1
  38. package/src/utils/Setting/Location.js +30 -0
  39. package/src/utils/__test__/Utils.test.js +12 -0
  40. package/src/commons/ActionGroup/__test__/NumberUpDownTemplateWithNullConfigValue.test.js +0 -60
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.02",
4
+ "version": "0.3.05",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -146,6 +146,8 @@
146
146
  "react-hooks-global-state": "^1.0.1",
147
147
  "react-i18next": "^11.8.12",
148
148
  "react-native-alert-async": "^1.0.5",
149
+ "react-native-android-keyboard-adjust": "^1.2.0",
150
+ "react-native-android-location-enabler": "^1.2.2",
149
151
  "react-native-android-wifi": "^0.0.41",
150
152
  "react-native-appearance": "^0.3.4",
151
153
  "react-native-base64": "^0.1.0",
@@ -22,7 +22,7 @@ Pod::Spec.new do |s|
22
22
  s.requires_arc = true
23
23
 
24
24
  s.dependency "React"
25
- s.dependency "react-native-permissions"
25
+ s.dependency "RNPermissions"
26
26
  # ...
27
27
  # s.dependency "..."
28
28
  end
@@ -1,38 +1,51 @@
1
- import React, { memo, useCallback, useState, useEffect, useMemo } from 'react';
1
+ import React, { memo, useState, useEffect } from 'react';
2
2
  import { View } from 'react-native';
3
3
  import styles from './ColorPickerTemplateStyles';
4
4
  import ColorPicker from 'react-native-wheel-color-picker';
5
5
  import { watchMultiConfigs } from '../../iot/Monitor';
6
6
  import { useConfigGlobalState } from '../../iot/states';
7
7
 
8
+ let isFirstTime = true;
9
+
10
+ const WheelColorPicker = ({ valueColor, onChangeColor }) => {
11
+ return (
12
+ <ColorPicker
13
+ style={styles.colorPicker}
14
+ sliderHidden={true}
15
+ swatches={false}
16
+ color={valueColor}
17
+ onColorChangeComplete={onChangeColor}
18
+ thumbSize={16}
19
+ />
20
+ );
21
+ };
22
+
8
23
  const ColorPickerTemplate = memo(({ actionGroup, doAction, sensor }) => {
9
24
  const { configuration } = actionGroup;
10
25
  const [valueColorComplete, setValueColorComplete] = useState('');
11
- const [isFirstColor, setIsFirstColor] = useState(false);
12
26
  const [configValues] = useConfigGlobalState('configValues');
13
27
 
14
- const onChangeColor = useCallback(
15
- (color) => {
16
- if (!isFirstColor) {
17
- setIsFirstColor(true);
18
- return;
19
- }
28
+ const onChangeColor = (color) => {
29
+ const to = setTimeout(() => {
30
+ isFirstTime = false;
31
+ clearTimeout(to);
32
+ }, 1000);
33
+
34
+ !isFirstTime &&
20
35
  doAction(
21
36
  configuration?.action_color_data,
22
37
  JSON.stringify({ value: color })
23
38
  );
24
- },
25
- [configuration?.action_color_data, doAction, isFirstColor]
26
- );
27
- const valueColor = useMemo(() => {
28
- return valueColorComplete || '';
29
- }, [valueColorComplete]);
39
+ };
30
40
 
31
41
  useEffect(() => {
32
42
  const { config } = configuration;
33
43
  const configValue = configValues[config];
34
- setValueColorComplete(configValue);
35
- }, [configuration.config, configValues, configuration]);
44
+ if (configValue && isFirstTime) {
45
+ setValueColorComplete(`#${configValue?.toString(16)}`);
46
+ }
47
+ // eslint-disable-next-line react-hooks/exhaustive-deps
48
+ }, [configValues]);
36
49
 
37
50
  useEffect(() => {
38
51
  if (sensor?.is_managed_by_backend && sensor.device_type !== 'GOOGLE_HOME') {
@@ -40,15 +53,15 @@ const ColorPickerTemplate = memo(({ actionGroup, doAction, sensor }) => {
40
53
  }
41
54
  }, [sensor, configuration.config]);
42
55
 
56
+ useEffect(() => {
57
+ return () => (isFirstTime = true);
58
+ }, []);
59
+
43
60
  return (
44
61
  <View style={styles.viewPickColor}>
45
- <ColorPicker
46
- style={styles.colorPicker}
47
- sliderHidden={true}
48
- swatches={false}
49
- color={valueColor}
50
- onColorChangeComplete={onChangeColor}
51
- thumbSize={16}
62
+ <WheelColorPicker
63
+ valueColor={valueColorComplete}
64
+ onChangeColor={onChangeColor}
52
65
  />
53
66
  </View>
54
67
  );
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useEffect, useState } from 'react';
2
- import { View, TouchableOpacity } from 'react-native';
2
+ import { View, TouchableOpacity, ActivityIndicator } from 'react-native';
3
3
  import { IconOutline } from '@ant-design/icons-react-native';
4
4
  import { Colors } from '../../configs';
5
5
 
@@ -7,7 +7,7 @@ import Text from '../Text';
7
7
  import { useConfigGlobalState } from '../../iot/states';
8
8
  import styles from './NumberUpDownActionTemplateStyle';
9
9
  import { watchMultiConfigs } from '../../iot/Monitor';
10
- import { TESTID } from '../../configs/Constants';
10
+ import { DEVICE_TYPE, TESTID } from '../../configs/Constants';
11
11
 
12
12
  const NumberUpDownActionTemplate = ({ actionGroup, doAction, sensor }) => {
13
13
  const { configuration, title } = actionGroup;
@@ -25,6 +25,19 @@ const NumberUpDownActionTemplate = ({ actionGroup, doAction, sensor }) => {
25
25
  const [value, setValue] = useState();
26
26
  const valueDefault = 28;
27
27
 
28
+ useEffect(() => {
29
+ if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
30
+ return;
31
+ }
32
+ if (
33
+ !!config &&
34
+ sensor?.is_managed_by_backend &&
35
+ sensor.device_type !== 'GOOGLE_HOME'
36
+ ) {
37
+ watchMultiConfigs([config]);
38
+ }
39
+ }, [sensor, config]);
40
+
28
41
  useEffect(() => {
29
42
  if (!config) {
30
43
  setValue(valueDefault);
@@ -34,11 +47,9 @@ const NumberUpDownActionTemplate = ({ actionGroup, doAction, sensor }) => {
34
47
  const configValue = configValues[config];
35
48
  if (configValue !== null && configValue !== undefined) {
36
49
  setValue(configValue);
37
- } else {
38
- setValue(valueDefault);
39
50
  }
40
51
  // eslint-disable-next-line react-hooks/exhaustive-deps
41
- }, []);
52
+ }, [JSON.stringify(configValues)]);
42
53
 
43
54
  const doActionAndWatchConfig = useCallback(
44
55
  async (actionData, actionValue, actionName) => {
@@ -113,7 +124,11 @@ const NumberUpDownActionTemplate = ({ actionGroup, doAction, sensor }) => {
113
124
  </TouchableOpacity>
114
125
 
115
126
  <Text testID={'abcd'} type="H2">
116
- {text_format.replace('{number}', value)}
127
+ {value !== undefined ? (
128
+ text_format.replace('{number}', value)
129
+ ) : (
130
+ <ActivityIndicator />
131
+ )}
117
132
  </Text>
118
133
 
119
134
  <TouchableOpacity
@@ -5,15 +5,20 @@ import React, { memo } from 'react';
5
5
  import { TouchableOpacity, View } from 'react-native';
6
6
  import { Colors } from '../../../configs';
7
7
  import styles from './OnOffButtonTemplateStyle';
8
+ import { TESTID } from '../../../configs/Constants';
8
9
 
9
10
  const OnOffButtonTemplate = memo(
10
11
  ({ isOn, triggerAction, actionGroup, isLight = false }) => {
11
- const { configuration } = actionGroup;
12
+ const { configuration, id } = actionGroup;
12
13
 
13
14
  return (
14
15
  <>
15
16
  <View style={styles.barrierControlContainer}>
16
- <TouchableOpacity style={styles.bigCircle} onPress={triggerAction}>
17
+ <TouchableOpacity
18
+ style={styles.bigCircle}
19
+ onPress={triggerAction}
20
+ testID={`${TESTID.ON_OFF_BUTTON}-${id}`}
21
+ >
17
22
  <View style={styles.smallCircle}>
18
23
  <Icon
19
24
  name={isOn ? configuration.icon_on : configuration.icon_off}
@@ -25,6 +30,7 @@ const OnOffButtonTemplate = memo(
25
30
  styles.textBig,
26
31
  { color: isOn ? Colors.Gray8 : Colors.Gray6 },
27
32
  ]}
33
+ testID={`${TESTID.SENSOR_STATUS}-${id}`}
28
34
  >
29
35
  {isOn ? configuration.text_on : configuration.text_off}
30
36
  </Text>
@@ -33,7 +33,11 @@ const SliderRangeTemplate = memo(({ actionGroup, doAction, sensor }) => {
33
33
  useEffect(() => {
34
34
  const { config } = configuration;
35
35
  const configValue = configValues[config];
36
- setValueBrightness(configValue);
36
+ let valueTemp = configValue;
37
+ if (configValue > 0) {
38
+ valueTemp = Math.round((configValue / 254) * 100);
39
+ }
40
+ setValueBrightness(valueTemp);
37
41
  }, [configuration.config, configValues, configuration]);
38
42
 
39
43
  useEffect(() => {
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
- import { TouchableOpacity } from 'react-native';
2
+ import { ActivityIndicator, TouchableOpacity } from 'react-native';
3
3
  import { act, create } from 'react-test-renderer';
4
4
  import Text from '../../../commons/Text';
5
- import { TESTID } from '../../../configs/Constants';
5
+ import { DEVICE_TYPE, TESTID } from '../../../configs/Constants';
6
6
  import { watchMultiConfigs } from '../../../iot/Monitor';
7
7
  import NumberUpDownActionTemplate from '../NumberUpDownActionTemplate';
8
8
 
@@ -48,7 +48,10 @@ describe('Test NumberUpDownActionTemplate', () => {
48
48
  <NumberUpDownActionTemplate
49
49
  actionGroup={actionGroup}
50
50
  doAction={mockDoAction}
51
- sensor={{ is_managed_by_backend: true }}
51
+ sensor={{
52
+ is_managed_by_backend: true,
53
+ device_type: DEVICE_TYPE.LG_THINQ,
54
+ }}
52
55
  />
53
56
  );
54
57
  });
@@ -288,4 +291,41 @@ describe('Test NumberUpDownActionTemplate', () => {
288
291
  const text = instance.findByType(Text);
289
292
  expect(text.props.children).toEqual('25 *C');
290
293
  });
294
+ test('render template have title', async () => {
295
+ const mockDoAction = jest.fn();
296
+ actionGroup.title = 'title';
297
+ await act(async () => {
298
+ wrapper = await create(
299
+ <NumberUpDownActionTemplate
300
+ actionGroup={actionGroup}
301
+ doAction={mockDoAction}
302
+ sensor={{
303
+ is_managed_by_backend: true,
304
+ device_type: DEVICE_TYPE.LG_THINQ,
305
+ }}
306
+ />
307
+ );
308
+ });
309
+ const instance = wrapper.root;
310
+ const text = instance.findAllByType(Text);
311
+ expect(text).toHaveLength(2);
312
+ });
313
+ test('render template watch config not exits', async () => {
314
+ const mockDoAction = jest.fn();
315
+ actionGroup.configuration.config = 100;
316
+ await act(async () => {
317
+ wrapper = await create(
318
+ <NumberUpDownActionTemplate
319
+ actionGroup={actionGroup}
320
+ doAction={mockDoAction}
321
+ sensor={{
322
+ is_managed_by_backend: true,
323
+ }}
324
+ />
325
+ );
326
+ });
327
+ const instance = wrapper.root;
328
+ const text = instance.findAllByType(ActivityIndicator);
329
+ expect(text).toHaveLength(1);
330
+ });
291
331
  });
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { TouchableOpacity, Switch } from 'react-native';
2
+ import { TouchableOpacity, Switch, ActivityIndicator } from 'react-native';
3
3
  import renderer, { act } from 'react-test-renderer';
4
4
  import DateTimePickerModal from 'react-native-modal-datetime-picker';
5
5
  import moment from 'moment';
@@ -344,7 +344,7 @@ describe('Test ActionGroup', () => {
344
344
  expect(mockDoAction).toHaveBeenCalledTimes(1);
345
345
  });
346
346
 
347
- test('render ActionGroup NumberUpDownActionTemplate', async () => {
347
+ test('render ActionGroup NumberUpDownActionTemplate watch config value null', async () => {
348
348
  const mockDoAction = jest.fn();
349
349
  const actionGroup = {
350
350
  template: 'NumberUpDownActionTemplate',
@@ -362,11 +362,8 @@ describe('Test ActionGroup', () => {
362
362
  );
363
363
  });
364
364
  const instance = wrapper.root;
365
- const text = instance.findAllByType(Text);
366
- expect(text[0].props.children).toEqual('28 *C');
367
-
368
- const touchs = instance.findAllByType(TouchableOpacity);
369
- expect(touchs).toHaveLength(2);
365
+ const activity = instance.findAllByType(ActivityIndicator);
366
+ expect(activity.length).toEqual(1);
370
367
  });
371
368
 
372
369
  test('render ActionGroup StatesGridActionTemplate', async () => {
@@ -45,6 +45,7 @@ const ConnectingProcess = ({ route }) => {
45
45
  );
46
46
  if (success) {
47
47
  setSensor(data);
48
+ setNewName(data?.name);
48
49
  } else {
49
50
  ToastBottomHelper.error(JSON.stringify(data));
50
51
  goBack();
@@ -64,6 +65,7 @@ const ConnectingProcess = ({ route }) => {
64
65
  });
65
66
  if (success) {
66
67
  setSensor(data);
68
+ setNewName(data?.name);
67
69
  } else {
68
70
  ToastBottomHelper.error(JSON.stringify(data));
69
71
  goBack();
@@ -80,6 +82,7 @@ const ConnectingProcess = ({ route }) => {
80
82
  );
81
83
  if (success) {
82
84
  setSensor({ name: gateway?.model });
85
+ setNewName(gateway?.model);
83
86
  } else {
84
87
  ToastBottomHelper.error(JSON.stringify(data));
85
88
  goBack();
@@ -72,7 +72,10 @@ const ItemDevice = memo(
72
72
  const textConnected = isConnected ? t('connected') : t('disconnected');
73
73
 
74
74
  return (
75
- <TouchableWithoutFeedback onPress={goToSensorDisplay}>
75
+ <TouchableWithoutFeedback
76
+ onPress={goToSensorDisplay}
77
+ testID={`${TESTID.SENSOR_NAME}-${sensor?.id}`}
78
+ >
76
79
  <View
77
80
  style={[styles.container, wrapStyle, { borderColor }]}
78
81
  testID={TESTID.SUB_UNIT_DEVICES}
@@ -37,7 +37,7 @@ const QualityIndicatorItem = memo(
37
37
  >
38
38
  <IconOutline
39
39
  name={'info-circle'}
40
- size={16}
40
+ size={18}
41
41
  color={Colors.Gray8}
42
42
  />
43
43
  </TouchableOpacity>
@@ -92,6 +92,11 @@ const styles = StyleSheet.create({
92
92
  marginTop: 8,
93
93
  },
94
94
  iconInfo: {
95
- top: 10,
95
+ width: 40,
96
+ height: 40,
97
+ justifyContent: 'center',
98
+ alignItems: 'center',
99
+ marginRight: -10,
100
+ marginTop: -2,
96
101
  },
97
102
  });
@@ -1,4 +1,10 @@
1
- import React, { useState, useRef, useCallback, useMemo } from 'react';
1
+ import React, {
2
+ useState,
3
+ useRef,
4
+ useCallback,
5
+ useMemo,
6
+ useEffect,
7
+ } from 'react';
2
8
  import {
3
9
  View,
4
10
  TextInput,
@@ -6,6 +12,7 @@ import {
6
12
  TouchableWithoutFeedback,
7
13
  Platform,
8
14
  } from 'react-native';
15
+ import AndroidKeyboardAdjust from 'react-native-android-keyboard-adjust';
9
16
  import Text from '../Text';
10
17
  import { Colors } from '../../configs';
11
18
 
@@ -125,6 +132,13 @@ const CurrencyInput = ({
125
132
  return textInputValue.toString().length < 2 ? -12 : 0;
126
133
  }, [textInputValue]);
127
134
 
135
+ useEffect(() => {
136
+ const isAndroid = Platform.OS === 'android';
137
+ isAndroid && AndroidKeyboardAdjust.setAdjustResize();
138
+
139
+ return () => isAndroid && AndroidKeyboardAdjust.setAdjustPan();
140
+ }, []);
141
+
128
142
  return (
129
143
  <TouchableWithoutFeedback onPress={focusInput}>
130
144
  <View style={styles.wrap}>
@@ -90,7 +90,7 @@ const styles = StyleSheet.create({
90
90
  borderRadius: 2,
91
91
  paddingTop: 12,
92
92
  paddingBottom: 12,
93
- paddingHorizontal: 20,
93
+ paddingRight: 20,
94
94
  backgroundColor: Colors.White,
95
95
  // ...Theme.shadow,
96
96
  shadowColor: Colors.Gray13,
@@ -6,6 +6,7 @@ import { getStatusBarHeight } from 'react-native-iphone-x-helper';
6
6
 
7
7
  import Text from '../../commons/Text';
8
8
  import { Colors, Constants } from '../../configs';
9
+ import { TESTID } from '../../configs/Constants';
9
10
 
10
11
  const screenHeight = Constants.height;
11
12
  const default_height = 44;
@@ -89,7 +90,11 @@ const HeaderAni = memo(
89
90
  },
90
91
  ]}
91
92
  >
92
- <TouchableOpacity style={styles.btnBack} onPress={onPressLeft}>
93
+ <TouchableOpacity
94
+ style={styles.btnBack}
95
+ onPress={onPressLeft}
96
+ testID={TESTID.ICON_BACK}
97
+ >
93
98
  <Icon name={'left'} size={27} color={Colors.Gray9} />
94
99
  </TouchableOpacity>
95
100
  <View styles={styles.wrapRightComponent}>{rightComponent}</View>
@@ -6,7 +6,14 @@ import React, {
6
6
  useContext,
7
7
  useMemo,
8
8
  } from 'react';
9
- import { Image, View, StyleSheet, Text, TouchableOpacity } from 'react-native';
9
+ import {
10
+ Image,
11
+ View,
12
+ StyleSheet,
13
+ Text,
14
+ TouchableOpacity,
15
+ Platform,
16
+ } from 'react-native';
10
17
  import { VLCPlayer } from 'react-native-vlc-media-player';
11
18
  import { useTranslations } from '../../hooks/Common/useTranslations';
12
19
 
@@ -68,7 +75,9 @@ const MediaPlayerDetail = ({
68
75
  newHeight = 224;
69
76
  break;
70
77
  case 4:
71
- newWidth = Constants.width / 1.5;
78
+ newWidth =
79
+ Constants.width /
80
+ (Platform.OS === 'ios' && Constants.width < 400 ? 1.5 : 2);
72
81
  newHeight = 112;
73
82
  break;
74
83
  case 6:
@@ -1,7 +1,7 @@
1
1
  import React, { memo } from 'react';
2
2
  import { View, StyleSheet } from 'react-native';
3
3
  import { useTranslations } from '../../hooks/Common/useTranslations';
4
- import { Colors } from '../../configs';
4
+ import { Colors, Constants } from '../../configs';
5
5
  import Text from '../../commons/Text';
6
6
  import RowMember from './RowMember';
7
7
 
@@ -26,7 +26,9 @@ const MemberList = ({
26
26
  />
27
27
  ))}
28
28
  {!dataMember.length && (
29
- <Text style={styles.textCenter}>{t('no_member')}</Text>
29
+ <View style={styles.viewEmpty}>
30
+ <Text style={styles.textCenter}>{t('no_member')}</Text>
31
+ </View>
30
32
  )}
31
33
  </View>
32
34
  );
@@ -37,4 +39,10 @@ const styles = StyleSheet.create({
37
39
  box: {
38
40
  backgroundColor: Colors.White,
39
41
  },
42
+ viewEmpty: {
43
+ justifyContent: 'center',
44
+ alignItems: 'center',
45
+ height: Constants.height - 200,
46
+ backgroundColor: Colors.White,
47
+ },
40
48
  });
@@ -13,6 +13,7 @@ import { isIphoneX } from 'react-native-iphone-x-helper';
13
13
  import { Colors, Theme } from '../../configs';
14
14
  import HeaderAni, { heightHeader } from '../../commons/HeaderAni';
15
15
  import Text from '../../commons/Text';
16
+ import { TESTID } from '../../configs/Constants';
16
17
 
17
18
  const WrapHeaderScrollable = ({
18
19
  children,
@@ -59,6 +60,7 @@ const WrapHeaderScrollable = ({
59
60
  onLeft={onGoBack}
60
61
  />
61
62
  <Animated.ScrollView
63
+ testID={TESTID.ANIMATED_SCROLL}
62
64
  scrollEventThrottle={16}
63
65
  onScroll={Animated.event(
64
66
  [{ nativeEvent: { contentOffset: { y: animatedScrollYValue } } }],
@@ -151,7 +151,7 @@ describe('test ShortDetail Subunit', () => {
151
151
  (item) =>
152
152
  item.props.testID === TESTID.SUB_UNIT_DEVICES && item.type === View
153
153
  );
154
- expect(itemDevice.length).toBe(1);
154
+ expect(itemDevice.length).toBe(0);
155
155
  });
156
156
 
157
157
  test('render ShortDetail add new device', async () => {
@@ -288,6 +288,8 @@ export const TESTID = {
288
288
  SUB_UNIT_TEXT_DROPDOWN: 'SUB_UNIT_TEXT_DROPDOWN',
289
289
  SUB_UNIT_GO_DETAIL: 'SUB_UNIT_GO_DETAIL',
290
290
  VIEW_SUB_UNIT_AUTOMATE: 'VIEW_SUB_UNIT_AUTOMATE',
291
+ SUB_UNIT_NAME: 'SUB_UNIT_NAME',
292
+ ANIMATED_SCROLL: 'ANIMATED_SCROLL',
291
293
  ADD_SUB_UNIT: 'ADD_SUB_UNIT',
292
294
 
293
295
  // NavBar
@@ -392,6 +394,7 @@ export const TESTID = {
392
394
  ITEM_TEXT_ERROR: 'ITEM_TEXT_ERROR',
393
395
  SEARCH_BAR_INPUT: 'SEARCH_BAR_INPUT',
394
396
  GO_DETAIL: 'GO_DETAIL',
397
+ NAV_LIST: 'NAV_LIST',
395
398
 
396
399
  // Automate
397
400
  AUTOMATE_SCRIPT_ACTION: 'AUTOMATE_SCRIPT_ACTION',
@@ -447,8 +450,13 @@ export const TESTID = {
447
450
  ITEM_QUICK_ACTION_PRESS: 'ITEM_QUICK_ACTION_PRESS',
448
451
  TIME_COUNT_DOWN_TEXT: 'TIME_COUNT_DOWN_TEXT',
449
452
  ACTION_ITEM: 'ACTION_ITEM',
453
+
450
454
  // Sensor Item
451
455
  TEXT_SENSOR_ITEM: 'TEXT_SENSOR_ITEM',
456
+ SENSOR_NAME: 'SENSOR_NAME',
457
+ ON_OFF_BUTTON: 'ON_OFF_BUTTON',
458
+ SENSOR_STATUS: 'SENSOR_STATUS',
459
+ ICON_BACK: 'ICON_BACK',
452
460
 
453
461
  // DeviceInfo
454
462
  DEVICE_INFO_BATTERY: 'DEVICE_INFO_BATTERY',
@@ -564,6 +572,7 @@ export const TESTID = {
564
572
  ICON_ADD_STAR_SHARED_UNIT: 'ICON_ADD_STAR_SHARED_UNIT',
565
573
  TOUCH_SHARED_UNIT: 'TOUCH_SHARED_UNIT',
566
574
  SHARED_UNIT_OWN_BY: 'SHARED_UNIT_OWN_BY',
575
+ ICON_UNIT: 'ICON_UNIT',
567
576
 
568
577
  // Select subunit
569
578
 
@@ -809,3 +818,13 @@ export const SENSOR_TYPE = {
809
818
  SOS: 'sos',
810
819
  FILTER_WATER: 'filter_water',
811
820
  };
821
+
822
+ export const PROBLEM_CODE = {
823
+ CLIENT_ERROR: 'CLIENT_ERROR',
824
+ SERVER_ERROR: 'SERVER_ERROR',
825
+ TIMEOUT_ERROR: 'TIMEOUT_ERROR',
826
+ CONNECTION_ERROR: 'CONNECTION_ERROR',
827
+ NETWORK_ERROR: 'NETWORK_ERROR',
828
+ UNKNOWN_ERROR: 'UNKNOWN_ERROR',
829
+ CANCEL_ERROR: 'CANCEL_ERROR',
830
+ };
@@ -107,11 +107,13 @@ export class SCConfig {
107
107
  static VCONNEX_REDIRECT_URI_APP = SCDefaultConfig.VCONNEX_REDIRECT_URI_APP;
108
108
  static pusherAppKey = SCDefaultConfig.pusherAppKey;
109
109
  static pusherAppCluste = SCDefaultConfig.pusherAppCluster;
110
+ static language = 'en';
110
111
  }
111
112
 
112
113
  export const initSCConfig = (config) => {
113
114
  api.setBaseURL(config.apiRoot ?? SCDefaultConfig.apiRoot);
114
115
  LocaleConfig.defaultLocale = config.language;
116
+ SCConfig.language = config.language ?? SCConfig.language;
115
117
  SCConfig.apiRoot = config.apiRoot ?? SCDefaultConfig.apiRoot;
116
118
  SCConfig.GOOGLE_MAP_API_KEY =
117
119
  config.GOOGLE_MAP_API_KEY ?? SCDefaultConfig.GOOGLE_MAP_API_KEY;
@@ -1,5 +1,5 @@
1
1
  import React, { memo, useContext, useEffect } from 'react';
2
- import { View, StyleSheet } from 'react-native';
2
+ import { View } from 'react-native';
3
3
  import { IconOutline } from '@ant-design/icons-react-native';
4
4
  import { createStackNavigator } from '@react-navigation/stack';
5
5
  import { BleManager } from 'react-native-ble-plx';
@@ -52,10 +52,10 @@ import ConfirmUnitDeletion from '../screens/ConfirmUnitDeletion';
52
52
  import InfoMemberUnit from '../screens/Sharing/InfoMemberUnit';
53
53
  import EnterPassword from '../screens/EnterPassword';
54
54
  import { HanetCameraStack } from './HanetCameraStack';
55
-
56
55
  import { axiosGet } from '../utils/Apis/axios';
57
56
  import { API } from '../configs';
58
57
  import SideMenuDetail from '../screens/SideMenuDetail';
58
+ import { styles } from './UnitStackStyles';
59
59
 
60
60
  const Stack = createStackNavigator();
61
61
 
@@ -173,12 +173,9 @@ export const UnitStack = memo((props) => {
173
173
  component={ChooseLocation}
174
174
  options={{
175
175
  headerShown: true,
176
- headerTitleStyle: {
177
- ...styles.headerLocation,
178
- },
179
176
  headerTitle: () => (
180
177
  <View style={styles.headerLocation}>
181
- <Text type="H3" color={Colors.Gray9} bold>
178
+ <Text color={Colors.Gray9} style={styles.headerTitle} bold>
182
179
  {t('choose_on_map')}
183
180
  </Text>
184
181
 
@@ -406,17 +403,3 @@ export const UnitStack = memo((props) => {
406
403
  </Stack.Navigator>
407
404
  );
408
405
  });
409
-
410
- const styles = StyleSheet.create({
411
- icLeft: {
412
- marginLeft: Device.isIOS ? 8 : 0,
413
- },
414
- headerLocation: {
415
- alignItems: 'center',
416
- justifyContent: 'center',
417
- },
418
- headerContent: {
419
- textAlign: 'center',
420
- paddingBottom: 8,
421
- },
422
- });
@@ -0,0 +1,21 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { Device } from '../configs';
3
+
4
+ export const styles = StyleSheet.create({
5
+ icLeft: {
6
+ marginLeft: Device.isIOS ? 8 : 0,
7
+ },
8
+ headerLocation: {
9
+ alignItems: 'center',
10
+ justifyContent: 'center',
11
+ width: 290,
12
+ },
13
+ headerTitle: {
14
+ fontSize: 20,
15
+ lineHeight: 28,
16
+ },
17
+ headerContent: {
18
+ textAlign: 'center',
19
+ paddingBottom: 4,
20
+ },
21
+ });