@ledvance/ui-biz-bundle 1.0.71 → 1.0.72

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.0.71",
7
+ "version": "1.0.72",
8
8
  "scripts": {},
9
9
  "dependencies": {
10
10
  "@ledvance/base": "^1.x",
@@ -0,0 +1,184 @@
1
+ import React, { useCallback, useEffect } from 'react'
2
+ import Page from '@ledvance/base/src/components/Page'
3
+ import { Utils } from 'tuya-panel-kit'
4
+ import { StripScenePageUIState, StripSceneUIState } from '../scene/SceneInfo'
5
+ import { getRemoteFantasyScene, useFantasyScene } from '../scene/SceneAction'
6
+ import { useDeviceInfo } from '@ledvance/base/src/models/modules/NativePropsSlice'
7
+ import { useReactive } from 'ahooks'
8
+ import Strings from '@ledvance/base/src/i18n'
9
+ import res from '@ledvance/base/src/res'
10
+ import { FlatList } from 'react-native'
11
+ import Spacer from '@ledvance/base/src/components/Spacer'
12
+ import FantasyMoodItem from './FantasyMoodItem'
13
+ import { useNavigation, useRoute } from '@react-navigation/core'
14
+ import { ui_biz_routerKey } from '../../navigation/Routers'
15
+ import { stripDp2Obj } from '../scene/SceneAction'
16
+ import { Buffer } from 'buffer'
17
+ import { NativeApi } from '@ledvance/base/src/api/native'
18
+ const cx = Utils.RatioUtils.convertX
19
+
20
+ interface MoodPageUIState extends StripScenePageUIState {
21
+ staticTagChecked: boolean
22
+ dynamicTagChecked: boolean
23
+ originScene: StripSceneUIState[]
24
+ filteredMoods: StripSceneUIState[]
25
+ loading: boolean
26
+ }
27
+
28
+ export interface FantasyMoodPageProps {
29
+ featureId: string
30
+ switchLedDpCode: string
31
+ sceneDpCode: string
32
+ workModeDpCode: string
33
+ isStringLight?: boolean
34
+ isStripLight?: boolean
35
+ isSupportColor: boolean
36
+ isSupportTemperature: boolean
37
+ isSupportBrightness: boolean
38
+ }
39
+
40
+
41
+ const FantasyMoodPage = () => {
42
+ const routeParams = useRoute().params as FantasyMoodPageProps
43
+ const params: FantasyMoodPageProps = {
44
+ ...routeParams,
45
+ }
46
+ const [sceneId, setScene] = useFantasyScene(params.sceneDpCode, params.workModeDpCode)
47
+ const deviceInfo = useDeviceInfo()
48
+ const navigation = useNavigation()
49
+
50
+ const state = useReactive<MoodPageUIState>({
51
+ currentScene: undefined,
52
+ staticTagChecked: true,
53
+ dynamicTagChecked: true,
54
+ scenes: [],
55
+ flag: Symbol(),
56
+ originScene: [],
57
+ filteredMoods: [],
58
+ loading: false,
59
+ })
60
+
61
+ useEffect(() =>{
62
+ console.log(stripDp2Obj(Buffer.from('AdgQMjIAAABkAABkAGQ8','base64').toString('hex')), '开合')
63
+ console.log(stripDp2Obj(Buffer.from('AdcPMjIAAABkAABkAGQ8','base64').toString('hex')), '乱闪')
64
+ console.log(stripDp2Obj(Buffer.from('AdYOMjIAAABkAABkAGQ8','base64').toString('hex')), '穿梭')
65
+ console.log(stripDp2Obj(Buffer.from('AdUNMjIAAABkAABkAGQ8','base64').toString('hex')), '反弹')
66
+ console.log(stripDp2Obj(Buffer.from('AdQMMjIAAABkAABkAGQ8','base64').toString('hex')), '闪现')
67
+ console.log(stripDp2Obj(Buffer.from('AdMJMjIAAABkAABkAGQ8','base64').toString('hex')), '飘动')
68
+ console.log(stripDp2Obj(Buffer.from('AdIIMjIAAABkAABkAGQ8','base64').toString('hex')), '追光')
69
+ console.log(stripDp2Obj(Buffer.from('AdEHMjIAAABkAABkAGQ8','base64').toString('hex')), '飘落')
70
+ console.log(stripDp2Obj(Buffer.from('AdAGMjIAAABkAABkAGQ8','base64').toString('hex')), '堆积')
71
+ console.log(stripDp2Obj(Buffer.from('Ac8FMjIAAABkAABkAGQ8','base64').toString('hex')), '流星')
72
+ console.log(stripDp2Obj(Buffer.from('Ac4LMjIAAABkAABkAGQ8','base64').toString('hex')), '彩虹')
73
+ console.log(stripDp2Obj(Buffer.from('Ac0KMjIAAABkAABkAGQ8','base64').toString('hex')), '流水')
74
+ console.log(stripDp2Obj(Buffer.from('AcwEMjIAAABkAABkAGQ8','base64').toString('hex')), '闪烁')
75
+ console.log(stripDp2Obj(Buffer.from('AcsDMjIAAABkAABkAGQ8','base64').toString('hex')), '呼吸2')
76
+ console.log(stripDp2Obj(Buffer.from('AcoCMjIAAABkAABkAGQ8','base64').toString('hex')), '呼吸1')
77
+ console.log(stripDp2Obj(Buffer.from('AckBMjIAAABkAABkAGQ8','base64').toString('hex')), '跳变')
78
+ }, [])
79
+
80
+ const getSceneList = useCallback(async (currentSceneId: number) => {
81
+ NativeApi.log(`getScene id ${currentSceneId}`)
82
+ const res = await getRemoteFantasyScene(routeParams.featureId, deviceInfo.devId, { isStringLight: routeParams.isStringLight, isStripLight: routeParams.isStripLight })
83
+ if (res.success) {
84
+ state.scenes = res.data || []
85
+ state.currentScene = state.scenes.find(scene => scene.id === currentSceneId)
86
+ }
87
+ }, [])
88
+
89
+ // useUpdateEffect(() => {
90
+ // state.currentScene = state.scenes.find(scene => scene.id === sceneId)
91
+ // }, [sceneId])
92
+
93
+ useEffect(() => {
94
+ getSceneList(sceneId).then()
95
+ }, [state.flag, sceneId])
96
+
97
+ const navigateToEdit = useCallback((mode: 'edit' | 'add', currentMood?: StripSceneUIState) => {
98
+ navigation.navigate(ui_biz_routerKey.ui_biz_fantasy_mood_edit, {
99
+ mode,
100
+ currentMood,
101
+ moods: state.scenes,
102
+ moduleParams: params,
103
+ onSave: () => {
104
+ state.flag = Symbol()
105
+ },
106
+ })
107
+ }, [])
108
+
109
+ const getSwitchEnable = useCallback((id: number) =>{
110
+ return state.currentScene?.id === id
111
+ }, [state.currentScene?.id])
112
+
113
+ return (
114
+ <>
115
+ <Page
116
+ backText={deviceInfo.name}
117
+ headlineText={Strings.getLang('mood_overview_headline_text')}
118
+ headlineIcon={res.add}
119
+ onHeadlineIconClick={() => {
120
+ navigateToEdit('add', newScene)
121
+ }}
122
+ loading={state.loading}>
123
+ <Spacer height={cx(10)} />
124
+ <FlatList
125
+ data={state.scenes}
126
+ renderItem={({ item }) => {
127
+ return (
128
+ <FantasyMoodItem
129
+ enable={getSwitchEnable(item.id)}
130
+ mood={item}
131
+ onPress={() => {
132
+ navigateToEdit('edit', item)
133
+ }}
134
+ onSwitch={async _ => {
135
+ if (getSwitchEnable(item.id)) return
136
+ state.loading = true
137
+ await setScene(item)
138
+ state.loading = false
139
+ }} />
140
+ )
141
+ }}
142
+ ListHeaderComponent={() => (<Spacer height={cx(10)} />)}
143
+ ItemSeparatorComponent={() => (<Spacer />)}
144
+ ListFooterComponent={() => (<Spacer />)}
145
+ keyExtractor={item => `${item.id}`} />
146
+ </Page>
147
+ </>
148
+ )
149
+ }
150
+
151
+ const newScene = {
152
+ version: 1,
153
+ id: 1,
154
+ mode: 10,
155
+ name: '',
156
+ speed: 50,
157
+ loop: 0,
158
+ segmented: 0,
159
+ direction: 0,
160
+ excessive: 0,
161
+ optionB: 0,
162
+ optionC: 0,
163
+ image: '',
164
+ nodes: [
165
+ {
166
+ brightness: 0,
167
+ colorTemp: 0,
168
+ h: 0,
169
+ isColorNode: true,
170
+ s: 100,
171
+ v: 100
172
+ },
173
+ {
174
+ brightness: 0,
175
+ colorTemp: 0,
176
+ h: 60,
177
+ isColorNode: true,
178
+ s: 100,
179
+ v: 100
180
+ }
181
+ ]
182
+ }
183
+
184
+ export default FantasyMoodPage
@@ -0,0 +1,548 @@
1
+ import Page from '@ledvance/base/src/components/Page'
2
+ import I18n from '@ledvance/base/src/i18n'
3
+ import { useNavigation, useRoute } from '@react-navigation/native'
4
+ import { StackNavigationProp } from '@react-navigation/stack'
5
+ import React, { useCallback, useEffect, useMemo } from 'react'
6
+ import { useReactive } from 'ahooks'
7
+ import { useWorkMode, COLOUR } from 'hooks/DeviceDpStateHooks'
8
+ import { hsv2Hex, mapFloatToRange } from '@ledvance/base/src/utils'
9
+ import { cctToColor } from '@ledvance/base/src/utils/cctUtils'
10
+ import res from '@ledvance/base/src/res'
11
+ import { cloneDeep, find, isEqual, maxBy } from 'lodash'
12
+ import { FlatList, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
13
+ import TextField from '@ledvance/base/src/components/TextField'
14
+ import Card from '@ledvance/base/src/components/Card'
15
+ import Spacer from '@ledvance/base/src/components/Spacer'
16
+ import LampAdjustView from '@ledvance/base/src/components/LampAdjustView'
17
+ import { Utils } from 'tuya-panel-kit'
18
+ import LdvSlider from '@ledvance/base/src/components/ldvSlider'
19
+ import { useDeviceId, useRole } from '@ledvance/base/src/models/modules/NativePropsSlice'
20
+ import TextButton from '@ledvance/base/src/components/TextButton'
21
+ import { stringLightSceneMode, stripLightSceneMode, StripSceneUIState, StripNodeInfo, StripLightSceneMode } from '../scene/SceneInfo'
22
+ import TextFieldStyleButton from '@ledvance/base/src/components/TextFieldStyleButton'
23
+ import { SelectPageParams } from '../select/SelectPage'
24
+ import { showDeleteMoodDialog } from './tools'
25
+ import { ui_biz_routerKey } from '../../navigation/Routers'
26
+ import { FantasyMoodPageProps } from './FantasyMood'
27
+ import Segmented from '@ledvance/base/src/components/Segmented'
28
+ import { saveFantasyScene, useFantasyScene } from '../scene/SceneAction'
29
+ const cx = Utils.RatioUtils.convertX
30
+
31
+ interface FantasyMoodEditPageState {
32
+ headline: string
33
+ mood: StripSceneUIState
34
+ currentNode: StripNodeInfo
35
+ paintBucketSelected: boolean
36
+ sceneMode: StripLightSceneMode
37
+ }
38
+
39
+ export interface FantasyMoodEditParams {
40
+ mode: 'add' | 'edit'
41
+ currentMood: StripSceneUIState
42
+ moods: StripSceneUIState[]
43
+ onSave: () => void
44
+ moduleParams: FantasyMoodPageProps
45
+ }
46
+ const FantasyMoodEditPage = () => {
47
+ const navigation = useNavigation<StackNavigationProp<any>>()
48
+ const routeParams = useRoute().params as FantasyMoodEditParams
49
+ const params = cloneDeep(routeParams)
50
+ const moduleParams = params.moduleParams
51
+ const deviceId = useDeviceId()
52
+ const [, setWorkMode] = useWorkMode(moduleParams.workModeDpCode)
53
+ const [, setFantasyScene] = useFantasyScene(params.moduleParams.sceneDpCode, params.moduleParams.workModeDpCode)
54
+ const role = useRole()
55
+ const state = useReactive<FantasyMoodEditPageState>({
56
+ headline: '',
57
+ mood: params.currentMood,
58
+ currentNode: params.currentMood.nodes[params.currentMood.nodes.length - 1],
59
+ paintBucketSelected: false,
60
+ sceneMode: params.moduleParams.isStringLight ? stringLightSceneMode : stripLightSceneMode
61
+ })
62
+ const canDelete = useMemo(() => (role === 0 || role === 2), [role])
63
+
64
+ useEffect(() => {
65
+ state.headline = I18n.getLang(params.mode ? 'add_new_dynamic_mood_headline_text' : 'edit_static_mood_headline_text')
66
+ }, [params.mode])
67
+
68
+ const getColorBlockColor = useCallback(() => {
69
+ const s = Math.round(mapFloatToRange(state.currentNode.s / 100, 30, 100))
70
+ if (state.currentNode.isColorNode) {
71
+ return hsv2Hex(state.currentNode.h, s, 100)
72
+ }
73
+ if (moduleParams.isSupportTemperature) {
74
+ return cctToColor(state.currentNode.colorTemp.toFixed())
75
+ }
76
+ }, [state.currentNode, state.currentNode.colorTemp])
77
+ const getNodeColor = useCallback((node: StripNodeInfo) => {
78
+ if (node.isColorNode) {
79
+ const s = Math.round(mapFloatToRange(node.s / 100, 30, 100))
80
+ return hsv2Hex(node.h, s, 100)
81
+ }
82
+ return cctToColor(node.colorTemp.toFixed())
83
+ }, [])
84
+
85
+ const onPost = useCallback(async (isDelete: boolean) => {
86
+ const maxModeObject = maxBy(params.moods, 'mode');
87
+ const currentMood = {
88
+ ...state.mood,
89
+ nodes: state.mood.nodes.map(node => {
90
+ if (node.isColorNode) {
91
+ node.brightness = 0;
92
+ node.colorTemp = 0;
93
+ } else {
94
+ node.h = 0
95
+ node.s = 0
96
+ node.v = 0
97
+ }
98
+ return node
99
+ }),
100
+ id: params.mode === 'add' ? maxModeObject && maxModeObject.mode > 200 ? maxModeObject.mode + 1 : 201 : state.mood.id
101
+ }
102
+ const list = params.mode === 'add' ? [currentMood,...params.moods] :
103
+ isDelete ? params.moods.filter(mood => mood.id !== currentMood.id) :
104
+ params.moods.map(mood => {
105
+ return mood.id === currentMood.id ? currentMood : mood
106
+ })
107
+ const saveRes = await saveFantasyScene(deviceId, params.moduleParams.featureId, list)
108
+ if (saveRes.success) {
109
+ if (list.length > 0) {
110
+ if (isDelete) {
111
+
112
+ } else {
113
+ await setFantasyScene(currentMood)
114
+ }
115
+ } else {
116
+ await setWorkMode(COLOUR)
117
+ }
118
+ }
119
+ navigation.navigate(ui_biz_routerKey.ui_biz_fantasy_mood)
120
+ routeParams.onSave()
121
+ }, [])
122
+
123
+ const createSelectPageData = useCallback(() => {
124
+ return Object.values(state.sceneMode).map(scene => {
125
+ return {
126
+ text: scene.title,
127
+ selected: scene.mode === state.mood.mode,
128
+ value: scene.mode,
129
+ }
130
+ })
131
+ }, [state.mood.mode, state.sceneMode])
132
+
133
+ const getButtonStatus = () => {
134
+ return (params.mode === 'edit' && isEqual(state.mood, routeParams.currentMood)) ||
135
+ !(!!state.mood.name) ||
136
+ nameRepeat ||
137
+ state.mood.name.length > 32 ||
138
+ state.mood.nodes.length < 2
139
+ }
140
+ console.log(state.mood, '< -- mood')
141
+ console.log(state.sceneMode, '< --- sceneMode')
142
+ const nameRepeat = useMemo(() => {
143
+ return !!find(params.moods, m => (m.id !== state.mood.id && m.name === state.mood.name))
144
+ }, [state.mood.name])
145
+ return (
146
+ <Page
147
+ backText={I18n.getLang('mesh_device_detail_mode')}
148
+ showBackDialog={true}
149
+ backDialogTitle={
150
+ I18n.getLang(params.mode === 'add' ?
151
+ 'string_light_pp_dialog_sm_add_headline_c' :
152
+ 'manage_user_unsaved_changes_dialog_headline')
153
+ }
154
+ backDialogContent={
155
+ I18n.getLang(params.mode === 'add' ?
156
+ 'strip_light_static_mood_add_step_2_dialog_text' :
157
+ 'strip_light_static_mood_editor_step_2_dialog_text')
158
+ }
159
+ headlineText={state.headline}
160
+ rightButtonIcon={getButtonStatus() ? res.ic_uncheck : res.ic_check}
161
+ rightButtonDisabled={getButtonStatus()}
162
+ rightButtonIconClick={async () => {
163
+ await onPost(false)
164
+ }}>
165
+ <ScrollView
166
+ style={{ flex: 1 }}
167
+ nestedScrollEnabled={true}>
168
+ <View style={styles.root}>
169
+ <TextField
170
+ style={styles.name}
171
+ value={state.mood.name}
172
+ placeholder={I18n.getLang('edit_static_mood_inputfield_topic_text')}
173
+ onChangeText={text => {
174
+ state.mood.name = text
175
+ }}
176
+ showError={state.mood.name.length > 32 || nameRepeat}
177
+ tipColor={nameRepeat ? '#f00' : undefined}
178
+ tipIcon={nameRepeat ? res.ic_text_field_input_error : undefined}
179
+ errorText={I18n.getLang(nameRepeat ? 'string_light_pp_field_sm_add_error1' : 'add_new_dynamic_mood_alert_text')} />
180
+ <Card style={styles.adjustCard}>
181
+ <Spacer height={cx(16)} />
182
+ <View style={styles.lightLine}>
183
+ <Text style={styles.light}>
184
+ {I18n.getLang('light_sources_tile_tw_lighting_headline')}
185
+ </Text>
186
+ </View>
187
+ <Spacer height={cx(18)} />
188
+ <TextFieldStyleButton
189
+ style={styles.transitionMode}
190
+ text={state.sceneMode[state.mood.mode]?.title}
191
+ placeholder={I18n.getLang('add_new_dynamic_mood_color_changing_mode_headline')}
192
+ onPress={() => {
193
+ const paramsSelect: SelectPageParams<number> = {
194
+ title: I18n.getLang('add_new_dynamic_mood_color_changing_mode_headline'),
195
+ data: createSelectPageData(),
196
+ onSelect: selectPageData => {
197
+ state.mood.mode = selectPageData.value
198
+ },
199
+ }
200
+ navigation.navigate(ui_biz_routerKey.ui_biz_select_page, paramsSelect)
201
+ }} />
202
+ <Spacer height={cx(10)} />
203
+ <LdvSlider
204
+ title={I18n.getLang('add_new_dynamic_mood_lights_field_speed_topic_text')}
205
+ value={state.mood.speed}
206
+ onValueChange={() => { }}
207
+ onSlidingComplete={value => {
208
+ state.mood.speed = value
209
+ }} />
210
+ <Spacer height={cx(16)} />
211
+ {state.sceneMode[state.mood.mode]?.turnOn && <View style={styles.transitionMode}>
212
+ <Text style={{ color: '#000', fontSize: cx(14) }}>Turn to</Text>
213
+ <Segmented
214
+ value={state.mood.direction}
215
+ options={[
216
+ {
217
+ label: 'Positive',
218
+ value: 0
219
+ },
220
+ {
221
+ label: 'Negative',
222
+ value: 1
223
+ },
224
+ ]}
225
+ onChange={(v) => state.mood.direction = Number(v)}
226
+ />
227
+ <Spacer />
228
+ </View>}
229
+ {state.sceneMode[state.mood.mode]?.paragraph && <View style={styles.transitionMode}>
230
+ <Text style={{ color: '#000', fontSize: cx(14) }}>Paragraph</Text>
231
+ <Segmented
232
+ value={state.mood.segmented}
233
+ options={[
234
+ {
235
+ label: 'Paragraph',
236
+ value: 0
237
+ },
238
+ {
239
+ label: 'Segmented',
240
+ value: 1
241
+ },
242
+ ]}
243
+ onChange={(v) => state.mood.segmented = Number(v)}
244
+ />
245
+ <Spacer />
246
+ </View>}
247
+ {state.sceneMode[state.mood.mode]?.other && <View style={styles.transitionMode}>
248
+ <Text style={{ color: '#000', fontSize: cx(14) }}>Other</Text>
249
+ <Segmented
250
+ value={state.mood.direction}
251
+ options={state.sceneMode[state.mood.mode]?.other}
252
+ onChange={(v) => state.mood.direction = Number(v)}
253
+ />
254
+ <Spacer />
255
+ </View>}
256
+ <View style={styles.nodesAdjust}>
257
+ <View style={styles.adjustButtons}>
258
+ <TouchableOpacity
259
+ onPress={() => {
260
+ state.paintBucketSelected = true
261
+ }}>
262
+ <Image
263
+ style={[styles.adjustButton, { tintColor: state.paintBucketSelected ? '#f60' : '#666' }]}
264
+ source={res.ic_paint_bucket} />
265
+ </TouchableOpacity>
266
+ <TouchableOpacity
267
+ onPress={() => {
268
+ state.paintBucketSelected = false
269
+ }}>
270
+ <Image
271
+ style={[styles.adjustButton, { tintColor: state.paintBucketSelected ? '#666' : '#f60' }]}
272
+ source={res.ic_colorize} />
273
+ </TouchableOpacity>
274
+ </View>
275
+ <FlatList
276
+ data={state.mood.nodes}
277
+ style={styles.nodeList}
278
+ renderItem={({ item, index }) => {
279
+ return (
280
+ <View style={styles.nodeItem}>
281
+ <TouchableOpacity
282
+ style={[
283
+ styles.nodeBlock,
284
+ {
285
+ backgroundColor: getNodeColor(item),
286
+ },
287
+ ]}
288
+ onPress={() => {
289
+ state.currentNode = item
290
+ }} />
291
+ <TouchableOpacity
292
+ style={styles.nodeDeleteBtn}
293
+ disabled={state.mood.nodes.length < 3}
294
+ onPress={() => {
295
+ state.mood.nodes.splice(index, 1)
296
+ state.currentNode = state.mood.nodes[state.mood.nodes.length - 1]
297
+ }}>
298
+ <Image
299
+ style={[
300
+ styles.nodeDeleteIcon,
301
+ {
302
+ tintColor: state.mood.nodes.length < 3 ? '#ccc' : '#666',
303
+ },
304
+ ]}
305
+ source={res.ic_mood_del} />
306
+ </TouchableOpacity>
307
+ </View>
308
+ )
309
+ }}
310
+ keyExtractor={(_, index) => `${index}`}
311
+ ItemSeparatorComponent={() => <Spacer height={cx(12)} />}
312
+ ListFooterComponent={() => {
313
+ if (state.mood.nodes.length >= 8) {
314
+ return (<></>)
315
+ }
316
+ return (
317
+ <View>
318
+ <Spacer height={cx(12)} />
319
+ <TouchableOpacity
320
+ style={styles.nodeAddBtn}
321
+ onPress={() => {
322
+ const node = {
323
+ ...state.currentNode,
324
+ }
325
+ state.mood.nodes.push(node)
326
+ state.currentNode = node
327
+ }}>
328
+ <Image
329
+ style={{
330
+ width: cx(18),
331
+ height: cx(18),
332
+ tintColor: '#000',
333
+ }}
334
+ source={{ uri: res.add }} />
335
+ </TouchableOpacity>
336
+ </View>
337
+ )
338
+ }} />
339
+ </View>
340
+ <Spacer />
341
+ <View style={styles.lightLine}>
342
+ <Text style={styles.light}>
343
+ {I18n.getLang('add_new_dynamic_mood_lights_field_headline2_text')}
344
+ </Text>
345
+ <View style={[styles.preview, { backgroundColor: getColorBlockColor() }]} />
346
+ </View>
347
+ <Spacer />
348
+ <LampAdjustView
349
+ isSupportColor={!moduleParams.isStripLight && moduleParams.isSupportColor}
350
+ isSupportBrightness={!moduleParams.isStripLight && moduleParams.isSupportBrightness}
351
+ isSupportTemperature={moduleParams.isSupportTemperature}
352
+ isColorMode={state.currentNode.isColorNode}
353
+ reserveSV={true}
354
+ setIsColorMode={isColorMode => {
355
+ if (state.paintBucketSelected) {
356
+ state.mood.nodes.forEach(node => {
357
+ node.isColorNode = isColorMode
358
+ })
359
+ } else {
360
+ state.currentNode.isColorNode = isColorMode
361
+ }
362
+ }}
363
+ h={state.currentNode.h}
364
+ s={state.currentNode.s}
365
+ v={state.currentNode.v}
366
+ onHSVChange={(h, s, v) => {
367
+ if (state.paintBucketSelected) {
368
+ state.mood.nodes.forEach(node => {
369
+ node.isColorNode = true
370
+ node.h = h
371
+ node.s = s
372
+ node.v = v
373
+ })
374
+ } else {
375
+ state.currentNode.h = h
376
+ state.currentNode.s = s
377
+ state.currentNode.v = v
378
+ }
379
+ }}
380
+ onHSVChangeComplete={(h, s, v) => {
381
+ if (state.paintBucketSelected) {
382
+ state.mood.nodes.forEach(node => {
383
+ node.isColorNode = true
384
+ node.h = h
385
+ node.s = s
386
+ node.v = v
387
+ })
388
+ } else {
389
+ state.currentNode.h = h
390
+ state.currentNode.s = s
391
+ state.currentNode.v = v
392
+ }
393
+ }}
394
+ colorTemp={state.currentNode.colorTemp}
395
+ brightness={state.currentNode.brightness}
396
+ onCCTChange={cct => {
397
+ if (state.paintBucketSelected) {
398
+ state.mood.nodes.forEach(node => {
399
+ node.isColorNode = false
400
+ node.colorTemp = cct
401
+ })
402
+ } else {
403
+ state.currentNode.colorTemp = cct
404
+ }
405
+ }}
406
+ onCCTChangeComplete={cct => {
407
+ if (state.paintBucketSelected) {
408
+ state.mood.nodes.forEach(node => {
409
+ node.isColorNode = false
410
+ node.colorTemp = cct
411
+ })
412
+ } else {
413
+ state.currentNode.colorTemp = cct
414
+ }
415
+ }}
416
+ onBrightnessChange={brightness => {
417
+ if (state.paintBucketSelected) {
418
+ state.mood.nodes.forEach(node => {
419
+ node.isColorNode = false
420
+ node.brightness = brightness
421
+ })
422
+ } else {
423
+ state.currentNode.brightness = brightness
424
+ }
425
+ }}
426
+ onBrightnessChangeComplete={brightness => {
427
+ if (state.paintBucketSelected) {
428
+ state.mood.nodes.forEach(node => {
429
+ node.isColorNode = false
430
+ node.brightness = brightness
431
+ })
432
+ } else {
433
+ state.currentNode.brightness = brightness
434
+ }
435
+ }} />
436
+ </Card>
437
+ <Spacer />
438
+ {params.mode === 'edit' && canDelete &&
439
+ <View style={{ marginTop: cx(20), marginHorizontal: cx(24) }}>
440
+ <TextButton
441
+ style={styles.deleteBtn}
442
+ textStyle={styles.deleteBtnText}
443
+ text={I18n.getLang('edit_static_mood_button_delete_text')}
444
+ onPress={() => {
445
+ showDeleteMoodDialog(async (_, { close }) => {
446
+ close()
447
+ await onPost(true)
448
+ })
449
+ }} />
450
+ </View>}
451
+ <Spacer />
452
+ </View>
453
+ </ScrollView>
454
+ </Page>
455
+ )
456
+ }
457
+ const styles = StyleSheet.create({
458
+ root: {
459
+ flex: 1,
460
+ flexDirection: 'column',
461
+ },
462
+ name: {
463
+ marginHorizontal: cx(24),
464
+ },
465
+ adjustCard: {
466
+ marginVertical: cx(12),
467
+ marginHorizontal: cx(24),
468
+ },
469
+ fanAdjustCard: {
470
+ marginHorizontal: cx(24),
471
+ },
472
+ lightLine: {
473
+ flexDirection: 'row',
474
+ marginHorizontal: cx(16),
475
+ },
476
+ light: {
477
+ color: '#000',
478
+ fontSize: cx(18),
479
+ fontFamily: 'helvetica_neue_lt_std_bd',
480
+ },
481
+ transitionMode: {
482
+ marginHorizontal: cx(16),
483
+ },
484
+ preview: {
485
+ width: cx(20),
486
+ height: cx(20),
487
+ marginStart: cx(12),
488
+ borderRadius: cx(4),
489
+ },
490
+ nodesAdjust: {
491
+ flexDirection: 'row',
492
+ alignItems: 'center',
493
+ },
494
+ adjustButtons: {
495
+ width: cx(44),
496
+ marginStart: cx(16),
497
+ },
498
+ adjustButton: {
499
+ width: cx(44),
500
+ height: cx(44),
501
+ },
502
+ nodeList: {
503
+ flex: 1,
504
+ marginHorizontal: cx(16),
505
+ },
506
+ nodeItem: {
507
+ flexDirection: 'row',
508
+ alignItems: 'center',
509
+ },
510
+ nodeBlock: {
511
+ flex: 1,
512
+ height: cx(40),
513
+ borderRadius: cx(8),
514
+ },
515
+ nodeDeleteBtn: {
516
+ width: cx(24),
517
+ height: cx(30),
518
+ justifyContent: 'center',
519
+ alignItems: 'center',
520
+ },
521
+ nodeDeleteIcon: {
522
+ width: cx(16),
523
+ height: cx(16),
524
+ },
525
+ nodeAddBtn: {
526
+ height: cx(40),
527
+ justifyContent: 'center',
528
+ alignItems: 'center',
529
+ marginEnd: cx(26),
530
+ borderRadius: cx(8),
531
+ borderWidth: cx(1),
532
+ borderStyle: 'dashed',
533
+ borderColor: '#666',
534
+ backgroundColor: '#f6f6f6',
535
+ },
536
+ deleteBtn: {
537
+ width: '100%',
538
+ height: cx(50),
539
+ backgroundColor: '#666',
540
+ borderRadius: cx(8),
541
+ },
542
+ deleteBtnText: {
543
+ color: '#fff',
544
+ fontSize: cx(16),
545
+ fontFamily: 'helvetica_neue_lt_std_bd',
546
+ },
547
+ })
548
+ export default FantasyMoodEditPage
@@ -0,0 +1,104 @@
1
+ import React, { useEffect, memo } from 'react'
2
+ import { StyleSheet, Text, View, ViewProps, ViewStyle } from 'react-native'
3
+ import { StripSceneUIState } from '../scene/SceneInfo'
4
+ import { SwitchButton, Utils } from 'tuya-panel-kit'
5
+ import { useReactive } from 'ahooks'
6
+ import { hsv2Hex } from '@ledvance/base/src/utils'
7
+ import {cctToColor} from '@ledvance/base/src/utils/cctUtils'
8
+ import {mapFloatToRange} from '@ledvance/base/src/utils'
9
+ import Card from '@ledvance/base/src/components/Card'
10
+ import Spacer from '@ledvance/base/src/components/Spacer'
11
+ import MoodColorsLine from '@ledvance/base/src/components/MoodColorsLine'
12
+
13
+ const cx = Utils.RatioUtils.convertX
14
+
15
+ interface FantasyMoodItemProps extends ViewProps {
16
+ enable: boolean
17
+ mood: StripSceneUIState
18
+ style?: ViewStyle
19
+ onPress?: () => void
20
+ onSwitch: (enable: boolean) => void
21
+ }
22
+
23
+ const FantasyMoodItem = (props: FantasyMoodItemProps) => {
24
+ const { mood } = props
25
+ const state = useReactive<{ colors: string[] }>({
26
+ colors: [],
27
+ })
28
+
29
+ useEffect(() => {
30
+ state.colors = props.mood.nodes.map(node => {
31
+ if (node.isColorNode) {
32
+ return hsv2Hex(node.h, Math.round(node.s), Math.round(mapFloatToRange(node.v / 100, 50, 100)))
33
+ }
34
+ return cctToColor(node.colorTemp.toFixed())
35
+ })
36
+ }, [props.mood.nodes])
37
+
38
+ return (
39
+ <Card
40
+ style={[styles.card, props.style]}
41
+ onPress={props.onPress}>
42
+ <View>
43
+ <Spacer height={cx(16)} />
44
+ <View style={styles.headline}>
45
+ <Text style={styles.headText}>{mood.name}</Text>
46
+ <SwitchButton
47
+ thumbStyle={{ elevation: 0 }}
48
+ value={props.enable}
49
+ onValueChange={props.onSwitch} />
50
+ </View>
51
+ <Spacer />
52
+ <View style={styles.gradientItem}>
53
+ <MoodColorsLine
54
+ type={'separate'}
55
+ colors={state.colors} />
56
+ </View>
57
+ <Spacer height={cx(16)} />
58
+ </View>
59
+ </Card>
60
+ )
61
+ }
62
+
63
+ export default memo(FantasyMoodItem)
64
+
65
+ const styles = StyleSheet.create({
66
+ card: {
67
+ marginHorizontal: cx(24),
68
+ },
69
+ headline: {
70
+ flexDirection: 'row',
71
+ marginHorizontal: cx(16),
72
+ },
73
+ headText: {
74
+ flex: 1,
75
+ color: '#000',
76
+ fontSize: cx(16),
77
+ fontFamily: 'helvetica_neue_lt_std_bd',
78
+ lineHeight: cx(20),
79
+ },
80
+ gradientItem: {
81
+ alignItems: 'center',
82
+ },
83
+ gradient: {
84
+ borderRadius: cx(8),
85
+ },
86
+ moodTypeItem: {
87
+ flexDirection: 'row',
88
+ },
89
+ moodTypeLabel: {
90
+ marginStart: cx(16),
91
+ paddingHorizontal: cx(12.5),
92
+ backgroundColor: '#E6E7E8',
93
+ borderRadius: cx(8),
94
+ },
95
+ moodTypeLabelText: {
96
+ height: cx(16),
97
+ color: '#000000DD',
98
+ fontSize: cx(10),
99
+ textAlignVertical: 'center',
100
+ fontFamily: 'helvetica_neue_lt_std_roman',
101
+ lineHeight: cx(16),
102
+ },
103
+ })
104
+
@@ -1,20 +1,26 @@
1
1
  import {NativeResult, Result} from '@ledvance/base/src/models/modules/Result'
2
2
  import {
3
3
  getDefSceneList,
4
+ getDefFantasyScene,
4
5
  RemoteSceneInfo,
5
6
  SceneInfo,
6
7
  SceneNodeInfo,
7
8
  SceneNodeTransitionMode,
8
9
  SceneUIState,
10
+ StripSceneUIState,
11
+ StripSceneInfo,
9
12
  } from './SceneInfo'
10
- import {getFeature, putFeature} from '@ledvance/base/src/api/native'
13
+ import {getFeature, putFeature, NativeApi} from '@ledvance/base/src/api/native'
11
14
  import {setSceneDp} from '../../hooks/DeviceDpStateHooks'
12
15
  import {hex2Int, spliceByStep} from '@ledvance/base/src/utils/common'
13
- import {asyncSetDps, useDp} from '@ledvance/base/src/models/modules/NativePropsSlice'
16
+ import {asyncSetDps, useDp, useDps} from '@ledvance/base/src/models/modules/NativePropsSlice'
14
17
  import {Dispatch, useState} from 'react'
15
18
  import {useUpdateEffect} from 'ahooks'
16
19
  import {useDispatch} from 'react-redux'
17
20
  import res from '@ledvance/base/src/res'
21
+ import { SCENE } from '../../hooks/DeviceDpStateHooks'
22
+ import { Utils } from '@tuya/tuya-panel-lamp-sdk'
23
+ const { nToHS, toFixed, sToN, toN, formatterTransform } = Utils
18
24
 
19
25
  type SetRemoteSceneListType = (
20
26
  deviceId: string,
@@ -266,3 +272,150 @@ export async function saveScene(
266
272
  })
267
273
  return await setRemoteSceneList(deviceId, newScenes)
268
274
  }
275
+
276
+
277
+ export function stripDp2Obj(dp: string): StripSceneInfo {
278
+ const version = hex2Int(dp.slice(0, 2))
279
+ const id = hex2Int(dp.slice(2, 4))
280
+ const mode = hex2Int(dp.slice(4, 6))
281
+ const intervalTime = hex2Int(dp.slice(6, 8))
282
+ const changeTime = hex2Int(dp.slice(8, 10))
283
+ const speed = intervalTime || changeTime
284
+ const optionA = toN(dp.slice(10, 12))
285
+ const optionAStr = toFixed(optionA.toString(2), 8);
286
+ const gn = formatterTransform(optionAStr);
287
+ const st = (n?: number) => gn.next(n);
288
+ st();
289
+ const segmented = sToN(st(1).value, 2)
290
+ const loop = sToN(st(1).value, 2)
291
+ const excessive = sToN(st(1).value, 2)
292
+ const direction = sToN(st(1).value, 2)
293
+ // 这两个目前灯具用不上
294
+ const optionB = toN(dp.slice(12, 14))
295
+ const optionC = toN(dp.slice(14, 16))
296
+ const nodes = spliceByStep(dp.slice(16, dp.length), 16).map(nodeHex => {
297
+ const v = hex2Int(nodeHex.slice(0, 2))
298
+ const h = hex2Int(nodeHex.slice(2, 6))
299
+ const s = hex2Int(nodeHex.slice(6, 8))
300
+ const brightness = hex2Int(nodeHex.slice(8, 12)) / 10
301
+ const colorTemp = hex2Int(nodeHex.slice(12, 16)) / 10
302
+ const isColorNode = v > 0 && brightness === 0
303
+ return { h, s, v, brightness, colorTemp, isColorNode }
304
+ })
305
+ return {
306
+ version,
307
+ id,
308
+ mode,
309
+ speed,
310
+ direction,
311
+ segmented,
312
+ loop,
313
+ excessive,
314
+ optionB,
315
+ optionC,
316
+ nodes
317
+ }
318
+ }
319
+
320
+ export function stripObj2Dp(scene: StripSceneInfo) {
321
+ const {
322
+ optionB = 0,
323
+ optionC = 0,
324
+ // mixedIds = [],
325
+ segmented = 0,
326
+ loop = 0,
327
+ excessive = 0,
328
+ direction = 0,
329
+ nodes
330
+ } = scene
331
+ const expand = 0
332
+ const versionHex = nToHS(scene.version)
333
+ const idHex = nToHS(scene.id)
334
+ const modeHex = nToHS(scene.mode)
335
+ const intervalTimeHex = nToHS(scene.speed)
336
+ const changeTimeHex = nToHS(scene.speed)
337
+ const optionAhex = nToHS(
338
+ parseInt(
339
+ `${segmented}${loop}${excessive}${direction}${toFixed(
340
+ expand.toString(2),
341
+ 2
342
+ )}${0}${0}`,
343
+ 2
344
+ )
345
+ );
346
+ const optionBhex = nToHS(optionB)
347
+ const optionChex = nToHS(optionC)
348
+ const nodeHex = nodes.map(node => {
349
+ return `${nToHS(node.v)}${nToHS(node.h, 4)}${nToHS(node.s)}${nToHS(node.brightness * 10, 4)}${nToHS(node.colorTemp * 10, 4)}`
350
+ }).join('')
351
+ return versionHex + idHex + modeHex + intervalTimeHex + changeTimeHex + optionAhex + optionBhex + optionChex + nodeHex
352
+ }
353
+
354
+ export function useFantasyScene(sceneDp: string, workModeDp: string): [number, (scene: StripSceneInfo) => Promise<Result<any>>] {
355
+ const [dps, setDps]: [any, (v: any) => Promise<Result<any>>] = useDps()
356
+ const dp = dps[sceneDp]
357
+ const [sceneState, setSceneState] = useState<StripSceneInfo>(stripDp2Obj(dp))
358
+
359
+ useUpdateEffect(() => {
360
+ setSceneState(stripDp2Obj(dp))
361
+ }, [dp])
362
+
363
+ const setFantasyScene = (scene: StripSceneInfo) => {
364
+ const sceneHex = stripObj2Dp(scene)
365
+ return setDps({
366
+ [sceneDp]: sceneHex,
367
+ [workModeDp]: SCENE
368
+ })
369
+ }
370
+ return [sceneState.id, setFantasyScene]
371
+ }
372
+
373
+ type LampType = {
374
+ isStringLight?: boolean
375
+ isStripLight?: boolean
376
+ }
377
+ export async function getRemoteFantasyScene(featureId: string, devId: string, lampType: LampType) {
378
+ const res = await NativeApi.getJson(devId, featureId)
379
+ if (res.success && res.data) {
380
+ return {
381
+ success: true,
382
+ data: JSON.parse(res.data)?.map(item => remoteFantasySceneInfo2SceneUIState(item)),
383
+ }
384
+ } else {
385
+ if (res.msg?.includes('资源未找到')) {
386
+ const defaultScene = getDefFantasyScene(lampType)
387
+ const res = await NativeApi.putJson(devId, featureId, JSON.stringify(defaultScene))
388
+ if (res.success) {
389
+ return {
390
+ success: true,
391
+ data: defaultScene.map(item => remoteFantasySceneInfo2SceneUIState(item))
392
+ }
393
+ }
394
+ return { success: false }
395
+ }
396
+ return { success: false }
397
+ }
398
+
399
+ }
400
+
401
+ function remoteFantasySceneInfo2SceneUIState(remoteScene: RemoteSceneInfo): StripSceneUIState {
402
+ const stripSceneInfo = stripDp2Obj(remoteScene.i)
403
+ return {
404
+ ...stripSceneInfo,
405
+ name: remoteScene.n,
406
+ image: ''
407
+ }
408
+ }
409
+
410
+ export function saveFantasyScene(devId: string, featureId: string, scenes: StripSceneUIState[]) {
411
+ const newScenes: RemoteSceneInfo[] = scenes.map(s => {
412
+ return {
413
+ n: s.name,
414
+ i: stripObj2Dp(s),
415
+ s: '',
416
+ t: 0,
417
+ e: false,
418
+ }
419
+ })
420
+ return NativeApi.putJson(devId, featureId, JSON.stringify(newScenes))
421
+ }
@@ -32,12 +32,94 @@ export interface SceneNodeInfo {
32
32
  isColorNode: boolean
33
33
  }
34
34
 
35
+ export interface StripSceneInfo {
36
+ // 版本号
37
+ version: number
38
+ // 场景号
39
+ id: number
40
+ // 变化方式
41
+ mode: number
42
+ // 速度
43
+ speed: number
44
+ // 段落 0 全段, 1 分段
45
+ segmented: number
46
+ // 循环 0 不循环, 1 循环
47
+ loop: number
48
+ // 过渡 0 不过渡, 1 过渡
49
+ excessive: number
50
+ // 方向 0 顺时针方向, 1 逆时针方向
51
+ direction: number
52
+ // 设置 目前灯用不上
53
+ optionB: number
54
+ optionC: number
55
+ nodes: StripNodeInfo[]
56
+ }
57
+
58
+ export interface StripNodeInfo {
59
+ // 0~360
60
+ h: number
61
+ // 饱和度 0~100
62
+ s: number
63
+ // 明度 1~100
64
+ v: number
65
+ // 灯泡亮度 10~1000 4hex
66
+ brightness: number
67
+ // 色温值 0~1000 4hex
68
+ colorTemp: number
69
+ // 节点类型
70
+ isColorNode: boolean
71
+ }
72
+
35
73
  export enum SceneNodeTransitionMode {
36
74
  Static,
37
75
  Jump,
38
76
  Gradient
39
77
  }
40
78
 
79
+
80
+ export interface StripLightSceneMode {
81
+ [key: string]: {
82
+ title: string;
83
+ mode: number;
84
+ turnOn?: boolean;
85
+ paragraph?: boolean;
86
+ other?: {
87
+ label: string
88
+ value: number
89
+ }[];
90
+ };
91
+ }
92
+
93
+ export const stringLightSceneMode: StripLightSceneMode = {
94
+ '13': { title: 'Flow', mode: 13, turnOn: true }, // 流水
95
+ '2': { title: 'Rainbow', mode: 2, turnOn: true }, // 彩虹
96
+ '14': { title: 'Chase', mode: 14, turnOn: true }, // 追光
97
+ '15': { title: 'Dazzle', mode: 15 }, // 炫彩
98
+ '16': { title: I18n.getLang('other_lights_modes_gradient_text'), mode: 16 }, // 渐变
99
+ '10': { title: I18n.getLang('other_lights_modes_jump_text'), mode: 10 }, // 跳变
100
+ '11': { title: 'Breathing', mode: 11 }, // 呼吸
101
+ '12': { title: 'Blink', mode: 12 } // 闪烁
102
+ }
103
+
104
+ export const stripLightSceneMode: StripLightSceneMode = {
105
+ '1': { title: 'Jump', mode: 1, paragraph: true }, // 跳变
106
+ '2': { title: 'Breath', mode: 2, paragraph: true }, // 呼吸1
107
+ '3': { title: 'Breathe', mode: 3, paragraph: true }, // 呼吸2
108
+ '4': { title: 'Blink', mode: 4, paragraph: true }, // 闪烁
109
+ '10': { title: 'Flow', mode: 10, turnOn: true }, // 流水
110
+ '11': { title: 'Rainbow', mode: 11, turnOn: true }, // 彩虹
111
+ '5': { title: 'Meteor', mode: 5, turnOn: true, other: [{label: 'Meteor',value: 0}, {label: 'Meteor shower',value: 1},{label: 'Magic meteor',value: 2}] }, // 流星
112
+ '6': { title: 'PileUp', mode: 6, turnOn: true, paragraph: true }, // 堆积
113
+ '7': { title: 'Falling', mode: 7, turnOn: true, paragraph: true }, // 飘落
114
+ '8': { title: 'Follow', mode: 8, turnOn: true }, // 追光
115
+ '9': { title: 'Flutter', mode: 9, turnOn: true }, // 飘动
116
+ '12': { title: 'flash', mode: 12, paragraph: true }, // 闪现
117
+ '13': { title: 'Rebound', mode: 13, other: [{label: 'Rebound',value: 0}, {label: 'Magic rebound',value: 1}]}, // 反弹
118
+ '14': { title: 'Shuttle', mode: 14, }, // 穿梭
119
+ '15': { title: 'Random', mode: 15 }, // 乱闪
120
+ '16': { title: 'Switch', mode: 16, other: [{label: 'Meanwhile',value: 0}, {label: 'Staggered',value: 1}] } // 开合
121
+ }
122
+
41
123
  /**
42
124
  * 萤石云端 Scene 物模型
43
125
  */
@@ -70,6 +152,17 @@ export interface SceneUIState extends SceneInfo {
70
152
  image: string
71
153
  }
72
154
 
155
+ export interface StripScenePageUIState {
156
+ currentScene: StripSceneUIState | undefined
157
+ scenes: StripSceneUIState[]
158
+ flag: symbol
159
+ }
160
+
161
+ export interface StripSceneUIState extends StripSceneInfo {
162
+ name: string
163
+ image: string
164
+ }
165
+
73
166
  export function getDefSceneList(
74
167
  isRGBWLamp: boolean = false,
75
168
  isRGBLamp: boolean = false,
@@ -99,6 +192,16 @@ export function getDefSceneList(
99
192
  return []
100
193
  }
101
194
 
195
+ export function getDefFantasyScene({
196
+ isStringLight = false,
197
+ isStripLight = false
198
+ }) {
199
+ if (isStringLight || isStripLight) {
200
+ return getStringLightSceneList()
201
+ }
202
+ return getStringLightSceneList()
203
+ }
204
+
102
205
  function getRGBWDefSceneList(): RemoteSceneInfo[] {
103
206
  return [
104
207
  {
@@ -339,6 +442,67 @@ function getDIMDefSceneList(): RemoteSceneInfo[] {
339
442
  ]
340
443
  }
341
444
 
445
+ function getStringLightSceneList(): RemoteSceneInfo[] {
446
+ return [
447
+ {
448
+ n: 'Flow',
449
+ i: '010d0d3232000000640000640000000064003c64000000006400f06400000000',
450
+ s: '',
451
+ t: 0,
452
+ e: false,
453
+ },
454
+ {
455
+ n: 'Rainbow',
456
+ i: '0102023232000000640000640000000064003c64000000006400f06400000000',
457
+ s: '',
458
+ t: 0,
459
+ e: false,
460
+ },
461
+ {
462
+ n: 'Chase',
463
+ i: '010e0e3232000000640000640000000064003c640000000064007864000000006400b464000000006400f0640000000064012c6400000000',
464
+ s: '',
465
+ t: 0,
466
+ e: false,
467
+ },
468
+ {
469
+ n: 'Dazzle',
470
+ i: '010f0f3232000000640000640000000064003c640000000064007864000000006400b464000000006400f0640000000064012c6400000000',
471
+ s: '',
472
+ t: 0,
473
+ e: false
474
+ },
475
+ {
476
+ n: 'Gradient',
477
+ i: '01101032320000006400f0640000000064012c640000000064003c6400000000',
478
+ s: '',
479
+ t: 0,
480
+ e: false,
481
+ },
482
+ {
483
+ n: 'Jump',
484
+ i: '010a0a32320000006400f0640000000064012c640000000064003c6400000000',
485
+ s: '',
486
+ t: 0,
487
+ e: false,
488
+ },
489
+ {
490
+ n: 'Breathing',
491
+ i: '010b0b32320000006400f0640000000064012c640000000064003c6400000000',
492
+ s: '',
493
+ t: 0,
494
+ e: false,
495
+ },
496
+ {
497
+ n: 'Blink',
498
+ i: '010c0c32320000006400f0640000000064012c640000000064003c6400000000',
499
+ s: '',
500
+ t: 0,
501
+ e: false,
502
+ },
503
+ ]
504
+ }
505
+
342
506
  export const MAXSCENE = 8
343
507
 
344
508
  export const AddScene = {
@@ -5,6 +5,8 @@ import DynamicMoodEditorPage from '../modules/mood/DynamicMoodEditorPage'
5
5
  import StaticMoodEditorPage from '../modules/mood/StaticMoodEditorPage'
6
6
  import AddMoodPage from '../modules/mood/AddMoodPage'
7
7
  import MoodPage from '../modules/mood/MoodPage'
8
+ import FantasyMoodPage from '../modules/mood/FantasyMood'
9
+ import FantasyMoodEditPage from '../modules/mood/FantasyMoodEditPage'
8
10
  import TimerPage from '../modules/timer/TimerPage'
9
11
  import SleepWakeUpPage from 'modules/sleepWakeup/SleepWakeUpPage'
10
12
  import SleepWakeUpDetailPage from 'modules/sleepWakeup/SleepWakeUpDetailPage'
@@ -21,6 +23,8 @@ import RandomTimeDetailPage from '../modules/randomTime/RandomTimeDetailPage'
21
23
  export const ui_biz_routerKey = {
22
24
  'ui_biz_time_schedule': 'ui_biz_time_schedule',
23
25
  'ui_biz_time_schedule_edit': 'ui_biz_time_schedule_edit',
26
+ 'ui_biz_fantasy_mood': 'ui_biz_fantasy_mood',
27
+ 'ui_biz_fantasy_mood_edit': 'ui_biz_fantasy_mood_edit',
24
28
  'ui_biz_mood': 'ui_biz_mood',
25
29
  'ui_biz_mood_add': 'ui-biz_mood_add',
26
30
  'ui_biz_static_mood_edit': 'ui_biz_static_mood_edit',
@@ -129,6 +133,34 @@ export const MoodPageRouters: NavigationRoute[] = [
129
133
  },
130
134
  ]
131
135
 
136
+ export const FantasyMoodRouters: NavigationRoute[] = [
137
+ {
138
+ name: ui_biz_routerKey.ui_biz_fantasy_mood,
139
+ component: FantasyMoodPage,
140
+ options: {
141
+ hideTopbar: true,
142
+ showOfflineView: false,
143
+ },
144
+ },
145
+ {
146
+ name: ui_biz_routerKey.ui_biz_fantasy_mood_edit,
147
+ component: FantasyMoodEditPage,
148
+ options: {
149
+ hideTopbar: true,
150
+ showOfflineView: false,
151
+ },
152
+ },
153
+ {
154
+ name: ui_biz_routerKey.ui_biz_select_page,
155
+ component: SelectPage,
156
+ options: {
157
+ gesture: true,
158
+ hideTopbar: true,
159
+ ...TransitionPresets.ModalPresentationIOS,
160
+ },
161
+ },
162
+ ]
163
+
132
164
  export const TimerPageRouters: NavigationRoute[] = [
133
165
  {
134
166
  name: ui_biz_routerKey.ui_biz_timer,