@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.
Files changed (37) hide show
  1. package/package.json +1 -1
  2. package/src/hooks/DeviceDpStateHooks.ts +156 -0
  3. package/src/modules/flags/FlagActions.ts +4 -1
  4. package/src/modules/flags/FlagPage.tsx +12 -42
  5. package/src/modules/music/MusicPage.tsx +13 -7
  6. package/src/modules/timer/TimerPage.tsx +4 -1
  7. package/src/modules/timer/TimerPageAction.ts +0 -1
  8. package/src/navigation/Routers.ts +3 -1
  9. package/src/newModules/biorhythm/BiorhythmBean.ts +1 -1
  10. package/src/newModules/biorhythm/BiorhythmPage.tsx +27 -4
  11. package/src/newModules/diyScene/DefaultScenes.ts +438 -0
  12. package/src/newModules/diyScene/DiySceneActions.ts +232 -0
  13. package/src/newModules/diyScene/DiySceneEditorPage.tsx +359 -0
  14. package/src/newModules/diyScene/DiyScenePage.tsx +297 -0
  15. package/src/newModules/diyScene/Router.ts +25 -0
  16. package/src/newModules/energyConsumption/EnergyConsumptionActions.ts +15 -2
  17. package/src/newModules/energyConsumption/EnergyConsumptionChart.tsx +31 -10
  18. package/src/newModules/energyConsumption/component/DateSwitch.tsx +111 -0
  19. package/src/newModules/energyConsumption/component/DateTypeItem.tsx +1 -0
  20. package/src/newModules/energyConsumption/component/NewBarChart.tsx +16 -3
  21. package/src/newModules/fixedTime/FixedTimeActions.ts +3 -3
  22. package/src/newModules/fixedTime/FixedTimePage.tsx +58 -6
  23. package/src/newModules/mood/MoodActions.ts +4 -1
  24. package/src/newModules/mood/MoodItem.tsx +2 -1
  25. package/src/newModules/mood/MoodPage.tsx +4 -3
  26. package/src/newModules/randomTime/RandomTimeActions.ts +3 -3
  27. package/src/newModules/randomTime/RandomTimePage.tsx +60 -7
  28. package/src/newModules/sleepWakeUp/SleepWakeUpActions.ts +21 -11
  29. package/src/newModules/sleepWakeUp/SleepWakeUpPage.tsx +108 -13
  30. package/src/newModules/switchGradient/SwitchGradientPage.tsx +7 -4
  31. package/src/newModules/swithInching/SwithInching.tsx +1 -0
  32. package/src/newModules/timeSchedule/Interface.ts +19 -7
  33. package/src/newModules/timeSchedule/TimeScheduleActions.ts +6 -0
  34. package/src/newModules/timeSchedule/TimeScheduleDetailPage.tsx +134 -57
  35. package/src/newModules/timeSchedule/TimeSchedulePage.tsx +23 -6
  36. package/src/newModules/timeSchedule/components/ManuaSettings.tsx +42 -9
  37. 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, SleepUIData, SleepUIItem, WakeUpData, WakeUpItem, WakeUpUIData, WakeUpUIItem } from './Interface'
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: WakeUpUIData) => Promise<Result<any>>, boolean]
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: WakeUpUIData) => {
81
- const featureData = wakeUp?.nodes.map(item => {
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(wakeUp)).then()
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: SleepUIData) => Promise<Result<any>>, boolean]
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: SleepUIData) => {
235
- const featureData = sleep?.nodes.map(item => {
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(sleep)).then()
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
- sleepModeDpCode: string
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.sleepModeDpCode)
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
- const def = {
118
- version: 0,
119
- num: cloneSleepWakeUp.length,
120
- nodes: cloneDeep(cloneSleepWakeUp)
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(def) : await setWakeUpList(def)
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
- <Text style={styles.stepTitle}>{I18n.getLang('matter_gradient_light_on_description_text')}</Text>
83
- <Spacer height={cx(10)}/>
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
- <Text style={styles.stepTitle}>{I18n.getLang('matter_gradient_light_off_description_text')}</Text>
103
- <Spacer height={cx(10)}/>
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
@@ -225,6 +225,7 @@ const SwitchInching = (props: { theme?: ThemeType }) => {
225
225
  setMinute={s => {
226
226
  state.second = s;
227
227
  }}
228
+ maxHour={61}
228
229
  />
229
230
  </View>
230
231
  </Page>
@@ -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, { useCallback, useEffect, useMemo } from 'react';
2
- import {
3
- FlatList,
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 { cloneDeep, isEqual } from 'lodash';
16
- import { useReactive } from 'ahooks';
17
- import { SwitchButton, TimerPicker, Utils } from 'tuya-panel-kit';
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 { convertTo12HourFormat, loopText, showDialog } from '@ledvance/base/src/utils/common';
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
- useDeviceId,
32
- useMoods,
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 { useParams } from '@ledvance/base/src/hooks/Hooks';
21
+ import {useParams} from '@ledvance/base/src/hooks/Hooks';
41
22
  import ManualSettings from './components/ManuaSettings';
42
- import { defDeviceData, defFanLightDeviceData, defMixDeviceData, defStripDeviceData } from './TimeScheduleActions';
23
+ import {
24
+ defDeviceData,
25
+ defFanLightDeviceData,
26
+ defMixDeviceData,
27
+ defMoodStripDeviceData,
28
+ defStripDeviceData
29
+ } from './TimeScheduleActions';
43
30
  import MoodItem from '../mood/MoodItem';
44
- import { getRemoteMoodList } from '../mood/MoodActions';
45
- import { MoodUIInfo } from '../mood/Interface';
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 ? <FlatList
477
- data={state.moods}
478
- renderItem={({ item }) => {
479
- return (
480
- <MoodItem
481
- enable={getMoodItemEnable(item)}
482
- mood={item}
483
- isMix={!!(params.isMixLight || params.isCeilingLight)}
484
- onSwitch={_ => {
485
- state.mood = cloneDeep(item);
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
- ListHeaderComponent={() => <Spacer height={cx(10)} />}
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
- : DeviceType.LightSource
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
- : defDeviceData;
718
+ : deviceType === DeviceType.MoodStrip
719
+ ? defMoodStripDeviceData
720
+ : defDeviceData;
644
721
 
645
722
  return {
646
723
  type: deviceType as any,