v0.12.1 1453d21

user_content.go RawHistoryFolder

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

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