@ledvance/ui-biz-bundle 1.1.163 → 1.1.164

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.1.163",
7
+ "version": "1.1.164",
8
8
  "scripts": {},
9
9
  "dependencies": {
10
10
  "@ledvance/base": "^1.x",
@@ -242,26 +242,37 @@ const BiorhythmPage = (props: { theme?: ThemeType }) => {
242
242
  <Page
243
243
  backText={deviceInfo.name}
244
244
  onBackClick={navigation.goBack}
245
- headlineTopContent={<View style={{ flexDirection: 'row', width: '100%', justifyContent: 'space-between' }}>
246
- <DeleteButton style={{flex: 1}} text={I18n.getLang('biorhythm_save_as')} onPress={() => {
247
- Dialog.prompt({
248
- title: I18n.getLang('biorhythm_save_title'),
249
- placeholder: I18n.getLang('biorhythm_save_placeholder'),
250
- defaultValue: `${deviceInfo.name}`,
251
- cancelText: I18n.getLang('auto_scan_system_cancel'),
252
- confirmText: I18n.getLang('auto_scan_system_wifi_confirm'),
253
- inputWrapperStyle: {backgroundColor: props.theme?.textInput.background, borderRadius: cx(10)},
254
- autoFocus: true,
255
- onConfirm: (data, { close }) => {
256
- saveStorageBiorhythms(data, state.enable, state.gradient, state.weeks, state.planList)
257
- close()
258
- }
259
- })
260
- }} />
261
- <DeleteButton style={{flex: 1}} text={I18n.getLang('biorhythm_load')} onPress={() => {
262
- setBiorhythmListVisible(true)
263
- }} />
264
- </View>}
245
+ headlineTopContent={
246
+ <View style={{flexDirection: 'row', justifyContent: 'flex-end'}}>
247
+ <TouchableOpacity
248
+ style={{paddingLeft: cx(16)}}
249
+ onPress={() => {
250
+ Dialog.prompt({
251
+ title: I18n.getLang('biorhythm_save_title'),
252
+ placeholder: I18n.getLang('biorhythm_save_placeholder'),
253
+ defaultValue: `${deviceInfo.name}`,
254
+ cancelText: I18n.getLang('auto_scan_system_cancel'),
255
+ confirmText: I18n.getLang('auto_scan_system_wifi_confirm'),
256
+ inputWrapperStyle: {backgroundColor: props.theme?.textInput.background, borderRadius: cx(10)},
257
+ autoFocus: true,
258
+ onConfirm: (data, { close }) => {
259
+ saveStorageBiorhythms(data, state.enable, state.gradient, state.weeks, state.planList)
260
+ close()
261
+ }
262
+ })
263
+ }}
264
+ >
265
+ <Image source={res.icon_save} style={{ width: cx(24), height: cx(24), tintColor: props.theme?.global.fontColor }} />
266
+ </TouchableOpacity>
267
+ <TouchableOpacity
268
+ style={{paddingLeft: cx(16)}}
269
+ onPress={() => {
270
+ setBiorhythmListVisible(true)
271
+ }}
272
+ >
273
+ <Image source={res.icon_import} style={{ width: cx(24), height: cx(24), tintColor: props.theme?.global.fontColor }} />
274
+ </TouchableOpacity>
275
+ </View>}
265
276
  headlineText={I18n.getLang('add_new_trigger_time_system_back_text')}
266
277
  headlineIconContent={<Switch
267
278
  value={state.enable}
@@ -189,6 +189,9 @@ const DiyScenePage = (props: { theme?: ThemeType }) => {
189
189
  infoLine: {
190
190
  marginHorizontal: cx(24),
191
191
  },
192
+ rightIconView: {
193
+ flexDirection: 'row'
194
+ },
192
195
  addMoodPopover: {
193
196
  position: 'absolute',
194
197
  right: cx(60),
@@ -201,6 +204,9 @@ const DiyScenePage = (props: { theme?: ThemeType }) => {
201
204
  alignItems: 'flex-start',
202
205
  alignSelf: 'flex-start'
203
206
  },
207
+ refresh: {
208
+ paddingLeft: cx(24)
209
+ },
204
210
  })
205
211
 
206
212
  return (
@@ -208,10 +214,33 @@ const DiyScenePage = (props: { theme?: ThemeType }) => {
208
214
  <Page
209
215
  backText={deviceInfo.name}
210
216
  headlineText={I18n.getLang('mood_overview_headline_text')}
211
- headlineIcon={state.originScenes.length < MAX_MOOD_COUNT ? res.add : undefined}
212
- onHeadlineIconClick={() => {
213
- navigationRoute('add', cloneDeep(DEFAULT_SCENE))
214
- }}
217
+ headlineIconContent={<View style={styles.rightIconView}>
218
+ <TouchableOpacity
219
+ style={styles.refresh}
220
+ onPress={() => {
221
+ showDialog({
222
+ method: 'confirm',
223
+ title: I18n.getLang('mood_resetbutton'),
224
+ subTitle: I18n.getLang('reset_mooddescription'),
225
+ onConfirm: async (_, { close }) => {
226
+ close()
227
+ await getRemoteMixSceneInfo(true)
228
+ }
229
+ })
230
+ }}
231
+ >
232
+ <Image source={{uri: res.ic_refresh}} style={{ width: cx(24), height: cx(24), tintColor: props.theme?.global.fontColor }} />
233
+ </TouchableOpacity>
234
+ {state.originScenes.length < MAX_MOOD_COUNT && <TouchableOpacity
235
+ style={styles.refresh}
236
+ onPress={() => {
237
+ navigationRoute('add', cloneDeep(DEFAULT_SCENE))
238
+ }}
239
+ >
240
+ <Image source={{uri: res.add}} style={{ width: cx(24), height: cx(24), tintColor: props.theme?.global.brand }} />
241
+ </TouchableOpacity>
242
+ }
243
+ </View>}
215
244
  loading={state.loading}
216
245
  >
217
246
  <View style={styles.tagLine}>
@@ -239,21 +268,6 @@ const DiyScenePage = (props: { theme?: ThemeType }) => {
239
268
  }}
240
269
  />
241
270
  </View>
242
- <TouchableOpacity style={{ alignItems: 'flex-end',paddingRight: cx(24) }}
243
- onPress={() => {
244
- showDialog({
245
- method: 'confirm',
246
- title: I18n.getLang('mood_resetbutton'),
247
- subTitle: I18n.getLang('reset_mooddescription'),
248
- onConfirm: async (_, { close }) => {
249
- close()
250
- await getRemoteMixSceneInfo(true)
251
- }
252
- })
253
- }}
254
- >
255
- <Image source={{uri: res.ic_refresh}} style={{ width: cx(24), height: cx(24), tintColor: props.theme?.global.fontColor }} />
256
- </TouchableOpacity>
257
271
  <Spacer height={cx(10)} />
258
272
  {state.originScenes.length >= MAX_MOOD_COUNT && (
259
273
  <View style={styles.infoLine}>
@@ -78,8 +78,6 @@ const BarChartWithTouch = (props: BarChartProps) => {
78
78
  rotate: 45,
79
79
  align: 'right',
80
80
  verticalAlign: 'top',
81
- showMinLabel: true,
82
- showMaxLabel: true,
83
81
  }
84
82
  },
85
83
  yAxis: [
@@ -498,6 +498,55 @@ function getStringLightSceneList(): RemoteMoodInfo[] {
498
498
  t: 0,
499
499
  e: false,
500
500
  },
501
+ {
502
+ n: I18n.getLang('strip_lights_mood_text45'),
503
+ i: '0125101e1e0000003700a032000000003700c3640000000037011364000000003700782800000000',
504
+ s: '',
505
+ t: 0,
506
+ e: false,
507
+ },
508
+ {
509
+ n: I18n.getLang('strip_lights_mood_text46'),
510
+ i: '01261014140000002d00174a000000002d002348000000002d001e24000000002d00014000000000',
511
+ s: '',
512
+ t: 0,
513
+ e: false,
514
+ },
515
+ {
516
+ n: I18n.getLang('strip_lights_mood_text47'),
517
+ i: '01270a555500000055012c64000000005500b4640000000055010f51000000005501485c00000000',
518
+ s: '',
519
+ t: 0,
520
+ e: false,
521
+ },
522
+ {
523
+ n: I18n.getLang('strip_lights_mood_text48'),
524
+ i: '01281028280000003700d258000000003700b564000000003700b152000000003700f06400000000',
525
+ s: '',
526
+ t: 0,
527
+ e: false,
528
+ },
529
+ {
530
+ n: I18n.getLang('strip_lights_mood_text49'),
531
+ i: '0129100f0f0000002300784c000000002300504b0000000023005238000000002300545200000000',
532
+ s: '',
533
+ t: 0,
534
+ e: false,
535
+ },
536
+ {
537
+ n: I18n.getLang('strip_lights_mood_text50'),
538
+ i: '012a0a5050000000640000640000000064007864000000006400f0640000000064003c640000000064012c6400000000',
539
+ s: '',
540
+ t: 0,
541
+ e: false,
542
+ },
543
+ {
544
+ n: I18n.getLang('strip_lights_mood_text51'),
545
+ i: '012b1032320000001e00f04e000000001e011364000000001e00b42900000000',
546
+ s: '',
547
+ t: 0,
548
+ e: false,
549
+ },
501
550
  ];
502
551
  }
503
552
 
@@ -811,6 +860,55 @@ function getStripLightSceneList(): RemoteMoodInfo[] {
811
860
  t: 0,
812
861
  e: false,
813
862
  },
863
+ {
864
+ n: I18n.getLang('strip_lights_mood_text45'),
865
+ i: '013b011e1e6000003700a03200c364011364007828',
866
+ s: '',
867
+ t: 0,
868
+ e: false,
869
+ },
870
+ {
871
+ n: I18n.getLang('strip_lights_mood_text46'),
872
+ i: '013c0114146000002d00174a002348001e24000140',
873
+ s: '',
874
+ t: 0,
875
+ e: false,
876
+ },
877
+ {
878
+ n: I18n.getLang('strip_lights_mood_text47'),
879
+ i: '013d02555560000055012c6400b464010f5101485c',
880
+ s: '',
881
+ t: 0,
882
+ e: false,
883
+ },
884
+ {
885
+ n: I18n.getLang('strip_lights_mood_text48'),
886
+ i: '013e0128286000003700d25800b56400b15200f064',
887
+ s: '',
888
+ t: 0,
889
+ e: false,
890
+ },
891
+ {
892
+ n: I18n.getLang('strip_lights_mood_text49'),
893
+ i: '013f010f0f6000002300784c00504b005238005452',
894
+ s: '',
895
+ t: 0,
896
+ e: false,
897
+ },
898
+ {
899
+ n: I18n.getLang('strip_lights_mood_text50'),
900
+ i: '01400250506000006400006400786400f064003c64012c64',
901
+ s: '',
902
+ t: 0,
903
+ e: false,
904
+ },
905
+ {
906
+ n: I18n.getLang('strip_lights_mood_text51'),
907
+ i: '01410132326000001e00f04e01136400b429',
908
+ s: '',
909
+ t: 0,
910
+ e: false,
911
+ },
814
912
  ];
815
913
  }
816
914
 
@@ -1152,6 +1250,55 @@ function getMixCeilingLightList(): RemoteMoodInfo[] {
1152
1250
  t: 0,
1153
1251
  e: false,
1154
1252
  },
1253
+ {
1254
+ n: I18n.getLang('strip_lights_mood_text45'),
1255
+ i: '040d0d0100000000000003e800000d0d0100000000000003e80000',
1256
+ s: '013b011e1e6000003700a03200c364011364007828',
1257
+ t: 0,
1258
+ e: false,
1259
+ },
1260
+ {
1261
+ n: I18n.getLang('strip_lights_mood_text46'),
1262
+ i: '040d0d0100000000000003e800000d0d0100000000000003e80000',
1263
+ s: '013c0114146000002d00174a002348001e24000140',
1264
+ t: 0,
1265
+ e: false,
1266
+ },
1267
+ {
1268
+ n: I18n.getLang('strip_lights_mood_text47'),
1269
+ i: '040d0d0100000000000003e800000d0d0100000000000003e80000',
1270
+ s: '013d02555560000055012c6400b464010f5101485c',
1271
+ t: 0,
1272
+ e: false,
1273
+ },
1274
+ {
1275
+ n: I18n.getLang('strip_lights_mood_text48'),
1276
+ i: '040d0d0100000000000003e800000d0d0100000000000003e80000',
1277
+ s: '013e0128286000003700d25800b56400b15200f064',
1278
+ t: 0,
1279
+ e: false,
1280
+ },
1281
+ {
1282
+ n: I18n.getLang('strip_lights_mood_text49'),
1283
+ i: '040d0d0100000000000003e800000d0d0100000000000003e80000',
1284
+ s: '013f010f0f6000002300784c00504b005238005452',
1285
+ t: 0,
1286
+ e: false,
1287
+ },
1288
+ {
1289
+ n: I18n.getLang('strip_lights_mood_text50'),
1290
+ i: '040d0d0100000000000003e800000d0d0100000000000003e80000',
1291
+ s: '01400250506000006400006400786400f064003c64012c64',
1292
+ t: 0,
1293
+ e: false,
1294
+ },
1295
+ {
1296
+ n: I18n.getLang('strip_lights_mood_text51'),
1297
+ i: '040d0d0100000000000003e800000d0d0100000000000003e80000',
1298
+ s: '01410132326000001e00f04e01136400b429',
1299
+ t: 0,
1300
+ e: false,
1301
+ },
1155
1302
  ];
1156
1303
  }
