@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 CHANGED
@@ -4,7 +4,7 @@
4
4
  "name": "@ledvance/ui-biz-bundle",
5
5
  "pid": [],
6
6
  "uiid": "",
7
- "version": "1.1.134",
7
+ "version": "1.1.135",
8
8
  "scripts": {},
9
9
  "dependencies": {
10
10
  "@ledvance/base": "^1.x",
@@ -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 = useCallback(() => {
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
- }, [dp])
47
+ }
48
48
 
49
49
  useEffect(() => {
50
50
  if (disabledFeature) return
51
- getBiorhythm()
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
- obj.repeatPeriod
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: string[] = setDataSource(
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
- <Text style={{
241
- fontSize: cx(14),
242
- flexDirection: 'row',
243
- }}>
244
- <Text style={{ color: props.theme?.global.fontColor }}>{text[0]}</Text>
245
- <Text onPress={openLink}
246
- style={{
247
- fontFamily: 'helvetica_neue_lt_std_roman',
248
- color: props.theme?.button.primary,
249
- textDecorationLine: 'underline',
250
- flexWrap: 'wrap',
251
- }}>SUN@HOME</Text>
252
- <Text style={{ color: props.theme?.global.fontColor }}>{text[1]}</Text>
253
- </Text>
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
- style={{ marginVertical: cx(10), flexDirection: 'row', alignItems: 'center', width: width - cx(48) }}>
456
- <Image style={{ width: cx(16), height: cx(16), tintColor: props.theme?.global.warning }} source={{ uri: res.ic_warning_amber }} />
457
- <Text
458
- style={{
459
- flexWrap: 'wrap',
460
- fontSize: cx(12),
461
- color: props.theme?.global.fontColor
462
- }}>{I18n.getLang('add_new_trigger_time_warning_max_number_text')}</Text>
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
- <Text
467
- style={{
468
- fontSize: cx(16),
469
- fontWeight: 'bold',
470
- color: props.theme?.global.fontColor,
471
- }}>{I18n.getLang('bio_ryhthm_default_subheadline_text')}</Text>
472
- <TouchableOpacity
473
- onPress={() => {
474
- const ids: number[] = state.planList.map(p => p.index)
475
- const newPlan: Plan = {
476
- index: Math.max(...ids) + 1,
477
- icon: res.rhythm_icon1,
478
- time: 0,
479
- name: '',
480
- colorTemperature: 0,
481
- brightness: 100,
482
- action: [
483
- {
484
- uri: 'model/attribute/set/LightCtrl/ColorTemperature',
485
- startValue: `${colorTemperatureValue(0)}`,
486
- },
487
- {
488
- uri: 'model/attribute/set/LightCtrl/Brightness',
489
- startValue: '100',
490
- },
491
- ],
492
- enable: true,
493
- iconId: randomIcon(),
494
- }
495
- const editPageParams: BiorhythmEditPageParams = {
496
- planData: newPlan,
497
- isAdd: true,
498
- onPlanEdited,
499
- onPlanDelete,
500
- minimumEnable,
501
- nameRepeat,
502
- iconIdList: state.planList?.map(item => {
503
- return item.iconId
504
- }),
505
- isMixRGBWLamp: !!params.isMixLight,
506
- isSupportTemperature: params.isSupportTemperature,
507
- isSupportBrightness: params.isSupportBrightness,
508
- showDeleteBtn
509
- }
510
- navigation.navigate(ui_biz_routerKey.bi_biz_biological_edit, editPageParams)
511
- }}>
512
- <Image source={{ uri: res.biorhythom_add }} style={{ height: cx(24), width: cx(24), tintColor: props.theme?.icon.primary }} />
513
- </TouchableOpacity>
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.map(item => item.countdownCode))
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
- updatedSwitchInching[existingItemIndex] = item;
77
- console.log('updatedSwitchInching', updatedSwitchInching)
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
- <Segmented
147
- style={{ marginHorizontal: cx(24) }}
148
- options={params.channelConfig.map(item => ({
149
- label: item.channelTitle,
150
- value: item.channel
151
- }))}
152
- value={state.channel}
153
- onChange={v => {
154
- updateState({ channel: Number(v) })
155
- }}
156
- />
157
- <Spacer />
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 switching = hex ? spliceByStep(Buffer.from(hex, 'base64').toString('hex'), 6).map(item => {
60
- const powerInfo = parseInt(`${item.slice(0, 2)}`, 16).toString(2).padStart(8, '0');
61
- const powerBits = powerInfo.split('');
62
- const enable = !!Number(powerBits[powerBits.length - 1]);
63
- // 通道号
64
- const channel = parseInt(powerBits.slice(1, powerBits.length - 1).join(''), 2);
65
- const time = parseInt(item.slice(2, 6), 16)
66
- return { enable, channel, time }
67
- }) : defSwitchInching
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 [switching, setSwitchInching] as const
86
+ return [value, setSwitchInching] as const
81
87
  }
82
88