@ledvance/group-ui-biz-bundle 1.0.45 → 1.0.47

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 (36) hide show
  1. package/package.json +1 -1
  2. package/src/modules/biorhythm/BiorhythmActions.ts +5 -13
  3. package/src/modules/biorhythm/BiorhythmBean.ts +6 -6
  4. package/src/modules/biorhythm/BiorhythmPage.tsx +14 -38
  5. package/src/modules/biorhythm/Router.ts +34 -0
  6. package/src/modules/fixedTimeForPlug/Router.ts +25 -0
  7. package/src/modules/fixedTimingForLight/Router.ts +25 -0
  8. package/src/modules/flags/Router.ts +25 -0
  9. package/src/modules/mood_new/AddMoodPage.tsx +197 -0
  10. package/src/modules/mood_new/DynamicMoodEditorPage.tsx +654 -0
  11. package/src/modules/mood_new/Interface.ts +219 -0
  12. package/src/modules/mood_new/MixDynamicMoodEditor.tsx +788 -0
  13. package/src/modules/mood_new/MoodActions.ts +227 -0
  14. package/src/modules/mood_new/MoodInfo.ts +2151 -0
  15. package/src/modules/mood_new/MoodItem.tsx +148 -0
  16. package/src/modules/mood_new/MoodPage.tsx +374 -0
  17. package/src/modules/mood_new/MoodParse.ts +442 -0
  18. package/src/modules/mood_new/RecommendMoodItem.tsx +69 -0
  19. package/src/modules/mood_new/Router.ts +43 -0
  20. package/src/modules/mood_new/StaticMoodEditorPage.tsx +293 -0
  21. package/src/modules/music/Router.ts +16 -0
  22. package/src/modules/randomTimeForPlug/Router.ts +25 -0
  23. package/src/modules/randomTimingForLight/Router.ts +25 -0
  24. package/src/modules/remoteSwitch/Router.ts +16 -0
  25. package/src/modules/select/Router.ts +16 -0
  26. package/src/modules/switchGradient/Router.ts +16 -0
  27. package/src/modules/timeSchedule/Interface.ts +150 -0
  28. package/src/modules/timeSchedule/Router.ts +25 -0
  29. package/src/modules/timeSchedule/TimeScheduleActions.ts +140 -0
  30. package/src/modules/timeSchedule/TimeScheduleDetailPage.tsx +625 -0
  31. package/src/modules/timeSchedule/TimeSchedulePage.tsx +220 -0
  32. package/src/modules/timeSchedule/components/ManuaSettings.tsx +376 -0
  33. package/src/modules/timeSchedule/components/ScheduleCard.tsx +109 -0
  34. package/src/modules/timeSchedule/components/Summary.tsx +124 -0
  35. package/src/modules/timer/Router.ts +16 -0
  36. package/src/navigation/Routers.ts +1 -0