1157
1304
 
@@ -1400,6 +1547,55 @@ const defColorSceneList: RemoteMoodInfo[] = [
1400
1547
  t: 0,
1401
1548
  e: false,
1402
1549
  },
1550
+ {
1551
+ n: I18n.getLang('strip_lights_mood_text45'),
1552
+ i: '251e1e0200a001f40226000000001e1e0200c303e80226000000001e1e02011303e80226000000001e1e0200780190022600000000',
1553
+ s: '',
1554
+ t: 0,
1555
+ e: false,
1556
+ },
1557
+ {
1558
+ n: I18n.getLang('strip_lights_mood_text46'),
1559
+ i: '26141402001702e401c200000000141402002302d001c200000000141402001e016801c2000000001414020001028001c200000000',
1560
+ s: '',
1561
+ t: 0,
1562
+ e: false,
1563
+ },
1564
+ {
1565
+ n: I18n.getLang('strip_lights_mood_text47'),
1566
+ i: '27555501012c03e803520000000055550100b403e8035200000000555501010f032a03520000000055550101480398035200000000',
1567
+ s: '',
1568
+ t: 0,
1569
+ e: false,
1570
+ },
1571
+ {
1572
+ n: I18n.getLang('strip_lights_mood_text48'),
1573
+ i: '2828280200d2037002260000000028280200b503e802260000000028280200b1033402260000000028280200f003e8022600000000',
1574
+ s: '',
1575
+ t: 0,
1576
+ e: false,
1577
+ },
1578
+ {
1579
+ n: I18n.getLang('strip_lights_mood_text49'),
1580
+ i: '290f0f02007802f8015e000000000f0f02005002ee015e000000000f0f0200520230015e000000000f0f0200540334015e00000000',
1581
+ s: '',
1582
+ t: 0,
1583
+ e: false,
1584
+ },
1585
+ {
1586
+ n: I18n.getLang('strip_lights_mood_text50'),
1587
+ i: '2a505001000003e803e800000000505001007803e803e80000000050500100f003e803e800000000505001003c03e803e800000000505001012c03e803e800000000',
1588
+ s: '',
1589
+ t: 0,
1590
+ e: false,
1591
+ },
1592
+ {
1593
+ n: I18n.getLang('strip_lights_mood_text51'),
1594
+ i: '2b32320200f0030c012c00000000323202011303e8012c0000000032320200b4019a012c00000000',
1595
+ s: '',
1596
+ t: 0,
1597
+ e: false,
1598
+ },
1403
1599
  ];
