pane.go RawHistoryFolder
1package browser
2
3import (
4 "fmt"
5 "time"
6
7 "github.com/bnema/dumber/internal/app/control"
8 "github.com/bnema/dumber/internal/app/messaging"
9 "github.com/bnema/dumber/internal/logging"
10 "github.com/bnema/dumber/pkg/webkit"
11)
12
13// BrowserPane bundles the per-pane WebView and its controllers.
14type BrowserPane struct {
15 webView *webkit.WebView
16 navigationController *control.NavigationController
17 zoomController *control.ZoomController
18 clipboardController *control.ClipboardController
19 messageHandler *messaging.Handler
20 shortcutHandler *ShortcutHandler
21
22 // Multi-pane support
23 id string
24 hasGUI bool
25 guiComponents map[string]bool
26 lastFocusTime time.Time
27}
28
29func (p *BrowserPane) WebView() *webkit.WebView { return p.webView }
30
31func (p *BrowserPane) MessageHandler() *messaging.Handler { return p.messageHandler }
32
33func (p *BrowserPane) NavigationController() *control.NavigationController {
34 return p.navigationController
35}
36
37func (p *BrowserPane) ZoomController() *control.ZoomController { return p.zoomController }
38
39func (p *BrowserPane) ClipboardController() *control.ClipboardController {
40 return p.clipboardController
41}
42
43func (p *BrowserPane) ShortcutHandler() *ShortcutHandler { return p.shortcutHandler }
44
45// ID returns the unique pane identifier
46func (p *BrowserPane) ID() string { return p.id }
47
48// HasGUI returns whether GUI components are injected
49func (p *BrowserPane) HasGUI() bool { return p.hasGUI }
50
51// SetHasGUI marks GUI components as injected
52func (p *BrowserPane) SetHasGUI(has bool) { p.hasGUI = has }
53
54// SetID sets the pane identifier
55func (p *BrowserPane) SetID(id string) { p.id = id }
56
57// UpdateLastFocus updates the last focus time
58func (p *BrowserPane) UpdateLastFocus() { p.lastFocusTime = time.Now() }
59
60// Initialize GUI component tracking
61func (p *BrowserPane) initializeGUITracking() {
62 if p.guiComponents == nil {
63 p.guiComponents = make(map[string]bool)
64 }
65}
66
67// HasGUIComponent checks if a specific GUI component is loaded
68func (p *BrowserPane) HasGUIComponent(component string) bool {
69 if p.guiComponents == nil {
70 return false
71 }
72 return p.guiComponents[component]
73}
74
75// SetGUIComponent marks a GUI component as loaded
76func (p *BrowserPane) SetGUIComponent(component string, loaded bool) {
77 p.initializeGUITracking()
78 p.guiComponents[component] = loaded
79}
80
81// Cleanup releases pane resources
82func (p *BrowserPane) Cleanup() {
83 if p == nil {
84 return
85 }
86
87 if p.shortcutHandler != nil {
88 p.shortcutHandler.Detach()
89 logging.Debug(fmt.Sprintf("[pane-%s] Cleaned up shortcuts", p.id))
90 }
91
92 if p.navigationController != nil {
93 p.navigationController.Detach()
94 }
95
96 if p.zoomController != nil {
97 p.zoomController.DetachWebView()
98 }
99
100 if p.clipboardController != nil {
101 p.clipboardController.Detach()
102 }
103
104 if p.messageHandler != nil {
105 p.messageHandler.SetWebView(nil)
106 }
107
108 // Destroy WebView to unregister from global registry and release resources
109 if p.webView != nil && !p.webView.IsDestroyed() {
110 if err := p.webView.Destroy(); err != nil {
111 logging.Error(fmt.Sprintf("[pane-%s] failed to destroy webview: %v", p.id, err))
112 } else {
113 logging.Debug(fmt.Sprintf("[pane-%s] successfully destroyed webview", p.id))
114 }
115 }
116
117 // Clear tracking
118 p.guiComponents = nil
119 p.hasGUI = false
120}
121
122// CleanupFromWorkspace removes this pane from workspace tracking maps and app.panes slice
123// This should be called before Cleanup() to ensure proper workspace state management
124func (p *BrowserPane) CleanupFromWorkspace(wm interface{}) {
125 if p == nil || p.webView == nil {
126 return
127 }
128
129 // Type assert to avoid circular import - workspace manager will pass itself
130 if workspaceManager, ok := wm.(interface {
131 removeFromMaps(*webkit.WebView)
132 removeFromAppPanes(*BrowserPane)
133 }); ok {
134 workspaceManager.removeFromMaps(p.webView)
135 workspaceManager.removeFromAppPanes(p)
136 logging.Debug(fmt.Sprintf("[pane-%s] Cleaned up from workspace tracking", p.id))
137 }
138}