1package config
2
3import (
4 "fmt"
5
6 "github.com/bnema/dumber/internal/domain/entity"
7)
8
9// Section names for grouping config keys.
10const (
11 SectionAppearance = "Appearance"
12 SectionLogging = "Logging"
13 SectionHistory = "History"
14 SectionWorkspace = "Workspace"
15 SectionSession = "Session"
16 SectionOmnibox = "Omnibox"
17 SectionClipboard = "Clipboard"
18 SectionContentFiltering = "Content Filtering"
19 SectionRendering = "Rendering"
20 SectionMedia = "Media"
21 SectionPrivacy = "Privacy"
22 SectionUpdate = "Update"
23 SectionDmenu = "Dmenu"
24 SectionDebug = "Debug"
25 SectionPerformance = "Performance"
26 SectionRuntime = "Runtime"
27 SectionDatabase = "Database"
28 SectionSearch = "Search"
29 SectionDownloads = "Downloads"
30)
31
32// SchemaProvider implements port.ConfigSchemaProvider.
33type SchemaProvider struct{}
34
35// NewSchemaProvider creates a new SchemaProvider.
36func NewSchemaProvider() *SchemaProvider {
37 return &SchemaProvider{}
38}
39
40// GetSchema returns all configuration keys with their metadata.
41func (p *SchemaProvider) GetSchema() []entity.ConfigKeyInfo {
42 defaults := DefaultConfig()
43
44 keys := make([]entity.ConfigKeyInfo, 0, 100)
45
46 // Appearance section
47 keys = append(keys, p.getAppearanceKeys(defaults)...)
48
49 // Logging section
50 keys = append(keys, p.getLoggingKeys(defaults)...)
51
52 // History section
53 keys = append(keys, p.getHistoryKeys(defaults)...)
54
55 // Search section
56 keys = append(keys, p.getSearchKeys(defaults)...)
57
58 // Dmenu section
59 keys = append(keys, p.getDmenuKeys(defaults)...)
60
61 // Workspace section
62 keys = append(keys, p.getWorkspaceKeys(defaults)...)
63
64 // Session section
65 keys = append(keys, p.getSessionKeys(defaults)...)
66
67 // Omnibox section
68 keys = append(keys, p.getOmniboxKeys(defaults)...)
69
70 // Clipboard section
71 keys = append(keys, p.getClipboardKeys(defaults)...)
72
73 // Content Filtering section
74 keys = append(keys, p.getContentFilteringKeys(defaults)...)
75
76 // Rendering section
77 keys = append(keys, p.getRenderingKeys(defaults)...)
78
79 // Media section
80 keys = append(keys, p.getMediaKeys(defaults)...)
81
82 // Privacy section
83 keys = append(keys, p.getPrivacyKeys(defaults)...)
84
85 // Update section
86 keys = append(keys, p.getUpdateKeys(defaults)...)
87
88 // Debug section
89 keys = append(keys, p.getDebugKeys(defaults)...)
90
91 // Performance section
92 keys = append(keys, p.getPerformanceKeys(defaults)...)
93
94 // Runtime section
95 keys = append(keys, p.getRuntimeKeys(defaults)...)
96
97 // Database section
98 keys = append(keys, p.getDatabaseKeys()...)
99
100 // Downloads section
101 keys = append(keys, p.getDownloadsKeys(defaults)...)
102
103 return keys
104}
105
106func (*SchemaProvider) getAppearanceKeys(defaults *Config) []entity.ConfigKeyInfo {
107 return []entity.ConfigKeyInfo{
108 {
109 Key: "appearance.color_scheme",
110 Type: "string",
111 Default: defaults.Appearance.ColorScheme,
112 Description: "Theme preference (follows system by default)",
113 Values: []string{"default", "prefer-dark", "prefer-light"},
114 Section: SectionAppearance,
115 },
116 {
117 Key: "appearance.default_font_size",
118 Type: "int",
119 Default: fmt.Sprintf("%d", defaults.Appearance.DefaultFontSize),
120 Description: "Default font size in CSS pixels",
121 Range: "1-72",
122 Section: SectionAppearance,
123 },
124 {
125 Key: "appearance.sans_font",
126 Type: "string",
127 Default: defaults.Appearance.SansFont,
128 Description: "Sans-serif font family for web pages",
129 Section: SectionAppearance,
130 },
131 {
132 Key: "appearance.serif_font",
133 Type: "string",
134 Default: defaults.Appearance.SerifFont,
135 Description: "Serif font family for web pages",
136 Section: SectionAppearance,
137 },
138 {
139 Key: "appearance.monospace_font",
140 Type: "string",
141 Default: defaults.Appearance.MonospaceFont,
142 Description: "Monospace font family for code",
143 Section: SectionAppearance,
144 },
145 {
146 Key: "appearance.gtk_font",
147 Type: "string",
148 Default: defaults.Appearance.GtkFont,
149 Description: "Native GTK UI font family for app chrome",
150 Section: SectionAppearance,
151 },
152 {
153 Key: "default_webpage_zoom",
154 Type: "float64",
155 Default: fmt.Sprintf("%.1f", defaults.DefaultWebpageZoom),
156 Description: "Default zoom level for web pages (1.0 = 100%%)",
157 Range: "0.1-5.0",
158 Section: SectionAppearance,
159 },
160 {
161 Key: "default_ui_scale",
162 Type: "float64",
163 Default: fmt.Sprintf("%.1f", defaults.DefaultUIScale),
164 Description: "UI scale multiplier for GTK widgets",
165 Range: "0.5-3.0",
166 Section: SectionAppearance,
167 },
168 {
169 Key: "sidebar_width",
170 Type: "int",
171 Default: fmt.Sprintf("%d", defaults.SidebarWidth),
172 Description: "Preferred width (px) for the history sidebar. 0 = default",
173 Range: "0 or 280-380",
174 Section: SectionAppearance,
175 },
176 {
177 Key: "appearance.light_palette.*",
178 Type: "string",
179 Default: "(hex colors)",
180 Description: "Light theme color palette (background, surface, surface_variant, text, muted, accent, border)",
181 Section: SectionAppearance,
182 },
183 {
184 Key: "appearance.dark_palette.*",
185 Type: "string",
186 Default: "(hex colors)",
187 Description: "Dark theme color palette (background, surface, surface_variant, text, muted, accent, border)",
188 Section: SectionAppearance,
189 },
190 {
191 Key: "appearance.external_theme.enabled",
192 Type: "bool",
193 Default: fmt.Sprintf("%t", defaults.Appearance.ExternalTheme.Enabled),
194 Description: "Enable loading theme settings from an external provider",
195 Section: SectionAppearance,
196 },
197 {
198 Key: "appearance.external_theme.provider",
199 Type: "string",
200 Default: defaults.Appearance.ExternalTheme.Provider,
201 Description: "External theme provider",
202 Values: []string{"noctalia"},
203 Section: SectionAppearance,
204 },
205 {
206 Key: "appearance.external_theme.format",
207 Type: "string",
208 Default: defaults.Appearance.ExternalTheme.Format,
209 Description: "External theme file format",
210 Values: []string{"colors-json", "dumber-json"},
211 Section: SectionAppearance,
212 },
213 {
214 Key: "appearance.external_theme.path",
215 Type: "string",
216 Default: defaults.Appearance.ExternalTheme.Path,
217 Description: "Path to the external theme file",
218 Section: SectionAppearance,
219 },
220 }
221}
222
223func (*SchemaProvider) getLoggingKeys(defaults *Config) []entity.ConfigKeyInfo {
224 return []entity.ConfigKeyInfo{
225 {
226 Key: "logging.level",
227 Type: "string",
228 Default: defaults.Logging.Level,
229 Description: "Log verbosity level",
230 Values: []string{"trace", "debug", "info", "warn", "error", "fatal"},
231 Section: SectionLogging,
232 },
233 {
234 Key: "logging.format",
235 Type: "string",
236 Default: defaults.Logging.Format,
237 Description: "Log output format",
238 Values: []string{"text", "json", "console"},
239 Section: SectionLogging,
240 },
241 {
242 Key: "logging.max_age",
243 Type: "int",
244 Default: fmt.Sprintf("%d", defaults.Logging.MaxAge),
245 Description: "Maximum age of log files in days",
246 Range: ">=0",
247 Section: SectionLogging,
248 },
249 {
250 Key: "logging.max_files",
251 Type: "int",
252 Default: fmt.Sprintf("%d", defaults.Logging.MaxFiles),
253 Description: "Maximum number of session log files to keep (0 disables count-based cleanup)",
254 Range: ">=0",
255 Section: SectionLogging,
256 },
257 {
258 Key: "logging.log_dir",
259 Type: "string",
260 Default: defaults.Logging.LogDir,
261 Description: "Directory for log files",
262 Section: SectionLogging,
263 },
264 {
265 Key: "logging.enable_file_log",
266 Type: "bool",
267 Default: fmt.Sprintf("%t", defaults.Logging.EnableFileLog),
268 Description: "Enable logging to file",
269 Section: SectionLogging,
270 },
271 {
272 Key: "logging.capture_console",
273 Type: "bool",
274 Default: fmt.Sprintf("%t", defaults.Logging.CaptureConsole),
275 Description: "Capture browser console messages to log",
276 Section: SectionLogging,
277 },
278 {
279 Key: "logging.capture_gtk_logs",
280 Type: "bool",
281 Default: fmt.Sprintf("%t", defaults.Logging.CaptureGTKLogs),
282 Description: "Capture GTK and GLib log messages",
283 Section: SectionLogging,
284 },
285 }
286}
287
288func (*SchemaProvider) getHistoryKeys(defaults *Config) []entity.ConfigKeyInfo {
289 return []entity.ConfigKeyInfo{
290 {
291 Key: "history.max_entries",
292 Type: "int",
293 Default: fmt.Sprintf("%d", defaults.History.MaxEntries),
294 Description: "Maximum number of history entries to keep",
295 Range: ">=0",
296 Section: SectionHistory,
297 },
298 {
299 Key: "history.retention_period_days",
300 Type: "int",
301 Default: fmt.Sprintf("%d", defaults.History.RetentionPeriodDays),
302 Description: "Number of days to retain history",
303 Range: ">=0",
304 Section: SectionHistory,
305 },
306 {
307 Key: "history.cleanup_interval_days",
308 Type: "int",
309 Default: fmt.Sprintf("%d", defaults.History.CleanupIntervalDays),
310 Description: "Days between automatic history cleanup",
311 Range: ">=0",
312 Section: SectionHistory,
313 },
314 }
315}
316
317func (*SchemaProvider) getSearchKeys(defaults *Config) []entity.ConfigKeyInfo {
318 return []entity.ConfigKeyInfo{
319 {
320 Key: "default_search_engine",
321 Type: "string",
322 Default: defaults.DefaultSearchEngine,
323 Description: "Default search engine URL (must contain %s placeholder)",
324 Section: SectionSearch,
325 },
326 {
327 Key: "search_shortcuts.<key>",
328 Type: "object",
329 Default: "(see defaults)",
330 Description: "Search shortcuts map with url and description fields",
331 Section: SectionSearch,
332 },
333 }
334}
335
336func (*SchemaProvider) getDmenuKeys(defaults *Config) []entity.ConfigKeyInfo {
337 return []entity.ConfigKeyInfo{
338 {
339 Key: "dmenu.max_history_days",
340 Type: "int",
341 Default: fmt.Sprintf("%d", defaults.Dmenu.MaxHistoryDays),
342 Description: "Number of days of history to show in dmenu (0 = all)",
343 Range: ">=0",
344 Section: SectionDmenu,
345 },
346 {
347 Key: "dmenu.show_visit_count",
348 Type: "bool",
349 Default: fmt.Sprintf("%t", defaults.Dmenu.ShowVisitCount),
350 Description: "Show visit count in dmenu entries",
351 Section: SectionDmenu,
352 },
353 {
354 Key: "dmenu.show_last_visited",
355 Type: "bool",
356 Default: fmt.Sprintf("%t", defaults.Dmenu.ShowLastVisited),
357 Description: "Show last visited date in dmenu entries",
358 Section: SectionDmenu,
359 },
360 {
361 Key: "dmenu.history_prefix",
362 Type: "string",
363 Default: defaults.Dmenu.HistoryPrefix,
364 Description: "Prefix for history entries in dmenu",
365 Section: SectionDmenu,
366 },
367 {
368 Key: "dmenu.shortcut_prefix",
369 Type: "string",
370 Default: defaults.Dmenu.ShortcutPrefix,
371 Description: "Prefix for search shortcuts in dmenu",
372 Section: SectionDmenu,
373 },
374 {
375 Key: "dmenu.url_prefix",
376 Type: "string",
377 Default: defaults.Dmenu.URLPrefix,
378 Description: "Prefix for URL entries in dmenu",
379 Section: SectionDmenu,
380 },
381 {
382 Key: "dmenu.date_format",
383 Type: "string",
384 Default: defaults.Dmenu.DateFormat,
385 Description: "Go time format for dates in dmenu",
386 Section: SectionDmenu,
387 },
388 {
389 Key: "dmenu.sort_by_visit_count",
390 Type: "bool",
391 Default: fmt.Sprintf("%t", defaults.Dmenu.SortByVisitCount),
392 Description: "Sort dmenu entries by visit count",
393 Section: SectionDmenu,
394 },
395 }
396}
397
398func (*SchemaProvider) getWorkspaceKeys(defaults *Config) []entity.ConfigKeyInfo {
399 return []entity.ConfigKeyInfo{
400 {
401 Key: "workspace.new_pane_url",
402 Type: "string",
403 Default: defaults.Workspace.NewPaneURL,
404 Description: "URL loaded when creating a new pane",
405 Section: SectionWorkspace,
406 },
407 {
408 Key: "workspace.tab_bar_position",
409 Type: "string",
410 Default: defaults.Workspace.TabBarPosition,
411 Description: "Position of the tab bar",
412 Values: []string{"top", "bottom"},
413 Section: SectionWorkspace,
414 },
415 {
416 Key: "workspace.hide_tab_bar_when_single_tab",
417 Type: "bool",
418 Default: fmt.Sprintf("%t", defaults.Workspace.HideTabBarWhenSingleTab),
419 Description: "Hide tab bar when only one tab exists",
420 Section: SectionWorkspace,
421 },
422 {
423 Key: "workspace.switch_to_tab_on_move",
424 Type: "bool",
425 Default: fmt.Sprintf("%t", defaults.Workspace.SwitchToTabOnMove),
426 Description: "Switch focus to tab when moving pane to it",
427 Section: SectionWorkspace,
428 },
429 // Pane mode
430 {
431 Key: "workspace.pane_mode.activation_shortcut",
432 Type: "string",
433 Default: defaults.Workspace.PaneMode.ActivationShortcut,
434 Description: "Shortcut to enter pane mode",
435 Section: SectionWorkspace,
436 },
437 {
438 Key: "workspace.pane_mode.timeout_ms",
439 Type: "int",
440 Default: fmt.Sprintf("%d", defaults.Workspace.PaneMode.TimeoutMilliseconds),
441 Description: "Pane mode timeout in milliseconds (0 = no timeout)",
442 Range: ">=0",
443 Section: SectionWorkspace,
444 },
445 {
446 Key: "workspace.pane_mode.actions.<action>",
447 Type: "[]string",
448 Default: "(see defaults)",
449 Description: "Key bindings for pane mode actions",
450 Section: SectionWorkspace,
451 },
452 // Tab mode
453 {
454 Key: "workspace.tab_mode.activation_shortcut",
455 Type: "string",
456 Default: defaults.Workspace.TabMode.ActivationShortcut,
457 Description: "Shortcut to enter tab mode",
458 Section: SectionWorkspace,
459 },
460 {
461 Key: "workspace.tab_mode.timeout_ms",
462 Type: "int",
463 Default: fmt.Sprintf("%d", defaults.Workspace.TabMode.TimeoutMilliseconds),
464 Description: "Tab mode timeout in milliseconds (0 = no timeout)",
465 Range: ">=0",
466 Section: SectionWorkspace,
467 },
468 {
469 Key: "workspace.tab_mode.actions.<action>",
470 Type: "[]string",
471 Default: "(see defaults)",
472 Description: "Key bindings for tab mode actions",
473 Section: SectionWorkspace,
474 },
475 // Vim mode
476 {
477 Key: "workspace.vim_mode.activation_shortcut",
478 Type: "string",
479 Default: defaults.Workspace.VimMode.ActivationShortcut,
480 Description: "Shortcut to enter vim scroll mode",
481 Section: SectionWorkspace,
482 },
483 {
484 Key: "workspace.vim_mode.timeout_ms",
485 Type: "int",
486 Default: fmt.Sprintf("%d", defaults.Workspace.VimMode.TimeoutMilliseconds),
487 Description: "Vim mode timeout in milliseconds (0 = no timeout)",
488 Range: ">=0",
489 Section: SectionWorkspace,
490 },
491 {
492 Key: "workspace.vim_mode.sequence_timeout_ms",
493 Type: "int",
494 Default: fmt.Sprintf("%d", defaults.Workspace.VimMode.SequenceTimeoutMilliseconds),
495 Description: "Vim mode multi-key sequence timeout in milliseconds (0 = immediate ambiguity resolution)",
496 Range: ">=0",
497 Section: SectionWorkspace,
498 },
499 {
500 Key: "workspace.vim_mode.preload_accessibility",
501 Type: "bool",
502 Default: fmt.Sprintf("%t", defaults.Workspace.VimMode.PreloadAccessibility),
503 Description: "Pre-enable browser accessibility when a WebView is shown (default false; enable on Vim Mode enter otherwise)",
504 Section: SectionWorkspace,
505 },
506 {
507 Key: "workspace.vim_mode.actions.<action>",
508 Type: "object",
509 Default: "(see defaults)",
510 Description: "Vim mode action object with keys ([]string) and desc (string)",
511 Section: SectionWorkspace,
512 },
513 // Resize mode
514 {
515 Key: "workspace.resize_mode.activation_shortcut",
516 Type: "string",
517 Default: defaults.Workspace.ResizeMode.ActivationShortcut,
518 Description: "Shortcut to enter resize mode",
519 Section: SectionWorkspace,
520 },
521 {
522 Key: "workspace.resize_mode.timeout_ms",
523 Type: "int",
524 Default: fmt.Sprintf("%d", defaults.Workspace.ResizeMode.TimeoutMilliseconds),
525 Description: "Resize mode timeout in milliseconds (0 = no timeout)",
526 Range: ">=0",
527 Section: SectionWorkspace,
528 },
529 {
530 Key: "workspace.resize_mode.step_percent",
531 Type: "float64",
532 Default: fmt.Sprintf("%.1f", defaults.Workspace.ResizeMode.StepPercent),
533 Description: "Percentage to resize panes per step",
534 Section: SectionWorkspace,
535 },
536 {
537 Key: "workspace.resize_mode.min_pane_percent",
538 Type: "float64",
539 Default: fmt.Sprintf("%.1f", defaults.Workspace.ResizeMode.MinPanePercent),
540 Description: "Minimum pane size as percentage",
541 Section: SectionWorkspace,
542 },
543 {
544 Key: "workspace.resize_mode.actions.<action>",
545 Type: "[]string",
546 Default: "(see defaults)",
547 Description: "Key bindings for resize mode actions",
548 Section: SectionWorkspace,
549 },
550 // Global shortcuts - managed via dedicated keybindings UI
551 {
552 Key: "workspace.shortcuts.actions",
553 Type: "object",
554 Default: "(see defaults)",
555 Description: "Global keyboard shortcuts (use Keybindings tab to edit)",
556 Section: SectionWorkspace,
557 },
558 // Floating pane
559 {
560 Key: "workspace.floating_pane.width_pct",
561 Type: "float64",
562 Default: fmt.Sprintf("%.2f", defaults.Workspace.FloatingPane.WidthPct),
563 Description: "Floating pane width as a fraction of workspace width",
564 Range: "(0,1]",
565 Section: SectionWorkspace,
566 },
567 {
568 Key: "workspace.floating_pane.height_pct",
569 Type: "float64",
570 Default: fmt.Sprintf("%.2f", defaults.Workspace.FloatingPane.HeightPct),
571 Description: "Floating pane height as a fraction of workspace height",
572 Range: "(0,1]",
573 Section: SectionWorkspace,
574 },
575 {
576 Key: "workspace.floating_pane.profiles.<name>",
577 Type: "object",
578 Default: "(empty)",
579 Description: "Named floating pane URL profiles with keys, url, and optional desc",
580 Section: SectionWorkspace,
581 },
582 // External links
583 {
584 Key: "workspace.external_links.behavior",
585 Type: "string",
586 Default: string(defaults.Workspace.ExternalLinks.Behavior),
587 Description: "How URLs opened from external applications are placed",
588 Values: []string{"windowed", "tabbed", "split", "stacked"},
589 Section: SectionWorkspace,
590 },
591 {
592 Key: "workspace.external_links.placement",
593 Type: "string",
594 Default: string(defaults.Workspace.ExternalLinks.Placement),
595 Description: "Placement direction for split external links",
596 Values: []string{"right", "left", "top", "bottom"},
597 Section: SectionWorkspace,
598 },
599 // Browsing contexts
600 {
601 Key: "workspace.browsing_contexts.behavior",
602 Type: "string",
603 Default: string(defaults.Workspace.BrowsingContexts.Behavior),
604 Description: "How to handle JavaScript popup windows",
605 Values: []string{"split", "stacked", "tabbed", "windowed"},
606 Section: SectionWorkspace,
607 },
608 {
609 Key: "workspace.browsing_contexts.placement",
610 Type: "string",
611 Default: defaults.Workspace.BrowsingContexts.Placement,
612 Description: "Placement direction for split popups",
613 Values: []string{"right", "left", "top", "bottom"},
614 Section: SectionWorkspace,
615 },
616 {
617 Key: "workspace.browsing_contexts.blank_target_behavior",
618 Type: "string",
619 Default: defaults.Workspace.BrowsingContexts.BlankTargetBehavior,
620 Description: "How to handle target=\"_blank\" links",
621 Values: []string{"split", "stacked", "tabbed"},
622 Section: SectionWorkspace,
623 },
624 {
625 Key: "workspace.browsing_contexts.open_in_new_pane",
626 Type: "bool",
627 Default: fmt.Sprintf("%t", defaults.Workspace.BrowsingContexts.OpenInNewPane),
628 Description: "Open popups in workspace instead of blocking",
629 Section: SectionWorkspace,
630 },
631 {
632 Key: "workspace.browsing_contexts.follow_pane_context",
633 Type: "bool",
634 Default: fmt.Sprintf("%t", defaults.Workspace.BrowsingContexts.FollowPaneContext),
635 Description: "Popup placement follows parent pane context",
636 Section: SectionWorkspace,
637 },
638 {
639 Key: "workspace.browsing_contexts.enable_smart_detection",
640 Type: "bool",
641 Default: fmt.Sprintf("%t", defaults.Workspace.BrowsingContexts.EnableSmartDetection),
642 Description: "Use window properties to detect popup intent",
643 Section: SectionWorkspace,
644 },
645 {
646 Key: "workspace.browsing_contexts.oauth_auto_close",
647 Type: "bool",
648 Default: fmt.Sprintf("%t", defaults.Workspace.BrowsingContexts.OAuthAutoClose),
649 Description: "Auto-close OAuth popups after success",
650 Section: SectionWorkspace,
651 },
652 // Styling
653 {
654 Key: "workspace.styling.border_width",
655 Type: "int",
656 Default: fmt.Sprintf("%d", defaults.Workspace.Styling.BorderWidth),
657 Description: "Active pane border width in pixels",
658 Range: ">=0",
659 Section: SectionWorkspace,
660 },
661 {
662 Key: "workspace.styling.border_color",
663 Type: "string",
664 Default: defaults.Workspace.Styling.BorderColor,
665 Description: "Active pane border color (CSS or @theme variable)",
666 Section: SectionWorkspace,
667 },
668 {
669 Key: "workspace.styling.mode_border_width",
670 Type: "int",
671 Default: fmt.Sprintf("%d", defaults.Workspace.Styling.ModeBorderWidth),
672 Description: "Border width for modal mode indicators",
673 Range: ">=0",
674 Section: SectionWorkspace,
675 },
676 {
677 Key: "workspace.styling.pane_mode_color",
678 Type: "string",
679 Default: defaults.Workspace.Styling.PaneModeColor,
680 Description: "Color for pane mode indicator",
681 Section: SectionWorkspace,
682 },
683 {
684 Key: "workspace.styling.tab_mode_color",
685 Type: "string",
686 Default: defaults.Workspace.Styling.TabModeColor,
687 Description: "Color for tab mode indicator",
688 Section: SectionWorkspace,
689 },
690 {
691 Key: "workspace.styling.session_mode_color",
692 Type: "string",
693 Default: defaults.Workspace.Styling.SessionModeColor,
694 Description: "Color for session mode indicator",
695 Section: SectionWorkspace,
696 },
697 {
698 Key: "workspace.styling.resize_mode_color",
699 Type: "string",
700 Default: defaults.Workspace.Styling.ResizeModeColor,
701 Description: "Color for resize mode indicator",
702 Section: SectionWorkspace,
703 },
704 {
705 Key: "workspace.styling.mode_indicator_toaster_enabled",
706 Type: "bool",
707 Default: fmt.Sprintf("%t", defaults.Workspace.Styling.ModeIndicatorToasterEnabled),
708 Description: "Show toaster notification for modal modes",
709 Section: SectionWorkspace,
710 },
711 {
712 Key: "workspace.styling.transition_duration",
713 Type: "int",
714 Default: fmt.Sprintf("%d", defaults.Workspace.Styling.TransitionDuration),
715 Description: "Border animation duration in milliseconds",
716 Range: ">=0",
717 Section: SectionWorkspace,
718 },
719 }
720}
721
722func (*SchemaProvider) getSessionKeys(defaults *Config) []entity.ConfigKeyInfo {
723 return []entity.ConfigKeyInfo{
724 {
725 Key: "session.auto_restore",
726 Type: "bool",
727 Default: fmt.Sprintf("%t", defaults.Session.AutoRestore),
728 Description: "Automatically restore last session on startup",
729 Section: SectionSession,
730 },
731 {
732 Key: "session.snapshot_interval_ms",
733 Type: "int",
734 Default: fmt.Sprintf("%d", defaults.Session.SnapshotIntervalMs),
735 Description: "Minimum interval between session snapshots",
736 Range: ">=0",
737 Section: SectionSession,
738 },
739 {
740 Key: "session.max_exited_sessions",
741 Type: "int",
742 Default: fmt.Sprintf("%d", defaults.Session.MaxExitedSessions),
743 Description: "Maximum number of exited sessions to keep",
744 Range: ">=0",
745 Section: SectionSession,
746 },
747 {
748 Key: "session.max_exited_session_age_days",
749 Type: "int",
750 Default: fmt.Sprintf("%d", defaults.Session.MaxExitedSessionAgeDays),
751 Description: "Maximum age of exited sessions in days",
752 Range: ">=0",
753 Section: SectionSession,
754 },
755 {
756 Key: "session.session_mode.activation_shortcut",
757 Type: "string",
758 Default: defaults.Session.SessionMode.ActivationShortcut,
759 Description: "Shortcut to enter session mode",
760 Section: SectionSession,
761 },
762 {
763 Key: "session.session_mode.timeout_ms",
764 Type: "int",
765 Default: fmt.Sprintf("%d", defaults.Session.SessionMode.TimeoutMilliseconds),
766 Description: "Session mode timeout in milliseconds",
767 Range: ">=0",
768 Section: SectionSession,
769 },
770 {
771 Key: "session.session_mode.actions.<action>",
772 Type: "[]string",
773 Default: "(see defaults)",
774 Description: "Key bindings for session mode actions",
775 Section: SectionSession,
776 },
777 }
778}
779
780func (*SchemaProvider) getOmniboxKeys(defaults *Config) []entity.ConfigKeyInfo {
781 return []entity.ConfigKeyInfo{
782 {
783 Key: "omnibox.initial_behavior",
784 Type: "string",
785 Default: string(defaults.Omnibox.InitialBehavior),
786 Description: "What to show when omnibox opens with empty input",
787 Values: []string{
788 string(OmniboxInitialBehaviorRecent),
789 string(OmniboxInitialBehaviorMostVisited),
790 string(OmniboxInitialBehaviorNone),
791 },
792 Section: SectionOmnibox,
793 },
794 {
795 Key: "omnibox.most_visited_days",
796 Type: "int",
797 Default: fmt.Sprintf("%d", defaults.Omnibox.MostVisitedDays),
798 Description: "Days of history to consider for most_visited (0 = all history)",
799 Range: ">=0",
800 Section: SectionOmnibox,
801 },
802 {
803 Key: "omnibox.auto_open_on_new_pane",
804 Type: "bool",
805 Default: fmt.Sprintf("%t", defaults.Omnibox.AutoOpenOnNewPane),
806 Description: "Auto-open omnibox when creating new pane",
807 Section: SectionOmnibox,
808 },
809 }
810}
811
812func (*SchemaProvider) getContentFilteringKeys(defaults *Config) []entity.ConfigKeyInfo {
813 return []entity.ConfigKeyInfo{
814 {
815 Key: "content_filtering.enabled",
816 Type: "bool",
817 Default: fmt.Sprintf("%t", defaults.ContentFiltering.Enabled),
818 Description: "Enable ad blocking and content filtering",
819 Section: SectionContentFiltering,
820 },
821 {
822 Key: "content_filtering.auto_update",
823 Type: "bool",
824 Default: fmt.Sprintf("%t", defaults.ContentFiltering.AutoUpdate),
825 Description: "Auto-update filter lists from GitHub",
826 Section: SectionContentFiltering,
827 },
828 }
829}
830
831func (*SchemaProvider) getClipboardKeys(defaults *Config) []entity.ConfigKeyInfo {
832 return []entity.ConfigKeyInfo{
833 {
834 Key: "clipboard.auto_copy_on_selection",
835 Type: "bool",
836 Default: fmt.Sprintf("%t", defaults.Clipboard.AutoCopyOnSelection),
837 Description: "Auto-copy selected text to clipboard (zellij-style)",
838 Section: SectionClipboard,
839 },
840 }
841}
842
843func (*SchemaProvider) getRenderingKeys(defaults *Config) []entity.ConfigKeyInfo {
844 return []entity.ConfigKeyInfo{
845 {
846 Key: "engine.type",
847 Type: "string",
848 Default: defaults.Engine.Type,
849 Description: "Browser engine selection; CEF is the default and WebKitGTK is the fallback",
850 Values: []string{"cef", "webkit"},
851 Section: SectionRendering,
852 },
853 {
854 Key: "engine.webkit.gsk_renderer",
855 Type: "string",
856 Default: string(defaults.Engine.WebKit.GSKRenderer),
857 Description: "GTK Scene Kit renderer selection",
858 Values: []string{"auto", "opengl", "vulkan", "cairo"},
859 Section: SectionRendering,
860 },
861 {
862 Key: "engine.webkit.disable_dmabuf_renderer",
863 Type: "bool",
864 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.DisableDMABufRenderer),
865 Description: "Disable DMA-BUF accelerated renderer",
866 Section: SectionRendering,
867 },
868 {
869 Key: "engine.webkit.force_compositing_mode",
870 Type: "bool",
871 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.ForceCompositingMode),
872 Description: "Force accelerated compositing",
873 Section: SectionRendering,
874 },
875 {
876 Key: "engine.webkit.disable_compositing_mode",
877 Type: "bool",
878 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.DisableCompositingMode),
879 Description: "Disable accelerated compositing",
880 Section: SectionRendering,
881 },
882 {
883 Key: "engine.webkit.disable_mipmaps",
884 Type: "bool",
885 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.DisableMipmaps),
886 Description: "Disable mipmap generation",
887 Section: SectionRendering,
888 },
889 {
890 Key: "engine.webkit.prefer_gl",
891 Type: "bool",
892 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.PreferGL),
893 Description: "Force OpenGL over GLES",
894 Section: SectionRendering,
895 },
896 {
897 Key: "engine.webkit.draw_compositing_indicators",
898 Type: "bool",
899 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.DrawCompositingIndicators),
900 Description: "Show compositing layer borders",
901 Section: SectionRendering,
902 },
903 {
904 Key: "engine.webkit.show_fps",
905 Type: "bool",
906 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.ShowFPS),
907 Description: "Display WebKit FPS counter",
908 Section: SectionRendering,
909 },
910 {
911 Key: "engine.webkit.sample_memory",
912 Type: "bool",
913 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.SampleMemory),
914 Description: "Enable memory sampling",
915 Section: SectionRendering,
916 },
917 {
918 Key: "engine.webkit.debug_frames",
919 Type: "bool",
920 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.DebugFrames),
921 Description: "Enable frame timing debug output",
922 Section: SectionRendering,
923 },
924 }
925}
926
927func (*SchemaProvider) getMediaKeys(defaults *Config) []entity.ConfigKeyInfo {
928 return []entity.ConfigKeyInfo{
929 {
930 Key: "media.hardware_decoding",
931 Type: "string",
932 Default: string(defaults.Media.HardwareDecodingMode),
933 Description: "Hardware vs software video decoding",
934 Values: []string{"auto", "force", "disable"},
935 Section: SectionMedia,
936 },
937 {
938 Key: "media.prefer_av1",
939 Type: "bool",
940 Default: fmt.Sprintf("%t", defaults.Media.PreferAV1),
941 Description: "Prioritize AV1 codec when available",
942 Section: SectionMedia,
943 },
944 {
945 Key: "media.show_diagnostics",
946 Type: "bool",
947 Default: fmt.Sprintf("%t", defaults.Media.ShowDiagnosticsOnStartup),
948 Description: "Show media capability warnings at startup",
949 Section: SectionMedia,
950 },
951 {
952 Key: "engine.webkit.force_vsync",
953 Type: "bool",
954 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.ForceVSync),
955 Description: "Force VSync for WebKit fallback video playback",
956 Section: SectionMedia,
957 },
958 {
959 Key: "engine.webkit.gl_rendering_mode",
960 Type: "string",
961 Default: string(defaults.Engine.WebKit.GLRenderingMode),
962 Description: "WebKit fallback GStreamer/OpenGL API selection",
963 Values: []string{"auto", "gles2", "gl3", "none"},
964 Section: SectionMedia,
965 },
966 {
967 Key: "engine.webkit.gstreamer_debug_level",
968 Type: "int",
969 Default: fmt.Sprintf("%d", defaults.Engine.WebKit.GStreamerDebugLevel),
970 Description: "WebKit fallback GStreamer debug verbosity",
971 Range: "0-5",
972 Section: SectionMedia,
973 },
974 }
975}
976
977func (*SchemaProvider) getPrivacyKeys(defaults *Config) []entity.ConfigKeyInfo {
978 return []entity.ConfigKeyInfo{
979 {
980 Key: "engine.cookie_policy",
981 Type: "string",
982 Default: string(defaults.Engine.CookiePolicy),
983 Description: "Cookie acceptance policy",
984 Values: []string{"always", "no_third_party", "never"},
985 Section: SectionPrivacy,
986 },
987 {
988 Key: "engine.webkit.itp_enabled",
989 Type: "bool",
990 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.ITPEnabled),
991 Description: "Enable WebKit fallback Intelligent Tracking Prevention",
992 Section: SectionPrivacy,
993 },
994 }
995}
996
997func (*SchemaProvider) getUpdateKeys(defaults *Config) []entity.ConfigKeyInfo {
998 return []entity.ConfigKeyInfo{
999 {
1000 Key: "update.enable_on_startup",
1001 Type: "bool",
1002 Default: fmt.Sprintf("%t", defaults.Update.EnableOnStartup),
1003 Description: "Check for updates on browser startup",
1004 Section: SectionUpdate,
1005 },
1006 {
1007 Key: "update.auto_download",
1008 Type: "bool",
1009 Default: fmt.Sprintf("%t", defaults.Update.AutoDownload),
1010 Description: "Auto-download updates in background",
1011 Section: SectionUpdate,
1012 },
1013 {
1014 Key: "update.notify_on_new_settings",
1015 Type: "bool",
1016 Default: fmt.Sprintf("%t", defaults.Update.NotifyOnNewSettings),
1017 Description: "Show toast when new config settings available",
1018 Section: SectionUpdate,
1019 },
1020 }
1021}
1022
1023func (*SchemaProvider) getDebugKeys(defaults *Config) []entity.ConfigKeyInfo {
1024 return []entity.ConfigKeyInfo{
1025 {
1026 Key: "debug.enable_devtools",
1027 Type: "bool",
1028 Default: fmt.Sprintf("%t", defaults.Debug.EnableDevTools),
1029 Description: "Enable browser developer tools (F12)",
1030 Section: SectionDebug,
1031 },
1032 {
1033 Key: "engine.cef.log_file",
1034 Type: "string",
1035 Default: defaults.Engine.CEF.LogFile,
1036 Description: "Path to the CEF runtime log file written during startup and browser process execution",
1037 Section: SectionDebug,
1038 },
1039 {
1040 Key: "engine.cef.log_severity",
1041 Type: "int32",
1042 Default: fmt.Sprintf("%d", defaults.Engine.CEF.LogSeverity),
1043 Description: "CEF internal log verbosity (0=default, 1=verbose, 2=info, 3=warning, 4=error, 99=disable)",
1044 Section: SectionDebug,
1045 },
1046 {
1047 Key: "engine.cef.trace_handlers",
1048 Type: "bool",
1049 Default: fmt.Sprintf("%t", defaults.Engine.CEF.TraceHandlers),
1050 Description: "Trace purego-cef handler wrapping and refcount activity",
1051 Section: SectionDebug,
1052 },
1053 {
1054 Key: "engine.cef.enable_audio_handler",
1055 Type: "bool",
1056 Default: fmt.Sprintf("%t", defaults.Engine.CEF.EnableAudioHandler),
1057 Description: "Enable the experimental CEF audio handler bridge",
1058 Section: SectionDebug,
1059 },
1060 }
1061}
1062
1063func (*SchemaProvider) getPerformanceKeys(defaults *Config) []entity.ConfigKeyInfo {
1064 return []entity.ConfigKeyInfo{
1065 {
1066 Key: "engine.profile",
1067 Type: "string",
1068 Default: string(defaults.Engine.Profile),
1069 Description: "Performance profile preset (custom enables manual tuning)",
1070 Values: []string{"default", "lite", "balanced", "max", "custom"},
1071 Section: SectionPerformance,
1072 },
1073 {
1074 Key: "engine.zoom_cache_size",
1075 Type: "int",
1076 Default: fmt.Sprintf("%d", defaults.Engine.ZoomCacheSize),
1077 Description: "Number of domain zoom levels to cache",
1078 Range: ">=0",
1079 Section: SectionPerformance,
1080 },
1081 {
1082 Key: "engine.pool_prewarm_count",
1083 Type: "int",
1084 Default: fmt.Sprintf("%d", defaults.Engine.PoolPrewarmCount),
1085 Description: "WebViews to pre-create at startup",
1086 Range: ">=0",
1087 Section: SectionPerformance,
1088 },
1089 {
1090 Key: "engine.cef.render_stack",
1091 Type: "string",
1092 Default: string(defaults.Engine.CEF.CEFRenderStack()),
1093 Description: "CEF GPU render stack",
1094 Values: []string{"vulkan", "egl"},
1095 Section: SectionPerformance,
1096 },
1097 {
1098 Key: "engine.cef.adaptive_windowless_frame_rate",
1099 Type: "bool",
1100 Default: fmt.Sprintf("%t", defaults.Engine.CEF.AdaptiveWindowlessFrameRate),
1101 Description: "Adapt CEF OSR frame rate to the active Wayland monitor refresh rate when no explicit windowless_frame_rate is set",
1102 Section: SectionPerformance,
1103 },
1104 {
1105 Key: "engine.cef.windowless_frame_rate",
1106 Type: "int32",
1107 Default: fmt.Sprintf("%d", defaults.Engine.CEF.WindowlessFrameRate),
1108 Description: "Explicit maximum off-screen frame rate for the CEF engine; 0 enables adaptive mode when configured",
1109 Range: ">=0",
1110 Section: SectionPerformance,
1111 },
1112 {
1113 Key: "engine.cef.windowless_frame_rate_max",
1114 Type: "int32",
1115 Default: fmt.Sprintf("%d", defaults.Engine.CEF.CEFWindowlessFrameRateMax()),
1116 Description: "Hard cap for adaptive CEF OSR frame rate; 0 uses the built-in default cap",
1117 Range: ">=0",
1118 Section: SectionPerformance,
1119 },
1120 {
1121 Key: "engine.cef.idle_runtime_timeout_ms",
1122 Type: "int",
1123 Default: fmt.Sprintf("%d", defaults.Engine.CEF.IdleRuntimeTimeoutMs),
1124 Description: "Bounded opt-in CEF runtime residency in milliseconds after the last window closes; 0 disables, changes require restart",
1125 Range: "0..300000",
1126 Section: SectionPerformance,
1127 },
1128 {
1129 Key: "engine.cef.input.scroll_wheel_multiplier",
1130 Type: "float64",
1131 Default: fmt.Sprintf("%.2f", defaults.Engine.CEF.Input.ScrollWheelMultiplier),
1132 Description: "CEF mouse wheel scroll delta multiplier",
1133 Range: ">0",
1134 Section: SectionPerformance,
1135 },
1136 {
1137 Key: "engine.cef.input.scroll_precise_multiplier",
1138 Type: "float64",
1139 Default: fmt.Sprintf("%.2f", defaults.Engine.CEF.Input.ScrollPreciseMultiplier),
1140 Description: "CEF precise/surface scroll delta multiplier for touchpads and high-resolution wheels",
1141 Range: ">0",
1142 Section: SectionPerformance,
1143 },
1144 {
1145 Key: "engine.cef.input.scroll_horizontal_multiplier",
1146 Type: "float64",
1147 Default: fmt.Sprintf("%.2f", defaults.Engine.CEF.Input.ScrollHorizontalMultiplier),
1148 Description: "CEF horizontal scroll delta multiplier",
1149 Range: ">0",
1150 Section: SectionPerformance,
1151 },
1152 {
1153 Key: "engine.cef.input.scroll_vertical_multiplier",
1154 Type: "float64",
1155 Default: fmt.Sprintf("%.2f", defaults.Engine.CEF.Input.ScrollVerticalMultiplier),
1156 Description: "CEF vertical scroll delta multiplier; touchpad vertical speed uses this together with scroll_precise_multiplier",
1157 Range: ">0",
1158 Section: SectionPerformance,
1159 },
1160 {
1161 Key: "engine.cef.input.scroll_max_delta",
1162 Type: "int32",
1163 Default: fmt.Sprintf("%d", defaults.Engine.CEF.Input.ScrollMaxDelta),
1164 Description: "CEF maximum absolute scroll delta after scaling; 0 disables clamping",
1165 Range: ">=0",
1166 Section: SectionPerformance,
1167 },
1168 {
1169 Key: "engine.cef.input.scroll_touchpad_inertia",
1170 Type: "bool",
1171 Default: fmt.Sprintf("%t", defaults.Engine.CEF.Input.ScrollTouchpadInertia),
1172 Description: "Enable direct touchpad tracking with exponential release decay for CEF views",
1173 Section: SectionPerformance,
1174 },
1175 {
1176 Key: "engine.cef.input.scroll_wheel_smoothing",
1177 Type: "bool",
1178 Default: fmt.Sprintf("%t", defaults.Engine.CEF.Input.ScrollWheelSmoothing),
1179 Description: "Interpolate accepted CEF wheel impulses across frames without a long coast",
1180 Section: SectionPerformance,
1181 },
1182 {
1183 Key: "engine.cef.input.touchpad_navigation_enabled",
1184 Type: "bool",
1185 Default: fmt.Sprintf("%t", defaults.Engine.CEF.Input.TouchpadNavigationEnabled),
1186 Description: "Enable deliberate two-finger touchpad swipe back/forward navigation for CEF views",
1187 Section: SectionPerformance,
1188 },
1189 {
1190 Key: "engine.cef.input.touchpad_navigation_min_delta",
1191 Type: "float64",
1192 Default: fmt.Sprintf("%.2f", defaults.Engine.CEF.Input.TouchpadNavigationMinDelta),
1193 Description: "Minimum accumulated horizontal touchpad swipe delta required before release triggers CEF back/forward navigation",
1194 Range: ">0",
1195 Section: SectionPerformance,
1196 },
1197 {
1198 Key: "engine.cef.input.touchpad_navigation_max_vertical_ratio",
1199 Type: "float64",
1200 Default: fmt.Sprintf("%.2f", defaults.Engine.CEF.Input.TouchpadNavigationMaxVerticalRatio),
1201 Description: "Maximum vertical-to-horizontal delta ratio allowed for CEF touchpad back/forward swipes; " +
1202 "does not affect vertical scroll speed",
1203 Range: ">0",
1204 Section: SectionPerformance,
1205 },
1206 {
1207 Key: "engine.webkit.skia_cpu_painting_threads",
1208 Type: "int",
1209 Default: fmt.Sprintf("%d", defaults.Engine.WebKit.SkiaCPUPaintingThreads),
1210 Description: "Skia CPU rendering threads (0=unset, custom profile only)",
1211 Range: ">=0",
1212 Section: SectionPerformance,
1213 },
1214 {
1215 Key: "engine.webkit.skia_gpu_painting_threads",
1216 Type: "int",
1217 Default: fmt.Sprintf("%d", defaults.Engine.WebKit.SkiaGPUPaintingThreads),
1218 Description: "Skia GPU rendering threads (-1=unset, 0=disable, custom profile only)",
1219 Range: ">=-1",
1220 Section: SectionPerformance,
1221 },
1222 {
1223 Key: "engine.webkit.skia_enable_cpu_rendering",
1224 Type: "bool",
1225 Default: fmt.Sprintf("%t", defaults.Engine.WebKit.SkiaEnableCPURendering),
1226 Description: "Force CPU rendering (custom profile only)",
1227 Section: SectionPerformance,
1228 },
1229 {
1230 Key: "engine.webkit.web_process_memory_limit_mb",
1231 Type: "int",
1232 Default: fmt.Sprintf("%d", defaults.Engine.WebKit.WebProcessMemoryLimitMB),
1233 Description: "Web process memory limit in MB (0=unset, custom profile only)",
1234 Range: ">=0",
1235 Section: SectionPerformance,
1236 },
1237 {
1238 Key: "engine.webkit.web_process_memory_poll_interval_sec",
1239 Type: "float64",
1240 Default: fmt.Sprintf("%.1f", defaults.Engine.WebKit.WebProcessMemoryPollIntervalSec),
1241 Description: "Memory check interval in seconds (0=default 30s, custom profile only)",
1242 Range: ">=0",
1243 Section: SectionPerformance,
1244 },
1245 {
1246 Key: "engine.webkit.web_process_memory_conservative_threshold",
1247 Type: "float64",
1248 Default: fmt.Sprintf("%.2f", defaults.Engine.WebKit.WebProcessMemoryConservativeThreshold),
1249 Description: "Conservative memory cleanup threshold (0-1, custom profile only)",
1250 Range: "0-1",
1251 Section: SectionPerformance,
1252 },
1253 {
1254 Key: "engine.webkit.web_process_memory_strict_threshold",
1255 Type: "float64",
1256 Default: fmt.Sprintf("%.2f", defaults.Engine.WebKit.WebProcessMemoryStrictThreshold),
1257 Description: "Strict memory cleanup threshold (0-1, custom profile only)",
1258 Range: "0-1",
1259 Section: SectionPerformance,
1260 },
1261 {
1262 Key: "engine.webkit.network_process_memory_limit_mb",
1263 Type: "int",
1264 Default: fmt.Sprintf("%d", defaults.Engine.WebKit.NetworkProcessMemoryLimitMB),
1265 Description: "Network process memory limit in MB (0=unset, custom profile only)",
1266 Range: ">=0",
1267 Section: SectionPerformance,
1268 },
1269 {
1270 Key: "engine.webkit.network_process_memory_poll_interval_sec",
1271 Type: "float64",
1272 Default: fmt.Sprintf("%.1f", defaults.Engine.WebKit.NetworkProcessMemoryPollIntervalSec),
1273 Description: "Network memory check interval in seconds (custom profile only)",
1274 Range: ">=0",
1275 Section: SectionPerformance,
1276 },
1277 {
1278 Key: "engine.webkit.network_process_memory_conservative_threshold",
1279 Type: "float64",
1280 Default: fmt.Sprintf("%.2f", defaults.Engine.WebKit.NetworkProcessMemoryConservativeThreshold),
1281 Description: "Network conservative memory threshold (0-1, custom profile only)",
1282 Range: "0-1",
1283 Section: SectionPerformance,
1284 },
1285 {
1286 Key: "engine.webkit.network_process_memory_strict_threshold",
1287 Type: "float64",
1288 Default: fmt.Sprintf("%.2f", defaults.Engine.WebKit.NetworkProcessMemoryStrictThreshold),
1289 Description: "Network strict memory threshold (0-1, custom profile only)",
1290 Range: "0-1",
1291 Section: SectionPerformance,
1292 },
1293 }
1294}
1295
1296func (*SchemaProvider) getRuntimeKeys(defaults *Config) []entity.ConfigKeyInfo {
1297 return []entity.ConfigKeyInfo{
1298 {
1299 Key: "engine.cef.cef_dir",
1300 Type: "string",
1301 Default: defaults.Engine.CEF.CEFDir,
1302 Description: "Optional CEF runtime directory containing libcef.so and Resources; overrides the default " +
1303 "runtime discovery order (CEF_DIR env, /usr/lib/cef, ~/.local/share/cef)",
1304 Section: SectionRuntime,
1305 },
1306 {
1307 Key: "engine.webkit.prefix",
1308 Type: "string",
1309 Default: defaults.Engine.WebKit.Prefix,
1310 Description: "Custom runtime prefix for WebKitGTK/GTK",
1311 Section: SectionRuntime,
1312 },
1313 }
1314}
1315
1316func (*SchemaProvider) getDatabaseKeys() []entity.ConfigKeyInfo {
1317 // Get actual default path for display
1318 dbPath := "$XDG_DATA_HOME/" + appName + "/" + databaseName
1319 if path, err := GetDatabaseFile(); err == nil {
1320 dbPath = path
1321 }
1322
1323 return []entity.ConfigKeyInfo{
1324 {
1325 Key: "database.path",
1326 Type: "string",
1327 Default: dbPath,
1328 Description: "Path to SQLite database file",
1329 Section: SectionDatabase,
1330 },
1331 }
1332}
1333
1334func (*SchemaProvider) getDownloadsKeys(_ *Config) []entity.ConfigKeyInfo {
1335 return []entity.ConfigKeyInfo{
1336 {
1337 Key: "downloads.path",
1338 Type: "string",
1339 Default: "(empty = $XDG_DOWNLOAD_DIR or ~/Downloads)",
1340 Description: "Directory where downloads are saved",
1341 Section: SectionDownloads,
1342 },
1343 }
1344}