1404
1600
 
1405
1601
  const defMixColorSceneList: MixRemoteMoodInfo[] = [
@@ -1553,6 +1749,41 @@ const defMixColorSceneList: MixRemoteMoodInfo[] = [
1553
1749
  image: '',
1554
1750
  value: '002400000103034b4b0200d203e803e84b4b0200b403e803e84b4b02009603e803e8',
1555
1751
  },
1752
+ {
1753
+ name: I18n.getLang('strip_lights_mood_text45'),
1754
+ image: '',
1755
+ value: '002500000104031e1e0200a001f402261e1e0200c303e802261e1e02011303e802261e1e02007801900226',
1756
+ },
1757
+ {
1758
+ name: I18n.getLang('strip_lights_mood_text46'),
1759
+ image: '',
1760
+ value: '00260000010403141402001702e401c2141402002302d001c2141402001e016801c21414020001028001c2',
1761
+ },
1762
+ {
1763
+ name: I18n.getLang('strip_lights_mood_text47'),
1764
+ image: '',
1765
+ value: '00270000010403555501012c03e8035255550100b403e80352555501010f032a0352555501014803980352',
1766
+ },
1767
+ {
1768
+ name: I18n.getLang('strip_lights_mood_text48'),
1769
+ image: '',
1770
+ value: '0028000001040328280200d20370022628280200b503e8022628280200b10334022628280200f003e80226',
1771
+ },
1772
+ {
1773
+ name: I18n.getLang('strip_lights_mood_text49'),
1774
+ image: '',
1775
+ value: '002900000104030f0f02007802f8015e0f0f02005002ee015e0f0f0200520230015e0f0f0200540334015e',
1776
+ },
1777
+ {
1778
+ name: I18n.getLang('strip_lights_mood_text50'),
1779
+ image: '',
1780
+ value: '002a0000010503505001000003e803e8505001007803e803e850500100f003e803e8505001003c03e803e8505001012c03e803e8',
1781
+ },
1782
+ {
1783
+ name: I18n.getLang('strip_lights_mood_text51'),
1784
+ image: '',
1785
+ value: '002b000001030332320200f0030c012c323202011303e8012c32320200b4019a012c',
1786
+ },
1556
1787
  ];
