refactor(M2): replace any with typed interfaces in Engine port
- Replace HandlerDependencies.{HistoryUC,FavoritesUC} any → HomepageHistory/HomepageFavorites
- Replace HandlerDependencies.ConfigGetter func() any → AutoCopyConfig AutoCopyConfig
- Replace RegisterAccentHandlers handler any → AccentKeyHandler
- Replace ConfigureDownloads prepareUC any → DownloadPreparer
- Replace UpdateSettings cfg any → EngineSettingsUpdate{Raw any} (documented wrapper)
- Update webkit/engine.go, engine_init.go, download_handler.go to match new signatures
- Simplify bootstrap/engine.go: remove type assertions now that deps are typed
- Add configAutoCopyAdapter in ui/app.go to satisfy port.AutoCopyConfig
- Only EngineSettingsUpdate.Raw and ApplyWebProcessSettings remain any (documented)- commit
- 516304980718d3f7219fe61ac06f0844571f4d9c
- author
- brice · · 2026-03-17 10:17 UTC
- parent
- d0d5c96
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
6 files · +60 -63
M internal/application/port/engine.go +16 -6
| @@ -127,10 +127,10 @@ type Engine interface { | |||
| 127 | 127 | RegisterHandlers(ctx context.Context, deps HandlerDependencies) error | |
| 128 | 128 | ||
| 129 | 129 | // RegisterAccentHandlers registers accent/dead-key input handlers. | |
| 130 | - | RegisterAccentHandlers(ctx context.Context, handler any) error | |
| 130 | + | RegisterAccentHandlers(ctx context.Context, handler AccentKeyHandler) error | |
| 131 | 131 | ||
| 132 | 132 | // ConfigureDownloads sets up download handling for this engine. | |
| 133 | - | ConfigureDownloads(ctx context.Context, downloadPath string, eventHandler DownloadEventHandler, prepareUC any) error | |
| 133 | + | ConfigureDownloads(ctx context.Context, downloadPath string, eventHandler DownloadEventHandler, preparer DownloadPreparer) error | |
| 134 | 134 | ||
| 135 | 135 | // OnToolkitReady is called after the UI toolkit has initialized. | |
| 136 | 136 | OnToolkitReady(ctx context.Context) error | |
| @@ -139,15 +139,25 @@ type Engine interface { | |||
| 139 | 139 | UpdateAppearance(ctx context.Context, r, g, b, alpha float64) error | |
| 140 | 140 | ||
| 141 | 141 | // UpdateSettings applies runtime config changes to engine internals. | |
| 142 | - | UpdateSettings(ctx context.Context, cfg any) error | |
| 142 | + | UpdateSettings(ctx context.Context, update EngineSettingsUpdate) error | |
| 143 | + | } | |
| 144 | + | ||
| 145 | + | // EngineSettingsUpdate carries a runtime config change to the engine. | |
| 146 | + | // Raw holds the implementation-specific config object; the engine type-asserts | |
| 147 | + | // to its concrete type (e.g. *config.Config for the WebKit engine). | |
| 148 | + | // This is the only intentional use of `any` in the Engine port. | |
| 149 | + | type EngineSettingsUpdate struct { | |
| 150 | + | // Raw holds the implementation-specific config. | |
| 151 | + | // WebKit engine expects *config.Config. | |
| 152 | + | Raw any | |
| 143 | 153 | } | |
| 144 | 154 | ||
| 145 | 155 | // HandlerDependencies holds use cases needed by WebUI message handlers. | |
| 146 | 156 | type HandlerDependencies struct { | |
| 147 | - | HistoryUC any | |
| 148 | - | FavoritesUC any | |
| 157 | + | HistoryUC HomepageHistory | |
| 158 | + | FavoritesUC HomepageFavorites | |
| 149 | 159 | Clipboard Clipboard | |
| 150 | - | ConfigGetter func() any | |
| 160 | + | AutoCopyConfig AutoCopyConfig | |
| 151 | 161 | OnClipboardCopied func(textLen int) | |
| 152 | 162 | } | |
| 153 | 163 | ||
| @@ -127,10 +127,10 @@ type Engine interface { | |||||
| 127 | RegisterHandlers(ctx context.Context, deps HandlerDependencies) error | 127 | RegisterHandlers(ctx context.Context, deps HandlerDependencies) error | ||
| 128 | 128 | ||||
| 129 | // RegisterAccentHandlers registers accent/dead-key input handlers. | 129 | // RegisterAccentHandlers registers accent/dead-key input handlers. | ||
| 130 | - | RegisterAccentHandlers(ctx context.Context, handler any) error | 130 | + | RegisterAccentHandlers(ctx context.Context, handler AccentKeyHandler) error |
| 131 | 131 | ||||
| 132 | // ConfigureDownloads sets up download handling for this engine. | 132 | // ConfigureDownloads sets up download handling for this engine. | ||
| 133 | - | ConfigureDownloads(ctx context.Context, downloadPath string, eventHandler DownloadEventHandler, prepareUC any) error | 133 | + | ConfigureDownloads(ctx context.Context, downloadPath string, eventHandler DownloadEventHandler, preparer DownloadPreparer) error |
| 134 | 134 | ||||
| 135 | // OnToolkitReady is called after the UI toolkit has initialized. | 135 | // OnToolkitReady is called after the UI toolkit has initialized. | ||
| 136 | OnToolkitReady(ctx context.Context) error | 136 | OnToolkitReady(ctx context.Context) error | ||
| @@ -139,15 +139,25 @@ type Engine interface { | |||||
| 139 | UpdateAppearance(ctx context.Context, r, g, b, alpha float64) error | 139 | UpdateAppearance(ctx context.Context, r, g, b, alpha float64) error | ||
| 140 | 140 | ||||
| 141 | // UpdateSettings applies runtime config changes to engine internals. | 141 | // UpdateSettings applies runtime config changes to engine internals. | ||
| 142 | - | UpdateSettings(ctx context.Context, cfg any) error | 142 | + | UpdateSettings(ctx context.Context, update EngineSettingsUpdate) error |
| 143 | + | } | |||
| 144 | + | ||||
| 145 | + | // EngineSettingsUpdate carries a runtime config change to the engine. | |||
| 146 | + | // Raw holds the implementation-specific config object; the engine type-asserts | |||
| 147 | + | // to its concrete type (e.g. *config.Config for the WebKit engine). | |||
| 148 | + | // This is the only intentional use of `any` in the Engine port. | |||
| 149 | + | type EngineSettingsUpdate struct { | |||
| 150 | + | // Raw holds the implementation-specific config. | |||
| 151 | + | // WebKit engine expects *config.Config. | |||
| 152 | + | Raw any | |||
| 143 | } | 153 | } | ||
| 144 | 154 | ||||
| 145 | // HandlerDependencies holds use cases needed by WebUI message handlers. | 155 | // HandlerDependencies holds use cases needed by WebUI message handlers. | ||
| 146 | type HandlerDependencies struct { | 156 | type HandlerDependencies struct { | ||
| 147 | - | HistoryUC any | 157 | + | HistoryUC HomepageHistory |
| 148 | - | FavoritesUC any | 158 | + | FavoritesUC HomepageFavorites |
| 149 | Clipboard Clipboard | 159 | Clipboard Clipboard | ||
| 150 | - | ConfigGetter func() any | 160 | + | AutoCopyConfig AutoCopyConfig |
| 151 | OnClipboardCopied func(textLen int) | 161 | OnClipboardCopied func(textLen int) | ||
| 152 | } | 162 | } | ||
| 153 | 163 | ||||
M internal/bootstrap/engine.go +5 -21
| @@ -54,34 +54,18 @@ func BuildEngine(input EngineInput) (port.Engine, error) { | |||
| 54 | 54 | input.Ctx, cfg, opts, wkCfg, | |
| 55 | 55 | input.ThemeManager, input.ColorResolver, input.Logger, | |
| 56 | 56 | func(ctx context.Context, router *webkit.MessageRouter, deps port.HandlerDependencies) error { | |
| 57 | - | var historyUC port.HomepageHistory | |
| 58 | - | if deps.HistoryUC != nil { | |
| 59 | - | historyUC, _ = deps.HistoryUC.(port.HomepageHistory) | |
| 60 | - | } | |
| 61 | - | var favoritesUC port.HomepageFavorites | |
| 62 | - | if deps.FavoritesUC != nil { | |
| 63 | - | favoritesUC, _ = deps.FavoritesUC.(port.HomepageFavorites) | |
| 64 | - | } | |
| 65 | - | var autoCopyConfig port.AutoCopyConfig | |
| 66 | - | if deps.ConfigGetter != nil { | |
| 67 | - | autoCopyConfig, _ = deps.ConfigGetter().(port.AutoCopyConfig) | |
| 68 | - | } | |
| 69 | 57 | return handlers.RegisterAll(ctx, router, handlers.Config{ | |
| 70 | - | HistoryUC: historyUC, | |
| 71 | - | FavoritesUC: favoritesUC, | |
| 58 | + | HistoryUC: deps.HistoryUC, | |
| 59 | + | FavoritesUC: deps.FavoritesUC, | |
| 72 | 60 | Clipboard: deps.Clipboard, | |
| 73 | - | AutoCopyConfig: autoCopyConfig, | |
| 61 | + | AutoCopyConfig: deps.AutoCopyConfig, | |
| 74 | 62 | SaveConfig: saveConfigFunc, | |
| 75 | 63 | KeybindingsHandler: keybindingsHandler, | |
| 76 | 64 | OnClipboardCopied: deps.OnClipboardCopied, | |
| 77 | 65 | }) | |
| 78 | 66 | }, | |
| 79 | - | func(ctx context.Context, router *webkit.MessageRouter, handler any) error { | |
| 80 | - | accentHandler, ok := handler.(port.AccentKeyHandler) | |
| 81 | - | if !ok { | |
| 82 | - | return fmt.Errorf("handler does not implement port.AccentKeyHandler") | |
| 83 | - | } | |
| 84 | - | return handlers.RegisterAccentHandlers(ctx, router, accentHandler) | |
| 67 | + | func(ctx context.Context, router *webkit.MessageRouter, handler port.AccentKeyHandler) error { | |
| 68 | + | return handlers.RegisterAccentHandlers(ctx, router, handler) | |
| 85 | 69 | }, | |
| 86 | 70 | ) | |
| 87 | 71 | case "cef": | |
| @@ -54,34 +54,18 @@ func BuildEngine(input EngineInput) (port.Engine, error) { | |||||
| 54 | input.Ctx, cfg, opts, wkCfg, | 54 | input.Ctx, cfg, opts, wkCfg, | ||
| 55 | input.ThemeManager, input.ColorResolver, input.Logger, | 55 | input.ThemeManager, input.ColorResolver, input.Logger, | ||
| 56 | func(ctx context.Context, router *webkit.MessageRouter, deps port.HandlerDependencies) error { | 56 | func(ctx context.Context, router *webkit.MessageRouter, deps port.HandlerDependencies) error { | ||
| 57 | - | var historyUC port.HomepageHistory | |||
| 58 | - | if deps.HistoryUC != nil { | |||
| 59 | - | historyUC, _ = deps.HistoryUC.(port.HomepageHistory) | |||
| 60 | - | } | |||
| 61 | - | var favoritesUC port.HomepageFavorites | |||
| 62 | - | if deps.FavoritesUC != nil { | |||
| 63 | - | favoritesUC, _ = deps.FavoritesUC.(port.HomepageFavorites) | |||
| 64 | - | } | |||
| 65 | - | var autoCopyConfig port.AutoCopyConfig | |||
| 66 | - | if deps.ConfigGetter != nil { | |||
| 67 | - | autoCopyConfig, _ = deps.ConfigGetter().(port.AutoCopyConfig) | |||
| 68 | - | } | |||
| 69 | return handlers.RegisterAll(ctx, router, handlers.Config{ | 57 | return handlers.RegisterAll(ctx, router, handlers.Config{ | ||
| 70 | - | HistoryUC: historyUC, | 58 | + | HistoryUC: deps.HistoryUC, |
| 71 | - | FavoritesUC: favoritesUC, | 59 | + | FavoritesUC: deps.FavoritesUC, |
| 72 | Clipboard: deps.Clipboard, | 60 | Clipboard: deps.Clipboard, | ||
| 73 | - | AutoCopyConfig: autoCopyConfig, | 61 | + | AutoCopyConfig: deps.AutoCopyConfig, |
| 74 | SaveConfig: saveConfigFunc, | 62 | SaveConfig: saveConfigFunc, | ||
| 75 | KeybindingsHandler: keybindingsHandler, | 63 | KeybindingsHandler: keybindingsHandler, | ||
| 76 | OnClipboardCopied: deps.OnClipboardCopied, | 64 | OnClipboardCopied: deps.OnClipboardCopied, | ||
| 77 | }) | 65 | }) | ||
| 78 | }, | 66 | }, | ||
| 79 | - | func(ctx context.Context, router *webkit.MessageRouter, handler any) error { | 67 | + | func(ctx context.Context, router *webkit.MessageRouter, handler port.AccentKeyHandler) error { |
| 80 | - | accentHandler, ok := handler.(port.AccentKeyHandler) | 68 | + | return handlers.RegisterAccentHandlers(ctx, router, handler) |
| 81 | - | if !ok { | |||
| 82 | - | return fmt.Errorf("handler does not implement port.AccentKeyHandler") | |||
| 83 | - | } | |||
| 84 | - | return handlers.RegisterAccentHandlers(ctx, router, accentHandler) | |||
| 85 | }, | 69 | }, | ||
| 86 | ) | 70 | ) | ||
| 87 | case "cef": | 71 | case "cef": | ||
M internal/infrastructure/webkit/download_handler.go +14 -15
| @@ -7,7 +7,6 @@ import ( | |||
| 7 | 7 | "sync" | |
| 8 | 8 | ||
| 9 | 9 | "github.com/bnema/dumber/internal/application/port" | |
| 10 | - | "github.com/bnema/dumber/internal/application/usecase" | |
| 11 | 10 | downloadutil "github.com/bnema/dumber/internal/domain/download" | |
| 12 | 11 | "github.com/bnema/dumber/internal/logging" | |
| 13 | 12 | "github.com/bnema/puregotk-webkit/webkit" | |
| @@ -20,26 +19,26 @@ const ( | |||
| 20 | 19 | ||
| 21 | 20 | // DownloadHandler manages WebKit downloads and notifies the UI layer. | |
| 22 | 21 | type DownloadHandler struct { | |
| 23 | - | downloadPath string | |
| 24 | - | eventHandler port.DownloadEventHandler | |
| 25 | - | prepareDownloadUC *usecase.PrepareDownloadUseCase | |
| 26 | - | mu sync.RWMutex | |
| 22 | + | downloadPath string | |
| 23 | + | eventHandler port.DownloadEventHandler | |
| 24 | + | preparer port.DownloadPreparer | |
| 25 | + | mu sync.RWMutex | |
| 27 | 26 | } | |
| 28 | 27 | ||
| 29 | 28 | // NewDownloadHandler creates a new download handler. | |
| 30 | - | // Panics if prepareDownloadUC is nil (fail fast on misconfiguration). | |
| 29 | + | // Panics if preparer is nil (fail fast on misconfiguration). | |
| 31 | 30 | func NewDownloadHandler( | |
| 32 | 31 | downloadPath string, | |
| 33 | 32 | handler port.DownloadEventHandler, | |
| 34 | - | prepareDownloadUC *usecase.PrepareDownloadUseCase, | |
| 33 | + | preparer port.DownloadPreparer, | |
| 35 | 34 | ) *DownloadHandler { | |
| 36 | - | if prepareDownloadUC == nil { | |
| 37 | - | panic("prepareDownloadUC is required") | |
| 35 | + | if preparer == nil { | |
| 36 | + | panic("preparer is required") | |
| 38 | 37 | } | |
| 39 | 38 | return &DownloadHandler{ | |
| 40 | - | downloadPath: downloadPath, | |
| 41 | - | eventHandler: handler, | |
| 42 | - | prepareDownloadUC: prepareDownloadUC, | |
| 39 | + | downloadPath: downloadPath, | |
| 40 | + | eventHandler: handler, | |
| 41 | + | preparer: preparer, | |
| 43 | 42 | } | |
| 44 | 43 | } | |
| 45 | 44 | ||
| @@ -57,7 +56,7 @@ func (h *DownloadHandler) HandleDownload(ctx context.Context, download *webkit.D | |||
| 57 | 56 | h.mu.RLock() | |
| 58 | 57 | downloadPath := h.downloadPath | |
| 59 | 58 | eventHandler := h.eventHandler | |
| 60 | - | prepareDownloadUC := h.prepareDownloadUC | |
| 59 | + | preparer := h.preparer | |
| 61 | 60 | h.mu.RUnlock() | |
| 62 | 61 | ||
| 63 | 62 | // Track download state in a dedicated struct to ensure proper isolation. | |
| @@ -80,8 +79,8 @@ func (h *DownloadHandler) HandleDownload(ctx context.Context, download *webkit.D | |||
| 80 | 79 | response = &uriResponseAdapter{resp: resp} | |
| 81 | 80 | } | |
| 82 | 81 | ||
| 83 | - | // Use PrepareDownloadUseCase to resolve filename | |
| 84 | - | output := prepareDownloadUC.Execute(ctx, usecase.PrepareDownloadInput{ | |
| 82 | + | // Use DownloadPreparer to resolve filename | |
| 83 | + | output := preparer.Execute(ctx, port.DownloadPrepareInput{ | |
| 85 | 84 | SuggestedFilename: suggestedFilename, | |
| 86 | 85 | Response: response, | |
| 87 | 86 | DownloadDir: downloadPath, | |
| @@ -7,7 +7,6 @@ import ( | |||||
| 7 | "sync" | 7 | "sync" | ||
| 8 | 8 | ||||
| 9 | "github.com/bnema/dumber/internal/application/port" | 9 | "github.com/bnema/dumber/internal/application/port" | ||
| 10 | - | "github.com/bnema/dumber/internal/application/usecase" | |||
| 11 | downloadutil "github.com/bnema/dumber/internal/domain/download" | 10 | downloadutil "github.com/bnema/dumber/internal/domain/download" | ||
| 12 | "github.com/bnema/dumber/internal/logging" | 11 | "github.com/bnema/dumber/internal/logging" | ||
| 13 | "github.com/bnema/puregotk-webkit/webkit" | 12 | "github.com/bnema/puregotk-webkit/webkit" | ||
| @@ -20,26 +19,26 @@ const ( | |||||
| 20 | 19 | ||||
| 21 | // DownloadHandler manages WebKit downloads and notifies the UI layer. | 20 | // DownloadHandler manages WebKit downloads and notifies the UI layer. | ||
| 22 | type DownloadHandler struct { | 21 | type DownloadHandler struct { | ||
| 23 | - | downloadPath string | 22 | + | downloadPath string |
| 24 | - | eventHandler port.DownloadEventHandler | 23 | + | eventHandler port.DownloadEventHandler |
| 25 | - | prepareDownloadUC *usecase.PrepareDownloadUseCase | 24 | + | preparer port.DownloadPreparer |
| 26 | - | mu sync.RWMutex | 25 | + | mu sync.RWMutex |
| 27 | } | 26 | } | ||
| 28 | 27 | ||||
| 29 | // NewDownloadHandler creates a new download handler. | 28 | // NewDownloadHandler creates a new download handler. | ||
| 30 | - | // Panics if prepareDownloadUC is nil (fail fast on misconfiguration). | 29 | + | // Panics if preparer is nil (fail fast on misconfiguration). |
| 31 | func NewDownloadHandler( | 30 | func NewDownloadHandler( | ||
| 32 | downloadPath string, | 31 | downloadPath string, | ||
| 33 | handler port.DownloadEventHandler, | 32 | handler port.DownloadEventHandler, | ||
| 34 | - | prepareDownloadUC *usecase.PrepareDownloadUseCase, | 33 | + | preparer port.DownloadPreparer, |
| 35 | ) *DownloadHandler { | 34 | ) *DownloadHandler { | ||
| 36 | - | if prepareDownloadUC == nil { | 35 | + | if preparer == nil { |
| 37 | - | panic("prepareDownloadUC is required") | 36 | + | panic("preparer is required") |
| 38 | } | 37 | } | ||
| 39 | return &DownloadHandler{ | 38 | return &DownloadHandler{ | ||
| 40 | - | downloadPath: downloadPath, | 39 | + | downloadPath: downloadPath, |
| 41 | - | eventHandler: handler, | 40 | + | eventHandler: handler, |
| 42 | - | prepareDownloadUC: prepareDownloadUC, | 41 | + | preparer: preparer, |
| 43 | } | 42 | } | ||
| 44 | } | 43 | } | ||
| 45 | 44 | ||||
| @@ -57,7 +56,7 @@ func (h *DownloadHandler) HandleDownload(ctx context.Context, download *webkit.D | |||||
| 57 | h.mu.RLock() | 56 | h.mu.RLock() | ||
| 58 | downloadPath := h.downloadPath | 57 | downloadPath := h.downloadPath | ||
| 59 | eventHandler := h.eventHandler | 58 | eventHandler := h.eventHandler | ||
| 60 | - | prepareDownloadUC := h.prepareDownloadUC | 59 | + | preparer := h.preparer |
| 61 | h.mu.RUnlock() | 60 | h.mu.RUnlock() | ||
| 62 | 61 | ||||
| 63 | // Track download state in a dedicated struct to ensure proper isolation. | 62 | // Track download state in a dedicated struct to ensure proper isolation. | ||
| @@ -80,8 +79,8 @@ func (h *DownloadHandler) HandleDownload(ctx context.Context, download *webkit.D | |||||
| 80 | response = &uriResponseAdapter{resp: resp} | 79 | response = &uriResponseAdapter{resp: resp} | ||
| 81 | } | 80 | } | ||
| 82 | 81 | ||||
| 83 | - | // Use PrepareDownloadUseCase to resolve filename | 82 | + | // Use DownloadPreparer to resolve filename |
| 84 | - | output := prepareDownloadUC.Execute(ctx, usecase.PrepareDownloadInput{ | 83 | + | output := preparer.Execute(ctx, port.DownloadPrepareInput{ |
| 85 | SuggestedFilename: suggestedFilename, | 84 | SuggestedFilename: suggestedFilename, | ||
| 86 | Response: response, | 85 | Response: response, | ||
| 87 | DownloadDir: downloadPath, | 86 | DownloadDir: downloadPath, | ||
M internal/infrastructure/webkit/engine.go +8 -13
| @@ -5,7 +5,6 @@ import ( | |||
| 5 | 5 | "fmt" | |
| 6 | 6 | ||
| 7 | 7 | "github.com/bnema/dumber/internal/application/port" | |
| 8 | - | "github.com/bnema/dumber/internal/application/usecase" | |
| 9 | 8 | "github.com/bnema/dumber/internal/infrastructure/config" | |
| 10 | 9 | "github.com/bnema/dumber/internal/infrastructure/filtering" | |
| 11 | 10 | "github.com/rs/zerolog" | |
| @@ -27,7 +26,7 @@ type Engine struct { | |||
| 27 | 26 | ||
| 28 | 27 | // Handler registrars - injected at construction to avoid import cycles. | |
| 29 | 28 | handlerRegistrar func(ctx context.Context, router *MessageRouter, deps port.HandlerDependencies) error | |
| 30 | - | accentHandlerRegistrar func(ctx context.Context, router *MessageRouter, handler any) error | |
| 29 | + | accentHandlerRegistrar func(ctx context.Context, router *MessageRouter, handler port.AccentKeyHandler) error | |
| 31 | 30 | } | |
| 32 | 31 | ||
| 33 | 32 | // Compile-time check that Engine implements port.Engine. | |
| @@ -112,7 +111,7 @@ func (e *Engine) RegisterHandlers(ctx context.Context, deps port.HandlerDependen | |||
| 112 | 111 | } | |
| 113 | 112 | ||
| 114 | 113 | // RegisterAccentHandlers registers accent/dead-key input handlers. | |
| 115 | - | func (e *Engine) RegisterAccentHandlers(ctx context.Context, handler any) error { | |
| 114 | + | func (e *Engine) RegisterAccentHandlers(ctx context.Context, handler port.AccentKeyHandler) error { | |
| 116 | 115 | if e.messageRouter == nil { | |
| 117 | 116 | return fmt.Errorf("message router not initialized") | |
| 118 | 117 | } | |
| @@ -123,15 +122,11 @@ func (e *Engine) RegisterAccentHandlers(ctx context.Context, handler any) error | |||
| 123 | 122 | } | |
| 124 | 123 | ||
| 125 | 124 | // ConfigureDownloads sets up download handling. | |
| 126 | - | func (e *Engine) ConfigureDownloads(ctx context.Context, downloadPath string, eventHandler port.DownloadEventHandler, prepareUC any) error { | |
| 125 | + | func (e *Engine) ConfigureDownloads(ctx context.Context, downloadPath string, eventHandler port.DownloadEventHandler, preparer port.DownloadPreparer) error { | |
| 127 | 126 | if e.wkCtx == nil { | |
| 128 | 127 | return fmt.Errorf("webkit context not initialized") | |
| 129 | 128 | } | |
| 130 | - | uc, ok := prepareUC.(*usecase.PrepareDownloadUseCase) | |
| 131 | - | if !ok { | |
| 132 | - | return fmt.Errorf("prepareUC does not implement PrepareDownloadUseCase") | |
| 133 | - | } | |
| 134 | - | handler := NewDownloadHandler(downloadPath, eventHandler, uc) | |
| 129 | + | handler := NewDownloadHandler(downloadPath, eventHandler, preparer) | |
| 135 | 130 | e.wkCtx.SetDownloadHandler(ctx, handler) | |
| 136 | 131 | return nil | |
| 137 | 132 | } | |
| @@ -156,13 +151,13 @@ func (e *Engine) UpdateAppearance(_ context.Context, r, g, b, alpha float64) err | |||
| 156 | 151 | } | |
| 157 | 152 | ||
| 158 | 153 | // UpdateSettings applies runtime config changes to engine settings. | |
| 159 | - | func (e *Engine) UpdateSettings(ctx context.Context, cfg any) error { | |
| 160 | - | configCfg, ok := cfg.(*config.Config) | |
| 154 | + | func (e *Engine) UpdateSettings(ctx context.Context, update port.EngineSettingsUpdate) error { | |
| 155 | + | cfg, ok := update.Raw.(*config.Config) | |
| 161 | 156 | if !ok { | |
| 162 | - | return fmt.Errorf("expected *config.Config, got %T", cfg) | |
| 157 | + | return fmt.Errorf("UpdateSettings: expected *config.Config, got %T", update.Raw) | |
| 163 | 158 | } | |
| 164 | 159 | if e.settings != nil { | |
| 165 | - | e.settings.UpdateFromConfig(ctx, configCfg) | |
| 160 | + | e.settings.UpdateFromConfig(ctx, cfg) | |
| 166 | 161 | } | |
| 167 | 162 | return nil | |
| 168 | 163 | } | |
| @@ -5,7 +5,6 @@ import ( | |||||
| 5 | "fmt" | 5 | "fmt" | ||
| 6 | 6 | ||||
| 7 | "github.com/bnema/dumber/internal/application/port" | 7 | "github.com/bnema/dumber/internal/application/port" | ||
| 8 | - | "github.com/bnema/dumber/internal/application/usecase" | |||
| 9 | "github.com/bnema/dumber/internal/infrastructure/config" | 8 | "github.com/bnema/dumber/internal/infrastructure/config" | ||
| 10 | "github.com/bnema/dumber/internal/infrastructure/filtering" | 9 | "github.com/bnema/dumber/internal/infrastructure/filtering" | ||
| 11 | "github.com/rs/zerolog" | 10 | "github.com/rs/zerolog" | ||
| @@ -27,7 +26,7 @@ type Engine struct { | |||||
| 27 | 26 | ||||
| 28 | // Handler registrars - injected at construction to avoid import cycles. | 27 | // Handler registrars - injected at construction to avoid import cycles. | ||
| 29 | handlerRegistrar func(ctx context.Context, router *MessageRouter, deps port.HandlerDependencies) error | 28 | handlerRegistrar func(ctx context.Context, router *MessageRouter, deps port.HandlerDependencies) error | ||
| 30 | - | accentHandlerRegistrar func(ctx context.Context, router *MessageRouter, handler any) error | 29 | + | accentHandlerRegistrar func(ctx context.Context, router *MessageRouter, handler port.AccentKeyHandler) error |
| 31 | } | 30 | } | ||
| 32 | 31 | ||||
| 33 | // Compile-time check that Engine implements port.Engine. | 32 | // Compile-time check that Engine implements port.Engine. | ||
| @@ -112,7 +111,7 @@ func (e *Engine) RegisterHandlers(ctx context.Context, deps port.HandlerDependen | |||||
| 112 | } | 111 | } | ||
| 113 | 112 | ||||
| 114 | // RegisterAccentHandlers registers accent/dead-key input handlers. | 113 | // RegisterAccentHandlers registers accent/dead-key input handlers. | ||
| 115 | - | func (e *Engine) RegisterAccentHandlers(ctx context.Context, handler any) error { | 114 | + | func (e *Engine) RegisterAccentHandlers(ctx context.Context, handler port.AccentKeyHandler) error { |
| 116 | if e.messageRouter == nil { | 115 | if e.messageRouter == nil { | ||
| 117 | return fmt.Errorf("message router not initialized") | 116 | return fmt.Errorf("message router not initialized") | ||
| 118 | } | 117 | } | ||
| @@ -123,15 +122,11 @@ func (e *Engine) RegisterAccentHandlers(ctx context.Context, handler any) error | |||||
| 123 | } | 122 | } | ||
| 124 | 123 | ||||
| 125 | // ConfigureDownloads sets up download handling. | 124 | // ConfigureDownloads sets up download handling. | ||
| 126 | - | func (e *Engine) ConfigureDownloads(ctx context.Context, downloadPath string, eventHandler port.DownloadEventHandler, prepareUC any) error { | 125 | + | func (e *Engine) ConfigureDownloads(ctx context.Context, downloadPath string, eventHandler port.DownloadEventHandler, preparer port.DownloadPreparer) error { |
| 127 | if e.wkCtx == nil { | 126 | if e.wkCtx == nil { | ||
| 128 | return fmt.Errorf("webkit context not initialized") | 127 | return fmt.Errorf("webkit context not initialized") | ||
| 129 | } | 128 | } | ||
| 130 | - | uc, ok := prepareUC.(*usecase.PrepareDownloadUseCase) | 129 | + | handler := NewDownloadHandler(downloadPath, eventHandler, preparer) |
| 131 | - | if !ok { | |||
| 132 | - | return fmt.Errorf("prepareUC does not implement PrepareDownloadUseCase") | |||
| 133 | - | } | |||
| 134 | - | handler := NewDownloadHandler(downloadPath, eventHandler, uc) | |||
| 135 | e.wkCtx.SetDownloadHandler(ctx, handler) | 130 | e.wkCtx.SetDownloadHandler(ctx, handler) | ||
| 136 | return nil | 131 | return nil | ||
| 137 | } | 132 | } | ||
| @@ -156,13 +151,13 @@ func (e *Engine) UpdateAppearance(_ context.Context, r, g, b, alpha float64) err | |||||
| 156 | } | 151 | } | ||
| 157 | 152 | ||||
| 158 | // UpdateSettings applies runtime config changes to engine settings. | 153 | // UpdateSettings applies runtime config changes to engine settings. | ||
| 159 | - | func (e *Engine) UpdateSettings(ctx context.Context, cfg any) error { | 154 | + | func (e *Engine) UpdateSettings(ctx context.Context, update port.EngineSettingsUpdate) error { |
| 160 | - | configCfg, ok := cfg.(*config.Config) | 155 | + | cfg, ok := update.Raw.(*config.Config) |
| 161 | if !ok { | 156 | if !ok { | ||
| 162 | - | return fmt.Errorf("expected *config.Config, got %T", cfg) | 157 | + | return fmt.Errorf("UpdateSettings: expected *config.Config, got %T", update.Raw) |
| 163 | } | 158 | } | ||
| 164 | if e.settings != nil { | 159 | if e.settings != nil { | ||
| 165 | - | e.settings.UpdateFromConfig(ctx, configCfg) | 160 | + | e.settings.UpdateFromConfig(ctx, cfg) |
| 166 | } | 161 | } | ||
| 167 | return nil | 162 | return nil | ||
| 168 | } | 163 | } | ||
M internal/infrastructure/webkit/engine_init.go +1 -1
| @@ -27,7 +27,7 @@ func NewEngine( | |||
| 27 | 27 | colorResolver port.ColorSchemeResolver, | |
| 28 | 28 | logger zerolog.Logger, | |
| 29 | 29 | handlerRegistrar func(ctx context.Context, router *MessageRouter, deps port.HandlerDependencies) error, | |
| 30 | - | accentHandlerRegistrar func(ctx context.Context, router *MessageRouter, handler any) error, | |
| 30 | + | accentHandlerRegistrar func(ctx context.Context, router *MessageRouter, handler port.AccentKeyHandler) error, | |
| 31 | 31 | ) (*Engine, error) { | |
| 32 | 32 | // --- Hardware survey and performance profile resolution --- | |
| 33 | 33 | perfSettings := engineSurveyHardwareAndResolveProfile(ctx, cfg, logger) | |
| @@ -27,7 +27,7 @@ func NewEngine( | |||||
| 27 | colorResolver port.ColorSchemeResolver, | 27 | colorResolver port.ColorSchemeResolver, | ||
| 28 | logger zerolog.Logger, | 28 | logger zerolog.Logger, | ||
| 29 | handlerRegistrar func(ctx context.Context, router *MessageRouter, deps port.HandlerDependencies) error, | 29 | handlerRegistrar func(ctx context.Context, router *MessageRouter, deps port.HandlerDependencies) error, | ||
| 30 | - | accentHandlerRegistrar func(ctx context.Context, router *MessageRouter, handler any) error, | 30 | + | accentHandlerRegistrar func(ctx context.Context, router *MessageRouter, handler port.AccentKeyHandler) error, |
| 31 | ) (*Engine, error) { | 31 | ) (*Engine, error) { | ||
| 32 | // --- Hardware survey and performance profile resolution --- | 32 | // --- Hardware survey and performance profile resolution --- | ||
| 33 | perfSettings := engineSurveyHardwareAndResolveProfile(ctx, cfg, logger) | 33 | perfSettings := engineSurveyHardwareAndResolveProfile(ctx, cfg, logger) | ||
M internal/ui/app.go +16 -7
| @@ -181,12 +181,10 @@ func New(deps *Dependencies) (*App, error) { | |||
| 181 | 181 | } | |
| 182 | 182 | // Register message handlers through the engine. | |
| 183 | 183 | if err := deps.Engine.RegisterHandlers(ctx, port.HandlerDependencies{ | |
| 184 | - | HistoryUC: deps.HistoryUC, | |
| 185 | - | FavoritesUC: deps.FavoritesUC, | |
| 186 | - | Clipboard: deps.Clipboard, | |
| 187 | - | ConfigGetter: func() any { | |
| 188 | - | return config.Get() | |
| 189 | - | }, | |
| 184 | + | HistoryUC: deps.HistoryUC, | |
| 185 | + | FavoritesUC: deps.FavoritesUC, | |
| 186 | + | Clipboard: deps.Clipboard, | |
| 187 | + | AutoCopyConfig: &configAutoCopyAdapter{}, | |
| 190 | 188 | OnClipboardCopied: func(textLen int) { | |
| 191 | 189 | cb := glib.SourceFunc(func(_ uintptr) bool { | |
| 192 | 190 | if app.appToaster != nil { | |
| @@ -621,6 +619,17 @@ func (d *downloadEventAdapter) OnDownloadEvent(ctx context.Context, event port.D | |||
| 621 | 619 | glib.IdleAdd(&cb, 0) | |
| 622 | 620 | } | |
| 623 | 621 | ||
| 622 | + | // configAutoCopyAdapter implements port.AutoCopyConfig by reading the live config. | |
| 623 | + | type configAutoCopyAdapter struct{} | |
| 624 | + | ||
| 625 | + | func (a *configAutoCopyAdapter) IsAutoCopyEnabled() bool { | |
| 626 | + | cfg := config.Get() | |
| 627 | + | if cfg == nil { | |
| 628 | + | return false | |
| 629 | + | } | |
| 630 | + | return cfg.Clipboard.AutoCopyOnSelection | |
| 631 | + | } | |
| 632 | + | ||
| 624 | 633 | func (a *App) initKeyboardHandler(ctx context.Context) { | |
| 625 | 634 | log := logging.FromContext(ctx) | |
| 626 | 635 | ||
| @@ -3063,7 +3072,7 @@ func (a *App) applyAppearanceConfig(ctx context.Context, cfg *config.Config) { | |||
| 3063 | 3072 | } | |
| 3064 | 3073 | ||
| 3065 | 3074 | if a.engine != nil { | |
| 3066 | - | _ = a.engine.UpdateSettings(ctx, cfg) | |
| 3075 | + | _ = a.engine.UpdateSettings(ctx, port.EngineSettingsUpdate{Raw: cfg}) | |
| 3067 | 3076 | } | |
| 3068 | 3077 | ||
| 3069 | 3078 | // Apply settings to existing webviews via coordinator | |
| @@ -181,12 +181,10 @@ func New(deps *Dependencies) (*App, error) { | |||||
| 181 | } | 181 | } | ||
| 182 | // Register message handlers through the engine. | 182 | // Register message handlers through the engine. | ||
| 183 | if err := deps.Engine.RegisterHandlers(ctx, port.HandlerDependencies{ | 183 | if err := deps.Engine.RegisterHandlers(ctx, port.HandlerDependencies{ | ||
| 184 | - | HistoryUC: deps.HistoryUC, | 184 | + | HistoryUC: deps.HistoryUC, |
| 185 | - | FavoritesUC: deps.FavoritesUC, | 185 | + | FavoritesUC: deps.FavoritesUC, |
| 186 | - | Clipboard: deps.Clipboard, | 186 | + | Clipboard: deps.Clipboard, |
| 187 | - | ConfigGetter: func() any { | 187 | + | AutoCopyConfig: &configAutoCopyAdapter{}, |
| 188 | - | return config.Get() | |||
| 189 | - | }, | |||
| 190 | OnClipboardCopied: func(textLen int) { | 188 | OnClipboardCopied: func(textLen int) { | ||
| 191 | cb := glib.SourceFunc(func(_ uintptr) bool { | 189 | cb := glib.SourceFunc(func(_ uintptr) bool { | ||
| 192 | if app.appToaster != nil { | 190 | if app.appToaster != nil { | ||
| @@ -621,6 +619,17 @@ func (d *downloadEventAdapter) OnDownloadEvent(ctx context.Context, event port.D | |||||
| 621 | glib.IdleAdd(&cb, 0) | 619 | glib.IdleAdd(&cb, 0) | ||
| 622 | } | 620 | } | ||
| 623 | 621 | ||||
| 622 | + | // configAutoCopyAdapter implements port.AutoCopyConfig by reading the live config. | |||
| 623 | + | type configAutoCopyAdapter struct{} | |||
| 624 | + | ||||
| 625 | + | func (a *configAutoCopyAdapter) IsAutoCopyEnabled() bool { | |||
| 626 | + | cfg := config.Get() | |||
| 627 | + | if cfg == nil { | |||
| 628 | + | return false | |||
| 629 | + | } | |||
| 630 | + | return cfg.Clipboard.AutoCopyOnSelection | |||
| 631 | + | } | |||
| 632 | + | ||||
| 624 | func (a *App) initKeyboardHandler(ctx context.Context) { | 633 | func (a *App) initKeyboardHandler(ctx context.Context) { | ||
| 625 | log := logging.FromContext(ctx) | 634 | log := logging.FromContext(ctx) | ||
| 626 | 635 | ||||
| @@ -3063,7 +3072,7 @@ func (a *App) applyAppearanceConfig(ctx context.Context, cfg *config.Config) { | |||||
| 3063 | } | 3072 | } | ||
| 3064 | 3073 | ||||
| 3065 | if a.engine != nil { | 3074 | if a.engine != nil { | ||
| 3066 | - | _ = a.engine.UpdateSettings(ctx, cfg) | 3075 | + | _ = a.engine.UpdateSettings(ctx, port.EngineSettingsUpdate{Raw: cfg}) |
| 3067 | } | 3076 | } | ||
| 3068 | 3077 | ||||
| 3069 | // Apply settings to existing webviews via coordinator | 3078 | // Apply settings to existing webviews via coordinator | ||