@ledvance/ui-biz-bundle 1.1.141 → 1.1.143

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 (31) hide show
  1. package/package.json +1 -1
  2. package/src/hooks/DeviceDpStateHooks.ts +1 -1
  3. package/src/modules/flags/FlagPage.tsx +4 -1
  4. package/src/modules/mood/MixMood/RecommendMixMoodItem.tsx +1 -1
  5. package/src/modules/mood/RecommendMoodItem.tsx +1 -1
  6. package/src/modules/timeSchedule/TimeScheduleEditpage.tsx +1 -1
  7. package/src/modules/timer/TimerPage.tsx +1 -1
  8. package/src/newModules/biorhythm/BiorhythmActions.ts +403 -451
  9. package/src/newModules/biorhythm/BiorhythmBean.ts +230 -230
  10. package/src/newModules/biorhythm/BiorhythmEditPage.tsx +18 -20
  11. package/src/newModules/biorhythm/BiorhythmPage.tsx +653 -698
  12. package/src/newModules/biorhythm/IconSelect.tsx +88 -88
  13. package/src/newModules/biorhythm/Router.ts +33 -33
  14. package/src/newModules/biorhythm/iconListData.ts +30 -30
  15. package/src/newModules/biorhythm/pIdList.ts +35 -35
  16. package/src/newModules/energyConsumption/EnergyConsumptionActions.ts +66 -28
  17. package/src/newModules/energyConsumption/EnergyConsumptionCard.tsx +172 -0
  18. package/src/newModules/energyConsumption/EnergyConsumptionChart.tsx +204 -118
  19. package/src/newModules/energyConsumption/EnergyConsumptionDetail.tsx +3 -0
  20. package/src/newModules/energyConsumption/EnergyConsumptionPage.tsx +16 -0
  21. package/src/newModules/energyConsumption/co2Data.ts +5 -0
  22. package/src/newModules/energyConsumption/component/NewBarChart.tsx +172 -168
  23. package/src/newModules/energyConsumption/component/PowerLineChart.tsx +108 -0
  24. package/src/newModules/energyConsumption/res/energy-chart.png +0 -0
  25. package/src/newModules/energyConsumption/res/index.ts +3 -0
  26. package/src/newModules/fixedTime/FixedTimeDetailPage.tsx +1 -1
  27. package/src/newModules/mood/RecommendMoodItem.tsx +1 -1
  28. package/src/newModules/sleepWakeUp/SleepWakeUpDetailPage.tsx +1 -1
  29. package/src/newModules/swithInching/SwithInching.tsx +1 -1
  30. package/src/newModules/timeSchedule/TimeScheduleActions.ts +12 -12
  31. package/tsconfig.json +73 -46
