detached 05fc8f4

refactor(webkit): extract bgColor helper to reduce duplication

commit
05fc8f41e98b8c8c7c8cfa5e1889a4746e9a5552
author
bnema · · 2025-12-28 12:12 UTC
parent
7b0cc18
signature
GPG Unverified2B82207D370127A0 The key is unknown
3 files · +46 -43
A internal/infrastructure/webkit/bgcolor.go +38 -0
@@ -0,0 +1,38 @@
1+package webkit
2+
3+import (
4+ "sync"
5+
6+ "github.com/jwijenbergh/puregotk/v4/gdk"
7+)
8+
9+// bgColor holds RGBA components for WebView background color (eliminates white flash).
10+// It is thread-safe and can be embedded in pool/factory structs.
11+type bgColor struct {
12+ r, g, b, a float32
13+ mu sync.RWMutex
14+}
15+
16+// set stores the background color components.
17+func (c *bgColor) set(r, g, b, a float32) {
18+ c.mu.Lock()
19+ c.r, c.g, c.b, c.a = r, g, b, a
20+ c.mu.Unlock()
21+}
22+
23+// get returns the background color components.
24+func (c *bgColor) get() (r, g, b, a float32) {
25+ c.mu.RLock()
26+ r, g, b, a = c.r, c.g, c.b, c.a
27+ c.mu.RUnlock()
28+ return
29+}
30+
31+// toGdkRGBA returns a *gdk.RGBA if a valid color is configured (alpha > 0), nil otherwise.
32+func (c *bgColor) toGdkRGBA() *gdk.RGBA {
33+ r, g, b, a := c.get()
34+ if a <= 0 {
35+ return nil
36+ }
37+ return &gdk.RGBA{Red: r, Green: g, Blue: b, Alpha: a}
38+}
@@ -0,0 +1,38 @@
1+package webkit
2+
3+import (
4+ "sync"
5+
6+ "github.com/jwijenbergh/puregotk/v4/gdk"
7+)
8+
9+// bgColor holds RGBA components for WebView background color (eliminates white flash).
10+// It is thread-safe and can be embedded in pool/factory structs.
11+type bgColor struct {
12+ r, g, b, a float32
13+ mu sync.RWMutex
14+}
15+
16+// set stores the background color components.
17+func (c *bgColor) set(r, g, b, a float32) {
18+ c.mu.Lock()
19+ c.r, c.g, c.b, c.a = r, g, b, a
20+ c.mu.Unlock()
21+}
22+
23+// get returns the background color components.
24+func (c *bgColor) get() (r, g, b, a float32) {
25+ c.mu.RLock()
26+ r, g, b, a = c.r, c.g, c.b, c.a
27+ c.mu.RUnlock()
28+ return
29+}
30+
31+// toGdkRGBA returns a *gdk.RGBA if a valid color is configured (alpha > 0), nil otherwise.
32+func (c *bgColor) toGdkRGBA() *gdk.RGBA {
33+ r, g, b, a := c.get()
34+ if a <= 0 {
35+ return nil
36+ }
37+ return &gdk.RGBA{Red: r, Green: g, Blue: b, Alpha: a}
38+}
M internal/infrastructure/webkit/factory.go +4 -22
@@ -3,11 +3,9 @@ package webkit
33 import (
44 "context"
55 "fmt"
6- "sync"
76
87 "github.com/bnema/dumber/internal/application/port"
98 "github.com/bnema/dumber/internal/logging"
10- "github.com/jwijenbergh/puregotk/v4/gdk"
119 )
1210
1311 // WebViewFactory creates WebView instances for the application.
@@ -22,8 +20,7 @@ type WebViewFactory struct {
2220 filterApplier FilterApplier // Optional content filter applier
2321
2422 // Background color for WebViews (eliminates white flash)
25- bgR, bgG, bgB, bgA float32
26- bgMu sync.RWMutex
23+ bg bgColor
2724 }
2825
2926 // NewWebViewFactory creates a new WebViewFactory.
@@ -57,9 +54,7 @@ func (f *WebViewFactory) SetFilterApplier(applier FilterApplier) {
5754 // SetBackgroundColor sets the background color for newly created WebViews.
5855 // This color is shown before content is painted, eliminating white flash.
5956 func (f *WebViewFactory) SetBackgroundColor(r, g, b, a float32) {
60- f.bgMu.Lock()
61- f.bgR, f.bgG, f.bgB, f.bgA = r, g, b, a
62- f.bgMu.Unlock()
57+ f.bg.set(r, g, b, a)
6358 // Also propagate to the pool if present
6459 if f.pool != nil {
6560 f.pool.SetBackgroundColor(r, g, b, a)
@@ -107,10 +102,7 @@ func (f *WebViewFactory) CreateRelated(ctx context.Context, parentID port.WebVie
107102 }
108103
109104 // Set background color to match theme (eliminates white flash)
110- f.bgMu.RLock()
111- r, g, b, a := f.bgR, f.bgG, f.bgB, f.bgA
112- f.bgMu.RUnlock()
113- if a > 0 {
105+ if r, g, b, a := f.bg.get(); a > 0 {
114106 wv.SetBackgroundColor(r, g, b, a)
115107 }
116108
@@ -139,17 +131,7 @@ func (f *WebViewFactory) CreateRelated(ctx context.Context, parentID port.WebVie
139131 func (f *WebViewFactory) createDirect(ctx context.Context) (*WebView, error) {
140132 log := logging.FromContext(ctx)
141133
142- // Build background color for immediate application during WebView creation
143- f.bgMu.RLock()
144- r, g, b, a := f.bgR, f.bgG, f.bgB, f.bgA
145- f.bgMu.RUnlock()
146-
147- var bgColor *gdk.RGBA
148- if a > 0 { // Only set if a valid color was configured
149- bgColor = &gdk.RGBA{Red: r, Green: g, Blue: b, Alpha: a}
150- }
151-
152- wv, err := NewWebView(ctx, f.wkCtx, f.settings, bgColor)
134+ wv, err := NewWebView(ctx, f.wkCtx, f.settings, f.bg.toGdkRGBA())
153135 if err != nil {
154136 return nil, err
155137 }
@@ -3,11 +3,9 @@ package webkit
3 import (3 import (
4 "context"4 "context"
5 "fmt"5 "fmt"
6- "sync"
7 6
8 "github.com/bnema/dumber/internal/application/port"7 "github.com/bnema/dumber/internal/application/port"
9 "github.com/bnema/dumber/internal/logging"8 "github.com/bnema/dumber/internal/logging"
10- "github.com/jwijenbergh/puregotk/v4/gdk"
11 )9 )
12 10
13 // WebViewFactory creates WebView instances for the application.11 // WebViewFactory creates WebView instances for the application.
@@ -22,8 +20,7 @@ type WebViewFactory struct {
22 filterApplier FilterApplier // Optional content filter applier20 filterApplier FilterApplier // Optional content filter applier
23 21
24 // Background color for WebViews (eliminates white flash)22 // Background color for WebViews (eliminates white flash)
25- bgR, bgG, bgB, bgA float3223+ bg bgColor
26- bgMu sync.RWMutex
27 }24 }
28 25
29 // NewWebViewFactory creates a new WebViewFactory.26 // NewWebViewFactory creates a new WebViewFactory.
@@ -57,9 +54,7 @@ func (f *WebViewFactory) SetFilterApplier(applier FilterApplier) {
57 // SetBackgroundColor sets the background color for newly created WebViews.54 // SetBackgroundColor sets the background color for newly created WebViews.
58 // This color is shown before content is painted, eliminating white flash.55 // This color is shown before content is painted, eliminating white flash.
59 func (f *WebViewFactory) SetBackgroundColor(r, g, b, a float32) {56 func (f *WebViewFactory) SetBackgroundColor(r, g, b, a float32) {
60- f.bgMu.Lock()57+ f.bg.set(r, g, b, a)
61- f.bgR, f.bgG, f.bgB, f.bgA = r, g, b, a
62- f.bgMu.Unlock()
63 // Also propagate to the pool if present58 // Also propagate to the pool if present
64 if f.pool != nil {59 if f.pool != nil {
65 f.pool.SetBackgroundColor(r, g, b, a)60 f.pool.SetBackgroundColor(r, g, b, a)
@@ -107,10 +102,7 @@ func (f *WebViewFactory) CreateRelated(ctx context.Context, parentID port.WebVie
107 }102 }
108 103
109 // Set background color to match theme (eliminates white flash)104 // Set background color to match theme (eliminates white flash)
110- f.bgMu.RLock()105+ if r, g, b, a := f.bg.get(); a > 0 {
111- r, g, b, a := f.bgR, f.bgG, f.bgB, f.bgA
112- f.bgMu.RUnlock()
113- if a > 0 {
114 wv.SetBackgroundColor(r, g, b, a)106 wv.SetBackgroundColor(r, g, b, a)
115 }107 }
116 108
@@ -139,17 +131,7 @@ func (f *WebViewFactory) CreateRelated(ctx context.Context, parentID port.WebVie
139 func (f *WebViewFactory) createDirect(ctx context.Context) (*WebView, error) {131 func (f *WebViewFactory) createDirect(ctx context.Context) (*WebView, error) {
140 log := logging.FromContext(ctx)132 log := logging.FromContext(ctx)
141 133
142- // Build background color for immediate application during WebView creation134+ wv, err := NewWebView(ctx, f.wkCtx, f.settings, f.bg.toGdkRGBA())
143- f.bgMu.RLock()
144- r, g, b, a := f.bgR, f.bgG, f.bgB, f.bgA
145- f.bgMu.RUnlock()
146-
147- var bgColor *gdk.RGBA
148- if a > 0 { // Only set if a valid color was configured
149- bgColor = &gdk.RGBA{Red: r, Green: g, Blue: b, Alpha: a}
150- }
151-
152- wv, err := NewWebView(ctx, f.wkCtx, f.settings, bgColor)
153 if err != nil {135 if err != nil {
154 return nil, err136 return nil, err
155 }137 }
M internal/infrastructure/webkit/pool.go +4 -21
@@ -9,7 +9,6 @@ import (
99
1010 "github.com/bnema/dumber/internal/logging"
1111 "github.com/bnema/puregotk-webkit/webkit"
12- "github.com/jwijenbergh/puregotk/v4/gdk"
1312 "github.com/jwijenbergh/puregotk/v4/glib"
1413 )
1514
@@ -56,8 +55,7 @@ type WebViewPool struct {
5655 filterApplier FilterApplier // Optional content filter applier
5756
5857 // Background color for WebViews (eliminates white flash)
59- bgR, bgG, bgB, bgA float32
60- bgMu sync.RWMutex
58+ bg bgColor
6159
6260 closed atomic.Bool
6361 wg sync.WaitGroup
@@ -109,9 +107,7 @@ func (p *WebViewPool) SetFilterApplier(applier FilterApplier) {
109107 // SetBackgroundColor sets the background color for newly created WebViews.
110108 // This color is shown before content is painted, eliminating white flash.
111109 func (p *WebViewPool) SetBackgroundColor(r, g, b, a float32) {
112- p.bgMu.Lock()
113- p.bgR, p.bgG, p.bgB, p.bgA = r, g, b, a
114- p.bgMu.Unlock()
110+ p.bg.set(r, g, b, a)
115111 }
116112
117113 // Acquire gets a WebView from the pool or creates a new one.
@@ -126,10 +122,7 @@ func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) {
126122 select {
127123 case wv := <-p.pool:
128124 if wv != nil && !wv.IsDestroyed() {
129- p.bgMu.RLock()
130- r, g, b, a := p.bgR, p.bgG, p.bgB, p.bgA
131- p.bgMu.RUnlock()
132- if a > 0 {
125+ if r, g, b, a := p.bg.get(); a > 0 {
133126 wv.SetBackgroundColor(r, g, b, a)
134127 }
135128 wv.inner.AddCssClass("webview-themed")
@@ -158,17 +151,7 @@ func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) {
158151 func (p *WebViewPool) createWebView(ctx context.Context) (*WebView, error) {
159152 log := logging.FromContext(ctx)
160153
161- // Build background color for immediate application during WebView creation
162- p.bgMu.RLock()
163- r, g, b, a := p.bgR, p.bgG, p.bgB, p.bgA
164- p.bgMu.RUnlock()
165-
166- var bgColor *gdk.RGBA
167- if a > 0 { // Only set if a valid color was configured
168- bgColor = &gdk.RGBA{Red: r, Green: g, Blue: b, Alpha: a}
169- }
170-
171- wv, err := NewWebView(ctx, p.wkCtx, p.settings, bgColor)
154+ wv, err := NewWebView(ctx, p.wkCtx, p.settings, p.bg.toGdkRGBA())
172155 if err != nil {
173156 return nil, err
174157 }
@@ -9,7 +9,6 @@ import (
9 9
10 "github.com/bnema/dumber/internal/logging"10 "github.com/bnema/dumber/internal/logging"
11 "github.com/bnema/puregotk-webkit/webkit"11 "github.com/bnema/puregotk-webkit/webkit"
12- "github.com/jwijenbergh/puregotk/v4/gdk"
13 "github.com/jwijenbergh/puregotk/v4/glib"12 "github.com/jwijenbergh/puregotk/v4/glib"
14 )13 )
15 14
@@ -56,8 +55,7 @@ type WebViewPool struct {
56 filterApplier FilterApplier // Optional content filter applier55 filterApplier FilterApplier // Optional content filter applier
57 56
58 // Background color for WebViews (eliminates white flash)57 // Background color for WebViews (eliminates white flash)
59- bgR, bgG, bgB, bgA float3258+ bg bgColor
60- bgMu sync.RWMutex
61 59
62 closed atomic.Bool60 closed atomic.Bool
63 wg sync.WaitGroup61 wg sync.WaitGroup
@@ -109,9 +107,7 @@ func (p *WebViewPool) SetFilterApplier(applier FilterApplier) {
109 // SetBackgroundColor sets the background color for newly created WebViews.107 // SetBackgroundColor sets the background color for newly created WebViews.
110 // This color is shown before content is painted, eliminating white flash.108 // This color is shown before content is painted, eliminating white flash.
111 func (p *WebViewPool) SetBackgroundColor(r, g, b, a float32) {109 func (p *WebViewPool) SetBackgroundColor(r, g, b, a float32) {
112- p.bgMu.Lock()110+ p.bg.set(r, g, b, a)
113- p.bgR, p.bgG, p.bgB, p.bgA = r, g, b, a
114- p.bgMu.Unlock()
115 }111 }
116 112
117 // Acquire gets a WebView from the pool or creates a new one.113 // Acquire gets a WebView from the pool or creates a new one.
@@ -126,10 +122,7 @@ func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) {
126 select {122 select {
127 case wv := <-p.pool:123 case wv := <-p.pool:
128 if wv != nil && !wv.IsDestroyed() {124 if wv != nil && !wv.IsDestroyed() {
129- p.bgMu.RLock()125+ if r, g, b, a := p.bg.get(); a > 0 {
130- r, g, b, a := p.bgR, p.bgG, p.bgB, p.bgA
131- p.bgMu.RUnlock()
132- if a > 0 {
133 wv.SetBackgroundColor(r, g, b, a)126 wv.SetBackgroundColor(r, g, b, a)
134 }127 }
135 wv.inner.AddCssClass("webview-themed")128 wv.inner.AddCssClass("webview-themed")
@@ -158,17 +151,7 @@ func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) {
158 func (p *WebViewPool) createWebView(ctx context.Context) (*WebView, error) {151 func (p *WebViewPool) createWebView(ctx context.Context) (*WebView, error) {
159 log := logging.FromContext(ctx)152 log := logging.FromContext(ctx)
160 153
161- // Build background color for immediate application during WebView creation154+ wv, err := NewWebView(ctx, p.wkCtx, p.settings, p.bg.toGdkRGBA())
162- p.bgMu.RLock()
163- r, g, b, a := p.bgR, p.bgG, p.bgB, p.bgA
164- p.bgMu.RUnlock()
165-
166- var bgColor *gdk.RGBA
167- if a > 0 { // Only set if a valid color was configured
168- bgColor = &gdk.RGBA{Red: r, Green: g, Blue: b, Alpha: a}
169- }
170-
171- wv, err := NewWebView(ctx, p.wkCtx, p.settings, bgColor)
172 if err != nil {155 if err != nil {
173 return nil, err156 return nil, err
174 }157 }

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close