@eohjsc/react-native-smart-city 0.4.95 → 0.4.96

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 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.4.95",
4
+ "version": "0.4.96",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -196,13 +196,13 @@
196
196
  "react-native-super-grid": "^4.0.3",
197
197
  "react-native-svg": "^12.1.0",
198
198
  "react-native-toast-message": "^2.1.1",
199
- "react-native-udp": "^4.1.7",
199
+ "react-native-udp": "4.1.3",
200
200
  "react-native-version-check": "^3.4.2",
201
201
  "react-native-vlc-media-player": "^1.0.41",
202
202
  "react-native-webview": "11.22.7",
203
203
  "react-native-wheel-color-picker": "^1.2.0",
204
204
  "react-native-wheel-scrollview-picker": "^1.2.2",
205
- "react-native-wifi-reborn": "^4.11.0",
205
+ "react-native-wifi-reborn": "4.5.0",
206
206
  "react-navigation": "^2.2.0",
207
207
  "string-format": "^2.0.0",
208
208
  "sync-directory": "^5.1.7",
@@ -91,10 +91,7 @@ const SliderRangeTemplate = memo(
91
91
  <View
92
92
  style={(isWidgetOrder && styles.wrapOrderItem) || styles.viewBrightness}
93
93
  >
94
- <Text type="H4" style={styles.LeftTextBrightness}>
95
- {item?.title || item?.label || t('brightness')}
96
- </Text>
97
-
94
+ <Text type="H4">{item?.title || item?.label || t('brightness')}</Text>
98
95
  <View style={styles.wrap}>
99
96
  <Slider
100
97
  step={1}
@@ -0,0 +1,68 @@
1
+ import React, { useCallback, useState } from 'react';
2
+ import { View, TouchableOpacity } from 'react-native';
3
+ import { IconOutline } from '@ant-design/icons-react-native';
4
+ import Text from '../../commons/Text';
5
+ import { AlertAction } from '../../commons';
6
+ import { useDropdownAction } from './hooks/useDropdownAction';
7
+ import { useConfigGlobalState } from '../../iot/states';
8
+ import styles from './TextBoxTemplateStyle';
9
+
10
+ import { useTranslations } from '../../hooks/Common/useTranslations';
11
+ import _TextInput from '../Form/TextInput';
12
+ import AccessibilityLabel from '../../configs/AccessibilityLabel';
13
+
14
+ const TextBoxTemplate = ({ item, doAction, isWidgetOrder }) => {
15
+ const t = useTranslations();
16
+ const { label, configuration } = item;
17
+ const { action_data, config } = configuration;
18
+ const [configValues] = useConfigGlobalState('configValues');
19
+ const [value, setValue] = useState();
20
+
21
+ const { stateAlert, hideAlertAction, onShowAlert } = useDropdownAction();
22
+
23
+ const onDone = useCallback(() => {
24
+ doAction(action_data, JSON.stringify({ value: value }));
25
+ hideAlertAction();
26
+ }, [doAction, action_data, value, hideAlertAction]);
27
+
28
+ const onInputChange = (value) => {
29
+ setValue(value);
30
+ };
31
+ return (
32
+ <View style={(isWidgetOrder && styles.wrapOrderItem) || styles.wrap}>
33
+ <View>
34
+ <Text type="H4">{label}</Text>
35
+ </View>
36
+
37
+ <View style={styles.iconAndText}>
38
+ <Text type="H4">{configValues[config.id]?.value}</Text>
39
+ <TouchableOpacity
40
+ style={styles.iconAndTextOption}
41
+ onPress={onShowAlert}
42
+ accessibilityLabel={AccessibilityLabel.TEXT_BOX_BUTTON_EDIT}
43
+ >
44
+ <IconOutline name="edit" size={20} />
45
+ </TouchableOpacity>
46
+ <AlertAction
47
+ visible={stateAlert.visible}
48
+ hideModal={hideAlertAction}
49
+ title={t('change')}
50
+ message={stateAlert.message}
51
+ leftButtonTitle={stateAlert.leftButton}
52
+ leftButtonClick={hideAlertAction}
53
+ rightButtonTitle={stateAlert.rightButton}
54
+ rightButtonClick={onDone}
55
+ rightDisabled={!value}
56
+ >
57
+ <_TextInput
58
+ wrapStyle={styles.wrapInputStyle}
59
+ value={value}
60
+ onChange={onInputChange}
61
+ />
62
+ </AlertAction>
63
+ </View>
64
+ </View>
65
+ );
66
+ };
67
+
68
+ export default TextBoxTemplate;
@@ -0,0 +1,37 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { Colors } from '../../configs';
3
+
4
+ export default StyleSheet.create({
5
+ wrapOrderItem: {
6
+ flex: 1,
7
+ flexDirection: 'row',
8
+ justifyContent: 'space-between',
9
+ padding: 16,
10
+ },
11
+ wrap: {
12
+ padding: 16,
13
+ marginHorizontal: 16,
14
+ marginBottom: 16,
15
+ borderWidth: 1,
16
+ borderColor: Colors.Gray4,
17
+ borderRadius: 10,
18
+ flex: 1,
19
+ flexDirection: 'column',
20
+ justifyContent: 'space-between',
21
+ },
22
+ iconAndText: {
23
+ flex: 1,
24
+ flexDirection: 'row',
25
+ alignItems: 'center',
26
+ },
27
+ iconAndTextOption: {
28
+ flex: 1,
29
+ flexDirection: 'row',
30
+ alignItems: 'center',
31
+ justifyContent: 'flex-end',
32
+ },
33
+ wrapInputStyle: {
34
+ marginRight: 14,
35
+ paddingLeft: 14,
36
+ },
37
+ });
@@ -0,0 +1,130 @@
1
+ import React from 'react';
2
+ import { TouchableOpacity, View } from 'react-native';
3
+ import { act, create } from 'react-test-renderer';
4
+ import { watchMultiConfigs } from '../../../iot/Monitor';
5
+ import { AlertAction } from '../..';
6
+ import { AccessibilityLabel } from '../../../configs/Constants';
7
+ import { SCProvider } from '../../../context';
8
+ import { mockSCStore } from '../../../context/mockStore';
9
+
10
+ import TextBoxTemplate from '../TextBoxTemplate';
11
+ import _TextInput from '../../Form/TextInput';
12
+ import { Colors } from '../../../configs';
13
+
14
+ const wrapComponent = (item, mockDoAction, isWidgetOrder = false) => (
15
+ <SCProvider initState={mockSCStore({})}>
16
+ <TextBoxTemplate
17
+ item={item}
18
+ doAction={mockDoAction}
19
+ isWidgetOrder={isWidgetOrder}
20
+ />
21
+ </SCProvider>
22
+ );
23
+
24
+ jest.mock('../../../iot/Monitor');
25
+
26
+ jest.mock('../../../iot/states', () => ({
27
+ useConfigGlobalState: () => [{ 5: { value: 2 } }, null],
28
+ }));
29
+
30
+ jest.mock('@react-navigation/native', () => {
31
+ return {
32
+ ...jest.requireActual('@react-navigation/native'),
33
+ useFocusEffect: jest.fn(),
34
+ };
35
+ });
36
+
37
+ describe('Test OptionsDropdownActionTemplate', () => {
38
+ const actionData = {
39
+ color: '#00979D',
40
+ command_prefer_over_bluetooth: true,
41
+ command_prefer_over_googlehome: false,
42
+ command_prefer_over_internet: false,
43
+ googlehome_actions: [],
44
+ icon: 'caret-up',
45
+ id: 20,
46
+ key: '5ed1d4dc-a905-47cd-b0c9-f979644bd21a',
47
+ };
48
+
49
+ let displayItem;
50
+ let sensor;
51
+ let wrapper;
52
+
53
+ beforeEach(() => {
54
+ watchMultiConfigs.mockClear();
55
+ displayItem = {
56
+ label: 'label',
57
+ configuration: {
58
+ title: 'Fan Speed',
59
+ action_data: actionData,
60
+ config: { id: 5 },
61
+ icon: 'slack',
62
+ },
63
+ };
64
+ sensor = {
65
+ name: 'Sensor name',
66
+ is_managed_by_backend: false,
67
+ };
68
+ });
69
+
70
+ it('render template', async () => {
71
+ const mockDoAction = jest.fn();
72
+ await act(async () => {
73
+ wrapper = await create(wrapComponent(displayItem, mockDoAction));
74
+ });
75
+ const instance = wrapper.root;
76
+ const views = instance.findAllByType(View);
77
+
78
+ expect(views[0].props.style).toEqual({
79
+ padding: 16,
80
+ marginHorizontal: 16,
81
+ marginBottom: 16,
82
+ borderWidth: 1,
83
+ borderColor: Colors.Gray4,
84
+ borderRadius: 10,
85
+ flex: 1,
86
+ flexDirection: 'column',
87
+ justifyContent: 'space-between',
88
+ });
89
+ const buttonEdit = instance.find(
90
+ (el) =>
91
+ el.props.accessibilityLabel ===
92
+ AccessibilityLabel.TEXT_BOX_BUTTON_EDIT &&
93
+ el.type === TouchableOpacity
94
+ );
95
+ await act(async () => {
96
+ await buttonEdit.props.onPress();
97
+ });
98
+ const alertAction = instance.findByType(AlertAction);
99
+ expect(alertAction.props.visible).toBeTruthy();
100
+ expect(alertAction.props.rightDisabled).toBeTruthy();
101
+ const textInput = instance.findByType(_TextInput);
102
+ await act(async () => {
103
+ await textInput.props.onChange('123');
104
+ });
105
+ expect(alertAction.props.rightDisabled).toBeFalsy();
106
+ await act(async () => {
107
+ await alertAction.props.rightButtonClick();
108
+ });
109
+ expect(mockDoAction).toHaveBeenCalledWith(
110
+ actionData,
111
+ JSON.stringify({ value: '123' })
112
+ );
113
+ });
114
+ it('render template isWidgetOrder change position', async () => {
115
+ const mockDoAction = jest.fn();
116
+ sensor.is_managed_by_backend = true;
117
+ await act(async () => {
118
+ wrapper = await create(wrapComponent(displayItem, mockDoAction, true));
119
+ });
120
+ const instance = wrapper.root;
121
+ const views = instance.findAllByType(View);
122
+
123
+ expect(views[0].props.style).toEqual({
124
+ flex: 1,
125
+ flexDirection: 'row',
126
+ justifyContent: 'space-between',
127
+ padding: 16,
128
+ });
129
+ });
130
+ });
@@ -13,6 +13,7 @@ import SliderRangeTemplate from './SliderRangeTemplate';
13
13
  import OnOffSmartLock from './OnOffSmartLock/OnOffSmartLock';
14
14
  import TwoButtonTemplate from './TwoButtonTemplate';
15
15
  import SwitchButtonTemplate from './OnOffTemplate/SwitchButtonTemplate';
16
+ import TextBoxTemplate from './TextBoxTemplate';
16
17
 
17
18
  export const getActionComponent = (template) => {
18
19
  switch (template) {
@@ -46,6 +47,8 @@ export const getActionComponent = (template) => {
46
47
  return TwoButtonTemplate;
47
48
  case 'switch_button_action_template':
48
49
  return SwitchButtonTemplate;
50
+ case 'TextBoxTemplate':
51
+ return TextBoxTemplate;
49
52
  default:
50
53
  return null;
51
54
  }
@@ -23,6 +23,7 @@ const AlertAction = ({
23
23
  boxLeftButtonStyle,
24
24
  boxRightButtonStyle,
25
25
  transY = 0,
26
+ rightDisabled = false,
26
27
  }) => {
27
28
  const [keyboardAnim] = useState(new Animated.Value(0));
28
29
 
@@ -82,6 +83,7 @@ const AlertAction = ({
82
83
  accessibilityLabelPrefix={accessibilityLabelPrefix}
83
84
  wrapStyle={styles.wrapViewButtonStyle}
84
85
  disableKeyBoardAnimated
86
+ rightDisabled={rightDisabled}
85
87
  />
86
88
  </View>
87
89
  </Animated.View>
@@ -559,6 +559,8 @@ export default {
559
559
  NUMBER_UP_DOWN_ACTION_DONE: 'NUMBER_UP_DOWN_ACTION_DONE',
560
560
  NUMBER_ACTION_UP: 'NUMBER_ACTION_UP',
561
561
  NUMBER_ACTION_DOWN: 'NUMBER_ACTION_DOWN',
562
+ //TestBoxTemplate
563
+ TEXT_BOX_BUTTON_EDIT: 'TEXT_BOX_BUTTON_EDIT',
562
564
 
563
565
  // OnOffButtonAction
564
566
  ON_OFF_BUTTON_ACTION_TITLE: 'ON_OFF_BUTTON_ACTION_TITLE',
@@ -43,7 +43,9 @@ const NewActionWrapper = ({ name, children, canNext, onNext, nextTitle }) => {
43
43
  isShowSeparator
44
44
  wrapTitleStyle={styles.wrapTitleStyle}
45
45
  />
46
- <KeyboardAwareScrollView>{children}</KeyboardAwareScrollView>
46
+ <KeyboardAwareScrollView contentContainerStyle={styles.scroll}>
47
+ {children}
48
+ </KeyboardAwareScrollView>
47
49
  {hasNext && (
48
50
  <BottomButtonView
49
51
  style={styles.bottomButtonView}
@@ -81,4 +81,7 @@ export default StyleSheet.create({
81
81
  paddingLeft: 16,
82
82
  paddingRight: 16,
83
83
  },
84
+ scroll: {
85
+ paddingBottom: 200,
86
+ },
84
87
  });
@@ -61,7 +61,7 @@ const ChangePosition = () => {
61
61
  <View style={styles.disableSensor} />
62
62
  <View style={styles.widgetOrder}>
63
63
  <SensorDisplayItem
64
- isWidgetOrder
64
+ isWidgetOrder={true}
65
65
  item={item}
66
66
  sensor={sensor}
67
67
  offsetTitle={offsetTitle}
@@ -170,6 +170,7 @@ export const SensorDisplayItem = ({
170
170
  case 'slider_range_template':
171
171
  case 'two_button_action_template':
172
172
  case 'switch_button_action_template':
173
+ case 'TextBoxTemplate':
173
174
  return (
174
175
  <ActionGroup
175
176
  accessibilityLabel={AccessibilityLabel.DEVICE_DETAIL_ACTION_GROUP}