detached 37b085f

feat(ui): add accent picker support to find bar

commit
37b085fb77e31b4e6bc0f424fa2826e4e627c24c
author
brice · · 2025-12-29 22:59 UTC
committer
brice · · 2025-12-30 13:48 UTC
parent
b3920c5
signature
unsigned
1 file · +43 -4
M internal/ui/component/find_bar.go +43 -4
@@ -39,16 +39,19 @@ type FindBar struct {
3939
4040 uc *usecase.FindInPageUseCase
4141
42- visible bool
43- mu sync.RWMutex
44- ctx context.Context
45- onClose func()
42+ visible bool
43+ mu sync.RWMutex
44+ ctx context.Context
45+ onClose func()
46+ retainedCallbacks []interface{} // Keep callbacks alive for GC
4647 }
4748
4849 // FindBarConfig holds configuration for creating a FindBar.
4950 type FindBarConfig struct {
5051 OnClose func()
5152 GetFindController func(paneID entity.PaneID) port.FindController
53+ OnFocusIn func(entry *gtk.SearchEntry) // Callback when entry gains focus (for accent picker)
54+ OnFocusOut func() // Callback when entry loses focus
5255 }
5356
5457 // NewFindBar creates a new FindBar component.
@@ -68,6 +71,7 @@ func NewFindBar(ctx context.Context, cfg FindBarConfig) *FindBar {
6871
6972 fb.setupHandlers()
7073 fb.bindUseCase()
74+ fb.setupFocusCallbacks(cfg.OnFocusIn, cfg.OnFocusOut)
7175
7276 log.Debug().Msg("find bar created")
7377 return fb
@@ -405,3 +409,38 @@ func (fb *FindBar) bindUseCase() {
405409 glib.IdleAdd(&cb, 0)
406410 })
407411 }
412+
413+// setupFocusCallbacks wires focus in/out callbacks for accent picker integration.
414+func (fb *FindBar) setupFocusCallbacks(onFocusIn func(*gtk.SearchEntry), onFocusOut func()) {
415+ if onFocusIn == nil && onFocusOut == nil {
416+ return
417+ }
418+
419+ if fb.entry == nil {
420+ return
421+ }
422+
423+ focusController := gtk.NewEventControllerFocus()
424+ if focusController == nil {
425+ return
426+ }
427+
428+ if onFocusIn != nil {
429+ entry := fb.entry // Capture for closure
430+ focusInCb := func(_ gtk.EventControllerFocus) {
431+ onFocusIn(entry)
432+ }
433+ fb.retainedCallbacks = append(fb.retainedCallbacks, focusInCb)
434+ focusController.ConnectEnter(&focusInCb)
435+ }
436+
437+ if onFocusOut != nil {
438+ focusOutCb := func(_ gtk.EventControllerFocus) {
439+ onFocusOut()
440+ }
441+ fb.retainedCallbacks = append(fb.retainedCallbacks, focusOutCb)
442+ focusController.ConnectLeave(&focusOutCb)
443+ }
444+
445+ fb.entry.AddController(&focusController.EventController)
446+}
@@ -39,16 +39,19 @@ type FindBar struct {
39 39
40 uc *usecase.FindInPageUseCase40 uc *usecase.FindInPageUseCase
41 41
42- visible bool42+ visible bool
43- mu sync.RWMutex43+ mu sync.RWMutex
44- ctx context.Context44+ ctx context.Context
45- onClose func()45+ onClose func()
46+ retainedCallbacks []interface{} // Keep callbacks alive for GC
46 }47 }
47 48
48 // FindBarConfig holds configuration for creating a FindBar.49 // FindBarConfig holds configuration for creating a FindBar.
49 type FindBarConfig struct {50 type FindBarConfig struct {
50 OnClose func()51 OnClose func()
51 GetFindController func(paneID entity.PaneID) port.FindController52 GetFindController func(paneID entity.PaneID) port.FindController
53+ OnFocusIn func(entry *gtk.SearchEntry) // Callback when entry gains focus (for accent picker)
54+ OnFocusOut func() // Callback when entry loses focus
52 }55 }
53 56
54 // NewFindBar creates a new FindBar component.57 // NewFindBar creates a new FindBar component.
@@ -68,6 +71,7 @@ func NewFindBar(ctx context.Context, cfg FindBarConfig) *FindBar {
68 71
69 fb.setupHandlers()72 fb.setupHandlers()
70 fb.bindUseCase()73 fb.bindUseCase()
74+ fb.setupFocusCallbacks(cfg.OnFocusIn, cfg.OnFocusOut)
71 75
72 log.Debug().Msg("find bar created")76 log.Debug().Msg("find bar created")
73 return fb77 return fb
@@ -405,3 +409,38 @@ func (fb *FindBar) bindUseCase() {
405 glib.IdleAdd(&cb, 0)409 glib.IdleAdd(&cb, 0)
406 })410 })
407 }411 }
412+
413+// setupFocusCallbacks wires focus in/out callbacks for accent picker integration.
414+func (fb *FindBar) setupFocusCallbacks(onFocusIn func(*gtk.SearchEntry), onFocusOut func()) {
415+ if onFocusIn == nil && onFocusOut == nil {
416+ return
417+ }
418+
419+ if fb.entry == nil {
420+ return
421+ }
422+
423+ focusController := gtk.NewEventControllerFocus()
424+ if focusController == nil {
425+ return
426+ }
427+
428+ if onFocusIn != nil {
429+ entry := fb.entry // Capture for closure
430+ focusInCb := func(_ gtk.EventControllerFocus) {
431+ onFocusIn(entry)
432+ }
433+ fb.retainedCallbacks = append(fb.retainedCallbacks, focusInCb)
434+ focusController.ConnectEnter(&focusInCb)
435+ }
436+
437+ if onFocusOut != nil {
438+ focusOutCb := func(_ gtk.EventControllerFocus) {
439+ onFocusOut()
440+ }
441+ fb.retainedCallbacks = append(fb.retainedCallbacks, focusOutCb)
442+ focusController.ConnectLeave(&focusOutCb)
443+ }
444+
445+ fb.entry.AddController(&focusController.EventController)
446+}

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