Rules-based browser launcher for TUI + GNOME. switchyard.aly.codes
tui gome bowser go
0

Configure Feed

Select the types of activity you want to include in your feed.

remove costly second calls to detectBrowsers() and loadConfig()

Aly Raffauf (Jan 23, 2026, 11:55 PM EST) 0995efb1 ed66166f

+18 -25
+1 -1
src/launcher_actions.go
··· 48 48 49 49 settingsAction := gio.NewSimpleAction("settings", nil) 50 50 settingsAction.ConnectActivate(func(p *glib.Variant) { 51 - showSettingsWindow(app, loadConfig()) 51 + showSettingsWindow(app, browsers, loadConfig()) 52 52 }) 53 53 actionGroup.AddAction(settingsAction) 54 54
+9 -13
src/main.go
··· 27 27 app.ConnectActivate(func() { 28 28 cfg := loadConfig() 29 29 setupApp(cfg) 30 - showSettingsWindow(app, cfg) 30 + browsers := detectBrowsers() 31 + showSettingsWindow(app, browsers, cfg) 31 32 }) 32 33 33 34 app.ConnectOpen(func(files []gio.Filer, hint string) { 34 35 cfg := loadConfig() 35 36 setupApp(cfg) 37 + browsers := detectBrowsers() 36 38 37 39 if len(files) == 0 { 38 - showSettingsWindow(app, cfg) 40 + showSettingsWindow(app, browsers, cfg) 39 41 return 40 42 } 41 43 ··· 43 45 44 46 // Check if this is a switchyard:// URL 45 47 if u, err := url.Parse(rawURL); err == nil && u.Scheme == "switchyard" { 46 - handleSwitchyardURL(app, rawURL) 48 + handleSwitchyardURL(app, browsers, cfg, rawURL) 47 49 return 48 50 } 49 51 ··· 54 56 cmd.Start() 55 57 return 56 58 } 57 - handleURL(app, cfg, sanitized) 59 + handleURL(app, browsers, cfg, sanitized) 58 60 }) 59 61 60 62 if code := app.Run(os.Args); code > 0 { ··· 83 85 } 84 86 85 87 // handleSwitchyardURL processes switchyard:// URLs with browser preferences 86 - func handleSwitchyardURL(app *adw.Application, rawURL string) { 87 - cfg := loadConfig() 88 - 88 + func handleSwitchyardURL(app *adw.Application, browsers []*Browser, cfg *Config, rawURL string) { 89 89 targetURL, browserPrefs, err := parseSwitchyardURL(rawURL) 90 90 if err != nil { 91 91 // Invalid switchyard URL - ignore ··· 100 100 cmd.Start() 101 101 return 102 102 } 103 - 104 - browsers := detectBrowsers() 105 103 106 104 // If browser preferences specified, try each in order 107 105 if len(browserPrefs) > 0 { ··· 123 121 } 124 122 125 123 // No browser specified - use standard routing 126 - handleURL(app, cfg, sanitized) 124 + handleURL(app, browsers, cfg, sanitized) 127 125 } 128 126 129 127 // handleURL routes a URL to the appropriate browser based on rules 130 - func handleURL(app *adw.Application, cfg *Config, urlStr string) { 131 - browsers := detectBrowsers() 132 - 128 + func handleURL(app *adw.Application, browsers []*Browser, cfg *Config, urlStr string) { 133 129 // Try to match a rule 134 130 browserID, alwaysAsk, matched := cfg.matchRule(urlStr) 135 131 if matched {
+1 -2
src/settings_appearance.go
··· 7 7 "github.com/diamondburned/gotk4/pkg/gtk/v4" 8 8 ) 9 9 10 - func createAppearancePage(win *adw.Window, cfg *Config) gtk.Widgetter { 11 - browsers := detectBrowsers() 10 + func createAppearancePage(win *adw.Window, browsers []*Browser, cfg *Config) gtk.Widgetter { 12 11 toolbarView, content, _ := settingsPageLayout("Appearance") 13 12 14 13 // General section
+1 -1
src/settings_behavior.go
··· 7 7 "github.com/diamondburned/gotk4/pkg/gtk/v4" 8 8 ) 9 9 10 - func createBehaviorPage(win *adw.Window, cfg *Config, browsers []*Browser) gtk.Widgetter { 10 + func createBehaviorPage(win *adw.Window, browsers []*Browser, cfg *Config) gtk.Widgetter { 11 11 toolbarView, content, _ := settingsPageLayout("Behavior") 12 12 13 13 // General Behavior section
+1 -1
src/settings_rules.go
··· 59 59 } 60 60 } 61 61 62 - func createRulesPage(win *adw.Window, cfg *Config, browsers []*Browser) gtk.Widgetter { 62 + func createRulesPage(win *adw.Window, browsers []*Browser, cfg *Config) gtk.Widgetter { 63 63 toolbarView := adw.NewToolbarView() 64 64 65 65 header := adw.NewHeaderBar()
+5 -7
src/window_settings.go
··· 11 11 "github.com/diamondburned/gotk4/pkg/gtk/v4" 12 12 ) 13 13 14 - func showSettingsWindow(app *adw.Application, cfg *Config) { 14 + func showSettingsWindow(app *adw.Application, browsers []*Browser, cfg *Config) { 15 15 win := adw.NewWindow() 16 16 win.SetTitle("Switchyard") 17 17 win.SetApplication(&app.Application) 18 18 win.SetDefaultSize(900, 600) 19 19 win.SetResizable(true) 20 20 win.SetSizeRequest(700, 500) 21 - 22 - browsers := detectBrowsers() 23 21 24 22 setupAppActions(app, win) 25 23 ··· 34 32 splitView.SetSidebar(sidebarPage) 35 33 36 34 // Initial content 37 - contentPage := adw.NewNavigationPage(createAppearancePage(win, cfg), "Appearance") 35 + contentPage := adw.NewNavigationPage(createAppearancePage(win, browsers, cfg), "Appearance") 38 36 splitView.SetContent(contentPage) 39 37 40 38 win.SetContent(splitView) ··· 141 139 142 140 switch index { 143 141 case 0: 144 - page = createAppearancePage(win, cfg) 142 + page = createAppearancePage(win, browsers, cfg) 145 143 title = "Appearance" 146 144 case 1: 147 - page = createBehaviorPage(win, cfg, browsers) 145 + page = createBehaviorPage(win, browsers, cfg) 148 146 title = "Behavior" 149 147 case 2: 150 - page = createRulesPage(win, cfg, browsers) 148 + page = createRulesPage(win, browsers, cfg) 151 149 title = "Rules" 152 150 case 3: 153 151 page = createAdvancedPage(win, cfg)