@ledvance/ui-biz-bundle 1.1.106 → 1.1.108

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "name": "@ledvance/ui-biz-bundle",
5
5
  "pid": [],
6
6
  "uiid": "",
7
- "version": "1.1.106",
7
+ "version": "1.1.108",
8
8
  "scripts": {},
9
9
  "dependencies": {
10
10
  "@ledvance/base": "^1.x",
@@ -1,6 +1,13 @@
1
1
  import {NativeApi} from '@ledvance/base/src/api/native'
2
2
  import {useDp} from '@ledvance/base/src/models/modules/NativePropsSlice'
3
3
  import {Result} from '@ledvance/base/src/models/modules/Result'
4
+ import { useRandomTime } from '../newModules/randomTime/RandomTimeActions'
5
+ import { useBiorhythm } from '../newModules/biorhythm/BiorhythmActions'
6
+ import { useFixedTime } from '../newModules/fixedTime/FixedTimeActions'
7
+ import { getEndTime, getStartTime, useSleepMode, useWakeUp } from '../newModules/sleepWakeUp/SleepWakeUpActions'
8
+ import { isConflictTask } from '@ledvance/base/src/utils/common'
9
+ import { isEmpty } from 'lodash'
10
+ import { useReactive } from 'ahooks'
4
11
 
5
12
  export const WHITE = 'white'
6
13
  export const COLOUR = 'colour'
@@ -48,4 +55,153 @@ export const setMixSceneDp = (deviceId: string, value: string, dpCodes: Record<s
48
55
 
49
56
  export const useWorkMode = (workModeDpCode: string): [string, (mode: string) => Promise<Result<any>>] => {
50
57
  return useDp(workModeDpCode)
58
+ }
59
+
60
+ interface ConflictDps {
61
+ fixedTimeDpCode?: string
62
+ randomTimeDpCode?: string
63
+ biorhythmDpCode?: string
64
+ sleepDpCode?: string
65
+ wakeUpDpCode?: string
66
+ }
67
+
68
+ interface ConflictItem {
69
+ startTime: number
70
+ endTime: number
71
+ weeks: number[]
72
+ enable: boolean
73
+ }
74
+
75
+ export const useConflictTask = (conflictDps: ConflictDps): [(v: ConflictItem) => boolean, () => void] => {
76
+ const [biorhythm, setBiorhythm] = useBiorhythm(conflictDps.biorhythmDpCode!, true)
77
+ const [fixedTime, setFixedTime] = useFixedTime(conflictDps.fixedTimeDpCode!, false, true)
78
+ const [randomTime, setRandomTime] = useRandomTime(conflictDps.randomTimeDpCode!, false, true)
79
+ const [sleepPlan, setSleepPlan] = useSleepMode(conflictDps.sleepDpCode!, true)
80
+ const [wakeUpPlan, setWakeUpPlan] = useWakeUp(conflictDps.wakeUpDpCode!, true)
81
+ const state = useReactive({
82
+ conflictTask: {}
83
+ })
84
+ const checkConflict = (conflictItem: ConflictItem) => {
85
+ state.conflictTask = {}
86
+ if (conflictDps.biorhythmDpCode && biorhythm.enable){
87
+ const biorhythmTask = {
88
+ startTime: 0,
89
+ endTime: 1440,
90
+ weeks: biorhythm.repeatPeriod.map(item => item.enabled ? 1 : 0)
91
+ }
92
+ if (isConflictTask(conflictItem, biorhythmTask)){
93
+ state.conflictTask = {
94
+ ...state.conflictTask,
95
+ [conflictDps.biorhythmDpCode]: {
96
+ ...biorhythm,
97
+ enable: false
98
+ }
99
+ }
100
+ }
101
+ }
102
+ if (conflictDps.fixedTimeDpCode && fixedTime.length){
103
+ let conflict = false
104
+ const newFixedTime = fixedTime.map(item => {
105
+ if (item.enable && isConflictTask(item, conflictItem)) {
106
+ conflict = true
107
+ return {
108
+ ...item,
109
+ enable: false
110
+ }
111
+ }
112
+ return item
113
+ })
114
+ if (conflict){
115
+ state.conflictTask = {
116
+ ...state.conflictTask,
117
+ [conflictDps.fixedTimeDpCode]: newFixedTime
118
+ }
119
+ }
120
+ }
121
+ if (conflictDps.randomTimeDpCode && randomTime.length){
122
+ let conflict = false
123
+ const newRandomTime = randomTime.map(item => {
124
+ if (item.enable && isConflictTask(item, conflictItem)) {
125
+ conflict = true
126
+ return {
127
+ ...item,
128
+ enable: false
129
+ }
130
+ }
131
+ return item
132
+ })
133
+ if (conflict){
134
+ state.conflictTask = {
135
+ ...state.conflictTask,
136
+ [conflictDps.randomTimeDpCode]: newRandomTime
137
+ }
138
+ }
139
+ }
140
+ if (conflictDps.sleepDpCode && sleepPlan.length){
141
+ let conflict = false
142
+ const newSleepPlan = sleepPlan.map(item => {
143
+ if (item.enable && isConflictTask({
144
+ ...item,
145
+ startTime: getStartTime(item),
146
+ endTime: getEndTime(item)
147
+ }, conflictItem)) {
148
+ conflict = true
149
+ return {
150
+ ...item,
151
+ enable: false
152
+ }
153
+ }
154
+ return item
155
+ })
156
+ if (conflict){
157
+ state.conflictTask = {
158
+ ...state.conflictTask,
159
+ [conflictDps.sleepDpCode]: newSleepPlan
160
+ }
161
+ }
162
+ }
163
+ if (conflictDps.wakeUpDpCode && wakeUpPlan.length){
164
+ let conflict = false
165
+ const newWakeUpPlan = wakeUpPlan.map(item => {
166
+ if (item.enable && isConflictTask({
167
+ ...item,
168
+ startTime: getStartTime(item),
169
+ endTime: getEndTime(item)
170
+ }, conflictItem)) {
171
+ conflict = true
172
+ return {
173
+ ...item,
174
+ enable: false
175
+ }
176
+ }
177
+ return item
178
+ })
179
+ if (conflict){
180
+ state.conflictTask = {
181
+ ...state.conflictTask,
182
+ [conflictDps.wakeUpDpCode]: newWakeUpPlan
183
+ }
184
+ }
185
+ }
186
+ return !isEmpty(state.conflictTask)
187
+ }
188
+
189
+ const resolveConfict = () => {
190
+ if (conflictDps.biorhythmDpCode && state.conflictTask[conflictDps.biorhythmDpCode]){
191
+ setBiorhythm(state.conflictTask[conflictDps.biorhythmDpCode], false).then()
192
+ }
193
+ if (conflictDps.fixedTimeDpCode && state.conflictTask[conflictDps.fixedTimeDpCode]){
194
+ setFixedTime(state.conflictTask[conflictDps.fixedTimeDpCode], false).then()
195
+ }
196
+ if (conflictDps.randomTimeDpCode && state.conflictTask[conflictDps.randomTimeDpCode]){
197
+ setRandomTime(state.conflictTask[conflictDps.randomTimeDpCode], false).then()
198
+ }
199
+ if (conflictDps.sleepDpCode && state.conflictTask[conflictDps.sleepDpCode]){
200
+ setSleepPlan(state.conflictTask[conflictDps.sleepDpCode], false).then()
201
+ }
202
+ if (conflictDps.wakeUpDpCode && state.conflictTask[conflictDps.wakeUpDpCode]){
203
+ setWakeUpPlan(state.conflictTask[conflictDps.wakeUpDpCode], false).then()
204
+ }
205
+ }
206
+ return [checkConflict, resolveConfict]
51
207
  }
@@ -9,6 +9,7 @@ import { useMemo, useState } from "react";
9
9
  import { useUpdateEffect } from "ahooks";
10
10
  import { NativeApi } from "@ledvance/base/src/api/native";
11
11
  import { stripDp2Obj } from "@ledvance/ui-biz-bundle/src/modules/scene/SceneAction";
12
+ import { cloneDeep } from "lodash";
12
13
 
13
14
  export interface ExtraParams extends FlagPageProps, FlagOption {
14
15
  }
@@ -71,7 +72,9 @@ export const useFlag: UseFlagType = (flagCode, extra) => {
71
72
  }
72
73
  return setDps(extraDps)
73
74
  } else {
74
- const hex = obj2Dp(flagItem, extra)
75
+ const cloneFlagItem = cloneDeep(flagItem)
76
+ cloneFlagItem.colors = cloneFlagItem.colors.reverse()
77
+ const hex = obj2Dp(cloneFlagItem, extra)
75
78
  const newHex = extra.isSolarLight ? ('01'+hex.substring(2)) : hex
76
79
  return setDps({ [flagCode]: newHex, [extra.workModeCode]: WORK_MODE.SCENE, [extra.switchLedCode]: true })
77
80
  }
@@ -1,6 +1,6 @@
1
1
  import React, { useCallback, useEffect, useMemo } from "react";
2
2
  import Page from "@ledvance/base/src/components/Page";
3
- import { useDeviceId, useDeviceInfo, useFlagMode, useFlags, useMoods } from "@ledvance/base/src/models/modules/NativePropsSlice";
3
+ import { useDeviceId, useDeviceInfo, useFlagMode, useFlags } from "@ledvance/base/src/models/modules/NativePropsSlice";
4
4
  import { FlatList, Image, TouchableOpacity, View } from "react-native";
5
5
  import Spacer from "@ledvance/base/src/components/Spacer";
6
6
  import { Utils } from "tuya-panel-kit";
@@ -22,8 +22,6 @@ import TextField from "@ledvance/base/src/components/TextField";
22
22
  import { showDialog } from "@ledvance/base/src/utils/common";
23
23
  import { defFlagHash, fnv1aHash } from "./FlagHash";
24
24
  import { NativeApi } from "@ledvance/base/src/api/native";
25
- import { useSceneStatusId } from "@ledvance/ui-biz-bundle/src/newModules/mood/MoodActions";
26
- import { SceneStatusType } from "@ledvance/base/src/utils/interface";
27
25
  import ThemeType from '@ledvance/base/src/config/themeType'
28
26
 
29
27
  const cx = Utils.RatioUtils.convertX
@@ -61,7 +59,6 @@ const FlagPage = (props: { theme?: ThemeType }) => {
61
59
  const devId = useDeviceId()
62
60
  const navigation = useNavigation()
63
61
  const [dps, setDps] = useDps()
64
- const [moods, setMoods] = useMoods()
65
62
  const [flags, setFlags] = useFlags()
66
63
  const [flagMode, setFlagMode] = useFlagMode()
67
64
  const [flagState, setFlag] = useFlag(((params.isStripLight || params.isCeilingLight) ? params?.drawToolLight?.drawToolCode : params.sceneDataCode)!!, {
@@ -70,14 +67,10 @@ const FlagPage = (props: { theme?: ThemeType }) => {
70
67
  isCeilingLight: params.isCeilingLight,
71
68
  ...params
72
69
  })
73
- const [sceneStatusId, setSceneStatusId] = useSceneStatusId({
74
- isSupportSceneStatus: params.isSupportSceneStatus,
75
- sceneStatusType: SceneStatusType.Flag
76
- });
77
70
  const state = useReactive({
78
71
  loading: false,
79
72
  flags: cloneDeep(flags) as FlagUiInfo[],
80
- moods: params.isStripLight ? [] : cloneDeep(moods),
73
+ filterFlags: cloneDeep(flags) as FlagUiInfo[],
81
74
  searchText: ''
82
75
  })
83
76
  const flagId = useMemo(() => {
@@ -97,30 +90,12 @@ const FlagPage = (props: { theme?: ThemeType }) => {
97
90
 
98
91
  useEffect(() => {
99
92
  if (!devInfo.devId) return
100
- if (!flags?.length) {
101
- getRemoteFlagInfo().then()
102
- }
103
- if (params.getRemoteMoodList && !moods?.length) {
104
- params.getRemoteMoodList(devInfo.devId).then(res => {
105
- if (res.success && Array.isArray(res.data)) {
106
- state.moods = res.data
107
- setMoods(cloneDeep(res.data))
108
- }
109
- })
110
- }
93
+ getRemoteFlagInfo().then()
111
94
  }, [devInfo.devId])
112
95
 
113
96
  useUpdateEffect(() => {
114
- state.moods = params.isStripLight ? [] : cloneDeep(moods)
115
- }, [JSON.stringify(moods)])
116
-
117
- useUpdateEffect(() => {
118
- state.flags = cloneDeep(flags)
119
- }, [JSON.stringify(flags)])
120
-
121
- useUpdateEffect(() => {
122
- state.flags = state.searchText !== '' ? cloneDeep(flags).filter(flag => (flag.name ?? '').toLowerCase().includes(state.searchText.toLowerCase())) : cloneDeep(flags)
123
- }, [state.searchText, flags])
97
+ state.filterFlags = state.searchText !== '' ? cloneDeep(state.flags).filter(flag => (flag.name ?? '').toLowerCase().includes(state.searchText.toLowerCase())) : cloneDeep(state.flags)
98
+ }, [state.searchText, state.flags])
124
99
 
125
100
  const getRemoteFlagInfo = async (isRefresh?: boolean) => {
126
101
  const res = await getRemoteFlag(devInfo.devId, isRefresh)
@@ -169,13 +144,12 @@ const FlagPage = (props: { theme?: ThemeType }) => {
169
144
  setFlags(cloneDeep(newScene))
170
145
  state.flags = cloneDeep(newScene)
171
146
  if (mood) {
172
- if (mode === 'del' && (!flagMode?.flagMode || currentMood.id !== flagId || !dps[params.switchLedCode])) {
147
+ if (mode === 'del' && (!flagMode?.flagMode || (params.isSolarLight ? (flagMode?.flagId !== currentMood.id) : currentMood.id !== flagId) || !dps[params.switchLedCode])) {
173
148
  return {
174
149
  success: true
175
150
  }
176
151
  }
177
152
  updateFlagMode(true, mood)
178
- setSceneStatusId(mood.id).then()
179
153
  return setFlag(mood)
180
154
  } else {
181
155
  updateFlagMode(false)
@@ -199,12 +173,10 @@ const FlagPage = (props: { theme?: ThemeType }) => {
199
173
  }
200
174
 
201
175
  const getItemEnable = useCallback((flagItem: FlagUiInfo) =>{
202
- if (params.isSupportSceneStatus && sceneStatusId !== -1){
203
- return flagMode?.flagMode && sceneStatusId === flagItem.id && dps[params.workModeCode] === WORK_MODE.SCENE && dps[params.switchLedCode]
204
- }else{
205
- return flagMode?.flagMode && dps[params.workModeCode] === (params.isCeilingLight ? WORK_MODE.WHITE : params.isStripLight ? WORK_MODE.COLOUR : WORK_MODE.SCENE) && flagId === flagItem.id && dps[params.switchLedCode]
206
- }
207
- }, [params.isSupportSceneStatus, sceneStatusId, dps[params.workModeCode], dps[params.switchLedCode], flagId, flagMode?.flagMode])
176
+ const workMode = params.isCeilingLight ? WORK_MODE.WHITE : params.isStripLight ? WORK_MODE.COLOUR : WORK_MODE.SCENE
177
+ const idEnable = params.isSolarLight ? (flagMode?.flagId === flagItem.id) : (flagId === flagItem.id)
178
+ return flagMode?.flagMode && dps[params.workModeCode] === workMode && idEnable && dps[params.switchLedCode]
179
+ }, [dps[params.workModeCode], dps[params.switchLedCode], flagId, JSON.stringify(flagMode)])
208
180
 
209
181
  return (
210
182
  <Page
@@ -214,8 +186,7 @@ const FlagPage = (props: { theme?: ThemeType }) => {
214
186
  loading={state.loading}
215
187
  onHeadlineIconClick={() => {
216
188
  const useIds = map([
217
- ...state.flags,
218
- ...state.moods
189
+ ...state.flags
219
190
  ], 'id')
220
191
  const idRange = range(0, 256)
221
192
  const unuseId = last(difference(idRange, useIds))
@@ -252,7 +223,7 @@ const FlagPage = (props: { theme?: ThemeType }) => {
252
223
  </TouchableOpacity>
253
224
  </View>
254
225
  <FlatList
255
- data={state.flags}
226
+ data={state.filterFlags}
256
227
  renderItem={({ item }) => <FlagItem
257
228
  enable={getItemEnable(item)}
258
229
  title={item.name}
@@ -262,7 +233,6 @@ const FlagPage = (props: { theme?: ThemeType }) => {
262
233
  if (enable) {
263
234
  state.loading = true
264
235
  await setFlag(item)
265
- await setSceneStatusId(item.id)
266
236
  const flagHash = fnv1aHash(JSON.stringify(item.colors))
267
237
  if (defFlagHash[flagHash]) {
268
238
  NativeApi.putFlagFirebase({
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect } from 'react'
2
2
  import { StyleSheet, View, Text, Image } from 'react-native'
3
3
  import { useRoute, useNavigation } from '@react-navigation/core'
4
4
  import Page from '@ledvance/base/src/components/Page'
5
- import { useDeviceId, useDeviceInfo } from '@ledvance/base/src/models/modules/NativePropsSlice'
5
+ import { useDeviceId, useDeviceInfo, useDps } from '@ledvance/base/src/models/modules/NativePropsSlice'
6
6
  import Strings from '@ledvance/base/src/i18n'
7
7
  import Img from './res'
8
8
  import { useEnable, useWorkMode, useMixRgbcw, useMixScene, useMusicData, useDreamMusic, DreamLightMicMusicData, getRemoteDreamMusic, DreamLightMicMusicUIState, saveRemoteDreamMusic } from './MusicPageActions'
@@ -17,7 +17,7 @@ import LdvSlider from '@ledvance/base/src/components/ldvSlider'
17
17
  import TextFieldStyleButton from '@ledvance/base/src/components/TextFieldStyleButton'
18
18
  import { SelectPageParams } from '../select/SelectPage'
19
19
  import { ui_biz_routerKey } from '../../navigation/Routers'
20
- import { cloneDeep } from 'lodash'
20
+ import { cloneDeep, isEmpty } from 'lodash'
21
21
  import ThemeType from '@ledvance/base/src/config/themeType'
22
22
  import { WorkMode } from '@ledvance/base/src/utils/interface'
23
23
 
@@ -45,6 +45,7 @@ const MusicPage = (props: { theme?: ThemeType }) => {
45
45
  const [, setMusicData] = useMusicData(params.music_data)
46
46
  const [dreamMusic, setDreamMusic] = params.dreamMusicDp ? useDreamMusic(params.dreamMusicDp) : []
47
47
  const [switchLed, setSwitchLed] = useEnable(params.switch_led)
48
+ const [, setDps] = useDps()
48
49
 
49
50
  const state = useReactive({
50
51
  musicEnable: false,
@@ -112,8 +113,12 @@ const MusicPage = (props: { theme?: ThemeType }) => {
112
113
  power: true
113
114
  }, extraDp).then()
114
115
  } else {
115
- if (workMode !== 'music') await setWorkMode(WorkMode.Music)
116
- if (!switchLed) setSwitchLed(true)
116
+ const dps = {}
117
+ if (workMode !== 'music') dps[params.work_mode] = WorkMode.Music
118
+ if (!switchLed) dps[params.switch_led] = true
119
+ if (!isEmpty(dps)){
120
+ await setDps(dps)
121
+ }
117
122
  await MusicManager.open(
118
123
  musicDefalutDatasource[state.phoneGenreMode],
119
124
  () => { },
@@ -184,11 +189,12 @@ const MusicPage = (props: { theme?: ThemeType }) => {
184
189
  }
185
190
 
186
191
  const getSelect = async () => {
192
+ state.musicEnable = workMode === 'music' && !!switchLed
193
+ if (!state.musicEnable) return
187
194
  const res: any = await NativeApi.getJson(deviceId, 'musicSelect')
188
195
  const type = res?.data ? (JSON.parse(res?.data)?.type || 0) : 0
189
196
  state.musicType = res?.data ? JSON.parse(res?.data)?.musicType : params.dreamMusicDp ? 0 : 1
190
197
  state.phoneGenreMode = musicDefalutDatasource[type]?.id
191
- state.musicEnable = workMode === 'music' && !!switchLed
192
198
  if (type !== '' && state.musicType === 1 && state.musicEnable) {
193
199
  openMusic()
194
200
  }
@@ -216,7 +222,7 @@ const MusicPage = (props: { theme?: ThemeType }) => {
216
222
 
217
223
  useEffect(() => {
218
224
  getSelect().then()
219
- }, [workMode])
225
+ }, [workMode, switchLed])
220
226
 
221
227
  const getSelectModeData = useCallback((): [string | undefined, any[]] => {
222
228
  const genreModeData = params.dreamMusicDp && state.musicType === 0 ? state.musicModeData : musicDefalutDatasource
@@ -270,8 +276,8 @@ const MusicPage = (props: { theme?: ThemeType }) => {
270
276
  confirmText: Strings.getLang('cancel_dialog_delete_item_sleepschedule_answer_yes_text'),
271
277
  onConfirm: async (_, { close }) => {
272
278
  close()
273
- state.musicEnable = v
274
279
  await openMusic()
280
+ state.musicEnable = v
275
281
  },
276
282
  })
277
283
  } else {
@@ -65,7 +65,10 @@ const TimerPage = (props: {theme?: ThemeType}) => {
65
65
 
66
66
  useEffect(() => {
67
67
  if (progress.length > 1) {
68
- state.skillList = progress.filter(p => p.progressHook.countdown === 0)
68
+ const runSkill = progress.filter(p => p.progressHook.countdown > 0)
69
+ const skill = progress.filter(p => p.progressHook.countdown === 0)
70
+ state.selectedSkill = state.selectedSkill.filter(item => runSkill.find(r => r.dpId !== item.dpId))
71
+ state.skillList = skill.filter(item => !state.selectedSkill.find(s => s.dpId === item.dpId))
69
72
  } else {
70
73
  state.skillList = []
71
74
  state.selectedSkill = cloneDeep(dps)
@@ -91,7 +91,7 @@ export function getDefBiorhythmUIState(): BiorhythmBean {
91
91
  {
92
92
  index: 1,
93
93
  icon: icon12,
94
- time: 420,
94
+ time: 390,
95
95
  name: I18n.getLang('bio_ryhthm_default_field_text2'),
96
96
  colorTemperature: 25,
97
97
  brightness: 20,
@@ -9,7 +9,7 @@ import {
9
9
  getDefBiorhythmUIState,
10
10
  Plan,
11
11
  } from './BiorhythmBean'
12
- import { Modal, Utils } from 'tuya-panel-kit'
12
+ import { Dialog, Modal, Utils } from 'tuya-panel-kit'
13
13
  import { cloneDeep, sortBy } from 'lodash'
14
14
  import iconList from './iconListData'
15
15
  import pIdList from './pIdList'
@@ -33,6 +33,7 @@ import Spacer from '@ledvance/base/src/components/Spacer'
33
33
  import DeleteButton from '@ledvance/base/src/components/DeleteButton'
34
34
  import { useParams } from '@ledvance/base/src/hooks/Hooks'
35
35
  import ThemeType from '@ledvance/base/src/config/themeType'
36
+ import { useConflictTask } from 'hooks/DeviceDpStateHooks'
36
37
 
37
38
  const cx = Utils.RatioUtils.convertX
38
39
  const { withTheme } = Utils.ThemeUtils
@@ -67,9 +68,8 @@ const BiorhythmPage = (props: { theme?: ThemeType }) => {
67
68
  const { productId } = deviceInfo
68
69
  const is24Hour = useSystemTimeFormate()
69
70
  const devicesJudge = pIdList.some(val => val === productId)
70
- // const [sleepList, setSleepList] = useSleepPlan({ sleep_mode: params.sleepPlanDp })
71
- // const [wakeUpList, setWakeUpList] = useWakeUpPlan({ wakeup_mode: params.wakeUpPlanDp })
72
- // const sleepWakeUpStatus = [...sleepList, ...wakeUpList].some(ele => ele.enable)
71
+ const [checkConflict, resolveConflict] = useConflictTask(params.conflictDps)
72
+
73
73
  const state = useReactive<UIState>({
74
74
  ...biorhythm,
75
75
  showGradientTypeSelectModal: false,
@@ -269,6 +269,29 @@ const BiorhythmPage = (props: { theme?: ThemeType }) => {
269
269
  thumbColor={props.theme?.icon.primary}
270
270
  trackColor={{ false: '#00000026', true: '#ff660036' }}
271
271
  onValueChange={async enable => {
272
+ const biorhythmTask = {
273
+ startTime: 0,
274
+ endTime: 1440,
275
+ weeks: biorhythm.repeatPeriod.map(item => item.enabled ? 1 : 0),
276
+ enable: biorhythm.enable
277
+ }
278
+ if (enable && checkConflict(biorhythmTask)) {
279
+ return showCommonDialog({
280
+ method: 'confirm',
281
+ title: I18n.getLang('conflict_dialog_active_item_bio_rhythm_titel'),
282
+ subTitle: I18n.getLang('conflict_dialog_active_item_bio_rhythm_description'),
283
+ onConfirm: (_, { close }) => {
284
+ resolveConflict()
285
+ close()
286
+ state.loading = true
287
+ state.enable = enable
288
+ requestSetBiorhythm(false)
289
+ },
290
+ onCancel: () => {
291
+ Dialog.close()
292
+ }
293
+ })
294
+ }
272
295
  state.loading = true
273
296
  state.enable = enable
274
297
  requestSetBiorhythm(false)
@@ -91,6 +91,7 @@ export default withTheme(function DateTypeItem(props: DateTypeItemProps) {
91
91
  state.showDateTypeModal = false;
92
92
  }}
93
93
  title={I18n.getLang('date_type')}
94
+ titleTextStyle={{fontWeight: 'bold', fontSize: cx(16)}}
94
95
  cancelText={I18n.getLang('auto_scan_system_cancel')}
95
96
  confirmText={I18n.getLang('auto_scan_system_wifi_confirm')}
96
97
  onConfirm={(item: DateType) => {
@@ -53,7 +53,7 @@ export interface PlugFixedTimer {
53
53
  closeTime: number;
54
54
  }
55
55
  let fixedTimer
56
- type UseFixedTimeType = (dpKey: string, isPlug?: boolean, disableFeature?: boolean) => [FixedTimerUiItem[], (fixedTimeList: FixedTimerUiItem[], manualEdit?: boolean) => Promise<{ success: boolean }>]
56
+ type UseFixedTimeType = (dpKey: string, isPlug?: boolean, disableFeature?: boolean) => [FixedTimerUiItem[], (fixedTimeList: FixedTimerUiItem[], pushFeature?: boolean) => Promise<{ success: boolean }>]
57
57
 
58
58
  export const useFixedTime: UseFixedTimeType = (dpKey, isPlug, disableFeature) => {
59
59
  const deviceId = useDeviceId()
@@ -107,7 +107,7 @@ export const useFixedTime: UseFixedTimeType = (dpKey, isPlug, disableFeature) =>
107
107
  }, [fixedTimeDp])
108
108
 
109
109
 
110
- const setFixedTimeFn = async (fixedTimeList: FixedTimerUiItem[]) => {
110
+ const setFixedTimeFn = async (fixedTimeList: FixedTimerUiItem[], pushFeature = true) => {
111
111
  const fixedData = fixedTimeList.map(item => {
112
112
  const fixedHex = fixedTimeToHex(item, isPlug)
113
113
  return {
@@ -115,7 +115,7 @@ export const useFixedTime: UseFixedTimeType = (dpKey, isPlug, disableFeature) =>
115
115
  v: isPlug ? JSON.stringify({dp: fixedHex}) : fixedHex
116
116
  }
117
117
  })
118
- const cloudStatus = await putFeatureFn(deviceId, isPlug ? plug_fixedFeatureId : fixedFeatureId, JSON.stringify(fixedData))
118
+ const cloudStatus = pushFeature ? await putFeatureFn(deviceId, isPlug ? plug_fixedFeatureId : fixedFeatureId, JSON.stringify(fixedData)) : !pushFeature
119
119
  if (cloudStatus) {
120
120
  const fixedTimerData = {
121
121
  version: 0,
@@ -9,10 +9,10 @@ import { ui_biz_routerKey } from "../../navigation/Routers";
9
9
  import { useReactive, useUpdateEffect } from "ahooks";
10
10
  import Spacer from "@ledvance/base/src/components/Spacer";
11
11
  import TextButton from '@ledvance/base/src/components/TextButton'
12
- import { SwitchButton, Utils } from "tuya-panel-kit";
12
+ import { Dialog, SwitchButton, Utils } from "tuya-panel-kit";
13
13
  import { FixedTimerUiItem, useFixedTime } from "./FixedTimeActions";
14
14
  import Card from "@ledvance/base/src/components/Card";
15
- import { convertMinutesTo12HourFormat, loopText } from "@ledvance/base/src/utils/common";
15
+ import { convertMinutesTo12HourFormat, loopText, isConflictTask, showDialog } from "@ledvance/base/src/utils/common";
16
16
  import { cloneDeep } from "lodash";
17
17
  import dayjs from "dayjs";
18
18
  import { ApplyForItem } from "@ledvance/base/src/utils/interface";
@@ -20,6 +20,7 @@ import { useParams } from "@ledvance/base/src/hooks/Hooks";
20
20
  import Tag from "@ledvance/base/src/components/Tag";
21
21
  import InfoText from "@ledvance/base/src/components/InfoText";
22
22
  import ThemeType from '@ledvance/base/src/config/themeType'
23
+ import { useConflictTask } from "hooks/DeviceDpStateHooks";
23
24
 
24
25
  const { convertX: cx } = Utils.RatioUtils
25
26
  const { withTheme } = Utils.ThemeUtils
@@ -47,6 +48,7 @@ const FixedTimePage = (props: { theme?: ThemeType }) => {
47
48
  const MAX_NUM = params.isPlug ? 10 : 4
48
49
  const is24Hour = useSystemTimeFormate()
49
50
  const [fixedTime, setFixedTime] = useFixedTime(params.fixedTimeDpCode, params.isPlug)
51
+ const [checkConflict, resolveConflict] = useConflictTask(params.conflictDps)
50
52
  const state = useReactive({
51
53
  loading: false,
52
54
  originList: cloneDeep(fixedTime),
@@ -79,7 +81,7 @@ const FixedTimePage = (props: { theme?: ThemeType }) => {
79
81
  return state.originList.length >= MAX_NUM
80
82
  }, [state.originList.length])
81
83
 
82
- const onPost = useCallback(async (mode: 'add' | 'edit' | 'del', fixedTime: FixedTimerUiItem) => {
84
+ const onPost = async (mode: 'add' | 'edit' | 'del', fixedTime: FixedTimerUiItem) => {
83
85
  const cloneFixedTimeList = cloneDeep(state.originList)
84
86
  const idx = state.originList.findIndex(f => f.index === fixedTime.index)
85
87
  if (mode === 'edit') {
@@ -87,12 +89,48 @@ const FixedTimePage = (props: { theme?: ThemeType }) => {
87
89
  }
88
90
  if (mode === 'del') cloneFixedTimeList.splice(idx, 1)
89
91
  const newFixedTimeList = mode === 'add' ? [...state.originList, fixedTime] : cloneFixedTimeList
92
+ if ((mode === 'edit' && fixedTime.enable) || mode === 'add'){
93
+ const cloneList = cloneDeep(newFixedTimeList)
94
+ let itselfConflict = false
95
+ cloneList.forEach((item, idx) => {
96
+ const itself = mode === 'add' ? (idx === cloneList.length - 1) : fixedTime.index === item.index
97
+ if (!itself && item.enable && isConflictTask(item, fixedTime)){
98
+ itselfConflict = true
99
+ item.enable = false
100
+ }
101
+ })
102
+ const isConflict = checkConflict(fixedTime) || itselfConflict
103
+ if (isConflict){
104
+ return new Promise((resolve) => {
105
+ showDialog({
106
+ method: 'confirm',
107
+ title: I18n.getLang('conflict_dialog_active_item_fixedtimecycle_titel'),
108
+ subTitle: I18n.getLang('conflict_dialog_active_item_fixedtimecycle_description'),
109
+ onConfirm: async (_, { close }) => {
110
+ close()
111
+ resolveConflict()
112
+ const res = await setFixedTime(cloneList)
113
+ if (res.success){
114
+ state.originList = cloneDeep(cloneList)
115
+ }
116
+ resolve(res)
117
+ },
118
+ onCancel: () => {
119
+ resolve({
120
+ success: false
121
+ })
122
+ Dialog.close()
123
+ }
124
+ })
125
+ })
126
+ }
127
+ }
90
128
  const res = await setFixedTime(newFixedTimeList)
91
129
  if (res.success) {
92
130
  state.originList = cloneDeep(newFixedTimeList)
93
131
  }
94
132
  return res
95
- }, [state.originList])
133
+ }
96
134
 
97
135
 
98
136
  const styles = StyleSheet.create({
@@ -207,6 +245,19 @@ const FixedTimePage = (props: { theme?: ThemeType }) => {
207
245
  onPress={() => {
208
246
  navigateToEdit('edit', item)
209
247
  }}
248
+ onLongPress={() =>{
249
+ showDialog({
250
+ method: 'confirm',
251
+ title: I18n.getLang('cancel_dialog_delete_item_fixedtimecycle_titel'),
252
+ subTitle: I18n.getLang('cancel_dialog_delete_item_fixedtimecycle_description'),
253
+ onConfirm: async (_, { close }) => {
254
+ close()
255
+ state.loading = true
256
+ await onPost('del', item)
257
+ state.loading = false
258
+ }
259
+ })
260
+ }}
210
261
  />
211
262
  )}
212
263
  keyExtractor={(item: any) => `${item?.index}`}
@@ -253,11 +304,12 @@ const FixedTimeCard = memo((props: {
253
304
  showTags?: boolean,
254
305
  onSwitch: (enable: boolean) => void,
255
306
  onPress: () => void
307
+ onLongPress?: () => void
256
308
  styles: StyleSheet.NamedStyles<any>
257
309
  }) => {
258
- const { is24Hour, fixedTime, tags, showTags, onSwitch, onPress, styles } = props
310
+ const { is24Hour, fixedTime, tags, showTags, onSwitch, onPress, onLongPress, styles } = props
259
311
  return (
260
- <Card style={styles.randomTimingCard} onPress={onPress}>
312
+ <Card style={styles.randomTimingCard} onPress={onPress} onLongPress={onLongPress}>
261
313
  <Spacer height={cx(16)} />
262
314
  <View style={styles.switchLine}>
263
315
  <Text style={styles.time}>
@@ -201,7 +201,10 @@ export const useMoodScene = (params: MoodPageParams): [MoodInfo, (moodInfo: Mood
201
201
  }
202
202
  mainLamp[params.switchLedDp] = true
203
203
  }
204
- return setDps(mainDps)
204
+ return setDps({
205
+ ...mainDps,
206
+ version: params.isStripLight ? 1 : 0
207
+ })
205
208
  };
206
209
  return [moodState, setMoodFn];
207
210
  };
@@ -119,8 +119,9 @@ export default withTheme(MoodItem)
119
119
  export function MixMoodColorsLine(props: { mixSubLight: MoodLampInfo; isMix: boolean, type: 'gradient' | 'separate' }) {
120
120
  const { mixSubLight, isMix } = props;
121
121
  const lightColors = !!(mixSubLight.enable && mixSubLight.nodes.length) ? mixSubLight.nodes?.map(n => {
122
+ const s = Math.round(mapFloatToRange(n.s / 100, 30, 100));
122
123
  return n.isColorNode
123
- ? hsv2Hex(n.h, Math.round(n.s), Math.round(mapFloatToRange(n.v / 100, 50, 100)))
124
+ ? hsv2Hex(n.h, s, Math.round(mapFloatToRange(n.v / 100, 50, 100)))
124
125
  : cctToColor(n.colorTemp.toFixed());
125
126
  }) : ['#eee'];
126
127
 
@@ -43,8 +43,9 @@ const MoodPage = (props: { theme?: ThemeType }) => {
43
43
  const [moodInfo, setMoodInfo] = useMoodScene(params);
44
44
  const [moods, setMoods] = useMoods();
45
45
  const [mainWork, setMainWork] = useWorkMode(params.mainWorkMode);
46
- const [secondaryWork, setSecondaryWork] = useWorkMode(params.secondaryWorkMode!);
46
+ const [secondaryWork] = useWorkMode(params.secondaryWorkMode!);
47
47
  const [switchLed] = useSwitchLed(params.switchLedDp)
48
+ const [, setSecondarySwitch] = useSwitchLed(params.secondarySwitch!)
48
49
  const [flagMode, setFlagMode] = useFlagMode();
49
50
  const [sceneStatusId, setSceneStatusId] = useSceneStatusId({
50
51
  isSupportSceneStatus: params.isSupportSceneStatus,
@@ -87,6 +88,7 @@ const MoodPage = (props: { theme?: ThemeType }) => {
87
88
  state.loading = false
88
89
  if (res.success && Array.isArray(res.data)) {
89
90
  state.originMoods = cloneDeep(res.data);
91
+ setMoods(cloneDeep(res.data));
90
92
  }
91
93
  }
92
94
 
@@ -230,8 +232,8 @@ const MoodPage = (props: { theme?: ThemeType }) => {
230
232
  setMainWork(work).then();
231
233
  }
232
234
  }
233
- if (params.isCeilingLight && params.secondaryWorkMode && secondaryWork === WorkMode.Scene) {
234
- setSecondaryWork(WorkMode.Colour).then();
235
+ if (params.isCeilingLight && params.secondaryWorkMode) {
236
+ setSecondarySwitch(false)
235
237
  }
236
238
  }
237
239
  return {
@@ -52,7 +52,7 @@ export interface PlugRandomTimerItem extends PlugRandomTimer {
52
52
  }
53
53
 
54
54
  let randomTimer
55
- type UseFixedTimeType = (dpKey: string, isPlug?: boolean, disableFeature?: boolean) => [RandomTimerUiItem[], (randomTimeList: RandomTimerUiItem[], manualEdit?: boolean) => Promise<{ success: boolean }>]
55
+ type UseFixedTimeType = (dpKey: string, isPlug?: boolean, disableFeature?: boolean) => [RandomTimerUiItem[], (randomTimeList: RandomTimerUiItem[], pushFeature?: boolean) => Promise<{ success: boolean }>]
56
56
 
57
57
  export const useRandomTime: UseFixedTimeType = (dpKey: string, isPlug?: boolean, disableFeature?: boolean) => {
58
58
  const deviceId = useDeviceId()
@@ -107,7 +107,7 @@ export const useRandomTime: UseFixedTimeType = (dpKey: string, isPlug?: boolean,
107
107
  return () => clearTimeout(randomTimer)
108
108
  }, [randomTimeDp])
109
109
 
110
- const setRandomTimeFn = async (randomTimeList: RandomTimerUiItem[]) => {
110
+ const setRandomTimeFn = async (randomTimeList: RandomTimerUiItem[], pushFeature = true) => {
111
111
  const randomData = randomTimeList.map(item => {
112
112
  const randomHex = randomTimeToHex(item, isPlug)
113
113
  return {
@@ -115,7 +115,7 @@ export const useRandomTime: UseFixedTimeType = (dpKey: string, isPlug?: boolean,
115
115
  v: isPlug ? JSON.stringify({dp: randomHex}) : randomHex
116
116
  }
117
117
  })
118
- const cloudStatus = await putFeatureFn(deviceId, isPlug ? plug_randomFeatureId : randomFeatureId, JSON.stringify(randomData))
118
+ const cloudStatus = pushFeature ? await putFeatureFn(deviceId, isPlug ? plug_randomFeatureId : randomFeatureId, JSON.stringify(randomData)) : !pushFeature
119
119
  if (cloudStatus) {
120
120
  const randomTimerData = {
121
121
  version: 0,
@@ -9,10 +9,10 @@ import { ui_biz_routerKey } from '../../navigation/Routers'
9
9
  import { useReactive, useUpdateEffect } from 'ahooks'
10
10
  import Spacer from '@ledvance/base/src/components/Spacer'
11
11
  import TextButton from '@ledvance/base/src/components/TextButton'
12
- import { SwitchButton, Utils } from 'tuya-panel-kit'
12
+ import { Dialog, SwitchButton, Utils } from 'tuya-panel-kit'
13
13
  import { RandomTimerUiItem, useRandomTime } from './RandomTimeActions'
14
14
  import Card from '@ledvance/base/src/components/Card'
15
- import { convertMinutesTo12HourFormat, loopText } from '@ledvance/base/src/utils/common'
15
+ import { convertMinutesTo12HourFormat, loopText, isConflictTask, showDialog } from '@ledvance/base/src/utils/common'
16
16
  import { cloneDeep } from 'lodash'
17
17
  import dayjs from 'dayjs'
18
18
  import { ApplyForItem } from '@ledvance/base/src/utils/interface'
@@ -20,6 +20,7 @@ import { useParams } from '@ledvance/base/src/hooks/Hooks'
20
20
  import Tag from '@ledvance/base/src/components/Tag'
21
21
  import InfoText from '@ledvance/base/src/components/InfoText'
22
22
  import ThemeType from '@ledvance/base/src/config/themeType'
23
+ import { useConflictTask } from 'hooks/DeviceDpStateHooks'
23
24
 
24
25
  const { convertX: cx } = Utils.RatioUtils
25
26
  const { withTheme } = Utils.ThemeUtils
@@ -48,6 +49,7 @@ const RandomTimePage = (props: { theme?: ThemeType }) => {
48
49
  const MAX_NUM = params.isPlug ? 16 : 4
49
50
  const is24Hour = useSystemTimeFormate()
50
51
  const [randomTime, setRandomTime] = useRandomTime(params.randomTimeDpCode, params.isPlug)
52
+ const [checkConflict, resolveConflict] = useConflictTask(params.conflictDps)
51
53
  const state = useReactive({
52
54
  loading: false,
53
55
  originList: cloneDeep(randomTime),
@@ -80,7 +82,7 @@ const RandomTimePage = (props: { theme?: ThemeType }) => {
80
82
  return state.originList.length >= MAX_NUM
81
83
  }, [state.originList.length])
82
84
 
83
- const onPost = useCallback(async (mode: 'add' | 'edit' | 'del', randomTime: RandomTimerUiItem) => {
85
+ const onPost = async (mode: 'add' | 'edit' | 'del', randomTime: RandomTimerUiItem) => {
84
86
  const cloneRandomTime = cloneDeep(state.originList)
85
87
  const idx = state.originList.findIndex(f => f.index === randomTime.index)
86
88
  if (mode === 'edit') {
@@ -88,12 +90,49 @@ const RandomTimePage = (props: { theme?: ThemeType }) => {
88
90
  }
89
91
  if (mode === 'del') cloneRandomTime.splice(idx, 1)
90
92
  const newRandomTimeList = mode === 'add' ? [...state.originList, randomTime] : cloneRandomTime
93
+ if ((mode === 'edit' && randomTime.enable) || mode === 'add') {
94
+ const cloneList = cloneDeep(newRandomTimeList)
95
+ let itselfConflict = false
96
+ cloneList.forEach((item, idx) => {
97
+ const itself = mode === 'add' ? (idx === cloneList.length - 1) : randomTime.index === item.index
98
+ if (!itself && item.enable && isConflictTask(item, randomTime)){
99
+ itselfConflict = true
100
+ item.enable = false
101
+ }
102
+ })
103
+ const isConflict = checkConflict(randomTime) || itselfConflict
104
+ if (isConflict) {
105
+ return new Promise((resolve) => {
106
+ showDialog({
107
+ method: 'confirm',
108
+ title: I18n.getLang('conflict_dialog_active_item_randomtimecycle_titel'),
109
+ subTitle: I18n.getLang('conflict_dialog_active_item_randomtimecycle_description'),
110
+ onConfirm: async (_, { close }) => {
111
+ close()
112
+ resolveConflict()
113
+ const res = await setRandomTime(cloneList)
114
+ if (res.success) {
115
+ state.originList = cloneDeep(cloneList)
116
+ }
117
+ resolve(res)
118
+ },
119
+ onCancel: () => {
120
+ resolve({
121
+ success: false
122
+ })
123
+ Dialog.close()
124
+ }
125
+ })
126
+ })
127
+ }
128
+ }
129
+
91
130
  const res = await setRandomTime(newRandomTimeList)
92
- if(res.success){
131
+ if (res.success) {
93
132
  state.originList = cloneDeep(newRandomTimeList)
94
133
  }
95
134
  return res
96
- }, [state.originList])
135
+ }
97
136
 
98
137
 
99
138
  const styles = StyleSheet.create({
@@ -208,6 +247,19 @@ const RandomTimePage = (props: { theme?: ThemeType }) => {
208
247
  onPress={() => {
209
248
  navigateToEdit('edit', item)
210
249
  }}
250
+ onLongPress={() =>{
251
+ showDialog({
252
+ method: 'confirm',
253
+ title: I18n.getLang('cancel_dialog_delete_item_randomtimecycle_titel'),
254
+ subTitle: I18n.getLang('cancel_dialog_delete_item_fixedtimecycle_description'),
255
+ onConfirm: async (_, { close }) => {
256
+ close()
257
+ state.loading = true
258
+ await onPost('del', item)
259
+ state.loading = false
260
+ }
261
+ })
262
+ }}
211
263
  />
212
264
  )}
213
265
  keyExtractor={(item: any) => `${item?.index}`}
@@ -254,10 +306,11 @@ const RandomTimeCard = (props: {
254
306
  showTags?: boolean,
255
307
  onSwitch: (enable: boolean) => void,
256
308
  onPress: () => void
309
+ onLongPress?: () => void
257
310
  }) => {
258
- const { is24Hour, randomTime, tags, showTags, onSwitch, onPress, styles } = props
311
+ const { is24Hour, randomTime, tags, showTags, onSwitch, onPress, onLongPress, styles } = props
259
312
  return (
260
- <Card style={styles.randomTimingCard} onPress={onPress}>
313
+ <Card style={styles.randomTimingCard} onPress={onPress} onLongPress={onLongPress}>
261
314
  <Spacer height={cx(16)} />
262
315
  <View style={styles.switchLine}>
263
316
  <Text style={styles.time}>
@@ -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>
@@ -22,6 +22,7 @@ import { ui_biz_routerKey } from '../../navigation/Routers';
22
22
  import Tag from '@ledvance/base/src/components/Tag';
23
23
  import { cloneDeep } from 'lodash';
24
24
  import ThemeType from '@ledvance/base/src/config/themeType'
25
+ import { showDialog } from '@ledvance/base/src/utils/common';
25
26
 
26
27
  const { convertX: cx } = Utils.RatioUtils;
27
28
  const { withTheme } = Utils.ThemeUtils
@@ -76,6 +77,8 @@ const TimeSchedulePage = (props: { theme?: ThemeType }) => {
76
77
  useEffect(() => {
77
78
  getTimeSchedule(devId).then(res => {
78
79
  state.originList = cloneDeep(res)
80
+ const status = res?.some(item => item.enable);
81
+ setTimeScheduleStatus(status);
79
82
  });
80
83
  }, [state.flag]);
81
84
 
@@ -198,31 +201,44 @@ const TimeSchedulePage = (props: { theme?: ThemeType }) => {
198
201
  )}
199
202
  {params.applyForList.length > 1 && !!state.originList.length && !(params.isCeilingLight || params.isMixLight) && showTags}
200
203
  {state.timeScheduleList.length > 0 ? <FlatList
201
- data={state.timeScheduleList}
202
- renderItem={({ item }) => (
203
- <ScheduleCard
204
- item={item}
205
- tags={params.applyForList}
206
- showTag={params.applyForList.length > 1}
207
- onEnableChange={async enable => {
208
- state.loading = true;
209
- await modDeleteTimeSchedule('update', {
210
- ...item,
211
- enable,
212
- });
213
- state.loading = false;
214
- }}
215
- onPress={() => {
216
- navigateToEdit('update', item);
217
- }}
218
- />
219
- )}
220
- keyExtractor={item => item.id.toString()}
221
- ListEmptyComponent={<Spacer />}
222
- ListHeaderComponent={() => <Spacer height={cx(10)} />}
223
- ItemSeparatorComponent={() => <Spacer />}
224
- ListFooterComponent={() => <Spacer height={cx(30)} />}
225
- /> :
204
+ data={state.timeScheduleList}
205
+ renderItem={({ item }) => (
206
+ <ScheduleCard
207
+ item={item}
208
+ tags={params.applyForList}
209
+ showTag={params.applyForList.length > 1}
210
+ onEnableChange={async enable => {
211
+ state.loading = true;
212
+ await modDeleteTimeSchedule('update', {
213
+ ...item,
214
+ enable,
215
+ });
216
+ state.loading = false;
217
+ }}
218
+ onPress={() => {
219
+ navigateToEdit('update', item);
220
+ }}
221
+ onLongPress={() =>{
222
+ showDialog({
223
+ method: 'confirm',
224
+ title: I18n.getLang('cancel_dialog_delete_item_timeschedule_titel'),
225
+ subTitle: I18n.getLang('cancel_dialog_delete_item_timeschedule_description'),
226
+ onConfirm: async (_, { close }) => {
227
+ state.loading = true;
228
+ close();
229
+ await modDeleteTimeSchedule('delete', item);
230
+ state.loading = false;
231
+ },
232
+ });
233
+ }}
234
+ />
235
+ )}
236
+ keyExtractor={item => item.id.toString()}
237
+ ListEmptyComponent={<Spacer />}
238
+ ListHeaderComponent={() => <Spacer height={cx(10)} />}
239
+ ItemSeparatorComponent={() => <Spacer />}
240
+ ListFooterComponent={() => <Spacer height={cx(30)} />}
241
+ /> :
226
242
  <View style={styles.emptyContainer}>
227
243
  <Spacer height={cx(60)} />
228
244
  <Image
@@ -274,12 +274,22 @@ function ManualSettings(props: ManualSettingProps) {
274
274
 
275
275
  const stripLightCard = useMemo(() => {
276
276
  const deviceData = state.deviceData as StripLightData
277
+ const getBlockColor = () => {
278
+ if (deviceData.activeKey === 1) {
279
+ const s = Math.round(mapFloatToRange(state.deviceData.s / 100, 30, 100))
280
+ return hsv2Hex(state.deviceData.h, s, 100)
281
+ }
282
+ if (deviceData.activeKey === 0) {
283
+ return cctToColor(state.deviceData.temperature)
284
+ }
285
+ return props.theme?.card.background
286
+ }
277
287
  return (
278
288
  <View>
279
289
  <Card style={{ marginHorizontal: cx(24) }}>
280
290
  <LdvSwitch
281
291
  title={I18n.getLang('light_sources_tile_tw_lighting_headline')}
282
- color={props.theme?.card.background}
292
+ color={getBlockColor()}
283
293
  colorAlpha={1}
284
294
  enable={state.applyForList[0]?.enable}
285
295
  setEnable={(enable: boolean) => {
@@ -18,10 +18,11 @@ interface ScheduleCardProps {
18
18
  tags: ApplyForItem[]
19
19
  onEnableChange: (enable: boolean) => void
20
20
  onPress: (item: any) => void
21
+ onLongPress?: (item: any) => void
21
22
  }
22
23
 
23
24
  const ScheduleCard = (props: ScheduleCardProps) => {
24
- const { item, style, showTag, tags, onEnableChange, onPress } = props;
25
+ const { item, style, showTag, tags, onEnableChange, onPress, onLongPress } = props;
25
26
  const is24HourClock = useSystemTimeFormate()
26
27
  const showTags = useMemo(() => {
27
28
  return tags.filter(tag => item.dps.hasOwnProperty(tag.dp))
@@ -93,6 +94,9 @@ const ScheduleCard = (props: ScheduleCardProps) => {
93
94
  onPress={() => {
94
95
  onPress(item);
95
96
  }}
97
+ onLongPress={() =>{
98
+ onLongPress && onLongPress(item)
99
+ }}
96
100
  >
97
101
  <View style={styles.infoContainer}>
98
102
  <Text style={styles.time}>{is24HourClock ? item.time : convertTo12HourFormat(item.time)}</Text>