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