v0.30.0 eb3068f

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/handlers/homepage"
11	"github.com/bnema/dumber/internal/logging"
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// RegisterAll registers all message handlers with the router.
21// The router can be any engine's message router that implements port.WebUIHandlerRouter.
22func RegisterAll(ctx context.Context, router port.WebUIHandlerRouter, deps port.HandlerDependencies) error {
23	// Homepage handlers (history, favorites, folders, tags)
24	if deps.HistoryUC != nil && deps.FavoritesUC != nil {
25		if err := homepage.RegisterHandlers(ctx, router, homepage.Config{
26			HistoryUC:   deps.HistoryUC,
27			FavoritesUC: deps.FavoritesUC,
28		}); err != nil {
29			return err
30		}
31	}
32
33	// Configuration handlers
34	if deps.SaveConfig != nil {
35		if err := RegisterConfigHandlers(ctx, router, deps.SaveConfig); err != nil {
36			return err
37		}
38	}
39
40	// Keybindings handlers (always available)
41	if deps.KeybindingsGetter == nil {
42		return fmt.Errorf("KeybindingsGetter is required")
43	}
44	kbHandler := NewKeybindingsHandler(
45		deps.KeybindingsGetter,
46		deps.KeybindingSetter,
47		deps.KeybindingResetter,
48		deps.AllKeybindingsResetter,
49	)
50	if err := RegisterKeybindingsHandlers(ctx, router, kbHandler); err != nil {
51		return err
52	}
53
54	// Clipboard handlers (for auto-copy on selection feature)
55	if deps.ClipboardTextOrchestrator != nil {
56		if err := RegisterClipboardHandlers(ctx, router, deps.ClipboardTextOrchestrator); err != nil {
57			return err
58		}
59	}
60
61	return nil
62}
63
64// RegisterAccentHandlers registers accent key press/release handlers with the router.
65// Must be called after the AccentKeyHandler is initialized (i.e., after initAccentPicker).
66func RegisterAccentHandlers(_ context.Context, router port.WebUIHandlerRouter, handler AccentKeyHandler) error {
67	if router == nil {
68		return fmt.Errorf("RegisterAccentHandlers: router must not be nil")
69	}
70	if handler == nil {
71		return fmt.Errorf("RegisterAccentHandlers: handler must not be nil")
72	}
73
74	if err := router.RegisterHandler("accent_key_press", port.WebUIMessageHandlerFunc(
75		func(ctx context.Context, _ port.WebViewID, payload json.RawMessage) (any, error) {
76			var p struct {
77				Char  string `json:"char"`
78				Shift bool   `json:"shift"`
79			}
80			if err := json.Unmarshal(payload, &p); err != nil {
81				return nil, err
82			}
83			if r, _ := utf8.DecodeRuneInString(p.Char); r != utf8.RuneError && utf8.RuneCountInString(p.Char) == 1 {
84				handler.OnKeyPressed(ctx, r, p.Shift)
85			} else {
86				logging.FromContext(ctx).Debug().Str("char", p.Char).Msg("ignoring invalid accent_key_press char")
87			}
88			return nil, nil
89		},
90	)); err != nil {
91		return err
92	}
93
94	if err := router.RegisterHandler("accent_key_release", port.WebUIMessageHandlerFunc(
95		func(ctx context.Context, _ port.WebViewID, payload json.RawMessage) (any, error) {
96			var p struct {
97				Char string `json:"char"`
98			}
99			if err := json.Unmarshal(payload, &p); err != nil {
100				return nil, err
101			}
102			if r, _ := utf8.DecodeRuneInString(p.Char); r != utf8.RuneError && utf8.RuneCountInString(p.Char) == 1 {
103				handler.OnKeyReleased(ctx, r)
104			} else {
105				logging.FromContext(ctx).Debug().Str("char", p.Char).Msg("ignoring invalid accent_key_release char")
106			}
107			return nil, nil
108		},
109	)); err != nil {
110		return err
111	}
112
113	return nil
114}

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