detached 57a5850

fix: reset selectedIndex on text change and fix lint errors

Reset stale row selection in onEntryChanged so Enter navigates to
the typed text, not a previously arrow-selected suggestion.

Fix magic number lint (mnd) and unparam lint errors in permission
logging by extracting maxPermissionLogURLLen const and renaming
containsPermissionType to isWebsiteDataAccessPermission.
commit
57a5850c915088774ea6e349bcc051a29a7d163d
author
brice · · 2026-03-27 20:18 UTC
parent
cb47167
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
4 files · +21 -16
M internal/application/usecase/handle_permission.go +10 -8
@@ -58,9 +58,11 @@ func (uc *HandlePermissionUseCase) logger(ctx context.Context) *zerolog.Logger {
5858 return log
5959 }
6060
61-func containsPermissionType(permTypes []entity.PermissionType, target entity.PermissionType) bool {
61+const maxPermissionLogURLLen = 96
62+
63+func isWebsiteDataAccessPermission(permTypes []entity.PermissionType) bool {
6264 for _, permType := range permTypes {
63- if permType == target {
65+ if permType == entity.PermissionTypeWebsiteDataAccess {
6466 return true
6567 }
6668 }
@@ -74,10 +76,10 @@ func permissionLoggerWithMetadata(log *zerolog.Logger, metadata entity.Permissio
7476 }
7577 ctx := log.With()
7678 if requesting := metadata[entity.PermissionMetadataKeyRequestingDomain]; requesting != "" {
77- ctx = ctx.Str("requesting_domain", logging.TruncateURL(requesting, 96))
79+ ctx = ctx.Str("requesting_domain", logging.TruncateURL(requesting, maxPermissionLogURLLen))
7880 }
7981 if current := metadata[entity.PermissionMetadataKeyCurrentDomain]; current != "" {
80- ctx = ctx.Str("current_domain", logging.TruncateURL(current, 96))
82+ ctx = ctx.Str("current_domain", logging.TruncateURL(current, maxPermissionLogURLLen))
8183 }
8284 enriched := ctx.Logger()
8385 return &enriched
@@ -153,7 +155,7 @@ func (uc *HandlePermissionUseCase) HandlePermissionRequest(
153155 decision := uc.checkStoredPermissions(ctx, origin, permTypes)
154156 switch decision {
155157 case entity.PermissionGranted:
156- if containsPermissionType(permTypes, entity.PermissionTypeWebsiteDataAccess) {
158+ if isWebsiteDataAccessPermission(permTypes) {
157159 permissionLoggerWithMetadata(&log, metadata).Info().
158160 Msg("using stored website data access permission: granted")
159161 }
@@ -161,7 +163,7 @@ func (uc *HandlePermissionUseCase) HandlePermissionRequest(
161163 callback.Allow()
162164 return
163165 case entity.PermissionDenied:
164- if containsPermissionType(permTypes, entity.PermissionTypeWebsiteDataAccess) {
166+ if isWebsiteDataAccessPermission(permTypes) {
165167 permissionLoggerWithMetadata(&log, metadata).Info().
166168 Msg("using stored website data access permission: denied")
167169 }
@@ -303,7 +305,7 @@ func (uc *HandlePermissionUseCase) showPermissionDialog(
303305
304306 dialog.ShowPermissionDialog(ctx, origin, permTypes, metadata, func(result port.PermissionDialogResult) {
305307 if result.Allowed {
306- if containsPermissionType(permTypes, entity.PermissionTypeWebsiteDataAccess) {
308+ if isWebsiteDataAccessPermission(permTypes) {
307309 permissionLoggerWithMetadata(log, metadata).Info().
308310 Bool("persistent", result.Persistent).
309311 Msg("website data access permission allowed")
@@ -316,7 +318,7 @@ func (uc *HandlePermissionUseCase) showPermissionDialog(
316318 uc.persistPermission(ctx, origin, permTypes, entity.PermissionGranted)
317319 }
318320 } else {
319- if containsPermissionType(permTypes, entity.PermissionTypeWebsiteDataAccess) {
321+ if isWebsiteDataAccessPermission(permTypes) {
320322 permissionLoggerWithMetadata(log, metadata).Info().
321323 Bool("persistent", result.Persistent).
322324 Msg("website data access permission denied")
@@ -58,9 +58,11 @@ func (uc *HandlePermissionUseCase) logger(ctx context.Context) *zerolog.Logger {
58 return log58 return log
59 }59 }
60 60
61-func containsPermissionType(permTypes []entity.PermissionType, target entity.PermissionType) bool {61+const maxPermissionLogURLLen = 96
62+
63+func isWebsiteDataAccessPermission(permTypes []entity.PermissionType) bool {
62 for _, permType := range permTypes {64 for _, permType := range permTypes {
63- if permType == target {65+ if permType == entity.PermissionTypeWebsiteDataAccess {
64 return true66 return true
65 }67 }
66 }68 }
@@ -74,10 +76,10 @@ func permissionLoggerWithMetadata(log *zerolog.Logger, metadata entity.Permissio
74 }76 }
75 ctx := log.With()77 ctx := log.With()
76 if requesting := metadata[entity.PermissionMetadataKeyRequestingDomain]; requesting != "" {78 if requesting := metadata[entity.PermissionMetadataKeyRequestingDomain]; requesting != "" {
77- ctx = ctx.Str("requesting_domain", logging.TruncateURL(requesting, 96))79+ ctx = ctx.Str("requesting_domain", logging.TruncateURL(requesting, maxPermissionLogURLLen))
78 }80 }
79 if current := metadata[entity.PermissionMetadataKeyCurrentDomain]; current != "" {81 if current := metadata[entity.PermissionMetadataKeyCurrentDomain]; current != "" {
80- ctx = ctx.Str("current_domain", logging.TruncateURL(current, 96))82+ ctx = ctx.Str("current_domain", logging.TruncateURL(current, maxPermissionLogURLLen))
81 }83 }
82 enriched := ctx.Logger()84 enriched := ctx.Logger()
83 return &enriched85 return &enriched
@@ -153,7 +155,7 @@ func (uc *HandlePermissionUseCase) HandlePermissionRequest(
153 decision := uc.checkStoredPermissions(ctx, origin, permTypes)155 decision := uc.checkStoredPermissions(ctx, origin, permTypes)
154 switch decision {156 switch decision {
155 case entity.PermissionGranted:157 case entity.PermissionGranted:
156- if containsPermissionType(permTypes, entity.PermissionTypeWebsiteDataAccess) {158+ if isWebsiteDataAccessPermission(permTypes) {
157 permissionLoggerWithMetadata(&log, metadata).Info().159 permissionLoggerWithMetadata(&log, metadata).Info().
158 Msg("using stored website data access permission: granted")160 Msg("using stored website data access permission: granted")
159 }161 }
@@ -161,7 +163,7 @@ func (uc *HandlePermissionUseCase) HandlePermissionRequest(
161 callback.Allow()163 callback.Allow()
162 return164 return
163 case entity.PermissionDenied:165 case entity.PermissionDenied:
164- if containsPermissionType(permTypes, entity.PermissionTypeWebsiteDataAccess) {166+ if isWebsiteDataAccessPermission(permTypes) {
165 permissionLoggerWithMetadata(&log, metadata).Info().167 permissionLoggerWithMetadata(&log, metadata).Info().
166 Msg("using stored website data access permission: denied")168 Msg("using stored website data access permission: denied")
167 }169 }
@@ -303,7 +305,7 @@ func (uc *HandlePermissionUseCase) showPermissionDialog(
303 305
304 dialog.ShowPermissionDialog(ctx, origin, permTypes, metadata, func(result port.PermissionDialogResult) {306 dialog.ShowPermissionDialog(ctx, origin, permTypes, metadata, func(result port.PermissionDialogResult) {
305 if result.Allowed {307 if result.Allowed {
306- if containsPermissionType(permTypes, entity.PermissionTypeWebsiteDataAccess) {308+ if isWebsiteDataAccessPermission(permTypes) {
307 permissionLoggerWithMetadata(log, metadata).Info().309 permissionLoggerWithMetadata(log, metadata).Info().
308 Bool("persistent", result.Persistent).310 Bool("persistent", result.Persistent).
309 Msg("website data access permission allowed")311 Msg("website data access permission allowed")
@@ -316,7 +318,7 @@ func (uc *HandlePermissionUseCase) showPermissionDialog(
316 uc.persistPermission(ctx, origin, permTypes, entity.PermissionGranted)318 uc.persistPermission(ctx, origin, permTypes, entity.PermissionGranted)
317 }319 }
318 } else {320 } else {
319- if containsPermissionType(permTypes, entity.PermissionTypeWebsiteDataAccess) {321+ if isWebsiteDataAccessPermission(permTypes) {
320 permissionLoggerWithMetadata(log, metadata).Info().322 permissionLoggerWithMetadata(log, metadata).Info().
321 Bool("persistent", result.Persistent).323 Bool("persistent", result.Persistent).
322 Msg("website data access permission denied")324 Msg("website data access permission denied")
M internal/infrastructure/webkit/webview.go +3 -2
@@ -609,6 +609,7 @@ func (wv *WebView) connectFaviconSignal() {
609609
610610 // progressThrottleInterval limits progress callbacks to ~60fps to reduce UI overhead.
611611 const progressThrottleInterval = 16 * time.Millisecond
612+const maxPermissionLogURLLen = 96
612613
613614 func (wv *WebView) connectProgressSignal() {
614615 progressCb := func() {
@@ -1050,8 +1051,8 @@ func (wv *WebView) connectPermissionRequestSignal() {
10501051 if len(permTypes) == 1 && permTypes[0] == "website_data_access" {
10511052 wv.logger.Info().
10521053 Str("origin", origin).
1053- Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], 96)).
1054- Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], 96)).
1054+ Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], maxPermissionLogURLLen)).
1055+ Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], maxPermissionLogURLLen)).
10551056 Msg("website data access permission requested")
10561057 }
10571058
@@ -609,6 +609,7 @@ func (wv *WebView) connectFaviconSignal() {
609 609
610 // progressThrottleInterval limits progress callbacks to ~60fps to reduce UI overhead.610 // progressThrottleInterval limits progress callbacks to ~60fps to reduce UI overhead.
611 const progressThrottleInterval = 16 * time.Millisecond611 const progressThrottleInterval = 16 * time.Millisecond
612+const maxPermissionLogURLLen = 96
612 613
613 func (wv *WebView) connectProgressSignal() {614 func (wv *WebView) connectProgressSignal() {
614 progressCb := func() {615 progressCb := func() {
@@ -1050,8 +1051,8 @@ func (wv *WebView) connectPermissionRequestSignal() {
1050 if len(permTypes) == 1 && permTypes[0] == "website_data_access" {1051 if len(permTypes) == 1 && permTypes[0] == "website_data_access" {
1051 wv.logger.Info().1052 wv.logger.Info().
1052 Str("origin", origin).1053 Str("origin", origin).
1053- Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], 96)).1054+ Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], maxPermissionLogURLLen)).
1054- Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], 96)).1055+ Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], maxPermissionLogURLLen)).
1055 Msg("website data access permission requested")1056 Msg("website data access permission requested")
1056 }1057 }
1057 1058
M internal/ui/component/omnibox.go +2 -2
@@ -863,11 +863,11 @@ func (o *Omnibox) onEntryChanged() {
863863 entryText = trimmed
864864 }
865865
866- // Reset ghost state (the buffer is already correct — GTK handled it).
866+ // Reset ghost and selection state (the buffer is already correct — GTK handled it).
867867 o.mu.Lock()
868868 oldGhost := o.ghostSuffix
869869 o.hasNavigated = false
870-
870+ o.selectedIndex = -1
871871 o.ghostSuffix = ""
872872 o.realInput = entryText
873873 shouldComplete := o.insertCompletion
@@ -863,11 +863,11 @@ func (o *Omnibox) onEntryChanged() {
863 entryText = trimmed863 entryText = trimmed
864 }864 }
865 865
866- // Reset ghost state (the buffer is already correct — GTK handled it).866+ // Reset ghost and selection state (the buffer is already correct — GTK handled it).
867 o.mu.Lock()867 o.mu.Lock()
868 oldGhost := o.ghostSuffix868 oldGhost := o.ghostSuffix
869 o.hasNavigated = false869 o.hasNavigated = false
870-870+ o.selectedIndex = -1
871 o.ghostSuffix = ""871 o.ghostSuffix = ""
872 o.realInput = entryText872 o.realInput = entryText
873 shouldComplete := o.insertCompletion873 shouldComplete := o.insertCompletion
M internal/ui/dialog/permission.go +6 -4
@@ -13,6 +13,8 @@ import (
1313 "github.com/bnema/dumber/internal/ui/component"
1414 )
1515
16+const maxPermissionLogURLLen = 96
17+
1618 type permissionPopup interface {
1719 Show(ctx context.Context, heading, body string, callback func(allowed, persistent bool))
1820 }
@@ -103,8 +105,8 @@ func (d *PermissionDialog) showRequest(req permissionDialogRequest) {
103105 if parsePermFlags(permTypes).dataAccess {
104106 log.Info().
105107 Str("origin", origin).
106- Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], 96)).
107- Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], 96)).
108+ Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], maxPermissionLogURLLen)).
109+ Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], maxPermissionLogURLLen)).
108110 Msg("showing website data access permission dialog")
109111 }
110112
@@ -112,8 +114,8 @@ func (d *PermissionDialog) showRequest(req permissionDialogRequest) {
112114 if parsePermFlags(permTypes).dataAccess {
113115 log.Info().
114116 Str("origin", origin).
115- Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], 96)).
116- Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], 96)).
117+ Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], maxPermissionLogURLLen)).
118+ Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], maxPermissionLogURLLen)).
117119 Bool("allowed", allowed).
118120 Bool("persistent", persistent).
119121 Msg("website data access permission dialog response")
@@ -13,6 +13,8 @@ import (
13 "github.com/bnema/dumber/internal/ui/component"13 "github.com/bnema/dumber/internal/ui/component"
14 )14 )
15 15
16+const maxPermissionLogURLLen = 96
17+
16 type permissionPopup interface {18 type permissionPopup interface {
17 Show(ctx context.Context, heading, body string, callback func(allowed, persistent bool))19 Show(ctx context.Context, heading, body string, callback func(allowed, persistent bool))
18 }20 }
@@ -103,8 +105,8 @@ func (d *PermissionDialog) showRequest(req permissionDialogRequest) {
103 if parsePermFlags(permTypes).dataAccess {105 if parsePermFlags(permTypes).dataAccess {
104 log.Info().106 log.Info().
105 Str("origin", origin).107 Str("origin", origin).
106- Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], 96)).108+ Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], maxPermissionLogURLLen)).
107- Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], 96)).109+ Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], maxPermissionLogURLLen)).
108 Msg("showing website data access permission dialog")110 Msg("showing website data access permission dialog")
109 }111 }
110 112
@@ -112,8 +114,8 @@ func (d *PermissionDialog) showRequest(req permissionDialogRequest) {
112 if parsePermFlags(permTypes).dataAccess {114 if parsePermFlags(permTypes).dataAccess {
113 log.Info().115 log.Info().
114 Str("origin", origin).116 Str("origin", origin).
115- Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], 96)).117+ Str("requesting_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyRequestingDomain], maxPermissionLogURLLen)).
116- Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], 96)).118+ Str("current_domain", logging.TruncateURL(metadata[entity.PermissionMetadataKeyCurrentDomain], maxPermissionLogURLLen)).
117 Bool("allowed", allowed).119 Bool("allowed", allowed).
118 Bool("persistent", persistent).120 Bool("persistent", persistent).
119 Msg("website data access permission dialog response")121 Msg("website data access permission dialog response")

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