detached e380785

feat(config): add content filtering whitelist

Adds content_filtering_whitelist config to selectively disable ad blocking
on specific domains. Default includes Twitch (twitch.tv, passport.twitch.tv,
gql.twitch.tv) to allow Arkose Labs bot detection to function correctly.

Whitelist checking happens during navigation before cosmetic filters are applied.
commit
e380785190cedda3da024d126d61d2a3bcc1b5e7
author
bamen · · 2025-10-08 06:45 UTC
parent
90f2a23
signature
unsigned
5 files · +18 -3
M internal/app/browser/webview.go +1 -1
@@ -371,7 +371,7 @@ func (app *BrowserApp) setupContentBlocking() error {
371371
372372 // Apply content filtering if available
373373 if app.filterManager != nil {
374- app.webView.OnNavigate(uri, app.filterManager)
374+ app.webView.OnNavigate(uri, app.filterManager, app.config.ContentFilteringWhitelist)
375375 }
376376
377377 // Note: GUI bundle (controls and toast) is now injected as User Script
@@ -371,7 +371,7 @@ func (app *BrowserApp) setupContentBlocking() error {
371 371
372 // Apply content filtering if available372 // Apply content filtering if available
373 if app.filterManager != nil {373 if app.filterManager != nil {
374- app.webView.OnNavigate(uri, app.filterManager)374+ app.webView.OnNavigate(uri, app.filterManager, app.config.ContentFilteringWhitelist)
375 }375 }
376 376
377 // Note: GUI bundle (controls and toast) is now injected as User Script377 // Note: GUI bundle (controls and toast) is now injected as User Script
M internal/config/config.go +2 -0
@@ -44,6 +44,8 @@ type Config struct {
4444 DefaultZoom float64 `mapstructure:"default_zoom" yaml:"default_zoom"`
4545 // Workspace defines workspace, pane, and tab handling behaviour.
4646 Workspace WorkspaceConfig `mapstructure:"workspace" yaml:"workspace"`
47+ // ContentFilteringWhitelist domains skip ad blocking (e.g. Twitch breaks with bot detection)
48+ ContentFilteringWhitelist []string `mapstructure:"content_filtering_whitelist" yaml:"content_filtering_whitelist"`
4749 }
4850
4951 // RenderingMode selects GPU vs CPU rendering.
@@ -44,6 +44,8 @@ type Config struct {
44 DefaultZoom float64 `mapstructure:"default_zoom" yaml:"default_zoom"`44 DefaultZoom float64 `mapstructure:"default_zoom" yaml:"default_zoom"`
45 // Workspace defines workspace, pane, and tab handling behaviour.45 // Workspace defines workspace, pane, and tab handling behaviour.
46 Workspace WorkspaceConfig `mapstructure:"workspace" yaml:"workspace"`46 Workspace WorkspaceConfig `mapstructure:"workspace" yaml:"workspace"`
47+ // ContentFilteringWhitelist domains skip ad blocking (e.g. Twitch breaks with bot detection)
48+ ContentFilteringWhitelist []string `mapstructure:"content_filtering_whitelist" yaml:"content_filtering_whitelist"`
47 }49 }
48 50
49 // RenderingMode selects GPU vs CPU rendering.51 // RenderingMode selects GPU vs CPU rendering.
M internal/config/defaults.go +5 -0
@@ -205,6 +205,11 @@ func DefaultConfig() *Config {
205205 BorderRadius: defaultBorderRadius,
206206 },
207207 },
208+ ContentFilteringWhitelist: []string{
209+ "twitch.tv", // Arkose Labs bot detection breaks with filtering
210+ "passport.twitch.tv", // Auth subdomain
211+ "gql.twitch.tv", // GraphQL API
212+ },
208213 }
209214 }
210215
@@ -205,6 +205,11 @@ func DefaultConfig() *Config {
205 BorderRadius: defaultBorderRadius,205 BorderRadius: defaultBorderRadius,
206 },206 },
207 },207 },
208+ ContentFilteringWhitelist: []string{
209+ "twitch.tv", // Arkose Labs bot detection breaks with filtering
210+ "passport.twitch.tv", // Auth subdomain
211+ "gql.twitch.tv", // GraphQL API
212+ },
208 }213 }
209 }214 }
210 215
M pkg/webkit/webview.go +1 -1
@@ -279,7 +279,7 @@ func (w *WebView) InitializeContentBlocking(filterManager interface{}) error {
279279 }
280280
281281 // OnNavigate sets up domain-specific cosmetic filtering on navigation (stub)
282-func (w *WebView) OnNavigate(url string, filterManager interface{}) {
282+func (w *WebView) OnNavigate(url string, filterManager interface{}, whitelist []string) {
283283 // No-op in stub
284284 }
285285
@@ -279,7 +279,7 @@ func (w *WebView) InitializeContentBlocking(filterManager interface{}) error {
279 }279 }
280 280
281 // OnNavigate sets up domain-specific cosmetic filtering on navigation (stub)281 // OnNavigate sets up domain-specific cosmetic filtering on navigation (stub)
282-func (w *WebView) OnNavigate(url string, filterManager interface{}) {282+func (w *WebView) OnNavigate(url string, filterManager interface{}, whitelist []string) {
283 // No-op in stub283 // No-op in stub
284 }284 }
285 285
M pkg/webkit/webview_cgo.go +9 -1
@@ -2654,7 +2654,7 @@ func (w *WebView) InitializeContentBlocking(filterManager FilterManager) error {
26542654 }
26552655
26562656 // OnNavigate sets up domain-specific cosmetic filtering on navigation
2657-func (w *WebView) OnNavigate(url string, filterManager FilterManager) {
2657+func (w *WebView) OnNavigate(url string, filterManager FilterManager, whitelist []string) {
26582658 if w == nil || w.destroyed {
26592659 return
26602660 }
@@ -2664,6 +2664,14 @@ func (w *WebView) OnNavigate(url string, filterManager FilterManager) {
26642664 return
26652665 }
26662666
2667+ // Skip cosmetic filtering for whitelisted domains (e.g., Twitch with Arkose Labs bot detection)
2668+ for _, whitelistedDomain := range whitelist {
2669+ if strings.Contains(domain, whitelistedDomain) {
2670+ logging.Info("[webkit] Skipping cosmetic filtering for whitelisted domain: " + domain)
2671+ return
2672+ }
2673+ }
2674+
26672675 // Get domain-specific cosmetic rules
26682676 script := filterManager.GetCosmeticScriptForDomain(domain)
26692677 if script != "" {
@@ -2654,7 +2654,7 @@ func (w *WebView) InitializeContentBlocking(filterManager FilterManager) error {
2654 }2654 }
2655 2655
2656 // OnNavigate sets up domain-specific cosmetic filtering on navigation2656 // OnNavigate sets up domain-specific cosmetic filtering on navigation
2657-func (w *WebView) OnNavigate(url string, filterManager FilterManager) {2657+func (w *WebView) OnNavigate(url string, filterManager FilterManager, whitelist []string) {
2658 if w == nil || w.destroyed {2658 if w == nil || w.destroyed {
2659 return2659 return
2660 }2660 }
@@ -2664,6 +2664,14 @@ func (w *WebView) OnNavigate(url string, filterManager FilterManager) {
2664 return2664 return
2665 }2665 }
2666 2666
2667+ // Skip cosmetic filtering for whitelisted domains (e.g., Twitch with Arkose Labs bot detection)
2668+ for _, whitelistedDomain := range whitelist {
2669+ if strings.Contains(domain, whitelistedDomain) {
2670+ logging.Info("[webkit] Skipping cosmetic filtering for whitelisted domain: " + domain)
2671+ return
2672+ }
2673+ }
2674+
2667 // Get domain-specific cosmetic rules2675 // Get domain-specific cosmetic rules
2668 script := filterManager.GetCosmeticScriptForDomain(domain)2676 script := filterManager.GetCosmeticScriptForDomain(domain)
2669 if script != "" {2677 if script != "" {

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