detached 2710fd5

refactor: add browser launch ports and runtime dir

commit
2710fd58e62480b0ae8299bd0123e414cff6780f
author
brice · · 2026-04-14 12:11 UTC
parent
592167c
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +8 -49
M internal/application/port/browser_launch.go +3 -0
@@ -12,6 +12,9 @@ type BrowserWindowOpener interface {
1212
1313 // BrowserLaunchRelay delivers fresh-window launch requests.
1414 type BrowserLaunchRelay interface {
15+ // DeliverOpenFreshWindow attempts to deliver a request to open a fresh window.
16+ // The bool reports whether the relay accepted the request; false means the
17+ // caller should treat it as undelivered and try another path.
1518 DeliverOpenFreshWindow(ctx context.Context, url string) (bool, error)
1619 Listen(ctx context.Context, opener BrowserWindowOpener) (io.Closer, error)
1720 }
@@ -12,6 +12,9 @@ type BrowserWindowOpener interface {
12 12
13 // BrowserLaunchRelay delivers fresh-window launch requests.13 // BrowserLaunchRelay delivers fresh-window launch requests.
14 type BrowserLaunchRelay interface {14 type BrowserLaunchRelay interface {
15+ // DeliverOpenFreshWindow attempts to deliver a request to open a fresh window.
16+ // The bool reports whether the relay accepted the request; false means the
17+ // caller should treat it as undelivered and try another path.
15 DeliverOpenFreshWindow(ctx context.Context, url string) (bool, error)18 DeliverOpenFreshWindow(ctx context.Context, url string) (bool, error)
16 Listen(ctx context.Context, opener BrowserWindowOpener) (io.Closer, error)19 Listen(ctx context.Context, opener BrowserWindowOpener) (io.Closer, error)
17 }20 }
M internal/infrastructure/xdg/adapter_test.go +5 -49
@@ -13,17 +13,7 @@ func TestAdapter_DownloadDir(t *testing.T) {
1313 adapter := New()
1414
1515 t.Run("returns XDG_DOWNLOAD_DIR when set", func(t *testing.T) {
16- // Save and restore original env.
17- original := os.Getenv("XDG_DOWNLOAD_DIR")
18- defer func() {
19- if original == "" {
20- os.Unsetenv("XDG_DOWNLOAD_DIR")
21- } else {
22- os.Setenv("XDG_DOWNLOAD_DIR", original)
23- }
24- }()
25-
26- os.Setenv("XDG_DOWNLOAD_DIR", "/custom/downloads")
16+ t.Setenv("XDG_DOWNLOAD_DIR", "/custom/downloads")
2717
2818 dir, err := adapter.DownloadDir()
2919
@@ -32,17 +22,7 @@ func TestAdapter_DownloadDir(t *testing.T) {
3222 })
3323
3424 t.Run("falls back to ~/Downloads when XDG_DOWNLOAD_DIR not set", func(t *testing.T) {
35- // Save and restore original env.
36- original := os.Getenv("XDG_DOWNLOAD_DIR")
37- defer func() {
38- if original == "" {
39- os.Unsetenv("XDG_DOWNLOAD_DIR")
40- } else {
41- os.Setenv("XDG_DOWNLOAD_DIR", original)
42- }
43- }()
44-
45- os.Unsetenv("XDG_DOWNLOAD_DIR")
25+ t.Setenv("XDG_DOWNLOAD_DIR", "")
4626
4727 dir, err := adapter.DownloadDir()
4828
@@ -60,16 +40,7 @@ func TestAdapter_RuntimeDir(t *testing.T) {
6040 adapter := New()
6141
6242 t.Run("returns XDG_RUNTIME_DIR when set", func(t *testing.T) {
63- original := os.Getenv("XDG_RUNTIME_DIR")
64- defer func() {
65- if original == "" {
66- os.Unsetenv("XDG_RUNTIME_DIR")
67- } else {
68- os.Setenv("XDG_RUNTIME_DIR", original)
69- }
70- }()
71-
72- os.Setenv("XDG_RUNTIME_DIR", "/custom/runtime")
43+ t.Setenv("XDG_RUNTIME_DIR", "/custom/runtime")
7344
7445 dir, err := adapter.RuntimeDir()
7546
@@ -78,23 +49,8 @@ func TestAdapter_RuntimeDir(t *testing.T) {
7849 })
7950
8051 t.Run("falls back to state runtime dir when XDG_RUNTIME_DIR not set", func(t *testing.T) {
81- originalRuntime := os.Getenv("XDG_RUNTIME_DIR")
82- originalState := os.Getenv("XDG_STATE_HOME")
83- defer func() {
84- if originalRuntime == "" {
85- os.Unsetenv("XDG_RUNTIME_DIR")
86- } else {
87- os.Setenv("XDG_RUNTIME_DIR", originalRuntime)
88- }
89- if originalState == "" {
90- os.Unsetenv("XDG_STATE_HOME")
91- } else {
92- os.Setenv("XDG_STATE_HOME", originalState)
93- }
94- }()
95-
96- os.Unsetenv("XDG_RUNTIME_DIR")
97- os.Setenv("XDG_STATE_HOME", "/tmp/dumber-state")
52+ t.Setenv("XDG_RUNTIME_DIR", "")
53+ t.Setenv("XDG_STATE_HOME", "/tmp/dumber-state")
9854
9955 dir, err := adapter.RuntimeDir()
10056
@@ -13,17 +13,7 @@ func TestAdapter_DownloadDir(t *testing.T) {
13 adapter := New()13 adapter := New()
14 14
15 t.Run("returns XDG_DOWNLOAD_DIR when set", func(t *testing.T) {15 t.Run("returns XDG_DOWNLOAD_DIR when set", func(t *testing.T) {
16- // Save and restore original env.16+ t.Setenv("XDG_DOWNLOAD_DIR", "/custom/downloads")
17- original := os.Getenv("XDG_DOWNLOAD_DIR")
18- defer func() {
19- if original == "" {
20- os.Unsetenv("XDG_DOWNLOAD_DIR")
21- } else {
22- os.Setenv("XDG_DOWNLOAD_DIR", original)
23- }
24- }()
25-
26- os.Setenv("XDG_DOWNLOAD_DIR", "/custom/downloads")
27 17
28 dir, err := adapter.DownloadDir()18 dir, err := adapter.DownloadDir()
29 19
@@ -32,17 +22,7 @@ func TestAdapter_DownloadDir(t *testing.T) {
32 })22 })
33 23
34 t.Run("falls back to ~/Downloads when XDG_DOWNLOAD_DIR not set", func(t *testing.T) {24 t.Run("falls back to ~/Downloads when XDG_DOWNLOAD_DIR not set", func(t *testing.T) {
35- // Save and restore original env.25+ t.Setenv("XDG_DOWNLOAD_DIR", "")
36- original := os.Getenv("XDG_DOWNLOAD_DIR")
37- defer func() {
38- if original == "" {
39- os.Unsetenv("XDG_DOWNLOAD_DIR")
40- } else {
41- os.Setenv("XDG_DOWNLOAD_DIR", original)
42- }
43- }()
44-
45- os.Unsetenv("XDG_DOWNLOAD_DIR")
46 26
47 dir, err := adapter.DownloadDir()27 dir, err := adapter.DownloadDir()
48 28
@@ -60,16 +40,7 @@ func TestAdapter_RuntimeDir(t *testing.T) {
60 adapter := New()40 adapter := New()
61 41
62 t.Run("returns XDG_RUNTIME_DIR when set", func(t *testing.T) {42 t.Run("returns XDG_RUNTIME_DIR when set", func(t *testing.T) {
63- original := os.Getenv("XDG_RUNTIME_DIR")43+ t.Setenv("XDG_RUNTIME_DIR", "/custom/runtime")
64- defer func() {
65- if original == "" {
66- os.Unsetenv("XDG_RUNTIME_DIR")
67- } else {
68- os.Setenv("XDG_RUNTIME_DIR", original)
69- }
70- }()
71-
72- os.Setenv("XDG_RUNTIME_DIR", "/custom/runtime")
73 44
74 dir, err := adapter.RuntimeDir()45 dir, err := adapter.RuntimeDir()
75 46
@@ -78,23 +49,8 @@ func TestAdapter_RuntimeDir(t *testing.T) {
78 })49 })
79 50
80 t.Run("falls back to state runtime dir when XDG_RUNTIME_DIR not set", func(t *testing.T) {51 t.Run("falls back to state runtime dir when XDG_RUNTIME_DIR not set", func(t *testing.T) {
81- originalRuntime := os.Getenv("XDG_RUNTIME_DIR")52+ t.Setenv("XDG_RUNTIME_DIR", "")
82- originalState := os.Getenv("XDG_STATE_HOME")53+ t.Setenv("XDG_STATE_HOME", "/tmp/dumber-state")
83- defer func() {
84- if originalRuntime == "" {
85- os.Unsetenv("XDG_RUNTIME_DIR")
86- } else {
87- os.Setenv("XDG_RUNTIME_DIR", originalRuntime)
88- }
89- if originalState == "" {
90- os.Unsetenv("XDG_STATE_HOME")
91- } else {
92- os.Setenv("XDG_STATE_HOME", originalState)
93- }
94- }()
95-
96- os.Unsetenv("XDG_RUNTIME_DIR")
97- os.Setenv("XDG_STATE_HOME", "/tmp/dumber-state")
98 54
99 dir, err := adapter.RuntimeDir()55 dir, err := adapter.RuntimeDir()
100 56

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