v0.28.0 3cb3770

register.go RawHistoryFolder

1package handlers
2
3import (
4	"context"
5	"encoding/json"
6	"fmt"
7	"unicode/utf8"
8
9	"github.com/bnema/dumber/internal/application/port"
10	"github.com/bnema/dumber/internal/infrastructure/webkit"
11	"github.com/bnema/dumber/internal/infrastructure/webkit/handlers/homepage"
12)
13
14// AccentKeyHandler is implemented by the InsertAccentUseCase to receive
15// key press/release events forwarded from WebView JS via the message bridge.
16//
17// Deprecated: use port.AccentKeyHandler instead. This alias is kept for compatibility.
18type AccentKeyHandler = port.AccentKeyHandler
19
20// Config holds all dependencies for message handlers.
21type Config struct {
22	HistoryUC      port.HomepageHistory
23	FavoritesUC    port.HomepageFavorites
24	Clipboard      port.Clipboard
25	AutoCopyConfig port.AutoCopyConfig
26	SaveConfig     func(context.Context, port.WebUIConfig) error // Pre-built by bootstrap (usecase.SaveWebUIConfigUseCase.Execute)
27	// KeybindingsHandler is required (not optional like other handlers) because the WebUI
28	// always needs keybinding read/write support regardless of configuration.
29	KeybindingsHandler *KeybindingsHandler // Pre-built by bootstrap
30	OnClipboardCopied  func(textLen int)   // Called when auto-copy completes (for toast notification)
31}
32
33// RegisterAll registers all message handlers with the router.
34func RegisterAll(ctx context.Context, router *webkit.MessageRouter, cfg Config) error {
35	// Homepage handlers (history, favorites, folders, tags)
36	if cfg.HistoryUC != nil && cfg.FavoritesUC != nil {
37		if err := homepage.RegisterHandlers(ctx, router, homepage.Config{
38			HistoryUC:   cfg.HistoryUC,
39			FavoritesUC: cfg.FavoritesUC,
40		}); err != nil {
41			return err
42		}
43	}
44
45	// Configuration handlers
46	if cfg.SaveConfig != nil {
47		if err := RegisterConfigHandlers(ctx, router, cfg.SaveConfig); err != nil {
48			return err
49		}
50	}
51
52	// Keybindings handlers (always available)
53	if cfg.KeybindingsHandler == nil {
54		return fmt.Errorf("KeybindingsHandler is required")
55	}
56	if err := RegisterKeybindingsHandlers(ctx, router, cfg.KeybindingsHandler); err != nil {
57		return err
58	}
59
60	// Clipboard handlers (for auto-copy on selection feature)
61	if cfg.Clipboard != nil && cfg.AutoCopyConfig != nil {
62		if err := RegisterClipboardHandlers(ctx, router, cfg.Clipboard, cfg.AutoCopyConfig, cfg.OnClipboardCopied); err != nil {
63			return err
64		}
65	}
66
67	return nil
68}
69
70// RegisterAccentHandlers registers accent key press/release handlers with the router.
71// Must be called after the AccentKeyHandler is initialized (i.e., after initAccentPicker).
72func RegisterAccentHandlers(_ context.Context, router *webkit.MessageRouter, handler AccentKeyHandler) error {
73	if router == nil {
74		return fmt.Errorf("RegisterAccentHandlers: router must not be nil")
75	}
76	if handler == nil {
77		return fmt.Errorf("RegisterAccentHandlers: handler must not be nil")
78	}
79
80	if err := router.RegisterHandler("accent_key_press", webkit.MessageHandlerFunc(
81		func(ctx context.Context, _ webkit.WebViewID, payload json.RawMessage) (any, error) {
82			var p struct {
83				Char  string `json:"char"`
84				Shift bool   `json:"shift"`
85			}
86			if err := json.Unmarshal(payload, &p); err != nil {
87				return nil, err
88			}
89			if r, _ := utf8.DecodeRuneInString(p.Char); r != utf8.RuneError && utf8.RuneCountInString(p.Char) == 1 {
90				handler.OnKeyPressed(ctx, r, p.Shift)
91			}
92			return nil, nil
93		},
94	)); err != nil {
95		return err
96	}
97
98	if err := router.RegisterHandler("accent_key_release", webkit.MessageHandlerFunc(
99		func(ctx context.Context, _ webkit.WebViewID, payload json.RawMessage) (any, error) {
100			var p struct {
101				Char string `json:"char"`
102			}
103			if err := json.Unmarshal(payload, &p); err != nil {
104				return nil, err
105			}
106			if r, _ := utf8.DecodeRuneInString(p.Char); r != utf8.RuneError && utf8.RuneCountInString(p.Char) == 1 {
107				handler.OnKeyReleased(ctx, r)
108			}
109			return nil, nil
110		},
111	)); err != nil {
112		return err
113	}
114
115	return nil
116}

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