@ledvance/group-ui-biz-bundle 1.0.95 → 1.0.97
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/modules/biorhythm/BiorhythmDetailPage.tsx +1 -0
- package/src/modules/biorhythm/BiorhythmPage.tsx +8 -2
- package/src/modules/energyConsumption/EnergyConsumptionActions.ts +144 -137
- package/src/modules/energyConsumption/EnergyConsumptionChart.tsx +74 -71
- package/src/modules/energyConsumption/EnergyConsumptionDetail.tsx +13 -11
- package/src/modules/energyConsumption/EnergyConsumptionPage.tsx +7 -6
- package/src/modules/energyConsumption/component/EnergyModal.tsx +1 -1
- package/src/modules/fixedTimeForPlug/FixedTimeForPlugDetailPage.tsx +6 -4
- package/src/modules/fixedTimeForPlug/FixedTimeForPlugPage.tsx +33 -5
- package/src/modules/fixedTimingForLight/FixedTimingForLightDetailPage.tsx +6 -4
- package/src/modules/fixedTimingForLight/FixedTimingForLightPage.tsx +34 -6
- package/src/modules/music/MusicActions.ts +3 -0
- package/src/modules/music/MusicPage.tsx +2 -0
- package/src/modules/randomTimeForPlug/RandomTimeForPlugDetailPage.tsx +6 -4
- package/src/modules/randomTimeForPlug/RandomTimeForPlugPage.tsx +34 -6
- package/src/modules/randomTimingForLight/ItemCard.tsx +3 -2
- package/src/modules/randomTimingForLight/RandomTimingForLightDetailPage.tsx +6 -4
- package/src/modules/randomTimingForLight/RandomTimingForLightPage.tsx +34 -6
- package/src/modules/sleepWakeUp/SleepWakeUpActions.ts +1 -1
- package/src/modules/sleepWakeUp/SleepWakeUpDetailPage.tsx +9 -8
- package/src/modules/sleepWakeUp/SleepWakeUpPage.tsx +120 -38
- package/src/modules/timeSchedule/TimeScheduleDetailPage.tsx +3 -2
- package/src/modules/timeSchedule/TimeSchedulePage.tsx +15 -1
- package/src/modules/timeSchedule/components/ManuaSettings.tsx +18 -8
|
@@ -16,7 +16,6 @@ import { useTimeZoneCity } from '@ledvance/base/src/models/modules/NativePropsSl
|
|
|
16
16
|
import { flattenDeep, isNumber, sumBy } from 'lodash';
|
|
17
17
|
import {
|
|
18
18
|
exchangeNumber,
|
|
19
|
-
exportFile,
|
|
20
19
|
localeNumber,
|
|
21
20
|
monthFormat,
|
|
22
21
|
monthFormatShort,
|
|
@@ -28,6 +27,7 @@ import { EnergyConsumptionDetailProps } from './EnergyConsumptionDetail';
|
|
|
28
27
|
import { EnergyConsumptionChartProps } from './EnergyConsumptionChart';
|
|
29
28
|
import SegmentControl from '@ledvance/base/src/components/segmentControl';
|
|
30
29
|
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
30
|
+
import { exportEnergyCsv } from "./EnergyConsumptionActions";
|
|
31
31
|
|
|
32
32
|
const { convertX: cx } = Utils.RatioUtils;
|
|
33
33
|
const { withTheme } = Utils.ThemeUtils;
|
|
@@ -285,7 +285,8 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
|
|
|
285
285
|
)}
|
|
286
286
|
headlineIcon={(state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList).length ? res.download_icon : undefined}
|
|
287
287
|
onHeadlineIconClick={() => {
|
|
288
|
-
|
|
288
|
+
const values = (state.isSolarMode ? state.solarOverviewList : state.wifiOverviewList).map(item => [item.key, item.value, (Number(state.price) * Number(item.value)).toFixed(2)])
|
|
289
|
+
exportEnergyCsv(values, state.unit)
|
|
289
290
|
}}
|
|
290
291
|
showGreenery={state.isSolarMode}
|
|
291
292
|
greeneryIcon={res.energy_consumption_greenery}
|
|
@@ -309,7 +310,7 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
|
|
|
309
310
|
{/* tip */}
|
|
310
311
|
<Spacer height={cx(15)} />
|
|
311
312
|
<View style={styles.showTip}>
|
|
312
|
-
<Text style={{ fontSize: cx(14) }}>
|
|
313
|
+
<Text style={{ fontSize: cx(14), color: props.theme?.global.fontColor, }}>
|
|
313
314
|
{I18n.getLang(
|
|
314
315
|
state.isSolarMode
|
|
315
316
|
? 'generation_data_description_text'
|
|
@@ -378,7 +379,7 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
|
|
|
378
379
|
style={{
|
|
379
380
|
height: cx(20),
|
|
380
381
|
width: cx(20),
|
|
381
|
-
tintColor: props.theme?.button.
|
|
382
|
+
tintColor: props.theme?.button.primary,
|
|
382
383
|
}}
|
|
383
384
|
/>
|
|
384
385
|
</View>
|
|
@@ -401,7 +402,7 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
|
|
|
401
402
|
style={{
|
|
402
403
|
height: cx(20),
|
|
403
404
|
width: cx(20),
|
|
404
|
-
tintColor: props.theme?.button.
|
|
405
|
+
tintColor: props.theme?.button.primary,
|
|
405
406
|
}}
|
|
406
407
|
/>
|
|
407
408
|
</TouchableOpacity>
|
|
@@ -420,7 +421,7 @@ const EnergyConsumptionPage = (props: { theme?: ThemeType }) => {
|
|
|
420
421
|
<Image
|
|
421
422
|
source={res.energy_consumption_cash}
|
|
422
423
|
resizeMode="contain"
|
|
423
|
-
style={{ height: cx(20), width: cx(20), tintColor: props.theme?.button.
|
|
424
|
+
style={{ height: cx(20), width: cx(20), tintColor: props.theme?.button.primary }}
|
|
424
425
|
/>
|
|
425
426
|
</View>
|
|
426
427
|
<View>
|
|
@@ -59,7 +59,7 @@ const EnergyModal = (props: EnergyModalProps) => {
|
|
|
59
59
|
<Text style={{ color: props.theme?.global.fontColor }}>{text[length - 4] + text[length - 3] + ':'}</Text>
|
|
60
60
|
<Spacer />
|
|
61
61
|
<Text
|
|
62
|
-
style={{ textDecorationLine: 'underline', color: props.theme?.button.
|
|
62
|
+
style={{ textDecorationLine: 'underline', color: props.theme?.button.primary }}
|
|
63
63
|
onPress={() => openLink(`${text[length - 2]}:${text[length - 1]}${text[length]}`)}
|
|
64
64
|
>
|
|
65
65
|
{`${text[length - 2]}:${text[length - 1]}${text[length]}`}
|
|
@@ -33,6 +33,7 @@ interface FixedTimeDetailParam extends FixedTimeParam {
|
|
|
33
33
|
const newFixedTimeItem = (): FixedTimeItem => {
|
|
34
34
|
const startTime = dayjs().hour() * 60 + dayjs().minute()
|
|
35
35
|
return {
|
|
36
|
+
name: I18n.getLang('fixedTimeCycle_socket_headline'),
|
|
36
37
|
enable: true,
|
|
37
38
|
channel: 0,
|
|
38
39
|
weeks: [0, 0, 0, 0, 0, 0, 0, 0],
|
|
@@ -89,14 +90,14 @@ const FixedTimeForPlugDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
89
90
|
return timeInterval >= workTime
|
|
90
91
|
}, [state.item.startTime, state.item.endTime, state.onHour, state.onMinute, state.offHour, state.offMinute])
|
|
91
92
|
|
|
92
|
-
const canSave = useMemo(() => {
|
|
93
|
-
return state.item.name && state.item.name.length < 33 && state.item.channel !== undefined && isTimeEffective
|
|
94
|
-
}, [state.item.name, state.item.channel, isTimeEffective])
|
|
95
|
-
|
|
96
93
|
const showConfirm = useMemo(() => {
|
|
97
94
|
return !isEqual(state.item, params.mode === 'edit' ? params.item : initItem)
|
|
98
95
|
}, [JSON.stringify(state.item), JSON.stringify(params.item)])
|
|
99
96
|
|
|
97
|
+
const canSave = useMemo(() => {
|
|
98
|
+
return state.item.name && state.item.name.length < 33 && state.item.channel !== undefined && isTimeEffective && (showConfirm || params.mode === 'add')
|
|
99
|
+
}, [state.item.name, state.item.channel, isTimeEffective, showConfirm])
|
|
100
|
+
|
|
100
101
|
const onSave = async () => {
|
|
101
102
|
if (!canSave) {
|
|
102
103
|
return
|
|
@@ -203,6 +204,7 @@ const FixedTimeForPlugDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
203
204
|
/>
|
|
204
205
|
{/* pick */}
|
|
205
206
|
<TimerPicker
|
|
207
|
+
key={props.theme?.type}
|
|
206
208
|
itemTextColor='#aeadb5'
|
|
207
209
|
style={{ paddingVertical: cx(0), marginVertical: cx(0), backgroundColor: props.theme?.global.background }}
|
|
208
210
|
pickerFontColor={props.theme?.global.fontColor}
|
|
@@ -10,7 +10,7 @@ import {useReactive} from "ahooks";
|
|
|
10
10
|
import {ui_biz_routerKey} from "../../navigation/Routers";
|
|
11
11
|
import {cloneDeep} from "lodash";
|
|
12
12
|
import Spacer from "@ledvance/base/src/components/Spacer";
|
|
13
|
-
import {Utils} from "tuya-panel-kit";
|
|
13
|
+
import {Utils, Dialog} from "tuya-panel-kit";
|
|
14
14
|
import ItemCard from "./ItemCard";
|
|
15
15
|
import InfoText from "@ledvance/base/src/components/InfoText";
|
|
16
16
|
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
@@ -43,18 +43,46 @@ const FixedTimeForPlugPage = (props: { theme?: ThemeType}) => {
|
|
|
43
43
|
})
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const onPost = useCallback(async (mode: 'add' | 'edit' | 'del', fixedTime: FixedTimeItem, goBack?: boolean) => {
|
|
46
|
+
const onPost = useCallback(async (mode: 'add' | 'edit' | 'del' | 'set', fixedTime: FixedTimeItem, goBack?: boolean) => {
|
|
47
47
|
state.loading = true
|
|
48
48
|
const cloneFixedTimeList = cloneDeep(fixedTimeList)
|
|
49
49
|
const idx = fixedTimeList.findIndex(it => it.index === fixedTime.index)
|
|
50
|
-
if (mode === 'edit') {
|
|
50
|
+
if (mode === 'edit' || mode === 'set') {
|
|
51
51
|
cloneFixedTimeList.splice(idx, 1, fixedTime)
|
|
52
52
|
}
|
|
53
53
|
if (mode === 'del') cloneFixedTimeList.splice(idx, 1)
|
|
54
|
-
|
|
54
|
+
let newFixedTimeList = mode === 'add' ? [...fixedTimeList, {
|
|
55
55
|
...fixedTime,
|
|
56
56
|
index: fixedTimeList.length
|
|
57
57
|
}] : cloneFixedTimeList
|
|
58
|
+
if (((mode === 'edit' || mode === 'set') && fixedTime.enable) || mode === 'add') {
|
|
59
|
+
const cloneList = cloneDeep(newFixedTimeList)
|
|
60
|
+
let itselfConflict = false
|
|
61
|
+
cloneList.forEach((item, idx) => {
|
|
62
|
+
const itself = mode === 'add' ? (idx === cloneList.length - 1) : fixedTime.index === item.index
|
|
63
|
+
if (!itself && item.enable && isConflictTask(item, fixedTime)) {
|
|
64
|
+
itselfConflict = true
|
|
65
|
+
item.enable = false
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
if (itselfConflict && mode === 'set') {
|
|
69
|
+
return showDialog({
|
|
70
|
+
method: 'confirm',
|
|
71
|
+
title: I18n.getLang('conflict_dialog_active_item_fixedtimecycle_titel'),
|
|
72
|
+
subTitle: I18n.getLang('conflict_dialog_active_item_fixedtimecycle_description'),
|
|
73
|
+
onConfirm: async (_, { close }) => {
|
|
74
|
+
close()
|
|
75
|
+
setFixedTimeList(cloneList)
|
|
76
|
+
state.loading = false
|
|
77
|
+
},
|
|
78
|
+
onCancel: () => {
|
|
79
|
+
state.loading = false
|
|
80
|
+
Dialog.close()
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
newFixedTimeList = cloneList
|
|
85
|
+
}
|
|
58
86
|
const res = await setFixedTimeList(newFixedTimeList)
|
|
59
87
|
state.loading = false
|
|
60
88
|
if (res.success && goBack) {
|
|
@@ -106,7 +134,7 @@ const FixedTimeForPlugPage = (props: { theme?: ThemeType}) => {
|
|
|
106
134
|
item={item}
|
|
107
135
|
is24Hour={params.is24Hour}
|
|
108
136
|
onSwitch={async (v) => {
|
|
109
|
-
await onPost('
|
|
137
|
+
await onPost('set', {
|
|
110
138
|
...item,
|
|
111
139
|
enable: v,
|
|
112
140
|
settingTime: new Date().getTime()
|
|
@@ -36,6 +36,7 @@ interface FixedTimeDetailParam extends FixedTimingParam {
|
|
|
36
36
|
const newFixedTimingItem = (): FixedTimingItem => {
|
|
37
37
|
const startTime = dayjs().hour() * 60 + dayjs().minute()
|
|
38
38
|
return {
|
|
39
|
+
name: I18n.getLang('fixedTimeCycle_socket_headline'),
|
|
39
40
|
power: true,
|
|
40
41
|
channel: 0,
|
|
41
42
|
weeks: [0, 0, 0, 0, 0, 0, 0],
|
|
@@ -105,14 +106,14 @@ const FixedTimingForLightDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
105
106
|
return timeInterval >= workTime
|
|
106
107
|
}, [state.item.startTime, state.item.endTime, state.onHour, state.onMinute, state.offHour, state.offMinute])
|
|
107
108
|
|
|
108
|
-
const canSave = useMemo(() => {
|
|
109
|
-
return state.item.name && state.item.name.length < 33 && state.item.channel !== undefined && isTimeEffective
|
|
110
|
-
}, [state.item.name, state.item.channel, isTimeEffective])
|
|
111
|
-
|
|
112
109
|
const showConfirm = useMemo(() => {
|
|
113
110
|
return !isEqual(state.item, params.mode === 'edit' ? params.item : initItem)
|
|
114
111
|
}, [JSON.stringify(state.item), JSON.stringify(params.item)])
|
|
115
112
|
|
|
113
|
+
const canSave = useMemo(() => {
|
|
114
|
+
return state.item.name && state.item.name.length < 33 && state.item.channel !== undefined && isTimeEffective && (showConfirm || params.mode === 'add')
|
|
115
|
+
}, [state.item.name, state.item.channel, isTimeEffective, showConfirm])
|
|
116
|
+
|
|
116
117
|
const onSave = async () => {
|
|
117
118
|
if (!canSave) {
|
|
118
119
|
return
|
|
@@ -230,6 +231,7 @@ const FixedTimingForLightDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
230
231
|
/>
|
|
231
232
|
{/* pick */}
|
|
232
233
|
<TimerPicker
|
|
234
|
+
key={props.theme?.type}
|
|
233
235
|
itemTextColor='#aeadb5'
|
|
234
236
|
style={{ paddingVertical: cx(0), marginVertical: cx(0), backgroundColor: props.theme?.global.background }}
|
|
235
237
|
pickerFontColor={props.theme?.global.fontColor}
|
|
@@ -6,7 +6,7 @@ import res from "@ledvance/base/src/res/index";
|
|
|
6
6
|
import {useReactive} from "ahooks";
|
|
7
7
|
import React, {useCallback, useMemo} from "react";
|
|
8
8
|
import {FlatList, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View} from "react-native";
|
|
9
|
-
import {Utils} from "tuya-panel-kit";
|
|
9
|
+
import {Utils, Dialog} from "tuya-panel-kit";
|
|
10
10
|
import {ui_biz_routerKey} from "../../navigation/Routers";
|
|
11
11
|
import {FixedTimingItem, FixedTimingParam, useFixedTiming} from "./FixedTimingForLightAction";
|
|
12
12
|
import Spacer from "@ledvance/base/src/components/Spacer";
|
|
@@ -14,7 +14,7 @@ import ItemCard from "./ItemCard";
|
|
|
14
14
|
import {cloneDeep} from "lodash";
|
|
15
15
|
import InfoText from "@ledvance/base/src/components/InfoText";
|
|
16
16
|
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
17
|
-
import { showDialog } from "@ledvance/base/src/utils/common";
|
|
17
|
+
import { isConflictTask, showDialog } from "@ledvance/base/src/utils/common";
|
|
18
18
|
|
|
19
19
|
const {convertX: cx, topBarHeight} = Utils.RatioUtils;
|
|
20
20
|
const { withTheme } = Utils.ThemeUtils
|
|
@@ -43,18 +43,46 @@ const FixedTimeForLightPage = (props: { theme?: ThemeType}) => {
|
|
|
43
43
|
})
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const onPost = useCallback(async (mode: 'add' | 'edit' | 'del', fixedTiming: FixedTimingItem, goBack?: boolean) => {
|
|
46
|
+
const onPost = useCallback(async (mode: 'add' | 'edit' | 'del' | 'set', fixedTiming: FixedTimingItem, goBack?: boolean) => {
|
|
47
47
|
state.loading = true
|
|
48
48
|
const cloneFixedTimingList = cloneDeep(fixedTimingList)
|
|
49
49
|
const idx = fixedTimingList.findIndex(it => it.index === fixedTiming.index)
|
|
50
|
-
if (mode === 'edit') {
|
|
50
|
+
if (mode === 'edit' || mode === 'set') {
|
|
51
51
|
cloneFixedTimingList.splice(idx, 1, fixedTiming)
|
|
52
52
|
}
|
|
53
53
|
if (mode === 'del') cloneFixedTimingList.splice(idx, 1)
|
|
54
|
-
|
|
54
|
+
let newFixedTimingList = mode === 'add' ? [...fixedTimingList, {
|
|
55
55
|
...fixedTiming,
|
|
56
56
|
index: fixedTimingList.length
|
|
57
57
|
}] : cloneFixedTimingList
|
|
58
|
+
if (((mode === 'edit' || mode === 'set') && fixedTiming.power) || mode === 'add') {
|
|
59
|
+
const cloneList = cloneDeep(newFixedTimingList)
|
|
60
|
+
let itselfConflict = false
|
|
61
|
+
cloneList.forEach((item, idx) => {
|
|
62
|
+
const itself = mode === 'add' ? (idx === cloneList.length - 1) : fixedTiming.index === item.index
|
|
63
|
+
if (!itself && item.power && isConflictTask(item, fixedTiming)) {
|
|
64
|
+
itselfConflict = true
|
|
65
|
+
item.power = false
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
if (itselfConflict && mode === 'set') {
|
|
69
|
+
return showDialog({
|
|
70
|
+
method: 'confirm',
|
|
71
|
+
title: I18n.getLang('conflict_dialog_active_item_fixedtimecycle_titel'),
|
|
72
|
+
subTitle: I18n.getLang('conflict_dialog_active_item_fixedtimecycle_description'),
|
|
73
|
+
onConfirm: async (_, { close }) => {
|
|
74
|
+
close()
|
|
75
|
+
await setFixedTimingList(cloneList)
|
|
76
|
+
state.loading = false
|
|
77
|
+
},
|
|
78
|
+
onCancel: () => {
|
|
79
|
+
state.loading = false
|
|
80
|
+
Dialog.close()
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
newFixedTimingList = cloneList
|
|
85
|
+
}
|
|
58
86
|
const res = await setFixedTimingList(newFixedTimingList)
|
|
59
87
|
state.loading = false
|
|
60
88
|
if (res.success && goBack) {
|
|
@@ -111,7 +139,7 @@ const FixedTimeForLightPage = (props: { theme?: ThemeType}) => {
|
|
|
111
139
|
item={item}
|
|
112
140
|
is24Hour={params.is24Hour}
|
|
113
141
|
onSwitch={async (v) => {
|
|
114
|
-
await onPost('
|
|
142
|
+
await onPost('set', {
|
|
115
143
|
...item,
|
|
116
144
|
power: v,
|
|
117
145
|
settingTime: new Date().getTime()
|
|
@@ -47,6 +47,9 @@ export const useDreamMusicData = (musicOption: MusicPageParams) => {
|
|
|
47
47
|
}
|
|
48
48
|
dps[musicOption.workModeDp] = WorkMode.Music
|
|
49
49
|
dps[musicOption.switchLedDp] = true
|
|
50
|
+
if (musicOption.colourLedDp && musicOption.isCeilingLight){
|
|
51
|
+
dps[musicOption.colourLedDp] = true
|
|
52
|
+
}
|
|
50
53
|
}else{
|
|
51
54
|
dps[musicOption.workModeDp] = v.lastWorkMode
|
|
52
55
|
}
|
|
@@ -33,6 +33,7 @@ interface RandomTimeDetailParam extends RandomTimeParam {
|
|
|
33
33
|
const newRandomTimeItem = (): RandomTimeItem => {
|
|
34
34
|
const startTime = dayjs().hour() * 60 + dayjs().minute()
|
|
35
35
|
return {
|
|
36
|
+
name: I18n.getLang('randomtimecycle_sockets_headline_text'),
|
|
36
37
|
enable: true,
|
|
37
38
|
channel: 0,
|
|
38
39
|
weeks: [0, 0, 0, 0, 0, 0, 0, 0],
|
|
@@ -51,14 +52,14 @@ const RandomTimeForPlugDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
51
52
|
loading: false
|
|
52
53
|
})
|
|
53
54
|
|
|
54
|
-
const canSave = useMemo(() => {
|
|
55
|
-
return state.item.name && state.item.name.length < 33 && state.item.channel !== undefined
|
|
56
|
-
}, [state.item.name, state.item.channel])
|
|
57
|
-
|
|
58
55
|
const showConfirm = useMemo(() => {
|
|
59
56
|
return !isEqual(state.item, params.mode === 'edit' ? params.item : initItem)
|
|
60
57
|
}, [JSON.stringify(state.item), JSON.stringify(params.item)])
|
|
61
58
|
|
|
59
|
+
const canSave = useMemo(() => {
|
|
60
|
+
return state.item.name && state.item.name.length < 33 && state.item.channel !== undefined && (showConfirm || params.mode === 'add')
|
|
61
|
+
}, [state.item.name, state.item.channel, showConfirm])
|
|
62
|
+
|
|
62
63
|
const onSave = async () => {
|
|
63
64
|
if (!canSave) {
|
|
64
65
|
return
|
|
@@ -162,6 +163,7 @@ const RandomTimeForPlugDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
162
163
|
/>
|
|
163
164
|
{/* pick */}
|
|
164
165
|
<TimerPicker
|
|
166
|
+
key={props.theme?.type}
|
|
165
167
|
itemTextColor="#aeadb5"
|
|
166
168
|
style={{ paddingVertical: cx(0), marginVertical: cx(0), backgroundColor: props.theme?.global.background }}
|
|
167
169
|
pickerFontColor={props.theme?.global.fontColor}
|
|
@@ -6,7 +6,7 @@ import res from "@ledvance/base/src/res/index";
|
|
|
6
6
|
import {useReactive} from "ahooks";
|
|
7
7
|
import React, {useCallback, useMemo} from "react";
|
|
8
8
|
import {FlatList, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View} from "react-native";
|
|
9
|
-
import {Utils} from "tuya-panel-kit";
|
|
9
|
+
import {Dialog, Utils} from "tuya-panel-kit";
|
|
10
10
|
import {ui_biz_routerKey} from "../../navigation/Routers";
|
|
11
11
|
import {RandomTimeItem, RandomTimeParam, useRandomTime} from "./RandomTimeForPlugAction";
|
|
12
12
|
import Spacer from "@ledvance/base/src/components/Spacer";
|
|
@@ -14,7 +14,7 @@ import ItemCard from "./ItemCard";
|
|
|
14
14
|
import {cloneDeep} from "lodash";
|
|
15
15
|
import InfoText from "@ledvance/base/src/components/InfoText";
|
|
16
16
|
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
17
|
-
import { showDialog } from "@ledvance/base/src/utils/common";
|
|
17
|
+
import { isConflictTask, showDialog } from "@ledvance/base/src/utils/common";
|
|
18
18
|
|
|
19
19
|
const {convertX: cx, topBarHeight} = Utils.RatioUtils;
|
|
20
20
|
const { withTheme } = Utils.ThemeUtils
|
|
@@ -43,18 +43,46 @@ const RandomTimeForPlugPage = (props: { theme?: ThemeType}) => {
|
|
|
43
43
|
})
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const onPost = useCallback(async (mode: 'add' | 'edit' | 'del', randomTime: RandomTimeItem, goBack?: boolean) => {
|
|
46
|
+
const onPost = useCallback(async (mode: 'add' | 'edit' | 'del' | 'set', randomTime: RandomTimeItem, goBack?: boolean) => {
|
|
47
47
|
state.loading = true
|
|
48
48
|
const cloneRandomTimeList = cloneDeep(randomTimeList)
|
|
49
49
|
const idx = randomTimeList.findIndex(it => it.index === randomTime.index)
|
|
50
|
-
if (mode === 'edit') {
|
|
50
|
+
if (mode === 'edit' || mode === 'set') {
|
|
51
51
|
cloneRandomTimeList.splice(idx, 1, randomTime)
|
|
52
52
|
}
|
|
53
53
|
if (mode === 'del') cloneRandomTimeList.splice(idx, 1)
|
|
54
|
-
|
|
54
|
+
let newRandomTimeList = mode === 'add' ? [...randomTimeList, {
|
|
55
55
|
...randomTime,
|
|
56
56
|
index: randomTimeList.length
|
|
57
57
|
}] : cloneRandomTimeList
|
|
58
|
+
if (((mode === 'edit' || mode === 'set') && randomTime.enable) || mode === 'add') {
|
|
59
|
+
const cloneList = cloneDeep(newRandomTimeList)
|
|
60
|
+
let itselfConflict = false
|
|
61
|
+
cloneList.forEach((item, idx) => {
|
|
62
|
+
const itself = mode === 'add' ? (idx === cloneList.length - 1) : randomTime.index === item.index
|
|
63
|
+
if (!itself && item.enable && isConflictTask(item, randomTime)) {
|
|
64
|
+
itselfConflict = true
|
|
65
|
+
item.enable = false
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
if (itselfConflict && mode === 'set') {
|
|
69
|
+
return showDialog({
|
|
70
|
+
method: 'confirm',
|
|
71
|
+
title: I18n.getLang('conflict_dialog_active_item_fixedtimecycle_titel'),
|
|
72
|
+
subTitle: I18n.getLang('conflict_dialog_active_item_fixedtimecycle_description'),
|
|
73
|
+
onConfirm: async (_, { close }) => {
|
|
74
|
+
close()
|
|
75
|
+
await setRandomTimeList(cloneList)
|
|
76
|
+
state.loading = false
|
|
77
|
+
},
|
|
78
|
+
onCancel: () => {
|
|
79
|
+
state.loading = false
|
|
80
|
+
Dialog.close()
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
newRandomTimeList = cloneList
|
|
85
|
+
}
|
|
58
86
|
const res = await setRandomTimeList(newRandomTimeList)
|
|
59
87
|
state.loading = false
|
|
60
88
|
if (res.success && goBack) {
|
|
@@ -120,7 +148,7 @@ const RandomTimeForPlugPage = (props: { theme?: ThemeType}) => {
|
|
|
120
148
|
item={item}
|
|
121
149
|
is24Hour={params.is24Hour}
|
|
122
150
|
onSwitch={async (v) => {
|
|
123
|
-
await onPost('
|
|
151
|
+
await onPost('set', {
|
|
124
152
|
...item,
|
|
125
153
|
enable: v,
|
|
126
154
|
settingTime: new Date().getTime()
|
|
@@ -24,10 +24,11 @@ export interface ItemCardProps<T> {
|
|
|
24
24
|
is24Hour?: boolean,
|
|
25
25
|
onSwitch: (enable: boolean) => void
|
|
26
26
|
onPress: () => void
|
|
27
|
+
onLongPress: () => void
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
const ItemCard = <T, >(props: ItemCardProps<T>) => {
|
|
30
|
-
const {item, is24Hour, onSwitch, onPress} = props
|
|
31
|
+
const {item, is24Hour, onSwitch, onPress, onLongPress} = props
|
|
31
32
|
// 判断是否关闭
|
|
32
33
|
const closed = getIsClosed(item)
|
|
33
34
|
|
|
@@ -56,7 +57,7 @@ const ItemCard = <T, >(props: ItemCardProps<T>) => {
|
|
|
56
57
|
})
|
|
57
58
|
|
|
58
59
|
return (
|
|
59
|
-
<Card style={styles.itemCard} onPress={onPress}>
|
|
60
|
+
<Card style={styles.itemCard} onPress={onPress} onLongPress={onLongPress}>
|
|
60
61
|
<Spacer height={cx(16)}/>
|
|
61
62
|
<View style={styles.switchLine}>
|
|
62
63
|
<Text style={styles.time}>
|
|
@@ -35,6 +35,7 @@ interface RandomTimeDetailParam extends RandomTimingParam {
|
|
|
35
35
|
const newRandomTimingItem = (): RandomTimingItem => {
|
|
36
36
|
const startTime = dayjs().hour() * 60 + dayjs().minute()
|
|
37
37
|
return {
|
|
38
|
+
name: I18n.getLang('randomtimecycle_sockets_headline_text'),
|
|
38
39
|
power: true,
|
|
39
40
|
channel: 0,
|
|
40
41
|
weeks: [0, 0, 0, 0, 0, 0, 0],
|
|
@@ -66,14 +67,14 @@ const RandomTimingForLightDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
66
67
|
state.isColorMode = brightness === 0 && temperature === 0 && (hue !== 0 || saturation !== 0 || value !== 0)
|
|
67
68
|
}, [])
|
|
68
69
|
|
|
69
|
-
const canSave = useMemo(() => {
|
|
70
|
-
return state.item.name && state.item.name.length < 33 && state.item.channel !== undefined
|
|
71
|
-
}, [state.item.name, state.item.channel])
|
|
72
|
-
|
|
73
70
|
const showConfirm = useMemo(() => {
|
|
74
71
|
return !isEqual(state.item, params.mode === 'edit' ? params.item : initItem)
|
|
75
72
|
}, [JSON.stringify(state.item), JSON.stringify(params.item)])
|
|
76
73
|
|
|
74
|
+
const canSave = useMemo(() => {
|
|
75
|
+
return state.item.name && state.item.name.length < 33 && state.item.channel !== undefined && (showConfirm || params.mode === 'add')
|
|
76
|
+
}, [state.item.name, state.item.channel, showConfirm])
|
|
77
|
+
|
|
77
78
|
const onSave = async () => {
|
|
78
79
|
if (!canSave) {
|
|
79
80
|
return
|
|
@@ -185,6 +186,7 @@ const RandomTimingForLightDetailPage = (props: { theme?: ThemeType }) => {
|
|
|
185
186
|
/>
|
|
186
187
|
{/* pick */}
|
|
187
188
|
<TimerPicker
|
|
189
|
+
key={props.theme?.type}
|
|
188
190
|
itemTextColor='#aeadb5'
|
|
189
191
|
style={{ paddingVertical: cx(0), marginVertical: cx(0), backgroundColor: props.theme?.global.background }}
|
|
190
192
|
pickerFontColor={props.theme?.global.fontColor}
|
|
@@ -6,7 +6,7 @@ import res from "@ledvance/base/src/res/index";
|
|
|
6
6
|
import {useReactive} from "ahooks";
|
|
7
7
|
import React, {useCallback, useMemo} from "react";
|
|
8
8
|
import {FlatList, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View} from "react-native";
|
|
9
|
-
import {Utils} from "tuya-panel-kit";
|
|
9
|
+
import {Utils, Dialog} from "tuya-panel-kit";
|
|
10
10
|
import {ui_biz_routerKey} from "../../navigation/Routers";
|
|
11
11
|
import {RandomTimingItem, RandomTimingParam, useRandomTiming} from "./RandomTimingForLightAction";
|
|
12
12
|
import Spacer from "@ledvance/base/src/components/Spacer";
|
|
@@ -14,7 +14,7 @@ import ItemCard from "./ItemCard";
|
|
|
14
14
|
import {cloneDeep} from "lodash";
|
|
15
15
|
import InfoText from "@ledvance/base/src/components/InfoText";
|
|
16
16
|
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
17
|
-
import { showDialog } from "@ledvance/base/src/utils/common";
|
|
17
|
+
import { isConflictTask, showDialog } from "@ledvance/base/src/utils/common";
|
|
18
18
|
|
|
19
19
|
const {convertX: cx, topBarHeight} = Utils.RatioUtils;
|
|
20
20
|
const { withTheme } = Utils.ThemeUtils
|
|
@@ -43,18 +43,46 @@ const RandomTimeForLightPage = (props: { theme?: ThemeType}) => {
|
|
|
43
43
|
})
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const onPost = useCallback(async (mode: 'add' | 'edit' | 'del', randomTiming: RandomTimingItem, goBack?: boolean) => {
|
|
46
|
+
const onPost = useCallback(async (mode: 'add' | 'edit' | 'del' | 'set', randomTiming: RandomTimingItem, goBack?: boolean) => {
|
|
47
47
|
state.loading = true
|
|
48
48
|
const cloneRandomTimingList = cloneDeep(randomTimingList)
|
|
49
49
|
const idx = randomTimingList.findIndex(it => it.index === randomTiming.index)
|
|
50
|
-
if (mode === 'edit') {
|
|
50
|
+
if (mode === 'edit' || mode === 'set') {
|
|
51
51
|
cloneRandomTimingList.splice(idx, 1, randomTiming)
|
|
52
52
|
}
|
|
53
53
|
if (mode === 'del') cloneRandomTimingList.splice(idx, 1)
|
|
54
|
-
|
|
54
|
+
let newRandomTimingList = mode === 'add' ? [...randomTimingList, {
|
|
55
55
|
...randomTiming,
|
|
56
56
|
index: randomTimingList.length
|
|
57
57
|
}] : cloneRandomTimingList
|
|
58
|
+
if (((mode === 'edit' || mode === 'set') && randomTiming.power) || mode === 'add') {
|
|
59
|
+
const cloneList = cloneDeep(newRandomTimingList)
|
|
60
|
+
let itselfConflict = false
|
|
61
|
+
cloneList.forEach((item, idx) => {
|
|
62
|
+
const itself = mode === 'add' ? (idx === cloneList.length - 1) : randomTiming.index === item.index
|
|
63
|
+
if (!itself && item.power && isConflictTask(item, randomTiming)) {
|
|
64
|
+
itselfConflict = true
|
|
65
|
+
item.power = false
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
if (itselfConflict && mode === 'set') {
|
|
69
|
+
return showDialog({
|
|
70
|
+
method: 'confirm',
|
|
71
|
+
title: I18n.getLang('conflict_dialog_active_item_fixedtimecycle_titel'),
|
|
72
|
+
subTitle: I18n.getLang('conflict_dialog_active_item_fixedtimecycle_description'),
|
|
73
|
+
onConfirm: async (_, { close }) => {
|
|
74
|
+
close()
|
|
75
|
+
await setRandomTimingList(cloneList)
|
|
76
|
+
state.loading = false
|
|
77
|
+
},
|
|
78
|
+
onCancel: () => {
|
|
79
|
+
state.loading = false
|
|
80
|
+
Dialog.close()
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
newRandomTimingList = cloneList
|
|
85
|
+
}
|
|
58
86
|
const res = await setRandomTimingList(newRandomTimingList)
|
|
59
87
|
state.loading = false
|
|
60
88
|
if (res.success && goBack) {
|
|
@@ -123,7 +151,7 @@ const RandomTimeForLightPage = (props: { theme?: ThemeType}) => {
|
|
|
123
151
|
item={item}
|
|
124
152
|
is24Hour={params.is24Hour}
|
|
125
153
|
onSwitch={async (v) => {
|
|
126
|
-
await onPost('
|
|
154
|
+
await onPost('set', {
|
|
127
155
|
...item,
|
|
128
156
|
power: v,
|
|
129
157
|
settingTime: new Date().getTime()
|
|
@@ -41,7 +41,7 @@ export function getEndTime(item: SleepWakeUpItem) {
|
|
|
41
41
|
return time > 1440 ? time - 1440 : time
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const encodeSleepOrWakeUp = (items: SleepWakeUpItem[]) => {
|
|
44
|
+
export const encodeSleepOrWakeUp = (items: SleepWakeUpItem[]) => {
|
|
45
45
|
const bytes: number[] = []
|
|
46
46
|
bytes.push(numToByte(0))
|
|
47
47
|
bytes.push(numToByte(items.length))
|
|
@@ -91,7 +91,7 @@ const SleepWakeUpDetailPage = (props: {theme?: ThemeType}) => {
|
|
|
91
91
|
return cctToColor(state.sleepWakeUp.temperature);
|
|
92
92
|
}, [state.sleepWakeUp]);
|
|
93
93
|
|
|
94
|
-
const showBackDialog = () => {
|
|
94
|
+
const showBackDialog = useMemo(() => {
|
|
95
95
|
const excludeKeys: string[] = []
|
|
96
96
|
if (state.sleepWakeUp.isColorMode) {
|
|
97
97
|
excludeKeys.push('brightness', 'temperature')
|
|
@@ -99,11 +99,11 @@ const SleepWakeUpDetailPage = (props: {theme?: ThemeType}) => {
|
|
|
99
99
|
excludeKeys.push('hue', 'sat', 'value')
|
|
100
100
|
}
|
|
101
101
|
return !isEqual(omit(params.scheduleItem, excludeKeys), omit(state.sleepWakeUp, excludeKeys))
|
|
102
|
-
}
|
|
102
|
+
}, [JSON.stringify(params.scheduleItem), JSON.stringify(state.sleepWakeUp)])
|
|
103
103
|
|
|
104
104
|
const caSubmit = useMemo(() => {
|
|
105
|
-
return state.sleepWakeUp.name?.length > 0 && state.sleepWakeUp.name?.length < 33;
|
|
106
|
-
}, [state.sleepWakeUp.name]);
|
|
105
|
+
return state.sleepWakeUp.name?.length > 0 && state.sleepWakeUp.name?.length < 33 && (showBackDialog || params.mode === 'add');
|
|
106
|
+
}, [state.sleepWakeUp.name, showBackDialog]);
|
|
107
107
|
|
|
108
108
|
const mixLightCard = useMemo(() => {
|
|
109
109
|
const applyList = params.applyForList.map(item => {
|
|
@@ -191,7 +191,7 @@ const SleepWakeUpDetailPage = (props: {theme?: ThemeType}) => {
|
|
|
191
191
|
picker: {
|
|
192
192
|
marginHorizontal: cx(24),
|
|
193
193
|
marginVertical: cx(15),
|
|
194
|
-
color: props.theme?.global.
|
|
194
|
+
color: props.theme?.global.background,
|
|
195
195
|
},
|
|
196
196
|
week: {},
|
|
197
197
|
itemTitle: {
|
|
@@ -257,7 +257,7 @@ const SleepWakeUpDetailPage = (props: {theme?: ThemeType}) => {
|
|
|
257
257
|
return (
|
|
258
258
|
<Page
|
|
259
259
|
backText={I18n.getLang('add_sleepschedule_one_source_system_back_text')}
|
|
260
|
-
showBackDialog={showBackDialog
|
|
260
|
+
showBackDialog={showBackDialog}
|
|
261
261
|
loading={state.loading}
|
|
262
262
|
backDialogTitle={I18n.getLang('cancel_dialog_leave_unsaved_titel')}
|
|
263
263
|
backDialogContent={I18n.getLang(
|
|
@@ -265,9 +265,9 @@ const SleepWakeUpDetailPage = (props: {theme?: ThemeType}) => {
|
|
|
265
265
|
? 'cancel_dialog_leave_unsaved_sleepschedule_note'
|
|
266
266
|
: 'cancel_dialog_leave_unsaved_wakeupschedule_note'
|
|
267
267
|
)}
|
|
268
|
-
rightButtonIcon={
|
|
268
|
+
rightButtonIcon={caSubmit ? res.ic_check : res.ic_uncheck}
|
|
269
269
|
rightButtonIconClick={async () => {
|
|
270
|
-
if (!
|
|
270
|
+
if (!caSubmit || state.loading) return;
|
|
271
271
|
showDialog({
|
|
272
272
|
method: 'confirm',
|
|
273
273
|
title: I18n.getLang('conflict_dialog_active_item_sleepschedule_titel'),
|
|
@@ -326,6 +326,7 @@ const SleepWakeUpDetailPage = (props: {theme?: ThemeType}) => {
|
|
|
326
326
|
/>
|
|
327
327
|
{/* pick */}
|
|
328
328
|
<TimerPicker
|
|
329
|
+
key={props.theme?.type}
|
|
329
330
|
itemTextColor="#aeadb5"
|
|
330
331
|
style={{ paddingVertical: cx(0), marginVertical: cx(0), backgroundColor: props.theme?.global.background }}
|
|
331
332
|
pickerFontColor={props.theme?.global.fontColor}
|