v0.29.0 21b3150

deps.go RawHistoryFolder

1// Package ui provides the GTK4 presentation layer for the dumber browser.
2package ui
3
4import (
5	"context"
6
7	"github.com/bnema/dumber/internal/application/port"
8	"github.com/bnema/dumber/internal/application/usecase"
9	"github.com/bnema/dumber/internal/domain/entity"
10	"github.com/bnema/dumber/internal/domain/repository"
11	"github.com/bnema/dumber/internal/infrastructure/config"
12	"github.com/bnema/dumber/internal/ui/adapter"
13	"github.com/bnema/dumber/internal/ui/theme"
14	"github.com/bnema/puregotk/v4/gtk"
15)
16
17// Dependencies holds all injected dependencies for the UI layer.
18// This struct is created once at startup and passed to UI components.
19type Dependencies struct {
20	// Core context and configuration
21	Ctx                    context.Context
22	Config                 *config.Config // TODO: replace with port interface in a later milestone
23	InitialURL             string         // URL to open on startup (optional)
24	RestoreSessionID       string         // Session ID to restore on startup (optional)
25	StartupCrashReports    []string
26	OnFirstWebViewShown    func(context.Context)
27	OnSessionPersisted     func() // Called by main after session is persisted to DB
28	OnCrashReportsDetected func([]string)
29
30	// Theme and color scheme management
31	Theme           *theme.Manager
32	ColorResolver   port.ColorSchemeResolver
33	AdwaitaDetector port.ToolkitAvailabilityNotifier
34
35	// XDG paths
36	XDG port.XDGPaths
37
38	// Engine (replaces individual webkit fields)
39	Engine port.Engine
40
41	// Handler dependencies built by bootstrap (keybindings, config save).
42	HandlerDeps port.HandlerDeps
43
44	// Repositories
45	HistoryRepo    repository.HistoryRepository
46	FavoriteRepo   repository.FavoriteRepository
47	ZoomRepo       repository.ZoomRepository
48	PermissionRepo port.PermissionRepository
49	FilterRepo     repository.ContentWhitelistRepository
50
51	// Use Cases
52	TabsUC       *usecase.ManageTabsUseCase
53	PanesUC      *usecase.ManagePanesUseCase
54	NavigateUC   *usecase.NavigateUseCase
55	ZoomUC       *usecase.ManageZoomUseCase
56	PermissionUC *usecase.HandlePermissionUseCase
57	FavoritesUC  *usecase.ManageFavoritesUseCase
58	HistoryUC    *usecase.SearchHistoryUseCase
59	CopyURLUC    *usecase.CopyURLUseCase
60
61	// Infrastructure Adapters
62	Clipboard            port.Clipboard
63	FaviconService       port.FaviconService
64	FaviconAdapterConfig adapter.FaviconAdapterConfig
65	FilterManager        port.FilterManager
66	IdleInhibitor        port.IdleInhibitor
67
68	// Accent picker for dead keys support
69	InsertAccentUC      *usecase.InsertAccentUseCase
70	AccentFocusProvider port.FocusedInputProvider
71	// NewGTKEntryTarget creates a port.TextInputTarget from a GTK SearchEntry.
72	// Injected to avoid importing infrastructure/textinput from the UI layer.
73	NewGTKEntryTarget func(entry *gtk.SearchEntry) port.TextInputTarget
74
75	// Session management
76	SessionStateRepo repository.SessionStateRepository
77	SessionRepo      repository.SessionRepository
78	CurrentSessionID entity.SessionID
79	SnapshotUC       *usecase.SnapshotSessionUseCase
80	// SnapshotServiceFactory creates a snapshot service bound to the given window state provider.
81	// Called after the App is initialized so the App can serve as the provider.
82	SnapshotServiceFactory func(provider port.WindowStateProvider, intervalMs int) port.SnapshotService
83	// SessionSpawner spawns a new dumber instance for session restoration.
84	SessionSpawner port.SessionSpawner
85	// FileSystem provides file operations (e.g., for download deduplication).
86	FileSystem port.FileSystem
87	// OnConfigChange registers a callback for config hot-reload.
88	// The config pointer in deps.Config is updated in-place before the callback fires.
89	OnConfigChange func(callback func())
90	// WatchConfig starts watching the config file for changes.
91	WatchConfig func() error
92
93	// Update management
94	CheckUpdateUC *usecase.CheckUpdateUseCase
95	ApplyUpdateUC *usecase.ApplyUpdateUseCase
96
97	// Config migration checker (optional; nil disables migration notifications)
98	ConfigMigrator port.ConfigMigrator
99
100	// LaunchExternalURL opens a URI with the system's default handler (e.g. xdg-open).
101	// Used for external URL schemes (vscode://, spotify://, etc.).
102	// Optional: if nil, external URLs are silently dropped.
103	LaunchExternalURL func(uri string)
104	// LaunchBrowserURL opens a URL in a new dumber browser window.
105	// Returns an error when the launcher is unavailable or the launch fails.
106	// Optional: if nil, standalone omnibox navigation returns a configuration error.
107	LaunchBrowserURL func(ctx context.Context, uri string) error
108	// BrowserLaunchRelay listens for in-process browser launch requests.
109	BrowserLaunchRelay port.BrowserLaunchRelay
110}
111
112// Validate checks that all required dependencies are set.
113func (d *Dependencies) Validate() error {
114	if d.Ctx == nil {
115		return ErrMissingDependency("Ctx")
116	}
117	if d.Config == nil {
118		return ErrMissingDependency("Config")
119	}
120	if d.Engine == nil {
121		return ErrMissingDependency("Engine")
122	}
123	if d.HandlerDeps.SaveConfig == nil {
124		return ErrMissingDependency("HandlerDeps.SaveConfig")
125	}
126	if d.HandlerDeps.SaveOmniboxInitialBehavior == nil {
127		return ErrMissingDependency("HandlerDeps.SaveOmniboxInitialBehavior")
128	}
129	// Use cases are optional - can be nil if not needed
130	return nil
131}
132
133// DependencyError indicates a missing required dependency.
134type DependencyError struct {
135	Name string
136}
137
138func (e DependencyError) Error() string {
139	return "missing required dependency: " + e.Name
140}
141
142// ErrMissingDependency creates a new DependencyError.
143func ErrMissingDependency(name string) error {
144	return DependencyError{Name: name}
145}

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