1package config
2
3import "github.com/bnema/dumber/internal/domain/entity"
4
5// Type aliases for config value types now defined in domain/entity.
6// These aliases keep all existing config-package callers working without
7// any changes to their import paths.
8
9// AppearanceConfig holds UI/rendering preferences.
10type AppearanceConfig = entity.AppearanceConfig
11
12// ColorPalette contains semantic color tokens for light/dark themes.
13type ColorPalette = entity.ColorPalette
14
15// ActionBinding defines a keybinding with optional description.
16type ActionBinding = entity.ActionBinding
17
18// PaneModeConfig defines modal behavior for pane management.
19type PaneModeConfig = entity.PaneModeConfig
20
21// TabModeConfig defines modal behavior for tab management (Zellij-style).
22type TabModeConfig = entity.TabModeConfig
23
24// ResizeModeConfig defines modal behavior for resizing panes (Zellij-style).
25type ResizeModeConfig = entity.ResizeModeConfig
26
27// VimModeConfig defines modal behavior for Vim-style scrolling.
28type VimModeConfig = entity.VimModeConfig
29
30// SessionModeConfig defines modal behavior for session management.
31type SessionModeConfig = entity.SessionModeConfig
32
33// SessionConfig holds session persistence settings.
34type SessionConfig = entity.SessionConfig
35
36// GlobalShortcutsConfig defines global shortcuts (always active, not modal).
37type GlobalShortcutsConfig = entity.GlobalShortcutsConfig
38
39// FloatingPaneProfile defines a shortcut profile that opens a URL in the floating pane.
40type FloatingPaneProfile = entity.FloatingPaneProfile
41
42// FloatingPaneConfig defines persistent floating pane behavior.
43type FloatingPaneConfig = entity.FloatingPaneConfig
44
45// WorkspaceStylingConfig defines visual styling for workspace panes.
46type WorkspaceStylingConfig = entity.WorkspaceStylingConfig
47
48// ExternalLinkBehavior defines how externally opened URLs are placed in the workspace.
49type ExternalLinkBehavior = entity.ExternalLinkBehavior
50
51const (
52 ExternalLinkBehaviorWindowed = entity.ExternalLinkBehaviorWindowed
53 ExternalLinkBehaviorTabbed = entity.ExternalLinkBehaviorTabbed
54 ExternalLinkBehaviorSplit = entity.ExternalLinkBehaviorSplit
55 ExternalLinkBehaviorStacked = entity.ExternalLinkBehaviorStacked
56)
57
58// ExternalLinkPlacement defines the direction used when splitting for an external URL.
59type ExternalLinkPlacement = entity.ExternalLinkPlacement
60
61const (
62 ExternalLinkPlacementRight = entity.ExternalLinkPlacementRight
63 ExternalLinkPlacementLeft = entity.ExternalLinkPlacementLeft
64 ExternalLinkPlacementTop = entity.ExternalLinkPlacementTop
65 ExternalLinkPlacementBottom = entity.ExternalLinkPlacementBottom
66)
67
68// ExternalLinksConfig controls how externally opened URLs are placed in the workspace.
69type ExternalLinksConfig = entity.ExternalLinksConfig
70
71// PopupBehavior defines how popup windows should be opened.
72type PopupBehavior = entity.PopupBehavior
73
74const (
75 // PopupBehaviorSplit opens popups in a split pane (default)
76 PopupBehaviorSplit = entity.PopupBehaviorSplit
77 // PopupBehaviorStacked opens popups in a stacked pane
78 PopupBehaviorStacked = entity.PopupBehaviorStacked
79 // PopupBehaviorTabbed opens popups as a new tab
80 PopupBehaviorTabbed = entity.PopupBehaviorTabbed
81 // PopupBehaviorWindowed opens popups in a new workspace window
82 PopupBehaviorWindowed = entity.PopupBehaviorWindowed
83)
84
85// OmniboxInitialBehavior defines how omnibox history is ordered on open.
86type OmniboxInitialBehavior = entity.OmniboxInitialBehavior
87
88const (
89 // OmniboxInitialBehaviorRecent shows recent visits first.
90 OmniboxInitialBehaviorRecent = entity.OmniboxInitialBehaviorRecent
91 // OmniboxInitialBehaviorMostVisited shows most visited sites first.
92 OmniboxInitialBehaviorMostVisited = entity.OmniboxInitialBehaviorMostVisited
93 // OmniboxInitialBehaviorNone shows no initial history.
94 OmniboxInitialBehaviorNone = entity.OmniboxInitialBehaviorNone
95)
96
97// BrowsingContextConfig defines handling for browsing contexts (popups, tabs, new windows).
98type BrowsingContextConfig = entity.BrowsingContextConfig
99
100// Deprecated: PopupBehaviorConfig is a compatibility alias for BrowsingContextConfig.
101type PopupBehaviorConfig = entity.BrowsingContextConfig
102
103// WorkspaceConfig captures layout, pane, and tab behavior preferences.
104type WorkspaceConfig = entity.WorkspaceConfig
105
106// UpdateConfig holds automatic update settings.
107type UpdateConfig = entity.UpdateConfig
108
109// Config represents the complete configuration for dumber.
110type Config struct {
111 Database DatabaseConfig `mapstructure:"database" yaml:"database" toml:"database"`
112 History HistoryConfig `mapstructure:"history" yaml:"history" toml:"history"`
113 SearchShortcuts map[string]SearchShortcut `mapstructure:"search_shortcuts" yaml:"search_shortcuts" toml:"search_shortcuts"`
114 // DefaultSearchEngine is the URL template for the default search engine (must contain %s placeholder)
115 DefaultSearchEngine string `mapstructure:"default_search_engine" yaml:"default_search_engine" toml:"default_search_engine"`
116 Dmenu DmenuConfig `mapstructure:"dmenu" yaml:"dmenu" toml:"dmenu"`
117 Logging LoggingConfig `mapstructure:"logging" yaml:"logging" toml:"logging"`
118 Appearance AppearanceConfig `mapstructure:"appearance" yaml:"appearance" toml:"appearance"`
119 Debug DebugConfig `mapstructure:"debug" yaml:"debug" toml:"debug"`
120 // DefaultWebpageZoom sets the default zoom level for pages without saved zoom settings (1.0 = 100%, 1.2 = 120%)
121 DefaultWebpageZoom float64 `mapstructure:"default_webpage_zoom" yaml:"default_webpage_zoom" toml:"default_webpage_zoom"`
122 // DefaultUIScale sets the default UI scale for GTK widgets (1.0 = 100%, 2.0 = 200%)
123 DefaultUIScale float64 `mapstructure:"default_ui_scale" yaml:"default_ui_scale" toml:"default_ui_scale"`
124 // SidebarWidth sets the preferred width (px) for the history sidebar.
125 // Clamped to [280, 380] at runtime. 0 means use default (320).
126 SidebarWidth int `mapstructure:"sidebar_width" yaml:"sidebar_width" toml:"sidebar_width"`
127 // Workspace defines workspace, pane, and tab handling behavior.
128 Workspace WorkspaceConfig `mapstructure:"workspace" yaml:"workspace" toml:"workspace"`
129 // Session controls session persistence and restoration.
130 Session SessionConfig `mapstructure:"session" yaml:"session" toml:"session"`
131 // ContentFiltering controls ad blocking and content filtering
132 ContentFiltering ContentFilteringConfig `mapstructure:"content_filtering" yaml:"content_filtering" toml:"content_filtering"`
133 // Clipboard controls clipboard-related behavior
134 Clipboard ClipboardConfig `mapstructure:"clipboard" yaml:"clipboard" toml:"clipboard"`
135 // Omnibox controls the omnibox behavior (initial history display)
136 Omnibox OmniboxConfig `mapstructure:"omnibox" yaml:"omnibox" toml:"omnibox"`
137 // Media controls video playback and hardware acceleration
138 Media MediaConfig `mapstructure:"media" yaml:"media" toml:"media"`
139 // Update controls automatic update checking and downloading.
140 Update UpdateConfig `mapstructure:"update" yaml:"update" toml:"update"`
141 // Downloads configures file download behavior.
142 Downloads DownloadsConfig `mapstructure:"downloads" yaml:"downloads" toml:"downloads"`
143 // Engine holds engine selection and unified engine options.
144 Engine EngineConfig `mapstructure:"engine" toml:"engine" yaml:"engine"`
145}
146
147// CookiePolicy controls cookie acceptance behavior.
148type CookiePolicy string
149
150const (
151 // CookiePolicyAlways accepts all cookies.
152 CookiePolicyAlways CookiePolicy = "always"
153 // CookiePolicyNoThirdParty blocks third-party cookies.
154 CookiePolicyNoThirdParty CookiePolicy = "no_third_party"
155 // CookiePolicyNever blocks all cookies.
156 CookiePolicyNever CookiePolicy = "never"
157)
158
159// GSKRendererMode controls the GTK Scene Kit renderer selection.
160type GSKRendererMode string
161
162const (
163 GSKRendererAuto GSKRendererMode = "auto"
164 GSKRendererOpenGL GSKRendererMode = "opengl"
165 GSKRendererVulkan GSKRendererMode = "vulkan"
166 GSKRendererCairo GSKRendererMode = "cairo"
167)
168
169// HardwareDecodingMode controls video hardware acceleration.
170type HardwareDecodingMode string
171
172const (
173 // HardwareDecodingAuto lets GStreamer choose (hw preferred, sw fallback)
174 HardwareDecodingAuto HardwareDecodingMode = "auto"
175 // HardwareDecodingForce requires hardware decoding (fails if unavailable)
176 HardwareDecodingForce HardwareDecodingMode = "force"
177 // HardwareDecodingDisable uses software decoding only
178 HardwareDecodingDisable HardwareDecodingMode = "disable"
179)
180
181// GLRenderingMode controls OpenGL API selection for video rendering.
182type GLRenderingMode string
183
184const (
185 // GLRenderingModeAuto lets GStreamer choose the best GL API
186 GLRenderingModeAuto GLRenderingMode = "auto"
187 // GLRenderingModeGLES2 forces GLES2 (better for some mobile/embedded GPUs)
188 GLRenderingModeGLES2 GLRenderingMode = "gles2"
189 // GLRenderingModeGL3 forces OpenGL 3.x desktop
190 GLRenderingModeGL3 GLRenderingMode = "gl3"
191 // GLRenderingModeNone disables GL-based rendering
192 GLRenderingModeNone GLRenderingMode = "none"
193)
194
195// PerformanceProfile selects preset performance tuning settings.
196type PerformanceProfile string
197
198const (
199 // ProfileDefault uses WebKit defaults (no tuning applied).
200 ProfileDefault PerformanceProfile = "default"
201 // ProfileLite reduces resource usage for low-RAM systems.
202 ProfileLite PerformanceProfile = "lite"
203 // ProfileBalanced is a conservative compatibility preset between lite and max.
204 ProfileBalanced PerformanceProfile = "balanced"
205 // ProfileMax maximizes responsiveness for heavy pages (GitHub PRs, etc).
206 ProfileMax PerformanceProfile = "max"
207 // ProfileCustom allows full control over individual performance settings.
208 ProfileCustom PerformanceProfile = "custom"
209)
210
211// ThemeDefault is the default theme setting (follows system).
212const ThemeDefault = "default"
213
214const (
215 // ThemePreferDark explicitly selects dark theme.
216 ThemePreferDark = "prefer-dark"
217 // ThemePreferLight explicitly selects light theme.
218 ThemePreferLight = "prefer-light"
219)
220
221// MediaConfig holds video playback and hardware acceleration preferences.
222type MediaConfig struct {
223 // HardwareDecodingMode controls hardware vs software video decoding
224 // Values: "auto" (default), "force", "disable"
225 HardwareDecodingMode HardwareDecodingMode `mapstructure:"hardware_decoding" yaml:"hardware_decoding" toml:"hardware_decoding"`
226 // PreferAV1 prioritizes AV1 codec (most efficient) when available
227 PreferAV1 bool `mapstructure:"prefer_av1" yaml:"prefer_av1" toml:"prefer_av1"`
228 // ShowDiagnosticsOnStartup shows media capability warnings at startup
229 ShowDiagnosticsOnStartup bool `mapstructure:"show_diagnostics" yaml:"show_diagnostics" toml:"show_diagnostics"`
230 // ForceVSync forces vertical sync for video playback (may help with tearing).
231 //
232 // Deprecated: moved to [engine.webkit]. Kept for read compatibility during migration.
233 ForceVSync bool `mapstructure:"force_vsync" yaml:"force_vsync" toml:"-"`
234 // GLRenderingMode controls OpenGL API selection for video rendering.
235 // Values: "auto" (default), "gles2", "gl3", "none"
236 //
237 // Deprecated: moved to [engine.webkit]. Kept for read compatibility during migration.
238 GLRenderingMode GLRenderingMode `mapstructure:"gl_rendering_mode" yaml:"gl_rendering_mode" toml:"-"`
239 // GStreamerDebugLevel sets GStreamer debug verbosity (0=off, 1-5=increasing verbosity).
240 //
241 // Deprecated: moved to [engine.webkit]. Kept for read compatibility during migration.
242 GStreamerDebugLevel int `mapstructure:"gstreamer_debug_level" yaml:"gstreamer_debug_level" toml:"-"`
243}
244
245// DatabaseConfig holds database-related configuration.
246type DatabaseConfig struct {
247 Path string `mapstructure:"path" yaml:"path" toml:"path"`
248}
249
250// HistoryConfig holds history-related configuration.
251type HistoryConfig struct {
252 MaxEntries int `mapstructure:"max_entries" yaml:"max_entries" toml:"max_entries"`
253 RetentionPeriodDays int `mapstructure:"retention_period_days" yaml:"retention_period_days" toml:"retention_period_days"`
254 CleanupIntervalDays int `mapstructure:"cleanup_interval_days" yaml:"cleanup_interval_days" toml:"cleanup_interval_days"`
255}
256
257// PerformanceConfig holds internal performance tuning options.
258// These are not exposed in dumb://config UI but can be set in config file.
259type PerformanceConfig struct {
260 // Profile selects a preset performance configuration.
261 // Values: "default" (no tuning), "lite" (low RAM), "balanced" (compatibility), "max" (heavy pages), "custom" (manual control)
262 // When profile is not "custom", individual tuning fields below are ignored and computed from the profile.
263 // Default: "default"
264 Profile PerformanceProfile `mapstructure:"profile" yaml:"profile" toml:"profile"`
265
266 // ZoomCacheSize is the number of domain zoom levels to cache in memory.
267 // Higher values reduce database queries but use more memory.
268 // Default: 256 domains (~20KB memory)
269 ZoomCacheSize int `mapstructure:"zoom_cache_size" yaml:"zoom_cache_size" toml:"zoom_cache_size"`
270
271 // WebViewPoolPrewarmCount is the number of WebViews to pre-create at startup.
272 // Higher values speed up initial tab creation but use more memory.
273 // Default: 4 (custom mode), computed from profile otherwise
274 WebViewPoolPrewarmCount int `mapstructure:"webview_pool_prewarm_count" yaml:"webview_pool_prewarm_count" toml:"webview_pool_prewarm_count"` //nolint:lll // struct tags must stay on one line
275
276 // --- Skia rendering threads (env vars) ---
277 // NOTE: Fields below only apply when Profile is "custom".
278 // SkiaCPUPaintingThreads sets WEBKIT_SKIA_CPU_PAINTING_THREADS.
279 // Default: 0 (unset, uses WebKit default)
280 SkiaCPUPaintingThreads int `mapstructure:"skia_cpu_painting_threads" yaml:"skia_cpu_painting_threads" toml:"skia_cpu_painting_threads"` //nolint:lll // struct tags must stay on one line
281
282 // SkiaGPUPaintingThreads sets WEBKIT_SKIA_GPU_PAINTING_THREADS.
283 // Default: -1 (unset). Value 0 disables GPU tile painting.
284 SkiaGPUPaintingThreads int `mapstructure:"skia_gpu_painting_threads" yaml:"skia_gpu_painting_threads" toml:"skia_gpu_painting_threads"` //nolint:lll // struct tags must stay on one line
285
286 // SkiaEnableCPURendering forces CPU rendering via WEBKIT_SKIA_ENABLE_CPU_RENDERING=1.
287 // Default: false
288 SkiaEnableCPURendering bool `mapstructure:"skia_enable_cpu_rendering" yaml:"skia_enable_cpu_rendering" toml:"skia_enable_cpu_rendering"` //nolint:lll // struct tags must stay on one line
289
290 // --- Web process memory pressure ---
291 // WebProcessMemoryLimitMB sets memory limit in MB for web processes.
292 // Default: 0 (unset, uses WebKit default: system RAM capped at 3GB)
293 WebProcessMemoryLimitMB int `mapstructure:"web_process_memory_limit_mb" yaml:"web_process_memory_limit_mb" toml:"web_process_memory_limit_mb"` //nolint:lll // struct tags must stay on one line
294
295 // WebProcessMemoryPollIntervalSec sets poll interval for memory checks.
296 // Default: 0 (unset, uses WebKit default: 30 seconds)
297 WebProcessMemoryPollIntervalSec float64 `mapstructure:"web_process_memory_poll_interval_sec" yaml:"web_process_memory_poll_interval_sec" toml:"web_process_memory_poll_interval_sec"` //nolint:lll // struct tags must stay on one line
298
299 // WebProcessMemoryConservativeThreshold sets threshold for conservative memory release.
300 // Valid: (0, 1). Default: 0 (unset, uses WebKit default: 0.33)
301 WebProcessMemoryConservativeThreshold float64 `mapstructure:"web_process_memory_conservative_threshold" yaml:"web_process_memory_conservative_threshold" toml:"web_process_memory_conservative_threshold"` //nolint:lll // struct tags must stay on one line
302
303 // WebProcessMemoryStrictThreshold sets threshold for strict memory release.
304 // Valid: (0, 1). Default: 0 (unset, uses WebKit default: 0.5)
305 WebProcessMemoryStrictThreshold float64 `mapstructure:"web_process_memory_strict_threshold" yaml:"web_process_memory_strict_threshold" toml:"web_process_memory_strict_threshold"` //nolint:lll // struct tags must stay on one line
306
307 // --- Network process memory pressure ---
308 // NetworkProcessMemoryLimitMB sets memory limit in MB for network process.
309 // Default: 0 (unset)
310 NetworkProcessMemoryLimitMB int `mapstructure:"network_process_memory_limit_mb" yaml:"network_process_memory_limit_mb" toml:"network_process_memory_limit_mb"` //nolint:lll // struct tags must stay on one line
311
312 // NetworkProcessMemoryPollIntervalSec sets poll interval for memory checks.
313 // Default: 0 (unset)
314 NetworkProcessMemoryPollIntervalSec float64 `mapstructure:"network_process_memory_poll_interval_sec" yaml:"network_process_memory_poll_interval_sec" toml:"network_process_memory_poll_interval_sec"` //nolint:lll // struct tags must stay on one line
315
316 // NetworkProcessMemoryConservativeThreshold sets threshold for conservative memory release.
317 // Valid: (0, 1). Default: 0 (unset)
318 NetworkProcessMemoryConservativeThreshold float64 `mapstructure:"network_process_memory_conservative_threshold" yaml:"network_process_memory_conservative_threshold" toml:"network_process_memory_conservative_threshold"` //nolint:lll // struct tags must stay on one line
319
320 // NetworkProcessMemoryStrictThreshold sets threshold for strict memory release.
321 // Valid: (0, 1). Default: 0 (unset)
322 NetworkProcessMemoryStrictThreshold float64 `mapstructure:"network_process_memory_strict_threshold" yaml:"network_process_memory_strict_threshold" toml:"network_process_memory_strict_threshold"` //nolint:lll // struct tags must stay on one line
323}
324
325// SearchShortcut represents a search shortcut configuration.
326type SearchShortcut struct {
327 URL string `mapstructure:"url" toml:"url" yaml:"url" json:"url"`
328 Description string `mapstructure:"description" toml:"description" yaml:"description" json:"description"`
329}
330
331// ShortcutURLs returns a simple map of shortcut keys to URL templates.
332// This is useful for passing to url.BuildSearchURL.
333func (c *Config) ShortcutURLs() map[string]string {
334 result := make(map[string]string, len(c.SearchShortcuts))
335 for key, shortcut := range c.SearchShortcuts {
336 result[key] = shortcut.URL
337 }
338 return result
339}
340
341// DmenuConfig holds dmenu/rofi integration configuration.
342type DmenuConfig struct {
343 MaxHistoryDays int `mapstructure:"max_history_days" yaml:"max_history_days" toml:"max_history_days"`
344 ShowVisitCount bool `mapstructure:"show_visit_count" yaml:"show_visit_count" toml:"show_visit_count"`
345 ShowLastVisited bool `mapstructure:"show_last_visited" yaml:"show_last_visited" toml:"show_last_visited"`
346 HistoryPrefix string `mapstructure:"history_prefix" yaml:"history_prefix" toml:"history_prefix"`
347 ShortcutPrefix string `mapstructure:"shortcut_prefix" yaml:"shortcut_prefix" toml:"shortcut_prefix"`
348 URLPrefix string `mapstructure:"url_prefix" yaml:"url_prefix" toml:"url_prefix"`
349 DateFormat string `mapstructure:"date_format" yaml:"date_format" toml:"date_format"`
350 SortByVisitCount bool `mapstructure:"sort_by_visit_count" yaml:"sort_by_visit_count" toml:"sort_by_visit_count"`
351}
352
353// LoggingConfig holds logging configuration.
354type LoggingConfig struct {
355 Level string `mapstructure:"level" yaml:"level" toml:"level"`
356 Format string `mapstructure:"format" yaml:"format" toml:"format"`
357 MaxAge int `mapstructure:"max_age" yaml:"max_age" toml:"max_age"`
358 MaxFiles int `mapstructure:"max_files" yaml:"max_files" toml:"max_files"`
359
360 // File output configuration
361 LogDir string `mapstructure:"log_dir" yaml:"log_dir" toml:"log_dir"`
362 EnableFileLog bool `mapstructure:"enable_file_log" yaml:"enable_file_log" toml:"enable_file_log"`
363
364 // Capture browser console to logs
365 CaptureConsole bool `mapstructure:"capture_console" yaml:"capture_console" toml:"capture_console" json:"capture_console"`
366
367 // Capture GTK4/WebKitGTK6 messages to session logs
368 CaptureGTKLogs bool `mapstructure:"capture_gtk_logs" yaml:"capture_gtk_logs" toml:"capture_gtk_logs" json:"capture_gtk_logs"`
369}
370
371// ContentFilteringConfig holds content filtering and ad blocking preferences
372type ContentFilteringConfig struct {
373 // Enabled controls whether ad blocking is active (default: true)
374 Enabled bool `mapstructure:"enabled" yaml:"enabled" toml:"enabled"`
375 // AutoUpdate controls whether filters are automatically updated (default: true)
376 AutoUpdate bool `mapstructure:"auto_update" yaml:"auto_update" toml:"auto_update"`
377 // Note: Filters are downloaded from bnema/ublock-webkit-filters GitHub releases
378 // Note: Whitelist is managed via database (content_whitelist table)
379}
380
381// ClipboardConfig holds clipboard-related behavior preferences
382type ClipboardConfig struct {
383 // AutoCopyOnSelection automatically copies selected text to clipboard (zellij-style).
384 // When enabled, selecting text in a webview immediately copies it to clipboard.
385 // Does not apply to text selection in input fields or textareas.
386 // Default: true
387 AutoCopyOnSelection bool `mapstructure:"auto_copy_on_selection" yaml:"auto_copy_on_selection" toml:"auto_copy_on_selection" json:"autoCopyOnSelection"` //nolint:lll // struct tags must stay on one line
388}
389
390// OmniboxConfig holds omnibox behavior preferences
391type OmniboxConfig struct {
392 // InitialBehavior controls what to show when omnibox opens with empty input
393 // Values: "recent" (recent visits), "most_visited" (most visited sites), "none" (nothing)
394 InitialBehavior OmniboxInitialBehavior `mapstructure:"initial_behavior" yaml:"initial_behavior" toml:"initial_behavior"`
395 // MostVisitedDays controls how many days of history are considered when initial behavior is most_visited.
396 // 0 means all history.
397 // Default: 30.
398 MostVisitedDays int `mapstructure:"most_visited_days" yaml:"most_visited_days" toml:"most_visited_days"`
399 // AutoOpenOnNewPane opens the omnibox automatically when a new pane is created.
400 // Default: false
401 AutoOpenOnNewPane bool `mapstructure:"auto_open_on_new_pane" yaml:"auto_open_on_new_pane" toml:"auto_open_on_new_pane"`
402}
403
404// DebugConfig holds debug and troubleshooting options
405type DebugConfig struct {
406 // Enable browser developer tools (F12, Inspect Element in context menu)
407 EnableDevTools bool `mapstructure:"enable_devtools" yaml:"enable_devtools" toml:"enable_devtools"`
408}
409
410// DownloadsConfig holds file download preferences.
411type DownloadsConfig struct {
412 // Path is the directory where downloads are saved.
413 // Empty string means use XDG_DOWNLOAD_DIR or ~/Downloads.
414 Path string `mapstructure:"path" yaml:"path" toml:"path"`
415}