@eohjsc/react-native-smart-city 0.7.26 → 0.7.30
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 +2 -1
- package/src/commons/Dashboard/MyDashboardDevice/__test__/index.test.js +68 -0
- package/src/commons/Dashboard/MyDashboardDevice/index.js +46 -11
- package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +43 -11
- package/src/commons/Dashboard/MyUnit/index.js +40 -32
- package/src/commons/ModalAlert/index.js +51 -0
- package/src/commons/ModalAlert/styles.js +54 -0
- package/src/commons/SubUnit/ShortDetail.js +20 -4
- package/src/commons/SubUnit/__test__/ShortDetail.test.js +46 -1
- package/src/configs/API.js +6 -0
- package/src/configs/AccessibilityLabel.js +1 -0
- package/src/configs/Constants.js +7 -0
- package/src/configs/SCConfig.js +6 -0
- package/src/context/SCContext.tsx +12 -1
- package/src/context/SCStore.ts +14 -0
- package/src/context/actionType.ts +10 -0
- package/src/context/mockStore.ts +30 -1
- package/src/context/reducer.ts +35 -0
- package/src/hooks/IoT/useRemoteControl.js +4 -1
- package/src/hooks/IoT/useWatchSharedChips.js +130 -0
- package/src/hooks/Review/__test__/useInAppReview.test.js +99 -0
- package/src/hooks/Review/useInAppReview.js +70 -0
- package/src/hooks/useMqtt.js +78 -27
- package/src/iot/Monitor.js +149 -26
- package/src/iot/UpdateStates.js +60 -0
- package/src/iot/mqtt.js +177 -22
- package/src/navigations/UnitStack.js +16 -0
- package/src/screens/ActivityLog/FilterPopup.js +4 -79
- package/src/screens/ActivityLog/ItemLog.js +1 -0
- package/src/screens/ActivityLog/__test__/FilterPopup.test.js +2 -6
- package/src/screens/ActivityLog/__test__/index.test.js +51 -29
- package/src/screens/ActivityLog/index.js +0 -1
- package/src/screens/ActivityLog/styles/filterPopupStyles.js +5 -2
- package/src/screens/AddNewGateway/RenameNewDevices.js +5 -0
- package/src/screens/AddNewGateway/__test__/RenameNewDevices.test.js +18 -0
- package/src/screens/Automate/AddNewAction/ReceiverSelect.js +208 -0
- package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +1 -1
- package/src/screens/Automate/AddNewAction/SetupScriptNotify.js +18 -28
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +22 -129
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverNotify.js +59 -0
- package/src/screens/Automate/AddNewAction/SetupScriptReceiverSms.js +22 -129
- package/src/screens/Automate/AddNewAction/SetupScriptSms.js +1 -1
- package/src/screens/Automate/AddNewAction/Styles/{SetupScriptReceiverEmailStyles.js → ReceiverSelectStyles.js} +18 -1
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptNotify.test.js +16 -33
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +10 -8
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverNotify.test.js +217 -0
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverSms.test.js +10 -8
- package/src/screens/Automate/Components/InputName.js +5 -1
- package/src/screens/Automate/OneTap/__test__/AddNewOneTap.test.js +18 -0
- package/src/screens/Automate/ScriptDetail/index.js +6 -6
- package/src/screens/CreatePassword/__test__/index.test.js +133 -0
- package/src/screens/CreatePassword/index.js +134 -0
- package/src/screens/CreatePassword/styles.js +45 -0
- package/src/screens/Device/__test__/DeviceDetail-3rdparty.test.js +447 -0
- package/src/screens/Device/__test__/DeviceDetail-arduino.test.js +344 -0
- package/src/screens/Device/__test__/{mqttDetail.test.js → DeviceDetail-modbus.test.js} +287 -320
- package/src/screens/Device/__test__/DeviceDetail-zigbee.test.js +451 -0
- package/src/screens/Device/__test__/DeviceDetail.test.js +502 -0
- package/src/screens/Device/__test__/detail.test.js +61 -3
- package/src/screens/Device/__test__/sensorDisplayItem.test.js +28 -3
- package/src/screens/Device/components/SensorDisplayItem.js +16 -14
- package/src/screens/Device/detail.js +14 -6
- package/src/screens/Device/hooks/useDeviceWatchConfigControl.js +3 -2
- package/src/screens/Device/styles.js +0 -5
- package/src/screens/EnterPassword/__test__/EnterPassword.test.js +76 -1
- package/src/screens/EnterPassword/index.js +34 -4
- package/src/screens/EnterPassword/styles.js +1 -1
- package/src/utils/FactoryGateway.js +597 -0
- package/src/utils/I18n/translations/en.js +10 -0
- package/src/utils/I18n/translations/vi.js +10 -0
- package/src/utils/Route/index.js +3 -1
- package/src/utils/Validation.js +5 -0
- package/src/utils/store.js +5 -0
|
@@ -955,7 +955,7 @@ const Item = ({ item, index, enableScript, t, local_control }) => {
|
|
|
955
955
|
</View>
|
|
956
956
|
);
|
|
957
957
|
} else if (notify_script) {
|
|
958
|
-
const { title, message, unit_name } = notify_script;
|
|
958
|
+
const { title, message, unit_name, str_receivers } = notify_script;
|
|
959
959
|
return (
|
|
960
960
|
<View style={styles.wrapItem}>
|
|
961
961
|
<View style={styles.leftItem}>
|
|
@@ -978,7 +978,7 @@ const Item = ({ item, index, enableScript, t, local_control }) => {
|
|
|
978
978
|
</View>
|
|
979
979
|
</View>
|
|
980
980
|
<Text numberOfLines={1} type="H4" color={color}>
|
|
981
|
-
{unit_name}
|
|
981
|
+
{`${unit_name}: ${str_receivers}`}
|
|
982
982
|
</Text>
|
|
983
983
|
</View>
|
|
984
984
|
</View>
|
|
@@ -1008,7 +1008,7 @@ const Item = ({ item, index, enableScript, t, local_control }) => {
|
|
|
1008
1008
|
</View>
|
|
1009
1009
|
);
|
|
1010
1010
|
} else if (email_script) {
|
|
1011
|
-
const { title, message, str_emails } = email_script;
|
|
1011
|
+
const { title, message, unit_name, str_emails } = email_script;
|
|
1012
1012
|
return (
|
|
1013
1013
|
<View style={styles.wrapItem}>
|
|
1014
1014
|
<View style={styles.leftItem}>
|
|
@@ -1031,13 +1031,13 @@ const Item = ({ item, index, enableScript, t, local_control }) => {
|
|
|
1031
1031
|
</View>
|
|
1032
1032
|
</View>
|
|
1033
1033
|
<Text numberOfLines={1} type="H4" color={color}>
|
|
1034
|
-
{str_emails}
|
|
1034
|
+
{`${unit_name}: ${str_emails}`}
|
|
1035
1035
|
</Text>
|
|
1036
1036
|
</View>
|
|
1037
1037
|
</View>
|
|
1038
1038
|
);
|
|
1039
1039
|
} else if (sms_script) {
|
|
1040
|
-
const { message, str_phone_numbers } = sms_script;
|
|
1040
|
+
const { message, unit_name, str_phone_numbers } = sms_script;
|
|
1041
1041
|
color = local_control.is_local_control ? color : Colors.Gray7;
|
|
1042
1042
|
return (
|
|
1043
1043
|
<View style={styles.wrapItem}>
|
|
@@ -1056,7 +1056,7 @@ const Item = ({ item, index, enableScript, t, local_control }) => {
|
|
|
1056
1056
|
{message}
|
|
1057
1057
|
</Text>
|
|
1058
1058
|
<Text numberOfLines={1} type="H4" color={color}>
|
|
1059
|
-
{str_phone_numbers}
|
|
1059
|
+
{`${unit_name}: ${str_phone_numbers}`}
|
|
1060
1060
|
</Text>
|
|
1061
1061
|
</View>
|
|
1062
1062
|
</View>
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { TouchableOpacity } from 'react-native';
|
|
4
|
+
import { act, create } from 'react-test-renderer';
|
|
5
|
+
|
|
6
|
+
import { useNavigation } from '@react-navigation/native';
|
|
7
|
+
import { API } from '../../../configs';
|
|
8
|
+
import { AccessibilityLabel } from '../../../configs/Constants';
|
|
9
|
+
import _TextInputPassword from '../../../commons/Form/TextInputPassword';
|
|
10
|
+
import { SCProvider } from '../../../context';
|
|
11
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
12
|
+
import api from '../../../utils/Apis/axios';
|
|
13
|
+
import t from '../../../hooks/Common/useTranslations';
|
|
14
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
15
|
+
import Routes from '../../../utils/Route';
|
|
16
|
+
import CreatePassword from '..';
|
|
17
|
+
|
|
18
|
+
const mock = new MockAdapter(api.axiosInstance);
|
|
19
|
+
|
|
20
|
+
const wrapComponent = () => (
|
|
21
|
+
<SCProvider initState={mockSCStore({})}>
|
|
22
|
+
<CreatePassword />
|
|
23
|
+
</SCProvider>
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
describe('test CreatePassword', () => {
|
|
27
|
+
let tree;
|
|
28
|
+
const { navigate } = useNavigation();
|
|
29
|
+
const spyToastSuccess = jest.spyOn(ToastBottomHelper, 'success');
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
spyToastSuccess.mockClear();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const onChangePasswords = async (component, text1, text2) => {
|
|
36
|
+
await act(async () => {
|
|
37
|
+
await component[0].props.onChange(text1);
|
|
38
|
+
});
|
|
39
|
+
await act(async () => {
|
|
40
|
+
await component[1].props.onChange(text2);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const buttonDone = (instance) => {
|
|
45
|
+
return instance.find(
|
|
46
|
+
(el) =>
|
|
47
|
+
el.props.accessibilityLabel ===
|
|
48
|
+
AccessibilityLabel.CREATE_PASSWORD_BUTTON_DONE &&
|
|
49
|
+
el.type === TouchableOpacity
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
it('validate and create password success', async () => {
|
|
54
|
+
mock.onPatch(API.AUTH.CREATE_PASSWORD).reply(200);
|
|
55
|
+
await act(async () => {
|
|
56
|
+
tree = await create(wrapComponent());
|
|
57
|
+
});
|
|
58
|
+
const instance = tree.root;
|
|
59
|
+
const button = buttonDone(instance);
|
|
60
|
+
const texts = instance.findAllByType(_TextInputPassword);
|
|
61
|
+
|
|
62
|
+
await onChangePasswords(texts, '', '');
|
|
63
|
+
expect(texts[0].props.errorText).toEqual(t('please_enter_new_password'));
|
|
64
|
+
expect(texts[1].props.errorText).toEqual(
|
|
65
|
+
t('please_enter_your_confirm_password')
|
|
66
|
+
);
|
|
67
|
+
expect(button.props.disabled).toBeTruthy();
|
|
68
|
+
|
|
69
|
+
await onChangePasswords(texts, '123', '123');
|
|
70
|
+
expect(texts[0].props.errorText).toEqual(t('password_must_be_strong'));
|
|
71
|
+
expect(texts[1].props.errorText).toEqual('');
|
|
72
|
+
expect(button.props.disabled).toBeTruthy();
|
|
73
|
+
|
|
74
|
+
await onChangePasswords(texts, 'Password1', 'Password2');
|
|
75
|
+
expect(texts[0].props.errorText).toEqual('');
|
|
76
|
+
expect(texts[1].props.errorText).toEqual(t('confirm_password_not_match'));
|
|
77
|
+
expect(button.props.disabled).toBeTruthy();
|
|
78
|
+
|
|
79
|
+
await act(async () => {
|
|
80
|
+
await texts[1].props.onChange('Password1');
|
|
81
|
+
});
|
|
82
|
+
expect(texts[0].props.errorText).toEqual('');
|
|
83
|
+
expect(texts[1].props.errorText).toEqual('');
|
|
84
|
+
expect(button.props.disabled).toBeFalsy();
|
|
85
|
+
|
|
86
|
+
await act(async () => {
|
|
87
|
+
await texts[0].props.onChange('Password2');
|
|
88
|
+
});
|
|
89
|
+
expect(texts[0].props.errorText).toEqual('');
|
|
90
|
+
expect(texts[1].props.errorText).toEqual(t('confirm_password_not_match'));
|
|
91
|
+
expect(button.props.disabled).toBeTruthy();
|
|
92
|
+
|
|
93
|
+
await act(async () => {
|
|
94
|
+
await texts[0].props.onChange('Password1');
|
|
95
|
+
});
|
|
96
|
+
expect(texts[0].props.errorText).toEqual('');
|
|
97
|
+
expect(texts[1].props.errorText).toEqual('');
|
|
98
|
+
expect(button.props.disabled).toBeFalsy();
|
|
99
|
+
|
|
100
|
+
await act(async () => {
|
|
101
|
+
await button.props.onPress();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
expect(spyToastSuccess).toHaveBeenCalledWith(
|
|
105
|
+
t('create_password_successfully')
|
|
106
|
+
);
|
|
107
|
+
expect(navigate).toHaveBeenCalledWith(Routes.Dashboard, {
|
|
108
|
+
needLogout: true,
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('create password fail', async () => {
|
|
113
|
+
mock.onPatch(API.AUTH.CREATE_PASSWORD).reply(400);
|
|
114
|
+
await act(async () => {
|
|
115
|
+
tree = await create(wrapComponent());
|
|
116
|
+
});
|
|
117
|
+
const instance = tree.root;
|
|
118
|
+
const button = buttonDone(instance);
|
|
119
|
+
const texts = instance.findAllByType(_TextInputPassword);
|
|
120
|
+
|
|
121
|
+
await onChangePasswords(texts, 'Password1', 'Password1');
|
|
122
|
+
expect(texts[0].props.errorText).toEqual('');
|
|
123
|
+
expect(texts[1].props.errorText).toEqual('');
|
|
124
|
+
expect(button.props.disabled).toBeFalsy();
|
|
125
|
+
|
|
126
|
+
await act(async () => {
|
|
127
|
+
await button.props.onPress();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
expect(spyToastSuccess).not.toHaveBeenCalled();
|
|
131
|
+
expect(navigate).not.toHaveBeenCalled();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import React, { useMemo, useState, useCallback } from 'react';
|
|
2
|
+
import { TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import { useNavigation } from '@react-navigation/native';
|
|
4
|
+
|
|
5
|
+
import { Colors, API } from '../../configs';
|
|
6
|
+
import { AccessibilityLabel } from '../../configs/Constants';
|
|
7
|
+
import { HeaderCustom } from '../../commons/Header';
|
|
8
|
+
import _TextInputPassword from '../../commons/Form/TextInputPassword';
|
|
9
|
+
import { Section } from '../../commons/Section';
|
|
10
|
+
import Text from '../../commons/Text';
|
|
11
|
+
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
12
|
+
import { axiosPatch } from '../../utils/Apis/axios';
|
|
13
|
+
import { isValidPassword } from '../../utils/Validation';
|
|
14
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
15
|
+
import Routes from '../../utils/Route';
|
|
16
|
+
|
|
17
|
+
import styles from './styles';
|
|
18
|
+
|
|
19
|
+
const CreatePassword = ({ route }) => {
|
|
20
|
+
const t = useTranslations();
|
|
21
|
+
const { navigate } = useNavigation();
|
|
22
|
+
const [newPassword, setNewPassword] = useState('');
|
|
23
|
+
const [confirmPassword, setConfirmPassword] = useState('');
|
|
24
|
+
const [newPasswordError, setNewPasswordError] = useState('');
|
|
25
|
+
const [confirmPasswordError, setConfirmPasswordError] = useState('');
|
|
26
|
+
|
|
27
|
+
const onChangeNewPassword = useCallback(
|
|
28
|
+
(value) => {
|
|
29
|
+
setNewPassword(value);
|
|
30
|
+
setNewPasswordError(
|
|
31
|
+
!value
|
|
32
|
+
? t('please_enter_new_password')
|
|
33
|
+
: !isValidPassword(value)
|
|
34
|
+
? t('password_must_be_strong')
|
|
35
|
+
: ''
|
|
36
|
+
);
|
|
37
|
+
setConfirmPasswordError((prev) =>
|
|
38
|
+
confirmPassword && value !== confirmPassword
|
|
39
|
+
? t('confirm_password_not_match')
|
|
40
|
+
: value === confirmPassword
|
|
41
|
+
? ''
|
|
42
|
+
: prev
|
|
43
|
+
);
|
|
44
|
+
},
|
|
45
|
+
[confirmPassword, t]
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const onChangeConfirmPassword = useCallback(
|
|
49
|
+
(value) => {
|
|
50
|
+
setConfirmPassword(value);
|
|
51
|
+
setConfirmPasswordError(
|
|
52
|
+
!value
|
|
53
|
+
? t('please_enter_your_confirm_password')
|
|
54
|
+
: value !== newPassword
|
|
55
|
+
? t('confirm_password_not_match')
|
|
56
|
+
: ''
|
|
57
|
+
);
|
|
58
|
+
},
|
|
59
|
+
[newPassword, t]
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const canDone = useMemo(() => {
|
|
63
|
+
return (
|
|
64
|
+
newPassword &&
|
|
65
|
+
confirmPassword &&
|
|
66
|
+
!newPasswordError &&
|
|
67
|
+
!confirmPasswordError
|
|
68
|
+
);
|
|
69
|
+
}, [newPassword, confirmPassword, newPasswordError, confirmPasswordError]);
|
|
70
|
+
|
|
71
|
+
const onCreatePassword = useCallback(async () => {
|
|
72
|
+
const { success } = await axiosPatch(API.AUTH.CREATE_PASSWORD, {
|
|
73
|
+
new_password: newPassword,
|
|
74
|
+
confirm_password: confirmPassword,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
if (success) {
|
|
78
|
+
ToastBottomHelper.success(t('create_password_successfully'));
|
|
79
|
+
navigate(Routes.Dashboard, { needLogout: true });
|
|
80
|
+
}
|
|
81
|
+
}, [newPassword, confirmPassword, navigate, t]);
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<View style={styles.container}>
|
|
85
|
+
<HeaderCustom
|
|
86
|
+
title={t('password')}
|
|
87
|
+
isShowSeparator
|
|
88
|
+
titleStyle={{ color: Colors.Gray9 }}
|
|
89
|
+
/>
|
|
90
|
+
<Text style={styles.boardTitle} color={Colors.Black} bold>
|
|
91
|
+
{t('create_password')}
|
|
92
|
+
</Text>
|
|
93
|
+
<Section type={'border'}>
|
|
94
|
+
<_TextInputPassword
|
|
95
|
+
secureTextEntry
|
|
96
|
+
label={t('new_password')}
|
|
97
|
+
labelStyle={styles.labelStyle}
|
|
98
|
+
wrapStyle={styles.wrapStyle}
|
|
99
|
+
onChange={onChangeNewPassword}
|
|
100
|
+
value={newPassword}
|
|
101
|
+
textInputStyle={styles.passwordInput}
|
|
102
|
+
selectionColor={Colors.Primary}
|
|
103
|
+
errorText={newPasswordError}
|
|
104
|
+
/>
|
|
105
|
+
<_TextInputPassword
|
|
106
|
+
secureTextEntry
|
|
107
|
+
label={t('confirm_password')}
|
|
108
|
+
labelStyle={styles.labelStyle}
|
|
109
|
+
wrapStyle={styles.wrapStyle}
|
|
110
|
+
onChange={onChangeConfirmPassword}
|
|
111
|
+
value={confirmPassword}
|
|
112
|
+
textInputStyle={styles.passwordInput}
|
|
113
|
+
selectionColor={Colors.Primary}
|
|
114
|
+
errorText={confirmPasswordError}
|
|
115
|
+
/>
|
|
116
|
+
</Section>
|
|
117
|
+
<TouchableOpacity
|
|
118
|
+
style={[styles.buttonDone, !canDone && styles.buttonDoneDisable]}
|
|
119
|
+
onPress={onCreatePassword}
|
|
120
|
+
accessibilityLabel={AccessibilityLabel.CREATE_PASSWORD_BUTTON_DONE}
|
|
121
|
+
disabled={!canDone}
|
|
122
|
+
>
|
|
123
|
+
<Text
|
|
124
|
+
type="H4"
|
|
125
|
+
style={canDone ? styles.textDone : styles.textDoneDisable}
|
|
126
|
+
>
|
|
127
|
+
{t('done')}
|
|
128
|
+
</Text>
|
|
129
|
+
</TouchableOpacity>
|
|
130
|
+
</View>
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export default CreatePassword;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { Colors } from '../../configs';
|
|
3
|
+
|
|
4
|
+
export default StyleSheet.create({
|
|
5
|
+
container: {
|
|
6
|
+
flex: 1,
|
|
7
|
+
backgroundColor: Colors.Gray2,
|
|
8
|
+
},
|
|
9
|
+
boardTitle: {
|
|
10
|
+
marginBottom: 8,
|
|
11
|
+
marginTop: 12,
|
|
12
|
+
marginLeft: 16,
|
|
13
|
+
},
|
|
14
|
+
labelStyle: {
|
|
15
|
+
color: Colors.Primary,
|
|
16
|
+
},
|
|
17
|
+
wrapStyle: {
|
|
18
|
+
marginTop: 12,
|
|
19
|
+
width: '100%',
|
|
20
|
+
},
|
|
21
|
+
passwordInput: {
|
|
22
|
+
paddingTop: 8,
|
|
23
|
+
paddingBottom: 8,
|
|
24
|
+
},
|
|
25
|
+
buttonDone: {
|
|
26
|
+
justifyContent: 'center',
|
|
27
|
+
alignItems: 'center',
|
|
28
|
+
paddingVertical: 12,
|
|
29
|
+
borderRadius: 30,
|
|
30
|
+
backgroundColor: Colors.Primary,
|
|
31
|
+
width: '90%',
|
|
32
|
+
alignSelf: 'center',
|
|
33
|
+
},
|
|
34
|
+
buttonDoneDisable: {
|
|
35
|
+
backgroundColor: Colors.White,
|
|
36
|
+
borderWidth: 1,
|
|
37
|
+
borderColor: Colors.Neutral.Neutral3,
|
|
38
|
+
},
|
|
39
|
+
textDone: {
|
|
40
|
+
color: Colors.White,
|
|
41
|
+
},
|
|
42
|
+
textDoneDisable: {
|
|
43
|
+
color: Colors.Gray6,
|
|
44
|
+
},
|
|
45
|
+
});
|