main 5041353

page_scroll.go RawHistoryFolder

1// Package usecase contains application use cases that orchestrate domain logic.
2package usecase
3
4import (
5	"context"
6	"errors"
7	"fmt"
8
9	"github.com/bnema/dumber/internal/application/port"
10)
11
12// PageScrollCommand represents a semantic page scroll action.
13// Each command maps to a fixed pixel delta defined in this package.
14type PageScrollCommand int
15
16const (
17	PageScrollLeft     PageScrollCommand = iota // scroll left by small horizontal amount
18	PageScrollRight                             // scroll right by small horizontal amount
19	PageScrollUp                                // scroll up by small vertical amount
20	PageScrollDown                              // scroll down by small vertical amount
21	PageScrollUpFast                            // scroll up by fast vertical amount
22	PageScrollDownFast                          // scroll down by fast vertical amount
23)
24
25// Internal fixed pixel defaults for page scroll commands.
26// These are application-layer constants, not user-configurable.
27const (
28	scrollSmallHorizontal = 80
29	scrollSmallVertical   = 80
30	scrollFastVertical    = 320
31)
32
33// PageScrollUseCase handles semantic page scrolling commands.
34// It maps semantic scroll actions (left, down, up-fast, etc.) to pixel deltas
35// and delegates to the WebView's scroll capability. No UI logic or
36// engine-specific JavaScript exists in this layer.
37type PageScrollUseCase struct{}
38
39// NewPageScrollUseCase creates a new PageScrollUseCase.
40func NewPageScrollUseCase() *PageScrollUseCase {
41	return &PageScrollUseCase{}
42}
43
44// Scroll applies a semantic scroll command to a WebView.
45// It returns an error if the WebView does not support semantic page scrolling
46// (i.e., does not implement port.PageScrollable).
47func (uc *PageScrollUseCase) Scroll(ctx context.Context, wv port.WebView, cmd PageScrollCommand) error {
48	return uc.scroll(ctx, wv, cmd, false)
49}
50
51// ScrollContinuous applies one autonomous held-key step. The pixel policy is
52// identical to Scroll; only lifecycle metadata differs for adapter coalescing.
53func (uc *PageScrollUseCase) ScrollContinuous(ctx context.Context, wv port.WebView, cmd PageScrollCommand) error {
54	return uc.scroll(ctx, wv, cmd, true)
55}
56
57// Stop cancels queued continuous work when the adapter supports cancellation.
58// Adapters such as WebKit that execute each step immediately need no special
59// capability and therefore treat this as a no-op.
60func (*PageScrollUseCase) Stop(ctx context.Context, wv port.WebView) error {
61	if wv == nil {
62		return errors.New("page scroll: nil webview")
63	}
64	if canceler, ok := wv.(port.PageScrollCanceler); ok {
65		canceler.CancelPageScroll(ctx)
66	}
67	return nil
68}
69
70func (*PageScrollUseCase) scroll(ctx context.Context, wv port.WebView, cmd PageScrollCommand, continuous bool) error {
71	if wv == nil {
72		return errors.New("page scroll: nil webview")
73	}
74
75	scroller, ok := wv.(port.PageScrollable)
76	if !ok {
77		return errors.New("page scroll: webview does not support page scrolling")
78	}
79
80	dx, dy := scrollDelta(cmd)
81	req := port.PageScrollRequest{
82		Command:    toPortPageScrollCommand(cmd),
83		FallbackDX: dx,
84		FallbackDY: dy,
85		Continuous: continuous,
86	}
87	if err := scroller.ScrollPage(ctx, req); err != nil {
88		return fmt.Errorf("page scroll: %w", err)
89	}
90	return nil
91}
92
93func toPortPageScrollCommand(cmd PageScrollCommand) port.PageScrollCommand {
94	switch cmd {
95	case PageScrollLeft:
96		return port.PageScrollCommandLeft
97	case PageScrollRight:
98		return port.PageScrollCommandRight
99	case PageScrollUp:
100		return port.PageScrollCommandUp
101	case PageScrollDown:
102		return port.PageScrollCommandDown
103	case PageScrollUpFast:
104		return port.PageScrollCommandUpFast
105	case PageScrollDownFast:
106		return port.PageScrollCommandDownFast
107	default:
108		return port.PageScrollCommand(-1)
109	}
110}
111
112// scrollDelta returns the pixel delta for a PageScrollCommand.
113func scrollDelta(cmd PageScrollCommand) (dx, dy int) {
114	switch cmd {
115	case PageScrollLeft:
116		return -scrollSmallHorizontal, 0
117	case PageScrollRight:
118		return scrollSmallHorizontal, 0
119	case PageScrollUp:
120		return 0, -scrollSmallVertical
121	case PageScrollDown:
122		return 0, scrollSmallVertical
123	case PageScrollUpFast:
124		return 0, -scrollFastVertical
125	case PageScrollDownFast:
126		return 0, scrollFastVertical
127	default:
128		return 0, 0
129	}
130}
131
132// String returns a human-readable name for the scroll command.
133func (cmd PageScrollCommand) String() string {
134	switch cmd {
135	case PageScrollLeft:
136		return "left"
137	case PageScrollRight:
138		return "right"
139	case PageScrollUp:
140		return "up"
141	case PageScrollDown:
142		return "down"
143	case PageScrollUpFast:
144		return "up-fast"
145	case PageScrollDownFast:
146		return "down-fast"
147	default:
148		return "unknown"
149	}
150}

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