v0.15.0 9006957

defaults.go RawHistoryFolder

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

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close