browser_window_history_sidebar.go RawHistoryFolder
1package ui
2
3import (
4 "context"
5 "fmt"
6
7 "github.com/bnema/dumber/internal/application/port"
8 "github.com/bnema/dumber/internal/application/usecase"
9 "github.com/bnema/dumber/internal/logging"
10 "github.com/bnema/dumber/internal/ui/component"
11 "github.com/bnema/dumber/internal/ui/window"
12)
13
14// initHistorySidebar creates and mounts the history sidebar into the
15// browser window's sidebar container. The sidebar is hidden by default.
16func (bw *browserWindow) initHistorySidebar(ctx context.Context, a *App) {
17 if bw == nil || a == nil || bw.mainWindow == nil || a.deps == nil || a.deps.HistoryUC == nil {
18 return
19 }
20 log := logging.FromContext(ctx)
21
22 cfg := a.buildHistorySidebarConfig(bw)
23
24 sidebar := component.NewHistorySidebar(ctx, cfg)
25 if sidebar == nil {
26 log.Warn().Msg("failed to create history sidebar")
27 return
28 }
29
30 bw.historySidebar = sidebar
31
32 // Mount into the main window's sidebar box.
33 bw.mainWindow.SetSidebarWidget(sidebar.Widget())
34 bw.historySidebar.Hide()
35 bw.mainWindow.SetSidebarVisible(false)
36 bw.sidebarVisible = false
37
38 // Apply sidebar width from config, falling back to the default 320px.
39 // The width is clamped to [280, 380] by SetSidebarWidth internally.
40 bw.applySidebarWidthConfig(a)
41
42 log.Debug().Msg("history sidebar initialized")
43}
44
45// buildHistorySidebarConfig constructs the HistorySidebarConfig for the given
46// browser window. Extracted from initHistorySidebar for testability.
47func (a *App) buildHistorySidebarConfig(bw *browserWindow) component.HistorySidebarConfig {
48 var historyUC port.HistorySidebarHistory
49 if a.deps != nil {
50 historyUC = a.deps.HistoryUC
51 }
52
53 return component.HistorySidebarConfig{
54 HistoryUC: historyUC,
55 OnNavigate: func(navCtx context.Context, url string) error {
56 return a.navigateHistorySidebarSelection(navCtx, bw, url)
57 },
58 OnNavigateKeepOpen: func(navCtx context.Context, url string) error {
59 return a.navigateHistorySidebarSelection(navCtx, bw, url)
60 },
61 OnOpenInNewPane: func(splitCtx context.Context, url string) error {
62 if a.wsCoord == nil || !a.hasBrowserWindow(bw) {
63 return nil
64 }
65 a.activateBrowserWindow(bw)
66 return a.wsCoord.SplitWithURL(splitCtx, usecase.SplitRight, url)
67 },
68 OnClose: func() {
69 a.hideAndRestoreFocusForBrowserWindow(bw)
70 },
71 }
72}
73
74func (a *App) navigateHistorySidebarSelection(ctx context.Context, bw *browserWindow, url string) error {
75 if a == nil || bw == nil || !a.hasBrowserWindow(bw) {
76 return nil
77 }
78 return a.navigateFromBrowserWindow(ctx, bw, url)
79}
80
81// toggleHistorySidebar toggles sidebar visibility.
82func (bw *browserWindow) toggleHistorySidebar() {
83 if bw == nil || bw.historySidebar == nil {
84 return
85 }
86
87 if bw.sidebarVisible {
88 bw.hideHistorySidebar()
89 } else {
90 bw.showHistorySidebar()
91 }
92}
93
94// showHistorySidebar makes the sidebar visible and grabs focus for the search
95// entry.
96func (bw *browserWindow) showHistorySidebar() {
97 if bw == nil || bw.historySidebar == nil || bw.mainWindow == nil {
98 return
99 }
100 bw.historySidebar.Show()
101 bw.mainWindow.SetSidebarVisible(true)
102 bw.sidebarVisible = true
103}
104
105// hideHistorySidebar hides the sidebar. Callers should also restore focus
106// to the active content pane after calling this.
107func (bw *browserWindow) hideHistorySidebar() {
108 if bw == nil || bw.historySidebar == nil || bw.mainWindow == nil {
109 return
110 }
111 bw.historySidebar.Hide()
112 bw.mainWindow.SetSidebarVisible(false)
113 bw.sidebarVisible = false
114}
115
116// historySidebarWidthConfig extracts the config-backed sidebar width and
117// applies it via the MainWindow.SetSidebarWidth path. It is called during
118// initialization and can be reused if config is reloaded at runtime.
119func historySidebarWidthConfig(widthPx int) window.SidebarWidthConfig {
120 cfg := window.SidebarDefaultWidth()
121 if widthPx > 0 {
122 cfg.WidthPx = widthPx
123 }
124 return cfg
125}
126
127// applySidebarWidthConfig applies the config-backed sidebar width to the
128// main window's sidebar.
129func (bw *browserWindow) applySidebarWidthConfig(a *App) {
130 if bw == nil || bw.mainWindow == nil || a == nil {
131 return
132 }
133 bw.mainWindow.SetSidebarWidth(historySidebarWidthConfig(a.runtimeConfigSnapshot().UI.SidebarWidth))
134}
135
136// toggleHistorySidebarAction is the keyboard-action handler for toggling the
137// history sidebar on the last focused browser window.
138func (a *App) toggleHistorySidebarAction(ctx context.Context) error {
139 bw := a.lastFocusedBrowserWindow()
140 if bw == nil {
141 return fmt.Errorf("history sidebar unavailable: no focused browser window")
142 }
143 if bw.historySidebar == nil {
144 return fmt.Errorf("history sidebar unavailable: native sidebar not initialized")
145 }
146 if bw.sidebarVisible {
147 a.hideAndRestoreFocusForBrowserWindow(bw)
148 return nil
149 }
150 bw.toggleHistorySidebar()
151 return nil
152}