@ledvance/ui-biz-bundle 1.1.134 → 1.1.135
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/newModules/biorhythm/BiorhythmActions.ts +20 -8
- package/src/newModules/biorhythm/BiorhythmPage.tsx +74 -78
- package/src/newModules/biorhythm/circular/RhythmsCircle.tsx +5 -0
- package/src/newModules/swithInching/SwithInching.tsx +23 -20
- package/src/newModules/swithInching/SwithInchingAction.ts +21 -15
package/package.json
CHANGED
|
@@ -23,8 +23,8 @@ import { useUpdateEffect } from 'ahooks'
|
|
|
23
23
|
|
|
24
24
|
type UseBiorhythmType = (dpKey: string, disabledFeature?: boolean) => [BiorhythmBean, SetBiorhythmType];
|
|
25
25
|
type SetBiorhythmType = (biorhythmObj: BiorhythmBean, pushFeature?: boolean) => Promise<Result<any>>;
|
|
26
|
-
let biorhythmTimer: undefined | number = undefined
|
|
27
26
|
|
|
27
|
+
let biorhythmTimer: number | undefined = undefined
|
|
28
28
|
export const useBiorhythm: UseBiorhythmType = (dpKey: string, disabledFeature?: boolean) => {
|
|
29
29
|
const [dp, setDp] = useDp<string, (v: string) => any>(dpKey)
|
|
30
30
|
const deviceId = useDeviceId()
|
|
@@ -32,7 +32,7 @@ export const useBiorhythm: UseBiorhythmType = (dpKey: string, disabledFeature?:
|
|
|
32
32
|
const isInternalUpdateRef = useRef(false)
|
|
33
33
|
const previousDpRef = useRef(dp)
|
|
34
34
|
|
|
35
|
-
const getBiorhythm =
|
|
35
|
+
const getBiorhythm = () => {
|
|
36
36
|
const biorhythm = dp2Obj(dp)
|
|
37
37
|
getRemoteBiorhythm(deviceId, biorhythm).then(res => {
|
|
38
38
|
if (res.success && res.data) {
|
|
@@ -44,23 +44,32 @@ export const useBiorhythm: UseBiorhythmType = (dpKey: string, disabledFeature?:
|
|
|
44
44
|
}))
|
|
45
45
|
}
|
|
46
46
|
})
|
|
47
|
-
}
|
|
47
|
+
}
|
|
48
48
|
|
|
49
49
|
useEffect(() => {
|
|
50
50
|
if (disabledFeature) return
|
|
51
|
-
|
|
51
|
+
biorhythmTimer = setTimeout(() => {
|
|
52
|
+
getBiorhythm()
|
|
53
|
+
}, 150)
|
|
54
|
+
return () => {
|
|
55
|
+
if (biorhythmTimer) {
|
|
56
|
+
clearTimeout(biorhythmTimer)
|
|
57
|
+
biorhythmTimer = undefined
|
|
58
|
+
}
|
|
59
|
+
}
|
|
52
60
|
}, [])
|
|
53
61
|
|
|
54
62
|
useUpdateEffect(() => {
|
|
55
63
|
if (isInternalUpdateRef.current || disabledFeature) {
|
|
64
|
+
if (disabledFeature) {
|
|
65
|
+
setBiorhythmState(dp2Obj(dp))
|
|
66
|
+
}
|
|
56
67
|
if (isInternalUpdateRef.current) {
|
|
57
68
|
previousDpRef.current = dp
|
|
58
69
|
}
|
|
59
|
-
console.log('跳过更新', isInternalUpdateRef.current, disabledFeature)
|
|
60
70
|
isInternalUpdateRef.current = false
|
|
61
71
|
return
|
|
62
72
|
}
|
|
63
|
-
console.log('dp updateEffect', dp, previousDpRef.current, dp === previousDpRef.current)
|
|
64
73
|
if (dp?.toLocaleLowerCase() === previousDpRef.current?.toLocaleLowerCase()) {
|
|
65
74
|
return
|
|
66
75
|
}
|
|
@@ -70,9 +79,10 @@ export const useBiorhythm: UseBiorhythmType = (dpKey: string, disabledFeature?:
|
|
|
70
79
|
const setBiorhythmFn = async (biorhythmObj: BiorhythmBean, pushFeature: boolean = true) => {
|
|
71
80
|
const dpValue = obj2Dp(biorhythmObj)
|
|
72
81
|
isInternalUpdateRef.current = true
|
|
73
|
-
|
|
82
|
+
|
|
74
83
|
if (pushFeature) {
|
|
75
84
|
const putFeatureRes = await putFeature(deviceId, biorhythmFeatureId, vo2Dto(biorhythmObj))
|
|
85
|
+
console.log(vo2Dto(biorhythmObj), '< --- biorhythmObj --- >')
|
|
76
86
|
if (putFeatureRes.result) {
|
|
77
87
|
setBiorhythmState(biorhythmObj)
|
|
78
88
|
return setDp(dpValue)
|
|
@@ -196,6 +206,7 @@ export function dp2Obj(dp: string): BiorhythmBean {
|
|
|
196
206
|
enabled: p === '1',
|
|
197
207
|
}
|
|
198
208
|
})
|
|
209
|
+
repeatPeriod.sort((a, b) => a.index - b.index)
|
|
199
210
|
dpCopy = dpCopy.slice(2)
|
|
200
211
|
// 节点个数 (每个节点长度18),最多8个节点
|
|
201
212
|
hex2Int(dpCopy.slice(0, 2))
|
|
@@ -360,8 +371,9 @@ function obj2Dp(obj: BiorhythmBean): string {
|
|
|
360
371
|
const versionHex = '00'
|
|
361
372
|
const enableHex = obj.enable ? '01' : '00'
|
|
362
373
|
const gradientHex = obj.gradient === BiorhythmGradientType.EntireGradient ? '00' : '0F'
|
|
374
|
+
const newRepeatPeriod = [obj.repeatPeriod[obj.repeatPeriod.length - 1], ...obj.repeatPeriod.slice(0, -1)]
|
|
363
375
|
const repeatPeriodHex = parseInt(
|
|
364
|
-
|
|
376
|
+
newRepeatPeriod
|
|
365
377
|
.map(p => (p.enabled ? '1' : '0'))
|
|
366
378
|
.reverse()
|
|
367
379
|
.join(''),
|
|
@@ -21,7 +21,6 @@ import I18n from '@ledvance/base/src/i18n'
|
|
|
21
21
|
import res from '@ledvance/base/src/res'
|
|
22
22
|
import { ui_biz_routerKey } from "../../navigation/Routers";
|
|
23
23
|
import { cctToColor } from '@ledvance/base/src/utils/cctUtils'
|
|
24
|
-
import { setDataSource } from '@ledvance/base/src/components/weekSelect'
|
|
25
24
|
import { BiorhythmEditPageParams } from './BiorhythmEditPage'
|
|
26
25
|
import { useBiorhythm } from './BiorhythmActions'
|
|
27
26
|
import { convertMinutesTo12HourFormat, showDialog as showCommonDialog } from '@ledvance/base/src/utils/common'
|
|
@@ -190,11 +189,7 @@ const BiorhythmPage = (props: { theme?: ThemeType }) => {
|
|
|
190
189
|
}
|
|
191
190
|
|
|
192
191
|
useEffect(() => {
|
|
193
|
-
const weeks
|
|
194
|
-
biorhythm.repeatPeriod.map(item => {
|
|
195
|
-
return item?.enabled ? 1 : 0
|
|
196
|
-
})).filter(item => item.enabled)
|
|
197
|
-
.map(item => item.title)
|
|
192
|
+
const weeks = biorhythm.repeatPeriod.filter(it => it.enabled).map(it => it.title)
|
|
198
193
|
|
|
199
194
|
if (weeks.length > 0) {
|
|
200
195
|
if (weeks.length === 7) {
|
|
@@ -237,20 +232,21 @@ const BiorhythmPage = (props: { theme?: ThemeType }) => {
|
|
|
237
232
|
const sunHomeText = string => {
|
|
238
233
|
const text = string.split('SUN@HOME')
|
|
239
234
|
return text?.length === 1 && <Text style={{ fontSize: cx(14), color: props.theme?.global.fontColor }}>{text[0]}</Text> ||
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
235
|
+
<Text style={{
|
|
236
|
+
fontSize: cx(14),
|
|
237
|
+
flexDirection: 'row',
|
|
238
|
+
}}>
|
|
239
|
+
<Text style={{ color: props.theme?.global.fontColor }}>{text[0]}</Text>
|
|
240
|
+
<Text
|
|
241
|
+
onPress={openLink}
|
|
242
|
+
style={{
|
|
243
|
+
fontFamily: 'helvetica_neue_lt_std_roman',
|
|
244
|
+
color: props.theme?.button.primary,
|
|
245
|
+
textDecorationLine: 'underline',
|
|
246
|
+
flexWrap: 'wrap',
|
|
247
|
+
}}>SUN@HOME</Text>
|
|
248
|
+
<Text style={{ color: props.theme?.global.fontColor }}>{text[1]}</Text>
|
|
249
|
+
</Text>
|
|
254
250
|
}
|
|
255
251
|
|
|
256
252
|
const randomIcon = () => {
|
|
@@ -452,66 +448,66 @@ const BiorhythmPage = (props: { theme?: ThemeType }) => {
|
|
|
452
448
|
marginTop: cx(26),
|
|
453
449
|
}}>
|
|
454
450
|
{state.planList.length === 8 && <View
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
451
|
+
style={{ marginVertical: cx(10), flexDirection: 'row', alignItems: 'center', width: width - cx(48) }}>
|
|
452
|
+
<Image style={{ width: cx(16), height: cx(16), tintColor: props.theme?.global.warning }} source={{ uri: res.ic_warning_amber }} />
|
|
453
|
+
<Text
|
|
454
|
+
style={{
|
|
455
|
+
flexWrap: 'wrap',
|
|
456
|
+
fontSize: cx(12),
|
|
457
|
+
color: props.theme?.global.fontColor
|
|
458
|
+
}}>{I18n.getLang('add_new_trigger_time_warning_max_number_text')}</Text>
|
|
463
459
|
</View>}
|
|
464
460
|
{state.planList.length < 8 &&
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
461
|
+
<>
|
|
462
|
+
<Text
|
|
463
|
+
style={{
|
|
464
|
+
fontSize: cx(16),
|
|
465
|
+
fontWeight: 'bold',
|
|
466
|
+
color: props.theme?.global.fontColor,
|
|
467
|
+
}}>{I18n.getLang('bio_ryhthm_default_subheadline_text')}</Text>
|
|
468
|
+
<TouchableOpacity
|
|
469
|
+
onPress={() => {
|
|
470
|
+
const ids: number[] = state.planList.map(p => p.index)
|
|
471
|
+
const newPlan: Plan = {
|
|
472
|
+
index: Math.max(...ids) + 1,
|
|
473
|
+
icon: res.rhythm_icon1,
|
|
474
|
+
time: 0,
|
|
475
|
+
name: '',
|
|
476
|
+
colorTemperature: 0,
|
|
477
|
+
brightness: 100,
|
|
478
|
+
action: [
|
|
479
|
+
{
|
|
480
|
+
uri: 'model/attribute/set/LightCtrl/ColorTemperature',
|
|
481
|
+
startValue: `${colorTemperatureValue(0)}`,
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
uri: 'model/attribute/set/LightCtrl/Brightness',
|
|
485
|
+
startValue: '100',
|
|
486
|
+
},
|
|
487
|
+
],
|
|
488
|
+
enable: true,
|
|
489
|
+
iconId: randomIcon(),
|
|
490
|
+
}
|
|
491
|
+
const editPageParams: BiorhythmEditPageParams = {
|
|
492
|
+
planData: newPlan,
|
|
493
|
+
isAdd: true,
|
|
494
|
+
onPlanEdited,
|
|
495
|
+
onPlanDelete,
|
|
496
|
+
minimumEnable,
|
|
497
|
+
nameRepeat,
|
|
498
|
+
iconIdList: state.planList?.map(item => {
|
|
499
|
+
return item.iconId
|
|
500
|
+
}),
|
|
501
|
+
isMixRGBWLamp: !!params.isMixLight,
|
|
502
|
+
isSupportTemperature: params.isSupportTemperature,
|
|
503
|
+
isSupportBrightness: params.isSupportBrightness,
|
|
504
|
+
showDeleteBtn
|
|
505
|
+
}
|
|
506
|
+
navigation.navigate(ui_biz_routerKey.bi_biz_biological_edit, editPageParams)
|
|
507
|
+
}}>
|
|
508
|
+
<Image source={{ uri: res.biorhythom_add }} style={{ height: cx(24), width: cx(24), tintColor: props.theme?.icon.primary }} />
|
|
509
|
+
</TouchableOpacity>
|
|
510
|
+
</>
|
|
515
511
|
}
|
|
516
512
|
</View>
|
|
517
513
|
<FlatList
|
|
@@ -94,6 +94,11 @@ const RhythmsCircle: React.FC<RhythmsCircleProps & { gradientMode?: boolean }> =
|
|
|
94
94
|
const getRingColors = (data: IData[]) => {
|
|
95
95
|
type ColorStop = { color: string; angle: number };
|
|
96
96
|
|
|
97
|
+
// 防止数据为空时崩溃
|
|
98
|
+
if (!data || !data.length) {
|
|
99
|
+
return [{ color: '#000', angle: 0 }, { color: '#000', angle: fullDeg }]
|
|
100
|
+
}
|
|
101
|
+
|
|
97
102
|
// 角度规范化函数:确保角度在0到2π范围内
|
|
98
103
|
const normalizeAngle = (angle: number) => {
|
|
99
104
|
while (angle < 0) {
|
|
@@ -23,7 +23,7 @@ const SwitchInching = (props: { theme?: ThemeType }) => {
|
|
|
23
23
|
const navigation = useNavigation()
|
|
24
24
|
const [switchInching, setSwitchInching] = useSwitchInching(params.switchIngCode)
|
|
25
25
|
const [checkConflict, resolveConflict] = useConflictTask(params.conflictDps, true)
|
|
26
|
-
const [countdowns, setCountdowns] = useCountdowns(params.countdownCode || params.channelConfig
|
|
26
|
+
const [countdowns, setCountdowns] = useCountdowns(params.countdownCode || params.channelConfig?.map(item => item.countdownCode) || [])
|
|
27
27
|
const timeRef = useRef({
|
|
28
28
|
minute: '00',
|
|
29
29
|
second: '00',
|
|
@@ -41,23 +41,23 @@ const SwitchInching = (props: { theme?: ThemeType }) => {
|
|
|
41
41
|
const updateTime = (minute?: string, second?: string) => {
|
|
42
42
|
if (minute !== undefined) timeRef.current.minute = minute;
|
|
43
43
|
if (second !== undefined) timeRef.current.second = second;
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
if (!Number(timeRef.current.minute) && Number(timeRef.current.second) < 1) {
|
|
46
46
|
timeRef.current.second = '01';
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
if (Number(timeRef.current.minute) === 60) {
|
|
50
50
|
timeRef.current.second = '00';
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
const time = Number(timeRef.current.minute) * 60 + Number(timeRef.current.second);
|
|
54
54
|
const newSwitchInchingItem = {
|
|
55
55
|
...state.switchInchingItem,
|
|
56
56
|
time
|
|
57
57
|
};
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
updateState({ switchInchingItem: newSwitchInchingItem });
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
const switchInchingItem = useMemo(() => {
|
|
@@ -73,8 +73,11 @@ const SwitchInching = (props: { theme?: ThemeType }) => {
|
|
|
73
73
|
const saveInchingConfig = async (item: SwitchInchingItem) => {
|
|
74
74
|
const updatedSwitchInching = [...switchInching];
|
|
75
75
|
const existingItemIndex = updatedSwitchInching.findIndex(item => item.channel === state.channel);
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
if (existingItemIndex === -1) {
|
|
77
|
+
updatedSwitchInching.push(item);
|
|
78
|
+
} else {
|
|
79
|
+
updatedSwitchInching[existingItemIndex] = item;
|
|
80
|
+
}
|
|
78
81
|
await setSwitchInching(updatedSwitchInching)
|
|
79
82
|
}
|
|
80
83
|
|
|
@@ -143,18 +146,18 @@ const SwitchInching = (props: { theme?: ThemeType }) => {
|
|
|
143
146
|
>
|
|
144
147
|
<ScrollView nestedScrollEnabled={true}>
|
|
145
148
|
{params.channelConfig && params.channelConfig.length > 1 && <>
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
149
|
+
<Segmented
|
|
150
|
+
style={{ marginHorizontal: cx(24) }}
|
|
151
|
+
options={params.channelConfig.map(item => ({
|
|
152
|
+
label: item.channelTitle,
|
|
153
|
+
value: item.channel
|
|
154
|
+
}))}
|
|
155
|
+
value={state.channel}
|
|
156
|
+
onChange={v => {
|
|
157
|
+
updateState({ channel: Number(v) })
|
|
158
|
+
}}
|
|
159
|
+
/>
|
|
160
|
+
<Spacer />
|
|
158
161
|
</>}
|
|
159
162
|
<View style={styles.switchContainer}>
|
|
160
163
|
<View style={styles.switchCardContainer}>
|
|
@@ -3,14 +3,15 @@ import { Result } from "@ledvance/base/src/models/modules/Result"
|
|
|
3
3
|
import { useDp } from "@ledvance/base/src/models/modules/NativePropsSlice";
|
|
4
4
|
import { spliceByStep } from '@ledvance/base/src/utils/common';
|
|
5
5
|
import { Utils } from '@tuya/tuya-panel-lamp-sdk'
|
|
6
|
+
import {useEffect, useState} from "react";
|
|
6
7
|
|
|
7
8
|
const { to16 } = Utils
|
|
8
9
|
export interface SwitchInchingPageParams {
|
|
9
10
|
switchIngCode: string
|
|
10
11
|
countdownCode?: string
|
|
11
12
|
channelConfig?: {
|
|
12
|
-
countdownCode: string
|
|
13
|
-
channelTitle: string
|
|
13
|
+
countdownCode: string
|
|
14
|
+
channelTitle: string
|
|
14
15
|
channel: number
|
|
15
16
|
}[]
|
|
16
17
|
conflictDps: {
|
|
@@ -31,20 +32,20 @@ export function useCountdowns(countdownCodes: string | string[]): [Record<string
|
|
|
31
32
|
const codes = Array.isArray(countdownCodes) ? countdownCodes : [countdownCodes];
|
|
32
33
|
const countdownValues: Record<string, number> = {};
|
|
33
34
|
const dpSetters: Record<string, (value: number) => Promise<Result<any>>> = {};
|
|
34
|
-
|
|
35
|
+
|
|
35
36
|
for (const code of codes) {
|
|
36
37
|
const [value, setDp] = useDp<number, any>(code);
|
|
37
38
|
countdownValues[code] = value;
|
|
38
39
|
dpSetters[code] = setDp;
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
+
|
|
41
42
|
const setCountdown = async (countdownCode: string, value: number) => {
|
|
42
43
|
if (dpSetters[countdownCode]) {
|
|
43
44
|
return await dpSetters[countdownCode](value);
|
|
44
45
|
}
|
|
45
46
|
return { success: false, msg: 'Countdown code not found' } as Result<any>;
|
|
46
47
|
};
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
return [countdownValues, setCountdown];
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -56,15 +57,19 @@ export const defSwitchInching = [{ enable: false, channel: 0, time: 1 }]
|
|
|
56
57
|
|
|
57
58
|
export const useSwitchInching = (switchInchingCode: string) => {
|
|
58
59
|
const [hex, setHex] = useSwitchInchingHex(switchInchingCode)
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
const [value, setValue] = useState(defSwitchInching)
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
const switching = hex ? spliceByStep(Buffer.from(hex, 'base64').toString('hex'), 6).map(item => {
|
|
63
|
+
const powerInfo = parseInt(`${item.slice(0, 2)}`, 16).toString(2).padStart(8, '0');
|
|
64
|
+
const powerBits = powerInfo.split('');
|
|
65
|
+
const enable = !!Number(powerBits[powerBits.length - 1]);
|
|
66
|
+
// 通道号
|
|
67
|
+
const channel = parseInt(powerBits.slice(1, powerBits.length - 1).join(''), 2);
|
|
68
|
+
const time = parseInt(item.slice(2, 6), 16)
|
|
69
|
+
return { enable, channel, time }
|
|
70
|
+
}) : defSwitchInching
|
|
71
|
+
setValue(switching)
|
|
72
|
+
}, [hex]);
|
|
68
73
|
|
|
69
74
|
const setSwitchInching = (switching: SwitchInchingItem[]) => {
|
|
70
75
|
const inchingString = switching.map(item => {
|
|
@@ -75,8 +80,9 @@ export const useSwitchInching = (switchInchingCode: string) => {
|
|
|
75
80
|
return powerChannelStr + timeHex
|
|
76
81
|
}).join('')
|
|
77
82
|
const inchingHex = Buffer.from(inchingString, 'hex').toString('base64')
|
|
83
|
+
setValue(switching)
|
|
78
84
|
return setHex(inchingHex)
|
|
79
85
|
}
|
|
80
|
-
return [
|
|
86
|
+
return [value, setSwitchInching] as const
|
|
81
87
|
}
|
|
82
88
|
|