@ledvance/ui-biz-bundle 1.0.2 → 1.0.4

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 (34) hide show
  1. package/.babelrc +31 -31
  2. package/.eslintignore +5 -5
  3. package/.eslintrc.js +27 -27
  4. package/.prettierrc.js +1 -1
  5. package/.versionrc +5 -5
  6. package/package.json +72 -72
  7. package/rn-cli.config.js +8 -8
  8. package/src/modules/history/HistoryPage.d.ts +2 -2
  9. package/src/modules/history/HistoryPage.tsx +254 -254
  10. package/src/modules/history/SwitchHistoryPageActions.d.ts +13 -13
  11. package/src/modules/history/SwitchHistoryPageActions.ts +53 -53
  12. package/src/modules/hooks/DeviceDpStateHooks.ts +27 -0
  13. package/src/modules/mood/MixLightActions.ts +82 -0
  14. package/src/modules/mood/MixLightSceneActions.ts +259 -0
  15. package/src/modules/mood/MixMoodItem.tsx +138 -0
  16. package/src/modules/mood/MixScene.tsx +131 -0
  17. package/src/modules/mood/MixSceneBeans.ts +62 -0
  18. package/src/modules/mood/MoodAction.ts +222 -0
  19. package/src/modules/mood/MoodItem.tsx +113 -0
  20. package/src/modules/mood/SceneInfo.ts +319 -0
  21. package/src/modules/timeSchedule/DeviceState.tsx +54 -0
  22. package/src/modules/timeSchedule/LdvScheduleItem.tsx +125 -0
  23. package/src/modules/timeSchedule/ManualSetting.tsx +69 -0
  24. package/src/modules/timeSchedule/MoodSetting.tsx +66 -0
  25. package/src/modules/timeSchedule/ScheduleScene.tsx +138 -0
  26. package/src/modules/timeSchedule/SingleLightView.tsx +254 -0
  27. package/src/modules/timeSchedule/TimeScheduleEditpage.tsx +480 -0
  28. package/src/modules/timeSchedule/TimeSchedulePage.tsx +323 -0
  29. package/src/modules/timeSchedule/mix/MixLightBean.ts +10 -0
  30. package/src/modules/timeSchedule/mix/MixLightView.tsx +221 -0
  31. package/src/modules/timeSchedule/utils.ts +7 -0
  32. package/src/modules/timer/TimerPage.tsx +409 -406
  33. package/src/modules/timer/{timerPageAction.ts → TimerPageAction.ts} +91 -91
  34. package/tsconfig.json +50 -50