@@ -1,698 +1,653 @@
1
- import React, { useCallback, useEffect, useMemo } from 'react'
2
- import { FlatList, Image, Linking, ScrollView, Switch, Text, TouchableOpacity, View } from 'react-native'
3
- import { useNavigation } from '@react-navigation/native'
4
- import { useDebounceFn, useReactive, useUpdateEffect } from 'ahooks'
5
- import {
6
- BiorhythmBean,
7
- BiorhythmGradientType,
8
- colorTemperatureValue,
9
- getDefBiorhythmUIState,
10
- Plan,
11
- } from './BiorhythmBean'
12
- import { Dialog, Modal, Utils } from 'tuya-panel-kit'
13
- import { cloneDeep, sortBy } from 'lodash'
14
- import iconList from './iconListData'
15
- import pIdList from './pIdList'
16
- import {
17
- useDeviceInfo,
18
- useSystemTimeFormate,
19
- } from '@ledvance/base/src/models/modules/NativePropsSlice'
20
- import I18n from '@ledvance/base/src/i18n'
21
- import res from '@ledvance/base/src/res'
22
- import { ui_biz_routerKey } from "../../navigation/Routers";
23
- import { cctToColor } from '@ledvance/base/src/utils/cctUtils'
24
- import { BiorhythmEditPageParams } from './BiorhythmEditPage'
25
- import { useBiorhythm } from './BiorhythmActions'
26
- import { convertMinutesTo12HourFormat, showDialog as showCommonDialog } from '@ledvance/base/src/utils/common'
27
- import Page from '@ledvance/base/src/components/Page'
28
- import Card from '@ledvance/base/src/components/Card'
29
- import Spacer from '@ledvance/base/src/components/Spacer'
30
- import DeleteButton from '@ledvance/base/src/components/DeleteButton'
31
- import { useParams } from '@ledvance/base/src/hooks/Hooks'
32
- import ThemeType from '@ledvance/base/src/config/themeType'
33
- import { useConflictTask } from 'hooks/DeviceDpStateHooks'
34
- import RhythmsCircle from './circular/RhythmsCircle'
35
-
36
- const cx = Utils.RatioUtils.convertX
37
- const { withTheme } = Utils.ThemeUtils
38
- const width = Utils.RatioUtils.width
39
-
40
- interface UIState extends BiorhythmBean {
41
- showGradientTypeSelectModal: boolean;
42
- flag: symbol;
43
- weekString: string,
44
- timeSchedule: any[]
45
- loading: boolean
46
- }
47
-
48
- export interface BiorhythmPageParams {
49
- biorhythmDpCode: string
50
- conflictDps: {
51
- randomTimeDpCode?: string
52
- fixedTimeDpCode?: string
53
- sleepDpCode?: string
54
- wakeUpDpCode?: string
55
- }
56
- isSupportTemperature: boolean
57
- isSupportBrightness: boolean
58
- isMixLight?: boolean
59
- }
60
-
61
- const BiorhythmPage = (props: { theme?: ThemeType }) => {
62
- const params = useParams<BiorhythmPageParams>()
63
- const navigation = useNavigation()
64
- const [biorhythm, setBiorhythm] = useBiorhythm(params.biorhythmDpCode)
65
- const deviceInfo = useDeviceInfo()
66
- const { productId } = deviceInfo
67
- const is24Hour = useSystemTimeFormate()
68
- const devicesJudge = pIdList.some(val => val === productId)
69
- const [checkConflict, resolveConflict] = useConflictTask(params.conflictDps)
70
-
71
- const state = useReactive<UIState>({
72
- ...biorhythm,
73
- showGradientTypeSelectModal: false,
74
- flag: Symbol(),
75
- weekString: '',
76
- timeSchedule: [],
77
- loading: false
78
- })
79
-
80
- const timeImg = useMemo(() => {
81
- if (is24Hour) {
82
- return devicesJudge ? res.ic_warning_amber_sun : res.ic_warning_amber_new
83
- } else {
84
- return devicesJudge ? res.ic_warning_amber_sun_12 : res.ic_warning_amber_new_12
85
- }
86
- }, [is24Hour, devicesJudge])
87
-
88
- const showGradientTypeSelectModal = useCallback((show: boolean) => {
89
- state.showGradientTypeSelectModal = show
90
- }, [])
91
-
92
- const onPlanEdited = useCallback((isAdd: boolean, newPlan: Plan) => {
93
- if (isAdd) {
94
- state.planList.push(newPlan)
95
- state.planList = sortBy(state.planList, p => p.time)
96
- } else {
97
- state.planList = state.planList.map(plan => (plan.index === newPlan.index ? newPlan : plan))
98
- }
99
- state.flag = Symbol()
100
- }, [])
101
-
102
- const onPlanDelete = useCallback((id: number) => {
103
- state.planList = state.planList.filter(plan => plan.index !== id)
104
- state.flag = Symbol()
105
- }, [])
106
-
107
- const requestSetBiorhythm = useCallback(async (pushFeature: boolean = true) => {
108
- state.loading = true
109
- const planList = state.planList?.map(item => { return { ...item, icon: `${item.icon}` } })
110
- .sort((a, b) => a.time - b.time);
111
- const res = await setBiorhythm(cloneDeep({ ...state, planList }), pushFeature)
112
- state.loading = false
113
- if (res.success) {
114
- console.log('设置生物节律 OK')
115
- }
116
- }, [])
117
-
118
- useUpdateEffect(() => {
119
- if (state.planList?.length === 0) {
120
- const data = getDefBiorhythmUIState()
121
- data.planList = data.planList?.map(item => {
122
- return { ...item, icon: `${item.icon}` }
123
- })
124
- setBiorhythm(cloneDeep(data)).then()
125
- }
126
- }, [state.planList])
127
-
128
- const setTimer = value => {
129
- switch (value) {
130
- case 'Sunrise':
131
- return I18n.getLang('bio_ryhthm_default_field_text')
132
- case 'Wake Up':
133
- return I18n.getLang('bio_ryhthm_default_field_text2')
134
- case 'Sunlight':
135
- return I18n.getLang('bio_ryhthm_default_field_text3')
136
- case 'Comfortable':
137
- return I18n.getLang('bio_ryhthm_default_field_text4')
138
- case 'Night light':
139
- return I18n.getLang('bio_ryhthm_default_field_text5')
140
- default:
141
- return value
142
- }
143
- }
144
-
145
- const minimumEnable = useCallback((plan: Plan) => {
146
- let enable = false
147
- state.planList.filter(p => p.index !== plan.index).forEach(item => {
148
- const diff = Math.abs(plan.time - item.time)
149
- if (diff < 15) enable = true
150
- })
151
- return enable
152
- }, [state.planList])
153
-
154
- const nameRepeat = useCallback((plan: Plan) => {
155
- return !!state.planList.filter(p => p.index !== plan.index).find(p => p.name === plan.name)
156
- }, [state.planList])
157
-
158
- const showDeleteBtn = useMemo(() => {
159
- return state.planList?.length > 1
160
- }, [state.planList?.length])
161
-
162
- const { run } = useDebounceFn(requestSetBiorhythm, { wait: 300 })
163
-
164
- useUpdateEffect(() => {
165
- run()
166
- }, [state.flag])
167
-
168
- const replaceImg = (img) => {
169
- const item = iconList?.find(val => val.id === Number(img))
170
- switch (img) {
171
- case 'rhythm_icon1':
172
- case '31':
173
- return { icon: res.biorhythom_icon1, iconId: 1 }
174
- case 'rhythm_icon2':
175
- case '33':
176
- return { icon: res.biorhythom_icon5, iconId: 5 }
177
- case 'rhythm_icon3':
178
- case '35':
179
- return { icon: res.biorhythom_icon2, iconId: 2 }
180
- case 'rhythm_icon4':
181
- case '32':
182
- return { icon: res.biorhythom_icon9, iconId: 9 }
183
- case 'rhythm_icon12':
184
- case '39':
185
- return { icon: res.biorhythom_icon3, iconId: 3 }
186
- default:
187
- return { icon: item?.icon, iconId: item?.id }
188
- }
189
- }
190
-
191
- useEffect(() => {
192
- const weeks = biorhythm.repeatPeriod.filter(it => it.enabled).map(it => it.title)
193
-
194
- if (weeks.length > 0) {
195
- if (weeks.length === 7) {
196
- state.weekString = I18n.getLang('motion_detection_time_schedule_notifications_field_weekdays_text4')
197
- } else {
198
- state.weekString = I18n.formatValue('timeschedule_add_schedule_text', weeks.join(', '))
199
- }
200
- } else {
201
- state.weekString = I18n.getLang('motion_detection_time_schedule_notifications_field_weekdays_text2')
202
- }
203
- }, [JSON.stringify(biorhythm.repeatPeriod)])
204
-
205
- useUpdateEffect(() => {
206
- console.log('Redux 生物节律数据更新', biorhythm)
207
- const planList = biorhythm.planList?.map(item => {
208
- return {
209
- ...item,
210
- icon: replaceImg(item?.iconId || item?.icon)?.icon,
211
- iconId: replaceImg(item?.iconId || item?.icon)?.iconId,
212
- }
213
- })
214
- state.enable = biorhythm.enable
215
- state.gradient = biorhythm.gradient
216
- state.repeatPeriod = biorhythm.repeatPeriod
217
- state.planList = planList
218
-
219
- }, [JSON.stringify(biorhythm)])
220
-
221
-
222
- const setImg = (id) => {
223
- const imgIcon = iconList?.find(val => val?.id === Number(id))?.icon
224
- return imgIcon || ''
225
- }
226
-
227
- const openLink = () => {
228
- const url = I18n.getLang('biorhythm_product_link') // 需要打开的链接
229
- Linking.openURL(url).catch((error) => console.error('无法打开链接:', error))
230
- }
231
-
232
- const sunHomeText = string => {
233
- const text = string.split('SUN@HOME')
234
- return text?.length === 1 && <Text style={{ fontSize: cx(14), color: props.theme?.global.fontColor }}>{text[0]}</Text> ||
235
- <Text style={{
236
- fontSize: cx(14),
237
- flexDirection: 'row',
238
- }}>
239
- <Text style={{ color: props.theme?.global.fontColor }}>{text[0]}</Text>
240
- <Text
241
- onPress={openLink}
242
- style={{
243
- fontFamily: 'helvetica_neue_lt_std_roman',
244
- color: props.theme?.button.primary,
245
- textDecorationLine: 'underline',
246
- flexWrap: 'wrap',
247
- }}>SUN@HOME</Text>
248
- <Text style={{ color: props.theme?.global.fontColor }}>{text[1]}</Text>
249
- </Text>
250
- }
251
-
252
- const randomIcon = () => {
253
- const iconIdList = state.planList?.map(item => {
254
- return item.iconId
255
- })
256
- const allIcon = iconList?.map(item => {
257
- return item.id
258
- })
259
- const availableChart = allIcon.filter((element) => !iconIdList.includes(element))
260
- const randomIndex = Math.floor(Math.random() * availableChart.length)
261
- return availableChart[randomIndex]
262
- }
263
-
264
- const convertPlandata = useCallback(() => {
265
- return state.planList.map(item => {
266
- return {
267
- ...item,
268
- noActiveColor: '#474e5d',
269
- activeColor: '#F7EB2A',
270
- color: item?.brightness === 0 ? '#000' : !params.isSupportTemperature && cctToColor(1) || cctToColor(item.colorTemperature.toFixed(), item?.brightness)
271
- }
272
- }).filter(plan => plan.enable)
273
- }, [JSON.stringify(state.planList), params.isSupportTemperature])
274
-
275
- return (
276
- <>
277
- <Page
278
- backText={deviceInfo.name}
279
- onBackClick={navigation.goBack}
280
- headlineText={I18n.getLang('add_new_trigger_time_system_back_text')}
281
- headlineIconContent={<Switch
282
- value={state.enable}
283
- thumbColor={props.theme?.icon.primary}
284
- trackColor={{ false: '#00000026', true: '#ff660036' }}
285
- onValueChange={async enable => {
286
- const biorhythmTask = {
287
- startTime: 0,
288
- endTime: 1440,
289
- weeks: biorhythm.repeatPeriod.map(item => item.enabled ? 1 : 0),
290
- enable: biorhythm.enable,
291
- channel: 1
292
- }
293
- if (enable && checkConflict(biorhythmTask)) {
294
- return showCommonDialog({
295
- method: 'confirm',
296
- title: I18n.getLang('conflict_dialog_active_item_bio_rhythm_titel'),
297
- subTitle: I18n.getLang('conflict_dialog_active_item_bio_rhythm_description'),
298
- onConfirm: (_, { close }) => {
299
- resolveConflict()
300
- close()
301
- state.loading = true
302
- state.enable = enable
303
- requestSetBiorhythm(false)
304
- },
305
- onCancel: () => {
306
- Dialog.close()
307
- }
308
- })
309
- }
310
- state.loading = true
311
- state.enable = enable
312
- requestSetBiorhythm(false)
313
- }}
314
- />}
315
- loading={state.loading}
316
- >
317
- <ScrollView nestedScrollEnabled={true} style={{ position: 'relative' }}>
318
- <View style={{ marginHorizontal: cx(24) }}>
319
- {sunHomeText(I18n.getLang(devicesJudge ? 'bio_ryhthm_default_description_text' : 'bio_ryhthm_non_sun_home_products_description_text'))}
320
- </View>
321
- <View style={{ height: cx(10) }} />
322
- <View
323
- style={{
324
- flexDirection: 'row',
325
- justifyContent: 'space-between',
326
- marginHorizontal: cx(24),
327
- }}
328
- >
329
- {state.repeatPeriod.map(period => {
330
- return (
331
- <TouchableOpacity
332
- key={period.title}
333
- onPress={() => {
334
- const periodNum = state.repeatPeriod.filter(p => p.enabled)?.length
335
- if (periodNum === 1 && period.enabled) return
336
- period.enabled = !period.enabled
337
- requestSetBiorhythm(false)
338
- }}
339
- >
340
- <View
341
- style={{
342
- width: cx(40),
343
- height: cx(40),
344
- justifyContent: 'center',
345
- alignItems: 'center',
346
- borderRadius: cx(20),
347
- backgroundColor: period.enabled ? props.theme?.global.thirdBrand : props.theme?.global.background,
348
- borderWidth: cx(1),
349
- borderColor: props.theme?.global.brand,
350
- }}
351
- >
352
- <Text
353
- style={{
354
- color: props.theme?.global.brand,
355
- textAlign: 'center',
356
- }}
357
- >
358
- {period.title}
359
- </Text>
360
- </View>
361
- </TouchableOpacity>
362
- )
363
- })}
364
- </View>
365
- <View style={{ marginHorizontal: cx(24), marginTop: cx(20) }}>
366
- <Text style={{ color: props.theme?.global.fontColor }}>{state.weekString}</Text>
367
- </View>
368
- <View style={{ marginHorizontal: cx(24), marginTop: cx(16) }}>
369
- <Text style={{ color: props.theme?.global.fontColor }}>
370
- {I18n.getLang('bio_ryhthm_default_selectionfield_topic_text')}
371
- </Text>
372
- <TouchableOpacity
373
- onPress={() => {
374
- showGradientTypeSelectModal(true)
375
- }}
376
- >
377
- <View
378
- style={{
379
- flexDirection: 'row',
380
- borderRadius: cx(4),
381
- backgroundColor: props.theme?.textInput.background,
382
- alignItems: 'center',
383
- flex: 1,
384
- height: cx(44),
385
- borderBottomWidth: cx(1),
386
- borderBottomColor: props.theme?.textInput.line,
387
- }}
388
- >
389
- <Text style={{
390
- fontSize: cx(16),
391
- color: props.theme?.textInput.fontColor,
392
- fontFamily: 'helvetica_neue_lt_std_roman',
393
- paddingLeft: cx(16),
394
- }}>
395
- {
396
- I18n.getLang(
397
- state.gradient === BiorhythmGradientType.DirectGradient
398
- ? 'add_new_dynamic_mood_color_changing_mode_value2'
399
- : 'add_new_dynamic_mood_color_changing_mode_value',
400
- )
401
- }
402
-
403
- </Text>
404
- </View>
405
- </TouchableOpacity>
406
- </View>
407
- <View style={{ height: cx(20) }} />
408
- {/* <TimeCircular
409
- planEdit={true}
410
- planList={state.planList}
411
- onPanMoved={(id, time) => {
412
- state.planList = state.planList.map(plan => {
413
- return {
414
- ...plan,
415
- time: plan.index === id ? time : plan.time,
416
- }
417
- })
418
- state.flag = Symbol()
419
- }}
420
- replaceStatus={devicesJudge}
421
- gradient={state.gradient === BiorhythmGradientType.DirectGradient}
422
- isSupportTemperature={!params.isSupportTemperature} /> */}
423
- <View style={{ alignItems: 'center', justifyContent: 'center' }}>
424
- <RhythmsCircle
425
- size={250}
426
- ringWidth={40}
427
- thumbSize={36}
428
- timeImg={timeImg}
429
- gradientMode={state.gradient === BiorhythmGradientType.EntireGradient}
430
- data={convertPlandata()}
431
- onRelease={(planList) => {
432
- state.planList = state.planList.map(item => {
433
- return {
434
- ...item,
435
- time: planList.find(p => p.index === item.index)?.time
436
- }
437
- })
438
- state.flag = Symbol()
439
- }}
440
- />
441
- </View>
442
- <View
443
- style={{
444
- flexDirection: 'row',
445
- justifyContent: 'space-between',
446
- marginHorizontal: cx(24),
447
- marginBottom: cx(-8),
448
- marginTop: cx(26),
449
- }}>
450
- {state.planList.length === 8 && <View
451
- style={{ marginVertical: cx(10), flexDirection: 'row', alignItems: 'center', width: width - cx(48) }}>
452
- <Image style={{ width: cx(16), height: cx(16), tintColor: props.theme?.global.warning }} source={{ uri: res.ic_warning_amber }} />
453
- <Text
454
- style={{
455
- flexWrap: 'wrap',
456
- fontSize: cx(12),
457
- color: props.theme?.global.fontColor
458
- }}>{I18n.getLang('add_new_trigger_time_warning_max_number_text')}</Text>
459
- </View>}
460
- {state.planList.length < 8 &&
461
- <>
462
- <Text
463
- style={{
464
- fontSize: cx(16),
465
- fontWeight: 'bold',
466
- color: props.theme?.global.fontColor,
467
- }}>{I18n.getLang('bio_ryhthm_default_subheadline_text')}</Text>
468
- <TouchableOpacity
469
- onPress={() => {
470
- const ids: number[] = state.planList.map(p => p.index)
471
- const newPlan: Plan = {
472
- index: Math.max(...ids) + 1,
473
- icon: res.rhythm_icon1,
474
- time: 0,
475
- name: '',
476
- colorTemperature: 0,
477
- brightness: 100,
478
- action: [
479
- {
480
- uri: 'model/attribute/set/LightCtrl/ColorTemperature',
481
- startValue: `${colorTemperatureValue(0)}`,
482
- },
483
- {
484
- uri: 'model/attribute/set/LightCtrl/Brightness',
485
- startValue: '100',
486
- },
487
- ],
488
- enable: true,
489
- iconId: randomIcon(),
490
- }
491
- const editPageParams: BiorhythmEditPageParams = {
492
- planData: newPlan,
493
- isAdd: true,
494
- onPlanEdited,
495
- onPlanDelete,
496
- minimumEnable,
497
- nameRepeat,
498
- iconIdList: state.planList?.map(item => {
499
- return item.iconId
500
- }),
501
- isMixRGBWLamp: !!params.isMixLight,
502
- isSupportTemperature: params.isSupportTemperature,
503
- isSupportBrightness: params.isSupportBrightness,
504
- showDeleteBtn
505
- }
506
- navigation.navigate(ui_biz_routerKey.bi_biz_biological_edit, editPageParams)
507
- }}>
508
- <Image source={{ uri: res.biorhythom_add }} style={{ height: cx(24), width: cx(24), tintColor: props.theme?.icon.primary }} />
509
- </TouchableOpacity>
510
- </>
511
- }
512
- </View>
513
- <FlatList
514
- data={state.planList}
515
- style={{
516
- flex: 1,
517
- marginTop: cx(12),
518
- }}
519
- nestedScrollEnabled={true}
520
- ListHeaderComponent={() => (<Spacer height={cx(16)} />)}
521
- ItemSeparatorComponent={() => (<Spacer height={cx(16)} />)}
522
- renderItem={({ item }) => {
523
- const type = typeof item?.icon === 'string'
524
- const bgColor = item?.brightness === 0 ? '#000' : !params.isSupportTemperature && cctToColor(1) || cctToColor(item.colorTemperature.toFixed(), item?.brightness)
525
- return (
526
- <Card
527
- style={{ marginHorizontal: cx(24) }}
528
- onPress={() => {
529
- const editPageParams: BiorhythmEditPageParams = {
530
- planData: {
531
- ...item,
532
- name: setTimer(item?.name)
533
- },
534
- isAdd: false,
535
- onPlanEdited,
536
- onPlanDelete,
537
- minimumEnable,
538
- nameRepeat,
539
- iconIdList: state.planList?.map(item => {
540
- return item.iconId
541
- }),
542
- isMixRGBWLamp: !!params.isMixLight,
543
- isSupportTemperature: params.isSupportTemperature,
544
- isSupportBrightness: params.isSupportBrightness,
545
- showDeleteBtn
546
- }
547
- navigation.navigate(ui_biz_routerKey.bi_biz_biological_edit, editPageParams)
548
- }}
549
- >
550
- <View
551
- style={{
552
- flex: 1,
553
- flexDirection: 'column',
554
- }}
555
- >
556
- <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', marginTop: cx(16) }}>
557
- <View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
558
- <Image
559
- source={{ uri: setImg(item?.iconId) }}
560
- style={{
561
- width: cx(24),
562
- height: cx(24),
563
- marginStart: cx(10),
564
- marginRight: cx(6),
565
- tintColor: props.theme?.icon.normal,
566
- }}
567
- />
568
- <Text
569
- style={{
570
- fontSize: cx(16),
571
- color: props.theme?.global.fontColor,
572
- fontFamily: 'helvetica_neue_lt_std_roman',
573
- }}
574
- >
575
- {convertMinutesTo12HourFormat(item.time, is24Hour)}
576
- </Text>
577
- </View>
578
- <Switch
579
- value={item.enable}
580
- thumbColor={props.theme?.icon.primary}
581
- trackColor={{ false: '#00000026', true: '#ff660036' }}
582
- onValueChange={e => {
583
- item.enable = e
584
- requestSetBiorhythm()
585
- }}
586
- style={{ marginRight: cx(10) }}
587
- />
588
- </View>
589
- <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between' }}>
590
- <Text
591
- style={{
592
- fontSize: cx(12),
593
- color: props.theme?.global.secondFontColor,
594
- fontFamily: 'helvetica_neue_lt_std_roman',
595
- paddingLeft: cx(20),
596
- }}
597
- >
598
- {setTimer(item?.name)}
599
- </Text>
600
- </View>
601
- <View
602
- style={{
603
- width: cx(295),
604
- height: cx(24),
605
- backgroundColor: bgColor,
606
- marginLeft: cx(20),
607
- marginTop: cx(5),
608
- marginBottom: cx(24),
609
- borderRadius: cx(8),
610
- }} />
611
- </View>
612
- </Card>
613
- )
614
- }}
615
- keyExtractor={item => `${item.index}`}
616
- ListFooterComponent={() => {
617
- return (
618
- <View style={{ marginHorizontal: cx(24) }}>
619
- <Spacer />
620
- <DeleteButton
621
- text={I18n.getLang('bio_ryhthm_default_button_reset_text')}
622
- textStyle={{
623
- fontSize: cx(16),
624
- fontFamily: 'helvetica_neue_lt_std_roman',
625
- }}
626
- onPress={() => {
627
- showCommonDialog({
628
- method: 'confirm',
629
- title: I18n.getLang('bio_ryhthm_reset_description_text'),
630
- onConfirm: (_, { close }) => {
631
- const defBiorhythmUIState = getDefBiorhythmUIState()
632
- state.enable = defBiorhythmUIState.enable
633
- state.gradient = defBiorhythmUIState.gradient
634
- state.repeatPeriod = defBiorhythmUIState.repeatPeriod
635
- state.planList = defBiorhythmUIState.planList
636
- requestSetBiorhythm()
637
- close()
638
- }
639
- })
640
- }}
641
- />
642
- <Spacer />
643
- </View>
644
- )
645
- }}
646
- />
647
- {!state.enable && (
648
- <View
649
- style={{
650
- backgroundColor: 'rgba(0,0,0,.5)',
651
- width: '100%',
652
- height: '100%',
653
- position: 'absolute',
654
- top: 0,
655
- zIndex: 999,
656
- }}
657
- />
658
- )}
659
- </ScrollView>
660
- </Page>
661
- <Modal.List
662
- type={'radio'}
663
- visible={state.showGradientTypeSelectModal}
664
- value={state.gradient}
665
- dataSource={[
666
- {
667
- title: I18n.getLang('add_new_dynamic_mood_color_changing_mode_value'),
668
- key: BiorhythmGradientType.EntireGradient.toString(),
669
- value: BiorhythmGradientType.EntireGradient,
670
- },
671
- {
672
- title: I18n.getLang('add_new_dynamic_mood_color_changing_mode_value2'),
673
- key: BiorhythmGradientType.DirectGradient.toString(),
674
- value: BiorhythmGradientType.DirectGradient,
675
- },
676
- ]}
677
- title={I18n.getLang('add_new_dynamic_mood_color_changing_mode_headline')}
678
- onMaskPress={() => {
679
- showGradientTypeSelectModal(false)
680
- }}
681
- onCancel={() => {
682
- showGradientTypeSelectModal(false)
683
- }}
684
- cancelText={I18n.getLang('auto_scan_system_cancel')}
685
- confirmText={I18n.getLang('auto_scan_system_wifi_confirm')}
686
- onConfirm={(item: BiorhythmGradientType) => {
687
- state.gradient = item
688
- requestSetBiorhythm()
689
- showGradientTypeSelectModal(false)
690
- }}
691
- />
692
- </>
693
- )
694
- }
695
-
696
- export default withTheme(BiorhythmPage)
697
-
698
-
1
+ import Card from '@ledvance/base/src/components/Card'
2
+ import DeleteButton from '@ledvance/base/src/components/DeleteButton'
3
+ import Page from '@ledvance/base/src/components/Page'
4
+ import Spacer from '@ledvance/base/src/components/Spacer'
5
+ import LdvWeekView from '@ledvance/base/src/components/weekSelect'
6
+ import ThemeType from '@ledvance/base/src/config/themeType'
7
+ import { useParams } from '@ledvance/base/src/hooks/Hooks'
8
+ import I18n from '@ledvance/base/src/i18n'
9
+ import { useDeviceInfo, useSystemTimeFormate, } from '@ledvance/base/src/models/modules/NativePropsSlice'
10
+ import res from '@ledvance/base/src/res'
11
+ import { cctToColor } from '@ledvance/base/src/utils/cctUtils'
12
+ import { convertMinutesTo12HourFormat, loopText, showDialog as showCommonDialog } from '@ledvance/base/src/utils/common'
13
+ import { useNavigation } from '@react-navigation/native'
14
+ import { useDebounceFn, useReactive, useUpdateEffect } from 'ahooks'
15
+ import { useConflictTask } from 'hooks/DeviceDpStateHooks'
16
+ import { cloneDeep, sortBy } from 'lodash'
17
+ import React, { useCallback, useMemo } from 'react'
18
+ import { FlatList, Image, Linking, ScrollView, Switch, Text, TouchableOpacity, View } from 'react-native'
19
+ import { Dialog, Modal, Utils } from 'tuya-panel-kit'
20
+ import { ui_biz_routerKey } from '../../navigation/Routers'
21
+ import { useBiorhythm } from './BiorhythmActions'
22
+ import {
23
+ BiorhythmBean,
24
+ BiorhythmGradientType,
25
+ colorTemperatureValue,
26
+ getDefBiorhythmUIState,
27
+ Plan,
28
+ } from './BiorhythmBean'
29
+ import { BiorhythmEditPageParams } from './BiorhythmEditPage'
30
+ import RhythmsCircle from './circular/RhythmsCircle'
31
+ import iconList from './iconListData'
32
+ import pIdList from './pIdList'
33
+
34
+ const cx = Utils.RatioUtils.convertX
35
+ const { withTheme } = Utils.ThemeUtils
36
+ const width = Utils.RatioUtils.width
37
+
38
+ interface UIState extends BiorhythmBean {
39
+ showGradientTypeSelectModal: boolean;
40
+ flag: symbol;
41
+ timeSchedule: any[]
42
+ loading: boolean
43
+ }
44
+
45
+ export interface BiorhythmPageParams {
46
+ biorhythmDpCode: string
47
+ conflictDps: {
48
+ randomTimeDpCode?: string
49
+ fixedTimeDpCode?: string
50
+ sleepDpCode?: string
51
+ wakeUpDpCode?: string
52
+ }
53
+ isSupportTemperature: boolean
54
+ isSupportBrightness: boolean
55
+ isMixLight?: boolean
56
+ }
57
+
58
+ const BiorhythmPage = (props: { theme?: ThemeType }) => {
59
+ const params = useParams<BiorhythmPageParams>()
60
+ const navigation = useNavigation()
61
+ const [biorhythm, setBiorhythm] = useBiorhythm(params.biorhythmDpCode)
62
+ const deviceInfo = useDeviceInfo()
63
+ const { productId } = deviceInfo
64
+ const is24Hour = useSystemTimeFormate()
65
+ const devicesJudge = pIdList.some(val => val === productId)
66
+ const [checkConflict, resolveConflict] = useConflictTask(params.conflictDps)
67
+
68
+ const state = useReactive<UIState>({
69
+ ...biorhythm,
70
+ showGradientTypeSelectModal: false,
71
+ flag: Symbol(),
72
+ timeSchedule: [],
73
+ loading: false
74
+ })
75
+
76
+ const timeImg = useMemo(() => {
77
+ if (is24Hour) {
78
+ return devicesJudge ? res.ic_warning_amber_sun : res.ic_warning_amber_new
79
+ } else {
80
+ return devicesJudge ? res.ic_warning_amber_sun_12 : res.ic_warning_amber_new_12
81
+ }
82
+ }, [is24Hour, devicesJudge])
83
+
84
+ const showGradientTypeSelectModal = useCallback((show: boolean) => {
85
+ state.showGradientTypeSelectModal = show
86
+ }, [])
87
+
88
+ const onPlanEdited = useCallback((isAdd: boolean, newPlan: Plan) => {
89
+ if (isAdd) {
90
+ state.planList.push(newPlan)
91
+ state.planList = sortBy(state.planList, p => p.time)
92
+ } else {
93
+ state.planList = state.planList.map(plan => (plan.index === newPlan.index ? newPlan : plan))
94
+ }
95
+ state.flag = Symbol()
96
+ }, [])
97
+
98
+ const onPlanDelete = useCallback((id: number) => {
99
+ state.planList = state.planList.filter(plan => plan.index !== id)
100
+ state.flag = Symbol()
101
+ }, [])
102
+
103
+ const requestSetBiorhythm = useCallback(async (pushFeature: boolean = true) => {
104
+ state.loading = true
105
+ const planList = state.planList?.map(item => {
106
+ return { ...item, icon: `${item.icon}` }
107
+ })
108
+ .sort((a, b) => a.time - b.time)
109
+ const res = await setBiorhythm(cloneDeep({ ...state, planList }), pushFeature)
110
+ state.loading = false
111
+ if (res.success) {
112
+ console.log('设置生物节律 OK')
113
+ }
114
+ }, [])
115
+
116
+ useUpdateEffect(() => {
117
+ if (state.planList?.length === 0) {
118
+ const data = getDefBiorhythmUIState()
119
+ data.planList = data.planList?.map(item => {
120
+ return { ...item, icon: `${item.icon}` }
121
+ })
122
+ setBiorhythm(cloneDeep(data)).then()
123
+ }
124
+ }, [state.planList])
125
+
126
+ const setTimer = value => {
127
+ switch (value) {
128
+ case 'Sunrise':
129
+ return I18n.getLang('bio_ryhthm_default_field_text')
130
+ case 'Wake Up':
131
+ return I18n.getLang('bio_ryhthm_default_field_text2')
132
+ case 'Sunlight':
133
+ return I18n.getLang('bio_ryhthm_default_field_text3')
134
+ case 'Comfortable':
135
+ return I18n.getLang('bio_ryhthm_default_field_text4')
136
+ case 'Night light':
137
+ return I18n.getLang('bio_ryhthm_default_field_text5')
138
+ default:
139
+ return value
140
+ }
141
+ }
142
+
143
+ const minimumEnable = useCallback((plan: Plan) => {
144
+ let enable = false
145
+ state.planList.filter(p => p.index !== plan.index).forEach(item => {
146
+ const diff = Math.abs(plan.time - item.time)
147
+ if (diff < 15) enable = true
148
+ })
149
+ return enable
150
+ }, [state.planList])
151
+
152
+ const nameRepeat = useCallback((plan: Plan) => {
153
+ return !!state.planList.filter(p => p.index !== plan.index).find(p => p.name === plan.name)
154
+ }, [state.planList])
155
+
156
+ const showDeleteBtn = useMemo(() => {
157
+ return state.planList?.length > 1
158
+ }, [state.planList?.length])
159
+
160
+ const { run } = useDebounceFn(requestSetBiorhythm, { wait: 300 })
161
+
162
+ useUpdateEffect(() => {
163
+ run()
164
+ }, [state.flag])
165
+
166
+ const replaceImg = (img) => {
167
+ const item = iconList?.find(val => val.id === Number(img))
168
+ switch (img) {
169
+ case 'rhythm_icon1':
170
+ case '31':
171
+ return { icon: res.biorhythom_icon1, iconId: 1 }
172
+ case 'rhythm_icon2':
173
+ case '33':
174
+ return { icon: res.biorhythom_icon5, iconId: 5 }
175
+ case 'rhythm_icon3':
176
+ case '35':
177
+ return { icon: res.biorhythom_icon2, iconId: 2 }
178
+ case 'rhythm_icon4':
179
+ case '32':
180
+ return { icon: res.biorhythom_icon9, iconId: 9 }
181
+ case 'rhythm_icon12':
182
+ case '39':
183
+ return { icon: res.biorhythom_icon3, iconId: 3 }
184
+ default:
185
+ return { icon: item?.icon, iconId: item?.id }
186
+ }
187
+ }
188
+
189
+ useUpdateEffect(() => {
190
+ const planList = biorhythm.planList?.map(item => {
191
+ return {
192
+ ...item,
193
+ icon: replaceImg(item?.iconId || item?.icon)?.icon,
194
+ iconId: replaceImg(item?.iconId || item?.icon)?.iconId,
195
+ }
196
+ })
197
+ state.enable = biorhythm.enable
198
+ state.gradient = biorhythm.gradient
199
+ state.weeks = biorhythm.weeks
200
+ state.planList = planList
201
+
202
+ }, [JSON.stringify(biorhythm)])
203
+
204
+
205
+ const setImg = (id) => {
206
+ const imgIcon = iconList?.find(val => val?.id === Number(id))?.icon
207
+ return imgIcon || ''
208
+ }
209
+
210
+ const openLink = () => {
211
+ const url = I18n.getLang('biorhythm_product_link') // 需要打开的链接
212
+ Linking.openURL(url).catch((error) => console.error('无法打开链接:', error))
213
+ }
214
+
215
+ const sunHomeText = string => {
216
+ const text = string.split('SUN@HOME')
217
+ return text?.length === 1 &&
218
+ <Text style={{ fontSize: cx(14), color: props.theme?.global.fontColor }}>{text[0]}</Text> ||
219
+ <Text style={{
220
+ fontSize: cx(14),
221
+ flexDirection: 'row',
222
+ }}>
223
+ <Text style={{ color: props.theme?.global.fontColor }}>{text[0]}</Text>
224
+ <Text
225
+ onPress={openLink}
226
+ style={{
227
+ fontFamily: 'helvetica_neue_lt_std_roman',
228
+ color: props.theme?.button.primary,
229
+ textDecorationLine: 'underline',
230
+ flexWrap: 'wrap',
231
+ }}>SUN@HOME</Text>
232
+ <Text style={{ color: props.theme?.global.fontColor }}>{text[1]}</Text>
233
+ </Text>
234
+ }
235
+
236
+ const randomIcon = () => {
237
+ const iconIdList = state.planList?.map(item => {
238
+ return item.iconId
239
+ })
240
+ const allIcon = iconList?.map(item => {
241
+ return item.id
242
+ })
243
+ const availableChart = allIcon.filter((element) => !iconIdList.includes(element))
244
+ const randomIndex = Math.floor(Math.random() * availableChart.length)
245
+ return availableChart[randomIndex]
246
+ }
247
+
248
+ const convertPlandata = useCallback(() => {
249
+ return state.planList.map(item => {
250
+ return {
251
+ ...item,
252
+ noActiveColor: '#474e5d',
253
+ activeColor: '#F7EB2A',
254
+ color: item?.brightness === 0 ? '#000' : !params.isSupportTemperature && cctToColor(1) || cctToColor(item.colorTemperature.toFixed(), item?.brightness)
255
+ }
256
+ }).filter(plan => plan.enable)
257
+ }, [JSON.stringify(state.planList), params.isSupportTemperature])
258
+
259
+ return (
260
+ <>
261
+ <Page
262
+ backText={deviceInfo.name}
263
+ onBackClick={navigation.goBack}
264
+ headlineText={I18n.getLang('add_new_trigger_time_system_back_text')}
265
+ headlineIconContent={<Switch
266
+ value={state.enable}
267
+ thumbColor={props.theme?.icon.primary}
268
+ trackColor={{ false: '#00000026', true: '#ff660036' }}
269
+ onValueChange={async enable => {
270
+ const biorhythmTask = {
271
+ startTime: 0,
272
+ endTime: 1440,
273
+ weeks: biorhythm.weeks,
274
+ enable: biorhythm.enable,
275
+ channel: 1
276
+ }
277
+ if (enable && checkConflict(biorhythmTask)) {
278
+ return showCommonDialog({
279
+ method: 'confirm',
280
+ title: I18n.getLang('conflict_dialog_active_item_bio_rhythm_titel'),
281
+ subTitle: I18n.getLang('conflict_dialog_active_item_bio_rhythm_description'),
282
+ onConfirm: (_, { close }) => {
283
+ resolveConflict()
284
+ close()
285
+ state.loading = true
286
+ state.enable = enable
287
+ requestSetBiorhythm(false)
288
+ },
289
+ onCancel: () => {
290
+ Dialog.close()
291
+ }
292
+ })
293
+ }
294
+ state.loading = true
295
+ state.enable = enable
296
+ requestSetBiorhythm(false)
297
+ }}
298
+ />}
299
+ loading={state.loading}
300
+ >
301
+ <ScrollView nestedScrollEnabled={true} style={{ position: 'relative' }}>
302
+ <View style={{ marginHorizontal: cx(24) }}>
303
+ {sunHomeText(I18n.getLang(devicesJudge ? 'bio_ryhthm_default_description_text' : 'bio_ryhthm_non_sun_home_products_description_text'))}
304
+ </View>
305
+ <View style={{ height: cx(10) }}/>
306
+ <LdvWeekView
307
+ value={state.weeks}
308
+ style={{ marginHorizontal: cx(24) }}
309
+ onSelect={(index: number) => {
310
+ const rawIndex = index - 1
311
+ const newWeeks = cloneDeep(state.weeks)
312
+ newWeeks[rawIndex] = newWeeks[rawIndex] === 1 ? 0 : 1
313
+ if (!newWeeks.every(item => item === 0)) {
314
+ state.weeks = newWeeks
315
+ requestSetBiorhythm(false)
316
+ }
317
+ }}/>
318
+ <Spacer/>
319
+ <Text style={{ marginHorizontal: cx(24), color: props.theme?.global.fontColor, fontSize: cx(14) }}>
320
+ {loopText(state.weeks)}
321
+ </Text>
322
+ <View style={{ marginHorizontal: cx(24), marginTop: cx(16) }}>
323
+ <Text style={{ color: props.theme?.global.fontColor }}>
324
+ {I18n.getLang('bio_ryhthm_default_selectionfield_topic_text')}
325
+ </Text>
326
+ <TouchableOpacity
327
+ onPress={() => {
328
+ showGradientTypeSelectModal(true)
329
+ }}
330
+ >
331
+ <View
332
+ style={{
333
+ flexDirection: 'row',
334
+ borderRadius: cx(4),
335
+ backgroundColor: props.theme?.textInput.background,
336
+ alignItems: 'center',
337
+ flex: 1,
338
+ height: cx(44),
339
+ borderBottomWidth: cx(1),
340
+ borderBottomColor: props.theme?.textInput.line,
341
+ }}
342
+ >
343
+ <Text style={{
344
+ fontSize: cx(16),
345
+ color: props.theme?.textInput.fontColor,
346
+ fontFamily: 'helvetica_neue_lt_std_roman',
347
+ paddingLeft: cx(16),
348
+ }}>
349
+ {
350
+ I18n.getLang(
351
+ state.gradient === BiorhythmGradientType.DirectGradient
352
+ ? 'add_new_dynamic_mood_color_changing_mode_value2'
353
+ : 'add_new_dynamic_mood_color_changing_mode_value',
354
+ )
355
+ }
356
+
357
+ </Text>
358
+ </View>
359
+ </TouchableOpacity>
360
+ </View>
361
+ <View style={{ height: cx(20) }}/>
362
+ {/* <TimeCircular
363
+ planEdit={true}
364
+ planList={state.planList}
365
+ onPanMoved={(id, time) => {
366
+ state.planList = state.planList.map(plan => {
367
+ return {
368
+ ...plan,
369
+ time: plan.index === id ? time : plan.time,
370
+ }
371
+ })
372
+ state.flag = Symbol()
373
+ }}
374
+ replaceStatus={devicesJudge}
375
+ gradient={state.gradient === BiorhythmGradientType.DirectGradient}
376
+ isSupportTemperature={!params.isSupportTemperature} /> */}
377
+ <View style={{ alignItems: 'center', justifyContent: 'center' }}>
378
+ <RhythmsCircle
379
+ size={250}
380
+ ringWidth={40}
381
+ thumbSize={36}
382
+ timeImg={timeImg}
383
+ gradientMode={state.gradient === BiorhythmGradientType.EntireGradient}
384
+ data={convertPlandata()}
385
+ onRelease={(planList) => {
386
+ state.planList = state.planList.map(item => {
387
+ return {
388
+ ...item,
389
+ time: planList.find(p => p.index === item.index)?.time
390
+ }
391
+ })
392
+ state.flag = Symbol()
393
+ }}
394
+ />
395
+ </View>
396
+ <View
397
+ style={{
398
+ flexDirection: 'row',
399
+ justifyContent: 'space-between',
400
+ marginHorizontal: cx(24),
401
+ marginBottom: cx(-8),
402
+ marginTop: cx(26),
403
+ }}>
404
+ {state.planList.length === 8 && <View
405
+ style={{ marginVertical: cx(10), flexDirection: 'row', alignItems: 'center', width: width - cx(48) }}>
406
+ <Image style={{ width: cx(16), height: cx(16), tintColor: props.theme?.global.warning }}
407
+ source={{ uri: res.ic_warning_amber }}/>
408
+ <Text
409
+ style={{
410
+ flexWrap: 'wrap',
411
+ fontSize: cx(12),
412
+ color: props.theme?.global.fontColor
413
+ }}>{I18n.getLang('add_new_trigger_time_warning_max_number_text')}</Text>
414
+ </View>}
415
+ {state.planList.length < 8 &&
416
+ <>
417
+ <Text
418
+ style={{
419
+ fontSize: cx(16),
420
+ fontWeight: 'bold',
421
+ color: props.theme?.global.fontColor,
422
+ }}>{I18n.getLang('bio_ryhthm_default_subheadline_text')}</Text>
423
+ <TouchableOpacity
424
+ onPress={() => {
425
+ const ids: number[] = state.planList.map(p => p.index)
426
+ const newPlan: Plan = {
427
+ index: Math.max(...ids) + 1,
428
+ icon: res.rhythm_icon1,
429
+ time: 0,
430
+ name: '',
431
+ colorTemperature: 0,
432
+ brightness: 100,
433
+ action: [
434
+ {
435
+ uri: 'model/attribute/set/LightCtrl/ColorTemperature',
436
+ startValue: `${colorTemperatureValue(0)}`,
437
+ },
438
+ {
439
+ uri: 'model/attribute/set/LightCtrl/Brightness',
440
+ startValue: '100',
441
+ },
442
+ ],
443
+ enable: true,
444
+ iconId: randomIcon(),
445
+ }
446
+ const editPageParams: BiorhythmEditPageParams = {
447
+ planData: newPlan,
448
+ isAdd: true,
449
+ onPlanEdited,
450
+ onPlanDelete,
451
+ minimumEnable,
452
+ nameRepeat,
453
+ iconIdList: state.planList?.map(item => {
454
+ return item.iconId
455
+ }),
456
+ isMixRGBWLamp: !!params.isMixLight,
457
+ isSupportTemperature: params.isSupportTemperature,
458
+ isSupportBrightness: params.isSupportBrightness,
459
+ showDeleteBtn
460
+ }
461
+ navigation.navigate(ui_biz_routerKey.bi_biz_biological_edit, editPageParams)
462
+ }}>
463
+ <Image source={{ uri: res.biorhythom_add }}
464
+ style={{ height: cx(24), width: cx(24), tintColor: props.theme?.icon.primary }}/>
465
+ </TouchableOpacity>
466
+ </>
467
+ }
468
+ </View>
469
+ <FlatList
470
+ data={state.planList}
471
+ style={{
472
+ flex: 1,
473
+ marginTop: cx(12),
474
+ }}
475
+ nestedScrollEnabled={true}
476
+ ListHeaderComponent={() => (<Spacer height={cx(16)}/>)}
477
+ ItemSeparatorComponent={() => (<Spacer height={cx(16)}/>)}
478
+ renderItem={({ item }) => {
479
+ const bgColor = item?.brightness === 0 ? '#000' : !params.isSupportTemperature && cctToColor(1) || cctToColor(item.colorTemperature.toFixed(), item?.brightness)
480
+ return (
481
+ <Card
482
+ style={{ marginHorizontal: cx(24) }}
483
+ onPress={() => {
484
+ const editPageParams: BiorhythmEditPageParams = {
485
+ planData: {
486
+ ...item,
487
+ name: setTimer(item?.name)
488
+ },
489
+ isAdd: false,
490
+ onPlanEdited,
491
+ onPlanDelete,
492
+ minimumEnable,
493
+ nameRepeat,
494
+ iconIdList: state.planList?.map(item => {
495
+ return item.iconId
496
+ }),
497
+ isMixRGBWLamp: !!params.isMixLight,
498
+ isSupportTemperature: params.isSupportTemperature,
499
+ isSupportBrightness: params.isSupportBrightness,
500
+ showDeleteBtn
501
+ }
502
+ navigation.navigate(ui_biz_routerKey.bi_biz_biological_edit, editPageParams)
503
+ }}
504
+ >
505
+ <View
506
+ style={{
507
+ flex: 1,
508
+ flexDirection: 'column',
509
+ }}
510
+ >
511
+ <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', marginTop: cx(16) }}>
512
+ <View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
513
+ <Image
514
+ source={{ uri: setImg(item?.iconId) }}
515
+ style={{
516
+ width: cx(24),
517
+ height: cx(24),
518
+ marginStart: cx(10),
519
+ marginRight: cx(6),
520
+ tintColor: props.theme?.icon.normal,
521
+ }}
522
+ />
523
+ <Text
524
+ style={{
525
+ fontSize: cx(16),
526
+ color: props.theme?.global.fontColor,
527
+ fontFamily: 'helvetica_neue_lt_std_roman',
528
+ }}
529
+ >
530
+ {convertMinutesTo12HourFormat(item.time, is24Hour)}
531
+ </Text>
532
+ </View>
533
+ <Switch
534
+ value={item.enable}
535
+ thumbColor={props.theme?.icon.primary}
536
+ trackColor={{ false: '#00000026', true: '#ff660036' }}
537
+ onValueChange={e => {
538
+ item.enable = e
539
+ requestSetBiorhythm()
540
+ }}
541
+ style={{ marginRight: cx(10) }}
542
+ />
543
+ </View>
544
+ <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between' }}>
545
+ <Text
546
+ style={{
547
+ fontSize: cx(12),
548
+ color: props.theme?.global.secondFontColor,
549
+ fontFamily: 'helvetica_neue_lt_std_roman',
550
+ paddingLeft: cx(20),
551
+ }}
552
+ >
553
+ {setTimer(item?.name)}
554
+ </Text>
555
+ </View>
556
+ <View
557
+ style={{
558
+ width: cx(295),
559
+ height: cx(24),
560
+ backgroundColor: bgColor,
561
+ marginLeft: cx(20),
562
+ marginTop: cx(5),
563
+ marginBottom: cx(24),
564
+ borderRadius: cx(8),
565
+ }}/>
566
+ </View>
567
+ </Card>
568
+ )
569
+ }}
570
+ keyExtractor={item => `${item.index}`}
571
+ ListFooterComponent={() => {
572
+ return (
573
+ <View style={{ marginHorizontal: cx(24) }}>
574
+ <Spacer/>
575
+ <DeleteButton
576
+ text={I18n.getLang('bio_ryhthm_default_button_reset_text')}
577
+ textStyle={{
578
+ fontSize: cx(16),
579
+ fontFamily: 'helvetica_neue_lt_std_roman',
580
+ }}
581
+ onPress={() => {
582
+ showCommonDialog({
583
+ method: 'confirm',
584
+ title: I18n.getLang('bio_ryhthm_reset_description_text'),
585
+ onConfirm: (_, { close }) => {
586
+ const defBiorhythmUIState = getDefBiorhythmUIState()
587
+ state.enable = defBiorhythmUIState.enable
588
+ state.weeks = defBiorhythmUIState.weeks
589
+ state.gradient = defBiorhythmUIState.gradient
590
+ state.planList = defBiorhythmUIState.planList
591
+ requestSetBiorhythm()
592
+ close()
593
+ }
594
+ })
595
+ }}
596
+ />
597
+ <Spacer/>
598
+ </View>
599
+ )
600
+ }}
601
+ />
602
+ {!state.enable && (
603
+ <View
604
+ style={{
605
+ backgroundColor: 'rgba(0,0,0,.5)',
606
+ width: '100%',
607
+ height: '100%',
608
+ position: 'absolute',
609
+ top: 0,
610
+ zIndex: 999,
611
+ }}
612
+ />
613
+ )}
614
+ </ScrollView>
615
+ </Page>
616
+ <Modal.List
617
+ type={'radio'}
618
+ visible={state.showGradientTypeSelectModal}
619
+ value={state.gradient}
620
+ dataSource={[
621
+ {
622
+ title: I18n.getLang('add_new_dynamic_mood_color_changing_mode_value'),
623
+ key: BiorhythmGradientType.EntireGradient.toString(),
624
+ value: BiorhythmGradientType.EntireGradient,
625
+ },
626
+ {
627
+ title: I18n.getLang('add_new_dynamic_mood_color_changing_mode_value2'),
628
+ key: BiorhythmGradientType.DirectGradient.toString(),
629
+ value: BiorhythmGradientType.DirectGradient,
630
+ },
631
+ ]}
632
+ title={I18n.getLang('add_new_dynamic_mood_color_changing_mode_headline')}
633
+ onMaskPress={() => {
634
+ showGradientTypeSelectModal(false)
635
+ }}
636
+ onCancel={() => {
637
+ showGradientTypeSelectModal(false)
638
+ }}
639
+ cancelText={I18n.getLang('auto_scan_system_cancel')}
640
+ confirmText={I18n.getLang('auto_scan_system_wifi_confirm')}
641
+ onConfirm={(item: BiorhythmGradientType) => {
642
+ state.gradient = item
643
+ requestSetBiorhythm()
644
+ showGradientTypeSelectModal(false)
645
+ }}
646
+ />
647
+ </>
648
+ )
649
+ }
650
+
651
+ export default withTheme(BiorhythmPage)
652
+
653
+