@ledvance/group-ui-biz-bundle 1.0.91 → 1.0.92

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.
@@ -0,0 +1,356 @@
1
+ import React, {useEffect, useMemo} from 'react';
2
+ import {Image, ScrollView, StyleSheet, TouchableOpacity, View} from 'react-native';
3
+ import {cloneDeep, isEqual} from 'lodash';
4
+ import {useReactive} from 'ahooks';
5
+ import Page from '@ledvance/base/src/components/Page';
6
+ import I18n from '@ledvance/base/src/i18n';
7
+ import {useNavigation} from '@react-navigation/native';
8
+ import TextField from '@ledvance/base/src/components/TextField';
9
+ import {Utils} from 'tuya-panel-kit';
10
+ import Card from '@ledvance/base/src/components/Card';
11
+ import Spacer from '@ledvance/base/src/components/Spacer';
12
+ import res from '@ledvance/base/src/res';
13
+ import TextButton from '@ledvance/base/src/components/TextButton';
14
+ import {useParams} from '@ledvance/base/src/hooks/Hooks';
15
+ import LdvSwitch from '@ledvance/base/src/components/ldvSwitch';
16
+ import {showDialog} from '@ledvance/base/src/utils/common';
17
+ import ColorAdjustView from '@ledvance/base/src/components/ColorAdjustView';
18
+ import ThemeType from '@ledvance/base/src/config/themeType'
19
+ import DiySceneNodeView from "@ledvance/base/src/components/DiySceneNodeView";
20
+ import { useLoveScenes} from "./DiySceneActions";
21
+ import LdvSlider from "@ledvance/base/src/components/ldvSlider";
22
+ import {Result} from "@ledvance/base/src/models/modules/Result";
23
+ import {ui_biz_routerKey} from "../../navigation/Routers";
24
+ import { DiySceneInfo } from '@ledvance/base/src/utils/interface';
25
+
26
+ const cx = Utils.RatioUtils.convertX;
27
+ const { withTheme } = Utils.ThemeUtils
28
+
29
+ export interface DiySceneEditorPageParams {
30
+ mode: 'add' | 'edit'
31
+ currentScene: DiySceneInfo
32
+ nameRepeat: (mood: DiySceneInfo) => boolean
33
+ sceneInfoOperation: (mode: 'add' | 'edit' | 'del', currentScene?: DiySceneInfo) => Promise<Result<any>>
34
+ }
35
+
36
+ export interface DiySceneEditorPageState {
37
+ headline: string;
38
+ h: number
39
+ s: number
40
+ v: number
41
+ sceneInfo: DiySceneInfo;
42
+ loading: boolean;
43
+ currentNode: number,
44
+ position: 'Top' | 'Bottom'
45
+ }
46
+
47
+ const DiySceneEditorPage = (props: { theme?: ThemeType }) => {
48
+ const navigation = useNavigation();
49
+ const routeParams = useParams<DiySceneEditorPageParams>();
50
+ const params = cloneDeep(routeParams);
51
+ const [loveScenes, setLoveScenes] = useLoveScenes()
52
+ const state = useReactive<DiySceneEditorPageState>({
53
+ headline: '',
54
+ h: 359,
55
+ s: 100,
56
+ v: 100,
57
+ sceneInfo: params.currentScene,
58
+ loading: false,
59
+ currentNode: 0,
60
+ position: 'Top'
61
+ });
62
+
63
+ useEffect(() => {
64
+ state.headline = I18n.getLang(
65
+ params.mode === 'add' ? 'string_light_pp_sm_headline_add' : 'edit_static_mood_headline_text'
66
+ );
67
+ }, [params.mode]);
68
+
69
+ useEffect(() => {
70
+ if (state.sceneInfo.nodes.length > 0) {
71
+ const color = state.sceneInfo.nodes[0].top;
72
+ state.h = color.h
73
+ state.s = Math.round(color.s / 10)
74
+ state.v = Math.round((state.sceneInfo.v || 1000) / 10)
75
+ }
76
+ }, []);
77
+
78
+ const onRightClick = async () => {
79
+ if (state.loading || !canSaveMoodData) return;
80
+ state.loading = true;
81
+ const newScene: DiySceneInfo = {
82
+ ...state.sceneInfo
83
+ };
84
+ const res = await params.sceneInfoOperation(params.mode, newScene);
85
+ state.loading = false;
86
+ if (res.success) {
87
+ navigation.navigate(ui_biz_routerKey.group_ui_biz_diy_scene_page);
88
+ }
89
+ };
90
+
91
+ const nameRepeat = useMemo(() => {
92
+ return params.nameRepeat(state.sceneInfo)
93
+ }, [state.sceneInfo.name]);
94
+
95
+ const isLove = useMemo(() => {
96
+ return loveScenes.some(it => it === state.sceneInfo.id)
97
+ }, [loveScenes]);
98
+
99
+ const checkSceneChanged = useMemo(() => {
100
+ return isEqual(state.sceneInfo, params.currentScene)
101
+ }, [JSON.stringify(state.sceneInfo), {}])
102
+
103
+ const canSaveMoodData = useMemo(() => {
104
+ return state.sceneInfo.name.length > 0 && state.sceneInfo.name.length < 33 && !nameRepeat && (params.mode === 'add' || !checkSceneChanged)
105
+ }, [nameRepeat, state.sceneInfo.name, checkSceneChanged, params.currentScene])
106
+
107
+ const toggleLoveScene = (id: number) => {
108
+ const newLoveScenes = loveScenes
109
+ const index = newLoveScenes.indexOf(id)
110
+ if (index !== -1) {
111
+ if (newLoveScenes.length <= 2) {
112
+ showLoveNumAlert()
113
+ } else {
114
+ newLoveScenes.splice(index, 1)
115
+ }
116
+ } else {
117
+ if (newLoveScenes.length >= 14) {
118
+ showLoveNumAlert()
119
+ } else {
120
+ newLoveScenes.push(id)
121
+ }
122
+ }
123
+ setLoveScenes(newLoveScenes).then()
124
+ }
125
+
126
+ const showLoveNumAlert = () => {
127
+ showDialog({
128
+ method: 'alert',
129
+ title: I18n.getLang('love_mood_alert_title'),
130
+ subTitle: I18n.getLang('love_mood_alert_content'),
131
+ onConfirm: async (_, { close }) => {
132
+ close()
133
+ }
134
+ })
135
+ }
136
+
137
+
138
+ const styles = StyleSheet.create({
139
+ root: {
140
+ flex: 1,
141
+ flexDirection: 'column',
142
+ },
143
+ name: {
144
+ marginHorizontal: cx(24),
145
+ },
146
+ nodeCard: {
147
+ marginHorizontal: cx(24),
148
+ },
149
+ nodeOperation: {
150
+ flexDirection: 'row',
151
+ justifyContent: 'flex-end',
152
+ marginTop: cx(12),
153
+ paddingHorizontal: cx(12),
154
+ },
155
+ nodeList: {
156
+ display: 'flex',
157
+ flexDirection: 'row',
158
+ justifyContent: 'flex-start',
159
+ flexWrap: 'wrap',
160
+ },
161
+ adjustCard: {
162
+ marginTop: cx(12),
163
+ marginHorizontal: cx(24),
164
+ },
165
+ fanAdjustCard: {
166
+ marginHorizontal: cx(24),
167
+ },
168
+ preview: {
169
+ width: cx(20),
170
+ height: cx(20),
171
+ marginStart: cx(12),
172
+ borderRadius: cx(4),
173
+ },
174
+ deleteBtn: {
175
+ width: '100%',
176
+ height: cx(50),
177
+ backgroundColor: props.theme?.button.delete,
178
+ borderRadius: cx(8),
179
+ },
180
+ deleteBtnText: {
181
+ color: props.theme?.button.fontColor,
182
+ fontSize: cx(16),
183
+ fontFamily: 'helvetica_neue_lt_std_bd',
184
+ },
185
+ })
186
+
187
+ return (
188
+ <Page
189
+ backText={I18n.getLang('mesh_device_detail_mode')}
190
+ showBackDialog={!checkSceneChanged}
191
+ backDialogTitle={I18n.getLang(
192
+ params.mode === 'add'
193
+ ? 'string_light_pp_dialog_sm_add_headline_c'
194
+ : 'manage_user_unsaved_changes_dialog_headline'
195
+ )}
196
+ backDialogContent={I18n.getLang(
197
+ params.mode === 'add'
198
+ ? 'strip_light_static_mood_add_step_2_dialog_text'
199
+ : 'strip_light_static_mood_editor_step_2_dialog_text'
200
+ )}
201
+ headlineText={state.headline}
202
+ headlineIconContent={
203
+ state.sceneInfo.type !== 'DIY' && <TouchableOpacity onPress={() => {
204
+ toggleLoveScene(state.sceneInfo.id)
205
+ }}>
206
+ {isLove ? <Image source={res.like} style={{width: cx(24), height: cx(24)}}/>
207
+ : <Image source={res.un_like}
208
+ style={{width: cx(24), height: cx(24), tintColor: props.theme?.global.fontColor}}/>}
209
+ </TouchableOpacity>
210
+ }
211
+ rightButtonIcon={canSaveMoodData ? res.ic_check : res.ic_uncheck}
212
+ rightButtonIconClick={onRightClick}
213
+ loading={state.loading}
214
+ >
215
+ <ScrollView style={{ flex: 1 }} nestedScrollEnabled={true}>
216
+ <View style={styles.root}>
217
+ <TextField
218
+ style={styles.name}
219
+ value={state.sceneInfo.name}
220
+ placeholder={I18n.getLang('edit_static_mood_inputfield_topic_text')}
221
+ onChangeText={text => {
222
+ state.sceneInfo.name = text;
223
+ }}
224
+ maxLength={33}
225
+ showError={state.sceneInfo.name.length > 32 || nameRepeat}
226
+ tipColor={nameRepeat ? props.theme?.global.error : undefined}
227
+ tipIcon={nameRepeat ? res.ic_text_field_input_error : undefined}
228
+ errorText={I18n.getLang(
229
+ nameRepeat ? 'string_light_pp_field_sm_add_error1' : 'add_new_dynamic_mood_alert_text'
230
+ )}
231
+ />
232
+ {
233
+ state.sceneInfo.type === 'DIY' && <Card style={styles.nodeCard}>
234
+ <View style={styles.nodeOperation}>
235
+ {state.sceneInfo.nodes.length < 8 && <TouchableOpacity onPress={() => {
236
+ const color = {h: state.h, s: state.s * 10, v: state.v}
237
+ state.sceneInfo.nodes.push({top: color, bottom: color});
238
+ }}>
239
+ <Image source={res.ic_plus} style={{tintColor: props.theme?.icon.primary}} />
240
+ </TouchableOpacity>}
241
+ { state.sceneInfo.nodes.length > 2 && <TouchableOpacity onPress={() => {
242
+ state.sceneInfo.nodes.splice(state.currentNode, 1)
243
+ state.currentNode = state.currentNode === state.sceneInfo.nodes.length ? 0 : state.currentNode
244
+ }}>
245
+ <Image source={res.ic_mood_del} style={{marginLeft: cx(5),tintColor: props.theme?.icon.primary}} />
246
+ </TouchableOpacity>}
247
+ </View>
248
+ <View style={styles.nodeList}>
249
+ {state.sceneInfo.nodes.map((node, index) => (
250
+ <DiySceneNodeView
251
+ key={index}
252
+ isCurrent={state.currentNode === index}
253
+ position={state.position}
254
+ topColor={node.top}
255
+ bottomColor={node.bottom}
256
+ onChangePosition={(position: 'Top' | 'Bottom') => {
257
+ state.currentNode = index
258
+ state.position = position
259
+ const color = state.sceneInfo.nodes[index];
260
+ state.h = position === 'Top' && color.top.h || color.bottom.h
261
+ state.s = Math.round((position === 'Top' && color.top.s || color.bottom.s) / 10)
262
+ }}
263
+ />
264
+ ))}
265
+ </View>
266
+ </Card>
267
+ }
268
+ <Card style={styles.adjustCard}>
269
+ <LdvSwitch
270
+ title={I18n.getLang('light_sources_tile_tw_lighting_headline')}
271
+ color={''}
272
+ colorAlpha={1}
273
+ enable={false}
274
+ setEnable={() => {}}
275
+ showSwitch={false}
276
+ />
277
+ {
278
+ state.sceneInfo.type === 'DIY' && <ColorAdjustView
279
+ reserveSV={true}
280
+ h={state.h}
281
+ s={state.s}
282
+ v={state.v}
283
+ onHSVChange={() => {}}
284
+ onHSVChangeComplete={(h, s, v) => {
285
+ state.h = h
286
+ state.s = s
287
+ state.v = v
288
+ state.sceneInfo.v = v * 10
289
+ const node = state.sceneInfo.nodes && state.sceneInfo.nodes[state.currentNode]
290
+ if (node) {
291
+ const color = { h: h, s: s * 10, v:1000 }
292
+ state.position === 'Top' && (node.top = color) || (node.bottom = color)
293
+ }
294
+ }} />
295
+ }
296
+ {
297
+ state.sceneInfo.type !== 'DIY' && <LdvSlider
298
+ title={I18n.getLang('light_sources_tile_rgb_lighting_brightness')}
299
+ min={1}
300
+ value={Math.round((state.sceneInfo.v || 1000) / 10)}
301
+ onValueChange={(v: number) => {state.sceneInfo.v = v * 10}}
302
+ onSlidingComplete={(v: number) => {state.sceneInfo.v = v * 10}}/>
303
+ }
304
+ <Spacer />
305
+ </Card>
306
+
307
+ {
308
+ state.sceneInfo.type !== 'Static' && <Card style={styles.adjustCard}>
309
+ <LdvSlider
310
+ title={I18n.getLang('add_new_dynamic_mood_ceiling_fan_field_text')}
311
+ value={state.sceneInfo.speed || 1}
312
+ min={1}
313
+ max={100}
314
+ onValueChange={(v: number) => {
315
+ state.sceneInfo.speed = v
316
+ }}
317
+ onSlidingComplete={(v: number) => {
318
+ state.sceneInfo.speed = v
319
+ }}
320
+ subTitleStr={`${(state.sceneInfo.speed || 1)}/100`}/>
321
+ </Card>
322
+ }
323
+
324
+ {(params.mode === 'edit' && state.sceneInfo.type === 'DIY') && (
325
+ <View style={{ marginTop: cx(20), marginHorizontal: cx(24) }}>
326
+ <TextButton
327
+ style={styles.deleteBtn}
328
+ textStyle={styles.deleteBtnText}
329
+ text={I18n.getLang('edit_static_mood_button_delete_text')}
330
+ onPress={() => {
331
+ showDialog({
332
+ method: 'confirm',
333
+ title: I18n.getLang('string_light_pp_dialog_sm_ed_headline_d'),
334
+ subTitle: I18n.getLang(`strip_light_static_mood_edit_dialog_text`),
335
+ onConfirm: async (_, { close }) => {
336
+ close();
337
+ state.loading = true;
338
+ const res = await params.sceneInfoOperation('del', state.sceneInfo);
339
+ state.loading = false;
340
+ if (res.success) {
341
+ navigation.navigate(ui_biz_routerKey.group_ui_biz_diy_scene_page);
342
+ }
343
+ }
344
+ })
345
+ }}
346
+ />
347
+ </View>
348
+ )}
349
+ <Spacer />
350
+ </View>
351
+ </ScrollView>
352
+ </Page>
353
+ );
354
+ };
355
+
356
+ export default withTheme(DiySceneEditorPage)
@@ -0,0 +1,281 @@
1
+ import React, {useCallback, useEffect, useMemo} from 'react';
2
+ import Page from '@ledvance/base/src/components/Page';
3
+ import {Utils} from 'tuya-panel-kit';
4
+ import {useDeviceInfo} from '@ledvance/base/src/models/modules/NativePropsSlice';
5
+ import {useReactive} from 'ahooks';
6
+ import I18n from '@ledvance/base/src/i18n';
7
+ import res from '@ledvance/base/src/res';
8
+ import {FlatList, Image, Platform, StyleSheet, TouchableOpacity, View} from 'react-native';
9
+ import Tag from '@ledvance/base/src/components/Tag';
10
+ import Spacer from '@ledvance/base/src/components/Spacer';
11
+ import InfoText from '@ledvance/base/src/components/InfoText';
12
+ import {useNavigation} from '@react-navigation/core';
13
+ import {showDialog} from '@ledvance/base/src/utils/common';
14
+ import ThemeType from '@ledvance/base/src/config/themeType'
15
+ import DiySceneItem from "@ledvance/base/src/components/DiySceneItem";
16
+ import {
17
+ useDiySceneId,
18
+ useMixSceneList,
19
+ useSceneData,
20
+ useSceneId,
21
+ useSceneStatus,
22
+ useSwitchLed,
23
+ useWorkMode
24
+ } from "./DiySceneActions";
25
+ import {cloneDeep, difference, head, range} from "lodash";
26
+ import {DiySceneInfo, SceneStatusType, WorkMode} from "@ledvance/base/src/utils/interface";
27
+ import {ui_biz_routerKey} from "../../navigation/Routers";
28
+
29
+
30
+ const cx = Utils.RatioUtils.convertX;
31
+ const { withTheme } = Utils.ThemeUtils
32
+
33
+ const MAX_MOOD_COUNT = 255;
34
+
35
+ const DiyScenePage = (props: { theme?: ThemeType }) => {
36
+ const deviceInfo = useDeviceInfo();
37
+ const [switchLed] = useSwitchLed()
38
+ const [workMode, setWorkMode] = useWorkMode()
39
+ const [sceneStatusId, setSceneStatus] = useSceneStatus()
40
+ const [sceneId] = useSceneId()
41
+ const [diySceneId] = useDiySceneId()
42
+ const [setSceneData] = useSceneData()
43
+ const [scenes, setScenes, resetMixScenes] = useMixSceneList()
44
+ const navigation = useNavigation();
45
+ const DEFAULT_SCENE: DiySceneInfo = {
46
+ id: -1,
47
+ type: 'DIY',
48
+ name: '',
49
+ speed: 50,
50
+ v: 1000,
51
+ nodes: [{ top: {h: 359, s: 1000, v: 1000}, bottom: {h: 120, s: 1000, v: 1000}}, { top: {h: 359, s: 1000, v: 1000}, bottom: {h: 120, s: 1000, v:1000}}]
52
+ }
53
+
54
+ const state = useReactive({
55
+ currentMood: undefined,
56
+ staticTagChecked: true,
57
+ dynamicTagChecked: true,
58
+ diyTagChecked: true,
59
+ showAddMoodPopover: false,
60
+ originScenes: cloneDeep(scenes) as DiySceneInfo[],
61
+ filterMoods: [] as DiySceneInfo[],
62
+ loading: false,
63
+ timerId: undefined as any,
64
+ flag: Symbol(),
65
+ });
66
+
67
+ const filterScenes = useMemo(() => {
68
+ return state.originScenes.filter(item => {
69
+ return [state.staticTagChecked, state.dynamicTagChecked, state.diyTagChecked].every(it => !it)
70
+ || (state.staticTagChecked && item.type === 'Static')
71
+ || (state.dynamicTagChecked && item.type === 'Dynamic')
72
+ || (state.diyTagChecked && item.type === 'DIY')
73
+ })
74
+ }, [JSON.stringify(state.originScenes), state.staticTagChecked, state.dynamicTagChecked, state.diyTagChecked])
75
+
76
+ const newSceneId = useMemo(() => {
77
+ const existsIds = state.originScenes.filter(it => it.type === 'DIY').map(it => it.id)
78
+ const idRange = range(1, 256);
79
+ const newId: number = head(difference(idRange, existsIds)) || 0;
80
+ return newId
81
+ }, [state.originScenes])
82
+
83
+ useEffect(() => {
84
+ if (sceneId) {
85
+ setSceneStatus(SceneStatusType.Scene, sceneId).then()
86
+ }
87
+ }, [sceneId])
88
+
89
+ useEffect(() => {
90
+ if (diySceneId && scenes.some(scene => scene.id === diySceneId)) {
91
+ setSceneStatus(SceneStatusType.DIY, diySceneId).then()
92
+ }
93
+ }, [diySceneId])
94
+
95
+ const navigationRoute = (mode: 'add' | 'edit' | 'del', currentScene?: DiySceneInfo) => {
96
+ navigation.navigate(ui_biz_routerKey.group_ui_biz_diy_scene_edit_page, {
97
+ mode,
98
+ currentScene,
99
+ nameRepeat,
100
+ sceneInfoOperation,
101
+ });
102
+ };
103
+
104
+ const getItemEnable = useCallback(
105
+ (sceneInfo: DiySceneInfo) => {
106
+ if (sceneStatusId !== -1) {
107
+ return sceneStatusId === sceneInfo.id && workMode === WorkMode.Scene && switchLed
108
+ }
109
+ return false
110
+ },
111
+ [workMode, switchLed, sceneStatusId]
112
+ );
113
+
114
+ const nameRepeat = useCallback((scene: DiySceneInfo) => {
115
+ return !!state.originScenes.filter(m => m.id !== scene.id).find(m => m.name === scene.name)
116
+ }, [state.originScenes])
117
+
118
+ const sceneInfoOperation = async (mode: 'add' | 'edit' | 'del' | 'set', currentScene: DiySceneInfo) => {
119
+ const checkedScene: DiySceneInfo = cloneDeep(currentScene);
120
+ if (mode === 'set') {
121
+ await setSceneStatus(checkedScene.type === 'DIY' ? SceneStatusType.DIY : SceneStatusType.Scene, checkedScene.id)
122
+ return setSceneData(checkedScene);
123
+ }
124
+ let newSceneList: DiySceneInfo[]
125
+ if (mode === 'add') {
126
+ checkedScene.id = newSceneId
127
+ newSceneList = [checkedScene, ...state.originScenes]
128
+ } else if (mode === 'del') {
129
+ newSceneList = state.originScenes.filter(item => item.id !== checkedScene.id)
130
+ } else {
131
+ newSceneList = state.originScenes.map(item => {
132
+ if (item.id === checkedScene.id) {
133
+ return checkedScene
134
+ }
135
+ return item
136
+ })
137
+ }
138
+ const scene = mode === 'del' ? (newSceneList.length === 0 ? undefined : newSceneList[0]) : checkedScene
139
+ const res = await setScenes(cloneDeep(newSceneList))
140
+ if (res.success) {
141
+ state.originScenes = cloneDeep(newSceneList);
142
+ if (scene) {
143
+ if (mode === 'del') {
144
+ if (currentScene.id !== sceneStatusId || !switchLed) {
145
+ return {
146
+ success: true,
147
+ };
148
+ }
149
+ }
150
+ setSceneData(scene).then(() => {
151
+ setSceneStatus(scene.type === 'DIY' ? SceneStatusType.DIY : SceneStatusType.Scene, scene.id).then()
152
+ })
153
+ } else {
154
+ if (workMode === WorkMode.Scene) {
155
+ setWorkMode(WorkMode.Colour).then()
156
+ }
157
+ }
158
+ return {
159
+ success: true,
160
+ };
161
+ } else {
162
+ return {
163
+ success: false,
164
+ };
165
+ }
166
+ }
167
+
168
+ const styles = StyleSheet.create({
169
+ tagLine: {
170
+ flexDirection: 'row',
171
+ marginHorizontal: cx(24),
172
+ },
173
+ infoLine: {
174
+ marginHorizontal: cx(24),
175
+ },
176
+ addMoodPopover: {
177
+ position: 'absolute',
178
+ right: cx(60),
179
+ top: Platform.OS === 'android' ? cx(90) : cx(130),
180
+ maxWidth: cx(200),
181
+ backgroundColor: props.theme?.card.background,
182
+ },
183
+ popoverItem: {
184
+ padding: cx(5),
185
+ alignItems: 'flex-start',
186
+ alignSelf: 'flex-start'
187
+ },
188
+ })
189
+
190
+ return (
191
+ <>
192
+ <Page
193
+ backText={deviceInfo.name}
194
+ headlineText={I18n.getLang('mood_overview_headline_text')}
195
+ headlineIcon={state.originScenes.length < MAX_MOOD_COUNT ? res.add : undefined}
196
+ onHeadlineIconClick={() => {
197
+ navigationRoute('add', cloneDeep(DEFAULT_SCENE))
198
+ }}
199
+ loading={state.loading}
200
+ >
201
+ <View style={styles.tagLine}>
202
+ <Tag
203
+ checked={state.staticTagChecked}
204
+ text={I18n.getLang('mood_overview_filter_name_text1')}
205
+ onCheckedChange={checked => {
206
+ state.staticTagChecked = checked;
207
+ }}
208
+ />
209
+ <Spacer width={cx(8)} height={0} />
210
+ <Tag
211
+ checked={state.dynamicTagChecked}
212
+ text={I18n.getLang('mood_overview_filter_name_text2')}
213
+ onCheckedChange={checked => {
214
+ state.dynamicTagChecked = checked;
215
+ }}
216
+ />
217
+ <Spacer width={cx(8)} height={0} />
218
+ <Tag
219
+ checked={state.diyTagChecked}
220
+ text={I18n.getLang('mood_overview_field_chip_diy')}
221
+ onCheckedChange={checked => {
222
+ state.diyTagChecked = checked;
223
+ }}
224
+ />
225
+ </View>
226
+ <TouchableOpacity style={{ alignItems: 'flex-end',paddingRight: cx(24) }}
227
+ onPress={() => {
228
+ showDialog({
229
+ method: 'confirm',
230
+ title: I18n.getLang('mood_resetbutton'),
231
+ subTitle: I18n.getLang('reset_mooddescription'),
232
+ onConfirm: async (_, { close }) => {
233
+ close()
234
+ resetMixScenes()
235
+ }
236
+ })
237
+ }}
238
+ >
239
+ <Image source={res.ic_refresh} style={{ width: cx(24), height: cx(24), tintColor: props.theme?.global.fontColor }} />
240
+ </TouchableOpacity>
241
+ <Spacer height={cx(10)} />
242
+ {state.originScenes.length >= MAX_MOOD_COUNT && (
243
+ <View style={styles.infoLine}>
244
+ <Spacer height={cx(10)} />
245
+ <InfoText
246
+ icon={res.ic_warning_amber}
247
+ text={I18n.getLang('mood_overview_warning_max_number_text')}
248
+ contentColor={props.theme?.global.warning}
249
+ />
250
+ <Spacer height={cx(6)} />
251
+ </View>
252
+ )}
253
+ <FlatList
254
+ data={filterScenes}
255
+ renderItem={({ item }) => {
256
+ return (
257
+ <DiySceneItem
258
+ enable={getItemEnable(item)}
259
+ scene={item}
260
+ onPress={() => {
261
+ navigationRoute('edit', item)
262
+ }}
263
+ onSwitch={async _ => {
264
+ state.loading = true;
265
+ await sceneInfoOperation('set', item);
266
+ state.loading = false;
267
+ }}
268
+ />
269
+ );
270
+ }}
271
+ ListHeaderComponent={() => <Spacer height={cx(10)} />}
272
+ ItemSeparatorComponent={() => <Spacer />}
273
+ ListFooterComponent={() => <Spacer />}
274
+ keyExtractor={item => `${item.name}`}
275
+ />
276
+ </Page>
277
+ </>
278
+ );
279
+ };
280
+
281
+ export default withTheme(DiyScenePage)
@@ -0,0 +1,25 @@
1
+ import {NavigationRoute} from "tuya-panel-kit";
2
+ import {ui_biz_routerKey} from "../../navigation/Routers";
3
+ import DiyScenePage from "./DiyScenePage";
4
+ import DiySceneEditorPage from "./DiySceneEditorPage";
5
+
6
+ const DiyScenePageRouters: NavigationRoute[] = [
7
+ {
8
+ name: ui_biz_routerKey.group_ui_biz_diy_scene_page,
9
+ component: DiyScenePage,
10
+ options: {
11
+ hideTopbar: true,
12
+ showOfflineView: false,
13
+ },
14
+ },
15
+ {
16
+ name: ui_biz_routerKey.group_ui_biz_diy_scene_edit_page,
17
+ component: DiySceneEditorPage,
18
+ options: {
19
+ hideTopbar: true,
20
+ showOfflineView: false,
21
+ },
22
+ },
23
+ ]
24
+
25
+ export default DiyScenePageRouters