bulk.go RawHistoryFolder
1package content
2
3import (
4 "context"
5 "maps"
6
7 "github.com/bnema/dumber/internal/application/port"
8 "github.com/bnema/dumber/internal/domain/entity"
9 "github.com/bnema/dumber/internal/logging"
10)
11
12// ApplyFiltersToAll applies content filters to all active webviews.
13// Called when filters become available after webviews were already created.
14func (c *Coordinator) ApplyFiltersToAll(ctx context.Context) {
15 log := logging.FromContext(ctx)
16 if c.filterApplier == nil {
17 log.Debug().Msg("ApplyFiltersToAll: no filter applier configured")
18 return
19 }
20
21 c.webViewsMu.RLock()
22 snapshot := make([]port.WebView, 0, len(c.webViews))
23 for _, wv := range c.webViews {
24 snapshot = append(snapshot, wv)
25 }
26 c.webViewsMu.RUnlock()
27
28 c.filterApplier.ApplyToAll(ctx, snapshot)
29 log.Debug().Int("count", len(snapshot)).Msg("applied filters to all webviews")
30}
31
32// ApplySettingsToAll reapplies engine settings to all active WebViews.
33func (c *Coordinator) ApplySettingsToAll(ctx context.Context) {
34 log := logging.FromContext(ctx)
35 if c.settingsApplier == nil {
36 log.Debug().Msg("ApplySettingsToAll: no settings applier configured")
37 return
38 }
39
40 c.webViewsMu.RLock()
41 snapshot := make([]port.WebView, 0, len(c.webViews))
42 for _, wv := range c.webViews {
43 snapshot = append(snapshot, wv)
44 }
45 c.webViewsMu.RUnlock()
46
47 c.settingsApplier.ApplyToAll(ctx, snapshot)
48 log.Debug().Int("count", len(snapshot)).Msg("applied settings to all webviews")
49}
50
51// RefreshInjectedScriptsToAll clears and re-injects user scripts into all active WebViews.
52//
53// WebKit user scripts are snapshotted when added to a WebKitUserContentManager, so when
54// appearance settings change at runtime (dark mode, palettes, UI scale), we must refresh
55// the scripts so future navigations pick up the latest values.
56// Script refresh is deferred for any WebView that is currently loading to avoid
57// removing scripts mid-navigation.
58func (c *Coordinator) RefreshInjectedScriptsToAll(ctx context.Context) {
59 log := logging.FromContext(ctx)
60 if c.injector == nil {
61 return
62 }
63
64 // Snapshot webViews under lock to avoid data race with concurrent popup create/close.
65 c.webViewsMu.RLock()
66 snapshot := make(map[entity.PaneID]port.WebView, len(c.webViews))
67 maps.Copy(snapshot, c.webViews)
68 c.webViewsMu.RUnlock()
69
70 for paneID, wv := range snapshot {
71 if wv == nil || wv.IsDestroyed() {
72 continue
73 }
74 if c.shouldDeferAppearance(wv) {
75 c.queueScriptRefresh(paneID)
76 log.Debug().Str("pane_id", string(paneID)).Msg("deferred script refresh until load finished")
77 continue
78 }
79
80 c.refreshInjectedScripts(ctx, c.injector, paneID, wv)
81 }
82}