feat(history): persist page titles via ContentCoordinator callback
- commit
- 751112c6e8f0f10d7d1eb7538604d08985ac837c
- author
- brice · · 2025-12-16 18:24 UTC
- parent
- 6a3405f
- signature
- unsigned
2 files · +23 -0
M internal/ui/app.go +5 -0
| @@ -294,6 +294,11 @@ func (a *App) initCoordinators(ctx context.Context) { | |||
| 294 | 294 | a.contentCoord, | |
| 295 | 295 | ) | |
| 296 | 296 | ||
| 297 | + | // Wire title updates to history persistence | |
| 298 | + | a.contentCoord.SetOnTitleUpdated(func(ctx context.Context, paneID entity.PaneID, url, title string) { | |
| 299 | + | a.navCoord.UpdateHistoryTitle(ctx, paneID, url, title) | |
| 300 | + | }) | |
| 301 | + | ||
| 297 | 302 | // 5. Keyboard Dispatcher | |
| 298 | 303 | a.kbDispatcher = dispatcher.NewKeyboardDispatcher( | |
| 299 | 304 | ctx, | |
| @@ -294,6 +294,11 @@ func (a *App) initCoordinators(ctx context.Context) { | |||||
| 294 | a.contentCoord, | 294 | a.contentCoord, | ||
| 295 | ) | 295 | ) | ||
| 296 | 296 | ||||
| 297 | + | // Wire title updates to history persistence | |||
| 298 | + | a.contentCoord.SetOnTitleUpdated(func(ctx context.Context, paneID entity.PaneID, url, title string) { | |||
| 299 | + | a.navCoord.UpdateHistoryTitle(ctx, paneID, url, title) | |||
| 300 | + | }) | |||
| 301 | + | ||||
| 297 | // 5. Keyboard Dispatcher | 302 | // 5. Keyboard Dispatcher | ||
| 298 | a.kbDispatcher = dispatcher.NewKeyboardDispatcher( | 303 | a.kbDispatcher = dispatcher.NewKeyboardDispatcher( | ||
| 299 | ctx, | 304 | ctx, | ||
M internal/ui/coordinator/content.go +18 -0
| @@ -31,6 +31,9 @@ type ContentCoordinator struct { | |||
| 31 | 31 | ||
| 32 | 32 | // Callback to get active workspace state (avoids circular dependency) | |
| 33 | 33 | getActiveWS func() (*entity.Workspace, *component.WorkspaceView) | |
| 34 | + | ||
| 35 | + | // Callback when title changes (for history persistence) | |
| 36 | + | onTitleUpdated func(ctx context.Context, paneID entity.PaneID, url, title string) | |
| 34 | 37 | } | |
| 35 | 38 | ||
| 36 | 39 | // NewContentCoordinator creates a new ContentCoordinator. | |
| @@ -55,6 +58,11 @@ func NewContentCoordinator( | |||
| 55 | 58 | } | |
| 56 | 59 | } | |
| 57 | 60 | ||
| 61 | + | // SetOnTitleUpdated sets the callback for title changes (for history persistence). | |
| 62 | + | func (c *ContentCoordinator) SetOnTitleUpdated(fn func(ctx context.Context, paneID entity.PaneID, url, title string)) { | |
| 63 | + | c.onTitleUpdated = fn | |
| 64 | + | } | |
| 65 | + | ||
| 58 | 66 | // EnsureWebView acquires or reuses a WebView for the given pane. | |
| 59 | 67 | func (c *ContentCoordinator) EnsureWebView(ctx context.Context, paneID entity.PaneID) (*webkit.WebView, error) { | |
| 60 | 68 | log := logging.FromContext(ctx) | |
| @@ -231,6 +239,16 @@ func (c *ContentCoordinator) onTitleChanged(ctx context.Context, paneID entity.P | |||
| 231 | 239 | } | |
| 232 | 240 | } | |
| 233 | 241 | ||
| 242 | + | // Notify history persistence (get URL from WebView) | |
| 243 | + | if c.onTitleUpdated != nil { | |
| 244 | + | if wv := c.webViews[paneID]; wv != nil { | |
| 245 | + | url := wv.URI() | |
| 246 | + | if url != "" && title != "" { | |
| 247 | + | c.onTitleUpdated(ctx, paneID, url, title) | |
| 248 | + | } | |
| 249 | + | } | |
| 250 | + | } | |
| 251 | + | ||
| 234 | 252 | log.Debug(). | |
| 235 | 253 | Str("pane_id", string(paneID)). | |
| 236 | 254 | Str("title", title). | |
| @@ -31,6 +31,9 @@ type ContentCoordinator struct { | |||||
| 31 | 31 | ||||
| 32 | // Callback to get active workspace state (avoids circular dependency) | 32 | // Callback to get active workspace state (avoids circular dependency) | ||
| 33 | getActiveWS func() (*entity.Workspace, *component.WorkspaceView) | 33 | getActiveWS func() (*entity.Workspace, *component.WorkspaceView) | ||
| 34 | + | ||||
| 35 | + | // Callback when title changes (for history persistence) | |||
| 36 | + | onTitleUpdated func(ctx context.Context, paneID entity.PaneID, url, title string) | |||
| 34 | } | 37 | } | ||
| 35 | 38 | ||||
| 36 | // NewContentCoordinator creates a new ContentCoordinator. | 39 | // NewContentCoordinator creates a new ContentCoordinator. | ||
| @@ -55,6 +58,11 @@ func NewContentCoordinator( | |||||
| 55 | } | 58 | } | ||
| 56 | } | 59 | } | ||
| 57 | 60 | ||||
| 61 | + | // SetOnTitleUpdated sets the callback for title changes (for history persistence). | |||
| 62 | + | func (c *ContentCoordinator) SetOnTitleUpdated(fn func(ctx context.Context, paneID entity.PaneID, url, title string)) { | |||
| 63 | + | c.onTitleUpdated = fn | |||
| 64 | + | } | |||
| 65 | + | ||||
| 58 | // EnsureWebView acquires or reuses a WebView for the given pane. | 66 | // EnsureWebView acquires or reuses a WebView for the given pane. | ||
| 59 | func (c *ContentCoordinator) EnsureWebView(ctx context.Context, paneID entity.PaneID) (*webkit.WebView, error) { | 67 | func (c *ContentCoordinator) EnsureWebView(ctx context.Context, paneID entity.PaneID) (*webkit.WebView, error) { | ||
| 60 | log := logging.FromContext(ctx) | 68 | log := logging.FromContext(ctx) | ||
| @@ -231,6 +239,16 @@ func (c *ContentCoordinator) onTitleChanged(ctx context.Context, paneID entity.P | |||||
| 231 | } | 239 | } | ||
| 232 | } | 240 | } | ||
| 233 | 241 | ||||
| 242 | + | // Notify history persistence (get URL from WebView) | |||
| 243 | + | if c.onTitleUpdated != nil { | |||
| 244 | + | if wv := c.webViews[paneID]; wv != nil { | |||
| 245 | + | url := wv.URI() | |||
| 246 | + | if url != "" && title != "" { | |||
| 247 | + | c.onTitleUpdated(ctx, paneID, url, title) | |||
| 248 | + | } | |||
| 249 | + | } | |||
| 250 | + | } | |||
| 251 | + | ||||
| 234 | log.Debug(). | 252 | log.Debug(). | ||
| 235 | Str("pane_id", string(paneID)). | 253 | Str("pane_id", string(paneID)). | ||
| 236 | Str("title", title). | 254 | Str("title", title). | ||