@focus8/settings-registry 0.5.0 → 0.7.0
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/dist/index.d.ts +45 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +509 -118
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +728 -53
package/src/index.ts
CHANGED
|
@@ -77,6 +77,47 @@ export type AllDayPreset = {
|
|
|
77
77
|
time: string;
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// UI type discriminator — determines which component renders each setting
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
export type SettingUiType =
|
|
85
|
+
| 'TOGGLE'
|
|
86
|
+
| 'SELECT'
|
|
87
|
+
| 'VOLUME_SLIDER'
|
|
88
|
+
| 'SLIDER'
|
|
89
|
+
| 'NUMBER_INPUT'
|
|
90
|
+
| 'TEXT_INPUT'
|
|
91
|
+
| 'PIN_INPUT'
|
|
92
|
+
| 'CUSTOM_THEME_PICKER'
|
|
93
|
+
| 'CUSTOM_LANGUAGE_PICKER'
|
|
94
|
+
| 'CUSTOM_CALENDAR_TYPE'
|
|
95
|
+
| 'CUSTOM_CLOCK_TYPE'
|
|
96
|
+
| 'CUSTOM_WEATHER_LOCATION'
|
|
97
|
+
| 'CUSTOM_IMAGE'
|
|
98
|
+
| 'CUSTOM_IMAGE_ARRAY'
|
|
99
|
+
| 'CUSTOM_CALENDAR_IDS'
|
|
100
|
+
| 'CUSTOM_REMINDER_PRESETS'
|
|
101
|
+
| 'CUSTOM_EVENT_FORM'
|
|
102
|
+
| 'CUSTOM_CHRONOLOGICAL_EVENT_FORM'
|
|
103
|
+
| 'CUSTOM_DISPLAY_DENSITY'
|
|
104
|
+
| 'CUSTOM_BRIGHTNESS'
|
|
105
|
+
| 'CUSTOM_SPLIT_VIEW_CONFIG'
|
|
106
|
+
| 'HIDDEN';
|
|
107
|
+
|
|
108
|
+
export type SettingOption<T = unknown> = {
|
|
109
|
+
/** The option value */
|
|
110
|
+
value: T;
|
|
111
|
+
/** i18n message key for the option label */
|
|
112
|
+
labelKey: string;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export type SliderConfig = {
|
|
116
|
+
min: number;
|
|
117
|
+
max: number;
|
|
118
|
+
step: number;
|
|
119
|
+
};
|
|
120
|
+
|
|
80
121
|
// ---------------------------------------------------------------------------
|
|
81
122
|
// Setting categories — used for UI grouping and profile organization
|
|
82
123
|
// ---------------------------------------------------------------------------
|
|
@@ -219,6 +260,8 @@ export type SettingsGroupDef = {
|
|
|
219
260
|
keys: string[];
|
|
220
261
|
/** Only show for this calendar type (undefined = always) */
|
|
221
262
|
calendarType?: CalendarType;
|
|
263
|
+
/** Only show for this app mode (undefined = always) */
|
|
264
|
+
appMode?: 'ENROLLED';
|
|
222
265
|
};
|
|
223
266
|
|
|
224
267
|
/**
|
|
@@ -242,21 +285,18 @@ export const SETTINGS_GROUPS: readonly SettingsGroupDef[] = [
|
|
|
242
285
|
id: 'calendarType',
|
|
243
286
|
labelKey: 'Settings.CalendarType',
|
|
244
287
|
icon: 'ArrowLeftRight',
|
|
245
|
-
keys: ['calendarView.type'],
|
|
288
|
+
keys: ['calendarView.type', 'calendarView.view'],
|
|
246
289
|
},
|
|
247
290
|
{
|
|
248
291
|
id: 'calendarView',
|
|
249
292
|
labelKey: 'Settings.CalendarView',
|
|
250
293
|
icon: 'Eye',
|
|
251
294
|
keys: [
|
|
252
|
-
'calendarView.view',
|
|
253
|
-
'calendarView.dayViewZoom',
|
|
254
|
-
'calendarView.weekViewZoom',
|
|
255
|
-
'calendarView.splitView',
|
|
256
295
|
'calendarView.showCalendarNames',
|
|
296
|
+
'calendarView.splitView',
|
|
257
297
|
'calendarView.calendarColumns',
|
|
258
|
-
'calendarView.
|
|
259
|
-
'calendarView.
|
|
298
|
+
'calendarView.dayViewZoom',
|
|
299
|
+
'calendarView.weekViewZoom',
|
|
260
300
|
],
|
|
261
301
|
},
|
|
262
302
|
{
|
|
@@ -301,12 +341,14 @@ export const SETTINGS_GROUPS: readonly SettingsGroupDef[] = [
|
|
|
301
341
|
'sound.timerAlarmTimeout',
|
|
302
342
|
'timer.',
|
|
303
343
|
],
|
|
344
|
+
appMode: 'ENROLLED',
|
|
304
345
|
},
|
|
305
346
|
{
|
|
306
347
|
id: 'lockScreen',
|
|
307
348
|
labelKey: 'Settings.LockScreen',
|
|
308
349
|
icon: 'Lock',
|
|
309
350
|
keys: ['lockScreen.'],
|
|
351
|
+
appMode: 'ENROLLED',
|
|
310
352
|
},
|
|
311
353
|
{
|
|
312
354
|
id: 'touch',
|
|
@@ -325,7 +367,11 @@ export const SETTINGS_GROUPS: readonly SettingsGroupDef[] = [
|
|
|
325
367
|
id: 'device',
|
|
326
368
|
labelKey: 'SettingsDevices.Title',
|
|
327
369
|
icon: 'Smartphone',
|
|
328
|
-
keys: [
|
|
370
|
+
keys: [
|
|
371
|
+
'device.',
|
|
372
|
+
'calendarView.autoReturnToTodayEnabled',
|
|
373
|
+
'calendarView.autoReturnToTodayTimeoutSeconds',
|
|
374
|
+
],
|
|
329
375
|
},
|
|
330
376
|
{
|
|
331
377
|
id: 'language',
|
|
@@ -346,6 +392,251 @@ export const EXCLUDED_DEVICE_SETTINGS: ReadonlySet<string> = new Set([
|
|
|
346
392
|
'notification.hasBeenPrompted',
|
|
347
393
|
]);
|
|
348
394
|
|
|
395
|
+
// ---------------------------------------------------------------------------
|
|
396
|
+
// Per-setting i18n label / description keys
|
|
397
|
+
// ---------------------------------------------------------------------------
|
|
398
|
+
|
|
399
|
+
export type SettingLabelDef = {
|
|
400
|
+
/** i18n message key for the setting label */
|
|
401
|
+
labelKey: string;
|
|
402
|
+
/** Optional i18n message key for a description shown below the label */
|
|
403
|
+
descriptionKey?: string;
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Maps each setting key to its i18n label and optional description key.
|
|
408
|
+
* These keys must exist in every consumer's i18n catalog.
|
|
409
|
+
*
|
|
410
|
+
* When a key is missing from this map, consumers should fall back to
|
|
411
|
+
* the auto-generated label from `SettingsRegistry.getSettingLabel()`.
|
|
412
|
+
*/
|
|
413
|
+
export const SETTINGS_LABELS: Readonly<Record<string, SettingLabelDef>> = {
|
|
414
|
+
// ── Appearance ──────────────────────────────────────────────────────────
|
|
415
|
+
'appearance.theme': { labelKey: 'Settings.SelectTheme' },
|
|
416
|
+
'appearance.clockType': {
|
|
417
|
+
labelKey: 'Settings.ClockType',
|
|
418
|
+
descriptionKey: 'Settings.ClockTypeDescription',
|
|
419
|
+
},
|
|
420
|
+
'appearance.enableDayColors': {
|
|
421
|
+
labelKey: 'Settings.EnableDayColors',
|
|
422
|
+
descriptionKey: 'Settings.EnableDayColorsDescription',
|
|
423
|
+
},
|
|
424
|
+
|
|
425
|
+
// ── Calendar type ───────────────────────────────────────────────────────
|
|
426
|
+
'calendarView.type': {
|
|
427
|
+
labelKey: 'Settings.CalendarType',
|
|
428
|
+
descriptionKey: 'Settings.ModeDescription',
|
|
429
|
+
},
|
|
430
|
+
'calendarView.view': { labelKey: 'Settings.Calendar' },
|
|
431
|
+
|
|
432
|
+
// ── Calendar view ───────────────────────────────────────────────────────
|
|
433
|
+
'calendarView.showCalendarNames': { labelKey: 'Settings.ShowCalendarNames' },
|
|
434
|
+
'calendarView.splitView': {
|
|
435
|
+
labelKey: 'Settings.SplitViewLabel',
|
|
436
|
+
descriptionKey: 'Settings.SplitViewDescription',
|
|
437
|
+
},
|
|
438
|
+
'calendarView.calendarColumns': {
|
|
439
|
+
labelKey: 'Settings.SplitViewConfig',
|
|
440
|
+
descriptionKey: 'Settings.SplitViewConfigDescription',
|
|
441
|
+
},
|
|
442
|
+
'calendarView.dayViewZoom': {
|
|
443
|
+
labelKey: 'Settings.CalendarDayViewIntervalTitle',
|
|
444
|
+
descriptionKey: 'Settings.CalendarDayViewIntervalDescription',
|
|
445
|
+
},
|
|
446
|
+
'calendarView.weekViewZoom': {
|
|
447
|
+
labelKey: 'Settings.CalendarWeekViewIntervalTitle',
|
|
448
|
+
descriptionKey: 'Settings.CalendarWeekViewIntervalDescription',
|
|
449
|
+
},
|
|
450
|
+
|
|
451
|
+
// ── Auto return to today ────────────────────────────────────────────────
|
|
452
|
+
'calendarView.autoReturnToTodayEnabled': {
|
|
453
|
+
labelKey: 'Settings.AutoReturnToTodayEnabled',
|
|
454
|
+
},
|
|
455
|
+
'calendarView.autoReturnToTodayTimeoutSeconds': {
|
|
456
|
+
labelKey: 'Settings.AutoReturnToTodayTimeout',
|
|
457
|
+
},
|
|
458
|
+
|
|
459
|
+
// ── Weather ─────────────────────────────────────────────────────────────
|
|
460
|
+
'calendarView.weatherLocation': { labelKey: 'Settings.WeatherLocation' },
|
|
461
|
+
'calendarView.showWeatherOnEvents': {
|
|
462
|
+
labelKey: 'Settings.ShowWeatherOnEvents',
|
|
463
|
+
descriptionKey: 'Settings.ShowWeatherOnEventsDescription',
|
|
464
|
+
},
|
|
465
|
+
'calendarView.showWeatherOnTimeline': {
|
|
466
|
+
labelKey: 'Settings.ShowWeatherOnTimeline',
|
|
467
|
+
descriptionKey: 'Settings.ShowWeatherOnTimelineDescription',
|
|
468
|
+
},
|
|
469
|
+
|
|
470
|
+
// ── Sound & alerts ──────────────────────────────────────────────────────
|
|
471
|
+
'sound.reminderVolume': {
|
|
472
|
+
labelKey: 'Settings.ReminderVolume',
|
|
473
|
+
descriptionKey: 'Settings.ReminderVolumeDescription',
|
|
474
|
+
},
|
|
475
|
+
'sound.timerVolume': {
|
|
476
|
+
labelKey: 'Settings.TimerVolume',
|
|
477
|
+
descriptionKey: 'Settings.TimerVolumeDescription',
|
|
478
|
+
},
|
|
479
|
+
'sound.mediaVolume': {
|
|
480
|
+
labelKey: 'Settings.MediaVolume',
|
|
481
|
+
descriptionKey: 'Settings.MediaVolumeDescription',
|
|
482
|
+
},
|
|
483
|
+
'sound.alarmSound': { labelKey: 'Settings.AlarmSound' },
|
|
484
|
+
'sound.reminderAlarmSound': { labelKey: 'Settings.ReminderAlarmAsset' },
|
|
485
|
+
'sound.reminderAlarmTimeout': { labelKey: 'Settings.ReminderAlarmTimeout' },
|
|
486
|
+
'sound.timerAlarmSound': { labelKey: 'Settings.TimerAlarmSound' },
|
|
487
|
+
'sound.timerAlarmTimeout': { labelKey: 'Settings.TimerAlarmTimeout' },
|
|
488
|
+
'sound.allowCustomReminderSounds': {
|
|
489
|
+
labelKey: 'Settings.AllowCustomReminderSounds',
|
|
490
|
+
},
|
|
491
|
+
'sound.ttsEnabled': {
|
|
492
|
+
labelKey: 'Settings.EnableSpeech',
|
|
493
|
+
descriptionKey: 'Settings.EnableSpeechDescription',
|
|
494
|
+
},
|
|
495
|
+
'sound.ttsRate': { labelKey: 'Settings.TtsTitle' },
|
|
496
|
+
|
|
497
|
+
// ── Timer ───────────────────────────────────────────────────────────────
|
|
498
|
+
'timer.showTimeRemaining': { labelKey: 'Settings.TimerShowTimeRemaining' },
|
|
499
|
+
'timer.showEndTime': { labelKey: 'Settings.TimerShowEndTime' },
|
|
500
|
+
'timer.showRestartButton': { labelKey: 'Settings.TimerShowRestartButton' },
|
|
501
|
+
'timer.showPauseButton': { labelKey: 'Settings.TimerShowPauseButton' },
|
|
502
|
+
|
|
503
|
+
// ── Lock screen ─────────────────────────────────────────────────────────
|
|
504
|
+
'lockScreen.pin': { labelKey: 'Settings.LockScreenTitlePin' },
|
|
505
|
+
'lockScreen.clockDisplay': { labelKey: 'Settings.LockScreenClockTitle' },
|
|
506
|
+
'lockScreen.showDate': { labelKey: 'Settings.LockScreenShowDate' },
|
|
507
|
+
'lockScreen.showHourNumbers': {
|
|
508
|
+
labelKey: 'Settings.LockScreenShowHourNumbers',
|
|
509
|
+
},
|
|
510
|
+
'lockScreen.imageMode': { labelKey: 'Settings.LockScreenImageModeTitle' },
|
|
511
|
+
'lockScreen.backgroundImage': {
|
|
512
|
+
labelKey: 'Settings.LockScreenImageModeBackground',
|
|
513
|
+
},
|
|
514
|
+
'lockScreen.photoFrameImages': {
|
|
515
|
+
labelKey: 'Settings.LockScreenImageModePhotoFrame',
|
|
516
|
+
},
|
|
517
|
+
'lockScreen.photoFrameIntervalSeconds': {
|
|
518
|
+
labelKey: 'Settings.LockScreenPhotoFrameIntervalTitle',
|
|
519
|
+
},
|
|
520
|
+
'lockScreen.inactivityLockEnabled': {
|
|
521
|
+
labelKey: 'SettingsInactivity.EnableLabel',
|
|
522
|
+
},
|
|
523
|
+
'lockScreen.inactivityTimeoutMinutes': {
|
|
524
|
+
labelKey: 'SettingsInactivity.TimeoutLabel',
|
|
525
|
+
},
|
|
526
|
+
|
|
527
|
+
// ── Touch / gestures ───────────────────────────────────────────────────
|
|
528
|
+
'touch.enableTapToCreate': {
|
|
529
|
+
labelKey: 'Settings.EnableTapToCreate',
|
|
530
|
+
descriptionKey: 'Settings.EnableTapToCreateDescription',
|
|
531
|
+
},
|
|
532
|
+
'touch.enableDragDrop': {
|
|
533
|
+
labelKey: 'Settings.EnableDragDrop',
|
|
534
|
+
descriptionKey: 'Settings.EnableDragDropDescription',
|
|
535
|
+
},
|
|
536
|
+
|
|
537
|
+
// ── Device ──────────────────────────────────────────────────────────────
|
|
538
|
+
'device.timePickerMode': { labelKey: 'Settings.DateTimeTitle' },
|
|
539
|
+
|
|
540
|
+
// ── Language ────────────────────────────────────────────────────────────
|
|
541
|
+
'language.locale': { labelKey: 'Settings.SelectLanguage' },
|
|
542
|
+
|
|
543
|
+
// ── Notifications ───────────────────────────────────────────────────────
|
|
544
|
+
'notification.enabled': { labelKey: 'Settings.NotificationsEnabled' },
|
|
545
|
+
'notification.notifyAllCalendars': {
|
|
546
|
+
labelKey: 'Settings.NotifyAllCalendars',
|
|
547
|
+
},
|
|
548
|
+
'notification.enabledCalendarIds': {
|
|
549
|
+
labelKey: 'Settings.NotificationsCalendars',
|
|
550
|
+
},
|
|
551
|
+
|
|
552
|
+
// ── Chronological header ────────────────────────────────────────────────
|
|
553
|
+
'chronological.header.showNavigationArrows': {
|
|
554
|
+
labelKey: 'ChronologicalFeatures.NavigationArrows',
|
|
555
|
+
},
|
|
556
|
+
'chronological.header.showClock': {
|
|
557
|
+
labelKey: 'ChronologicalFeatures.Clock',
|
|
558
|
+
},
|
|
559
|
+
'chronological.header.showCurrentYearInDate': {
|
|
560
|
+
labelKey: 'ChronologicalFeatures.ShowCurrentYear',
|
|
561
|
+
},
|
|
562
|
+
'chronological.header.showTimeOfDay': {
|
|
563
|
+
labelKey: 'ChronologicalFeatures.TimeOfDay',
|
|
564
|
+
},
|
|
565
|
+
|
|
566
|
+
// ── Chronological footer ────────────────────────────────────────────────
|
|
567
|
+
'chronological.footer.showMenuButton': {
|
|
568
|
+
labelKey: 'ChronologicalFeatures.MenuButton',
|
|
569
|
+
},
|
|
570
|
+
'chronological.footer.showViewSwitcherDay': {
|
|
571
|
+
labelKey: 'ChronologicalFeatures.ViewSwitcherDay',
|
|
572
|
+
},
|
|
573
|
+
'chronological.footer.showViewSwitcherWeek': {
|
|
574
|
+
labelKey: 'ChronologicalFeatures.ViewSwitcherWeek',
|
|
575
|
+
},
|
|
576
|
+
'chronological.footer.showViewSwitcherMonth': {
|
|
577
|
+
labelKey: 'ChronologicalFeatures.ViewSwitcherMonth',
|
|
578
|
+
},
|
|
579
|
+
'chronological.footer.showTimerButton': {
|
|
580
|
+
labelKey: 'ChronologicalFeatures.TimerButton',
|
|
581
|
+
},
|
|
582
|
+
'chronological.footer.showNewEventButton': {
|
|
583
|
+
labelKey: 'ChronologicalFeatures.NewEventButton',
|
|
584
|
+
},
|
|
585
|
+
'chronological.footer.showSettingsButton': {
|
|
586
|
+
labelKey: 'ChronologicalFeatures.SettingsButton',
|
|
587
|
+
},
|
|
588
|
+
|
|
589
|
+
// ── Chronological timer ─────────────────────────────────────────────────
|
|
590
|
+
'chronological.timer.showNewCountdown': {
|
|
591
|
+
labelKey: 'TimerFeatures.ShowNewCountdown',
|
|
592
|
+
},
|
|
593
|
+
'chronological.timer.showFromTemplate': {
|
|
594
|
+
labelKey: 'TimerFeatures.ShowFromTemplate',
|
|
595
|
+
},
|
|
596
|
+
'chronological.timer.showEditTemplate': {
|
|
597
|
+
labelKey: 'TimerFeatures.ShowEditTemplate',
|
|
598
|
+
},
|
|
599
|
+
'chronological.timer.showDeleteTemplate': {
|
|
600
|
+
labelKey: 'TimerFeatures.ShowDeleteTemplate',
|
|
601
|
+
},
|
|
602
|
+
'chronological.timer.showAddTemplate': {
|
|
603
|
+
labelKey: 'TimerFeatures.ShowAddTemplate',
|
|
604
|
+
},
|
|
605
|
+
|
|
606
|
+
// ── Chronological menu ──────────────────────────────────────────────────
|
|
607
|
+
'chronological.menu.showSettingsButton': {
|
|
608
|
+
labelKey: 'ChronologicalFeatures.MenuSettingsButton',
|
|
609
|
+
},
|
|
610
|
+
'chronological.quickSettings.showTimerVolume': {
|
|
611
|
+
labelKey: 'ChronologicalFeatures.QuickSettingsTimerVolume',
|
|
612
|
+
},
|
|
613
|
+
'chronological.quickSettings.showReminderVolume': {
|
|
614
|
+
labelKey: 'ChronologicalFeatures.QuickSettingsReminderVolume',
|
|
615
|
+
},
|
|
616
|
+
'chronological.quickSettings.showMediaVolume': {
|
|
617
|
+
labelKey: 'ChronologicalFeatures.QuickSettingsMediaVolume',
|
|
618
|
+
},
|
|
619
|
+
'chronological.quickSettings.showBrightness': {
|
|
620
|
+
labelKey: 'ChronologicalFeatures.QuickSettingsBrightness',
|
|
621
|
+
},
|
|
622
|
+
'chronological.quickSettings.showLockScreen': {
|
|
623
|
+
labelKey: 'ChronologicalFeatures.QuickSettingsLockScreen',
|
|
624
|
+
},
|
|
625
|
+
|
|
626
|
+
// ── Event form (time-based) ─────────────────────────────────────────────
|
|
627
|
+
'eventForm.recurrence': { labelKey: 'Calendar.LabelRecurrence' },
|
|
628
|
+
'eventForm.reminders': { labelKey: 'Calendar.LabelReminders' },
|
|
629
|
+
'eventForm.emailReminders': { labelKey: 'Calendar.LabelEmailReminders' },
|
|
630
|
+
'eventForm.location': { labelKey: 'Common.Location' },
|
|
631
|
+
'eventForm.travelTime': { labelKey: 'TravelTime.Title' },
|
|
632
|
+
'eventForm.description': { labelKey: 'Common.Description' },
|
|
633
|
+
'eventForm.checklist': { labelKey: 'EventChecklist.DefaultName' },
|
|
634
|
+
'eventForm.images': { labelKey: 'EventImageGallery.SectionTitle' },
|
|
635
|
+
'eventForm.audioClips': { labelKey: 'EventAudioGallery.SectionTitle' },
|
|
636
|
+
'eventForm.notificationReceivers': { labelKey: 'EventForm.NotificationReceivers' },
|
|
637
|
+
'eventForm.visibility': { labelKey: 'EventVisibility.Title' },
|
|
638
|
+
};
|
|
639
|
+
|
|
349
640
|
/**
|
|
350
641
|
* Check whether a setting key matches a group's key matchers.
|
|
351
642
|
*/
|
|
@@ -367,10 +658,11 @@ function matchesGroup(key: string, group: SettingsGroupDef): boolean {
|
|
|
367
658
|
export function groupSettingsForDevice(
|
|
368
659
|
allSettings: ParsedSettingEntry[],
|
|
369
660
|
calendarType: CalendarType,
|
|
661
|
+
appMode?: 'ENROLLED',
|
|
370
662
|
): { id: SettingsGroupId; labelKey: string; icon: string; settings: ParsedSettingEntry[] }[] {
|
|
371
|
-
// Filter excluded
|
|
663
|
+
// Filter excluded and hidden settings
|
|
372
664
|
const settings = allSettings.filter(
|
|
373
|
-
(s) => !EXCLUDED_DEVICE_SETTINGS.has(s.key),
|
|
665
|
+
(s) => !EXCLUDED_DEVICE_SETTINGS.has(s.key) && s.uiType !== 'HIDDEN',
|
|
374
666
|
);
|
|
375
667
|
|
|
376
668
|
// Calendar type filtering for event form keys
|
|
@@ -399,6 +691,11 @@ export function groupSettingsForDevice(
|
|
|
399
691
|
continue;
|
|
400
692
|
}
|
|
401
693
|
|
|
694
|
+
// Skip groups not relevant for current app mode
|
|
695
|
+
if (group.appMode && group.appMode !== appMode) {
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
|
|
402
699
|
const matched = filteredSettings.filter(
|
|
403
700
|
(s) => !claimed.has(s.key) && matchesGroup(s.key, group),
|
|
404
701
|
);
|
|
@@ -437,6 +734,12 @@ export type SettingDef<T = unknown> = {
|
|
|
437
734
|
default: T;
|
|
438
735
|
/** Whether this setting should be synced to the server. Default true. */
|
|
439
736
|
sync: boolean;
|
|
737
|
+
/** UI component type for rendering this setting */
|
|
738
|
+
uiType: SettingUiType;
|
|
739
|
+
/** Available options for SELECT-type settings */
|
|
740
|
+
options?: readonly SettingOption<T>[];
|
|
741
|
+
/** Slider configuration for SLIDER-type settings */
|
|
742
|
+
sliderConfig?: SliderConfig;
|
|
440
743
|
};
|
|
441
744
|
|
|
442
745
|
// ---------------------------------------------------------------------------
|
|
@@ -459,6 +762,39 @@ export const DEFAULT_REGISTRY_CONFIG: RegistryConfig = {
|
|
|
459
762
|
defaultLocale: 'nb',
|
|
460
763
|
};
|
|
461
764
|
|
|
765
|
+
// ---------------------------------------------------------------------------
|
|
766
|
+
// Shared option arrays (reused across multiple settings)
|
|
767
|
+
// ---------------------------------------------------------------------------
|
|
768
|
+
|
|
769
|
+
const ALARM_SOUND_OPTIONS: readonly SettingOption<AlarmSound>[] = [
|
|
770
|
+
{ value: 'none', labelKey: 'Settings.Option.AlarmSound.None' },
|
|
771
|
+
{ value: 'alarm1', labelKey: 'Settings.Option.AlarmSound.Alarm1' },
|
|
772
|
+
{ value: 'alarm2', labelKey: 'Settings.Option.AlarmSound.Alarm2' },
|
|
773
|
+
{ value: 'alarm3', labelKey: 'Settings.Option.AlarmSound.Alarm3' },
|
|
774
|
+
{ value: 'alarm4', labelKey: 'Settings.Option.AlarmSound.Alarm4' },
|
|
775
|
+
{ value: 'alarm5', labelKey: 'Settings.Option.AlarmSound.Alarm5' },
|
|
776
|
+
{ value: 'alarm6', labelKey: 'Settings.Option.AlarmSound.Alarm6' },
|
|
777
|
+
{ value: 'alarm7', labelKey: 'Settings.Option.AlarmSound.Alarm7' },
|
|
778
|
+
{ value: 'alarm8', labelKey: 'Settings.Option.AlarmSound.Alarm8' },
|
|
779
|
+
{ value: 'alarm9', labelKey: 'Settings.Option.AlarmSound.Alarm9' },
|
|
780
|
+
];
|
|
781
|
+
|
|
782
|
+
const ALARM_TIMEOUT_OPTIONS: readonly SettingOption<AlarmTimeout>[] = [
|
|
783
|
+
{ value: 1, labelKey: 'Settings.Option.AlarmTimeout.1min' },
|
|
784
|
+
{ value: 2, labelKey: 'Settings.Option.AlarmTimeout.2min' },
|
|
785
|
+
{ value: 3, labelKey: 'Settings.Option.AlarmTimeout.3min' },
|
|
786
|
+
{ value: 5, labelKey: 'Settings.Option.AlarmTimeout.5min' },
|
|
787
|
+
{ value: 10, labelKey: 'Settings.Option.AlarmTimeout.10min' },
|
|
788
|
+
];
|
|
789
|
+
|
|
790
|
+
const DAY_VIEW_ZOOM_OPTIONS: readonly SettingOption<CalendarDayViewCellZoom>[] = [
|
|
791
|
+
{ value: 15, labelKey: 'Settings.Option.DayViewZoom.15min' },
|
|
792
|
+
{ value: 30, labelKey: 'Settings.Option.DayViewZoom.30min' },
|
|
793
|
+
{ value: 60, labelKey: 'Settings.Option.DayViewZoom.60min' },
|
|
794
|
+
];
|
|
795
|
+
|
|
796
|
+
const TIME_OF_DAY_SLIDER: SliderConfig = { min: 0, max: 23, step: 1 };
|
|
797
|
+
|
|
462
798
|
// ---------------------------------------------------------------------------
|
|
463
799
|
// Helper
|
|
464
800
|
// ---------------------------------------------------------------------------
|
|
@@ -467,9 +803,27 @@ function def<T>(
|
|
|
467
803
|
category: SettingsCategory,
|
|
468
804
|
type: SettingsDataType,
|
|
469
805
|
defaultValue: T,
|
|
470
|
-
|
|
806
|
+
uiType: SettingUiType,
|
|
807
|
+
extra?: {
|
|
808
|
+
sync?: boolean;
|
|
809
|
+
options?: readonly SettingOption<T>[];
|
|
810
|
+
sliderConfig?: SliderConfig;
|
|
811
|
+
},
|
|
471
812
|
): SettingDef<T> {
|
|
472
|
-
|
|
813
|
+
const result: SettingDef<T> = {
|
|
814
|
+
category,
|
|
815
|
+
type,
|
|
816
|
+
default: defaultValue,
|
|
817
|
+
sync: extra?.sync ?? true,
|
|
818
|
+
uiType,
|
|
819
|
+
};
|
|
820
|
+
if (extra?.options) {
|
|
821
|
+
result.options = extra.options;
|
|
822
|
+
}
|
|
823
|
+
if (extra?.sliderConfig) {
|
|
824
|
+
result.sliderConfig = extra.sliderConfig;
|
|
825
|
+
}
|
|
826
|
+
return result;
|
|
473
827
|
}
|
|
474
828
|
|
|
475
829
|
// ---------------------------------------------------------------------------
|
|
@@ -485,9 +839,33 @@ function buildEntries(config: RegistryConfig) {
|
|
|
485
839
|
'appearance',
|
|
486
840
|
'string',
|
|
487
841
|
config.defaultTheme,
|
|
842
|
+
'CUSTOM_THEME_PICKER',
|
|
843
|
+
{
|
|
844
|
+
options: [
|
|
845
|
+
{ value: 'light', labelKey: 'Settings.Option.Theme.Light' },
|
|
846
|
+
{ value: 'dark', labelKey: 'Settings.Option.Theme.Dark' },
|
|
847
|
+
{ value: 'system', labelKey: 'Settings.Option.Theme.System' },
|
|
848
|
+
],
|
|
849
|
+
},
|
|
850
|
+
),
|
|
851
|
+
'appearance.clockType': def<ClockType>(
|
|
852
|
+
'appearance',
|
|
853
|
+
'string',
|
|
854
|
+
'digital',
|
|
855
|
+
'CUSTOM_CLOCK_TYPE',
|
|
856
|
+
{
|
|
857
|
+
options: [
|
|
858
|
+
{ value: 'digital', labelKey: 'Settings.Option.ClockType.Digital' },
|
|
859
|
+
{ value: 'analog', labelKey: 'Settings.Option.ClockType.Analog' },
|
|
860
|
+
],
|
|
861
|
+
},
|
|
862
|
+
),
|
|
863
|
+
'appearance.enableDayColors': def<boolean>(
|
|
864
|
+
'appearance',
|
|
865
|
+
'boolean',
|
|
866
|
+
false,
|
|
867
|
+
'TOGGLE',
|
|
488
868
|
),
|
|
489
|
-
'appearance.clockType': def<ClockType>('appearance', 'string', 'digital'),
|
|
490
|
-
'appearance.enableDayColors': def<boolean>('appearance', 'boolean', false),
|
|
491
869
|
|
|
492
870
|
// ═══════════════════════════════════════════════════════════════════════
|
|
493
871
|
// Calendar view
|
|
@@ -496,152 +874,346 @@ function buildEntries(config: RegistryConfig) {
|
|
|
496
874
|
'calendarView',
|
|
497
875
|
'string',
|
|
498
876
|
'time-based',
|
|
877
|
+
'CUSTOM_CALENDAR_TYPE',
|
|
878
|
+
{
|
|
879
|
+
options: [
|
|
880
|
+
{
|
|
881
|
+
value: 'chronological',
|
|
882
|
+
labelKey: 'Settings.Option.CalendarType.Chronological',
|
|
883
|
+
},
|
|
884
|
+
{
|
|
885
|
+
value: 'time-based',
|
|
886
|
+
labelKey: 'Settings.Option.CalendarType.TimeBased',
|
|
887
|
+
},
|
|
888
|
+
],
|
|
889
|
+
},
|
|
890
|
+
),
|
|
891
|
+
'calendarView.view': def<CalendarViewMode>(
|
|
892
|
+
'calendarView',
|
|
893
|
+
'string',
|
|
894
|
+
'day',
|
|
895
|
+
'SELECT',
|
|
896
|
+
{
|
|
897
|
+
options: [
|
|
898
|
+
{ value: 'day', labelKey: 'Settings.Option.CalendarView.Day' },
|
|
899
|
+
{
|
|
900
|
+
value: '3-days',
|
|
901
|
+
labelKey: 'Settings.Option.CalendarView.3Days',
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
value: '5-days',
|
|
905
|
+
labelKey: 'Settings.Option.CalendarView.5Days',
|
|
906
|
+
},
|
|
907
|
+
{
|
|
908
|
+
value: '7-days',
|
|
909
|
+
labelKey: 'Settings.Option.CalendarView.7Days',
|
|
910
|
+
},
|
|
911
|
+
{ value: 'week', labelKey: 'Settings.Option.CalendarView.Week' },
|
|
912
|
+
{
|
|
913
|
+
value: 'month',
|
|
914
|
+
labelKey: 'Settings.Option.CalendarView.Month',
|
|
915
|
+
},
|
|
916
|
+
{
|
|
917
|
+
value: 'overview',
|
|
918
|
+
labelKey: 'Settings.Option.CalendarView.Overview',
|
|
919
|
+
},
|
|
920
|
+
],
|
|
921
|
+
},
|
|
499
922
|
),
|
|
500
|
-
'calendarView.view': def<CalendarViewMode>('calendarView', 'string', 'day'),
|
|
501
923
|
'calendarView.dayViewZoom': def<CalendarDayViewCellZoom>(
|
|
502
924
|
'calendarView',
|
|
503
925
|
'number',
|
|
504
926
|
60,
|
|
927
|
+
'SELECT',
|
|
928
|
+
{ options: DAY_VIEW_ZOOM_OPTIONS },
|
|
505
929
|
),
|
|
506
930
|
'calendarView.weekViewZoom': def<CalendarDayViewCellZoom>(
|
|
507
931
|
'calendarView',
|
|
508
932
|
'number',
|
|
509
933
|
60,
|
|
934
|
+
'SELECT',
|
|
935
|
+
{ options: DAY_VIEW_ZOOM_OPTIONS },
|
|
936
|
+
),
|
|
937
|
+
'calendarView.splitView': def<boolean>(
|
|
938
|
+
'calendarView',
|
|
939
|
+
'boolean',
|
|
940
|
+
false,
|
|
941
|
+
'TOGGLE',
|
|
510
942
|
),
|
|
511
|
-
'calendarView.splitView': def<boolean>('calendarView', 'boolean', false),
|
|
512
943
|
'calendarView.showCalendarNames': def<boolean>(
|
|
513
944
|
'calendarView',
|
|
514
945
|
'boolean',
|
|
515
946
|
true,
|
|
947
|
+
'TOGGLE',
|
|
948
|
+
),
|
|
949
|
+
'calendarView.calendarColumns': def<unknown[]>(
|
|
950
|
+
'calendarView',
|
|
951
|
+
'json',
|
|
952
|
+
[],
|
|
953
|
+
'CUSTOM_SPLIT_VIEW_CONFIG',
|
|
516
954
|
),
|
|
517
|
-
'calendarView.calendarColumns': def<unknown[]>('calendarView', 'json', []),
|
|
518
955
|
'calendarView.autoReturnToTodayEnabled': def<boolean>(
|
|
519
956
|
'calendarView',
|
|
520
957
|
'boolean',
|
|
521
958
|
config.isEnrolled,
|
|
959
|
+
'TOGGLE',
|
|
522
960
|
),
|
|
523
961
|
'calendarView.autoReturnToTodayTimeoutSeconds': def<number>(
|
|
524
962
|
'calendarView',
|
|
525
963
|
'number',
|
|
526
964
|
300,
|
|
965
|
+
'SLIDER',
|
|
966
|
+
{ sliderConfig: { min: 30, max: 600, step: 30 } },
|
|
527
967
|
),
|
|
528
968
|
'calendarView.showWeatherOnEvents': def<boolean>(
|
|
529
969
|
'calendarView',
|
|
530
970
|
'boolean',
|
|
531
971
|
false,
|
|
972
|
+
'TOGGLE',
|
|
532
973
|
),
|
|
533
974
|
'calendarView.showWeatherOnTimeline': def<boolean>(
|
|
534
975
|
'calendarView',
|
|
535
976
|
'boolean',
|
|
536
977
|
false,
|
|
978
|
+
'TOGGLE',
|
|
537
979
|
),
|
|
538
980
|
'calendarView.weatherLocation': def<WeatherLocation | null>(
|
|
539
981
|
'calendarView',
|
|
540
982
|
'json',
|
|
541
983
|
null,
|
|
984
|
+
'CUSTOM_WEATHER_LOCATION',
|
|
542
985
|
),
|
|
543
986
|
|
|
544
987
|
// ═══════════════════════════════════════════════════════════════════════
|
|
545
988
|
// Event form field visibility (time-based)
|
|
546
989
|
// ═══════════════════════════════════════════════════════════════════════
|
|
547
|
-
'eventForm.recurrence': def<boolean>('eventForm', 'boolean', true),
|
|
548
|
-
'eventForm.reminders': def<boolean>('eventForm', 'boolean', true),
|
|
549
|
-
'eventForm.emailReminders': def<boolean>('eventForm', 'boolean', false),
|
|
550
|
-
'eventForm.location': def<boolean>('eventForm', 'boolean', true),
|
|
551
|
-
'eventForm.travelTime': def<boolean>('eventForm', 'boolean', false),
|
|
552
|
-
'eventForm.description': def<boolean>('eventForm', 'boolean', true),
|
|
553
|
-
'eventForm.checklist': def<boolean>('eventForm', 'boolean', true),
|
|
554
|
-
'eventForm.images': def<boolean>('eventForm', 'boolean', false),
|
|
555
|
-
'eventForm.audioClips': def<boolean>('eventForm', 'boolean', false),
|
|
990
|
+
'eventForm.recurrence': def<boolean>('eventForm', 'boolean', true, 'TOGGLE'),
|
|
991
|
+
'eventForm.reminders': def<boolean>('eventForm', 'boolean', true, 'TOGGLE'),
|
|
992
|
+
'eventForm.emailReminders': def<boolean>('eventForm', 'boolean', false, 'TOGGLE'),
|
|
993
|
+
'eventForm.location': def<boolean>('eventForm', 'boolean', true, 'TOGGLE'),
|
|
994
|
+
'eventForm.travelTime': def<boolean>('eventForm', 'boolean', false, 'TOGGLE'),
|
|
995
|
+
'eventForm.description': def<boolean>('eventForm', 'boolean', true, 'TOGGLE'),
|
|
996
|
+
'eventForm.checklist': def<boolean>('eventForm', 'boolean', true, 'TOGGLE'),
|
|
997
|
+
'eventForm.images': def<boolean>('eventForm', 'boolean', false, 'TOGGLE'),
|
|
998
|
+
'eventForm.audioClips': def<boolean>('eventForm', 'boolean', false, 'TOGGLE'),
|
|
556
999
|
'eventForm.notificationReceivers': def<boolean>(
|
|
557
1000
|
'eventForm',
|
|
558
1001
|
'boolean',
|
|
559
1002
|
true,
|
|
1003
|
+
'TOGGLE',
|
|
560
1004
|
),
|
|
561
|
-
'eventForm.visibility': def<boolean>('eventForm', 'boolean', false),
|
|
1005
|
+
'eventForm.visibility': def<boolean>('eventForm', 'boolean', false, 'TOGGLE'),
|
|
562
1006
|
|
|
563
1007
|
// ═══════════════════════════════════════════════════════════════════════
|
|
564
1008
|
// Sound & alerts
|
|
565
1009
|
// ═══════════════════════════════════════════════════════════════════════
|
|
566
|
-
'sound.timerVolume': def<number>('sound', 'number', 0.5),
|
|
567
|
-
'sound.reminderVolume': def<number>('sound', 'number', 0.5),
|
|
568
|
-
'sound.mediaVolume': def<number>('sound', 'number', 0.5),
|
|
569
|
-
'sound.alarmSound': def<AlarmSound>(
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
'sound.
|
|
1010
|
+
'sound.timerVolume': def<number>('sound', 'number', 0.5, 'VOLUME_SLIDER'),
|
|
1011
|
+
'sound.reminderVolume': def<number>('sound', 'number', 0.5, 'VOLUME_SLIDER'),
|
|
1012
|
+
'sound.mediaVolume': def<number>('sound', 'number', 0.5, 'VOLUME_SLIDER'),
|
|
1013
|
+
'sound.alarmSound': def<AlarmSound>(
|
|
1014
|
+
'sound',
|
|
1015
|
+
'string',
|
|
1016
|
+
'alarm1',
|
|
1017
|
+
'SELECT',
|
|
1018
|
+
{ options: ALARM_SOUND_OPTIONS },
|
|
1019
|
+
),
|
|
1020
|
+
'sound.reminderAlarmSound': def<AlarmSound>(
|
|
1021
|
+
'sound',
|
|
1022
|
+
'string',
|
|
1023
|
+
'alarm1',
|
|
1024
|
+
'SELECT',
|
|
1025
|
+
{ options: ALARM_SOUND_OPTIONS },
|
|
1026
|
+
),
|
|
1027
|
+
'sound.timerAlarmSound': def<AlarmSound>(
|
|
1028
|
+
'sound',
|
|
1029
|
+
'string',
|
|
1030
|
+
'alarm1',
|
|
1031
|
+
'SELECT',
|
|
1032
|
+
{ options: ALARM_SOUND_OPTIONS },
|
|
1033
|
+
),
|
|
1034
|
+
'sound.timerAlarmTimeout': def<AlarmTimeout>(
|
|
1035
|
+
'sound',
|
|
1036
|
+
'number',
|
|
1037
|
+
3,
|
|
1038
|
+
'SELECT',
|
|
1039
|
+
{ options: ALARM_TIMEOUT_OPTIONS },
|
|
1040
|
+
),
|
|
1041
|
+
'sound.reminderAlarmTimeout': def<AlarmTimeout>(
|
|
1042
|
+
'sound',
|
|
1043
|
+
'number',
|
|
1044
|
+
3,
|
|
1045
|
+
'SELECT',
|
|
1046
|
+
{ options: ALARM_TIMEOUT_OPTIONS },
|
|
1047
|
+
),
|
|
1048
|
+
'sound.allowCustomReminderSounds': def<boolean>(
|
|
1049
|
+
'sound',
|
|
1050
|
+
'boolean',
|
|
1051
|
+
false,
|
|
1052
|
+
'TOGGLE',
|
|
1053
|
+
),
|
|
1054
|
+
'sound.ttsEnabled': def<boolean>(
|
|
1055
|
+
'sound',
|
|
1056
|
+
'boolean',
|
|
1057
|
+
config.isEnrolled,
|
|
1058
|
+
'TOGGLE',
|
|
1059
|
+
),
|
|
1060
|
+
'sound.ttsRate': def<number>(
|
|
1061
|
+
'sound',
|
|
1062
|
+
'number',
|
|
1063
|
+
1.0,
|
|
1064
|
+
'SLIDER',
|
|
1065
|
+
{ sliderConfig: { min: 0.5, max: 2, step: 0.1 } },
|
|
1066
|
+
),
|
|
577
1067
|
|
|
578
1068
|
// ═══════════════════════════════════════════════════════════════════════
|
|
579
1069
|
// Timer
|
|
580
1070
|
// ═══════════════════════════════════════════════════════════════════════
|
|
581
|
-
'timer.showTimeRemaining': def<boolean>('timer', 'boolean', true),
|
|
582
|
-
'timer.showEndTime': def<boolean>('timer', 'boolean', true),
|
|
583
|
-
'timer.showRestartButton': def<boolean>('timer', 'boolean', true),
|
|
584
|
-
'timer.showPauseButton': def<boolean>('timer', 'boolean', true),
|
|
1071
|
+
'timer.showTimeRemaining': def<boolean>('timer', 'boolean', true, 'TOGGLE'),
|
|
1072
|
+
'timer.showEndTime': def<boolean>('timer', 'boolean', true, 'TOGGLE'),
|
|
1073
|
+
'timer.showRestartButton': def<boolean>('timer', 'boolean', true, 'TOGGLE'),
|
|
1074
|
+
'timer.showPauseButton': def<boolean>('timer', 'boolean', true, 'TOGGLE'),
|
|
585
1075
|
|
|
586
1076
|
// ═══════════════════════════════════════════════════════════════════════
|
|
587
1077
|
// Lock screen
|
|
588
1078
|
// ═══════════════════════════════════════════════════════════════════════
|
|
589
|
-
'lockScreen.pin': def<string>('lockScreen', 'string', ''),
|
|
1079
|
+
'lockScreen.pin': def<string>('lockScreen', 'string', '', 'PIN_INPUT'),
|
|
590
1080
|
'lockScreen.inactivityLockEnabled': def<boolean>(
|
|
591
1081
|
'lockScreen',
|
|
592
1082
|
'boolean',
|
|
593
1083
|
false,
|
|
1084
|
+
'TOGGLE',
|
|
594
1085
|
),
|
|
595
1086
|
'lockScreen.inactivityTimeoutMinutes': def<InactivityTimeoutMinutes>(
|
|
596
1087
|
'lockScreen',
|
|
597
1088
|
'number',
|
|
598
1089
|
5,
|
|
1090
|
+
'SELECT',
|
|
1091
|
+
{
|
|
1092
|
+
options: [
|
|
1093
|
+
{ value: 1, labelKey: 'Settings.Option.InactivityTimeout.1min' },
|
|
1094
|
+
{ value: 5, labelKey: 'Settings.Option.InactivityTimeout.5min' },
|
|
1095
|
+
{ value: 10, labelKey: 'Settings.Option.InactivityTimeout.10min' },
|
|
1096
|
+
{ value: 15, labelKey: 'Settings.Option.InactivityTimeout.15min' },
|
|
1097
|
+
{ value: 30, labelKey: 'Settings.Option.InactivityTimeout.30min' },
|
|
1098
|
+
{ value: 45, labelKey: 'Settings.Option.InactivityTimeout.45min' },
|
|
1099
|
+
],
|
|
1100
|
+
},
|
|
599
1101
|
),
|
|
600
1102
|
'lockScreen.clockDisplay': def<LockScreenClockDisplay>(
|
|
601
1103
|
'lockScreen',
|
|
602
1104
|
'string',
|
|
603
1105
|
'digital',
|
|
1106
|
+
'SELECT',
|
|
1107
|
+
{
|
|
1108
|
+
options: [
|
|
1109
|
+
{ value: 'none', labelKey: 'Settings.Option.ClockDisplay.None' },
|
|
1110
|
+
{
|
|
1111
|
+
value: 'digital',
|
|
1112
|
+
labelKey: 'Settings.Option.ClockDisplay.Digital',
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
value: 'analog',
|
|
1116
|
+
labelKey: 'Settings.Option.ClockDisplay.Analog',
|
|
1117
|
+
},
|
|
1118
|
+
],
|
|
1119
|
+
},
|
|
1120
|
+
),
|
|
1121
|
+
'lockScreen.showDate': def<boolean>(
|
|
1122
|
+
'lockScreen',
|
|
1123
|
+
'boolean',
|
|
1124
|
+
true,
|
|
1125
|
+
'TOGGLE',
|
|
1126
|
+
),
|
|
1127
|
+
'lockScreen.showHourNumbers': def<boolean>(
|
|
1128
|
+
'lockScreen',
|
|
1129
|
+
'boolean',
|
|
1130
|
+
true,
|
|
1131
|
+
'TOGGLE',
|
|
604
1132
|
),
|
|
605
|
-
'lockScreen.showDate': def<boolean>('lockScreen', 'boolean', true),
|
|
606
|
-
'lockScreen.showHourNumbers': def<boolean>('lockScreen', 'boolean', true),
|
|
607
1133
|
'lockScreen.imageMode': def<LockScreenImageMode>(
|
|
608
1134
|
'lockScreen',
|
|
609
1135
|
'string',
|
|
610
1136
|
'none',
|
|
1137
|
+
'SELECT',
|
|
1138
|
+
{
|
|
1139
|
+
options: [
|
|
1140
|
+
{ value: 'none', labelKey: 'Settings.Option.ImageMode.None' },
|
|
1141
|
+
{
|
|
1142
|
+
value: 'background',
|
|
1143
|
+
labelKey: 'Settings.Option.ImageMode.Background',
|
|
1144
|
+
},
|
|
1145
|
+
{
|
|
1146
|
+
value: 'photoFrame',
|
|
1147
|
+
labelKey: 'Settings.Option.ImageMode.PhotoFrame',
|
|
1148
|
+
},
|
|
1149
|
+
],
|
|
1150
|
+
},
|
|
611
1151
|
),
|
|
612
1152
|
'lockScreen.backgroundImage': def<string | null>(
|
|
613
1153
|
'lockScreen',
|
|
614
1154
|
'json',
|
|
615
1155
|
null,
|
|
1156
|
+
'CUSTOM_IMAGE',
|
|
616
1157
|
),
|
|
617
1158
|
'lockScreen.photoFrameImages': def<LockScreenImage[]>(
|
|
618
1159
|
'lockScreen',
|
|
619
1160
|
'json',
|
|
620
1161
|
[],
|
|
1162
|
+
'CUSTOM_IMAGE_ARRAY',
|
|
621
1163
|
),
|
|
622
1164
|
'lockScreen.photoFrameIntervalSeconds': def<PhotoFrameIntervalSeconds>(
|
|
623
1165
|
'lockScreen',
|
|
624
1166
|
'number',
|
|
625
1167
|
60,
|
|
1168
|
+
'SELECT',
|
|
1169
|
+
{
|
|
1170
|
+
options: [
|
|
1171
|
+
{ value: 30, labelKey: 'Settings.Option.PhotoFrameInterval.30sec' },
|
|
1172
|
+
{ value: 60, labelKey: 'Settings.Option.PhotoFrameInterval.1min' },
|
|
1173
|
+
{ value: 120, labelKey: 'Settings.Option.PhotoFrameInterval.2min' },
|
|
1174
|
+
{ value: 300, labelKey: 'Settings.Option.PhotoFrameInterval.5min' },
|
|
1175
|
+
],
|
|
1176
|
+
},
|
|
626
1177
|
),
|
|
627
1178
|
|
|
628
1179
|
// ═══════════════════════════════════════════════════════════════════════
|
|
629
1180
|
// Touch / gestures
|
|
630
1181
|
// ═══════════════════════════════════════════════════════════════════════
|
|
631
|
-
'touch.enableTapToCreate': def<boolean>('touch', 'boolean', false),
|
|
632
|
-
'touch.enableDragDrop': def<boolean>('touch', 'boolean', false),
|
|
1182
|
+
'touch.enableTapToCreate': def<boolean>('touch', 'boolean', false, 'TOGGLE'),
|
|
1183
|
+
'touch.enableDragDrop': def<boolean>('touch', 'boolean', false, 'TOGGLE'),
|
|
633
1184
|
|
|
634
1185
|
// ═══════════════════════════════════════════════════════════════════════
|
|
635
1186
|
// Device (not synced unless noted)
|
|
636
1187
|
// ═══════════════════════════════════════════════════════════════════════
|
|
637
|
-
'device.id': def<string>('device', 'string', '', false),
|
|
638
|
-
'device.timePickerMode': def<TimePickerMode>(
|
|
639
|
-
|
|
1188
|
+
'device.id': def<string>('device', 'string', '', 'HIDDEN', { sync: false }),
|
|
1189
|
+
'device.timePickerMode': def<TimePickerMode>(
|
|
1190
|
+
'device',
|
|
1191
|
+
'string',
|
|
1192
|
+
'dials',
|
|
1193
|
+
'SELECT',
|
|
1194
|
+
{
|
|
1195
|
+
options: [
|
|
1196
|
+
{ value: 'dials', labelKey: 'Settings.Option.TimePickerMode.Dials' },
|
|
1197
|
+
{
|
|
1198
|
+
value: 'keypad',
|
|
1199
|
+
labelKey: 'Settings.Option.TimePickerMode.Keypad',
|
|
1200
|
+
},
|
|
1201
|
+
],
|
|
1202
|
+
},
|
|
1203
|
+
),
|
|
1204
|
+
'device.devMenuEnabled': def<boolean>(
|
|
1205
|
+
'device',
|
|
1206
|
+
'boolean',
|
|
1207
|
+
false,
|
|
1208
|
+
'HIDDEN',
|
|
1209
|
+
{ sync: false },
|
|
1210
|
+
),
|
|
640
1211
|
'device.authWarningDismissTtlDays': def<number>(
|
|
641
1212
|
'device',
|
|
642
1213
|
'number',
|
|
643
1214
|
3,
|
|
644
|
-
|
|
1215
|
+
'HIDDEN',
|
|
1216
|
+
{ sync: false },
|
|
645
1217
|
),
|
|
646
1218
|
|
|
647
1219
|
// ═══════════════════════════════════════════════════════════════════════
|
|
@@ -651,27 +1223,42 @@ function buildEntries(config: RegistryConfig) {
|
|
|
651
1223
|
'language',
|
|
652
1224
|
'string',
|
|
653
1225
|
config.defaultLocale,
|
|
1226
|
+
'CUSTOM_LANGUAGE_PICKER',
|
|
1227
|
+
{
|
|
1228
|
+
options: [
|
|
1229
|
+
{ value: 'nb', labelKey: 'Settings.Option.Language.Norwegian' },
|
|
1230
|
+
{ value: 'en', labelKey: 'Settings.Option.Language.English' },
|
|
1231
|
+
],
|
|
1232
|
+
},
|
|
654
1233
|
),
|
|
655
1234
|
|
|
656
1235
|
// ═══════════════════════════════════════════════════════════════════════
|
|
657
1236
|
// Notifications
|
|
658
1237
|
// ═══════════════════════════════════════════════════════════════════════
|
|
659
|
-
'notification.enabled': def<boolean>(
|
|
1238
|
+
'notification.enabled': def<boolean>(
|
|
1239
|
+
'notification',
|
|
1240
|
+
'boolean',
|
|
1241
|
+
false,
|
|
1242
|
+
'TOGGLE',
|
|
1243
|
+
),
|
|
660
1244
|
'notification.notifyAllCalendars': def<boolean>(
|
|
661
1245
|
'notification',
|
|
662
1246
|
'boolean',
|
|
663
1247
|
true,
|
|
1248
|
+
'TOGGLE',
|
|
664
1249
|
),
|
|
665
1250
|
'notification.enabledCalendarIds': def<string[]>(
|
|
666
1251
|
'notification',
|
|
667
1252
|
'json',
|
|
668
1253
|
[],
|
|
1254
|
+
'CUSTOM_CALENDAR_IDS',
|
|
669
1255
|
),
|
|
670
1256
|
'notification.hasBeenPrompted': def<boolean>(
|
|
671
1257
|
'notification',
|
|
672
1258
|
'boolean',
|
|
673
1259
|
false,
|
|
674
|
-
|
|
1260
|
+
'HIDDEN',
|
|
1261
|
+
{ sync: false },
|
|
675
1262
|
),
|
|
676
1263
|
|
|
677
1264
|
// ═══════════════════════════════════════════════════════════════════════
|
|
@@ -682,141 +1269,173 @@ function buildEntries(config: RegistryConfig) {
|
|
|
682
1269
|
'chronological',
|
|
683
1270
|
'boolean',
|
|
684
1271
|
true,
|
|
1272
|
+
'TOGGLE',
|
|
685
1273
|
),
|
|
686
1274
|
'chronological.header.showClock': def<boolean>(
|
|
687
1275
|
'chronological',
|
|
688
1276
|
'boolean',
|
|
689
1277
|
true,
|
|
1278
|
+
'TOGGLE',
|
|
690
1279
|
),
|
|
691
1280
|
'chronological.header.showCurrentYearInDate': def<boolean>(
|
|
692
1281
|
'chronological',
|
|
693
1282
|
'boolean',
|
|
694
1283
|
false,
|
|
1284
|
+
'TOGGLE',
|
|
695
1285
|
),
|
|
696
1286
|
'chronological.header.showTimeOfDay': def<boolean>(
|
|
697
1287
|
'chronological',
|
|
698
1288
|
'boolean',
|
|
699
1289
|
false,
|
|
1290
|
+
'TOGGLE',
|
|
700
1291
|
),
|
|
701
1292
|
// Footer
|
|
702
1293
|
'chronological.footer.showMenuButton': def<boolean>(
|
|
703
1294
|
'chronological',
|
|
704
1295
|
'boolean',
|
|
705
1296
|
true,
|
|
1297
|
+
'TOGGLE',
|
|
706
1298
|
),
|
|
707
1299
|
'chronological.footer.showViewSwitcherDay': def<boolean>(
|
|
708
1300
|
'chronological',
|
|
709
1301
|
'boolean',
|
|
710
1302
|
true,
|
|
1303
|
+
'TOGGLE',
|
|
711
1304
|
),
|
|
712
1305
|
'chronological.footer.showViewSwitcherWeek': def<boolean>(
|
|
713
1306
|
'chronological',
|
|
714
1307
|
'boolean',
|
|
715
1308
|
true,
|
|
1309
|
+
'TOGGLE',
|
|
716
1310
|
),
|
|
717
1311
|
'chronological.footer.showViewSwitcherMonth': def<boolean>(
|
|
718
1312
|
'chronological',
|
|
719
1313
|
'boolean',
|
|
720
1314
|
true,
|
|
1315
|
+
'TOGGLE',
|
|
721
1316
|
),
|
|
722
1317
|
'chronological.footer.showTimerButton': def<boolean>(
|
|
723
1318
|
'chronological',
|
|
724
1319
|
'boolean',
|
|
725
1320
|
true,
|
|
1321
|
+
'TOGGLE',
|
|
726
1322
|
),
|
|
727
1323
|
'chronological.footer.showNewEventButton': def<boolean>(
|
|
728
1324
|
'chronological',
|
|
729
1325
|
'boolean',
|
|
730
1326
|
true,
|
|
1327
|
+
'TOGGLE',
|
|
731
1328
|
),
|
|
732
1329
|
'chronological.footer.showSettingsButton': def<boolean>(
|
|
733
1330
|
'chronological',
|
|
734
1331
|
'boolean',
|
|
735
1332
|
true,
|
|
1333
|
+
'TOGGLE',
|
|
736
1334
|
),
|
|
737
1335
|
// Timer features
|
|
738
1336
|
'chronological.timer.showNewCountdown': def<boolean>(
|
|
739
1337
|
'chronological',
|
|
740
1338
|
'boolean',
|
|
741
1339
|
true,
|
|
1340
|
+
'TOGGLE',
|
|
742
1341
|
),
|
|
743
1342
|
'chronological.timer.showFromTemplate': def<boolean>(
|
|
744
1343
|
'chronological',
|
|
745
1344
|
'boolean',
|
|
746
1345
|
true,
|
|
1346
|
+
'TOGGLE',
|
|
747
1347
|
),
|
|
748
1348
|
'chronological.timer.showEditTemplate': def<boolean>(
|
|
749
1349
|
'chronological',
|
|
750
1350
|
'boolean',
|
|
751
1351
|
true,
|
|
1352
|
+
'TOGGLE',
|
|
752
1353
|
),
|
|
753
1354
|
'chronological.timer.showDeleteTemplate': def<boolean>(
|
|
754
1355
|
'chronological',
|
|
755
1356
|
'boolean',
|
|
756
1357
|
true,
|
|
1358
|
+
'TOGGLE',
|
|
757
1359
|
),
|
|
758
1360
|
'chronological.timer.showAddTemplate': def<boolean>(
|
|
759
1361
|
'chronological',
|
|
760
1362
|
'boolean',
|
|
761
1363
|
true,
|
|
1364
|
+
'TOGGLE',
|
|
762
1365
|
),
|
|
763
1366
|
// Menu
|
|
764
1367
|
'chronological.menu.showSettingsButton': def<boolean>(
|
|
765
1368
|
'chronological',
|
|
766
1369
|
'boolean',
|
|
767
1370
|
true,
|
|
1371
|
+
'TOGGLE',
|
|
768
1372
|
),
|
|
769
1373
|
// Quick settings
|
|
770
1374
|
'chronological.quickSettings.showTimerVolume': def<boolean>(
|
|
771
1375
|
'chronological',
|
|
772
1376
|
'boolean',
|
|
773
1377
|
true,
|
|
1378
|
+
'TOGGLE',
|
|
774
1379
|
),
|
|
775
1380
|
'chronological.quickSettings.showReminderVolume': def<boolean>(
|
|
776
1381
|
'chronological',
|
|
777
1382
|
'boolean',
|
|
778
1383
|
true,
|
|
1384
|
+
'TOGGLE',
|
|
779
1385
|
),
|
|
780
1386
|
'chronological.quickSettings.showMediaVolume': def<boolean>(
|
|
781
1387
|
'chronological',
|
|
782
1388
|
'boolean',
|
|
783
1389
|
true,
|
|
1390
|
+
'TOGGLE',
|
|
784
1391
|
),
|
|
785
1392
|
'chronological.quickSettings.showBrightness': def<boolean>(
|
|
786
1393
|
'chronological',
|
|
787
1394
|
'boolean',
|
|
788
1395
|
true,
|
|
1396
|
+
'TOGGLE',
|
|
789
1397
|
),
|
|
790
1398
|
'chronological.quickSettings.showLockScreen': def<boolean>(
|
|
791
1399
|
'chronological',
|
|
792
1400
|
'boolean',
|
|
793
1401
|
true,
|
|
1402
|
+
'TOGGLE',
|
|
794
1403
|
),
|
|
795
1404
|
// Time-of-day periods
|
|
796
1405
|
'chronological.timeOfDay.morningStart': def<number>(
|
|
797
1406
|
'chronological',
|
|
798
1407
|
'number',
|
|
799
1408
|
6,
|
|
1409
|
+
'SLIDER',
|
|
1410
|
+
{ sliderConfig: TIME_OF_DAY_SLIDER },
|
|
800
1411
|
),
|
|
801
1412
|
'chronological.timeOfDay.forenoonStart': def<number>(
|
|
802
1413
|
'chronological',
|
|
803
1414
|
'number',
|
|
804
1415
|
9,
|
|
1416
|
+
'SLIDER',
|
|
1417
|
+
{ sliderConfig: TIME_OF_DAY_SLIDER },
|
|
805
1418
|
),
|
|
806
1419
|
'chronological.timeOfDay.afternoonStart': def<number>(
|
|
807
1420
|
'chronological',
|
|
808
1421
|
'number',
|
|
809
1422
|
12,
|
|
1423
|
+
'SLIDER',
|
|
1424
|
+
{ sliderConfig: TIME_OF_DAY_SLIDER },
|
|
810
1425
|
),
|
|
811
1426
|
'chronological.timeOfDay.eveningStart': def<number>(
|
|
812
1427
|
'chronological',
|
|
813
1428
|
'number',
|
|
814
1429
|
18,
|
|
1430
|
+
'SLIDER',
|
|
1431
|
+
{ sliderConfig: TIME_OF_DAY_SLIDER },
|
|
815
1432
|
),
|
|
816
1433
|
'chronological.timeOfDay.nightStart': def<number>(
|
|
817
1434
|
'chronological',
|
|
818
1435
|
'number',
|
|
819
1436
|
0,
|
|
1437
|
+
'SLIDER',
|
|
1438
|
+
{ sliderConfig: TIME_OF_DAY_SLIDER },
|
|
820
1439
|
),
|
|
821
1440
|
|
|
822
1441
|
// ═══════════════════════════════════════════════════════════════════════
|
|
@@ -827,80 +1446,115 @@ function buildEntries(config: RegistryConfig) {
|
|
|
827
1446
|
'chronologicalEventForm',
|
|
828
1447
|
'boolean',
|
|
829
1448
|
true,
|
|
1449
|
+
'TOGGLE',
|
|
830
1450
|
),
|
|
831
1451
|
'chronologicalEventForm.field.recurrence': def<boolean>(
|
|
832
1452
|
'chronologicalEventForm',
|
|
833
1453
|
'boolean',
|
|
834
1454
|
true,
|
|
1455
|
+
'TOGGLE',
|
|
835
1456
|
),
|
|
836
1457
|
'chronologicalEventForm.field.acknowledge': def<boolean>(
|
|
837
1458
|
'chronologicalEventForm',
|
|
838
1459
|
'boolean',
|
|
839
1460
|
true,
|
|
1461
|
+
'TOGGLE',
|
|
840
1462
|
),
|
|
841
1463
|
'chronologicalEventForm.field.checklist': def<boolean>(
|
|
842
1464
|
'chronologicalEventForm',
|
|
843
1465
|
'boolean',
|
|
844
1466
|
true,
|
|
1467
|
+
'TOGGLE',
|
|
845
1468
|
),
|
|
846
1469
|
'chronologicalEventForm.field.extraImages': def<boolean>(
|
|
847
1470
|
'chronologicalEventForm',
|
|
848
1471
|
'boolean',
|
|
849
1472
|
true,
|
|
1473
|
+
'TOGGLE',
|
|
850
1474
|
),
|
|
851
1475
|
'chronologicalEventForm.field.reminders': def<boolean>(
|
|
852
1476
|
'chronologicalEventForm',
|
|
853
1477
|
'boolean',
|
|
854
1478
|
true,
|
|
1479
|
+
'TOGGLE',
|
|
855
1480
|
),
|
|
856
1481
|
'chronologicalEventForm.field.audioClips': def<boolean>(
|
|
857
1482
|
'chronologicalEventForm',
|
|
858
1483
|
'boolean',
|
|
859
1484
|
true,
|
|
1485
|
+
'TOGGLE',
|
|
860
1486
|
),
|
|
861
1487
|
// Fixed fields
|
|
862
1488
|
'chronologicalEventForm.fixedField.allDay': def<boolean>(
|
|
863
1489
|
'chronologicalEventForm',
|
|
864
1490
|
'boolean',
|
|
865
1491
|
true,
|
|
1492
|
+
'TOGGLE',
|
|
866
1493
|
),
|
|
867
1494
|
'chronologicalEventForm.fixedField.endTime': def<boolean>(
|
|
868
1495
|
'chronologicalEventForm',
|
|
869
1496
|
'boolean',
|
|
870
1497
|
true,
|
|
1498
|
+
'TOGGLE',
|
|
871
1499
|
),
|
|
872
1500
|
'chronologicalEventForm.fixedField.visibility': def<boolean>(
|
|
873
1501
|
'chronologicalEventForm',
|
|
874
1502
|
'boolean',
|
|
875
1503
|
true,
|
|
1504
|
+
'TOGGLE',
|
|
876
1505
|
),
|
|
877
1506
|
// Suggest end time
|
|
878
1507
|
'chronologicalEventForm.suggestEndTime.enabled': def<boolean>(
|
|
879
1508
|
'chronologicalEventForm',
|
|
880
1509
|
'boolean',
|
|
881
1510
|
false,
|
|
1511
|
+
'TOGGLE',
|
|
882
1512
|
),
|
|
883
1513
|
'chronologicalEventForm.suggestEndTime.value': def<number>(
|
|
884
1514
|
'chronologicalEventForm',
|
|
885
1515
|
'number',
|
|
886
1516
|
30,
|
|
1517
|
+
'SLIDER',
|
|
1518
|
+
{ sliderConfig: { min: 5, max: 480, step: 5 } },
|
|
887
1519
|
),
|
|
888
1520
|
'chronologicalEventForm.suggestEndTime.unit': def<SuggestEndTimeUnit>(
|
|
889
1521
|
'chronologicalEventForm',
|
|
890
1522
|
'string',
|
|
891
1523
|
'minutes',
|
|
1524
|
+
'SELECT',
|
|
1525
|
+
{
|
|
1526
|
+
options: [
|
|
1527
|
+
{
|
|
1528
|
+
value: 'minutes',
|
|
1529
|
+
labelKey: 'Settings.Option.SuggestEndTimeUnit.Minutes',
|
|
1530
|
+
},
|
|
1531
|
+
{
|
|
1532
|
+
value: 'hours',
|
|
1533
|
+
labelKey: 'Settings.Option.SuggestEndTimeUnit.Hours',
|
|
1534
|
+
},
|
|
1535
|
+
],
|
|
1536
|
+
},
|
|
892
1537
|
),
|
|
893
1538
|
// Default visibility
|
|
894
1539
|
'chronologicalEventForm.defaultVisibility': def<EventVisibility>(
|
|
895
1540
|
'chronologicalEventForm',
|
|
896
1541
|
'string',
|
|
897
1542
|
'Private',
|
|
1543
|
+
'SELECT',
|
|
1544
|
+
{
|
|
1545
|
+
options: [
|
|
1546
|
+
{ value: 'Public', labelKey: 'Settings.Option.Visibility.Public' },
|
|
1547
|
+
{ value: 'Private', labelKey: 'Settings.Option.Visibility.Private' },
|
|
1548
|
+
{ value: 'Custom', labelKey: 'Settings.Option.Visibility.Custom' },
|
|
1549
|
+
],
|
|
1550
|
+
},
|
|
898
1551
|
),
|
|
899
1552
|
// Reminder presets
|
|
900
1553
|
'chronologicalEventForm.reminderPresets.timed': def<number[]>(
|
|
901
1554
|
'chronologicalEventForm',
|
|
902
1555
|
'json',
|
|
903
1556
|
[5, 15, 30, 60, 120, 1440],
|
|
1557
|
+
'CUSTOM_REMINDER_PRESETS',
|
|
904
1558
|
),
|
|
905
1559
|
'chronologicalEventForm.reminderPresets.allDay': def<AllDayPreset[]>(
|
|
906
1560
|
'chronologicalEventForm',
|
|
@@ -910,6 +1564,7 @@ function buildEntries(config: RegistryConfig) {
|
|
|
910
1564
|
{ daysBefore: 1, time: '18:00' },
|
|
911
1565
|
{ daysBefore: 2, time: '09:00' },
|
|
912
1566
|
],
|
|
1567
|
+
'CUSTOM_REMINDER_PRESETS',
|
|
913
1568
|
),
|
|
914
1569
|
} as const satisfies Record<string, SettingDef>;
|
|
915
1570
|
}
|
|
@@ -1064,8 +1719,18 @@ export type ParsedSettingEntry = {
|
|
|
1064
1719
|
name: string;
|
|
1065
1720
|
/** Human-readable label (e.g. 'Inactivity Timeout Minutes') */
|
|
1066
1721
|
label: string;
|
|
1722
|
+
/** i18n message key for the label (from SETTINGS_LABELS) */
|
|
1723
|
+
labelKey?: string;
|
|
1724
|
+
/** i18n message key for a description (from SETTINGS_LABELS) */
|
|
1725
|
+
descriptionKey?: string;
|
|
1067
1726
|
/** The setting value */
|
|
1068
1727
|
value: unknown;
|
|
1728
|
+
/** UI component type for rendering this setting */
|
|
1729
|
+
uiType: SettingUiType;
|
|
1730
|
+
/** Available options for SELECT-type settings */
|
|
1731
|
+
options?: readonly SettingOption[];
|
|
1732
|
+
/** Slider configuration for SLIDER-type settings */
|
|
1733
|
+
sliderConfig?: SliderConfig;
|
|
1069
1734
|
};
|
|
1070
1735
|
|
|
1071
1736
|
export type ParsedSettingsGroup = {
|
|
@@ -1122,11 +1787,21 @@ export function parseSettingsSnapshot(
|
|
|
1122
1787
|
if (!groups.has(category)) {
|
|
1123
1788
|
groups.set(category, []);
|
|
1124
1789
|
}
|
|
1790
|
+
|
|
1791
|
+
const labelDef = SETTINGS_LABELS[key];
|
|
1792
|
+
const entryDef = key in registry.entries
|
|
1793
|
+
? registry.entries[key as SettingKey]
|
|
1794
|
+
: undefined;
|
|
1125
1795
|
groups.get(category)!.push({
|
|
1126
1796
|
key,
|
|
1127
1797
|
name,
|
|
1128
1798
|
label: registry.getSettingLabel(key),
|
|
1799
|
+
labelKey: labelDef?.labelKey,
|
|
1800
|
+
descriptionKey: labelDef?.descriptionKey,
|
|
1129
1801
|
value,
|
|
1802
|
+
uiType: entryDef?.uiType ?? 'TEXT_INPUT',
|
|
1803
|
+
...(entryDef?.options && { options: entryDef.options as readonly SettingOption[] }),
|
|
1804
|
+
...(entryDef?.sliderConfig && { sliderConfig: entryDef.sliderConfig }),
|
|
1130
1805
|
});
|
|
1131
1806
|
}
|
|
1132
1807
|
|