@ledvance/group-ui-biz-bundle 1.0.31 → 1.0.33

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
@@ -4,7 +4,7 @@
4
4
  "name": "@ledvance/group-ui-biz-bundle",
5
5
  "pid": [],
6
6
  "uiid": "",
7
- "version": "1.0.31",
7
+ "version": "1.0.33",
8
8
  "scripts": {},
9
9
  "dependencies": {
10
10
  "@ledvance/base": "^1.x",
@@ -55,7 +55,7 @@ export const useFlag: UseFlagType = (params) => {
55
55
 
56
56
  return dps
57
57
  }
58
- }, flagData => ({workMode: (params.isStripLight && flagData?.drawToolStatus) ? WorkMode.Colour : WorkMode.Scene, switchLed: true}))
58
+ }, flagData => ({workMode: (params.isStripLight && flagData?.drawToolStatus) ? WorkMode.Colour : WorkMode.Scene, switch_led: true}))
59
59
  }
60
60
 
61
61
  export interface FlagOption {
@@ -180,6 +180,7 @@ const MoodPage = () => {
180
180
  success: true
181
181
  }
182
182
  }
183
+ let workMode: WorkMode = getWorkMode(mood, params);
183
184
  return setScene({
184
185
  scene: cloneDeep(mood),
185
186
  sceneDataDpCode: params.sceneDataDpCode,
@@ -0,0 +1,76 @@
1
+ import React from 'react'
2
+ import Card from "@ledvance/base/src/components/Card";
3
+ import Spacer from "@ledvance/base/src/components/Spacer";
4
+ import {StyleSheet, Text, View} from "react-native";
5
+ import {SwitchButton, Utils} from "tuya-panel-kit";
6
+ import {loopText} from "@ledvance/base/src/utils/common";
7
+ import {parseHour12} from "@tuya/tuya-panel-lamp-sdk/lib/utils";
8
+
9
+ const {convertX: cx} = Utils.RatioUtils
10
+ const {parseTimer} = Utils.TimeUtils
11
+
12
+ export interface ItemCardProps<T> {
13
+ item: T & {
14
+ enable: boolean
15
+ startTime: number
16
+ endTime: number
17
+ weeks: number[]
18
+ name?: string
19
+ },
20
+ is24Hour?: boolean,
21
+ onSwitch: (enable: boolean) => void
22
+ onPress: () => void
23
+ }
24
+
25
+ const ItemCard = <T, >(props: ItemCardProps<T>) => {
26
+ const {item, is24Hour, onSwitch, onPress} = props
27
+ return (
28
+ <Card style={styles.itemCard} onPress={onPress}>
29
+ <Spacer height={cx(16)}/>
30
+ <View style={styles.switchLine}>
31
+ <Text style={styles.time}>
32
+ {is24Hour ?
33
+ `${parseTimer(item.startTime * 60)} - ${parseTimer(item.endTime * 60)}`
34
+ :
35
+ `${parseHour12(item.startTime * 60)} - ${parseHour12(item.endTime * 60)}`
36
+ }
37
+ </Text>
38
+ <SwitchButton
39
+ style={styles.switchBtn}
40
+ value={item.enable}
41
+ thumbStyle={{elevation: 0}}
42
+ onValueChange={onSwitch}/>
43
+ </View>
44
+ <Text style={styles.loopText}>{loopText(item.weeks, parseTimer(item.startTime * 60))}</Text>
45
+ <Spacer height={cx(5)}/>
46
+ <Text style={styles.loopText}>{item.name}</Text>
47
+ <Spacer/>
48
+ </Card>
49
+ )
50
+ }
51
+
52
+ const styles = StyleSheet.create({
53
+ itemCard: {
54
+ marginHorizontal: cx(24),
55
+ paddingHorizontal: cx(16),
56
+ },
57
+ switchLine: {
58
+ flexDirection: 'row',
59
+ alignItems: 'center',
60
+ },
61
+ time: {
62
+ flex: 1,
63
+ color: '#000',
64
+ fontSize: cx(16),
65
+ fontWeight: 'bold',
66
+ fontFamily: 'helvetica_neue_lt_std_bd',
67
+ },
68
+ switchBtn: {},
69
+ loopText: {
70
+ color: '#000',
71
+ fontSize: cx(14),
72
+ fontFamily: 'helvetica_neue_lt_std_roman',
73
+ },
74
+ })
75
+
76
+ export default ItemCard
@@ -0,0 +1,136 @@
1
+ /**
2
+ * 随机定时:最大 16 个定时功能。每 6 个字节代表含义如下:
3
+ *
4
+ * 第 1 个字节:通道号。bit0 代表开关,bit7-bit1 代表通道号,排插位数 0-6。
5
+ * 第 2 个字节:星期。
6
+ * 第 3 个字节和第 4 个字节:起始时间。单位:分钟。
7
+ * 第 5 个字节和第 6 个字节:结束时间。单位:分钟。
8
+ */
9
+
10
+ import {useFeatureHook} from "@ledvance/base/src/models/modules/NativePropsSlice";
11
+
12
+
13
+ export interface RandomTimeParam {
14
+ channels: string[],
15
+ is24Hour?: boolean
16
+ }
17
+
18
+ export interface RandomTimeItem {
19
+ enable: boolean
20
+ channel?: number
21
+ weeks: number[]
22
+ startTime: number
23
+ endTime: number
24
+ name?: string
25
+ index?: number
26
+ }
27
+
28
+ interface PlugConfig {
29
+ randomTime: RandomTimeItem[]
30
+ }
31
+
32
+ export function useRandomTime() {
33
+ return useFeatureHook<PlugConfig, RandomTimeItem[]>('randomTime', [], (val) => randomTimeItemsToBase64(val))
34
+ }
35
+
36
+ const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
37
+
38
+ const decodeBase64 = (base64: string): Uint8Array => {
39
+ const bufferLength = base64.length * 0.75;
40
+ const buffer = new Uint8Array(bufferLength);
41
+ let encoded1: number, encoded2: number, encoded3: number, encoded4: number;
42
+ let p = 0;
43
+
44
+ for (let i = 0; i < base64.length; i += 4) {
45
+ encoded1 = base64Chars.indexOf(base64[i]);
46
+ encoded2 = base64Chars.indexOf(base64[i + 1]);
47
+ encoded3 = base64Chars.indexOf(base64[i + 2]);
48
+ encoded4 = base64Chars.indexOf(base64[i + 3]);
49
+
50
+ buffer[p++] = (encoded1 << 2) | (encoded2 >> 4);
51
+ buffer[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
52
+ buffer[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
53
+ }
54
+
55
+ return buffer;
56
+ }
57
+
58
+ const encodeBase64 = (buffer: Uint8Array): string => {
59
+ let base64 = '';
60
+ let p = 0;
61
+ const length = buffer.length;
62
+
63
+ while (p < length) {
64
+ const byte1 = buffer[p++];
65
+ const byte2 = p < length ? buffer[p++] : 0;
66
+ const byte3 = p < length ? buffer[p++] : 0;
67
+
68
+ const encoded1 = byte1 >> 2;
69
+ const encoded2 = ((byte1 & 3) << 4) | (byte2 >> 4);
70
+ const encoded3 = ((byte2 & 15) << 2) | (byte3 >> 6);
71
+ const encoded4 = byte3 & 63;
72
+
73
+ base64 += base64Chars[encoded1] + base64Chars[encoded2];
74
+ base64 += p < length + 2 ? base64Chars[encoded3] : '=';
75
+ base64 += p < length + 1 ? base64Chars[encoded4] : '=';
76
+ }
77
+
78
+ return base64;
79
+ }
80
+
81
+ // @ts-ignore
82
+ const randomTimeItemsFromBase64 = (base64: string): RandomTimeItem[] => {
83
+ const bytes = decodeBase64(base64);
84
+ const items: RandomTimeItem[] = [];
85
+
86
+ for (let i = 0; i < bytes.length; i += 6) {
87
+ const channelByte = bytes[i];
88
+ const enable = (channelByte & 1) === 1;
89
+ const channel = (channelByte >> 1) & 0x7F;
90
+ const week = bytes[i + 1];
91
+ const startTime = (bytes[i + 2] << 8) | bytes[i + 3];
92
+ const endTime = (bytes[i + 4] << 8) | bytes[i + 5];
93
+
94
+ items.push({
95
+ enable,
96
+ channel,
97
+ weeks: [
98
+ (week & 0b00000001) >> 0,
99
+ (week & 0b00000010) >> 1,
100
+ (week & 0b00000100) >> 2,
101
+ (week & 0b00001000) >> 3,
102
+ (week & 0b00010000) >> 4,
103
+ (week & 0b00100000) >> 5,
104
+ (week & 0b01000000) >> 6,
105
+ (week & 0b10000000) >> 7,
106
+ ],
107
+ startTime,
108
+ endTime,
109
+ index: i % 6
110
+ });
111
+ }
112
+
113
+ return items;
114
+ }
115
+
116
+ export const randomTimeItemsToBase64 = (items: RandomTimeItem[]): string => {
117
+ const bytes = new Uint8Array(items.length * 6);
118
+
119
+ items.forEach((item, index) => {
120
+ const channelByte = (item.channel!! << 1) | (item.enable ? 1 : 0);
121
+ const week = item.weeks.reduce((acc, bit, i) => acc | (bit << i), 0);
122
+ const startTime = item.startTime;
123
+ const endTime = item.endTime;
124
+
125
+ const offset = index * 6;
126
+ bytes[offset] = channelByte;
127
+ bytes[offset + 1] = week;
128
+ bytes[offset + 2] = (startTime >> 8) & 0xFF;
129
+ bytes[offset + 3] = startTime & 0xFF;
130
+ bytes[offset + 4] = (endTime >> 8) & 0xFF;
131
+ bytes[offset + 5] = endTime & 0xFF;
132
+ });
133
+
134
+ return encodeBase64(bytes);
135
+ }
136
+
@@ -0,0 +1,268 @@
1
+ import React, {useMemo} from 'react'
2
+ import Page from "@ledvance/base/src/components/Page";
3
+ import I18n from "@ledvance/base/src/i18n";
4
+ import {Image, ScrollView, StyleSheet, Text, TouchableOpacity, View} from "react-native";
5
+ import {TimerPicker, Utils} from "tuya-panel-kit";
6
+ import {RandomTimeItem} from "./RandomTimeForPlugAction";
7
+ import res from "@ledvance/base/src/res/index";
8
+ import {useReactive} from "ahooks";
9
+ import {useNavigation, useRoute} from '@react-navigation/core';
10
+ import LdvTopName from "@ledvance/base/src/components/ldvTopName";
11
+ import TextField from "@ledvance/base/src/components/TextField";
12
+ import LdvWeekView from "@ledvance/base/src/components/weekSelect";
13
+ import Spacer from "@ledvance/base/src/components/Spacer";
14
+ import {loopText, showDialog} from "@ledvance/base/src/utils/common";
15
+ import DeleteButton from "@ledvance/base/src/components/DeleteButton";
16
+ import dayjs from "dayjs";
17
+ import {cloneDeep, isEqual} from "lodash";
18
+ import Summary from "./Summary";
19
+ import {RandomTimeParam} from "./RandomTimeForPlugAction";
20
+ import {parseHour12} from "@tuya/tuya-panel-lamp-sdk/lib/utils";
21
+
22
+ const {parseTimer} = Utils.TimeUtils
23
+ const {convertX: cx} = Utils.RatioUtils;
24
+
25
+ interface RandomTimeDetailParam extends RandomTimeParam {
26
+ mode: 'add' | 'edit',
27
+ item: RandomTimeItem,
28
+ onPost: (mode: 'add' | 'edit' | 'del', item: RandomTimeItem, goBack?: boolean) => Promise<void>
29
+ }
30
+
31
+ const newRandomTimeItem = (): RandomTimeItem => {
32
+ const startTime = dayjs().hour() * 60 + dayjs().minute()
33
+ return {
34
+ enable: true,
35
+ channel: 0,
36
+ weeks: [0, 0, 0, 0, 0, 0, 0, 0],
37
+ startTime: startTime,
38
+ endTime: startTime + 30
39
+ }
40
+ }
41
+
42
+ const RandomTimeForPlugDetailPage = () => {
43
+ const navigation = useNavigation()
44
+ const params = useRoute().params as RandomTimeDetailParam
45
+ const state = useReactive({
46
+ item: params.mode === 'add' ? newRandomTimeItem() : cloneDeep(params.item),
47
+ loading: false
48
+ })
49
+
50
+ const canSave = useMemo(() => {
51
+ return state.item.name && state.item.name.length < 33 && state.item.channel !== undefined
52
+ }, [state.item.name, state.item.channel])
53
+
54
+ const showConfirm = useMemo(() => {
55
+ return params.mode === 'edit' && !isEqual(state.item, params.item)
56
+ }, [JSON.stringify(state.item), JSON.stringify(params.item)])
57
+
58
+ const onSave = async () => {
59
+ if (!canSave) {
60
+ return
61
+ }
62
+ const timeInterval = state.item.endTime - state.item.startTime;
63
+ if (timeInterval >= 0 && timeInterval < 30) {
64
+ showDialog({
65
+ method: 'alert',
66
+ title: I18n.getLang('conflict_dialog_save_item_randomtimecycle_tips'),
67
+ subTitle: I18n.getLang('conflict_dialog_save_item_randomtimecycle_interval_description'),
68
+ onConfirm: async (_, { close }) => {
69
+ close()
70
+ }
71
+ })
72
+ return
73
+ }
74
+ await params.onPost(params.mode, cloneDeep(state.item), true);
75
+ }
76
+
77
+ const onDelete = () => {
78
+ return showDialog({
79
+ method: 'confirm',
80
+ title: I18n.getLang('cancel_dialog_delete_item_randomtimecycle_titel'),
81
+ subTitle: I18n.getLang('cancel_dialog_delete_item_randomtimecycle_description'),
82
+ onConfirm: async (_, {close}) => {
83
+ close()
84
+ await params.onPost('del', state.item, true)
85
+ }
86
+ })
87
+ }
88
+ return (
89
+ <Page
90
+ backText={I18n.getLang('randomtimecycle_sockets_headline_text')}
91
+ onBackClick={!showConfirm ? navigation.goBack : undefined}
92
+ rightButtonIcon={canSave ? res.ic_check : res.ic_uncheck}
93
+ rightButtonDisabled={state.loading}
94
+ loading={state.loading}
95
+ showBackDialog={showConfirm}
96
+ backDialogTitle={I18n.getLang('cancel_dialog_leave_unsaved_titel')}
97
+ backDialogContent={I18n.getLang('cancel_dialog_delete_item_randomtimecycle_description')}
98
+ rightButtonIconClick={onSave}
99
+ >
100
+ <ScrollView nestedScrollEnabled={true}>
101
+ <LdvTopName
102
+ title={I18n.getLang(params.mode === 'add' ? 'add_fixedtimecycle_headline_text' : 'edit_fixedtimecycle_headline_text')}/>
103
+ <TextField
104
+ style={styles.cardContainer}
105
+ value={state.item.name}
106
+ showError={(state.item.name?.length || 0) > 32}
107
+ maxLength={33}
108
+ errorText={I18n.getLang('add_new_dynamic_mood_alert_text')}
109
+ placeholder={I18n.getLang('add_new_trigger_time_inputfield_value_text')}
110
+ onChangeText={(t: string) => {
111
+ state.item.name = t;
112
+ }}
113
+ />
114
+ {/* pick */}
115
+ <TimerPicker
116
+ itemTextColor='#aeadb5'
117
+ style={{paddingVertical: cx(0), marginVertical: cx(0)}}
118
+ is12Hours={!params.is24Hour}
119
+ startTime={state.item.startTime}
120
+ endTime={state.item.endTime}
121
+ onTimerChange={(startTime, endTime) => {
122
+ state.item.startTime = startTime
123
+ state.item.endTime = endTime
124
+ }}/>
125
+ <LdvWeekView
126
+ value={state.item.weeks}
127
+ style={styles.cardContainer}
128
+ onSelect={(index: number) => {
129
+ const rawIndex = index - 1
130
+ state.item.weeks[rawIndex] = state.item.weeks[rawIndex] === 1 ? 0 : 1
131
+ }}/>
132
+ <Spacer/>
133
+ <Text style={styles.cardContainer}>{loopText(state.item.weeks, parseTimer(state.item.startTime * 60))}</Text>
134
+ <Spacer/>
135
+ {/*Apply for */}
136
+ <View style={styles.cardContainer}>
137
+ <Text style={styles.itemTitle}>{I18n.getLang('timeschedule_add_schedule_subheadline_text')}</Text>
138
+ <Spacer height={cx(10)}/>
139
+ <View style={styles.applyContent}>
140
+ {state.item.channel === undefined ?
141
+ <Text>{I18n.getLang('timer_ceiling_fan_selectionfield_no_components_text')}</Text> :
142
+ <View style={[styles.applyItem, {marginBottom: cx(10), borderRadius: 4}]}>
143
+ <Text style={{color: '#000'}}>{params.channels[state.item.channel]}</Text>
144
+ {params.channels.length > 1 && <TouchableOpacity
145
+ onPress={() => {
146
+ state.item.channel = undefined
147
+ }}
148
+ style={{paddingHorizontal: cx(5)}}>
149
+ <Image style={{width: cx(16), height: cx(16)}} source={res.ic_arrows_nav_clear}/>
150
+ </TouchableOpacity>}
151
+ </View>
152
+ }
153
+ </View>
154
+ {params.channels.map((item: string, index: number) => {
155
+ if (state.item.channel === index) {
156
+ return null
157
+ }
158
+ return (
159
+ <TouchableOpacity
160
+ style={styles.applyItem}
161
+ key={item}
162
+ onPress={() => {
163
+ state.item.channel = index
164
+ }}
165
+ >
166
+ <Text style={{color: '#000'}}>{item}</Text>
167
+ <Image style={{width: cx(16), height: cx(16)}} source={res.device_panel_timer_add}/>
168
+ </TouchableOpacity>
169
+ )
170
+ })}
171
+ </View>
172
+ <Spacer/>
173
+ {/* summary */}
174
+ <Summary
175
+ frequency={loopText(state.item.weeks)}
176
+ time={params.is24Hour ?
177
+ `${parseTimer(state.item.startTime * 60)} - ${parseTimer(state.item.endTime * 60)}`
178
+ :
179
+ `${parseHour12(state.item.startTime * 60)} - ${parseHour12(state.item.endTime * 60)}`
180
+ }
181
+ hideActions={true}
182
+ />
183
+ <Spacer/>
184
+ {params.mode === 'edit' &&
185
+ <View style={{marginHorizontal: cx(24)}}>
186
+ <DeleteButton
187
+ text={I18n.getLang('edit_fixedtimecycle_bttn_text')}
188
+ onPress={onDelete}/>
189
+ </View>
190
+ }
191
+ <Spacer/>
192
+ </ScrollView>
193
+ </Page>
194
+ )
195
+ }
196
+
197
+ const styles = StyleSheet.create({
198
+ cardContainer: {
199
+ marginHorizontal: cx(24)
200
+ },
201
+ itemTitle: {
202
+ color: '#000',
203
+ fontSize: cx(16),
204
+ fontWeight: 'bold',
205
+ fontFamily: 'helvetica_neue_lt_std_bd',
206
+ },
207
+ applyContent: {
208
+ backgroundColor: '#f6f6f6',
209
+ borderRadius: 4,
210
+ minHeight: cx(55),
211
+ flex: 1,
212
+ justifyContent: 'center',
213
+ paddingHorizontal: cx(10),
214
+ paddingTop: cx(10)
215
+ },
216
+ applyItem: {
217
+ paddingLeft: cx(5),
218
+ flexDirection: 'row',
219
+ justifyContent: 'space-between',
220
+ alignItems: 'center',
221
+ backgroundColor: '#fff',
222
+ height: cx(35),
223
+ },
224
+ summaryContainer: {
225
+ flexDirection: 'row',
226
+ justifyContent: 'flex-start',
227
+ marginBottom: cx(10)
228
+ },
229
+ summaryLeft: {
230
+ flexDirection: 'row',
231
+ justifyContent: 'flex-start',
232
+ alignItems: 'center',
233
+ },
234
+ summaryImg: {
235
+ width: cx(12),
236
+ height: cx(12),
237
+ marginRight: cx(6)
238
+ },
239
+ leftTitle: {
240
+ fontSize: cx(14),
241
+ color: '#000'
242
+ },
243
+ summaryRight: {
244
+ flexDirection: 'column',
245
+ marginLeft: cx(21),
246
+ borderRadius: cx(16),
247
+ backgroundColor: '#cbcbcb',
248
+ },
249
+ rightItem: {
250
+ paddingHorizontal: cx(12),
251
+ color: '#000',
252
+ },
253
+ rightTitle: {
254
+ paddingLeft: cx(12),
255
+ paddingRight: cx(12),
256
+ fontSize: cx(10),
257
+ textAlign: 'center',
258
+ alignSelf: 'flex-start'
259
+ },
260
+ filletCorner: {
261
+ flexDirection: 'row',
262
+ backgroundColor: '#cbcbcb',
263
+ borderRadius: cx(16),
264
+ alignSelf: 'flex-start'
265
+ }
266
+ })
267
+
268
+ export default RandomTimeForPlugDetailPage
@@ -0,0 +1,192 @@
1
+ import Page from "@ledvance/base/src/components/Page";
2
+ import {useDeviceInfo} from "@ledvance/base/src/models/modules/NativePropsSlice";
3
+ import {useNavigation, useRoute} from '@react-navigation/native'
4
+ import I18n from "@ledvance/base/src/i18n/index";
5
+ import res from "@ledvance/base/src/res/index";
6
+ import {useReactive} from "ahooks";
7
+ import React, {useCallback, useMemo} from "react";
8
+ import {FlatList, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View} from "react-native";
9
+ import {Utils} from "tuya-panel-kit";
10
+ import {ui_biz_routerKey} from "../../navigation/Routers";
11
+ import {RandomTimeItem, RandomTimeParam, useRandomTime} from "./RandomTimeForPlugAction";
12
+ import Spacer from "@ledvance/base/src/components/Spacer";
13
+ import ItemCard from "./ItemCard";
14
+ import {cloneDeep} from "lodash";
15
+
16
+ const {convertX: cx, topBarHeight} = Utils.RatioUtils;
17
+ const MAX_NUM = 16
18
+
19
+ const RandomTimeForPlugPage = () => {
20
+ const devInfo = useDeviceInfo()
21
+ const navigation = useNavigation()
22
+ const params = useRoute().params as RandomTimeParam
23
+ const [randomTimeList, setRandomTimeList] = useRandomTime()
24
+ const state = useReactive({
25
+ loading: false
26
+ })
27
+
28
+ const isMaxNum = useMemo(() => {
29
+ return randomTimeList.length >= MAX_NUM
30
+ }, [randomTimeList])
31
+
32
+ const onAddOrEditItem = (mode: 'add' | 'edit', item?: RandomTimeItem) => {
33
+ const path = ui_biz_routerKey.group_ui_biz_random_time_plug_detail
34
+ navigation.navigate(path, {
35
+ ...params,
36
+ mode,
37
+ item,
38
+ onPost
39
+ })
40
+ }
41
+
42
+ const onPost = useCallback(async (mode: 'add' | 'edit' | 'del', randomTime: RandomTimeItem, goBack?: boolean) => {
43
+ state.loading = true
44
+ const cloneRandomTimeList = cloneDeep(randomTimeList)
45
+ const idx = randomTimeList.findIndex(it => it.index === randomTime.index)
46
+ if (mode === 'edit') {
47
+ cloneRandomTimeList.splice(idx, 1, randomTime)
48
+ }
49
+ if (mode === 'del') cloneRandomTimeList.splice(idx, 1)
50
+ const newRandomTimeList = mode === 'add' ? [...randomTimeList, {
51
+ ...randomTime,
52
+ index: randomTimeList.length
53
+ }] : cloneRandomTimeList
54
+ const res = await setRandomTimeList(newRandomTimeList)
55
+ state.loading = false
56
+ if (res.success && goBack) {
57
+ navigation.goBack()
58
+ }
59
+ }, [randomTimeList])
60
+
61
+ const renderList = () => {
62
+ return (
63
+ <ScrollView nestedScrollEnabled={true}>
64
+ <Text style={{
65
+ color: '#000',
66
+ marginLeft: cx(24),
67
+ }}>{I18n.getLang('timeschedule_overview_description_text')}</Text>
68
+ <Spacer height={cx(10)}/>
69
+ {isMaxNum && <View style={{marginHorizontal: cx(24), flexDirection: 'row'}}>
70
+ <Image style={{width: cx(16), height: cx(16), tintColor: '#ff9500'}} source={res.ic_warning_amber}/>
71
+ <Text>{I18n.getLang('fixedtimecycle_warning_max_number_text')}</Text>
72
+ </View>}
73
+ <FlatList
74
+ data={randomTimeList}
75
+ renderItem={({item}) => (
76
+ <ItemCard
77
+ item={item}
78
+ is24Hour={params.is24Hour}
79
+ onSwitch={async (v) => {
80
+ await onPost('edit', {
81
+ ...item,
82
+ enable: v,
83
+ })
84
+ }}
85
+ onPress={() => {
86
+ onAddOrEditItem('edit', item)
87
+ }}
88
+ />
89
+ )}
90
+ keyExtractor={(item: any) => `${item?.index}`}
91
+ ItemSeparatorComponent={() => <Spacer/>}
92
+ ListHeaderComponent={<Spacer height={cx(10)}/>}
93
+ ListFooterComponent={<Spacer/>}
94
+ />
95
+ </ScrollView>
96
+ )
97
+ }
98
+ const renderEmpty = () => {
99
+ return (
100
+ <View style={styles.emptyListCon}>
101
+ <Image
102
+ style={styles.emptyImage}
103
+ source={{uri: res.ldv_timer_empty}}
104
+ resizeMode="contain"/>
105
+ <View
106
+ style={{
107
+ marginHorizontal: cx(24),
108
+ marginTop: cx(30),
109
+ flexDirection: 'row',
110
+ alignItems: 'center',
111
+ }}
112
+ >
113
+ <Image
114
+ source={{uri: res.device_panel_schedule_alert}}
115
+ style={{width: cx(16), height: cx(16)}}
116
+ />
117
+ <Text style={styles.emptyNoTime}>{I18n.getLang('randomtimecycle_empty_information_text')}</Text>
118
+ </View>
119
+ <View
120
+ style={{
121
+ height: cx(36),
122
+ width: cx(150),
123
+ marginVertical: cx(25),
124
+ marginHorizontal: cx(24),
125
+ borderRadius: cx(6),
126
+ backgroundColor: '#f60',
127
+ }}
128
+ >
129
+ <TouchableOpacity
130
+ style={{
131
+ flex: 1,
132
+ justifyContent: 'center',
133
+ alignItems: 'center',
134
+ }}
135
+ onPress={() => onAddOrEditItem('add')}
136
+ >
137
+ <Text style={{fontSize: cx(12), fontWeight: 'bold', color: '#fff', textAlign: 'center'}}>
138
+ {I18n.getLang('randomtimecycle_empty_bttn_text')}
139
+ </Text>
140
+ </TouchableOpacity>
141
+ </View>
142
+ </View>
143
+ )
144
+ }
145
+ return (
146
+ <Page
147
+ backText={devInfo.name}
148
+ headlineText={I18n.getLang('randomtimecycle_sockets_headline_text')}
149
+ headlineIcon={!isMaxNum && res.device_panel_schedule_add || undefined}
150
+ onHeadlineIconClick={() => onAddOrEditItem('add')}
151
+ loading={state.loading}
152
+ >
153
+ {randomTimeList.length > 0 ? renderList() : renderEmpty()}
154
+ </Page>
155
+ )
156
+ }
157
+
158
+ const styles = StyleSheet.create({
159
+ bg: {
160
+ marginTop: topBarHeight,
161
+ flex: 1,
162
+ },
163
+ emptyListCon: {
164
+ justifyContent: 'center',
165
+ alignItems: 'center',
166
+ marginTop: cx(30),
167
+ },
168
+ emptyImage: {
169
+ width: cx(225),
170
+ height: cx(198)
171
+ },
172
+ emptyNoTime: {
173
+ fontSize: cx(12),
174
+ color: '#000'
175
+ },
176
+ emptyTimeTip: {
177
+ fontSize: cx(12),
178
+ lineHeight: cx(17),
179
+ marginTop: cx(6),
180
+ width: '76%',
181
+ textAlign: 'center'
182
+ },
183
+ listContainer: {
184
+ bottom: cx(74)
185
+ },
186
+ categoryList: {
187
+ marginHorizontal: cx(24),
188
+ marginBottom: cx(12),
189
+ },
190
+ })
191
+
192
+ export default RandomTimeForPlugPage