@ledvance/group-ui-biz-bundle 1.0.0

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/.babelrc +31 -0
  2. package/.eslintignore +6 -0
  3. package/.eslintrc.js +27 -0
  4. package/.prettierignore +0 -0
  5. package/.prettierrc.js +1 -0
  6. package/.versionrc +5 -0
  7. package/package.json +73 -0
  8. package/rn-cli.config.js +8 -0
  9. package/src/modules/mood/AddMoodPage.tsx +826 -0
  10. package/src/modules/mood/DynamicMoodEditorPage.tsx +547 -0
  11. package/src/modules/mood/MoodItem.tsx +114 -0
  12. package/src/modules/mood/MoodPage.tsx +332 -0
  13. package/src/modules/mood/RecommendMoodItem.tsx +75 -0
  14. package/src/modules/mood/SceneAction.ts +459 -0
  15. package/src/modules/mood/SceneInfo.ts +886 -0
  16. package/src/modules/mood/StaticMoodEditorPage.tsx +251 -0
  17. package/src/modules/mood/tools.ts +12 -0
  18. package/src/modules/select/SelectPage.d.ts +12 -0
  19. package/src/modules/select/SelectPage.tsx +139 -0
  20. package/src/modules/time_schedule/Interface.ts +85 -0
  21. package/src/modules/time_schedule/ScheduleCard.tsx +111 -0
  22. package/src/modules/time_schedule/TimeScheduleActions.ts +81 -0
  23. package/src/modules/time_schedule/TimeScheduleDetailPage.tsx +704 -0
  24. package/src/modules/time_schedule/TimeSchedulePage.tsx +246 -0
  25. package/src/modules/timer/TimerAction.d.ts +12 -0
  26. package/src/modules/timer/TimerAction.ts +150 -0
  27. package/src/modules/timer/TimerPage.d.ts +2 -0
  28. package/src/modules/timer/TimerPage.tsx +351 -0
  29. package/src/navigation/Routers.d.ts +5 -0
  30. package/src/navigation/Routers.ts +97 -0
  31. package/src/navigation/tools.d.ts +0 -0
  32. package/src/navigation/tools.ts +0 -0
  33. package/src/res/GroupBizRes.ts +4 -0
  34. package/src/res/materialiconsFilledCancel.png +0 -0
  35. package/src/res/materialiconsFilledCancel@2x.png +0 -0
  36. package/src/res/materialiconsFilledCancel@3x.png +0 -0
  37. package/src/res/materialiconsOutlinedArrowsNavAddBox.png +0 -0
  38. package/src/res/materialiconsOutlinedArrowsNavAddBox@2x.png +0 -0
  39. package/src/res/materialiconsOutlinedArrowsNavAddBox@3x.png +0 -0
  40. package/tsconfig.json +51 -0