@@ -0,0 +1,654 @@
1
+ import React, { useCallback, useEffect, useMemo } from 'react';
2
+ import {
3
+ FlatList,
4
+ Image,
5
+ ScrollView,
6
+ StyleSheet,
7
+ Text,
8
+ TouchableOpacity,
9
+ View,
10
+ } from 'react-native';
11
+ import { Utils } from 'tuya-panel-kit';
12
+ import { useReactive } from 'ahooks';
13
+ import { cloneDeep, find, isEqual } from 'lodash';
14
+ import Page from '@ledvance/base/src/components/Page';
15
+ import Strings from '@ledvance/base/src/i18n';
16
+ import { StaticMoodEditorPageParams } from './StaticMoodEditorPage';
17
+ import { useNavigation } from '@react-navigation/native';
18
+ import { hsv2Hex, mapFloatToRange } from '@ledvance/base/src/utils';
19
+ import { cctToColor } from '@ledvance/base/src/utils/cctUtils';
20
+ import res from '@ledvance/base/src/res';
21
+ import TextField from '@ledvance/base/src/components/TextField';
22
+ import Card from '@ledvance/base/src/components/Card';
23
+ import Spacer from '@ledvance/base/src/components/Spacer';
24
+ import LampAdjustView from '@ledvance/base/src/components/LampAdjustView';
25
+ import LdvSlider from '@ledvance/base/src/components/ldvSlider';
26
+ import { useFanMaxSpeed } from '@ledvance/base/src/models/modules/NativePropsSlice';
27
+ import TextButton from '@ledvance/base/src/components/TextButton';
28
+ import {
29
+ MoodNodeTransitionMode,
30
+ stripLightMoodMode,
31
+ stringLightMoodMode,
32
+ lightMoodMode,
33
+ StripLightMoodMode,
34
+ MoodUIInfo,
35
+ } from './Interface';
36
+ import TextFieldStyleButton from '@ledvance/base/src/components/TextFieldStyleButton';
37
+ import FanAdjustView from '@ledvance/base/src/components/FanAdjustView';
38
+ import { ui_biz_routerKey } from '../../navigation/Routers'
39
+ import { SelectPageParams } from '../select/SelectPage';
40
+ import I18n from '@ledvance/base/src/i18n';
41
+ import Segmented from '@ledvance/base/src/components/Segmented';
42
+ import { MoodNodeInfo } from './Interface';
43
+ import { showDialog } from '@ledvance/base/src/utils/common';
44
+ import { useParams } from '@ledvance/base/src/hooks/Hooks';
45
+
46
+ const cx = Utils.RatioUtils.convertX;
47
+ interface DynamicMoodEditorPageState {
48
+ headline: string;
49
+ mood: MoodUIInfo;
50
+ mainNode: MoodNodeInfo;
51
+ mainBucketSelected: boolean;
52
+ sceneMode: StripLightMoodMode;
53
+ loading: boolean;
54
+ }
55
+ const DynamicMoodEditorPage = () => {
56
+ const navigation = useNavigation();
57
+ const routeParams = useParams<StaticMoodEditorPageParams>()
58
+ const params = cloneDeep(routeParams);
59
+ const moduleParams = params.moduleParams;
60
+ const state = useReactive<DynamicMoodEditorPageState>({
61
+ headline: '',
62
+ mood: params.currentMood,
63
+ mainNode: params.currentMood.mainLamp.nodes[params.currentMood.mainLamp.nodes.length - 1],
64
+ mainBucketSelected: false,
65
+ loading: false,
66
+ sceneMode: moduleParams.isStringLight
67
+ ? stringLightMoodMode
68
+ : moduleParams.isStripLight
69
+ ? stripLightMoodMode
70
+ : lightMoodMode,
71
+ });
72
+
73
+ useEffect(() => {
74
+ state.headline = Strings.getLang(
75
+ params.mode === 'add'
76
+ ? 'add_new_dynamic_mood_headline_text'
77
+ : 'edit_static_mood_headline_text'
78
+ );
79
+ }, [params.mode]);
80
+
81
+ const getColorBlockColor = useCallback((node: MoodNodeInfo) => {
82
+ const s = Math.round(mapFloatToRange(node.s / 100, 30, 100));
83
+ if (node.isColorNode) {
84
+ return hsv2Hex(node.h, s, 100);
85
+ } else {
86
+ return cctToColor(node.colorTemp.toFixed());
87
+ }
88
+ }, []);
89
+
90
+ const getNodeColor = useCallback((node: MoodNodeInfo) => {
91
+ if (node.isColorNode) {
92
+ const s = Math.round(mapFloatToRange(node.s / 100, 30, 100));
93
+ return hsv2Hex(node.h, s, 100);
94
+ }
95
+ return cctToColor(node.colorTemp.toFixed());
96
+ }, []);
97
+
98
+ const getButtonStatus = () => {
99
+ return (
100
+ (params.mode === 'edit' && isEqual(state.mood, routeParams.currentMood)) ||
101
+ !!!state.mood.name ||
102
+ nameRepeat ||
103
+ state.mood.name.length > 32
104
+ );
105
+ };
106
+
107
+ const createSelectModeData = useCallback(
108
+ (mode: number, moodMode?: StripLightMoodMode) => {
109
+ return Object.values(moodMode ? moodMode : state.sceneMode).map(scene => {
110
+ return {
111
+ text: scene.title,
112
+ selected: scene.mode === mode,
113
+ value: scene.mode,
114
+ };
115
+ });
116
+ },
117
+ [state.sceneMode]
118
+ );
119
+
120
+ const createSelectOtherData = useCallback((otherData, expand) => {
121
+ return otherData.map(other => {
122
+ return {
123
+ text: other.label,
124
+ selected: other.value === expand,
125
+ value: other.value,
126
+ };
127
+ });
128
+ }, []);
129
+
130
+ const getSelectOther = useCallback((otherData, expand) => {
131
+ const currentOther = otherData.find(other => other.value === expand);
132
+ return currentOther.label;
133
+ }, []);
134
+
135
+ const nameRepeat = useMemo(() => {
136
+ return !!find(params.moods, m => m.id !== state.mood.id && m.name === state.mood.name);
137
+ }, [state.mood.name]);
138
+
139
+
140
+ return (
141
+ <Page
142
+ backText={Strings.getLang('mesh_device_detail_mode')}
143
+ showBackDialog={true}
144
+ backDialogTitle={Strings.getLang(
145
+ params.mode === 'add'
146
+ ? 'string_light_pp_dialog_sm_add_headline_c'
147
+ : 'manage_user_unsaved_changes_dialog_headline'
148
+ )}
149
+ backDialogContent={Strings.getLang(
150
+ params.mode === 'add'
151
+ ? 'strip_light_static_mood_add_step_2_dialog_text'
152
+ : 'strip_light_static_mood_editor_step_2_dialog_text'
153
+ )}
154
+ headlineText={state.headline}
155
+ rightButtonIcon={getButtonStatus() ? res.ic_uncheck : res.ic_check}
156
+ rightButtonDisabled={getButtonStatus()}
157
+ rightButtonIconClick={async () => {
158
+ if (state.loading) return;
159
+ state.loading = true;
160
+ const res = await params.modDeleteMood(params.mode, cloneDeep(state.mood));
161
+ if (res.success) {
162
+ navigation.navigate(ui_biz_routerKey.group_ui_biz_mood);
163
+ }
164
+ state.loading = false;
165
+ }}
166
+ loading={state.loading}
167
+ >
168
+ <ScrollView style={{ flex: 1 }} nestedScrollEnabled={true}>
169
+ <View style={styles.root}>
170
+ <TextField
171
+ style={styles.name}
172
+ value={state.mood.name}
173
+ placeholder={Strings.getLang('edit_static_mood_inputfield_topic_text')}
174
+ onChangeText={text => {
175
+ state.mood.name = text;
176
+ }}
177
+ maxLength={33}
178
+ showError={state.mood.name.length > 32 || nameRepeat}
179
+ tipColor={nameRepeat ? '#f00' : undefined}
180
+ tipIcon={nameRepeat ? res.ic_text_field_input_error : undefined}
181
+ errorText={Strings.getLang(
182
+ nameRepeat ? 'string_light_pp_field_sm_add_error1' : 'add_new_dynamic_mood_alert_text'
183
+ )}
184
+ />
185
+ <Card style={styles.adjustCard}>
186
+ <Spacer height={cx(16)} />
187
+ <View style={styles.lightLine}>
188
+ <Text style={styles.light}>
189
+ {Strings.getLang('light_sources_tile_tw_lighting_headline')}
190
+ </Text>
191
+ </View>
192
+ <Spacer height={cx(18)} />
193
+ <TextFieldStyleButton
194
+ style={styles.transitionMode}
195
+ text={state.sceneMode[state.mood.mainLamp.mode]?.title}
196
+ placeholder={Strings.getLang('add_new_dynamic_mood_color_changing_mode_headline')}
197
+ onPress={() => {
198
+ const paramsSelect: SelectPageParams<number> = {
199
+ title: I18n.getLang('add_new_dynamic_mood_color_changing_mode_headline'),
200
+ data: createSelectModeData(state.mood.mainLamp.mode),
201
+ onSelect: selectPageData => {
202
+ state.mood.mainLamp.mode = selectPageData.value;
203
+ },
204
+ };
205
+ navigation.navigate(ui_biz_routerKey.group_ui_biz_select_page, paramsSelect);
206
+ }}
207
+ />
208
+ <Spacer height={cx(10)} />
209
+ <LdvSlider
210
+ title={Strings.getLang('add_new_dynamic_mood_lights_field_speed_topic_text')}
211
+ value={state.mood.mainLamp.speed}
212
+ onValueChange={() => {}}
213
+ onSlidingComplete={value => {
214
+ state.mood.mainLamp.speed = value;
215
+ }}
216
+ />
217
+ <Spacer height={cx(16)} />
218
+ {state.sceneMode[state.mood.mainLamp.mode]?.turnOn && (
219
+ <View style={styles.transitionMode}>
220
+ <Segmented
221
+ value={state.mood.mainLamp.direction}
222
+ options={[
223
+ {
224
+ label: I18n.getLang('add_new_dynamic_mood_strip_lights_switch_tab_text1'),
225
+ value: 0,
226
+ },
227
+ {
228
+ label: I18n.getLang('add_new_dynamic_mood_strip_lights_switch_tab_text2'),
229
+ value: 1,
230
+ },
231
+ ]}
232
+ onChange={v => (state.mood.mainLamp.direction = Number(v))}
233
+ />
234
+ <Spacer />
235
+ </View>
236
+ )}
237
+ {state.sceneMode[state.mood.mainLamp.mode]?.paragraph && (
238
+ <View style={styles.transitionMode}>
239
+ <Segmented
240
+ value={state.mood.mainLamp.segmented}
241
+ options={[
242
+ {
243
+ label: I18n.getLang('add_new_dynamic_mood_strip_lights_switch_tab_text3'),
244
+ value: 0,
245
+ },
246
+ {
247
+ label: I18n.getLang('add_new_dynamic_mood_strip_lights_switch_tab_text4'),
248
+ value: 1,
249
+ },
250
+ ]}
251
+ onChange={v => (state.mood.mainLamp.segmented = Number(v))}
252
+ />
253
+ <Spacer />
254
+ </View>
255
+ )}
256
+ {state.sceneMode[state.mood.mainLamp.mode]?.other && (
257
+ <>
258
+ <TextFieldStyleButton
259
+ style={styles.transitionMode}
260
+ text={getSelectOther(
261
+ state.sceneMode[state.mood.mainLamp.mode]?.other,
262
+ state.mood.mainLamp.expand
263
+ )}
264
+ placeholder={I18n.getLang(
265
+ 'add_new_dynamic_mood_strip_lights_selectionfield2_topic_text'
266
+ )}
267
+ onPress={() => {
268
+ const paramsSelect: SelectPageParams<number> = {
269
+ title: I18n.getLang(
270
+ 'add_new_dynamic_mood_strip_lights_selectionfield2_topic_text'
271
+ ),
272
+ data: createSelectOtherData(
273
+ state.sceneMode[state.mood.mainLamp.mode]?.other,
274
+ state.mood.mainLamp.expand
275
+ ),
276
+ onSelect: selectPageData => {
277
+ state.mood.mainLamp.expand = selectPageData.value;
278
+ },
279
+ };
280
+ navigation.navigate(ui_biz_routerKey.group_ui_biz_select_page, paramsSelect);
281
+ }}
282
+ />
283
+ <Spacer />
284
+ </>
285
+ )}
286
+ <View style={styles.nodesAdjust}>
287
+ <View style={styles.adjustButtons}>
288
+ <TouchableOpacity
289
+ onPress={() => {
290
+ state.mainBucketSelected = true;
291
+ }}
292
+ >
293
+ <Image
294
+ style={[
295
+ styles.adjustButton,
296
+ { tintColor: state.mainBucketSelected ? '#f60' : '#666' },
297
+ ]}
298
+ source={res.ic_paint_bucket}
299
+ />
300
+ </TouchableOpacity>
301
+ <TouchableOpacity
302
+ onPress={() => {
303
+ state.mainBucketSelected = false;
304
+ }}
305
+ >
306
+ <Image
307
+ style={[
308
+ styles.adjustButton,
309
+ { tintColor: state.mainBucketSelected ? '#666' : '#f60' },
310
+ ]}
311
+ source={res.ic_colorize}
312
+ />
313
+ </TouchableOpacity>
314
+ </View>
315
+ <FlatList
316
+ data={state.mood.mainLamp.nodes}
317
+ style={styles.nodeList}
318
+ renderItem={({ item, index }) => {
319
+ return (
320
+ <View style={styles.nodeItem}>
321
+ <TouchableOpacity
322
+ style={[
323
+ styles.nodeBlock,
324
+ {
325
+ backgroundColor: getNodeColor(item),
326
+ },
327
+ ]}
328
+ onPress={() => {
329
+ state.mainNode = item;
330
+ }}
331
+ />
332
+ <TouchableOpacity
333
+ style={styles.nodeDeleteBtn}
334
+ disabled={state.mood.mainLamp.nodes.length < 3}
335
+ onPress={() => {
336
+ state.mood.mainLamp.nodes.splice(index, 1);
337
+ state.mainNode = state.mood.mainLamp.nodes[state.mood.mainLamp.nodes.length - 1];
338
+ }}
339
+ >
340
+ <Image
341
+ style={[
342
+ styles.nodeDeleteIcon,
343
+ {
344
+ tintColor: state.mood.mainLamp.nodes.length < 3 ? '#ccc' : '#666',
345
+ },
346
+ ]}
347
+ source={res.ic_mood_del}
348
+ />
349
+ </TouchableOpacity>
350
+ </View>
351
+ );
352
+ }}
353
+ keyExtractor={(_, index) => `${index}`}
354
+ ItemSeparatorComponent={() => <Spacer height={cx(12)} />}
355
+ ListFooterComponent={() => {
356
+ if (state.mood.mainLamp.nodes.length >= 8) {
357
+ return <></>;
358
+ }
359
+ return (
360
+ <View>
361
+ <Spacer height={cx(12)} />
362
+ <TouchableOpacity
363
+ style={styles.nodeAddBtn}
364
+ onPress={() => {
365
+ const node = {
366
+ ...state.mainNode,
367
+ };
368
+ state.mood.mainLamp.nodes.push(node);
369
+ state.mainNode = node;
370
+ }}
371
+ >
372
+ <Image
373
+ style={{
374
+ width: cx(18),
375
+ height: cx(18),
376
+ tintColor: '#000',
377
+ }}
378
+ source={{ uri: res.add }}
379
+ />
380
+ </TouchableOpacity>
381
+ </View>
382
+ );
383
+ }}
384
+ />
385
+ </View>
386
+ <Spacer />
387
+ <View style={styles.lightLine}>
388
+ <Text style={styles.light}>
389
+ {Strings.getLang('add_new_dynamic_mood_lights_field_headline2_text')}
390
+ </Text>
391
+ <View
392
+ style={[styles.preview, { backgroundColor: getColorBlockColor(state.mainNode) }]}
393
+ />
394
+ </View>
395
+ <Spacer />
396
+ <LampAdjustView
397
+ isSupportColor={moduleParams.isSupportColor}
398
+ isSupportBrightness={moduleParams.isSupportBrightness}
399
+ isSupportTemperature={moduleParams.isSupportTemperature}
400
+ isColorMode={state.mainNode.isColorNode}
401
+ reserveSV={true}
402
+ setIsColorMode={isColorMode => {
403
+ if (state.mainBucketSelected) {
404
+ state.mood.mainLamp.nodes.forEach(node => {
405
+ node.isColorNode = isColorMode;
406
+ if (isColorMode && node.h === 0 && node.s === 0 && node.v === 0) {
407
+ node.s = 100;
408
+ node.v = 100;
409
+ } else {
410
+ if (node.brightness === 0 && node.colorTemp === 0) {
411
+ node.brightness = 100;
412
+ }
413
+ }
414
+ });
415
+ } else {
416
+ state.mainNode.isColorNode = isColorMode;
417
+ if (
418
+ isColorMode &&
419
+ state.mainNode.h === 0 &&
420
+ state.mainNode.s === 0 &&
421
+ state.mainNode.v === 0
422
+ ) {
423
+ state.mainNode.s = 100;
424
+ state.mainNode.v = 100;
425
+ } else {
426
+ if (state.mainNode.brightness === 0 && state.mainNode.colorTemp === 0) {
427
+ state.mainNode.brightness = 100;
428
+ }
429
+ }
430
+ }
431
+ }}
432
+ h={state.mainNode.h}
433
+ s={state.mainNode.s}
434
+ v={state.mainNode.v}
435
+ onHSVChange={(h, s, v) => {
436
+ if (state.mainBucketSelected) {
437
+ state.mood.mainLamp.nodes.forEach(node => {
438
+ node.isColorNode = true;
439
+ node.h = h;
440
+ node.s = s;
441
+ node.v = v;
442
+ });
443
+ } else {
444
+ state.mainNode.h = h;
445
+ state.mainNode.s = s;
446
+ state.mainNode.v = v;
447
+ }
448
+ }}
449
+ onHSVChangeComplete={(h, s, v) => {
450
+ if (state.mainBucketSelected) {
451
+ state.mood.mainLamp.nodes.forEach(node => {
452
+ node.isColorNode = true;
453
+ node.h = h;
454
+ node.s = s;
455
+ node.v = v;
456
+ });
457
+ } else {
458
+ state.mainNode.h = h;
459
+ state.mainNode.s = s || 1;
460
+ state.mainNode.v = v;
461
+ }
462
+ }}
463
+ colorTemp={state.mainNode.colorTemp}
464
+ brightness={state.mainNode.brightness}
465
+ onCCTChange={cct => {
466
+ if (state.mainBucketSelected) {
467
+ state.mood.mainLamp.nodes.forEach(node => {
468
+ node.isColorNode = false;
469
+ node.colorTemp = cct;
470
+ });
471
+ } else {
472
+ state.mainNode.colorTemp = cct;
473
+ }
474
+ }}
475
+ onCCTChangeComplete={cct => {
476
+ if (state.mainBucketSelected) {
477
+ state.mood.mainLamp.nodes.forEach(node => {
478
+ node.isColorNode = false;
479
+ node.colorTemp = cct;
480
+ });
481
+ } else {
482
+ state.mainNode.colorTemp = cct;
483
+ }
484
+ }}
485
+ onBrightnessChange={brightness => {
486
+ if (state.mainBucketSelected) {
487
+ state.mood.mainLamp.nodes.forEach(node => {
488
+ node.isColorNode = false;
489
+ node.brightness = brightness;
490
+ });
491
+ } else {
492
+ state.mainNode.brightness = brightness;
493
+ }
494
+ }}
495
+ onBrightnessChangeComplete={brightness => {
496
+ if (state.mainBucketSelected) {
497
+ state.mood.mainLamp.nodes.forEach(node => {
498
+ node.isColorNode = false;
499
+ node.brightness = brightness;
500
+ });
501
+ } else {
502
+ state.mainNode.brightness = brightness;
503
+ }
504
+ }}
505
+ />
506
+ </Card>
507
+ <Spacer />
508
+ {(moduleParams.isFanLight || moduleParams.isUVCFan) && (
509
+ <FanAdjustView
510
+ fanEnable={!!state.mood.mainLamp.fanEnable}
511
+ fanSpeed={state.mood.mainLamp.fanSpeed || 1}
512
+ maxFanSpeed={useFanMaxSpeed()}
513
+ onFanSwitch={fanEnable => {
514
+ state.mood.mainLamp.fanEnable = fanEnable;
515
+ }}
516
+ onFanSpeedChange={fanSpeed => {
517
+ state.mood.mainLamp.fanSpeed = fanSpeed;
518
+ }}
519
+ onFanSpeedChangeComplete={fanSpeed => {
520
+ state.mood.mainLamp.fanSpeed = fanSpeed;
521
+ }}
522
+ style={styles.fanAdjustCard}
523
+ />
524
+ )}
525
+ {params.mode === 'edit' && (
526
+ <View style={{ marginTop: cx(20), marginHorizontal: cx(24) }}>
527
+ <TextButton
528
+ style={styles.deleteBtn}
529
+ textStyle={styles.deleteBtnText}
530
+ text={Strings.getLang('edit_static_mood_button_delete_text')}
531
+ onPress={() => {
532
+ showDialog({
533
+ method: 'confirm',
534
+ title: I18n.getLang('string_light_pp_dialog_sm_ed_headline_d'),
535
+ subTitle: I18n.getLang('strip_light_static_mood_edit_dialog_text'),
536
+ onConfirm: async (_, { close }) => {
537
+ close()
538
+ if (state.loading) return
539
+ state.loading = true
540
+ const res = await params.modDeleteMood('del', state.mood);
541
+ state.loading = false
542
+ if (res.success) {
543
+ navigation.navigate(ui_biz_routerKey.group_ui_biz_mood);
544
+ }
545
+ }
546
+ })
547
+ }}
548
+ />
549
+ </View>
550
+ )}
551
+ <Spacer />
552
+ </View>
553
+ </ScrollView>
554
+ </Page>
555
+ );
556
+ };
557
+ const styles = StyleSheet.create({
558
+ root: {
559
+ flex: 1,
560
+ flexDirection: 'column',
561
+ },
562
+ name: {
563
+ marginHorizontal: cx(24),
564
+ },
565
+ adjustCard: {
566
+ marginVertical: cx(12),
567
+ marginHorizontal: cx(24),
568
+ },
569
+ fanAdjustCard: {
570
+ marginHorizontal: cx(24),
571
+ },
572
+ lightLine: {
573
+ flexDirection: 'row',
574
+ marginHorizontal: cx(16),
575
+ },
576
+ light: {
577
+ color: '#000',
578
+ fontSize: cx(18),
579
+ fontFamily: 'helvetica_neue_lt_std_bd',
580
+ },
581
+ transitionMode: {
582
+ marginHorizontal: cx(16),
583
+ },
584
+ preview: {
585
+ width: cx(20),
586
+ height: cx(20),
587
+ marginStart: cx(12),
588
+ borderRadius: cx(4),
589
+ },
590
+ nodesAdjust: {
591
+ flexDirection: 'row',
592
+ alignItems: 'center',
593
+ },
594
+ adjustButtons: {
595
+ width: cx(44),
596
+ marginStart: cx(16),
597
+ },
598
+ adjustButton: {
599
+ width: cx(44),
600
+ height: cx(44),
601
+ },
602
+ nodeList: {
603
+ flex: 1,
604
+ marginHorizontal: cx(16),
605
+ },
606
+ nodeItem: {
607
+ flexDirection: 'row',
608
+ alignItems: 'center',
609
+ },
610
+ nodeBlock: {
611
+ flex: 1,
612
+ height: cx(40),
613
+ borderRadius: cx(8),
614
+ },
615
+ nodeDeleteBtn: {
616
+ width: cx(24),
617
+ height: cx(30),
618
+ justifyContent: 'center',
619
+ alignItems: 'center',
620
+ },
621
+ nodeDeleteIcon: {
622
+ width: cx(16),
623
+ height: cx(16),
624
+ },
625
+ nodeAddBtn: {
626
+ height: cx(40),
627
+ justifyContent: 'center',
628
+ alignItems: 'center',
629
+ marginEnd: cx(26),
630
+ borderRadius: cx(8),
631
+ borderWidth: cx(1),
632
+ borderStyle: 'dashed',
633
+ borderColor: '#666',
634
+ backgroundColor: '#f6f6f6',
635
+ },
636
+ deleteBtn: {
637
+ width: '100%',
638
+ height: cx(50),
639
+ backgroundColor: '#666',
640
+ borderRadius: cx(8),
641
+ },
642
+ deleteBtnText: {
643
+ color: '#fff',
644
+ fontSize: cx(16),
645
+ fontFamily: 'helvetica_neue_lt_std_bd',
646
+ },
647
+ });
648
+ export default DynamicMoodEditorPage;
649
+ export function getTransitionModeString(transitionMode: MoodNodeTransitionMode): string {
650
+ if (transitionMode === MoodNodeTransitionMode.Jump) {
651
+ return Strings.getLang('other_lights_modes_jump_text');
652
+ }
653
+ return Strings.getLang('other_lights_modes_gradient_text');
654
+ }