@ledvance/ui-biz-bundle 1.1.105 → 1.1.107
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 +1 -1
- package/src/hooks/DeviceDpStateHooks.ts +156 -0
- package/src/modules/flags/FlagActions.ts +4 -1
- package/src/modules/flags/FlagPage.tsx +12 -42
- package/src/modules/music/MusicPage.tsx +13 -7
- package/src/modules/timer/TimerPage.tsx +4 -1
- package/src/modules/timer/TimerPageAction.ts +0 -1
- package/src/navigation/Routers.ts +3 -1
- package/src/newModules/biorhythm/BiorhythmBean.ts +1 -1
- package/src/newModules/biorhythm/BiorhythmPage.tsx +27 -4
- package/src/newModules/diyScene/DefaultScenes.ts +438 -0
- package/src/newModules/diyScene/DiySceneActions.ts +232 -0
- package/src/newModules/diyScene/DiySceneEditorPage.tsx +359 -0
- package/src/newModules/diyScene/DiyScenePage.tsx +297 -0
- package/src/newModules/diyScene/Router.ts +25 -0
- package/src/newModules/energyConsumption/EnergyConsumptionActions.ts +15 -2
- package/src/newModules/energyConsumption/EnergyConsumptionChart.tsx +31 -10
- package/src/newModules/energyConsumption/component/DateSwitch.tsx +111 -0
- package/src/newModules/energyConsumption/component/DateTypeItem.tsx +1 -0
- package/src/newModules/energyConsumption/component/NewBarChart.tsx +16 -3
- package/src/newModules/fixedTime/FixedTimeActions.ts +3 -3
- package/src/newModules/fixedTime/FixedTimePage.tsx +58 -6
- package/src/newModules/mood/MoodActions.ts +4 -1
- package/src/newModules/mood/MoodItem.tsx +2 -1
- package/src/newModules/mood/MoodPage.tsx +4 -3
- package/src/newModules/randomTime/RandomTimeActions.ts +3 -3
- package/src/newModules/randomTime/RandomTimePage.tsx +60 -7
- package/src/newModules/sleepWakeUp/SleepWakeUpActions.ts +21 -11
- package/src/newModules/sleepWakeUp/SleepWakeUpPage.tsx +108 -13
- package/src/newModules/switchGradient/SwitchGradientPage.tsx +7 -4
- package/src/newModules/swithInching/SwithInching.tsx +1 -0
- package/src/newModules/timeSchedule/Interface.ts +19 -7
- package/src/newModules/timeSchedule/TimeScheduleActions.ts +6 -0
- package/src/newModules/timeSchedule/TimeScheduleDetailPage.tsx +134 -57
- package/src/newModules/timeSchedule/TimeSchedulePage.tsx +23 -6
- package/src/newModules/timeSchedule/components/ManuaSettings.tsx +42 -9
- package/src/newModules/timeSchedule/components/ScheduleCard.tsx +5 -1
|
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'
|
|
|
2
2
|
import { useDp, useDeviceId } from '@ledvance/base/src/models/modules/NativePropsSlice'
|
|
3
3
|
import { getFeature, putFeature } from '@ledvance/base/src/api/native'
|
|
4
4
|
import { hex2Int, spliceByStep } from '@ledvance/base/src/utils/common'
|
|
5
|
-
import { SleepData, SleepItem,
|
|
5
|
+
import { SleepData, SleepItem, SleepUIItem, WakeUpData, WakeUpItem, WakeUpUIItem } from './Interface'
|
|
6
6
|
import { cloneDeep, padStart } from 'lodash'
|
|
7
7
|
import { parseJSON, to16 } from '@tuya/tuya-panel-lamp-sdk/lib/utils'
|
|
8
8
|
import { Result } from '@ledvance/base/src/models/modules/Result'
|
|
@@ -38,7 +38,7 @@ const putFeatureFn = async (devId, featureId, data) => {
|
|
|
38
38
|
return status
|
|
39
39
|
}
|
|
40
40
|
let wakeUpTimerId: number | undefined = undefined
|
|
41
|
-
type WakeUpType = (wakeUpDp: string, disableFeature?: boolean) => [WakeUpUIItem[], (wakeUpData:
|
|
41
|
+
type WakeUpType = (wakeUpDp: string, disableFeature?: boolean) => [WakeUpUIItem[], (wakeUpData: WakeUpUIItem[], pushFeature?: boolean) => Promise<Result<any>>, boolean]
|
|
42
42
|
// @ts-ignore
|
|
43
43
|
export const useWakeUp: WakeUpType = (wakeUpDp, disableFeature) => {
|
|
44
44
|
const devId = useDeviceId()
|
|
@@ -77,8 +77,8 @@ export const useWakeUp: WakeUpType = (wakeUpDp, disableFeature) => {
|
|
|
77
77
|
}
|
|
78
78
|
}, [wakeUp])
|
|
79
79
|
|
|
80
|
-
const setWakeUpFn = async (wakeUp:
|
|
81
|
-
const featureData = wakeUp
|
|
80
|
+
const setWakeUpFn = async (wakeUp: WakeUpUIItem[], pushFeature = true) => {
|
|
81
|
+
const featureData = wakeUp.map(item => {
|
|
82
82
|
return {
|
|
83
83
|
name: item.name,
|
|
84
84
|
startTime: JSON.stringify({
|
|
@@ -86,9 +86,14 @@ export const useWakeUp: WakeUpType = (wakeUpDp, disableFeature) => {
|
|
|
86
86
|
})
|
|
87
87
|
}
|
|
88
88
|
})
|
|
89
|
-
const res = await putFeature(devId, wakeUpPlanFeatureId, featureData || [])
|
|
89
|
+
const res = pushFeature ? await putFeature(devId, wakeUpPlanFeatureId, featureData || []) : {result: true}
|
|
90
|
+
const wakeUpData = {
|
|
91
|
+
version: 0,
|
|
92
|
+
num: wakeUp.length,
|
|
93
|
+
nodes: cloneDeep(wakeUp)
|
|
94
|
+
}
|
|
90
95
|
if (res.result) {
|
|
91
|
-
setWakeUp(wakeUpObj2Dp(
|
|
96
|
+
setWakeUp(wakeUpObj2Dp(wakeUpData)).then()
|
|
92
97
|
return {
|
|
93
98
|
success: true
|
|
94
99
|
}
|
|
@@ -192,7 +197,7 @@ export const wakeUpNode2Dp = (node: WakeUpItem) =>{
|
|
|
192
197
|
}
|
|
193
198
|
|
|
194
199
|
let sleepTimerId: number | undefined = undefined
|
|
195
|
-
type SleepModeType = (sleepDp: string, disableFeature?: boolean) => [SleepUIItem[], (sleepData:
|
|
200
|
+
type SleepModeType = (sleepDp: string, disableFeature?: boolean) => [SleepUIItem[], (sleepData: SleepUIItem[], pushFeature?: boolean) => Promise<Result<any>>, boolean]
|
|
196
201
|
// @ts-ignore
|
|
197
202
|
export const useSleepMode: SleepModeType = (sleepDp, disableFeature) => {
|
|
198
203
|
const devId = useDeviceId()
|
|
@@ -231,8 +236,8 @@ export const useSleepMode: SleepModeType = (sleepDp, disableFeature) => {
|
|
|
231
236
|
}
|
|
232
237
|
}, [sleepMode])
|
|
233
238
|
|
|
234
|
-
const setSleepPlanFn = async (sleep:
|
|
235
|
-
const featureData = sleep
|
|
239
|
+
const setSleepPlanFn = async (sleep: SleepUIItem[], pushFeature = true) => {
|
|
240
|
+
const featureData = sleep.map(item => {
|
|
236
241
|
return {
|
|
237
242
|
name: item.name,
|
|
238
243
|
startTime: JSON.stringify({
|
|
@@ -240,9 +245,14 @@ export const useSleepMode: SleepModeType = (sleepDp, disableFeature) => {
|
|
|
240
245
|
})
|
|
241
246
|
}
|
|
242
247
|
})
|
|
243
|
-
const res = await putFeature(devId, sleepPlanFeatureId, featureData || [])
|
|
248
|
+
const res = pushFeature ? await putFeature(devId, sleepPlanFeatureId, featureData || []) : {result: true}
|
|
249
|
+
const sleepData = {
|
|
250
|
+
version: 0,
|
|
251
|
+
num: sleep.length,
|
|
252
|
+
nodes: cloneDeep(sleep)
|
|
253
|
+
}
|
|
244
254
|
if (res.result) {
|
|
245
|
-
setSleepMode(sleepObj2Dp(
|
|
255
|
+
setSleepMode(sleepObj2Dp(sleepData)).then()
|
|
246
256
|
return {
|
|
247
257
|
success: true
|
|
248
258
|
}
|
|
@@ -9,8 +9,8 @@ import res from '@ledvance/base/src/res'
|
|
|
9
9
|
import { useDeviceInfo, useSystemTimeFormate } from "@ledvance/base/src/models/modules/NativePropsSlice";
|
|
10
10
|
import { useReactive, useUpdateEffect } from "ahooks";
|
|
11
11
|
import CustomListDialog from "@ledvance/base/src/components/CustomListDialog";
|
|
12
|
-
import { SwitchButton, Utils } from "tuya-panel-kit";
|
|
13
|
-
import { convertMinutesTo12HourFormat, loopText } from "@ledvance/base/src/utils/common";
|
|
12
|
+
import { Dialog, SwitchButton, Utils } from "tuya-panel-kit";
|
|
13
|
+
import { convertMinutesTo12HourFormat, loopText, isConflictTask, showDialog } from "@ledvance/base/src/utils/common";
|
|
14
14
|
import TextButton from "@ledvance/base/src/components/TextButton";
|
|
15
15
|
import { ui_biz_routerKey } from '../../navigation/Routers'
|
|
16
16
|
import { cloneDeep } from "lodash";
|
|
@@ -21,6 +21,8 @@ import { useParams } from "@ledvance/base/src/hooks/Hooks";
|
|
|
21
21
|
import { ApplyForItem } from "../timeSchedule/Interface";
|
|
22
22
|
import InfoText from "@ledvance/base/src/components/InfoText";
|
|
23
23
|
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
24
|
+
import { useConflictTask } from "hooks/DeviceDpStateHooks";
|
|
25
|
+
|
|
24
26
|
|
|
25
27
|
const cx = Utils.RatioUtils.convertX
|
|
26
28
|
const { parseTimer } = Utils.TimeUtils
|
|
@@ -31,7 +33,7 @@ export interface SleepWakeUpPageRouteParams {
|
|
|
31
33
|
isSupportTemperature?: boolean
|
|
32
34
|
isSupportBrightness?: boolean
|
|
33
35
|
isMixLight?: boolean
|
|
34
|
-
|
|
36
|
+
sleepDpCode: string
|
|
35
37
|
wakeUpDpCode: string
|
|
36
38
|
conflictDps: {
|
|
37
39
|
randomTimeDpCode?: string
|
|
@@ -48,7 +50,8 @@ const SleepWakeUpPage = (props: { theme?: ThemeType }) => {
|
|
|
48
50
|
const is24HourClock = useSystemTimeFormate()
|
|
49
51
|
const params = useParams<SleepWakeUpPageRouteParams>()
|
|
50
52
|
const [wakeUpList, setWakeUpList, wakeupComplete] = useWakeUp(params.wakeUpDpCode)
|
|
51
|
-
const [sleepList, setSleepList, sleepComplete] = useSleepMode(params.
|
|
53
|
+
const [sleepList, setSleepList, sleepComplete] = useSleepMode(params.sleepDpCode)
|
|
54
|
+
const [checkConflict, resolveConflict] = useConflictTask(params.conflictDps)
|
|
52
55
|
const state = useReactive({
|
|
53
56
|
showAddSchedulePopover: false,
|
|
54
57
|
sleepTagChecked: false,
|
|
@@ -65,12 +68,10 @@ const SleepWakeUpPage = (props: { theme?: ThemeType }) => {
|
|
|
65
68
|
}, [state.sleepScheduleList, state.wakeUpScheduleList])
|
|
66
69
|
|
|
67
70
|
useUpdateEffect(() => {
|
|
68
|
-
console.log(sleepList, '< --- sleepList')
|
|
69
71
|
state.sleepScheduleList = cloneDeep(sleepList)
|
|
70
72
|
}, [JSON.stringify(sleepList)])
|
|
71
73
|
|
|
72
74
|
useUpdateEffect(() => {
|
|
73
|
-
console.log(wakeUpList, '< --- wakeUpList')
|
|
74
75
|
state.wakeUpScheduleList = cloneDeep(wakeUpList)
|
|
75
76
|
}, [JSON.stringify(wakeUpList)])
|
|
76
77
|
|
|
@@ -114,12 +115,79 @@ const SleepWakeUpPage = (props: { theme?: ThemeType }) => {
|
|
|
114
115
|
return item
|
|
115
116
|
})
|
|
116
117
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
118
|
+
if ((mode === 'edit' && sleepWakeUp.enable) || mode === 'add') {
|
|
119
|
+
let sleepConflict = false
|
|
120
|
+
let wakeUpConflict = false
|
|
121
|
+
const cloneSleepPlan = isSleep ? cloneSleepWakeUp : cloneDeep(sleepList)
|
|
122
|
+
const cloneWakeUpPlan = isSleep ? cloneDeep(wakeUpList) : cloneSleepWakeUp
|
|
123
|
+
const currentSleepWakeUp = {
|
|
124
|
+
...sleepWakeUp,
|
|
125
|
+
startTime: getStartTime(sleepWakeUp),
|
|
126
|
+
endTime: getEndTime(sleepWakeUp)
|
|
127
|
+
}
|
|
128
|
+
const newSleepList = cloneSleepPlan.map((item, idx) => {
|
|
129
|
+
const itself = isSleep ? (mode === 'add' ? (idx === cloneSleepPlan.length - 1) : sleepWakeUp.id === item.id) : isSleep
|
|
130
|
+
if (!itself && item.enable && isConflictTask({
|
|
131
|
+
...item,
|
|
132
|
+
startTime: getStartTime(item),
|
|
133
|
+
endTime: getEndTime(item)
|
|
134
|
+
}, currentSleepWakeUp)){
|
|
135
|
+
sleepConflict = true
|
|
136
|
+
item.enable = false
|
|
137
|
+
return item
|
|
138
|
+
}
|
|
139
|
+
return item
|
|
140
|
+
})
|
|
141
|
+
const newWakeUpList = cloneWakeUpPlan.map((item, idx) => {
|
|
142
|
+
const itself = !isSleep ? (mode === 'add' ? (idx === cloneWakeUpPlan.length - 1) : sleepWakeUp.id === item.id) : !isSleep
|
|
143
|
+
if (!itself && item.enable && isConflictTask({
|
|
144
|
+
...item,
|
|
145
|
+
startTime: getStartTime(item),
|
|
146
|
+
endTime: getEndTime(item)
|
|
147
|
+
}, currentSleepWakeUp)){
|
|
148
|
+
wakeUpConflict = true
|
|
149
|
+
item.enable = false
|
|
150
|
+
return item
|
|
151
|
+
}
|
|
152
|
+
return item
|
|
153
|
+
})
|
|
154
|
+
const isConflict = checkConflict(currentSleepWakeUp) || sleepConflict || wakeUpConflict
|
|
155
|
+
if (isConflict) {
|
|
156
|
+
return new Promise((resolve) => {
|
|
157
|
+
showDialog({
|
|
158
|
+
method: 'confirm',
|
|
159
|
+
title: I18n.getLang(isSleep ? 'conflict_dialog_active_item_sleepschedule_titel' : 'conflict_dialog_active_item_wakeupschedule_titel'),
|
|
160
|
+
subTitle: I18n.getLang(isSleep ? 'conflict_dialog_active_item_sleepschedule_description' : 'conflict_dialog_active_item_wakeupschedule_description'),
|
|
161
|
+
onConfirm: async (_, { close }) => {
|
|
162
|
+
close()
|
|
163
|
+
resolveConflict()
|
|
164
|
+
const res = isSleep ? await setSleepList(newSleepList) : await setWakeUpList(newWakeUpList)
|
|
165
|
+
if (isSleep) {
|
|
166
|
+
if (wakeUpConflict){
|
|
167
|
+
setWakeUpList(newWakeUpList).then()
|
|
168
|
+
state.wakeUpScheduleList = cloneDeep(newWakeUpList)
|
|
169
|
+
}
|
|
170
|
+
state.sleepScheduleList = cloneDeep(newSleepList)
|
|
171
|
+
} else {
|
|
172
|
+
if (sleepConflict){
|
|
173
|
+
setSleepList(newSleepList).then()
|
|
174
|
+
state.sleepScheduleList = cloneDeep(newSleepList)
|
|
175
|
+
}
|
|
176
|
+
state.wakeUpScheduleList = cloneDeep(newWakeUpList)
|
|
177
|
+
}
|
|
178
|
+
resolve(res)
|
|
179
|
+
},
|
|
180
|
+
onCancel: () => {
|
|
181
|
+
resolve({
|
|
182
|
+
success: false
|
|
183
|
+
})
|
|
184
|
+
Dialog.close()
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
}
|
|
121
189
|
}
|
|
122
|
-
const res = isSleep ? await setSleepList(
|
|
190
|
+
const res = isSleep ? await setSleepList(cloneSleepWakeUp) : await setWakeUpList(cloneSleepWakeUp)
|
|
123
191
|
if (res.success) {
|
|
124
192
|
if (isSleep) {
|
|
125
193
|
state.sleepScheduleList = cloneDeep(cloneSleepWakeUp)
|
|
@@ -332,6 +400,32 @@ const SleepWakeUpPage = (props: { theme?: ThemeType }) => {
|
|
|
332
400
|
enable: v ? 1 : 0
|
|
333
401
|
})
|
|
334
402
|
}}
|
|
403
|
+
onLongPress={() =>{
|
|
404
|
+
showDialog({
|
|
405
|
+
method: 'confirm',
|
|
406
|
+
title: I18n.getLang(
|
|
407
|
+
item.isSleep
|
|
408
|
+
? 'cancel_dialog_delete_item_sleepschedule_titel'
|
|
409
|
+
: 'cancel_dialog_delete_item_wakeupschedule_titel'
|
|
410
|
+
),
|
|
411
|
+
subTitle: I18n.getLang(
|
|
412
|
+
item.isSleep
|
|
413
|
+
? 'cancel_dialog_delete_item_sleepschedule_description'
|
|
414
|
+
: 'cancel_dialog_delete_item_wakeupschedule_description'
|
|
415
|
+
),
|
|
416
|
+
onConfirm: async (_, { close }) => {
|
|
417
|
+
close();
|
|
418
|
+
if (state.loading) return;
|
|
419
|
+
state.loading = true;
|
|
420
|
+
await modDeleteTimeSchedule(
|
|
421
|
+
'del',
|
|
422
|
+
item.isSleep,
|
|
423
|
+
item
|
|
424
|
+
);
|
|
425
|
+
state.loading = false;
|
|
426
|
+
},
|
|
427
|
+
});
|
|
428
|
+
}}
|
|
335
429
|
/>
|
|
336
430
|
)}
|
|
337
431
|
ListHeaderComponent={() => (<Spacer height={cx(10)} />)}
|
|
@@ -408,12 +502,13 @@ const SleepWakeUpCard = (props: {
|
|
|
408
502
|
sleepWakeUp: SleepUIItem | WakeUpUIItem,
|
|
409
503
|
onSwitch: (enable: boolean) => void,
|
|
410
504
|
onPress: () => void
|
|
505
|
+
onLongPress: () => void
|
|
411
506
|
is24HourClock: boolean
|
|
412
507
|
styles: StyleSheet.NamedStyles<any>
|
|
413
508
|
}) => {
|
|
414
|
-
const { sleepWakeUp, is24HourClock, onSwitch, onPress, styles } = props
|
|
509
|
+
const { sleepWakeUp, is24HourClock, onSwitch, onPress, onLongPress, styles } = props
|
|
415
510
|
return (
|
|
416
|
-
<Card style={styles.randomTimingCard} onPress={onPress}>
|
|
511
|
+
<Card style={styles.randomTimingCard} onPress={onPress} onLongPress={onLongPress}>
|
|
417
512
|
<Spacer height={cx(16)} />
|
|
418
513
|
<View style={styles.switchLine}>
|
|
419
514
|
<Text style={styles.time}>
|
|
@@ -79,8 +79,10 @@ const SwitchGradientPage = (props: { theme?: ThemeType }) => {
|
|
|
79
79
|
<View>
|
|
80
80
|
<Card style={styles.stepCard}>
|
|
81
81
|
<Spacer height={cx(16)}/>
|
|
82
|
-
<
|
|
83
|
-
|
|
82
|
+
<View style={{ minHeight: cx(70), flexDirection: 'row'}}>
|
|
83
|
+
<Text style={styles.stepTitle}>{I18n.getLang('matter_gradient_light_on_description_text')}</Text>
|
|
84
|
+
</View>
|
|
85
|
+
<Spacer height={cx(5)}/>
|
|
84
86
|
<View style={styles.stepGroup}>
|
|
85
87
|
<Text style={styles.stepText}>{I18n.getLang('matter_gradient_light_on_title')}</Text>
|
|
86
88
|
<Stepper
|
|
@@ -99,8 +101,9 @@ const SwitchGradientPage = (props: { theme?: ThemeType }) => {
|
|
|
99
101
|
<Spacer/>
|
|
100
102
|
<Card style={styles.stepCard}>
|
|
101
103
|
<Spacer height={cx(16)}/>
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
+
<View style={{ minHeight: cx(70), flexDirection: 'row'}}>
|
|
105
|
+
<Text style={styles.stepTitle}>{I18n.getLang('matter_gradient_light_off_description_text')}</Text>
|
|
106
|
+
</View>
|
|
104
107
|
<View style={styles.stepGroup}>
|
|
105
108
|
<Text style={styles.stepText}>{I18n.getLang('matter_gradient_light_off_title')}</Text>
|
|
106
109
|
<Stepper
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import I18n from "@ledvance/base/src/i18n";
|
|
2
|
+
import { AdjustType, DiySceneInfo } from "@ledvance/base/src/utils/interface";
|
|
2
3
|
import { MoodInfo, MoodUIInfo } from "../mood/Interface";
|
|
3
4
|
|
|
4
5
|
export interface Timer {
|
|
@@ -27,8 +28,8 @@ export interface HSV {
|
|
|
27
28
|
export type Category = 'light' | 'socket' | 'fan' | 'mainLight' | 'secondaryLight'
|
|
28
29
|
|
|
29
30
|
export interface ApplyForItem {
|
|
30
|
-
name?: string
|
|
31
|
-
index?: number
|
|
31
|
+
name?: string
|
|
32
|
+
index?: number
|
|
32
33
|
key: string;
|
|
33
34
|
dp: string;
|
|
34
35
|
type: Category;
|
|
@@ -45,6 +46,7 @@ interface judgmentSupport {
|
|
|
45
46
|
isMixLight?: boolean;
|
|
46
47
|
isFanLight?: boolean;
|
|
47
48
|
isUVCFan?: boolean;
|
|
49
|
+
isMoodStrip?: boolean;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
export interface ManualSettingProps extends judgmentSupport {
|
|
@@ -63,7 +65,8 @@ export enum DeviceType {
|
|
|
63
65
|
MixLight = 'mixLight',
|
|
64
66
|
StripLight = 'stripLight',
|
|
65
67
|
CeilingLight = 'ceilingLight',
|
|
66
|
-
FanLight = 'fanLight'
|
|
68
|
+
FanLight = 'fanLight',
|
|
69
|
+
MoodStrip = 'moodStrip',
|
|
67
70
|
}
|
|
68
71
|
// export type DeviceType = 'LightSource' | 'CeilingLight' | 'StringLight' | 'StripLight' | 'MixLight';
|
|
69
72
|
|
|
@@ -93,12 +96,16 @@ export interface StripLightData extends DeviceData {
|
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
export interface FanLightData extends DeviceData {
|
|
96
|
-
fanSpeed: number
|
|
99
|
+
fanSpeed: number
|
|
97
100
|
direction: 'forward' | 'reverse'
|
|
98
101
|
mode: 'nature' | 'normal'
|
|
99
102
|
disinfect: boolean
|
|
100
103
|
}
|
|
101
104
|
|
|
105
|
+
export interface MoodStripData extends DeviceData {
|
|
106
|
+
adjustType: AdjustType
|
|
107
|
+
}
|
|
108
|
+
|
|
102
109
|
export type ComponentConfig =
|
|
103
110
|
| { type: DeviceType.LightSource; deviceData: DeviceData }
|
|
104
111
|
| { type: DeviceType.MixLight; deviceData: MixLightData }
|
|
@@ -106,6 +113,7 @@ export type ComponentConfig =
|
|
|
106
113
|
| { type: DeviceType.CeilingLight; deviceData: StripLightData }
|
|
107
114
|
| { type: DeviceType.FanLight; deviceData: FanLightData }
|
|
108
115
|
| { type: DeviceType.PowerStrip; deviceData: DeviceData}
|
|
116
|
+
| { type: DeviceType.MoodStrip; deviceData: MoodStripData}
|
|
109
117
|
|
|
110
118
|
export interface TimeScheduleDetailState {
|
|
111
119
|
timeSchedule: Timer;
|
|
@@ -117,14 +125,18 @@ export interface TimeScheduleDetailState {
|
|
|
117
125
|
loading: boolean;
|
|
118
126
|
moodLoading: boolean;
|
|
119
127
|
manualData: ComponentConfig;
|
|
120
|
-
mood?: MoodInfo;
|
|
121
|
-
moods: MoodUIInfo[];
|
|
128
|
+
mood?: MoodInfo | DiySceneInfo;
|
|
129
|
+
moods: MoodUIInfo[] | DiySceneInfo[];
|
|
130
|
+
filterMoods: MoodUIInfo[] | DiySceneInfo[];
|
|
131
|
+
staticTagChecked: boolean;
|
|
132
|
+
dynamicTagChecked: boolean;
|
|
133
|
+
diyTagChecked: boolean;
|
|
122
134
|
timerId: any;
|
|
123
135
|
moodName: string;
|
|
124
136
|
}
|
|
125
137
|
export interface DeviceStateType {
|
|
126
138
|
deviceData: ComponentConfig
|
|
127
|
-
mood?: MoodInfo
|
|
139
|
+
mood?: MoodInfo | DiySceneInfo
|
|
128
140
|
isManual: boolean
|
|
129
141
|
}
|
|
130
142
|
|
|
@@ -2,6 +2,7 @@ import { NativeApi } from '@ledvance/base/src/api/native';
|
|
|
2
2
|
import { Timer, TimerActions } from './Interface';
|
|
3
3
|
import { parseJSON } from '@tuya/tuya-panel-lamp-sdk/lib/utils';
|
|
4
4
|
import { ColorList } from '@ledvance/base/src/components/StripAdjustView';
|
|
5
|
+
import {AdjustType} from "@ledvance/base/src/utils/interface";
|
|
5
6
|
|
|
6
7
|
export const defDeviceData = {
|
|
7
8
|
h: 0,
|
|
@@ -32,6 +33,11 @@ export const defFanLightDeviceData = {
|
|
|
32
33
|
disinfect: false
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
export const defMoodStripDeviceData = {
|
|
37
|
+
...defDeviceData,
|
|
38
|
+
adjustType: AdjustType.COLOUR
|
|
39
|
+
};
|
|
40
|
+
|
|
35
41
|
export const getTimeSchedule = async (deviceId: string): Promise<Timer[]> => {
|
|
36
42
|
const res = await NativeApi.getAllTaskTimer(deviceId);
|
|
37
43
|
if (res.success && Array.isArray(res.data)) {
|
|
@@ -1,50 +1,40 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
Image,
|
|
5
|
-
ScrollView,
|
|
6
|
-
StyleSheet,
|
|
7
|
-
Text,
|
|
8
|
-
TouchableOpacity,
|
|
9
|
-
View,
|
|
10
|
-
} from 'react-native';
|
|
11
|
-
import { useNavigation } from '@react-navigation/core';
|
|
1
|
+
import React, {useCallback, useEffect, useMemo} from 'react';
|
|
2
|
+
import {FlatList, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View,} from 'react-native';
|
|
3
|
+
import {useNavigation} from '@react-navigation/core';
|
|
12
4
|
import Page from '@ledvance/base/src/components/Page';
|
|
13
5
|
import I18n from '@ledvance/base/src/i18n';
|
|
14
6
|
import TextField from '@ledvance/base/src/components/TextField';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
7
|
+
import {cloneDeep, isEqual} from 'lodash';
|
|
8
|
+
import {useReactive} from 'ahooks';
|
|
9
|
+
import {SwitchButton, TimerPicker, Utils} from 'tuya-panel-kit';
|
|
18
10
|
import Spacer from '@ledvance/base/src/components/Spacer';
|
|
19
11
|
import LdvWeekView from '@ledvance/base/src/components/weekSelect';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
ApplyForItem,
|
|
23
|
-
ComponentConfig,
|
|
24
|
-
DeviceType,
|
|
25
|
-
TimeScheduleDetailState,
|
|
26
|
-
Timer,
|
|
27
|
-
TimerActions,
|
|
28
|
-
} from './Interface';
|
|
12
|
+
import {convertTo12HourFormat, loopText, showDialog} from '@ledvance/base/src/utils/common';
|
|
13
|
+
import {ApplyForItem, ComponentConfig, DeviceType, Timer, TimerActions, TimeScheduleDetailState,} from './Interface';
|
|
29
14
|
import res from '@ledvance/base/src/res';
|
|
30
|
-
import {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
useSystemTimeFormate,
|
|
34
|
-
} from '@ledvance/base/src/models/modules/NativePropsSlice';
|
|
35
|
-
import { TimeSchedulePageParams } from './TimeSchedulePage';
|
|
36
|
-
import { Result } from '@ledvance/base/src/models/modules/Result';
|
|
15
|
+
import {useDeviceId, useMoods, useSystemTimeFormate,} from '@ledvance/base/src/models/modules/NativePropsSlice';
|
|
16
|
+
import {TimeSchedulePageParams} from './TimeSchedulePage';
|
|
17
|
+
import {Result} from '@ledvance/base/src/models/modules/Result';
|
|
37
18
|
import DeleteButton from '@ledvance/base/src/components/DeleteButton';
|
|
38
19
|
import InfoText from '@ledvance/base/src/components/InfoText';
|
|
39
20
|
import SegmentControl from '@ledvance/base/src/components/segmentControl';
|
|
40
|
-
import {
|
|
21
|
+
import {useParams} from '@ledvance/base/src/hooks/Hooks';
|
|
41
22
|
import ManualSettings from './components/ManuaSettings';
|
|
42
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
defDeviceData,
|
|
25
|
+
defFanLightDeviceData,
|
|
26
|
+
defMixDeviceData,
|
|
27
|
+
defMoodStripDeviceData,
|
|
28
|
+
defStripDeviceData
|
|
29
|
+
} from './TimeScheduleActions';
|
|
43
30
|
import MoodItem from '../mood/MoodItem';
|
|
44
|
-
import {
|
|
45
|
-
import { MoodUIInfo
|
|
31
|
+
import {getRemoteMoodList} from '../mood/MoodActions';
|
|
32
|
+
import {MoodInfo, MoodUIInfo} from '../mood/Interface';
|
|
46
33
|
import Summary from '@ledvance/base/src/components/Summary'
|
|
47
34
|
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
35
|
+
import Tag from "@ledvance/base/src/components/Tag";
|
|
36
|
+
import DiySceneItem from '@ledvance/base/src/components/DiySceneItem';
|
|
37
|
+
import {DiySceneInfo} from "@ledvance/base/src/utils/interface";
|
|
48
38
|
|
|
49
39
|
const { convertX: cx } = Utils.RatioUtils;
|
|
50
40
|
const { toFixedString } = Utils.NumberUtils;
|
|
@@ -63,6 +53,7 @@ const TimeScheduleDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
63
53
|
const navigation = useNavigation();
|
|
64
54
|
const devId = useDeviceId();
|
|
65
55
|
const [moods, setMoods] = useMoods();
|
|
56
|
+
type MoodsType = typeof params.isMoodStrip extends true ? DiySceneInfo[] : MoodUIInfo[]
|
|
66
57
|
const state = useReactive<TimeScheduleDetailState>({
|
|
67
58
|
timeSchedule: params.mode === 'add' ? newTimeSchedule() : cloneDeep(params.timeSchedule),
|
|
68
59
|
dps: params.mode === 'add' ? {} : params.timeSchedule.dps,
|
|
@@ -78,6 +69,10 @@ const TimeScheduleDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
78
69
|
: params.manualDataDp2Obj(params.timeSchedule.dps).deviceData,
|
|
79
70
|
mood: params.mode === 'add' ? undefined : params.manualDataDp2Obj(params.timeSchedule.dps)?.mood,
|
|
80
71
|
moods: cloneDeep(moods),
|
|
72
|
+
filterMoods: cloneDeep(moods),
|
|
73
|
+
staticTagChecked: true,
|
|
74
|
+
dynamicTagChecked: true,
|
|
75
|
+
diyTagChecked: true,
|
|
81
76
|
timerId: undefined,
|
|
82
77
|
moodName: '',
|
|
83
78
|
});
|
|
@@ -149,15 +144,37 @@ const TimeScheduleDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
149
144
|
useEffect(() => {
|
|
150
145
|
if (state.moods?.length) {
|
|
151
146
|
state.moodName =
|
|
152
|
-
state.moods.find(m =>
|
|
147
|
+
(state.moods as MoodsType).find(m =>
|
|
153
148
|
params.isCeilingLight
|
|
154
|
-
? m.mainLamp.id === state.mood?.mainLamp.id &&
|
|
155
|
-
m.secondaryLamp.id === state.mood?.secondaryLamp.id
|
|
149
|
+
? m.mainLamp.id === (state.mood as MoodInfo)?.mainLamp.id &&
|
|
150
|
+
m.secondaryLamp.id === (state.mood as MoodInfo)?.secondaryLamp.id
|
|
156
151
|
: m.id === state.mood?.id
|
|
157
152
|
)?.name || '';
|
|
158
153
|
}
|
|
159
154
|
}, [state.mood, state.moods]);
|
|
160
155
|
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
if (params.isMoodStrip) {
|
|
158
|
+
state.filterMoods = (state.moods as DiySceneInfo[]).filter(item => {
|
|
159
|
+
return [state.staticTagChecked, state.dynamicTagChecked, state.diyTagChecked].every(it => !it)
|
|
160
|
+
|| (state.staticTagChecked && item.type === 'Static')
|
|
161
|
+
|| (state.dynamicTagChecked && item.type === 'Dynamic')
|
|
162
|
+
|| (state.diyTagChecked && item.type === 'DIY')
|
|
163
|
+
})
|
|
164
|
+
} else {
|
|
165
|
+
state.filterMoods = (state.moods as MoodsType).filter(item => {
|
|
166
|
+
return (
|
|
167
|
+
(state.staticTagChecked && state.dynamicTagChecked) ||
|
|
168
|
+
(!state.staticTagChecked && !state.dynamicTagChecked) ||
|
|
169
|
+
(state.staticTagChecked && item.mainLamp.nodes.length < 2) ||
|
|
170
|
+
(state.dynamicTagChecked &&
|
|
171
|
+
(item.secondaryLamp.nodes.length > 1 || item.mainLamp.nodes.length > 1))
|
|
172
|
+
);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
}, [state.staticTagChecked, state.dynamicTagChecked, state.diyTagChecked, state.moods]);
|
|
177
|
+
|
|
161
178
|
const getFormateTime = useCallback((time: number | string) => {
|
|
162
179
|
if (typeof time === 'number') {
|
|
163
180
|
return `${toFixedString(Math.trunc(time / 60), 2)}:${toFixedString(time % 60, 2)}`;
|
|
@@ -208,7 +225,7 @@ const TimeScheduleDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
208
225
|
}, [params.applyForList.length, params.applyForDisabled]);
|
|
209
226
|
|
|
210
227
|
const getMoodItemEnable = useCallback((item: MoodUIInfo) => {
|
|
211
|
-
return params.isCeilingLight ? ((item.mainLamp.id === state.mood?.mainLamp?.id) && (item.secondaryLamp.id === state.mood?.secondaryLamp?.id)) : item.id === state.mood?.id
|
|
228
|
+
return params.isCeilingLight ? ((item.mainLamp.id === (state.mood as MoodInfo)?.mainLamp?.id) && (item.secondaryLamp.id === (state.mood as MoodInfo)?.secondaryLamp?.id)) : item.id === state.mood?.id
|
|
212
229
|
}, [state.mood, params.isCeilingLight])
|
|
213
230
|
|
|
214
231
|
const styles = StyleSheet.create({
|
|
@@ -284,6 +301,10 @@ const TimeScheduleDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
284
301
|
color: props.theme?.global.fontColor,
|
|
285
302
|
fontSize: cx(14)
|
|
286
303
|
},
|
|
304
|
+
tagLine: {
|
|
305
|
+
flexDirection: 'row',
|
|
306
|
+
marginHorizontal: cx(24),
|
|
307
|
+
}
|
|
287
308
|
});
|
|
288
309
|
|
|
289
310
|
return (
|
|
@@ -473,25 +494,77 @@ const TimeScheduleDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
473
494
|
}}
|
|
474
495
|
/>
|
|
475
496
|
) : (
|
|
476
|
-
!showMoodFanSelectText ?
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
497
|
+
!showMoodFanSelectText ? (
|
|
498
|
+
<View>
|
|
499
|
+
{!(params.isStringLight || params.isStripLight) && <View style={styles.tagLine}>
|
|
500
|
+
<Tag
|
|
501
|
+
checked={state.staticTagChecked}
|
|
502
|
+
text={I18n.getLang('mood_overview_filter_name_text1')}
|
|
503
|
+
onCheckedChange={checked => {
|
|
504
|
+
state.staticTagChecked = checked;
|
|
505
|
+
}}
|
|
506
|
+
/>
|
|
507
|
+
<Spacer width={cx(8)} height={0} />
|
|
508
|
+
<Tag
|
|
509
|
+
checked={state.dynamicTagChecked}
|
|
510
|
+
text={I18n.getLang('mood_overview_filter_name_text2')}
|
|
511
|
+
onCheckedChange={checked => {
|
|
512
|
+
state.dynamicTagChecked = checked;
|
|
513
|
+
}}
|
|
514
|
+
/>
|
|
515
|
+
{
|
|
516
|
+
params.isMoodStrip && <>
|
|
517
|
+
<Spacer width={cx(8)} height={0}/>
|
|
518
|
+
<Tag
|
|
519
|
+
checked={state.diyTagChecked}
|
|
520
|
+
text={I18n.getLang('mood_overview_field_chip_diy')}
|
|
521
|
+
onCheckedChange={checked => {
|
|
522
|
+
state.diyTagChecked = checked;
|
|
523
|
+
}}
|
|
524
|
+
/>
|
|
525
|
+
</>
|
|
526
|
+
}
|
|
527
|
+
</View>}
|
|
528
|
+
{params.isMoodStrip ? <FlatList
|
|
529
|
+
data={state.filterMoods as DiySceneInfo[]}
|
|
530
|
+
renderItem={({item}) => {
|
|
531
|
+
return (
|
|
532
|
+
<DiySceneItem
|
|
533
|
+
enable={item.id === state.mood?.id}
|
|
534
|
+
scene={item}
|
|
535
|
+
onSwitch={_ => {
|
|
536
|
+
state.mood = cloneDeep(item);
|
|
537
|
+
}}
|
|
538
|
+
/>
|
|
539
|
+
);
|
|
540
|
+
}}
|
|
541
|
+
ListHeaderComponent={() => <Spacer height={cx(10)}/>}
|
|
542
|
+
ItemSeparatorComponent={() => <Spacer/>}
|
|
543
|
+
ListFooterComponent={() => <Spacer/>}
|
|
544
|
+
keyExtractor={item => `${item.name}`}
|
|
545
|
+
/> :
|
|
546
|
+
<FlatList
|
|
547
|
+
data={state.filterMoods as MoodUIInfo[]}
|
|
548
|
+
renderItem={({ item }) => {
|
|
549
|
+
return (
|
|
550
|
+
<MoodItem
|
|
551
|
+
enable={getMoodItemEnable(item)}
|
|
552
|
+
mood={item}
|
|
553
|
+
isMix={!!(params.isMixLight || params.isCeilingLight)}
|
|
554
|
+
onSwitch={_ => {
|
|
555
|
+
state.mood = cloneDeep(item);
|
|
556
|
+
}}
|
|
557
|
+
/>
|
|
558
|
+
);
|
|
486
559
|
}}
|
|
560
|
+
ListHeaderComponent={() => <Spacer height={cx(10)} />}
|
|
561
|
+
ItemSeparatorComponent={() => <Spacer />}
|
|
562
|
+
ListFooterComponent={() => <Spacer />}
|
|
563
|
+
keyExtractor={item => `${item.name}`}
|
|
487
564
|
/>
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
ItemSeparatorComponent={() => <Spacer />}
|
|
492
|
-
ListFooterComponent={() => <Spacer />}
|
|
493
|
-
keyExtractor={item => `${item.name}`}
|
|
494
|
-
/> : <View></View>
|
|
565
|
+
}
|
|
566
|
+
</View>
|
|
567
|
+
) : <View></View>
|
|
495
568
|
)}
|
|
496
569
|
<Spacer />
|
|
497
570
|
|
|
@@ -632,7 +705,9 @@ const getDefaultManual = (props: TimeScheduleDetailPageParams): ComponentConfig
|
|
|
632
705
|
? DeviceType.FanLight
|
|
633
706
|
: props.isCeilingLight
|
|
634
707
|
? DeviceType.CeilingLight
|
|
635
|
-
:
|
|
708
|
+
: props.isMoodStrip
|
|
709
|
+
? DeviceType.MoodStrip
|
|
710
|
+
: DeviceType.LightSource
|
|
636
711
|
const deviceData =
|
|
637
712
|
(deviceType === DeviceType.StripLight || deviceType === DeviceType.CeilingLight)
|
|
638
713
|
? defStripDeviceData
|
|
@@ -640,7 +715,9 @@ const getDefaultManual = (props: TimeScheduleDetailPageParams): ComponentConfig
|
|
|
640
715
|
? defMixDeviceData
|
|
641
716
|
: deviceType === DeviceType.FanLight
|
|
642
717
|
? defFanLightDeviceData
|
|
643
|
-
:
|
|
718
|
+
: deviceType === DeviceType.MoodStrip
|
|
719
|
+
? defMoodStripDeviceData
|
|
720
|
+
: defDeviceData;
|
|
644
721
|
|
|
645
722
|
return {
|
|
646
723
|
type: deviceType as any,
|