@@ -0,0 +1,27 @@
1
+ import { NativeApi } from "@ledvance/base/src/api/native"
2
+ export const WHITE = 'white'
3
+ export const COLOUR = 'colour'
4
+ export const SCENE = 'scene'
5
+ export const MUSIC = 'music'
6
+
7
+ export const setBiorhythmDp = (deviceId: string, value: string, dpCodes: Record<string, string>) => {
8
+ return NativeApi.setDp(deviceId, dpCodes.rhythm_mode, value)
9
+ }
10
+
11
+ export const setMixRgbcwDp = (deviceId: string, value: string, enable: boolean | undefined, dpCodes: Record<string, string>) => {
12
+ const dps: { [p: string]: any } = {
13
+ [dpCodes.mix_rgbcw]: value,
14
+ }
15
+ if (enable != undefined) {
16
+ dps[dpCodes.switch_led] = enable
17
+ }
18
+ return NativeApi.setDps(deviceId, dps)
19
+ }
20
+
21
+ export const setSceneDp = (deviceId: string, value: string, dpCodes: Record<string, string>) => {
22
+ return NativeApi.setDps(deviceId, { [dpCodes.switch_led]: true, [dpCodes.work_mode]: 'scene', [dpCodes.scene_data]: value })
23
+ }
24
+
25
+ export const setMixSceneDp = (deviceId: string, value: string, dpCodes: Record<string, string>) => {
26
+ return NativeApi.setDps(deviceId, { [dpCodes.work_mode]: 'scene', [dpCodes.mix_light_scene]: value })
27
+ }
@@ -0,0 +1,82 @@
1
+ import { MixLightBean } from '../timeSchedulecopy/mix/MixLightBean'
2
+ import { spliceByStep } from '@ledvance/base/src/utils/common';
3
+ import { asyncSetDps, useDp } from '@ledvance/base/src/models/modules/NativePropsSlice';
4
+ import { Dispatch, useState } from 'react'
5
+ import { useDispatch } from 'react-redux'
6
+ import { useUpdateEffect } from 'ahooks'
7
+ import { setMixRgbcwDp } from '../hooks/DeviceDpStateHooks'
8
+ import { Result } from '@ledvance/base/src/models/modules/Result'
9
+
10
+ export function useMixRgbcw(dpCodes: Record<string,string>): [MixLightBean, SetMixLightResultType] {
11
+ const [dp]:any = useDp(dpCodes.mix_rgbcw)
12
+ const setMixLightFn = setMixLight(useDispatch())
13
+ const [mixLightState, setMixLightState] = useState(dp2Obj(dp))
14
+ useUpdateEffect(() => {
15
+ const newMixLightState = dp2Obj(dp)
16
+ setMixLightState(newMixLightState)
17
+ console.log('长链接MIX', newMixLightState)
18
+ }, [dp])
19
+ return [mixLightState, setMixLightFn]
20
+ }
21
+
22
+ type SetMixLightResultType = (deviceId: string, mixLightBean: MixLightBean, dpCodes: Record<string,string>) => Promise<Result<any>>
23
+
24
+ function setMixLight(dispatch: Dispatch<any>): SetMixLightResultType {
25
+ return (deviceId: string, mixLightBean: MixLightBean, dpCodes) => asyncSetDps(dispatch, async () => {
26
+ const dpValue = obj2Dp(mixLightBean)
27
+ const enable = mixLightBean.whiteLightSwitch === mixLightBean.colorLightSwitch ? mixLightBean.whiteLightSwitch : undefined
28
+ const controlResult: any = await setMixRgbcwDp(deviceId, dpValue, enable, dpCodes)
29
+ return {
30
+ result: { success: controlResult.result },
31
+ dps: { [dpCodes.mix_rgbcw]: dpValue },
32
+ }
33
+ })
34
+ }
35
+
36
+ export function obj2Dp(obj: MixLightBean): string {
37
+ const powerSwitchDpValueArray = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
38
+ if (obj.whiteLightSwitch) {
39
+ powerSwitchDpValueArray[15] = '1'
40
+ }
41
+ if (obj.colorLightSwitch) {
42
+ powerSwitchDpValueArray[14] = '1'
43
+ }
44
+ if (obj.mixRgbcwEnabled) {
45
+ powerSwitchDpValueArray[13] = '1'
46
+ }
47
+ const powerSwitchDpValueBinary = powerSwitchDpValueArray.join('')
48
+ const powerSwitchDpValue = parseInt(powerSwitchDpValueBinary, 2).toString(16).padStart(4, '0')
49
+ const hueDpValue = obj.hue.toString(16).padStart(4, '0')
50
+ const satDpValue = (obj.sat * 10).toString(16).padStart(4, '0')
51
+ const lightnessDpValue = (obj.lightness * 10).toString(16).padStart(4, '0')
52
+ const brightnessDpValue = (obj.brightness * 10).toString(16).padStart(4, '0')
53
+ const colorTempDpValue = (obj.colorTempPercent * 10).toString(16).padStart(4, '0')
54
+ return powerSwitchDpValue + hueDpValue + satDpValue + lightnessDpValue + brightnessDpValue + colorTempDpValue
55
+ }
56
+
57
+ export function dp2Obj(dp: string): MixLightBean {
58
+ if (!dp) {
59
+ return {
60
+ whiteLightSwitch: true,
61
+ colorLightSwitch: true,
62
+ mixRgbcwEnabled: true,
63
+ hue: 360,
64
+ sat: 100,
65
+ lightness: 100,
66
+ brightness: 100,
67
+ colorTempPercent: 100,
68
+ }
69
+ }
70
+ const dpValueArray = spliceByStep(dp, 4)
71
+ const powerSwitch = parseInt(dpValueArray[0], 16).toString(2).padStart(16, '0')
72
+ return {
73
+ whiteLightSwitch: powerSwitch[15] === '1',
74
+ colorLightSwitch: powerSwitch[14] === '1',
75
+ mixRgbcwEnabled: powerSwitch[13] === '1',
76
+ hue: parseInt(dpValueArray[1], 16), // 色相 0-360
77
+ sat: parseInt(dpValueArray[2], 16) / 10, // 饱和度 0-100
78
+ lightness: parseInt(dpValueArray[3], 16) / 10, // 明度 0-100
79
+ brightness: parseInt(dpValueArray[4], 16) / 10, // 亮度 0-100
80
+ colorTempPercent: parseInt(dpValueArray[5], 16) / 10, // 色温 0-100
81
+ }
82
+ }
@@ -0,0 +1,259 @@
1
+ import { getFeature, putFeature } from '@ledvance/base/src/api/native';
2
+ import { setMixSceneDp } from '../hooks/DeviceDpStateHooks'
3
+ import {
4
+ MixMood,
5
+ MixSceneInfo,
6
+ MixSceneLampInfo,
7
+ MixSceneNodeInfo,
8
+ RemoteMixScene,
9
+ } from './MixSceneBeans'
10
+ import I18n from '@ledvance/base/src/i18n'
11
+ import res from '@ledvance/base/src/res';
12
+ import { NativeResult, Result } from '@ledvance/base/src/models/modules/Result';
13
+ import { asyncSetDps, useDp } from '@ledvance/base/src/models/modules/NativePropsSlice';
14
+ import { Dispatch, useState } from 'react'
15
+ import { useUpdateEffect } from 'ahooks'
16
+ import { useDispatch } from 'react-redux'
17
+ import { SceneNodeTransitionMode } from './SceneInfo'
18
+
19
+ const MixLightSceneListFeatureId = 'MixLightSceneList'
20
+
21
+ export function useMixScene(dpCodes: Record<string, string>): [number | undefined, SetMixSceneType] {
22
+ const [dp]:any = useDp(dpCodes.mix_light_scene)
23
+ const [mixSceneState, setMixSceneState] = useState<MixSceneInfo | undefined>(dp2Obj(dp))
24
+ useUpdateEffect(() => {
25
+ setMixSceneState(dp2Obj(dp))
26
+ }, [dp])
27
+ return [mixSceneState?.id, setMixScene(useDispatch())]
28
+ }
29
+
30
+ type SetMixSceneType = (deviceId: string, mixScene: MixSceneInfo, dpCodes: Record<string, string>) => Promise<Result<any>>
31
+
32
+ function setMixScene(dispatch: Dispatch<any>): SetMixSceneType {
33
+ return (deviceId: string, mixScene: MixSceneInfo, dpCodes) => {
34
+ return asyncSetDps(dispatch, async () => {
35
+ const dpValue = obj2Dp(mixScene)
36
+ const controlResult: any = await setMixSceneDp(deviceId, dpValue, dpCodes)
37
+ return {
38
+ result: { success: controlResult.result },
39
+ dps: { [dpCodes.work_mode]: 'scene', [dpCodes.mix_light_scene]: dpValue },
40
+ }
41
+ })
42
+ }
43
+ }
44
+
45
+ export async function getMixLightSceneList(deviceId: string): Promise<Result<MixMood[]>> {
46
+ const res: NativeResult<MixMood[]> = await getFeature(deviceId, MixLightSceneListFeatureId)
47
+ if (!(!!res.data)) {
48
+ const setDefRes = await putFeature(deviceId, MixLightSceneListFeatureId, getDefMixLightSceneList())
49
+ if (setDefRes.result) {
50
+ return getMixLightSceneList(deviceId)
51
+ }
52
+ return { success: false }
53
+ }
54
+ return {
55
+ success: true,
56
+ data: res.data.map(scene => {
57
+ return {
58
+ ...scene,
59
+ ...dp2Obj(scene.value),
60
+ }
61
+ }),
62
+ }
63
+ }
64
+
65
+ export async function saveMixScene(
66
+ deviceId: string,
67
+ isDelete: boolean,
68
+ name: string,
69
+ mixSceneObj: MixSceneInfo,
70
+ sceneList: MixMood[],
71
+ ): Promise<Result<any>> {
72
+ if (!isDelete) {
73
+ mixSceneObj.lamps.forEach(lamp => {
74
+ if (lamp.enable) {
75
+ if (lamp.nodes[0].changeType === SceneNodeTransitionMode.Static) {
76
+ lamp.nodes = [lamp.nodes[0]]
77
+ }
78
+ } else {
79
+ lamp.nodes = []
80
+ }
81
+ })
82
+ }
83
+ const newSceneList: RemoteMixScene[] = isDelete ? sceneList : sceneList.map(scene => {
84
+ return {
85
+ name: scene.id === mixSceneObj.id ? name : scene.name,
86
+ image: scene.image,
87
+ value: scene.id === mixSceneObj.id ? obj2Dp(mixSceneObj) : scene.value,
88
+ }
89
+ })
90
+ return setMixLightSceneList(deviceId, newSceneList)
91
+ }
92
+
93
+ export async function setMixLightSceneList(deviceId: string, sceneList: RemoteMixScene[]): Promise<Result<any>> {
94
+ const res = await putFeature(deviceId, MixLightSceneListFeatureId, sceneList)
95
+ return {
96
+ success: res.result,
97
+ msg: res.msg,
98
+ data: res.data,
99
+ }
100
+ }
101
+
102
+ /**
103
+ * 混光场景命令对象转换为dp数据
104
+ * @param obj
105
+ */
106
+ export function obj2Dp(obj: MixSceneInfo) {
107
+ const versionHex = obj.version.toString(16).padStart(2, '0')
108
+ const sceneNoHex = obj.id.toString(16).padStart(2, '0')
109
+ const lampsHex = obj.lamps.map(lamp => {
110
+ let lampHex = lamp.enable ? '01' : '00'
111
+ const nodes = lamp.nodes || []
112
+ lampHex += nodes.length.toString(16).padStart(2, '0')
113
+ if (nodes.length === 0 || !lamp.enable) {
114
+ return lampHex
115
+ }
116
+ lampHex += lamp.type.toString(16).padStart(2, '0')
117
+ lampHex += nodes.map(node => {
118
+ let nodeHex = ''
119
+ nodeHex += node.intervalTime.toString(16).padStart(2, '0')
120
+ nodeHex += node.changeTime.toString(16).padStart(2, '0')
121
+ nodeHex += node.changeType.toString(16).padStart(2, '0')
122
+ switch (lamp.type) { // 1:W 只有亮度,2:CW 亮度+色温,3:RGB HSV,4:RGBC HSV+色温,5:RGBCW HSV+色温+亮度
123
+ case 1:
124
+ nodeHex += (node.brightness * 10).toString(16).padStart(4, '0')
125
+ break
126
+ case 2:
127
+ nodeHex += (node.brightness * 10).toString(16).padStart(4, '0')
128
+ nodeHex += (node.colorTemp * 10).toString(16).padStart(4, '0')
129
+ break
130
+ case 3:
131
+ nodeHex += node.hue.toString(16).padStart(4, '0')
132
+ nodeHex += (node.sat * 10).toString(16).padStart(4, '0')
133
+ nodeHex += (node.lightness * 10).toString(16).padStart(4, '0')
134
+ break
135
+ case 4:
136
+ nodeHex += node.hue.toString(16).padStart(4, '0')
137
+ nodeHex += (node.sat * 10).toString(16).padStart(4, '0')
138
+ nodeHex += (node.lightness * 10).toString(16).padStart(4, '0')
139
+ nodeHex += (node.colorTemp * 10).toString(16).padStart(4, '0')
140
+ break
141
+ case 5:
142
+ nodeHex += node.hue.toString(16).padStart(4, '0')
143
+ nodeHex += (node.sat * 10).toString(16).padStart(4, '0')
144
+ nodeHex += (node.lightness * 10).toString(16).padStart(4, '0')
145
+ nodeHex += (node.brightness * 10).toString(16).padStart(4, '0')
146
+ nodeHex += (node.colorTemp * 10).toString(16).padStart(4, '0')
147
+ break
148
+ }
149
+ return nodeHex
150
+ }).join('')
151
+ return lampHex
152
+ }).join('')
153
+ return versionHex + sceneNoHex + lampsHex
154
+ }
155
+
156
+ /**
157
+ * dp数据转换为混光场景对象
158
+ * @returns MixSceneInfo
159
+ */
160
+ export function dp2Obj(dp: string): MixSceneInfo | undefined {
161
+ if (!(!!dp)) {
162
+ return undefined
163
+ }
164
+ const result = {} as MixSceneInfo
165
+ result.version = parseInt(dp.slice(0, 2), 16)
166
+ result.id = parseInt(dp.slice(2, 4), 16)
167
+ result.lamps = []
168
+ let lampsHex = dp.slice(4)
169
+ while (lampsHex.length != 0) {
170
+ const lamp = { nodes: [] as MixSceneNodeInfo[] } as MixSceneLampInfo
171
+ lamp.enable = parseInt(lampsHex.slice(0, 2), 16) === 1
172
+ lampsHex = lampsHex.slice(2)
173
+ const nodeCount = parseInt(lampsHex.slice(0, 2), 16)
174
+ lampsHex = lampsHex.slice(2)
175
+ if (nodeCount === 0) {
176
+ result.lamps.push(lamp)
177
+ continue
178
+ }
179
+ lamp.type = parseInt(lampsHex.slice(0, 2), 16)
180
+ lampsHex = lampsHex.slice(2)
181
+ for (let i = 0; i < nodeCount; i++) {
182
+ const node = {} as MixSceneNodeInfo
183
+ node.intervalTime = parseInt(lampsHex.slice(0, 2), 16)
184
+ node.changeTime = parseInt(lampsHex.slice(2, 4), 16)
185
+ node.changeType = parseInt(lampsHex.slice(4, 6), 16)
186
+ lampsHex = lampsHex.slice(6)
187
+ switch (lamp.type) {
188
+ case 1:
189
+ node.brightness = parseInt(lampsHex.slice(0, 4), 16) / 10
190
+ lampsHex = lampsHex.slice(4)
191
+ break
192
+ case 2:
193
+ node.brightness = parseInt(lampsHex.slice(0, 4), 16) / 10
194
+ node.colorTemp = parseInt(lampsHex.slice(4, 8), 16) / 10
195
+ lampsHex = lampsHex.slice(8)
196
+ break
197
+ case 3:
198
+ node.hue = parseInt(lampsHex.slice(0, 4), 16)
199
+ node.sat = parseInt(lampsHex.slice(4, 8), 16) / 10
200
+ node.lightness = parseInt(lampsHex.slice(8, 12), 16) / 10
201
+ lampsHex = lampsHex.slice(12)
202
+ break
203
+ case 4:
204
+ node.hue = parseInt(lampsHex.slice(0, 4), 16)
205
+ node.sat = parseInt(lampsHex.slice(4, 8), 16) / 10
206
+ node.lightness = parseInt(lampsHex.slice(8, 12), 16) / 10
207
+ node.colorTemp = parseInt(lampsHex.slice(12, 16), 16) / 10
208
+ lampsHex = lampsHex.slice(16)
209
+ break
210
+ case 5:
211
+ node.hue = parseInt(lampsHex.slice(0, 4), 16)
212
+ node.sat = parseInt(lampsHex.slice(4, 8), 16) / 10
213
+ node.lightness = parseInt(lampsHex.slice(8, 12), 16) / 10
214
+ node.brightness = parseInt(lampsHex.slice(12, 16), 16) / 10
215
+ node.colorTemp = parseInt(lampsHex.slice(16, 20), 16) / 10
216
+ lampsHex = lampsHex.slice(20)
217
+ break
218
+ }
219
+ lamp.nodes.push(node)
220
+ }
221
+ result.lamps.push(lamp)
222
+ }
223
+ return result
224
+ }
225
+
226
+ function getDefMixLightSceneList(): RemoteMixScene[] {
227
+ return [
228
+ {
229
+ name: I18n.getLang('mesh_device_detail_lighting_goodnight'),
230
+ image: res.scene_goodnight,
231
+ value: '00000101020e0d0000c800000000',
232
+ },
233
+ {
234
+ name: I18n.getLang('mesh_device_detail_lighting_read'),
235
+ image: res.scene_reading,
236
+ value: '00010101020e0d0003e801f40000',
237
+ },
238
+ {
239
+ name: I18n.getLang('mesh_device_detail_lighting_work'),
240
+ image: res.scene_work,
241
+ value: '00020101020e0d0003e803e80000',
242
+ },
243
+ {
244
+ name: I18n.getLang('mesh_device_detail_lighting_leisure'),
245
+ image: res.scene_leisure,
246
+ value: '00030101020e0d0001f401f40000',
247
+ },
248
+ {
249
+ name: I18n.getLang('mesh_device_detail_lighting_color_mode'),
250
+ image: res.scene_custom1,
251
+ value: '00040000010603464601000003e803e8464601007803e803e846460100f003e803e8464601003d03e803e846460100ae03e803e8464601011303e803e8',
252
+ },
253
+ {
254
+ name: I18n.getLang('mesh_device_detail_lighting_white_mode'),
255
+ image: res.scene_custom2,
256
+ value: '000501030246460103e8000a46460103e8015446460103e803e80000',
257
+ },
258
+ ]
259
+ }
@@ -0,0 +1,138 @@
1
+ import React from 'react'
2
+ import Card from '@ledvance/base/src/components/Card'
3
+ import { SwitchButton, Utils } from 'tuya-panel-kit'
4
+ import { Image, StyleSheet, Text, View, ViewProps } from 'react-native'
5
+ import {
6
+ getMainLight,
7
+ getSecondaryLight,
8
+ isStaticMixMood,
9
+ MixMood,
10
+ MixSceneLampInfo,
11
+ } from './MixSceneBeans'
12
+ import { hsv2Hex } from '@ledvance/base/src/utils'
13
+ import { cctToColor } from '@ledvance/base/src/utils/cctUtils'
14
+ import Spacer from '@ledvance/base/src/components/Spacer'
15
+ import MoodColorsLine from '@ledvance/base/src/components/MoodColorsLine'
16
+ import { SceneNodeTransitionMode } from './SceneInfo'
17
+ import I18n from '@ledvance/base/src/i18n'
18
+ import { mapFloatToRange } from '@ledvance/base/src/utils'
19
+
20
+ const cx = Utils.RatioUtils.convertX
21
+
22
+ const lightOn = require('../res/light_on.png')
23
+ const lightOff = require('../res/light_off.png')
24
+
25
+ interface MixMoodItemProps extends ViewProps {
26
+ enable: boolean
27
+ mixMood: MixMood
28
+ onPress?: () => void
29
+ onSwitch: (enable: boolean) => void
30
+ }
31
+
32
+ const MixMoodItem = (props: MixMoodItemProps) => {
33
+ const { mixMood } = props
34
+ const mainLight = getMainLight(mixMood)
35
+ const secondaryLight = getSecondaryLight(mixMood)
36
+
37
+ return (
38
+ <Card style={styles.card} onPress={props.onPress}>
39
+ <View>
40
+ <Spacer height={cx(16)} />
41
+ <View style={styles.headline}>
42
+ <Text style={styles.headText}>{mixMood.name}</Text>
43
+ <SwitchButton value={props.enable} onValueChange={props.onSwitch} thumbStyle={{ elevation: 0 }} />
44
+ </View>
45
+ <Spacer />
46
+ <MixMoodColorsLine mixSubLight={mainLight} colorLight={false} />
47
+ <Spacer height={cx(7)} />
48
+ <MixMoodColorsLine mixSubLight={secondaryLight} colorLight={true} />
49
+ <Spacer height={cx(12)} />
50
+ <View style={styles.moodTypeItem}>
51
+ <View style={styles.moodTypeLabel}>
52
+ <Text style={styles.moodTypeLabelText}>
53
+ {I18n.getLang(isStaticMixMood(mixMood) ? 'mood_overview_field_chip_text' : 'mood_overview_field_chip_2')}
54
+ </Text>
55
+ </View>
56
+ </View>
57
+ <Spacer height={cx(16)} />
58
+ </View>
59
+ </Card>
60
+ )
61
+ }
62
+
63
+ export default MixMoodItem
64
+
65
+ export function MixMoodColorsLine(props: { mixSubLight: MixSceneLampInfo, colorLight: boolean }) {
66
+ const { mixSubLight, colorLight } = props
67
+ const lightColors = mixSubLight.nodes?.map(n => {
68
+ return colorLight ? hsv2Hex(n.hue, Math.round(n.sat), Math.round(mapFloatToRange(n.lightness / 100, 50, 100)))
69
+ : cctToColor(n.colorTemp.toFixed())
70
+ })
71
+ return (
72
+ <View style={styles.gradientItem}>
73
+ <Spacer height={0} width={cx(16)} />
74
+ <MoodColorsLine
75
+ width={cx(264)}
76
+ type={mixSubLight.enable && mixSubLight.nodes[0].changeType === SceneNodeTransitionMode.Gradient ? 'gradient' : 'separate'}
77
+ colors={mixSubLight.enable ? lightColors : ['#eee']} />
78
+ <Spacer height={0} width={cx(7)} />
79
+ <View style={styles.gradientItemIconView}>
80
+ <Image style={styles.gradientItemIcon} source={mixSubLight.enable ? lightOn : lightOff} />
81
+ </View>
82
+ <Spacer height={0} width={cx(16)} />
83
+ </View>
84
+ )
85
+ }
86
+
87
+ const styles = StyleSheet.create({
88
+ card: {
89
+ marginHorizontal: cx(24),
90
+ },
91
+ headline: {
92
+ flexDirection: 'row',
93
+ marginHorizontal: cx(16),
94
+ },
95
+ headText: {
96
+ flex: 1,
97
+ color: '#000',
98
+ fontSize: cx(16),
99
+ fontFamily: 'helvetica_neue_lt_std_bd',
100
+ lineHeight: cx(20),
101
+ },
102
+ gradientItem: {
103
+ flexDirection: 'row',
104
+ },
105
+ gradientItemIconView: {
106
+ width: cx(24),
107
+ height: cx(24),
108
+ justifyContent: 'center',
109
+ alignItems: 'center',
110
+ backgroundColor: '#aaa',
111
+ borderRadius: cx(8),
112
+ },
113
+ gradientItemIcon: {
114
+ width: cx(16),
115
+ height: cx(16),
116
+ tintColor: '#fff',
117
+ },
118
+ gradient: {
119
+ borderRadius: cx(8),
120
+ },
121
+ moodTypeItem: {
122
+ flexDirection: 'row',
123
+ },
124
+ moodTypeLabel: {
125
+ marginStart: cx(16),
126
+ paddingHorizontal: cx(12.5),
127
+ backgroundColor: '#E6E7E8',
128
+ borderRadius: cx(8),
129
+ },
130
+ moodTypeLabelText: {
131
+ height: cx(16),
132
+ color: '#000000DD',
133
+ fontSize: cx(10),
134
+ textAlignVertical: 'center',
135
+ fontFamily: 'helvetica_neue_lt_std_roman',
136
+ lineHeight: cx(16),
137
+ },
138
+ })
@@ -0,0 +1,131 @@
1
+ import React, { useCallback, useEffect } from 'react'
2
+ import { useDeviceInfo } from '@ledvance/base/src/models/modules/NativePropsSlice'
3
+ import I18n from '@ledvance/base/src/i18n'
4
+ import res from '@res'
5
+ import { isStaticMixMood, MixMood } from './MixSceneBeans'
6
+ import { useReactive } from 'ahooks'
7
+ import { FlatList, StyleSheet, View } from 'react-native'
8
+ import Tag from '@ledvance/base/src/components/Tag'
9
+ import Spacer from '@ledvance/base/src/components/Spacer'
10
+ import InfoText from '@ledvance/base/src/components/InfoText'
11
+ import { Utils } from 'tuya-panel-kit'
12
+ import MixMoodItem from './MixMoodItem'
13
+ import { getMixLightSceneList } from './MixLightSceneActions'
14
+
15
+ const cx = Utils.RatioUtils.convertX
16
+
17
+ interface MixUIState {
18
+ showAddMixMoodDialog: boolean
19
+ staticTagChecked: boolean
20
+ dynamicTagChecked: boolean
21
+ currentMixMood?: MixMood
22
+ mixMoods: MixMood[]
23
+ filteredMoods: MixMood[]
24
+ flag: symbol
25
+ }
26
+
27
+ const MixScene = ({ setActionScene, mixScene }) => {
28
+ const deviceInfo = useDeviceInfo()
29
+
30
+ const state = useReactive<MixUIState>({
31
+ showAddMixMoodDialog: false,
32
+ staticTagChecked: true,
33
+ dynamicTagChecked: true,
34
+ mixMoods: [],
35
+ filteredMoods: [],
36
+ flag: Symbol(),
37
+ })
38
+
39
+ const initMixLightSceneList = useCallback(async () => {
40
+ const res = await getMixLightSceneList(deviceInfo.devId)
41
+ if (res.success) {
42
+ state.mixMoods = res.data || []
43
+ const itemSence = state.mixMoods?.find(mix => mix.value === mixScene)
44
+ setActionScene(itemSence || state.mixMoods[0])
45
+ state.currentMixMood = itemSence || state.mixMoods[0]
46
+ }
47
+ }, [])
48
+
49
+ useEffect(() => {
50
+ initMixLightSceneList().then()
51
+ }, [state.flag])
52
+
53
+ useEffect(() => {
54
+ state.filteredMoods = state.mixMoods.filter(item => {
55
+ return (state.staticTagChecked && state.dynamicTagChecked) ||
56
+ (state.staticTagChecked && isStaticMixMood(item)) ||
57
+ (state.dynamicTagChecked && !isStaticMixMood(item))
58
+ })
59
+ }, [state.staticTagChecked, state.dynamicTagChecked, state.mixMoods])
60
+
61
+ return (
62
+ <>
63
+ <View style={styles.tagLine}>
64
+ <Tag
65
+ checked={state.staticTagChecked}
66
+ text={I18n.getLang('mood_overview_filter_name_text1')}
67
+ onCheckedChange={checked => {
68
+ state.staticTagChecked = checked
69
+ }} />
70
+ <Spacer width={cx(8)} height={0} />
71
+ <Tag
72
+ checked={state.dynamicTagChecked}
73
+ text={I18n.getLang('mood_overview_filter_name_text2')}
74
+ onCheckedChange={checked => {
75
+ state.dynamicTagChecked = checked
76
+ }} />
77
+ </View>
78
+ <Spacer height={cx(10)} />
79
+ <FlatList
80
+ data={state.filteredMoods}
81
+ renderItem={({ item }) =>
82
+ <MixMoodItem
83
+ enable={item.id === state.currentMixMood?.id}
84
+ mixMood={item}
85
+ onSwitch={async enable => {
86
+ if (enable) {
87
+ state.currentMixMood = item
88
+ setActionScene(item)
89
+ }
90
+ }} />
91
+ }
92
+ ListHeaderComponent={() => (<Spacer height={cx(10)} />)}
93
+ ItemSeparatorComponent={() => (<Spacer />)}
94
+ ListFooterComponent={() => (
95
+ <View style={styles.infoLine}>
96
+ <Spacer />
97
+ <InfoText
98
+ icon={res.ic_info}
99
+ text={I18n.getLang('mood_overview_information_text')} />
100
+ <Spacer height={cx(40)} />
101
+ </View>
102
+ )}
103
+ keyExtractor={item => `${item.id}`} />
104
+ </>
105
+ )
106
+ }
107
+
108
+ const styles = StyleSheet.create({
109
+ tagLine: {
110
+ flexDirection: 'row',
111
+ marginHorizontal: cx(24),
112
+ marginTop: cx(24),
113
+ },
114
+ infoLine: {
115
+ marginHorizontal: cx(24),
116
+ },
117
+ addMixMoodDialog: {
118
+ width: cx(171),
119
+ height: cx(90.5),
120
+ marginStart: cx(156),
121
+ marginTop: cx(105),
122
+ backgroundColor: '#fff',
123
+ },
124
+ popoverItem: {
125
+ width: cx(171),
126
+ height: cx(45),
127
+ alignItems: 'flex-start',
128
+ },
129
+ })
130
+
131
+ export default MixScene