detached f36a1c5

refactor(ui): replace webkit fields in Dependencies with Engine

Replace concrete webkit fields (WebContext, Pool, Factory, Settings,
Injector, MessageRouter) in ui.Dependencies with a single Engine
port.Engine field. Add engine/wkEngine fields to App struct with a
type assertion to *webkit.Engine for webkit-specific operations.
FilterManager kept in deps pending port.FilterApplier integration.
commit
f36a1c533aafa00ecf99f31922ecef081afdb58a
author
brice · · 2026-03-15 16:41 UTC
parent
4f0e3ae
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
3 files · +28 -26
M cmd/dumber/main.go +2 -7
@@ -514,8 +514,7 @@ func buildUIDependencies(
514514 currentSessionID entity.SessionID,
515515 startupCrashReports []string,
516516 ) *ui.Dependencies {
517- // Type-assert to *webkit.Engine to access concrete types for ui.Dependencies.
518- // This bridge will be removed when ui.Dependencies is updated to use port.Engine (M4).
517+ // Type-assert to *webkit.Engine to access FilterManager (not yet on port.Engine).
519518 wkEngine := engine.(*webkit.Engine)
520519
521520 return &ui.Dependencies{
@@ -528,11 +527,7 @@ func buildUIDependencies(
528527 ColorResolver: colorResolver,
529528 AdwaitaDetector: adwaitaDetector,
530529 XDG: xdg.New(),
531- WebContext: wkEngine.InternalContext(),
532- Pool: wkEngine.InternalPool(),
533- Settings: wkEngine.InternalSettings(),
534- Injector: wkEngine.InternalInjector(),
535- MessageRouter: wkEngine.InternalMessageRouter(),
530+ Engine: engine,
536531 FilterManager: wkEngine.InternalFilterManager(),
537532 HistoryRepo: repos.history,
538533 FavoriteRepo: repos.favorite,
@@ -514,8 +514,7 @@ func buildUIDependencies(
514 currentSessionID entity.SessionID,514 currentSessionID entity.SessionID,
515 startupCrashReports []string,515 startupCrashReports []string,
516 ) *ui.Dependencies {516 ) *ui.Dependencies {
517- // Type-assert to *webkit.Engine to access concrete types for ui.Dependencies.517+ // Type-assert to *webkit.Engine to access FilterManager (not yet on port.Engine).
518- // This bridge will be removed when ui.Dependencies is updated to use port.Engine (M4).
519 wkEngine := engine.(*webkit.Engine)518 wkEngine := engine.(*webkit.Engine)
520 519
521 return &ui.Dependencies{520 return &ui.Dependencies{
@@ -528,11 +527,7 @@ func buildUIDependencies(
528 ColorResolver: colorResolver,527 ColorResolver: colorResolver,
529 AdwaitaDetector: adwaitaDetector,528 AdwaitaDetector: adwaitaDetector,
530 XDG: xdg.New(),529 XDG: xdg.New(),
531- WebContext: wkEngine.InternalContext(),530+ Engine: engine,
532- Pool: wkEngine.InternalPool(),
533- Settings: wkEngine.InternalSettings(),
534- Injector: wkEngine.InternalInjector(),
535- MessageRouter: wkEngine.InternalMessageRouter(),
536 FilterManager: wkEngine.InternalFilterManager(),531 FilterManager: wkEngine.InternalFilterManager(),
537 HistoryRepo: repos.history,532 HistoryRepo: repos.history,
538 FavoriteRepo: repos.favorite,533 FavoriteRepo: repos.favorite,
M internal/ui/app.go +24 -11
@@ -99,6 +99,10 @@ type App struct {
9999 // Floating pane sessions keyed by tab and profile session ID.
100100 floatingSessions map[floatingSessionKey]*floatingWorkspaceSession
101101
102+ // Engine (port-level and concrete for webkit-specific operations)
103+ engine port.Engine
104+ wkEngine *webkit.Engine
105+
102106 // Web content (managed by ContentCoordinator)
103107 pool *webkit.WebViewPool
104108 webViewFactory *webkit.WebViewFactory
@@ -179,13 +183,18 @@ func New(deps *Dependencies) (*App, error) {
179183 panesUC: deps.PanesUC,
180184 workspaceViews: make(map[entity.TabID]*component.WorkspaceView),
181185 floatingSessions: make(map[floatingSessionKey]*floatingWorkspaceSession),
182- pool: deps.Pool,
183- injector: deps.Injector,
184- router: deps.MessageRouter,
185- settings: deps.Settings,
186+ engine: deps.Engine,
186187 configManager: config.GetManager(),
187188 cancel: cancel,
188189 }
190+ // Type-assert engine to concrete *webkit.Engine for webkit-specific operations.
191+ if wke, ok := deps.Engine.(*webkit.Engine); ok {
192+ app.wkEngine = wke
193+ app.pool = wke.InternalPool()
194+ app.injector = wke.InternalInjector()
195+ app.router = wke.InternalMessageRouter()
196+ app.settings = wke.InternalSettings()
197+ }
189198 if app.router == nil {
190199 app.router = webkit.NewMessageRouter(ctx)
191200 }
@@ -563,7 +572,7 @@ func (a *App) registerAccentHandlers(ctx context.Context) {
563572 func (a *App) initDownloadHandler(ctx context.Context) {
564573 log := logging.FromContext(ctx)
565574
566- if a.deps == nil || a.deps.WebContext == nil {
575+ if a.deps == nil || a.wkEngine == nil {
567576 log.Debug().Msg("WebContext not available, skipping download handler")
568577 return
569578 }
@@ -599,7 +608,7 @@ func (a *App) initDownloadHandler(ctx context.Context) {
599608
600609 // Create and wire the download handler.
601610 handler := webkit.NewDownloadHandler(downloadPath, eventAdapter, prepareDownloadUC)
602- a.deps.WebContext.SetDownloadHandler(ctx, handler)
611+ a.wkEngine.InternalContext().SetDownloadHandler(ctx, handler)
603612
604613 log.Info().Str("path", downloadPath).Msg("download handler initialized")
605614 }
@@ -1482,8 +1491,8 @@ func (a *App) onShutdown(ctx context.Context) {
14821491 for _, tabID := range tabIDs {
14831492 a.releaseFloatingSessionsForTab(ctx, tabID)
14841493 }
1485- if a.deps.Pool != nil {
1486- a.deps.Pool.Close(ctx)
1494+ if a.pool != nil {
1495+ a.pool.Close(ctx)
14871496 }
14881497 // Close idle inhibitor to release D-Bus connection
14891498 if a.deps.IdleInhibitor != nil {
@@ -1507,8 +1516,8 @@ func (a *App) initCoordinators(ctx context.Context) {
15071516
15081517 // Create FaviconAdapter with service and WebKit FaviconDatabase
15091518 var faviconDB *webkit.FaviconDatabase
1510- if a.deps.WebContext != nil {
1511- faviconDB = a.deps.WebContext.FaviconDatabase()
1519+ if a.wkEngine != nil {
1520+ faviconDB = a.wkEngine.InternalContext().FaviconDatabase()
15121521 }
15131522 a.faviconAdapter = adapter.NewFaviconAdapter(a.deps.FaviconService, faviconDB)
15141523
@@ -1592,8 +1601,12 @@ func (a *App) initCoordinators(ctx context.Context) {
15921601 a.wsCoord.SetOnStateChanged(a.MarkDirty)
15931602
15941603 // Wire popup handling
1604+ var wkCtx *webkit.WebKitContext
1605+ if a.wkEngine != nil {
1606+ wkCtx = a.wkEngine.InternalContext()
1607+ }
15951608 a.webViewFactory = webkit.NewWebViewFactory(
1596- a.deps.WebContext,
1609+ wkCtx,
15971610 a.settings,
15981611 a.pool,
15991612 a.injector,
@@ -99,6 +99,10 @@ type App struct {
99 // Floating pane sessions keyed by tab and profile session ID.99 // Floating pane sessions keyed by tab and profile session ID.
100 floatingSessions map[floatingSessionKey]*floatingWorkspaceSession100 floatingSessions map[floatingSessionKey]*floatingWorkspaceSession
101 101
102+ // Engine (port-level and concrete for webkit-specific operations)
103+ engine port.Engine
104+ wkEngine *webkit.Engine
105+
102 // Web content (managed by ContentCoordinator)106 // Web content (managed by ContentCoordinator)
103 pool *webkit.WebViewPool107 pool *webkit.WebViewPool
104 webViewFactory *webkit.WebViewFactory108 webViewFactory *webkit.WebViewFactory
@@ -179,13 +183,18 @@ func New(deps *Dependencies) (*App, error) {
179 panesUC: deps.PanesUC,183 panesUC: deps.PanesUC,
180 workspaceViews: make(map[entity.TabID]*component.WorkspaceView),184 workspaceViews: make(map[entity.TabID]*component.WorkspaceView),
181 floatingSessions: make(map[floatingSessionKey]*floatingWorkspaceSession),185 floatingSessions: make(map[floatingSessionKey]*floatingWorkspaceSession),
182- pool: deps.Pool,186+ engine: deps.Engine,
183- injector: deps.Injector,
184- router: deps.MessageRouter,
185- settings: deps.Settings,
186 configManager: config.GetManager(),187 configManager: config.GetManager(),
187 cancel: cancel,188 cancel: cancel,
188 }189 }
190+ // Type-assert engine to concrete *webkit.Engine for webkit-specific operations.
191+ if wke, ok := deps.Engine.(*webkit.Engine); ok {
192+ app.wkEngine = wke
193+ app.pool = wke.InternalPool()
194+ app.injector = wke.InternalInjector()
195+ app.router = wke.InternalMessageRouter()
196+ app.settings = wke.InternalSettings()
197+ }
189 if app.router == nil {198 if app.router == nil {
190 app.router = webkit.NewMessageRouter(ctx)199 app.router = webkit.NewMessageRouter(ctx)
191 }200 }
@@ -563,7 +572,7 @@ func (a *App) registerAccentHandlers(ctx context.Context) {
563 func (a *App) initDownloadHandler(ctx context.Context) {572 func (a *App) initDownloadHandler(ctx context.Context) {
564 log := logging.FromContext(ctx)573 log := logging.FromContext(ctx)
565 574
566- if a.deps == nil || a.deps.WebContext == nil {575+ if a.deps == nil || a.wkEngine == nil {
567 log.Debug().Msg("WebContext not available, skipping download handler")576 log.Debug().Msg("WebContext not available, skipping download handler")
568 return577 return
569 }578 }
@@ -599,7 +608,7 @@ func (a *App) initDownloadHandler(ctx context.Context) {
599 608
600 // Create and wire the download handler.609 // Create and wire the download handler.
601 handler := webkit.NewDownloadHandler(downloadPath, eventAdapter, prepareDownloadUC)610 handler := webkit.NewDownloadHandler(downloadPath, eventAdapter, prepareDownloadUC)
602- a.deps.WebContext.SetDownloadHandler(ctx, handler)611+ a.wkEngine.InternalContext().SetDownloadHandler(ctx, handler)
603 612
604 log.Info().Str("path", downloadPath).Msg("download handler initialized")613 log.Info().Str("path", downloadPath).Msg("download handler initialized")
605 }614 }
@@ -1482,8 +1491,8 @@ func (a *App) onShutdown(ctx context.Context) {
1482 for _, tabID := range tabIDs {1491 for _, tabID := range tabIDs {
1483 a.releaseFloatingSessionsForTab(ctx, tabID)1492 a.releaseFloatingSessionsForTab(ctx, tabID)
1484 }1493 }
1485- if a.deps.Pool != nil {1494+ if a.pool != nil {
1486- a.deps.Pool.Close(ctx)1495+ a.pool.Close(ctx)
1487 }1496 }
1488 // Close idle inhibitor to release D-Bus connection1497 // Close idle inhibitor to release D-Bus connection
1489 if a.deps.IdleInhibitor != nil {1498 if a.deps.IdleInhibitor != nil {
@@ -1507,8 +1516,8 @@ func (a *App) initCoordinators(ctx context.Context) {
1507 1516
1508 // Create FaviconAdapter with service and WebKit FaviconDatabase1517 // Create FaviconAdapter with service and WebKit FaviconDatabase
1509 var faviconDB *webkit.FaviconDatabase1518 var faviconDB *webkit.FaviconDatabase
1510- if a.deps.WebContext != nil {1519+ if a.wkEngine != nil {
1511- faviconDB = a.deps.WebContext.FaviconDatabase()1520+ faviconDB = a.wkEngine.InternalContext().FaviconDatabase()
1512 }1521 }
1513 a.faviconAdapter = adapter.NewFaviconAdapter(a.deps.FaviconService, faviconDB)1522 a.faviconAdapter = adapter.NewFaviconAdapter(a.deps.FaviconService, faviconDB)
1514 1523
@@ -1592,8 +1601,12 @@ func (a *App) initCoordinators(ctx context.Context) {
1592 a.wsCoord.SetOnStateChanged(a.MarkDirty)1601 a.wsCoord.SetOnStateChanged(a.MarkDirty)
1593 1602
1594 // Wire popup handling1603 // Wire popup handling
1604+ var wkCtx *webkit.WebKitContext
1605+ if a.wkEngine != nil {
1606+ wkCtx = a.wkEngine.InternalContext()
1607+ }
1595 a.webViewFactory = webkit.NewWebViewFactory(1608 a.webViewFactory = webkit.NewWebViewFactory(
1596- a.deps.WebContext,1609+ wkCtx,
1597 a.settings,1610 a.settings,
1598 a.pool,1611 a.pool,
1599 a.injector,1612 a.injector,
M internal/ui/deps.go +2 -8
@@ -12,7 +12,6 @@ import (
1212 "github.com/bnema/dumber/internal/infrastructure/config"
1313 "github.com/bnema/dumber/internal/infrastructure/favicon"
1414 "github.com/bnema/dumber/internal/infrastructure/filtering"
15- "github.com/bnema/dumber/internal/infrastructure/webkit"
1615 "github.com/bnema/dumber/internal/ui/theme"
1716 )
1817
@@ -37,13 +36,8 @@ type Dependencies struct {
3736 // XDG paths
3837 XDG port.XDGPaths
3938
40- // WebKit infrastructure
41- WebContext *webkit.WebKitContext
42- Pool *webkit.WebViewPool
43- Factory port.WebViewFactory
44- Settings *webkit.SettingsManager
45- Injector *webkit.ContentInjector
46- MessageRouter *webkit.MessageRouter
39+ // Engine (replaces individual webkit fields)
40+ Engine port.Engine
4741
4842 // Repositories
4943 HistoryRepo repository.HistoryRepository
@@ -12,7 +12,6 @@ import (
12 "github.com/bnema/dumber/internal/infrastructure/config"12 "github.com/bnema/dumber/internal/infrastructure/config"
13 "github.com/bnema/dumber/internal/infrastructure/favicon"13 "github.com/bnema/dumber/internal/infrastructure/favicon"
14 "github.com/bnema/dumber/internal/infrastructure/filtering"14 "github.com/bnema/dumber/internal/infrastructure/filtering"
15- "github.com/bnema/dumber/internal/infrastructure/webkit"
16 "github.com/bnema/dumber/internal/ui/theme"15 "github.com/bnema/dumber/internal/ui/theme"
17 )16 )
18 17
@@ -37,13 +36,8 @@ type Dependencies struct {
37 // XDG paths36 // XDG paths
38 XDG port.XDGPaths37 XDG port.XDGPaths
39 38
40- // WebKit infrastructure39+ // Engine (replaces individual webkit fields)
41- WebContext *webkit.WebKitContext40+ Engine port.Engine
42- Pool *webkit.WebViewPool
43- Factory port.WebViewFactory
44- Settings *webkit.SettingsManager
45- Injector *webkit.ContentInjector
46- MessageRouter *webkit.MessageRouter
47 41
48 // Repositories42 // Repositories
49 HistoryRepo repository.HistoryRepository43 HistoryRepo repository.HistoryRepository

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