v0.20.0 c741a39

manage_zoom.go RawHistoryFolder

1// Package usecase contains application use cases that orchestrate domain logic.
2package usecase
3
4import (
5	"context"
6	"fmt"
7	"net/url"
8
9	"github.com/bnema/dumber/internal/application/port"
10	"github.com/bnema/dumber/internal/domain/entity"
11	"github.com/bnema/dumber/internal/domain/repository"
12	"github.com/bnema/dumber/internal/logging"
13)
14
15// ManageZoomUseCase handles per-domain zoom level operations.
16type ManageZoomUseCase struct {
17	zoomRepo    repository.ZoomRepository
18	defaultZoom float64
19}
20
21// NewManageZoomUseCase creates a new zoom management use case.
22// defaultZoom is the zoom level to use when resetting (typically from config).
23func NewManageZoomUseCase(zoomRepo repository.ZoomRepository, defaultZoom float64) *ManageZoomUseCase {
24	if defaultZoom <= 0 {
25		defaultZoom = entity.ZoomDefault
26	}
27	return &ManageZoomUseCase{
28		zoomRepo:    zoomRepo,
29		defaultZoom: defaultZoom,
30	}
31}
32
33// DefaultZoom returns the configured default zoom level.
34func (uc *ManageZoomUseCase) DefaultZoom() float64 {
35	return uc.defaultZoom
36}
37
38// GetZoom retrieves the zoom level for a domain.
39// Returns the configured default zoom level if none is set.
40func (uc *ManageZoomUseCase) GetZoom(ctx context.Context, domain string) (*entity.ZoomLevel, error) {
41	log := logging.FromContext(ctx)
42	log.Debug().Str("domain", domain).Msg("getting zoom level")
43
44	zoom, err := uc.zoomRepo.Get(ctx, domain)
45	if err != nil {
46		return nil, fmt.Errorf("failed to get zoom level: %w", err)
47	}
48
49	if zoom == nil {
50		zoom = entity.NewZoomLevel(domain, uc.defaultZoom)
51		log.Debug().Str("domain", domain).Float64("zoom", zoom.ZoomFactor).Msg("using default zoom")
52	}
53
54	return zoom, nil
55}
56
57// SetZoom saves a zoom level for a domain.
58func (uc *ManageZoomUseCase) SetZoom(ctx context.Context, domain string, factor float64) error {
59	log := logging.FromContext(ctx)
60	log.Debug().Str("domain", domain).Float64("factor", factor).Msg("setting zoom level")
61
62	zoom := entity.NewZoomLevel(domain, factor)
63	if err := uc.zoomRepo.Set(ctx, zoom); err != nil {
64		return fmt.Errorf("failed to set zoom level: %w", err)
65	}
66
67	log.Info().Str("domain", domain).Float64("factor", zoom.ZoomFactor).Msg("zoom level saved")
68	return nil
69}
70
71// ResetZoom removes the custom zoom level for a domain.
72func (uc *ManageZoomUseCase) ResetZoom(ctx context.Context, domain string) error {
73	log := logging.FromContext(ctx)
74	log.Debug().Str("domain", domain).Msg("resetting zoom level")
75
76	if err := uc.zoomRepo.Delete(ctx, domain); err != nil {
77		return fmt.Errorf("failed to reset zoom level: %w", err)
78	}
79
80	log.Info().Str("domain", domain).Msg("zoom level reset to default")
81	return nil
82}
83
84// ZoomIn increases the zoom level by one step (0.1).
85func (uc *ManageZoomUseCase) ZoomIn(ctx context.Context, domain string, current float64) (*entity.ZoomLevel, error) {
86	log := logging.FromContext(ctx)
87
88	zoom := entity.NewZoomLevel(domain, current)
89	zoom.ZoomIn()
90
91	log.Debug().
92		Str("domain", domain).
93		Float64("from", current).
94		Float64("to", zoom.ZoomFactor).
95		Msg("zooming in")
96
97	if err := uc.zoomRepo.Set(ctx, zoom); err != nil {
98		return nil, fmt.Errorf("failed to save zoom level: %w", err)
99	}
100
101	return zoom, nil
102}
103
104// ZoomOut decreases the zoom level by one step (0.1).
105func (uc *ManageZoomUseCase) ZoomOut(ctx context.Context, domain string, current float64) (*entity.ZoomLevel, error) {
106	log := logging.FromContext(ctx)
107
108	zoom := entity.NewZoomLevel(domain, current)
109	zoom.ZoomOut()
110
111	log.Debug().
112		Str("domain", domain).
113		Float64("from", current).
114		Float64("to", zoom.ZoomFactor).
115		Msg("zooming out")
116
117	if err := uc.zoomRepo.Set(ctx, zoom); err != nil {
118		return nil, fmt.Errorf("failed to save zoom level: %w", err)
119	}
120
121	return zoom, nil
122}
123
124// ApplyToWebView loads the saved zoom level and applies it to a webview.
125func (uc *ManageZoomUseCase) ApplyToWebView(ctx context.Context, webview port.WebView, domain string) error {
126	log := logging.FromContext(ctx)
127
128	zoom, err := uc.GetZoom(ctx, domain)
129	if err != nil {
130		return err
131	}
132
133	log.Debug().
134		Str("domain", domain).
135		Float64("factor", zoom.ZoomFactor).
136		Msg("applying zoom to webview")
137
138	if err := webview.SetZoomLevel(ctx, zoom.ZoomFactor); err != nil {
139		return fmt.Errorf("failed to set zoom level: %w", err)
140	}
141	return nil
142}
143
144// GetAll retrieves all saved zoom levels.
145func (uc *ManageZoomUseCase) GetAll(ctx context.Context) ([]*entity.ZoomLevel, error) {
146	log := logging.FromContext(ctx)
147	log.Debug().Msg("getting all zoom levels")
148
149	levels, err := uc.zoomRepo.GetAll(ctx)
150	if err != nil {
151		return nil, fmt.Errorf("failed to get zoom levels: %w", err)
152	}
153
154	log.Debug().Int("count", len(levels)).Msg("retrieved zoom levels")
155	return levels, nil
156}
157
158// ExtractDomain extracts the host from a URL string.
159func ExtractDomain(rawURL string) (string, error) {
160	u, err := url.Parse(rawURL)
161	if err != nil {
162		return "", fmt.Errorf("invalid URL: %w", err)
163	}
164	if u.Host == "" {
165		return "", fmt.Errorf("URL has no host: %s", rawURL)
166	}
167	return u.Host, nil
168}

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