@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,12 @@ import {useDp} from "@ledvance/base/src/models/modules/NativePropsSlice";
2
2
  import {localeNumber, loopsText, monthFormat, monthFormatShort} from "@ledvance/base/src/utils/common";
3
3
  import {EnergyData} from "./component/EnergyModal";
4
4
  import {NativeApi} from "@ledvance/base/src/api/native";
5
- import {getDataWithSpecified, getDpResultByHour, getDpResultByMonth} from "@ledvance/base/src/models/TuyaApi";
5
+ import {
6
+ DpResultByMonthResData,
7
+ getDataWithSpecified,
8
+ getDpResultByHour,
9
+ getDpResultByMonth
10
+ } from "@ledvance/base/src/models/TuyaApi";
6
11
  import {DateType} from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/co2Data";
7
12
  import {OverviewItem} from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/EnergyConsumptionPage";
8
13
  import {overDays} from "@ledvance/base/src/utils/index";
@@ -44,8 +49,13 @@ export async function getElectricity(devId: string, addEleDpCode: string, date:
44
49
  return res
45
50
  }
46
51
 
52
+ let dpResultByMonthCache: DpResultByMonthResData | undefined = undefined
47
53
  const getDpResultByYear = async (devId: string, addEleDpCode: string, dateStr: string): Promise<OverviewItem[]> => {
48
- const res = await getDpResultByMonth(devId, addEleDpCode, 'sum')
54
+ let res: DpResultByMonthResData | undefined;
55
+ if (!dpResultByMonthCache) {
56
+ dpResultByMonthCache = await getDpResultByMonth(devId, addEleDpCode, 'sum')
57
+ }
58
+ res = dpResultByMonthCache;
49
59
  if (!isEmpty(res)) {
50
60
  if (!isEmpty(res.years)) {
51
61
  const year = dateStr;
@@ -105,6 +115,9 @@ const getDpResultByDate = async (devId: string, addEleDpCode: string, date: stri
105
115
  return []
106
116
  }
107
117
  const res = await getDpResultByHour(devId, addEleDpCode, date, 'sum')
118
+ if (!res) {
119
+ return []
120
+ }
108
121
  const list: Array<OverviewItem> = []
109
122
  const resData = Object.keys(res)?.map(val => {
110
123
  return {key: Number(val?.slice(8, 10)), value: Number(res[val])}
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback } from "react";
2
- import {Image, Platform, StyleSheet, View, Text} from "react-native";
2
+ import {Image, Platform, StyleSheet, View, Text, TouchableOpacity} from "react-native";
3
3
  import {useRoute} from '@react-navigation/core'
4
4
  import Page from "@ledvance/base/src/components/Page";
5
5
  import res from "@ledvance/base/src/res";
@@ -19,6 +19,7 @@ import DateSelectedItem from "@ledvance/ui-biz-bundle/src/newModules/energyConsu
19
19
  import {useReactive, useUpdateEffect} from "ahooks";
20
20
  import {getElectricity} from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/EnergyConsumptionActions";
21
21
  import {useDeviceId} from "@ledvance/base/src/models/modules/NativePropsSlice";
22
+ import DateSwitch from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/component/DateSwitch";
22
23
 
23
24
  const {convertX: cx} = Utils.RatioUtils
24
25
  const {withTheme} = Utils.ThemeUtils
@@ -50,6 +51,14 @@ const EnergyConsumptionChart = (props: { theme?: ThemeType }) => {
50
51
  listEmptyText: {
51
52
  flex: 0
52
53
  },
54
+ downloadIcon: {
55
+ width: cx(24),
56
+ height: cx(24),
57
+ tintColor: props.theme?.global.brand,
58
+ position: 'absolute',
59
+ right: 0,
60
+ top: cx(10)
61
+ }
53
62
  });
54
63
 
55
64
  const getDateType = useCallback((date: string) => {
@@ -64,7 +73,7 @@ const EnergyConsumptionChart = (props: { theme?: ThemeType }) => {
64
73
  }
65
74
  }
66
75
  return DateType.Day;
67
- }, [])
76
+ }, []);
68
77
  const dateType = getDateType(date);
