@ledvance/group-ui-biz-bundle 1.0.0

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 (40) hide show
  1. package/.babelrc +31 -0
  2. package/.eslintignore +6 -0
  3. package/.eslintrc.js +27 -0
  4. package/.prettierignore +0 -0
  5. package/.prettierrc.js +1 -0
  6. package/.versionrc +5 -0
  7. package/package.json +73 -0
  8. package/rn-cli.config.js +8 -0
  9. package/src/modules/mood/AddMoodPage.tsx +826 -0
  10. package/src/modules/mood/DynamicMoodEditorPage.tsx +547 -0
  11. package/src/modules/mood/MoodItem.tsx +114 -0
  12. package/src/modules/mood/MoodPage.tsx +332 -0
  13. package/src/modules/mood/RecommendMoodItem.tsx +75 -0
  14. package/src/modules/mood/SceneAction.ts +459 -0
  15. package/src/modules/mood/SceneInfo.ts +886 -0
  16. package/src/modules/mood/StaticMoodEditorPage.tsx +251 -0
  17. package/src/modules/mood/tools.ts +12 -0
  18. package/src/modules/select/SelectPage.d.ts +12 -0
  19. package/src/modules/select/SelectPage.tsx +139 -0
  20. package/src/modules/time_schedule/Interface.ts +85 -0
  21. package/src/modules/time_schedule/ScheduleCard.tsx +111 -0
  22. package/src/modules/time_schedule/TimeScheduleActions.ts +81 -0
  23. package/src/modules/time_schedule/TimeScheduleDetailPage.tsx +704 -0
  24. package/src/modules/time_schedule/TimeSchedulePage.tsx +246 -0
  25. package/src/modules/timer/TimerAction.d.ts +12 -0
  26. package/src/modules/timer/TimerAction.ts +150 -0
  27. package/src/modules/timer/TimerPage.d.ts +2 -0
  28. package/src/modules/timer/TimerPage.tsx +351 -0
  29. package/src/navigation/Routers.d.ts +5 -0
  30. package/src/navigation/Routers.ts +97 -0
  31. package/src/navigation/tools.d.ts +0 -0
  32. package/src/navigation/tools.ts +0 -0
  33. package/src/res/GroupBizRes.ts +4 -0
  34. package/src/res/materialiconsFilledCancel.png +0 -0
  35. package/src/res/materialiconsFilledCancel@2x.png +0 -0
  36. package/src/res/materialiconsFilledCancel@3x.png +0 -0
  37. package/src/res/materialiconsOutlinedArrowsNavAddBox.png +0 -0
  38. package/src/res/materialiconsOutlinedArrowsNavAddBox@2x.png +0 -0
  39. package/src/res/materialiconsOutlinedArrowsNavAddBox@3x.png +0 -0
  40. package/tsconfig.json +51 -0
