1// Package config provides default configuration values for dumber.
2package config
3
4// Default configuration constants
5const (
6 // History defaults
7 defaultMaxHistoryEntries = 10000 // entries
8 defaultRetentionDays = 365 // 1 year
9
10 // Dmenu defaults
11 defaultMaxHistoryItems = 20 // items
12
13 // Logging defaults
14 defaultMaxLogSizeMB = 100 // MB
15 defaultMaxBackups = 3 // backup files
16 defaultMaxLogAgeDays = 7 // days
17
18 // Appearance defaults
19 defaultFontSize = 16 // points
20
21 // Omnibox defaults
22 defaultOmniboxInitialBehavior = "recent"
23
24 // Workspace defaults
25 defaultPaneActivationShortcut = "ctrl+p"
26 defaultPaneTimeoutMilliseconds = 3000
27 defaultTabActivationShortcut = "ctrl+t"
28 defaultTabTimeoutMilliseconds = 3000
29 defaultTabBarPosition = "bottom"
30 defaultPopupPlacement = "right"
31
32 // Workspace styling defaults
33 // Active pane border (overlay)
34 defaultBorderWidth = 1
35 defaultBorderColor = "@theme_selected_bg_color"
36
37 // Pane mode border (Ctrl+P N - overlay)
38 defaultPaneModeBorderWidth = 4
39 defaultPaneModeBorderColor = "#4A90E2" // Blue for pane mode indicator
40
41 // Tab mode border (Ctrl+P T - overlay)
42 defaultTabModeBorderWidth = 4
43 defaultTabModeBorderColor = "#FFA500" // Orange for tab mode indicator
44
45 // Other styling
46 defaultTransitionDuration = 120
47 defaultUIScale = 1.0 // UI scale multiplier (1.0 = 100%, 1.2 = 120%)
48)
49
50// getDefaultLogDir returns the default log directory, falls back to empty string on error
51func getDefaultLogDir() string {
52 logDir, err := GetLogDir()
53 if err != nil {
54 return ""
55 }
56 return logDir
57}
58
59// DefaultConfig returns the default configuration values for dumber.
60func DefaultConfig() *Config {
61 return &Config{
62 Database: DatabaseConfig{
63 // Path is set dynamically in config.Load()
64 },
65 History: HistoryConfig{
66 MaxEntries: defaultMaxHistoryEntries,
67 RetentionPeriodDays: defaultRetentionDays, // 1 year
68 CleanupIntervalDays: 1, // daily cleanup
69 },
70 SearchShortcuts: GetDefaultSearchShortcuts(),
71 DefaultSearchEngine: "https://duckduckgo.com/?q=%s",
72 Dmenu: DmenuConfig{
73 MaxHistoryItems: defaultMaxHistoryItems,
74 ShowVisitCount: true,
75 ShowLastVisited: true,
76 HistoryPrefix: "🕒",
77 ShortcutPrefix: "🔍",
78 URLPrefix: "🌐",
79 DateFormat: "2006-01-02 15:04",
80 SortByVisitCount: true,
81 },
82 Logging: LoggingConfig{
83 Level: "info",
84 Format: "text", // text or json
85 Filename: "", // empty means stdout
86 MaxSize: defaultMaxLogSizeMB, // MB
87 MaxBackups: defaultMaxBackups,
88 MaxAge: defaultMaxLogAgeDays, // days
89 Compress: true,
90 LogDir: getDefaultLogDir(),
91 EnableFileLog: true,
92 CaptureStdout: false,
93 CaptureStderr: false,
94 CaptureCOutput: false, // Disabled by default to avoid performance impact
95 CaptureConsole: false, // Disabled by default
96 DebugFile: "debug.log",
97 VerboseWebKit: false,
98 },
99 Appearance: AppearanceConfig{
100 SansFont: "Fira Sans",
101 SerifFont: "Fira Sans",
102 MonospaceFont: "Fira Code",
103 DefaultFontSize: defaultFontSize,
104 LightPalette: ColorPalette{
105 Background: "#f8f8f8",
106 Surface: "#f2f2f2",
107 SurfaceVariant: "#ececec",
108 Text: "#1a1a1a",
109 Muted: "#6e6e6e",
110 Accent: "#404040",
111 Border: "#d2d2d2",
112 },
113 DarkPalette: ColorPalette{
114 Background: "#0e0e0e",
115 Surface: "#1a1a1a",
116 SurfaceVariant: "#141414",
117 Text: "#e4e4e4",
118 Muted: "#848484",
119 Accent: "#a8a8a8",
120 Border: "#363636",
121 },
122 ColorScheme: "default", // default follows system theme
123 },
124 VideoAcceleration: VideoAccelerationConfig{
125 EnableVAAPI: true,
126 AutoDetectGPU: true,
127 VAAPIDriverName: "", // Will be auto-detected
128 EnableAllDrivers: true,
129 LegacyVAAPI: false,
130 },
131 CodecPreferences: CodecConfig{
132 PreferredCodecs: "av1,h264", // AV1 first, but allow VP9 fallback for higher resolutions
133 ForceAV1: false, // Use smart AV1 negotiation instead of forcing
134 BlockVP9: false, // Allow VP9 for higher resolutions
135 BlockVP8: false, // Allow VP8 fallback for ad segments (lower priority)
136 AV1HardwareOnly: false, // Allow software AV1 fallback
137 DisableVP9Hardware: false, // Allow VP9 hardware for high res content
138 VideoBufferSizeMB: 64, // Larger buffer for bursty Twitch/AV1 segments
139 QueueBufferTimeSec: 20, // More buffering time for smooth playback
140 CustomUserAgent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15", // WebKitGTK default (same as Epiphany)
141 AV1MaxResolution: "1080p", // Optimal AV1 up to 1080p, fallback to VP9 for higher res
142 DisableTwitchCodecControl: true, // Disable codec control on Twitch by default (prevents theater/fullscreen freezing)
143 },
144 Debug: DebugConfig{
145 EnableWebKitDebug: false,
146 WebKitDebugCategories: "Network:preconnectTo,ContentFilters",
147 EnableFilteringDebug: false,
148 EnableWebViewDebug: false,
149 LogWebKitCrashes: true, // Always log crashes
150 EnableScriptDebug: false,
151 EnableGeneralDebug: false,
152 EnableWorkspaceDebug: false,
153 EnableFocusDebug: false,
154 EnableCSSDebug: false,
155 EnableFocusMetrics: false,
156 EnablePaneCloseDebug: false,
157 },
158 RenderingMode: RenderingModeGPU,
159 UseDomZoom: false,
160 DefaultZoom: 1.2, // 120% default zoom for better readability
161 Workspace: WorkspaceConfig{
162 PaneMode: PaneModeConfig{
163 ActivationShortcut: defaultPaneActivationShortcut,
164 TimeoutMilliseconds: defaultPaneTimeoutMilliseconds,
165 Actions: map[string][]string{
166 "split-right": {"arrowright", "r"},
167 "split-left": {"arrowleft", "l"},
168 "split-up": {"arrowup", "u"},
169 "split-down": {"arrowdown", "d"},
170 "close-pane": {"x"},
171 "confirm": {"enter"},
172 "cancel": {"escape"},
173 },
174 },
175 TabMode: TabModeConfig{
176 ActivationShortcut: defaultTabActivationShortcut,
177 TimeoutMilliseconds: defaultTabTimeoutMilliseconds,
178 Actions: map[string][]string{
179 "new-tab": {"n", "c"},
180 "close-tab": {"x"},
181 "next-tab": {"l", "tab"},
182 "previous-tab": {"h", "shift+tab"},
183 "rename-tab": {"r"},
184 "confirm": {"enter"},
185 "cancel": {"escape"},
186 },
187 },
188 Tabs: TabKeyConfig{
189 NewTab: "ctrl+t",
190 CloseTab: "ctrl+w",
191 NextTab: "ctrl+tab",
192 PreviousTab: "ctrl+shift+tab",
193 },
194 TabBarPosition: defaultTabBarPosition,
195 Popups: PopupBehaviorConfig{
196 Behavior: PopupBehaviorSplit, // Default: open JavaScript popups in split panes
197 Placement: defaultPopupPlacement,
198 OpenInNewPane: true,
199 FollowPaneContext: true,
200 BlankTargetBehavior: "stacked", // Default: open _blank links in stacked mode
201 EnableSmartDetection: true, // Use WindowProperties to detect popup vs tab
202 OAuthAutoClose: true, // Auto-close OAuth popups on success
203 },
204 Styling: WorkspaceStylingConfig{
205 BorderWidth: defaultBorderWidth,
206 BorderColor: defaultBorderColor,
207 PaneModeBorderWidth: defaultPaneModeBorderWidth,
208 PaneModeBorderColor: defaultPaneModeBorderColor,
209 TabModeBorderWidth: defaultTabModeBorderWidth,
210 TabModeBorderColor: defaultTabModeBorderColor,
211 TransitionDuration: defaultTransitionDuration,
212 UIScale: defaultUIScale,
213 },
214 },
215 ContentFiltering: ContentFilteringConfig{
216 Enabled: true, // Ad blocking enabled by default
217 Whitelist: []string{
218 "twitch.tv", // Arkose Labs bot detection breaks with filtering
219 "passport.twitch.tv", // Auth subdomain
220 "gql.twitch.tv", // GraphQL API
221 },
222 FilterLists: []string{
223 // Core blocking
224 "https://easylist.to/easylist/easylist.txt", // Ads
225 "https://easylist.to/easylist/easyprivacy.txt", // Tracking
226 // uBlock extras
227 "https://raw.githubusercontent.com/uBlockOrigin/uAssets/master/filters/filters.txt", // uBO optimizations
228 "https://raw.githubusercontent.com/uBlockOrigin/uAssets/master/filters/annoyances.txt", // Cookie banners, popups
229 "https://raw.githubusercontent.com/uBlockOrigin/uAssets/master/filters/quick-fixes.txt", // Site fixes
230 },
231 },
232 Omnibox: OmniboxConfig{
233 InitialBehavior: defaultOmniboxInitialBehavior,
234 },
235 }
236}
237
238// GetDefaultSearchShortcuts returns the default search shortcuts.
239func GetDefaultSearchShortcuts() map[string]SearchShortcut {
240 return map[string]SearchShortcut{
241 "ddg": {
242 URL: "https://duckduckgo.com/?q=%s",
243 Description: "DuckDuckGo search",
244 },
245 "g": {
246 URL: "https://www.google.com/search?q=%s",
247 Description: "Google search",
248 },
249 "gh": {
250 URL: "https://github.com/search?q=%s",
251 Description: "GitHub search",
252 },
253 "go": {
254 URL: "https://pkg.go.dev/search?q=%s",
255 Description: "Go package search",
256 },
257 "mdn": {
258 URL: "https://developer.mozilla.org/en-US/search?q=%s",
259 Description: "MDN Web Docs search",
260 },
261 "npm": {
262 URL: "https://www.npmjs.com/search?q=%s",
263 Description: "npm package search",
264 },
265 "r": {
266 URL: "https://www.reddit.com/search?q=%s",
267 Description: "Reddit search",
268 },
269 "so": {
270 URL: "https://stackoverflow.com/search?q=%s",
271 Description: "Stack Overflow search",
272 },
273 "w": {
274 URL: "https://en.wikipedia.org/wiki/%s",
275 Description: "Wikipedia search",
276 },
277 "yt": {
278 URL: "https://www.youtube.com/results?search_query=%s",
279 Description: "YouTube search",
280 },
281 }
282}
283
284// Note: We build our own browser, so no external browser commands needed