@ledvance/group-ui-biz-bundle 1.0.46 → 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 (37) 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/AddMoodPage.tsx +2 -2
  10. package/src/modules/mood_new/AddMoodPage.tsx +197 -0
  11. package/src/modules/mood_new/DynamicMoodEditorPage.tsx +654 -0
  12. package/src/modules/mood_new/Interface.ts +219 -0
  13. package/src/modules/mood_new/MixDynamicMoodEditor.tsx +788 -0
  14. package/src/modules/mood_new/MoodActions.ts +227 -0
  15. package/src/modules/mood_new/MoodInfo.ts +2151 -0
  16. package/src/modules/mood_new/MoodItem.tsx +148 -0
  17. package/src/modules/mood_new/MoodPage.tsx +374 -0
  18. package/src/modules/mood_new/MoodParse.ts +442 -0
  19. package/src/modules/mood_new/RecommendMoodItem.tsx +69 -0
  20. package/src/modules/mood_new/Router.ts +43 -0
  21. package/src/modules/mood_new/StaticMoodEditorPage.tsx +293 -0
  22. package/src/modules/music/Router.ts +16 -0
  23. package/src/modules/randomTimeForPlug/Router.ts +25 -0
  24. package/src/modules/randomTimingForLight/Router.ts +25 -0
  25. package/src/modules/remoteSwitch/Router.ts +16 -0
  26. package/src/modules/select/Router.ts +16 -0
  27. package/src/modules/switchGradient/Router.ts +16 -0
  28. package/src/modules/timeSchedule/Interface.ts +150 -0
  29. package/src/modules/timeSchedule/Router.ts +25 -0
  30. package/src/modules/timeSchedule/TimeScheduleActions.ts +140 -0
  31. package/src/modules/timeSchedule/TimeScheduleDetailPage.tsx +625 -0
  32. package/src/modules/timeSchedule/TimeSchedulePage.tsx +220 -0
  33. package/src/modules/timeSchedule/components/ManuaSettings.tsx +376 -0
  34. package/src/modules/timeSchedule/components/ScheduleCard.tsx +109 -0
  35. package/src/modules/timeSchedule/components/Summary.tsx +124 -0
  36. package/src/modules/timer/Router.ts +16 -0
  37. package/src/navigation/Routers.ts +1 -0