@@ -0,0 +1,704 @@
1
+ import React, { useCallback, useEffect, useMemo } from "react";
2
+ import { FlatList, ScrollView, StyleSheet, Text, View } from 'react-native'
3
+ import { useNavigation, useRoute } from '@react-navigation/native'
4
+ import Page from "@ledvance/base/src/components/Page";
5
+ import I18n from "@ledvance/base/src/i18n";
6
+ import TextField from "@ledvance/base/src/components/TextField";
7
+ import { cloneDeep, isEqual } from "lodash";
8
+ import { useCreation, useReactive } from "ahooks";
9
+ import { SwitchButton, TimerPicker, Utils } from "tuya-panel-kit";
10
+ import Spacer from "@ledvance/base/src/components/Spacer";
11
+ import LdvWeekView from '@ledvance/base/src/components/weekSelect'
12
+ import { loopText, showDialog } from "@ledvance/base/src/utils/common";
13
+ import Card from "@ledvance/base/src/components/Card";
14
+ import LdvSwitch from "@ledvance/base/src/components/ldvSwitch";
15
+ import ApplyForDeviceList from '@ledvance/base/src/components/ApplyForDeviceList'
16
+ import LampAdjustView from "@ledvance/base/src/components/LampAdjustView";
17
+ import { Timer } from './Interface'
18
+ import res from "@ledvance/base/src/res";
19
+ import { useGroupDevices, useMoods, useUAGroupInfo } from "@ledvance/base/src/models/modules/NativePropsSlice";
20
+ import { TimeSchedulePageParams } from "./TimeSchedulePage";
21
+ import { Result } from "@ledvance/base/src/models/modules/Result";
22
+ import DeleteButton from "@ledvance/base/src/components/DeleteButton";
23
+ import InfoText from "@ledvance/base/src/components/InfoText";
24
+ import SegmentControl from "@ledvance/base/src/components/segmentControl";
25
+ import { getHSVByHex, getHexByHSV } from "@ledvance/base/src/utils";
26
+ import MoodItem from "../mood/MoodItem";
27
+ import { dp2Obj, getRemoteSceneList, obj2Dp, stripDp2Obj, stripObj2Dp } from "../mood/SceneAction";
28
+ import FanAdjustView from "@ledvance/base/src/components/FanAdjustView";
29
+ import { SceneMode } from "../mood/SceneInfo";
30
+ import StripAdjustView, { ColorList } from "@ledvance/base/src/components/StripAdjustView"
31
+ import { WorkMode } from "@ledvance/base/src/utils/interface";
32
+ import { Buffer } from 'buffer'
33
+
34
+ const { convertX: cx } = Utils.RatioUtils;
35
+ const { toFixedString } = Utils.NumberUtils;
36
+ interface TimeScheduleDetailPageParams extends TimeSchedulePageParams {
37
+ mode: 'add' | 'edit'
38
+ timeSchedule: Timer,
39
+ modDeleteTimeSchedule: (mode: 'add' | 'edit' | 'del', timeSchedule: Timer, ids: string) => Promise<Result<any>>
40
+ refreshFn: () => void
41
+ }
42
+ const TimeScheduleDetailPage = () => {
43
+ const navigation = useNavigation()
44
+ const uaGroupInfo = useUAGroupInfo()
45
+ const [groupDevices] = useGroupDevices()
46
+ const [moods, setMoods] = useMoods()
47
+ const props = cloneDeep(useRoute().params) as TimeScheduleDetailPageParams
48
+ const state = useReactive({
49
+ timeSchedule: props.mode === 'add' ? newTimeSchedule() : cloneDeep(props.timeSchedule),
50
+ isManual: true, // manual ,mood
51
+ isColorMode: true,
52
+ switchLed: true, // light
53
+ switchSocket: true,
54
+ switchFan: true,
55
+ brightness: 100,
56
+ temperature: 0,
57
+ hsv: defaultHsv(),
58
+ stripState: defaultStripState(),
59
+ scene: '',
60
+ loading: false
61
+ })
62
+
63
+ const tabList = useCreation(() => {
64
+ const isSupportWhite = props.isSupportBrightness || props.isSupportTemperature
65
+ const tabs = [
66
+ { key: 1, title: I18n.getLang('add_new_static_mood_lights_schedule_switch_tab_color_text') },
67
+ { key: 0, title: I18n.getLang('add_new_static_mood_lights_schedule_switch_tab_white_text') },
68
+ { key: 3, title: I18n.getLang('add_new_dynamic_mood_strip_lights_schedule_switch_tab_combination_text') },
69
+ ]
70
+ if (!isSupportWhite) {
71
+ return tabs.filter(tab => tab.key !== 0)
72
+ }
73
+ if (!props.isSupportColor) {
74
+ return tabs.filter(tab => tab.key === 0)
75
+ }
76
+ return tabs
77
+ }, [])
78
+
79
+ const getSceneByDp = (sceneDp: string) => {
80
+ if (props.sceneDataDp2Obj) {
81
+ return props.sceneDataDp2Obj(sceneDp)
82
+ }
83
+ const isFantasy = props.isStringLight || props.isStripLight
84
+ return isFantasy ? stripDp2Obj(Buffer.from(sceneDp, 'base64').toString('hex'), props.isStringLight) : dp2Obj(sceneDp, props.isSupportFan, props.isSupportUVC)
85
+ }
86
+
87
+ const getDpByScene = (scene: any) => {
88
+ if (props.sceneDataObj2Dp) {
89
+ return props.sceneDataObj2Dp(scene)
90
+ }
91
+ const isFantasy = props.isStringLight || props.isStripLight
92
+ return isFantasy ? Buffer.from(stripObj2Dp(scene, props.isStringLight), 'hex').toString('base64') : obj2Dp(scene, props.isSupportFan, props.isSupportUVC)
93
+ }
94
+
95
+ const modeId = useMemo(() => {
96
+ if (state.scene) {
97
+ return getSceneByDp(state.scene).id
98
+ }
99
+ return -1
100
+ }, [state.scene])
101
+
102
+ useEffect(() => {
103
+ if (!(moods && moods.length) && props.sceneDataCode) {
104
+ getRemoteSceneList(uaGroupInfo.tyGroupId.toString(), {
105
+ isSupportColor: props.isSupportColor,
106
+ isSupportTemperature: props.isSupportTemperature,
107
+ isSupportBrightness: props.isSupportBrightness,
108
+ isStringLight: props.isStringLight,
109
+ isStripLight: props.isStripLight
110
+ }).then(res => {
111
+ if (res.success && res.data) {
112
+ setMoods(res.data)
113
+ if (props.mode === 'add') state.scene = getDpByScene(res.data[0])
114
+ }
115
+ })
116
+ }
117
+ }, [])
118
+
119
+ useEffect(() => {
120
+ if (props.mode === 'edit' && props.timeSchedule) {
121
+ const dps = JSON.parse(props.timeSchedule.dps)
122
+ if (props.switchLedCode && dps.hasOwnProperty(props.switchLedCode)) {
123
+ state.switchLed = dps[props.switchLedCode]
124
+ }
125
+ if (props.tempValueCode && dps.hasOwnProperty(props.tempValueCode)) {
126
+ state.temperature = Math.round(dps[props.tempValueCode] / 10)
127
+ state.isColorMode = false
128
+ }
129
+ if (props.brightValueCode && dps.hasOwnProperty(props.brightValueCode)) {
130
+ state.brightness = Math.round(dps[props.brightValueCode] / 10)
131
+ state.isColorMode = false
132
+ }
133
+ if (props.colorDataCode && dps.hasOwnProperty(props.colorDataCode)) {
134
+ if (props.colorDataDp2Obj) {
135
+ const color = props.colorDataDp2Obj(dps[props.colorDataCode])
136
+ state.hsv = {
137
+ h: color.h,
138
+ s: Math.round(color.s / 10),
139
+ v: Math.round(color.v / 10),
140
+ }
141
+ return
142
+ }
143
+ const hsv = getHSVByHex(dps[props.colorDataCode])
144
+ state.hsv = {
145
+ h: hsv.h,
146
+ s: Math.round(hsv.s / 10),
147
+ v: Math.round(hsv.v / 10),
148
+ }
149
+ }
150
+ if (props.sceneDataCode && dps.hasOwnProperty(props.sceneDataCode)) {
151
+ if (dps[props.sceneDataCode]) {
152
+ state.scene = dps[props.sceneDataCode]
153
+ } else {
154
+ state.scene = getDpByScene(moods[0])
155
+ }
156
+ state.isManual = false
157
+ }
158
+ if (props.drawToolDataCode && dps.hasOwnProperty(props.drawToolDataCode)) {
159
+ if (props.drawToolDataDp2Obj && dps[props.drawToolDataCode]) {
160
+ const { hsv, brightness, temperature, stripState, isColor } = props.drawToolDataDp2Obj(dps[props.drawToolDataCode])
161
+ state.brightness = brightness
162
+ state.temperature = temperature
163
+ state.hsv = cloneDeep(hsv)
164
+ if (stripState) {
165
+ state.stripState = cloneDeep(stripState)
166
+ }
167
+ state.isColorMode = !!isColor
168
+ }
169
+ }
170
+ } else {
171
+ if (moods && moods.length) {
172
+ state.scene = getDpByScene(moods[0])
173
+ }
174
+ }
175
+ }, [props.mode, JSON.stringify(props.timeSchedule), JSON.stringify(moods)])
176
+
177
+
178
+ const getFormateTime = useCallback((time: number | string) => {
179
+ if (typeof time === 'number') {
180
+ return `${toFixedString(Math.trunc(time / 60), 2)}:${toFixedString(time % 60, 2)}`
181
+ }
182
+ if (typeof time === 'string') {
183
+ const t = time.split(':')
184
+ return Number(t[0]) * 60 + Number(t[1])
185
+ }
186
+ return time
187
+ }, [])
188
+
189
+ const getActionOnOff = useMemo(() => {
190
+ const off = [] as string[]
191
+ const on = [] as string[]
192
+ if (props.switchLedCode) {
193
+ if (state.switchLed) {
194
+ on.push(I18n.getLang('light_sources_tile_tw_lighting_headline'))
195
+ } else {
196
+ off.push(I18n.getLang('light_sources_tile_tw_lighting_headline'))
197
+ }
198
+ }
199
+ if (props.switchSocket) {
200
+ if (state.switchSocket) {
201
+ on.push(I18n.getLang('feature_summary_action_component_5'))
202
+ } else {
203
+ off.push(I18n.getLang('feature_summary_action_component_5'))
204
+ }
205
+ }
206
+ if (props.switchFan) {
207
+ if (state.switchFan) {
208
+ on.push(I18n.getLang('add_new_dynamic_mood_ceiling_fan_field_headline'))
209
+ } else {
210
+ off.push(I18n.getLang('add_new_dynamic_mood_ceiling_fan_field_headline'))
211
+ }
212
+ }
213
+ return {
214
+ on, off
215
+ }
216
+ }, [state.switchLed, state.switchSocket, state.switchFan])
217
+
218
+ const getActions = useCallback(() => {
219
+ const actions = {
220
+ time: state.timeSchedule.time,
221
+ dps: {}
222
+ }
223
+ if (state.isManual) {
224
+ if (state.switchLed) {
225
+ if (props.drawToolDataObj2Dp && props.drawToolDataCode) {
226
+ actions.dps[props.drawToolDataCode] = props.drawToolDataObj2Dp({
227
+ hsv: state.hsv,
228
+ stripState: state.stripState,
229
+ brightness: state.brightness,
230
+ temperature: state.temperature,
231
+ isColor: state.isColorMode
232
+ })
233
+ const whiteMode = props.isStringLight ? !state.isColorMode : state.stripState.activeKey === 0
234
+ actions.dps[props.workModeCode] = whiteMode ? WorkMode.White : WorkMode.Colour
235
+
236
+ } else if (state.isColorMode) {
237
+ if (props.colorDataCode) {
238
+ const hsv = {
239
+ ...state.hsv,
240
+ s: state.hsv.s * 10,
241
+ v: state.hsv.v * 10,
242
+ }
243
+ if (props.colorDataObj2Dp) {
244
+ actions.dps[props.colorDataCode] = props.colorDataObj2Dp(hsv)
245
+ } else {
246
+ const hex = getHexByHSV(hsv)
247
+ actions.dps[props.colorDataCode] = hex
248
+ }
249
+ }
250
+ actions.dps[props.workModeCode] = WorkMode.Colour
251
+ } else {
252
+ if (props.brightValueCode) {
253
+ actions.dps[props.brightValueCode] = state.brightness * 10
254
+ }
255
+ if (props.tempValueCode) {
256
+ actions.dps[props.tempValueCode] = state.temperature * 10
257
+ }
258
+ actions.dps[props.workModeCode] = WorkMode.White
259
+ }
260
+ }
261
+ if (props.switchLedCode) {
262
+ actions.dps[props.switchLedCode] = state.switchLed
263
+ }
264
+ } else {
265
+ if (props.sceneDataCode) {
266
+ actions.dps[props.sceneDataCode] = state.scene
267
+ }
268
+ actions.dps[props.workModeCode] = WorkMode.Scene
269
+ if (props.switchLedCode) {
270
+ actions.dps[props.switchLedCode] = true
271
+ }
272
+ }
273
+ console.log(state, '< --- state')
274
+ console.log(actions, '< --- actions')
275
+ return JSON.stringify(actions)
276
+ }, [state.timeSchedule.time, state.switchLed, state.brightness, state.temperature])
277
+
278
+ const isModify = useMemo(() => {
279
+ const schedule = props.mode === 'add' ? newTimeSchedule() : props.timeSchedule
280
+ const before = {
281
+ aliasName: schedule.aliasName,
282
+ time: schedule.time,
283
+ isAppPush: schedule.isAppPush,
284
+ loops: schedule.loops
285
+ }
286
+ const now = {
287
+ aliasName: state.timeSchedule.aliasName,
288
+ time: state.timeSchedule.time,
289
+ isAppPush: state.timeSchedule.isAppPush,
290
+ loops: state.timeSchedule.loops
291
+ }
292
+ if (props.mode === 'add') {
293
+ return isEqual(before, now)
294
+ } else {
295
+ return isEqual({
296
+ ...before,
297
+ dps: JSON.stringify({
298
+ time: before.time,
299
+ dps: JSON.parse(schedule.dps)
300
+ })
301
+ }, {
302
+ ...now,
303
+ dps: getActions()
304
+ })
305
+ }
306
+ }, [JSON.stringify(state)])
307
+
308
+ const allowSubmit = useMemo(() => {
309
+ return !!(state.timeSchedule.aliasName.length && state.timeSchedule.aliasName.length < 33) && !isModify
310
+ }, [state.timeSchedule.aliasName, isModify])
311
+
312
+ const gradientMode = useMemo(() => (
313
+ props.isStringLight ? SceneMode.StringGradient : props.isStripLight ? SceneMode.StripGradient : SceneMode.SourceGradient
314
+ ), [props.isStringLight, props.isStripLight, SceneMode])
315
+
316
+ return (
317
+ <Page
318
+ backText={I18n.getLang('motion_detection_add_time_schedule_system_back_text')}
319
+ headlineText={I18n.getLang(props.mode === 'add' ? 'motion_detection_add_time_schedule_headline_text' : 'edit_timeschedule_headline_text')}
320
+ rightButtonIcon={allowSubmit ? res.ic_check : res.ic_uncheck}
321
+ rightButtonIconClick={async () => {
322
+ getActions()
323
+ return
324
+ if (!allowSubmit || state.loading) return
325
+ state.loading = true
326
+ const res = await props.modDeleteTimeSchedule(props.mode, {
327
+ ...state.timeSchedule,
328
+ status: 1,
329
+ dps: getActions()
330
+ }, '')
331
+ console.log(res, '< ---- resss')
332
+ state.loading = false
333
+ if (res.success) {
334
+ props.refreshFn()
335
+ navigation.goBack()
336
+ }
337
+ }}
338
+ backDialogTitle={I18n.getLang('cancel_dialog_leave_unsaved_titel')}
339
+ backDialogContent={I18n.getLang('cancel_dialog_leave_unsaved_timeschedule_note')}
340
+ showBackDialog={!isModify}
341
+ loading={state.loading}
342
+ >
343
+ <ScrollView nestedScrollEnabled={true}>
344
+ <TextField
345
+ style={styles.cardContainer}
346
+ value={state.timeSchedule.aliasName}
347
+ showError={state.timeSchedule.aliasName?.length > 32}
348
+ maxLength={33}
349
+ errorText={I18n.getLang('add_new_dynamic_mood_alert_text')}
350
+ placeholder={I18n.getLang('add_new_trigger_time_inputfield_value_text')}
351
+ onChangeText={(t: string) => {
352
+ state.timeSchedule.aliasName = t;
353
+ }}
354
+ />
355
+
356
+ {/* pick */}
357
+ <TimerPicker
358
+ itemTextColor='#aeadb5'
359
+ style={{ paddingVertical: cx(0), marginVertical: cx(0) }}
360
+ is12Hours={false}
361
+ singlePicker={true}
362
+ startTime={getFormateTime(state.timeSchedule.time) as number}
363
+ symbol={''}
364
+ onTimerChange={(startTime) => {
365
+ state.timeSchedule.time = getFormateTime(startTime) as string
366
+ }} />
367
+ <LdvWeekView
368
+ value={state.timeSchedule.loops.split('').map(Number)}
369
+ style={styles.cardContainer}
370
+ onSelect={(index: number) => {
371
+ const rawIndex = index - 1
372
+ const weeks = state.timeSchedule.loops.split('')
373
+ weeks[rawIndex] = weeks[rawIndex] === '1' ? '0' : '1'
374
+ state.timeSchedule.loops = weeks.join('')
375
+ }} />
376
+ <Spacer />
377
+ <Text style={styles.cardContainer}>{loopText(state.timeSchedule.loops.split(''))}</Text>
378
+ <Spacer height={cx(30)} />
379
+
380
+ {/* device state */}
381
+ <Text style={[styles.itemTitle, styles.cardContainer]}>{I18n.getLang('timeschedule_add_schedule_subheadline2_text')}</Text>
382
+ <Spacer height={cx(10)} />
383
+ {props.isSupportMood && <SegmentControl
384
+ title1={I18n.getLang('timeschedule_add_schedule_switch_tab_manual_text')}
385
+ title2={I18n.getLang('timeschedule_add_schedule_switch_tab_mood_text')}
386
+ isFirst={state.isManual}
387
+ setIsFirst={(v: boolean) => state.isManual = v}
388
+ />}
389
+ <Spacer height={cx(10)} />
390
+ {state.isManual ?
391
+ <>
392
+ {!!props.switchLedCode && <Card
393
+ style={styles.cardContainer}
394
+ >
395
+ <LdvSwitch
396
+ title={I18n.getLang('light_sources_tile_tw_lighting_headline')}
397
+ color={'#fff'}
398
+ colorAlpha={1}
399
+ enable={state.switchLed}
400
+ setEnable={(enable: boolean) => {
401
+ state.switchLed = enable
402
+ }}
403
+ />
404
+ {state.switchLed && (props.isStripLight ?
405
+ <StripAdjustView
406
+ lampTabs={tabList}
407
+ onColorDiskChange={(color, idx: K) => {
408
+ state.stripState = {
409
+ ...state.stripState,
410
+ colors: color,
411
+ colorDiskActiveKey: idx
412
+ }
413
+ }}
414
+ colorDiskActiveKey={state.stripState.colorDiskActiveKey}
415
+ activeKey={state.stripState.activeKey}
416
+ onActiveKeyChange={(v) => {
417
+ state.stripState = {
418
+ ...state.stripState,
419
+ activeKey: Number(v) as K
420
+ }
421
+ }}
422
+ isSupportTemperature={props.isSupportTemperature}
423
+ isSupportBrightness={props.isSupportBrightness}
424
+ h={state.hsv.h} s={state.hsv.s} v={state.hsv.v}
425
+ onHSVChange={(h, s, v) => { state.hsv = { h, s, v } }}
426
+ onHSVChangeComplete={(h, s, v) => { state.hsv = { h, s, v } }}
427
+ colorTemp={state.temperature}
428
+ brightness={state.brightness}
429
+ onCCTChange={() => { }}
430
+ onCCTChangeComplete={(cct) => { state.temperature = cct }}
431
+ onBrightnessChange={() => { }}
432
+ onBrightnessChangeComplete={(bright) => { state.brightness = bright }}
433
+ /> :
434
+ <LampAdjustView
435
+ reserveSV={true}
436
+ isSupportBrightness={props.isSupportBrightness}
437
+ isSupportColor={props.isSupportColor}
438
+ isSupportTemperature={props.isSupportTemperature}
439
+ isColorMode={state.isColorMode}
440
+ setIsColorMode={(v) => { state.isColorMode = v }}
441
+ h={state.hsv.h} s={state.hsv.s} v={state.hsv.v}
442
+ colorTemp={state.temperature}
443
+ brightness={state.brightness}
444
+ onHSVChangeComplete={(h, s, v) => { state.hsv = { h, s, v } }}
445
+ onHSVChange={(h, s, v) => { state.hsv = { h, s, v } }}
446
+ onCCTChangeComplete={(cct) => { state.temperature = cct }}
447
+ onCCTChange={(cct) => { state.temperature = cct }}
448
+ onBrightnessChangeComplete={(bright) => { state.brightness = bright }}
449
+ onBrightnessChange={(bright) => { state.brightness = bright }}
450
+ />)}
451
+ <ApplyForDeviceList
452
+ devices={cloneDeep(groupDevices)}
453
+ />
454
+ <Spacer height={cx(16)} />
455
+ </Card>}
456
+
457
+ {/* socket */}
458
+ {!!props.switchSocket && <Card
459
+ style={styles.cardContainer}
460
+ >
461
+ <LdvSwitch
462
+ title={I18n.getLang('feature_summary_action_component_5')}
463
+ color={'#fff'}
464
+ colorAlpha={1}
465
+ enable={state.switchSocket}
466
+ setEnable={(enable: boolean) => {
467
+ state.switchSocket = enable
468
+ }}
469
+ />
470
+ <ApplyForDeviceList
471
+ devices={cloneDeep(groupDevices)}
472
+ />
473
+ <Spacer height={cx(16)} />
474
+ </Card>}
475
+
476
+ {/* Fan */}
477
+ {props.isSupportFan && <FanAdjustView
478
+ fanEnable={state.switchFan}
479
+ fanSpeed={1}
480
+ onFanSpeedChangeComplete={() => { }}
481
+ onFanSwitch={(enable) => {
482
+ state.switchFan = enable
483
+ }}
484
+ isSupportMode={true}
485
+ />}
486
+ </> :
487
+ <FlatList
488
+ data={cloneDeep(moods)}
489
+ renderItem={({ item }) => {
490
+ return (
491
+ <MoodItem
492
+ enable={modeId === item.id}
493
+ mood={item}
494
+ type={gradientMode === item.mode ? 'gradient' : 'separate'}
495
+ onSwitch={async _ => {
496
+ state.scene = getDpByScene(item)
497
+ }} />
498
+ )
499
+ }}
500
+ ListHeaderComponent={() => (<Spacer height={cx(10)} />)}
501
+ ItemSeparatorComponent={() => (<Spacer />)}
502
+ ListFooterComponent={() => (<View style={{ marginHorizontal: cx(8) }}>
503
+ <Spacer height={cx(16)} />
504
+ <ApplyForDeviceList
505
+ devices={cloneDeep(groupDevices)}
506
+ />
507
+ </View>)}
508
+ keyExtractor={item => `${item.id}`} />
509
+ }
510
+ <Spacer height={cx(30)} />
511
+ <Text style={[styles.itemTitle, styles.cardContainer]}>{I18n.getLang('timeschedule_add_schedule_subheadline4_text')}</Text>
512
+ <View style={[styles.switchButton, styles.cardContainer]}>
513
+ <Text style={styles.text}>{I18n.getLang('timeschedule_add_schedule_text2')}</Text>
514
+ <SwitchButton
515
+ value={state.timeSchedule.isAppPush}
516
+ onValueChange={value => {
517
+ state.timeSchedule.isAppPush = value
518
+ }} />
519
+ </View>
520
+ <Spacer />
521
+
522
+ {/* summary */}
523
+ <Text style={[styles.itemTitle, styles.cardContainer]}>{I18n.getLang('add_sleepschedule_one_source_subheadline4_text')}</Text>
524
+ <Spacer height={cx(10)} />
525
+ <View style={styles.summaryContainer}>
526
+ <InfoText
527
+ icon={res.summary_icon1}
528
+ text={I18n.getLang('feature_summary_frequency_headline')}
529
+ iconStyle={styles.summaryImg}
530
+ textStyle={styles.leftTitle}
531
+ style={styles.summaryLeft}
532
+ />
533
+ <View style={styles.summaryRight}>
534
+ <Text style={styles.rightItem}>{loopText(state.timeSchedule.loops.split(''), state.timeSchedule.time)}</Text>
535
+ </View>
536
+ </View>
537
+ <View style={styles.summaryContainer}>
538
+ <InfoText
539
+ icon={res.summary_icon2}
540
+ text={I18n.getLang('feature_summary_time_headline')}
541
+ iconStyle={styles.summaryImg}
542
+ textStyle={styles.leftTitle}
543
+ style={styles.summaryLeft}
544
+ />
545
+ <View style={styles.summaryRight}>
546
+ <Text style={styles.rightItem}>{state.timeSchedule.time}</Text>
547
+ </View>
548
+ </View>
549
+ <View style={[styles.summaryContainer, { alignItems: 'flex-start' }]}>
550
+ <InfoText
551
+ icon={res.summary_icon3}
552
+ text={I18n.getLang('motion_detection_add_time_schedule_actions_text1')}
553
+ iconStyle={styles.summaryImg}
554
+ textStyle={styles.leftTitle}
555
+ style={styles.summaryLeft}
556
+ />
557
+ <View style={{ marginLeft: cx(16) }}>
558
+ {!!getActionOnOff.on.length && <View>
559
+ <Text style={{ marginLeft: cx(5) }}>{I18n.getLang('feature_summary_action_txt_1')}</Text>
560
+ <View style={{ flexDirection: 'row' }}>{
561
+ getActionOnOff.on.map(item => (
562
+ <View style={[styles.summaryRight, { marginLeft: cx(5), marginBottom: cx(5) }]}
563
+ key={item}>
564
+ <Text style={[styles.rightItem]}
565
+ >{item}</Text>
566
+ </View>
567
+ ))
568
+ }</View>
569
+ </View>}
570
+ {!!getActionOnOff.off.length && <View>
571
+ <Text style={{ marginLeft: cx(5) }}>{I18n.getLang('feature_summary_action_txt_2')}</Text>
572
+ <View style={{ flexDirection: 'row' }}>{
573
+ getActionOnOff.off.map(item => (
574
+ <View style={[styles.summaryRight, { marginLeft: cx(5), marginBottom: cx(5) }]}
575
+ key={item}>
576
+ <Text style={[styles.rightItem]}
577
+ >{item}</Text>
578
+ </View>
579
+ ))}
580
+ </View>
581
+ </View>}
582
+ </View>
583
+ </View>
584
+ <Spacer height={cx(30)} />
585
+
586
+ {/* delete */}
587
+ {props.mode === 'edit' && <View style={{ marginHorizontal: cx(24) }}>
588
+ <DeleteButton
589
+ text={I18n.getLang('edit_timeschedule_bttn_text')}
590
+ onPress={() => {
591
+ showDialog({
592
+ method: 'confirm',
593
+ title: I18n.getLang('cancel_dialog_delete_item_timeschedule_titel'),
594
+ subTitle: I18n.getLang('cancel_dialog_delete_item_timeschedule_description'),
595
+ onConfirm: async (_, { close }) => {
596
+ state.loading = true
597
+ close()
598
+ const res = await props.modDeleteTimeSchedule('del', {
599
+ ...state.timeSchedule,
600
+ status: 2
601
+ }, state.timeSchedule.id.toString())
602
+ state.loading = false
603
+ if (res.success) {
604
+ props.refreshFn()
605
+ navigation.goBack()
606
+ }
607
+ },
608
+ })
609
+ }}
610
+ />
611
+ <Spacer />
612
+ </View>}
613
+ </ScrollView>
614
+ </Page>
615
+ )
616
+ }
617
+
618
+ const newTimeSchedule = () => {
619
+ return {
620
+ status: 1,
621
+ loops: '0000000',
622
+ isAppPush: false,
623
+ aliasName: '',
624
+ time: `${toFixedString(new Date().getHours(), 2)}:${toFixedString(new Date().getMinutes(), 2)}`,
625
+ dps: '',
626
+ id: -1
627
+ }
628
+ }
629
+
630
+ const defaultHsv = () => {
631
+ return {
632
+ h: 0,
633
+ s: 50,
634
+ v: 80
635
+ }
636
+ }
637
+ type K = 0 | 1 | 3
638
+ export interface StripState {
639
+ colorDiskActiveKey: number
640
+ colors: string[]
641
+ activeKey: K
642
+ }
643
+
644
+ const defaultStripState = (): StripState => {
645
+ return {
646
+ colorDiskActiveKey: 0,
647
+ colors: ColorList[0],
648
+ activeKey: 1,
649
+ }
650
+ }
651
+
652
+ const styles = StyleSheet.create({
653
+ cardContainer: {
654
+ marginHorizontal: cx(24)
655
+ },
656
+ itemTitle: {
657
+ color: '#000',
658
+ fontSize: cx(16),
659
+ fontWeight: 'bold',
660
+ fontFamily: 'helvetica_neue_lt_std_bd',
661
+ },
662
+ summaryContainer: {
663
+ flexDirection: 'row',
664
+ justifyContent: 'flex-start',
665
+ marginBottom: cx(10),
666
+ marginHorizontal: cx(24)
667
+ },
668
+ summaryImg: {
669
+ height: cx(12),
670
+ width: cx(12),
671
+ tintColor: '#000'
672
+ },
673
+ summaryLeft: {
674
+ flexDirection: 'row',
675
+ alignItems: 'center',
676
+ minWidth: cx(90),
677
+ },
678
+ leftTitle: {
679
+ fontSize: cx(14),
680
+ color: '#000',
681
+ marginTop: 0
682
+ },
683
+ summaryRight: {
684
+ flexDirection: 'column',
685
+ marginLeft: cx(21),
686
+ backgroundColor: '#cbcbcb',
687
+ borderRadius: cx(16),
688
+ },
689
+ rightItem: {
690
+ paddingHorizontal: cx(12),
691
+ color: '#000',
692
+ },
693
+ switchButton: {
694
+ flexDirection: 'row',
695
+ alignItems: 'center',
696
+ justifyContent: 'space-between',
697
+ marginBottom: cx(10),
698
+ },
699
+ text: {
700
+ color: '#000',
701
+ },
702
+ })
703
+
704
+ export default TimeScheduleDetailPage