detached 1b3ed0a

Merge pull request #237 from bnema/fix/browse-default-startup-url

Fix browse startup default URL
commit
1b3ed0a9c83157fa6b46a97f9351df9ff4cbe7bc
author
bnema · · 2026-04-27 05:07 UTC
committer
GitHub · · 2026-04-27 05:07 UTC
merge of
be6fa56 + bf4a0b5 · diff against the first parent
signature
GPG UnverifiedB5690EEEBB952194 The key is unknown
5 files · +66 -7
M cmd/dumber/main.go +6 -4
@@ -17,6 +17,7 @@ import (
1717 "github.com/bnema/dumber/internal/domain/build"
1818 "github.com/bnema/dumber/internal/domain/entity"
1919 "github.com/bnema/dumber/internal/domain/repository"
20+ domainurl "github.com/bnema/dumber/internal/domain/url"
2021 "github.com/bnema/dumber/internal/infrastructure/cache"
2122 infracef "github.com/bnema/dumber/internal/infrastructure/cef"
2223 "github.com/bnema/dumber/internal/infrastructure/clipboard"
@@ -92,7 +93,7 @@ func launchModeFromArgs(args []string) (launchMode, string) {
9293 }
9394
9495 func tryForwardBrowseURLToRunningInstance(ctx context.Context, relay port.BrowserLaunchRelay, browseURL string) (bool, error) {
95- if relay == nil || browseURL == "" {
96+ if relay == nil {
9697 return false, nil
9798 }
9899
@@ -148,18 +149,19 @@ func main() {
148149 if mode == launchModeBrowse {
149150 cfg := initConfig()
150151 configureBrowserLaunchRelay(cfg)
151- if forwarded, err := tryForwardBrowseURLToRunningInstance(context.Background(), browserLaunchRelay, browseURL); err != nil {
152+ startupURL := domainurl.ResolveBrowserStartupURL(browseURL)
153+ if forwarded, err := tryForwardBrowseURLToRunningInstance(context.Background(), browserLaunchRelay, startupURL); err != nil {
152154 fmt.Fprintf(
153155 os.Stderr,
154156 "warning: failed to forward browse URL %q to a running instance, falling back to a new process: %v\n",
155- browseURL,
157+ startupURL,
156158 err,
157159 )
158160 } else if forwarded {
159161 os.Exit(0)
160162 }
161163
162- initialURL = browseURL
164+ initialURL = startupURL
163165 restoreSessionID = os.Getenv("DUMBER_RESTORE_SESSION")
164166 os.Args = os.Args[:1]
165167 os.Exit(runGUI(cfg))
@@ -17,6 +17,7 @@ import (
17 "github.com/bnema/dumber/internal/domain/build"17 "github.com/bnema/dumber/internal/domain/build"
18 "github.com/bnema/dumber/internal/domain/entity"18 "github.com/bnema/dumber/internal/domain/entity"
19 "github.com/bnema/dumber/internal/domain/repository"19 "github.com/bnema/dumber/internal/domain/repository"
20+ domainurl "github.com/bnema/dumber/internal/domain/url"
20 "github.com/bnema/dumber/internal/infrastructure/cache"21 "github.com/bnema/dumber/internal/infrastructure/cache"
21 infracef "github.com/bnema/dumber/internal/infrastructure/cef"22 infracef "github.com/bnema/dumber/internal/infrastructure/cef"
22 "github.com/bnema/dumber/internal/infrastructure/clipboard"23 "github.com/bnema/dumber/internal/infrastructure/clipboard"
@@ -92,7 +93,7 @@ func launchModeFromArgs(args []string) (launchMode, string) {
92 }93 }
93 94
94 func tryForwardBrowseURLToRunningInstance(ctx context.Context, relay port.BrowserLaunchRelay, browseURL string) (bool, error) {95 func tryForwardBrowseURLToRunningInstance(ctx context.Context, relay port.BrowserLaunchRelay, browseURL string) (bool, error) {
95- if relay == nil || browseURL == "" {96+ if relay == nil {
96 return false, nil97 return false, nil
97 }98 }
98 99
@@ -148,18 +149,19 @@ func main() {
148 if mode == launchModeBrowse {149 if mode == launchModeBrowse {
149 cfg := initConfig()150 cfg := initConfig()
150 configureBrowserLaunchRelay(cfg)151 configureBrowserLaunchRelay(cfg)
151- if forwarded, err := tryForwardBrowseURLToRunningInstance(context.Background(), browserLaunchRelay, browseURL); err != nil {152+ startupURL := domainurl.ResolveBrowserStartupURL(browseURL)
153+ if forwarded, err := tryForwardBrowseURLToRunningInstance(context.Background(), browserLaunchRelay, startupURL); err != nil {
152 fmt.Fprintf(154 fmt.Fprintf(
153 os.Stderr,155 os.Stderr,
154 "warning: failed to forward browse URL %q to a running instance, falling back to a new process: %v\n",156 "warning: failed to forward browse URL %q to a running instance, falling back to a new process: %v\n",
155- browseURL,157+ startupURL,
156 err,158 err,
157 )159 )
158 } else if forwarded {160 } else if forwarded {
159 os.Exit(0)161 os.Exit(0)
160 }162 }
161 163
162- initialURL = browseURL164+ initialURL = startupURL
163 restoreSessionID = os.Getenv("DUMBER_RESTORE_SESSION")165 restoreSessionID = os.Getenv("DUMBER_RESTORE_SESSION")
164 os.Args = os.Args[:1]166 os.Args = os.Args[:1]
165 os.Exit(runGUI(cfg))167 os.Exit(runGUI(cfg))
M cmd/dumber/main_test.go +14 -0
@@ -196,6 +196,20 @@ func TestPreInitializeAdwaitaForCEF_SkipsNonCEF(t *testing.T) {
196196 }
197197 }
198198
199+func TestTryForwardBrowseURLToRunningInstance_ForwardsDefaultStartupURL(t *testing.T) {
200+ relay := mocks.NewMockBrowserLaunchRelay(t)
201+ relay.EXPECT().DeliverOpenFreshWindow(context.Background(), "dumb://history").Return(true, nil)
202+
203+ forwarded, err := tryForwardBrowseURLToRunningInstance(context.Background(), relay, "dumb://history")
204+
205+ if err != nil {
206+ t.Fatalf("expected no error, got %v", err)
207+ }
208+ if !forwarded {
209+ t.Fatal("expected default startup URL to be forwarded")
210+ }
211+}
212+
199213 func TestTryForwardBrowseURLToRunningInstance_ReturnsTrueOnRelayHit(t *testing.T) {
200214 relay := mocks.NewMockBrowserLaunchRelay(t)
201215 relay.EXPECT().DeliverOpenFreshWindow(context.Background(), "https://example.com").Return(true, nil)
@@ -196,6 +196,20 @@ func TestPreInitializeAdwaitaForCEF_SkipsNonCEF(t *testing.T) {
196 }196 }
197 }197 }
198 198
199+func TestTryForwardBrowseURLToRunningInstance_ForwardsDefaultStartupURL(t *testing.T) {
200+ relay := mocks.NewMockBrowserLaunchRelay(t)
201+ relay.EXPECT().DeliverOpenFreshWindow(context.Background(), "dumb://history").Return(true, nil)
202+
203+ forwarded, err := tryForwardBrowseURLToRunningInstance(context.Background(), relay, "dumb://history")
204+
205+ if err != nil {
206+ t.Fatalf("expected no error, got %v", err)
207+ }
208+ if !forwarded {
209+ t.Fatal("expected default startup URL to be forwarded")
210+ }
211+}
212+
199 func TestTryForwardBrowseURLToRunningInstance_ReturnsTrueOnRelayHit(t *testing.T) {213 func TestTryForwardBrowseURLToRunningInstance_ReturnsTrueOnRelayHit(t *testing.T) {
200 relay := mocks.NewMockBrowserLaunchRelay(t)214 relay := mocks.NewMockBrowserLaunchRelay(t)
201 relay.EXPECT().DeliverOpenFreshWindow(context.Background(), "https://example.com").Return(true, nil)215 relay.EXPECT().DeliverOpenFreshWindow(context.Background(), "https://example.com").Return(true, nil)
A internal/domain/url/startup.go +19 -0
@@ -0,0 +1,19 @@
1+package url
2+
3+const defaultBrowserStartupURL = "dumb://history"
4+
5+// DefaultBrowserStartupURL is the user-facing destination used when the browser
6+// opens without an explicit URL. Engine implementations may still use their own
7+// technical bootstrap URL (for example, about:blank) before navigating here.
8+func DefaultBrowserStartupURL() string {
9+ return defaultBrowserStartupURL
10+}
11+
12+// ResolveBrowserStartupURL returns the explicit URL when provided, otherwise
13+// the global user-facing browser startup URL.
14+func ResolveBrowserStartupURL(rawURL string) string {
15+ if rawURL != "" {
16+ return rawURL
17+ }
18+ return defaultBrowserStartupURL
19+}
@@ -0,0 +1,19 @@
1+package url
2+
3+const defaultBrowserStartupURL = "dumb://history"
4+
5+// DefaultBrowserStartupURL is the user-facing destination used when the browser
6+// opens without an explicit URL. Engine implementations may still use their own
7+// technical bootstrap URL (for example, about:blank) before navigating here.
8+func DefaultBrowserStartupURL() string {
9+ return defaultBrowserStartupURL
10+}
11+
12+// ResolveBrowserStartupURL returns the explicit URL when provided, otherwise
13+// the global user-facing browser startup URL.
14+func ResolveBrowserStartupURL(rawURL string) string {
15+ if rawURL != "" {
16+ return rawURL
17+ }
18+ return defaultBrowserStartupURL
19+}
A internal/domain/url/startup_test.go +24 -0
@@ -0,0 +1,24 @@
1+package url
2+
3+import "testing"
4+
5+func TestResolveBrowserStartupURL_PreservesExplicitURL(t *testing.T) {
6+ got := ResolveBrowserStartupURL("https://example.com")
7+ if got != "https://example.com" {
8+ t.Fatalf("expected explicit URL to be preserved, got %q", got)
9+ }
10+}
11+
12+func TestResolveBrowserStartupURL_DefaultsToHistory(t *testing.T) {
13+ got := ResolveBrowserStartupURL("")
14+ if got != "dumb://history" {
15+ t.Fatalf("expected default browser startup URL, got %q", got)
16+ }
17+}
18+
19+func TestDefaultBrowserStartupURL(t *testing.T) {
20+ got := DefaultBrowserStartupURL()
21+ if got != "dumb://history" {
22+ t.Fatalf("expected history default, got %q", got)
23+ }
24+}
@@ -0,0 +1,24 @@
1+package url
2+
3+import "testing"
4+
5+func TestResolveBrowserStartupURL_PreservesExplicitURL(t *testing.T) {
6+ got := ResolveBrowserStartupURL("https://example.com")
7+ if got != "https://example.com" {
8+ t.Fatalf("expected explicit URL to be preserved, got %q", got)
9+ }
10+}
11+
12+func TestResolveBrowserStartupURL_DefaultsToHistory(t *testing.T) {
13+ got := ResolveBrowserStartupURL("")
14+ if got != "dumb://history" {
15+ t.Fatalf("expected default browser startup URL, got %q", got)
16+ }
17+}
18+
19+func TestDefaultBrowserStartupURL(t *testing.T) {
20+ got := DefaultBrowserStartupURL()
21+ if got != "dumb://history" {
22+ t.Fatalf("expected history default, got %q", got)
23+ }
24+}
M internal/ui/app.go +3 -3
@@ -796,10 +796,10 @@ func (a *App) openFreshWindowWithTabsUC(ctx context.Context, url string, created
796796 }
797797
798798 func (a *App) initialWindowURL() string {
799- if a.deps != nil && a.deps.InitialURL != "" {
800- return a.deps.InitialURL
799+ if a.deps != nil {
800+ return urlutil.ResolveBrowserStartupURL(a.deps.InitialURL)
801801 }
802- return "dumb://history"
802+ return urlutil.DefaultBrowserStartupURL()
803803 }
804804
805805 func (a *App) initLayoutInfrastructure() {
@@ -796,10 +796,10 @@ func (a *App) openFreshWindowWithTabsUC(ctx context.Context, url string, created
796 }796 }
797 797
798 func (a *App) initialWindowURL() string {798 func (a *App) initialWindowURL() string {
799- if a.deps != nil && a.deps.InitialURL != "" {799+ if a.deps != nil {
800- return a.deps.InitialURL800+ return urlutil.ResolveBrowserStartupURL(a.deps.InitialURL)
801 }801 }
802- return "dumb://history"802+ return urlutil.DefaultBrowserStartupURL()
803 }803 }
804 804
805 func (a *App) initLayoutInfrastructure() {805 func (a *App) initLayoutInfrastructure() {

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 9

Tags 42

↑↓ moveenter openesc close