@@ -0,0 +1,148 @@
1
+ import React, { useMemo } from 'react';
2
+ import { StyleSheet, Text, View, ViewProps, ViewStyle, Image } from 'react-native';
3
+ import { SwitchButton, Utils } from 'tuya-panel-kit';
4
+ import { hsv2Hex } from '@ledvance/base/src/utils';
5
+ import { cctToColor } from '@ledvance/base/src/utils/cctUtils';
6
+ import { mapFloatToRange } from '@ledvance/base/src/utils';
7
+ import Card from '@ledvance/base/src/components/Card';
8
+ import Spacer from '@ledvance/base/src/components/Spacer';
9
+ import MoodColorsLine from '@ledvance/base/src/components/MoodColorsLine';
10
+ import { MoodLampInfo, MoodUIInfo } from './Interface';
11
+ import I18n from '@ledvance/base/src/i18n';
12
+ import res from '@ledvance/base/src/res';
13
+
14
+ const cx = Utils.RatioUtils.convertX;
15
+
16
+ interface MoodItemProps extends ViewProps {
17
+ enable: boolean;
18
+ isMix: boolean;
19
+ mood: MoodUIInfo;
20
+ style?: ViewStyle;
21
+ onPress?: () => void;
22
+ onSwitch: (enable: boolean) => void;
23
+ }
24
+
25
+ const MoodItem = (props: MoodItemProps) => {
26
+ const { mood, isMix } = props;
27
+ const isDynamic = useMemo(() => {
28
+ return mood.mainLamp.nodes?.length > 1 || mood.secondaryLamp.nodes?.length > 1;
29
+ }, [mood.mainLamp.nodes, mood.secondaryLamp.nodes]);
30
+
31
+ return (
32
+ <Card style={[styles.card, props.style]} onPress={props.onPress}>
33
+ <View>
34
+ <Spacer height={cx(16)} />
35
+ <View style={styles.headline}>
36
+ <Text style={styles.headText}>{mood.name}</Text>
37
+ <SwitchButton
38
+ thumbStyle={{ elevation: 0 }}
39
+ value={props.enable}
40
+ onValueChange={props.onSwitch}
41
+ />
42
+ </View>
43
+ <Spacer />
44
+ <MixMoodColorsLine mixSubLight={mood.mainLamp} isMix={isMix} />
45
+ {(isMix && !!mood.secondaryLamp.nodes.length) && (
46
+ <>
47
+ <Spacer height={cx(7)} />
48
+ <MixMoodColorsLine mixSubLight={mood.secondaryLamp} isMix={isMix} />
49
+ </>
50
+ )}
51
+ <Spacer height={cx(12)} />
52
+ <View style={styles.moodTypeItem}>
53
+ <View style={styles.moodTypeLabel}>
54
+ <Text style={styles.moodTypeLabelText}>
55
+ {I18n.getLang(
56
+ isDynamic ? 'mood_overview_field_chip_2' : 'mood_overview_field_chip_text'
57
+ )}
58
+ </Text>
59
+ </View>
60
+ </View>
61
+ <Spacer height={cx(16)} />
62
+ </View>
63
+ </Card>
64
+ );
65
+ };
66
+
67
+ export default MoodItem;
68
+
69
+ export function MixMoodColorsLine(props: { mixSubLight: MoodLampInfo; isMix: boolean }) {
70
+ const { mixSubLight, isMix } = props;
71
+ const lightColors = !!(mixSubLight.enable && mixSubLight.nodes.length) ? mixSubLight.nodes?.map(n => {
72
+ return n.isColorNode
73
+ ? hsv2Hex(n.h, Math.round(n.s), Math.round(mapFloatToRange(n.v / 100, 50, 100)))
74
+ : cctToColor(n.colorTemp.toFixed());
75
+ }) : ['#eee'];
76
+ return (
77
+ <View style={styles.gradientItem}>
78
+ <Spacer height={0} width={cx(16)} />
79
+ <MoodColorsLine
80
+ nodeStyle={{ borderColor: '#ccc', borderWidth: 1 }}
81
+ width={isMix ? cx(264) : undefined}
82
+ type={'separate'}
83
+ colors={lightColors}
84
+ />
85
+ {isMix && (
86
+ <>
87
+ <Spacer height={0} width={cx(7)} />
88
+ <View style={styles.gradientItemIconView}>
89
+ <Image style={styles.gradientItemIcon} source={mixSubLight.enable ? res.light_on : res.light_off} />
90
+ </View>
91
+ </>
92
+ )}
93
+ </View>
94
+ );
95
+ }
96
+
97
+ const styles = StyleSheet.create({
98
+ card: {
99
+ marginHorizontal: cx(24),
100
+ },
101
+ headline: {
102
+ flexDirection: 'row',
103
+ marginHorizontal: cx(16),
104
+ },
105
+ headText: {
106
+ flex: 1,
107
+ color: '#000',
108
+ fontSize: cx(16),
109
+ fontFamily: 'helvetica_neue_lt_std_bd',
110
+ lineHeight: cx(20),
111
+ },
112
+ gradientItem: {
113
+ flexDirection: 'row',
114
+ },
115
+ gradientItemIconView: {
116
+ width: cx(24),
117
+ height: cx(24),
118
+ justifyContent: 'center',
119
+ alignItems: 'center',
120
+ backgroundColor: '#aaa',
121
+ borderRadius: cx(8),
122
+ },
123
+ gradientItemIcon: {
124
+ width: cx(16),
125
+ height: cx(16),
126
+ tintColor: '#fff',
127
+ },
128
+ gradient: {
129
+ borderRadius: cx(8),
130
+ },
131
+ moodTypeItem: {
132
+ flexDirection: 'row',
133
+ },
134
+ moodTypeLabel: {
135
+ marginStart: cx(16),
136
+ paddingHorizontal: cx(12.5),
137
+ backgroundColor: '#E6E7E8',
138
+ borderRadius: cx(8),
139
+ },
140
+ moodTypeLabelText: {
141
+ height: cx(16),
142
+ color: '#000000DD',
143
+ fontSize: cx(10),
144
+ textAlignVertical: 'center',
145
+ fontFamily: 'helvetica_neue_lt_std_roman',
146
+ lineHeight: cx(16),
147
+ },
148
+ });
@@ -0,0 +1,374 @@
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 { saveMoodList, useRgbicWorkMode, useWorkMode } from './MoodActions';
5
+ import {
6
+ useDeviceInfo,
7
+ useFlagMode,
8
+ useMoods,
9
+ useUAGroupInfo,
10
+ } from '@ledvance/base/src/models/modules/NativePropsSlice';
11
+ import { useReactive, useUpdateEffect } from 'ahooks';
12
+ import Strings from '@ledvance/base/src/i18n';
13
+ import res from '@ledvance/base/src/res';
14
+ import { FlatList, StyleSheet, View, Platform } from 'react-native';
15
+ import Tag from '@ledvance/base/src/components/Tag';
16
+ import Spacer from '@ledvance/base/src/components/Spacer';
17
+ import InfoText from '@ledvance/base/src/components/InfoText';
18
+ import CustomListDialog from '@ledvance/base/src/components/CustomListDialog';
19
+ import MoodItem from './MoodItem';
20
+ import { useNavigation } from '@react-navigation/core';
21
+ import { MoodPageParams, MoodPageState, MoodUIInfo } from './Interface';
22
+ import { getRemoteMoodList, useMoodScene } from './MoodActions';
23
+ import { useParams } from '@ledvance/base/src/hooks/Hooks';
24
+ import { ui_biz_routerKey } from '../../navigation/Routers'
25
+ import { cloneDeep } from 'lodash';
26
+ import { saveFlagMode } from '../flags/FlagActions';
27
+ import { WorkMode } from '@ledvance/base/src/utils/interface';
28
+
29
+ const cx = Utils.RatioUtils.convertX;
30
+
31
+ const MAX_MOOD_COUNT = 255;
32
+
33
+ const MoodPage = () => {
34
+ const params = useParams<MoodPageParams>();
35
+ const deviceInfo = useDeviceInfo();
36
+ const uaGroupInfo = useUAGroupInfo()
37
+ const navigation = useNavigation();
38
+ const option = {
39
+ isCeilingLight: params.isCeilingLight,
40
+ isStripLight: params.isStripLight,
41
+ isStringLight: params.isStringLight,
42
+ isFanLight: params.isFanLight,
43
+ isMixLight: params.isMixLight,
44
+ isUVCFan: params.isUVCFan,
45
+ isMatterLight: params.isMatterLight,
46
+ };
47
+ const [moodInfo, setMoodInfo] = useMoodScene(option);
48
+ const workMode = useWorkMode()
49
+ const rgbicWorkMode = useRgbicWorkMode()
50
+ const [moods, setMoods] = useMoods();
51
+ const [flagMode, setFlagMode] = useFlagMode();
52
+ const state = useReactive<MoodPageState>({
53
+ currentMood: undefined,
54
+ staticTagChecked: true,
55
+ dynamicTagChecked: true,
56
+ showAddMoodPopover: false,
57
+ originMoods: cloneDeep(moods),
58
+ filterMoods: [],
59
+ loading: false,
60
+ timerId: undefined as any,
61
+ flag: Symbol(),
62
+ });
63
+
64
+ useEffect(() => {
65
+ state.timerId = setTimeout(() => {
66
+ state.loading = true
67
+ getRemoteMoodList(
68
+ uaGroupInfo.tyGroupId.toString(),
69
+ {
70
+ ...option,
71
+ isSupportBrightness: params.isSupportBrightness,
72
+ isSupportColor: params.isSupportColor,
73
+ isSupportTemperature: params.isSupportTemperature,
74
+ }
75
+ ).then(res => {
76
+ state.loading = false
77
+ console.log(res.data, '< --- res.data --- >')
78
+ if (res.success && Array.isArray(res.data)) {
79
+ state.originMoods = cloneDeep(res.data);
80
+ }
81
+ });
82
+ }, 200);
83
+
84
+ return () => {
85
+ clearTimeout(state.timerId);
86
+ };
87
+ }, []);
88
+
89
+ useEffect(() => {
90
+ state.filterMoods = state.originMoods.filter(item => {
91
+ return (
92
+ (state.staticTagChecked && state.dynamicTagChecked) ||
93
+ (!state.staticTagChecked && !state.dynamicTagChecked) ||
94
+ (state.staticTagChecked && item.mainLamp.nodes.length < 2) ||
95
+ (state.dynamicTagChecked &&
96
+ (item.secondaryLamp.nodes.length > 1 || item.mainLamp.nodes.length > 1))
97
+ );
98
+ });
99
+ }, [state.staticTagChecked, state.dynamicTagChecked, state.originMoods]);
100
+
101
+ const navigationRoute = (isStatic: boolean, mode: 'add' | 'edit', currentMood?: MoodUIInfo) => {
102
+ const path =
103
+ mode === 'add'
104
+ ? ui_biz_routerKey.group_ui_biz_mood_add
105
+ : isStatic
106
+ ? ui_biz_routerKey.group_ui_biz_static_mood_edit
107
+ : !!(params.isMixLight || params.isCeilingLight)
108
+ ? ui_biz_routerKey.group_ui_biz_dynamic_mix_mood_edit
109
+ : ui_biz_routerKey.group_ui_biz_dynamic_mood_edit;
110
+
111
+ navigation.navigate(path, {
112
+ mode,
113
+ isStatic,
114
+ moods: state.originMoods,
115
+ currentMood,
116
+ moduleParams: params,
117
+ modDeleteMood,
118
+ });
119
+ };
120
+
121
+ const modDeleteMood = async (mode: 'add' | 'edit' | 'del' | 'set', currentMood: MoodUIInfo) => {
122
+ const checkedMood: MoodUIInfo = {
123
+ ...currentMood,
124
+ mainLamp: {
125
+ ...currentMood.mainLamp,
126
+ nodes: currentMood.mainLamp.nodes.map(node => {
127
+ if (mode !== 'del') {
128
+ if (node.isColorNode) {
129
+ node.brightness = 0;
130
+ node.colorTemp = 0;
131
+ } else {
132
+ node.h = 0;
133
+ node.s = 0;
134
+ node.v = 0;
135
+ if (!params.isSupportTemperature) {
136
+ node.colorTemp = 100; // 适配dim灯
137
+ }
138
+ }
139
+ return node;
140
+ }
141
+ return node;
142
+ }),
143
+ },
144
+ secondaryLamp: {
145
+ ...currentMood.secondaryLamp,
146
+ nodes: currentMood.secondaryLamp
147
+ ? currentMood.secondaryLamp.nodes.map(node => {
148
+ if (mode !== 'del') {
149
+ if (node.isColorNode) {
150
+ node.brightness = 0;
151
+ node.colorTemp = 0;
152
+ } else {
153
+ node.h = 0;
154
+ node.s = 0;
155
+ node.v = 0;
156
+ }
157
+ return node;
158
+ }
159
+ return node;
160
+ })
161
+ : [],
162
+ },
163
+ };
164
+ if (mode === 'set') {
165
+ return setMoodInfo({
166
+ scene: checkedMood,
167
+ });
168
+ }
169
+ let newScene: MoodUIInfo[] = [];
170
+ if (mode === 'add') {
171
+ newScene = [checkedMood, ...state.originMoods];
172
+ } else if (mode === 'del') {
173
+ if (params.isCeilingLight) {
174
+ newScene = state.originMoods.filter(item => (item.mainLamp.id !== checkedMood.mainLamp.id) || (item.secondaryLamp.id !== checkedMood.secondaryLamp.id))
175
+ } else {
176
+ newScene = state.originMoods.filter(item => item.id !== checkedMood.id);
177
+ }
178
+ } else {
179
+ if (params.isCeilingLight) {
180
+ newScene = state.originMoods.map(item => {
181
+ if (item.mainLamp.id === checkedMood.mainLamp.id && item.secondaryLamp.id === checkedMood.secondaryLamp.id) {
182
+ return checkedMood;
183
+ }
184
+ return item;
185
+ });
186
+ } else {
187
+ newScene = state.originMoods.map(item => {
188
+ if (item.id === checkedMood.id) {
189
+ return checkedMood;
190
+ }
191
+ return item;
192
+ });
193
+ }
194
+ }
195
+ const mood = mode === 'del' ? (newScene.length === 0 ? undefined : newScene[0]) : checkedMood;
196
+ const res = await saveMoodList(uaGroupInfo.tyGroupId.toString(), newScene, option);
197
+ if (res.success) {
198
+ state.originMoods = cloneDeep(newScene);
199
+ setMoods(cloneDeep(newScene));
200
+ updateFlagMode();
201
+ if ((mode === 'del' && (params.isCeilingLight ?
202
+ (moodInfo.scene?.mainLamp.id !== checkedMood.mainLamp.id || moodInfo.scene?.secondaryLamp.id !== checkedMood.secondaryLamp.id) :
203
+ moodInfo.scene?.id !== checkedMood.id)) ||
204
+ (params.isCeilingLight ? (workMode !== WorkMode.Scene && rgbicWorkMode !== WorkMode.Scene) : workMode !== WorkMode.Scene)) {
205
+ return {
206
+ success: true
207
+ }
208
+ }
209
+ return setMoodInfo({
210
+ scene: cloneDeep(mood)
211
+ })
212
+ }
213
+ return {
214
+ success: false
215
+ }
216
+ };
217
+
218
+ const updateFlagMode = () => {
219
+ if (flagMode?.flagMode) {
220
+ saveFlagMode(
221
+ uaGroupInfo.tyGroupId.toString(),
222
+ JSON.stringify({
223
+ flagMode: false,
224
+ flagId: undefined,
225
+ })
226
+ ).then();
227
+ setFlagMode({
228
+ flagMode: false,
229
+ flagId: undefined,
230
+ });
231
+ }
232
+ };
233
+
234
+ const onAddMoodDialogItemClick = useCallback(
235
+ (isStatic: boolean, _: number) => {
236
+ if (!!state.originMoods) {
237
+ navigationRoute(isStatic, 'add');
238
+ }
239
+ state.showAddMoodPopover = false;
240
+ },
241
+ [state.originMoods]
242
+ );
243
+
244
+ const getItemEnable = useCallback(
245
+ (moodItem: MoodUIInfo) => {
246
+ if (option.isCeilingLight) {
247
+ return (
248
+ moodInfo.scene?.mainLamp?.id === moodItem.mainLamp.id &&
249
+ moodInfo.scene?.secondaryLamp.id === moodItem.secondaryLamp.id &&
250
+ (workMode === WorkMode.Scene || rgbicWorkMode === WorkMode.Scene)
251
+ );
252
+ } else {
253
+ return moodInfo.scene?.id === moodItem.id && workMode === WorkMode.Scene && !flagMode.flagMode;
254
+ }
255
+ },
256
+ [moodInfo]
257
+ );
258
+
259
+
260
+ return (
261
+ <>
262
+ <Page
263
+ backText={deviceInfo.name}
264
+ headlineText={Strings.getLang('mood_overview_headline_text')}
265
+ headlineIcon={state.originMoods.length < MAX_MOOD_COUNT ? res.add : undefined}
266
+ onHeadlineIconClick={() => {
267
+ if (params.isStringLight || params.isStripLight) {
268
+ onAddMoodDialogItemClick(false, 1);
269
+ } else {
270
+ state.showAddMoodPopover = !state.showAddMoodPopover;
271
+ }
272
+ }}
273
+ loading={state.loading}
274
+ >
275
+ <View style={styles.tagLine}>
276
+ <Tag
277
+ checked={state.staticTagChecked}
278
+ text={Strings.getLang('mood_overview_filter_name_text1')}
279
+ onCheckedChange={checked => {
280
+ state.staticTagChecked = checked;
281
+ }}
282
+ />
283
+ <Spacer width={cx(8)} height={0} />
284
+ <Tag
285
+ checked={state.dynamicTagChecked}
286
+ text={Strings.getLang('mood_overview_filter_name_text2')}
287
+ onCheckedChange={checked => {
288
+ state.dynamicTagChecked = checked;
289
+ }}
290
+ />
291
+ </View>
292
+ <Spacer height={cx(10)} />
293
+ {state.originMoods.length >= MAX_MOOD_COUNT && (
294
+ <View style={styles.infoLine}>
295
+ <Spacer height={cx(10)} />
296
+ <InfoText
297
+ icon={res.ic_warning_amber}
298
+ text={Strings.getLang('mood_overview_warning_max_number_text')}
299
+ contentColor={'#ff9500'}
300
+ />
301
+ <Spacer height={cx(6)} />
302
+ </View>
303
+ )}
304
+ <FlatList
305
+ data={state.filterMoods}
306
+ renderItem={({ item }) => {
307
+ return (
308
+ <MoodItem
309
+ enable={getItemEnable(item)}
310
+ isMix={!!(params.isMixLight || params.isCeilingLight)}
311
+ mood={item}
312
+ onPress={() => {
313
+ navigationRoute(item.mainLamp.nodes.length === 1, 'edit', item);
314
+ }}
315
+ onSwitch={async _ => {
316
+ state.loading = true;
317
+ await modDeleteMood('set', item);
318
+ updateFlagMode();
319
+ state.loading = false;
320
+ }}
321
+ />
322
+ );
323
+ }}
324
+ ListHeaderComponent={() => <Spacer height={cx(10)} />}
325
+ ItemSeparatorComponent={() => <Spacer />}
326
+ ListFooterComponent={() => <Spacer />}
327
+ keyExtractor={item => `${item.name}`}
328
+ />
329
+ </Page>
330
+ <CustomListDialog
331
+ show={state.showAddMoodPopover}
332
+ style={styles.addMoodPopover}
333
+ itemStyle={styles.popoverItem}
334
+ onDismiss={() => {
335
+ state.showAddMoodPopover = false;
336
+ }}
337
+ data={[
338
+ {
339
+ text: Strings.getLang('mood_overview_add_mood_text'),
340
+ value: true,
341
+ },
342
+ {
343
+ text: Strings.getLang('mood_overview_add_mood_text2'),
344
+ value: false,
345
+ },
346
+ ]}
347
+ onItemPress={onAddMoodDialogItemClick}
348
+ />
349
+ </>
350
+ );
351
+ };
352
+
353
+ const styles = StyleSheet.create({
354
+ tagLine: {
355
+ flexDirection: 'row',
356
+ marginHorizontal: cx(24),
357
+ },
358
+ infoLine: {
359
+ marginHorizontal: cx(24),
360
+ },
361
+ addMoodPopover: {
362
+ position: 'absolute',
363
+ right: cx(60),
364
+ top: Platform.OS === 'android' ? cx(90) : cx(130),
365
+ maxWidth: cx(200),
366
+ backgroundColor: '#fff',
367
+ },
368
+ popoverItem: {
369
+ padding: cx(5),
370
+ alignItems: 'flex-start',
371
+ },
372
+ });
373
+
374
+ export default MoodPage;