v0.13.0 976176a

user_content.go RawHistoryFolder

1package webkit
2
3import (
4	"fmt"
5	"log"
6
7	"github.com/bnema/dumber/assets"
8	"github.com/bnema/dumber/internal/config"
9	webkit "github.com/diamondburned/gotk4-webkitgtk/pkg/webkit/v6"
10)
11
12// SetupUserContentManager configures UserContentManager for the WebView
13// This injects GUI scripts at document-start and registers message handlers
14func SetupUserContentManager(view *webkit.WebView, appearanceConfigJSON string, webviewID uint64) error {
15	if view == nil {
16		return nil
17	}
18
19	// Get the UserContentManager from the WebView
20	ucm := view.UserContentManager()
21	if ucm == nil {
22		log.Printf("[webkit] UserContentManager is nil, skipping script injection")
23		return nil
24	}
25
26	// Inject webview ID FIRST, so GUI scripts can access it immediately
27	// Note: webviewID is uint64, formatted as number (not string) to avoid any injection concerns
28	webviewIDScript := fmt.Sprintf(`
29		window.__dumber_webview_id = %d;
30		console.log('[webkit] WebView ID set in JavaScript:', window.__dumber_webview_id);
31	`, webviewID)
32	ucm.AddScript(webkit.NewUserScript(
33		webviewIDScript,
34		webkit.UserContentInjectTopFrame, // Only top frame needs the webview ID
35		webkit.UserScriptInjectAtDocumentStart,
36		nil,
37		nil,
38	))
39	log.Printf("[webkit] Injected webview ID script for ID: %d", webviewID)
40
41	// Inject GTK theme detection SECOND, before color-scheme script
42	// The color-scheme.ts expects window.__dumber_gtk_prefers_dark to be set
43	// Respect the ColorScheme config setting
44	cfg := config.Get()
45	var prefersDark bool
46	switch cfg.Appearance.ColorScheme {
47	case "prefer-dark":
48		prefersDark = true
49		log.Printf("[webkit] Using config-forced dark theme (color_scheme: prefer-dark)")
50	case "prefer-light":
51		prefersDark = false
52		log.Printf("[webkit] Using config-forced light theme (color_scheme: prefer-light)")
53	default:
54		// "default" or empty - follow system GTK preference
55		prefersDark = PrefersDarkTheme()
56		log.Printf("[webkit] Using system GTK theme preference (color_scheme: %s)", cfg.Appearance.ColorScheme)
57	}
58
59	gtkThemeScript := fmt.Sprintf(`window.__dumber_gtk_prefers_dark = %t;`, prefersDark)
60	ucm.AddScript(webkit.NewUserScript(
61		gtkThemeScript,
62		webkit.UserContentInjectTopFrame, // Only top frame needs theme preference
63		webkit.UserScriptInjectAtDocumentStart,
64		nil,
65		nil,
66	))
67	log.Printf("[webkit] Injected theme preference: prefersDark=%t", prefersDark)
68
69	// Inject palette config SECOND, before GUI scripts
70	// The GUI expects window.__dumber_palette = { "light": {...}, "dark": {...} }
71	if appearanceConfigJSON != "" {
72		paletteScript := fmt.Sprintf(`window.__dumber_palette = %s;`, appearanceConfigJSON)
73		ucm.AddScript(webkit.NewUserScript(
74			paletteScript,
75			webkit.UserContentInjectTopFrame, // Only top frame needs palette config
76			webkit.UserScriptInjectAtDocumentStart,
77			nil,
78			nil,
79		))
80		log.Printf("[webkit] Injected palette config at document-start (%d bytes)", len(paletteScript))
81	}
82
83	// Inject color-scheme script at document-start
84	if assets.ColorSchemeScript != "" {
85		ucm.AddScript(webkit.NewUserScript(
86			assets.ColorSchemeScript,
87			webkit.UserContentInjectTopFrame, // Only top frame needs color scheme detection
88			webkit.UserScriptInjectAtDocumentStart,
89			nil, // whitelist (nil = all)
90			nil, // blacklist (nil = none)
91		))
92		log.Printf("[webkit] Injected color-scheme script (%d bytes)", len(assets.ColorSchemeScript))
93	}
94
95	// Inject main-world script at document-start
96	if assets.MainWorldScript != "" {
97		ucm.AddScript(webkit.NewUserScript(
98			assets.MainWorldScript,
99			webkit.UserContentInjectTopFrame, // Only top frame needs bridge/UI functionality
100			webkit.UserScriptInjectAtDocumentStart,
101			nil,
102			nil,
103		))
104		log.Printf("[webkit] Injected main-world script (%d bytes)", len(assets.MainWorldScript))
105	}
106
107	// Inject GUI controls script at document-start
108	if assets.GUIScript != "" {
109		ucm.AddScript(webkit.NewUserScript(
110			assets.GUIScript,
111			webkit.UserContentInjectTopFrame, // Only top frame needs GUI controls
112			webkit.UserScriptInjectAtDocumentStart,
113			nil,
114			nil,
115		))
116		log.Printf("[webkit] Injected GUI controls script (%d bytes)", len(assets.GUIScript))
117	}
118
119	// Register script message handler "dumber" for communication from JS
120	// Pass empty string for worldName to use the default world
121	if !ucm.RegisterScriptMessageHandler("dumber", "") {
122		log.Printf("[webkit] Warning: failed to register 'dumber' script message handler")
123	} else {
124		log.Printf("[webkit] Registered 'dumber' script message handler")
125	}
126
127	return nil
128}

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