1557
1788
 
1558
1789
  export type RecommendMood = {
@@ -6,6 +6,7 @@ import {
6
6
  useDeviceId,
7
7
  useDeviceInfo,
8
8
  useFlagMode,
9
+ useIsPad,
9
10
  useMoods,
10
11
  } from '@ledvance/base/src/models/modules/NativePropsSlice';
11
12
  import { useReactive } from 'ahooks';
@@ -30,19 +31,14 @@ import I18n from '@ledvance/base/src/i18n';
30
31
  import ThemeType from '@ledvance/base/src/config/themeType'
31
32
 
32
33
 
33
- const { convertX: cx, width: screenWidth } = Utils.RatioUtils;
34
+ const { convertX: cx } = Utils.RatioUtils;
34
35
  const { withTheme } = Utils.ThemeUtils
35
36
 
36
37
  const MAX_MOOD_COUNT = 255;
37
- // --- 动态计算项目宽度 ---
38
- // 1. 定义网格的边距和列间距
39
- const GRID_HORIZONTAL_PADDING = cx(24);
38
+
39
+ // --- 关键修改 1: 定义新的布局常量 ---
40
+ const OPTIMAL_ITEM_WIDTH = cx(165); // 定义一个在所有设备上看起来都很好的“最佳宽度”
40
41
  const GRID_GAP = cx(16);
41
- const NUM_COLUMNS = 2;
42
- // 2. 计算每个 MoodItem 的宽度
43
- // (屏幕总宽度 - 两边的边距 - (列数 - 1) * 列间距) / 列数
44
- const ITEM_WIDTH =
45
- (screenWidth - GRID_HORIZONTAL_PADDING * 2 - (NUM_COLUMNS - 1) * GRID_GAP) / NUM_COLUMNS;
46
42
 
47
43
  const MoodPage = (props: { theme?: ThemeType }) => {
48
44
  const params = useParams<MoodPageParams>();
@@ -60,6 +56,7 @@ const MoodPage = (props: { theme?: ThemeType }) => {
60
56
  isSupportSceneStatus: params.isSupportSceneStatus,
61
57
  sceneStatusType: SceneStatusType.Mood
62
58
  });
59
+ const isPad = useIsPad(); // 使用 isPad hook
63
60
 
64
61
  const state = useReactive<MoodPageState>({
65
62
  currentMood: undefined,
@@ -73,6 +70,28 @@ const MoodPage = (props: { theme?: ThemeType }) => {
73
70
  flag: Symbol(),
74
71
  });
75
72
 
73
+ // --- 关键修改 2: 基于 isPad 决定列数,并计算出 FlatList 自身所需的总宽度 ---
74
+ const { numColumns, flatListWidth } = useMemo(() => {
75
+ const cols = isPad ? 3 : 2;
76
+ const listWidth = cols * OPTIMAL_ITEM_WIDTH + (cols - 1) * GRID_GAP;
77
+ return {
78
+ numColumns: cols,
79
+ flatListWidth: listWidth,
80
+ };
81
+ }, [isPad]);
82
+
83
+ // --- 关键修改 3: 准备幽灵元素数据 ---
84
+ const gridData = useMemo(() => {
85
+ const data = state.filterMoods;
86
+ const numToPad = numColumns - (data.length % numColumns);
87
+ if (numToPad === numColumns) {
88
+ return data;
89
+ }
90
+ const ghostItems = Array.from({ length: numToPad }, (_, i) => ({ name: `ghost-${i}`, isGhost: true }));
91
+ return [...data, ...ghostItems];
92
+ }, [state.filterMoods, numColumns]);
93
+
94
+ // ... (其余所有业务逻辑和状态管理保持不变) ...
76
95
  const moodIds = useMemo(() => {
77
96
  // @ts-ignore
78
97
  const mainIds = map(params.isCeilingLight ? (state.originMoods.map(m => m.mainLamp) || []) : state.originMoods, 'id').filter(v => v !== undefined)
@@ -316,6 +335,9 @@ const MoodPage = (props: { theme?: ThemeType }) => {
316
335
  infoLine: {
317
336
  marginHorizontal: cx(24),
318
337
  },
338
+ rightIconView: {
339
+ flexDirection: 'row'
340
+ },
319
341
  addMoodPopover: {
320
342
  position: 'absolute',
321
343
  right: cx(60),
@@ -329,12 +351,16 @@ const MoodPage = (props: { theme?: ThemeType }) => {
329
351
  alignSelf: 'flex-start'
330
352
  },
331
353
  refresh: {
332
- alignItems: 'flex-end',
333
- paddingRight: cx(24)
354
+ paddingLeft: cx(24)
334
355
  },
335
356
  columnWrapperStyle: {
336
357
  justifyContent: 'space-between',
337
358
  },
359
+ // --- 关键修改 4: 新增列表容器样式 ---
360
+ listContainer: {
361
+ flex: 1,
362
+ alignItems: 'center', // 让内部的 FlatList 水平居中
363
+ },
338
364
  })
339
365
 
340
366
  return (
@@ -342,14 +368,37 @@ const MoodPage = (props: { theme?: ThemeType }) => {
342
368
  <Page
343
369
  backText={deviceInfo.name}
344
370
  headlineText={Strings.getLang('mood_overview_headline_text')}
345
- headlineIcon={state.originMoods.length < MAX_MOOD_COUNT ? res.add : undefined}
346
- onHeadlineIconClick={() => {
347
- if (params.isStringLight || params.isStripLight) {
348
- onAddMoodDialogItemClick(false, 1);
349
- } else {
350
- state.showAddMoodPopover = !state.showAddMoodPopover;
371
+ headlineIconContent={<View style={styles.rightIconView}>
372
+ <TouchableOpacity
373
+ style={styles.refresh}
374
+ onPress={() => {
375
+ showDialog({
376
+ method: 'confirm',
377
+ title: I18n.getLang('mood_resetbutton'),
378
+ subTitle: I18n.getLang('reset_mooddescription'),
379
+ onConfirm: async (_, { close }) => {
380
+ close()
381
+ await getRemoteMoodInfo(true)
382
+ }
383
+ })
384
+ }}
385
+ >
386
+ <Image source={{uri: res.ic_refresh}} style={{ width: cx(24), height: cx(24), tintColor: props.theme?.global.fontColor }} />
387
+ </TouchableOpacity>
388
+ {state.originMoods.length < MAX_MOOD_COUNT && <TouchableOpacity
389
+ style={styles.refresh}
390
+ onPress={() => {
391
+ if (params.isStringLight || params.isStripLight) {
392
+ onAddMoodDialogItemClick(false, 1);
393
+ } else {
394
+ state.showAddMoodPopover = !state.showAddMoodPopover;
395
+ }
396
+ }}
397
+ >
398
+ <Image source={{uri: res.add}} style={{ width: cx(24), height: cx(24), tintColor: props.theme?.global.brand }} />
399
+ </TouchableOpacity>
351
400
  }
352
- }}
401
+ </View>}
353
402
  loading={state.loading}
354
403
  >
355
404
  {!(params.isStringLight || params.isStripLight) && <View style={styles.tagLine}>
@@ -369,22 +418,6 @@ const MoodPage = (props: { theme?: ThemeType }) => {
369
418
  }}
370
419
  />
371
420
  </View>}
372
- <TouchableOpacity
373
- style={styles.refresh}
374
- onPress={() => {
375
- showDialog({
376
- method: 'confirm',
377
- title: I18n.getLang('mood_resetbutton'),
378
- subTitle: I18n.getLang('reset_mooddescription'),
379
- onConfirm: async (_, { close }) => {
380
- close()
381
- await getRemoteMoodInfo(true)
382
- }
383
- })
384
- }}
385
- >
386
- <Image source={{uri: res.ic_refresh}} style={{ width: cx(24), height: cx(24), tintColor: props.theme?.global.fontColor }} />
387
- </TouchableOpacity>
388
421
  <Spacer height={cx(10)} />
389
422
  {state.originMoods.length >= MAX_MOOD_COUNT && (
390
423
  <View style={styles.infoLine}>
@@ -397,44 +430,45 @@ const MoodPage = (props: { theme?: ThemeType }) => {
397
430
  <Spacer height={cx(6)} />
398
431
  </View>
399
432
  )}
400
- <FlatList
401
- data={state.filterMoods}
402
- // 关键属性 1: 设置列数
403
- numColumns={NUM_COLUMNS}
404
- // 关键属性 2: 为 FlatList 提供一个唯一的 key,当列数改变时强制刷新
405
- key={NUM_COLUMNS}
406
- // 关键属性 3: 设置整个列表容器的样式,主要是左右边距
407
- contentContainerStyle={{
408
- paddingHorizontal: GRID_HORIZONTAL_PADDING,
409
- }}
410
- // 关键属性 4: 设置行包装器的样式,用于在列之间创建间距
411
- columnWrapperStyle={styles.columnWrapperStyle}
412
- renderItem={({ item }) => {
413
- return (
414
- <MoodItem
415
- // 关键修改:通过 style prop 传入计算好的宽度
416
- style={{ width: ITEM_WIDTH }}
417
- enable={getItemEnable(item)}
418
- isMix={!!(params.isMixLight || params.isCeilingLight)}
419
- mood={item}
420
- deviceTypeOption={params}
421
- onPress={() => {
422
- navigationRoute(item.mainLamp.nodes.length === 1, 'edit', item);
423
- }}
424
- onSwitch={async _ => {
425
- state.loading = true;
426
- await modDeleteMood('set', item);
427
- updateFlagMode();
428
- state.loading = false;
429
- }}
430
- />
431
- );
432
- }}
433
- ListHeaderComponent={() => <Spacer height={cx(10)} />}
434
- ItemSeparatorComponent={() => <Spacer />}
435
- ListFooterComponent={() => <Spacer />}
436
- keyExtractor={item => `${item.name}`}
437
- />
433
+
434
+ {/* --- 关键修改 5: 应用新的 FlatList 布局 --- */}
435
+ <View style={styles.listContainer}>
436
+ <FlatList
437
+ data={gridData}
438
+ numColumns={numColumns}
439
+ key={numColumns}
440
+ style={{ width: flatListWidth }}
441
+ columnWrapperStyle={styles.columnWrapperStyle}
442
+ renderItem={({ item }) => {
443
+ if (item.isGhost) {
444
+ return <View style={{ width: OPTIMAL_ITEM_WIDTH, marginBottom: cx(16) }} />;
445
+ }
446
+
447
+ return (
448
+ <MoodItem
449
+ style={{ width: OPTIMAL_ITEM_WIDTH }}
450
+ enable={getItemEnable(item)}
451
+ isMix={!!(params.isMixLight || params.isCeilingLight)}
452
+ mood={item}
453
+ deviceTypeOption={params}
454
+ onPress={() => {
455
+ navigationRoute(item.mainLamp.nodes.length === 1, 'edit', item);
456
+ }}
457
+ onSwitch={async _ => {
458
+ state.loading = true;
459
+ await modDeleteMood('set', item);
460
+ updateFlagMode();
461
+ state.loading = false;
462
+ }}
463
+ />
464
+ );
465
+ }}
466
+ ListHeaderComponent={() => <Spacer height={cx(10)} />}
467
+ ItemSeparatorComponent={() => <Spacer />}
468
+ ListFooterComponent={() => <Spacer />}
469
+ keyExtractor={item => `${item.name}`}
470
+ />
471
+ </View>
438
472
  </Page>
439
473
  <CustomListDialog
440
474
  show={state.showAddMoodPopover}
@@ -459,4 +493,4 @@ const MoodPage = (props: { theme?: ThemeType }) => {
459
493
  );
460
494
  };
461
495
 
462
- export default withTheme(MoodPage)
496
+ export default withTheme(MoodPage)
@@ -450,7 +450,7 @@ const TimeScheduleDetailPage = (props: { theme?: ThemeType }) => {
450
450
  }}
451
451
  />
452
452
  <Spacer />
453
- <Text style={{ ...styles.cardContainer, color: props.theme?.global.fontColor, fontSize: cx(14) }}>{loopText(state.timeSchedule.loops.split(''))}</Text>
453
+ <Text style={{ ...styles.cardContainer, color: props.theme?.global.fontColor, fontSize: cx(14) }}>{loopText(state.timeSchedule.loops.split(''), state.timeSchedule.time)}</Text>
454
454
  <Spacer height={cx(30)} />
455
455
 
456
456
  {/* Apply for */}