69
78
  const state = useReactive({
70
79
  loading: false,
@@ -87,11 +96,13 @@ const EnergyConsumptionChart = (props: { theme?: ThemeType }) => {
87
96
  getElectricity(devId, addEleDpCode, state.date, state.dateType).then((res) => {
88
97
  state.chartData = res;
89
98
  state.loading = false;
90
- })
99
+ }).catch(()=>{
100
+ state.loading = false;
101
+ });
91
102
  }, [state.date]);
92
103
 
93
104
  const getEmptyDataTip = useCallback(() => {
94
- if (state.over365Days) {
105
+ if (state.over365Days && state.dateType !== DateType.Day) {
95
106
  return I18n.getLang('energyconsumption_Daylimit')
96
107
  }
97
108
  if (state.dateType === DateType.Day && state.over7Days) {
@@ -139,16 +150,26 @@ const EnergyConsumptionChart = (props: { theme?: ThemeType }) => {
139
150
  return (
140
151
  <Page
141
152
  backText={I18n.getLang('consumption_data_annual_bar_chart_system_back_text')}
142
- headlineIcon={state.chartData?.length ? res.download_icon : undefined}
143
- onHeadlineIconClick={() => {
144
- exportFile(state.chartData,params.price,params.unit)
145
- }}
146
153
  showGreenery={false}
147
154
  loading={state.loading}
148
155
  greeneryIcon={res.energy_consumption_greenery}
149
156
  headlineContent={
150
- <View style={{alignItems: 'center', justifyContent: 'center', flex: 1, marginStart: cx(24)}}>
151
- <Text style={{fontSize: cx(24), color: props.theme?.global.brand}}>{state.headlineText}</Text>
157
+ <View style={{width: '100%',flexDirection:'row'}}>
158
+ <DateSwitch
159
+ style={{flex: 1}}
160
+ date={state.date}
161
+ dateType={state.dateType}
162
+ headlineText={state.headlineText}
163
+ onDateChange={(date) => {
164
+ state.date = date;
165
+ }}/>
166
+ <TouchableOpacity onPress={() => {
167
+ exportFile(state.chartData, params.price, params.unit)
168
+ }}>
169
+ <Image
170
+ style={styles.downloadIcon}
171
+ source={state.chartData?.length ? res.download_icon : undefined}/>
172
+ </TouchableOpacity>
152
173
  </View>
153
174
  }
154
175
  >
@@ -0,0 +1,111 @@
1
+ import ThemeType from "@ledvance/base/src/config/themeType";
2
+ import React, {PropsWithChildren, useCallback, useEffect} from "react";
3
+ import {Image, Text, TouchableOpacity, View, ViewProps} from "react-native";
4
+ import {Utils} from "tuya-panel-kit";
5
+ import {useReactive} from "ahooks";
6
+ import {DateType} from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/co2Data";
7
+ import res from "@ledvance/base/src/res";
8
+ import dayjs from "dayjs";
9
+
10
+ const cx = Utils.RatioUtils.convertX;
11
+ const {withTheme} = Utils.ThemeUtils
12
+
13
+ interface DateSwitchProps extends PropsWithChildren<ViewProps> {
14
+ theme?: ThemeType
15
+ headlineText: string,
16
+ date: string,
17
+ dateType: DateType,
18
+ onDateChange: (string) => void
19
+ }
20
+
21
+ export default withTheme(function DateSwitch(props: DateSwitchProps) {
22
+ const {dateType, date, onDateChange, theme, headlineText} = props;
23
+ const state = useReactive({
24
+ date: date,
25
+ dateType: dateType,
26
+ headlineText: headlineText,
27
+ disableArrowLeft: false,
28
+ disableArrowRight: false,
29
+ });
30
+
31
+ useEffect(() => {
32
+ state.date = date;
33
+ state.headlineText = headlineText;
34
+ state.dateType = dateType;
35
+ const {canPreChangeDate, canNextChangeDate} = canPreOrNextChangeDate(dayjs(date));
36
+ state.disableArrowRight = !canNextChangeDate;
37
+ state.disableArrowLeft = !canPreChangeDate;
38
+ }, [date, headlineText, dateType]);
39
+
40
+ const canPreOrNextChangeDate = useCallback((datejs: dayjs.Dayjs) => {
41
+ const minDatejs = dayjs('2000-1-1');
42
+ const nowDatejs = dayjs();
43
+ const year = datejs.year();
44
+ const month = (datejs.month() + 1).toString().padStart(2, '0');
45
+ const day = datejs.date().toString().padStart(2, '0');
46
+ const dateType = state.dateType;
47
+ const dateUnit = dateType === DateType.Year ? 'year' : (dateType === DateType.Month ? 'month' : 'day');
48
+ let canPreChangeDate = datejs.isAfter(minDatejs, dateUnit);
49
+ let canNextChangeDate = datejs.isBefore(nowDatejs, dateUnit);
50
+ let date: string | undefined = undefined;
51
+ if (datejs >= minDatejs && datejs <= nowDatejs) {
52
+ switch (state.dateType) {
53
+ case DateType.Day:
54
+ date = `${year}${month}${day}`;
55
+ break
56
+ case DateType.Month:
57
+ date = `${year}${month}`;
58
+ break
59
+ case DateType.Year:
60
+ date = `${year}`;
61
+ break
62
+ }
63
+ }
64
+ return {date, canPreChangeDate, canNextChangeDate};
65
+ }, [state.dateType]);
66
+
67
+ const changeDate = useCallback((isNextDate: boolean) => {
68
+ const datejs = dayjs(state.date)
69
+ const dateType = state.dateType
70
+ const dateUnit = dateType === DateType.Year ? 'year' : (dateType === DateType.Month ? 'month' : 'day');
71
+ const newDatejs = datejs.add(isNextDate ? 1 : -1, dateUnit);
72
+ const {date, canPreChangeDate, canNextChangeDate} = canPreOrNextChangeDate(newDatejs);
73
+ state.disableArrowRight = !canNextChangeDate;
74
+ state.disableArrowLeft = !canPreChangeDate;
75
+ if (date) {
76
+ onDateChange(date);
77
+ }
78
+ }, [state.date, canPreOrNextChangeDate, state.disableArrowRight, state.disableArrowLeft, onDateChange]);
79
+
80
+ return (<View style={[props.style, {flexDirection: 'row', alignItems: 'center', justifyContent: 'center'}]}>
81
+ <TouchableOpacity
82
+ disabled={state.disableArrowLeft}
83
+ onPress={() => {
84
+ changeDate(false);
85
+ }}>
86
+ <Image
87
+ source={res.arrow_left}
88
+ style={{tintColor: state.disableArrowLeft ? theme?.global.disabledFontColor : theme?.global.brand}}
89
+ height={cx(36)}
90
+ width={cx(36)}/>
91
+ </TouchableOpacity>
92
+ <Text style={{
93
+ fontSize: cx(24),
94
+ minWidth: cx(200),
95
+ textAlign: 'center',
96
+ color: theme?.global.brand,
97
+ fontFamily: 'helvetica_neue_lt_std_roman',
98
+ }}>{state.headlineText}</Text>
99
+ <TouchableOpacity
100
+ disabled={state.disableArrowRight}
101
+ onPress={() => {
102
+ changeDate(true);
103
+ }}>
104
+ <Image
105
+ source={res.arrow_right}
106
+ style={{tintColor: state.disableArrowRight ? theme?.global.disabledFontColor : theme?.global.brand}}
107
+ height={cx(36)}
108
+ width={cx(36)}/>
109
+ </TouchableOpacity>
110
+ </View>)
111
+ })
@@ -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) => {
@@ -1,4 +1,4 @@
1
- import React, {useRef} from 'react';
1
+ import React, {useMemo, useRef} from 'react';
2
2
  import {View} from 'react-native';
3
3
  import ECharts from '@ledvance/react-native-echarts-pro';
4
4
  import I18n from "@ledvance/base/src/i18n";
@@ -28,7 +28,20 @@ const BarChartWithTouch = (props: BarChartProps) => {
28
28
  const dataPriceY = data?.map(item => {
29
29
  return ((isNaN(Number(item.value)) ? 0 : Number(item.value)) * price).toFixed(2);
30
30
  });
31
- const maxValue = Math.max(...dataKwhY);
31
+ const maxValue = useMemo(() => {
32
+ let max = Math.max(...dataKwhY)
33
+ if (max < 0.1) {
34
+ max += 0.02
35
+ max = max - (max % 0.02)
36
+ } else if (max < 1) {
37
+ max += 0.2
38
+ max = max - (max % 0.2)
39
+ } else if (max < 10) {
40
+ max = Math.ceil(max) + 2
41
+ max = max - (max % 2)
42
+ }
43
+ return max
44
+ }, [dataKwhY]);
32
45
  const option = {
33
46
  tooltip: {
34
47
  show: true,
@@ -56,7 +69,7 @@ const BarChartWithTouch = (props: BarChartProps) => {
56
69
  yAxis: [{
57
70
  type: 'value',
58
71
  name: I18n.getLang('consumption_data_annual_bar_chart_text'),
59
- max: Math.ceil(maxValue),
72
+ max: Math.max(maxValue, 0.02),
60
73
  min: 0,
61
74
  position: 'left',
62
75
  axisLabel: {
@@ -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
 
@@ -23,7 +23,7 @@ import { getRemoteMoodList, useMoodScene } from './MoodActions';
23
23
  import { useParams } from '@ledvance/base/src/hooks/Hooks';
24
24
  import { ui_biz_routerKey } from '../../navigation/Routers'
25
25
  import { cloneDeep, filter, map } from 'lodash';
26
- import { saveFlagMode } from '@ledvance/ui-biz-bundle/src/modules/flags/FlagActions';
26
+ import { saveFlagMode } from '../../modules/flags/FlagActions';
27
27
  import { SceneStatusType, WorkMode } from '@ledvance/base/src/utils/interface';
28
28
  import { showDialog } from '@ledvance/base/src/utils/common';
29
29
  import I18n from '@ledvance/base/src/i18n';
@@ -87,6 +87,7 @@ const MoodPage = (props: { theme?: ThemeType }) => {
87
87
  state.loading = false
88
88
  if (res.success && Array.isArray(res.data)) {
89
89
  state.originMoods = cloneDeep(res.data);
90
+ setMoods(cloneDeep(res.data));
90
91
  }
91
92
  }
92
93
 
@@ -311,7 +312,7 @@ const MoodPage = (props: { theme?: ThemeType }) => {
311
312
  right: cx(60),
312
313
  top: Platform.OS === 'android' ? cx(90) : cx(130),
313
314
  maxWidth: cx(200),
314
- backgroundColor: props.theme.card.background,
315
+ backgroundColor: props.theme?.card.background,
315
316
  },
316
317
  popoverItem: {
317
318
  padding: cx(5),
@@ -365,7 +366,7 @@ const MoodPage = (props: { theme?: ThemeType }) => {
365
366
  })
366
367
  }}
367
368
  >
368
- <Image source={res.ic_refresh} style={{ width: cx(24), height: cx(24), tintColor: props.theme.global.fontColor }} />
369
+ <Image source={res.ic_refresh} style={{ width: cx(24), height: cx(24), tintColor: props.theme?.global.fontColor }} />
369
370
  </TouchableOpacity>
370
371
  <Spacer height={cx(10)} />
371
372
  {state.originMoods.length >= MAX_MOOD_COUNT && (
@@ -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}>