@@ -0,0 +1,459 @@
1
+ import { useState } from 'react'
2
+ import { useUpdateEffect } from 'ahooks'
3
+ import { Result } from '@ledvance/base/src/models/modules/Result'
4
+ import {
5
+ getDefSceneList,
6
+ getDefFantasyScene,
7
+ RemoteSceneInfo,
8
+ SceneInfo,
9
+ SceneNodeInfo,
10
+ SceneUIState,
11
+ StripSceneUIState,
12
+ StripSceneInfo,
13
+ StripNodeInfo,
14
+ } from './SceneInfo'
15
+ import { NativeApi } from '@ledvance/base/src/api/native'
16
+ import { hex2Int, spliceByStep } from '@ledvance/base/src/utils/common'
17
+ import { useDps, useFeatureHook } from '@ledvance/base/src/models/modules/NativePropsSlice'
18
+ import res from '@ledvance/base/src/res'
19
+ import { Utils } from '@tuya/tuya-panel-lamp-sdk'
20
+ import { parseJSON } from '@tuya/tuya-panel-lamp-sdk/lib/utils'
21
+ import { WorkMode } from "@ledvance/base/src/utils/interface"
22
+ const { nToHS, toFixed, sToN } = Utils
23
+
24
+ export function useWorkMode(): [WorkMode, (value: WorkMode) => Promise<Result<any>>] {
25
+ return useFeatureHook<SceneDataConfigType, WorkMode>('workMode', WorkMode.White)
26
+ }
27
+
28
+ export function useSwitchLed(): [boolean, (value: boolean) => Promise<Result<any>>] {
29
+ return useFeatureHook<SceneDataConfigType, boolean>('switchLed', false)
30
+ }
31
+
32
+ interface SceneDataType {
33
+ sceneDataDpCode: string
34
+ scene?: SceneUIState
35
+ workModeDpCode: string
36
+ workMode: WorkMode
37
+ switchLedDpCode: string
38
+ }
39
+ export interface SceneDataConfigType {
40
+ sceneConfig?: SceneDataType
41
+ workMode: WorkMode
42
+ switchLed: boolean
43
+ }
44
+
45
+ interface LightType {
46
+ isStringLight?: boolean
47
+ isStripLight?: boolean
48
+ isSupportFan?: boolean
49
+ isSupportUVC?: boolean
50
+ }
51
+
52
+ export function useScene(params: LightType): [SceneDataType | undefined, (scene?: SceneDataType) => Promise<Result<any>>] {
53
+ return useFeatureHook<SceneDataConfigType, SceneDataType | undefined>('sceneConfig', undefined, undefined, (scene) => {
54
+ if (scene) {
55
+ const isFantasy = params.isStringLight || params.isStripLight
56
+ console.log(scene.scene, isFantasy, '< --- scene')
57
+ const dps = {}
58
+ // @ts-ignore
59
+ dps[scene.sceneDataDpCode] = scene.scene ? (isFantasy ? stripObj2Dp(scene.scene, params.isStringLight) : obj2Dp(scene.scene, params.isSupportFan, params.isSupportUVC)) : ''
60
+ dps[scene.workModeDpCode] = scene.workMode
61
+ dps[scene.switchLedDpCode] = true
62
+ console.log(dps, '< --- dpss')
63
+ return dps
64
+ }
65
+ }, scene => { return { workMode: scene?.workMode, switchLed: true } })
66
+ }
67
+
68
+ const SceneFeatureId = 'SimplifyScene'
69
+
70
+
71
+ interface LampParams {
72
+ isSupportColor?: boolean
73
+ isSupportBrightness?: boolean
74
+ isSupportTemperature?: boolean
75
+ isSupportFan?: boolean
76
+ isSupportUVC?: boolean
77
+ isStringLight?: boolean
78
+ isStripLight?: boolean
79
+ }
80
+
81
+ export async function getRemoteSceneList(
82
+ deviceId: string,
83
+ lampParams: LampParams,
84
+ ): Promise<Result<SceneUIState[] | StripSceneUIState[]>> {
85
+ const res = await NativeApi.getJson(deviceId, SceneFeatureId)
86
+ const isNormalData = Array.isArray(parseJSON(res?.data))
87
+ if (res.success && isNormalData) {
88
+ return {
89
+ success: true,
90
+ data: res.data && parseJSON(res.data).map((item, index) => remoteSceneInfo2SceneUIState(item, index, lampParams)),
91
+ }
92
+ } else {
93
+ if (res.msg?.includes('资源未找到') || !isNormalData) {
94
+ const defaultScene = getDefSceneList(lampParams)
95
+ const res = await NativeApi.putJson(deviceId, SceneFeatureId, JSON.stringify(defaultScene))
96
+ if (res.success) {
97
+ return {
98
+ success: true,
99
+ // @ts-ignore
100
+ data: defaultScene.map((item, index) => remoteSceneInfo2SceneUIState(item, index, lampParams))
101
+ }
102
+ }
103
+ return { success: false }
104
+ }
105
+ return { success: false }
106
+ }
107
+ }
108
+
109
+ interface SceneParams {
110
+ isSupportFan?: boolean
111
+ isSupportUVC?: boolean
112
+ isStringLight?: boolean
113
+ isStripLight?: boolean
114
+ }
115
+
116
+ function remoteSceneInfo2SceneUIState(
117
+ remoteSceneInfo: RemoteSceneInfo,
118
+ index: number,
119
+ sceneParams: SceneParams
120
+ ):SceneUIState | StripSceneUIState {
121
+ const isFantasy = sceneParams.isStringLight || sceneParams.isStripLight
122
+ const sceneInfo = isFantasy ? stripDp2Obj(remoteSceneInfo.i, sceneParams.isStringLight) : dp2Obj(remoteSceneInfo.i, sceneParams.isSupportFan, sceneParams.isSupportUVC)
123
+
124
+ return {
125
+ ...sceneInfo,
126
+ id: sceneInfo.id,
127
+ // @ts-ignore
128
+ fanEnable: sceneInfo?.fanEnable || false,
129
+ // @ts-ignore
130
+ fanSpeed: sceneInfo?.fanSpeed || false,
131
+ name: remoteSceneInfo.n,
132
+ image: getSceneImage(index),
133
+ }
134
+ }
135
+
136
+ export function dp2Obj(dp: string, isFan: boolean = false, isUVCFan?: boolean): SceneInfo {
137
+ let dpCopy = dp
138
+ let fanEnable = false
139
+ let fanSpeed = 0
140
+ const id = hex2Int(dpCopy.slice(0, 2))
141
+ dpCopy = dpCopy.slice(2)
142
+ if (isFan) {
143
+ fanEnable = hex2Int(dpCopy.slice(0, 2)) === 1
144
+ dpCopy = dpCopy.slice(2)
145
+ fanSpeed = hex2Int(dpCopy.slice(0, 2))
146
+ dpCopy = dpCopy.slice(2)
147
+ }
148
+ const nodes: SceneNodeInfo[] = spliceByStep(dpCopy, 26).map(nodeHex => {
149
+ let hex = nodeHex
150
+ const switchingInterval = isUVCFan ? 101 - hex2Int(hex.slice(0, 2)) : hex2Int(hex.slice(0, 2))
151
+ hex = hex.slice(2)
152
+ const transitionTime = isUVCFan ? 101 - hex2Int(hex.slice(0, 2)) : hex2Int(hex.slice(0, 2))
153
+ hex = hex.slice(2)
154
+ const transitionMode = hex2Int(hex.slice(0, 2))
155
+ hex = hex.slice(2)
156
+ const h = hex2Int(hex.slice(0, 4))
157
+ hex = hex.slice(4)
158
+ const s = Math.round(hex2Int(hex.slice(0, 4)) / 10)
159
+ hex = hex.slice(4)
160
+ const v = Math.round(hex2Int(hex.slice(0, 4)) / 10)
161
+ hex = hex.slice(4)
162
+ const brightness = Math.round(hex2Int(hex.slice(0, 4)) / 10)
163
+ hex = hex.slice(4)
164
+ const colorTemp = Math.round(hex2Int(hex.slice(0, 4)) / 10)
165
+ const isColorNode = h !== 0 || s !== 0 || v !== 0
166
+ return {
167
+ switchingInterval,
168
+ transitionTime,
169
+ transitionMode,
170
+ h,
171
+ s,
172
+ v,
173
+ brightness,
174
+ colorTemp,
175
+ isColorNode,
176
+ }
177
+ })
178
+ return {
179
+ id,
180
+ fanEnable: isFan ? fanEnable : undefined,
181
+ fanSpeed: isFan ? fanSpeed : undefined,
182
+ nodes,
183
+ speed: nodes[0].transitionTime,
184
+ mode: nodes[0].transitionMode,
185
+ segmented: 0,
186
+ excessive: 0,
187
+ expand: 0,
188
+ direction: 0
189
+ }
190
+ }
191
+
192
+ function getSceneImage(index: number): string {
193
+ if (index === 0) {
194
+ return res.scene_goodnight
195
+ }
196
+ if (index === 1) {
197
+ return res.scene_reading
198
+ }
199
+ if (index === 2) {
200
+ return res.scene_work
201
+ }
202
+ if (index === 3) {
203
+ return res.scene_leisure
204
+ }
205
+ if (index === 4) {
206
+ return res.scene_custom1
207
+ }
208
+ if (index === 5) {
209
+ return res.scene_custom2
210
+ }
211
+ if (index === 6) {
212
+ return res.scene_work
213
+ }
214
+ if (index === 7) {
215
+ return res.scene_work
216
+ }
217
+ return ''
218
+ }
219
+
220
+ export function obj2Dp(scene: SceneInfo, isFan: boolean = false, isUVCFan?: boolean): string {
221
+ let fanEnableHex = ''
222
+ let fanSpeedHex = ''
223
+ const idHex = scene.id.toString(16).padStart(2, '0')
224
+ if (isFan) {
225
+ fanEnableHex = (scene.fanEnable ? 1 : 0).toString(16).padStart(2, '0')
226
+ fanSpeedHex = (scene.fanSpeed || 1).toString(16).padStart(2, '0')
227
+ }
228
+ const hex = idHex + fanEnableHex + fanSpeedHex + scene.nodes?.map(node => {
229
+ const switchingIntervalHex = (isUVCFan ? 101 - scene.speed : scene.speed).toString(16).padStart(2, '0')
230
+ const transitionTimeHex = (isUVCFan ? 101 - scene.speed : scene.speed).toString(16).padStart(2, '0')
231
+ const transitionModeHex = scene.mode.toString(16).padStart(2, '0')
232
+ const hHex = node.h.toString(16).padStart(4, '0')
233
+ const sHex = (node.s * 10).toString(16).padStart(4, '0')
234
+ const vHex = (node.v * 10).toString(16).padStart(4, '0')
235
+ const brightnessHex = (node.brightness * 10).toString(16).padStart(4, '0')
236
+ const colorTempHex = (node.colorTemp * 10).toString(16).padStart(4, '0')
237
+ return switchingIntervalHex + transitionTimeHex + transitionModeHex + hHex + sHex + vHex + brightnessHex + colorTempHex
238
+ }).join('')
239
+ return hex
240
+ }
241
+
242
+ export function saveScene(
243
+ devId: string,
244
+ scenes: SceneUIState[] | StripSceneUIState[],
245
+ sceneParams: SceneParams
246
+ ) {
247
+ console.log(scenes, '< --- save new Scenes')
248
+ const isFantasy = sceneParams.isStringLight || sceneParams.isStripLight
249
+ const newScenes = scenes.map(s => {
250
+ return {
251
+ n: s.name,
252
+ i: isFantasy ? stripObj2Dp(s, sceneParams.isStringLight) : obj2Dp(s, sceneParams.isSupportFan, sceneParams.isSupportUVC),
253
+ s: '',
254
+ t: 0,
255
+ e: false,
256
+ }
257
+ })
258
+ return NativeApi.putJson(devId, SceneFeatureId, JSON.stringify(newScenes))
259
+ }
260
+
261
+ const getDefaultScene = () => {
262
+ return {
263
+ version: 0,
264
+ // 场景号
265
+ id: -1,
266
+ // 变化方式
267
+ mode: 0,
268
+ // 速度
269
+ speed: 0,
270
+ // 段落 0 全段, 1 分段
271
+ segmented: 0,
272
+ // 循环 0 不循环, 1 循环
273
+ loop: 0,
274
+ // 过渡 0 不过渡, 1 过渡
275
+ excessive: 0,
276
+ // 拓展 other
277
+ expand: 0,
278
+ // 方向 0 顺时针方向, 1 逆时针方向
279
+ direction: 0,
280
+ // 设置 目前灯用不上
281
+ reserved1: 0,
282
+ reserved2: 0,
283
+ nodes: []
284
+ }
285
+ }
286
+
287
+ export function stripDp2Obj(dp: string, isStringLight: boolean = false): StripSceneInfo {
288
+ if (!dp) return getDefaultScene()
289
+ const version = hex2Int(dp.slice(0, 2))
290
+ const id = hex2Int(dp.slice(2, 4))
291
+ const mode = hex2Int(dp.slice(4, 6))
292
+ const intervalTime = hex2Int(dp.slice(6, 8))
293
+ const changeTime = hex2Int(dp.slice(8, 10))
294
+ const speed = intervalTime || changeTime
295
+ const optionA = hex2Int(dp.slice(10, 12)).toString(2).padStart(8, '0')
296
+ const segmented = sToN(optionA.slice(0, 1), 2)
297
+ const loop = sToN(optionA.slice(1, 2), 2)
298
+ const excessive = sToN(optionA.slice(2, 3), 2)
299
+ const direction = sToN(optionA.slice(3, 4), 2)
300
+ const expand = sToN(optionA.slice(4, 6), 2)
301
+ const reserved1 = sToN(optionA.slice(6, 7), 2)
302
+ const reserved2 = sToN(optionA.slice(7, 8), 2)
303
+ // 这两个目前灯具用不上
304
+ // const optionB = toN(dp.slice(12, 14))
305
+ // const optionC = toN(dp.slice(14, 16))
306
+ let nodes = [] as StripNodeInfo[]
307
+ if (isStringLight) {
308
+ nodes = spliceByStep(dp.slice(16, dp.length), 16).map(nodeHex => {
309
+ const v = hex2Int(nodeHex.slice(0, 2))
310
+ const h = hex2Int(nodeHex.slice(2, 6))
311
+ const s = hex2Int(nodeHex.slice(6, 8))
312
+ const brightness = hex2Int(nodeHex.slice(8, 12)) / 10
313
+ const colorTemp = hex2Int(nodeHex.slice(12, 16)) / 10
314
+ const isColorNode = v > 0 && brightness === 0
315
+ return { h, s, v, brightness, colorTemp, isColorNode }
316
+ })
317
+ } else {
318
+ const bright = hex2Int(dp.slice(16, 18))
319
+ nodes = spliceByStep(dp.slice(18, dp.length), 6).map(nodeHex => {
320
+ const h = hex2Int(nodeHex.slice(0, 4))
321
+ const s = hex2Int(nodeHex.slice(4, 6))
322
+ const v = bright
323
+ const brightness = 0
324
+ const colorTemp = 0
325
+ const isColorNode = true
326
+ return { h, s, v, brightness, colorTemp, isColorNode }
327
+ })
328
+ }
329
+
330
+ return {
331
+ version,
332
+ id,
333
+ mode,
334
+ speed,
335
+ direction,
336
+ segmented,
337
+ loop,
338
+ excessive,
339
+ expand,
340
+ reserved1,
341
+ reserved2,
342
+ nodes
343
+ }
344
+ }
345
+
346
+ export function stripObj2Dp(scene: StripSceneInfo, isStringLight: boolean = false) {
347
+ const {
348
+ expand = 0,
349
+ reserved1 = 0,
350
+ reserved2 = 0,
351
+ // mixedIds = [],
352
+ segmented = 0,
353
+ loop = 0,
354
+ excessive = 0,
355
+ direction = 0,
356
+ version = 1,
357
+ nodes
358
+ } = scene
359
+ const versionHex = nToHS(version)
360
+ const idHex = nToHS(scene.id)
361
+ const modeHex = nToHS(scene.mode)
362
+ const intervalTimeHex = nToHS(scene.speed)
363
+ const changeTimeHex = nToHS(scene.speed)
364
+ const optionAHex = nToHS(
365
+ parseInt(
366
+ `${segmented}${loop}${excessive}${direction}${toFixed(
367
+ expand.toString(2),
368
+ 2
369
+ )}${reserved1}${reserved2}`,
370
+ 2
371
+ )
372
+ );
373
+ const optionBHex = nToHS(0)
374
+ const optionCHex = nToHS(0)
375
+ let nodeHex = ''
376
+ if (isStringLight) {
377
+ nodeHex = nodes.map(node => {
378
+ return `${nToHS(node.v)}${nToHS(node.h, 4)}${nToHS(node.s)}${nToHS(node.brightness * 10, 4)}${nToHS(node.colorTemp * 10, 4)}`
379
+ }).join('')
380
+ } else {
381
+ const brightHex = nToHS(nodes[0].v)
382
+ nodeHex = brightHex + nodes.map(node => {
383
+ return `${nToHS(node.h, 4)}${nToHS(node.s)}`
384
+ }).join('')
385
+ }
386
+
387
+ return versionHex + idHex + modeHex + intervalTimeHex + changeTimeHex + optionAHex + optionBHex + optionCHex + nodeHex
388
+ }
389
+
390
+ export function useFantasyScene(sceneDp: string, workModeDp: string, switchDp: string, isStringLight?: boolean): [number, (scene: StripSceneInfo) => Promise<Result<any>>] {
391
+ const [dps, setDps]: [any, (v: any) => Promise<Result<any>>] = useDps()
392
+ const dp = dps[sceneDp]
393
+ const [sceneState, setSceneState] = useState<StripSceneInfo>(stripDp2Obj(dp, isStringLight))
394
+
395
+ useUpdateEffect(() => {
396
+ setSceneState(stripDp2Obj(dp, isStringLight))
397
+ }, [dp])
398
+
399
+ const setFantasyScene = (scene: StripSceneInfo) => {
400
+ const sceneHex = stripObj2Dp(scene, isStringLight)
401
+ return setDps({
402
+ [sceneDp]: sceneHex,
403
+ [workModeDp]: WorkMode.Scene,
404
+ [switchDp]: true
405
+ })
406
+ }
407
+ return [sceneState.id, setFantasyScene]
408
+ }
409
+
410
+ type LampType = {
411
+ isStringLight?: boolean
412
+ isStripLight?: boolean
413
+ }
414
+ export async function getRemoteFantasyScene(featureId: string, devId: string, lampType: LampType) {
415
+ const res = await NativeApi.getJson(devId, featureId)
416
+ const isNormalData = Array.isArray(parseJSON(res?.data))
417
+ if (res.success && isNormalData) {
418
+ return {
419
+ success: true,
420
+ data: JSON.parse(res.data)?.map(item => remoteFantasySceneInfo2SceneUIState(item, lampType.isStringLight)),
421
+ }
422
+ } else {
423
+ if (res.msg?.includes('资源未找到') || !isNormalData) {
424
+ const defaultScene = getDefFantasyScene(lampType)
425
+ const res = await NativeApi.putJson(devId, featureId, JSON.stringify(defaultScene))
426
+ if (res.success) {
427
+ return {
428
+ success: true,
429
+ data: defaultScene.map(item => remoteFantasySceneInfo2SceneUIState(item, lampType.isStringLight))
430
+ }
431
+ }
432
+ return { success: false }
433
+ }
434
+ return { success: false }
435
+ }
436
+
437
+ }
438
+
439
+ function remoteFantasySceneInfo2SceneUIState(remoteScene: RemoteSceneInfo, isStringLight?: boolean): StripSceneUIState {
440
+ const stripSceneInfo = stripDp2Obj(remoteScene.i, isStringLight)
441
+ return {
442
+ ...stripSceneInfo,
443
+ name: remoteScene.n,
444
+ image: ''
445
+ }
446
+ }
447
+
448
+ export function saveFantasyScene(devId: string, featureId: string, scenes: StripSceneUIState[], isStringLight?: boolean) {
449
+ const newScenes: RemoteSceneInfo[] = scenes.map(s => {
450
+ return {
451
+ n: s.name,
452
+ i: stripObj2Dp(s, isStringLight),
453
+ s: '',
454
+ t: 0,
455
+ e: false,
456
+ }
457
+ })
458
+ return NativeApi.putJson(devId, featureId, JSON.stringify(newScenes))
459
+ }