From 3f7afa9fce05a3d10af7b4cd092c6306a994b992 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Wed, 24 Sep 2025 14:58:42 -0400 Subject: [PATCH 1/4] improve Linux compatibility --- cmd/goose/icons.go | 81 +++++++++++++++++ cmd/goose/icons/goose.png | Bin 0 -> 16334 bytes cmd/goose/icons/lock.png | Bin 0 -> 9832 bytes cmd/goose/icons/popper.png | Bin 0 -> 31568 bytes cmd/goose/icons/smiling-face.png | Bin 0 -> 51381 bytes cmd/goose/icons/warning.png | Bin 0 -> 9954 bytes cmd/goose/main.go | 140 ++++++++++++++++++++--------- cmd/goose/notifications.go | 77 ++++++++-------- cmd/goose/systray_interface.go | 9 ++ cmd/goose/ui.go | 147 +++++++++++++++++++------------ 10 files changed, 321 insertions(+), 133 deletions(-) create mode 100644 cmd/goose/icons.go create mode 100644 cmd/goose/icons/goose.png create mode 100644 cmd/goose/icons/lock.png create mode 100644 cmd/goose/icons/popper.png create mode 100644 cmd/goose/icons/smiling-face.png create mode 100644 cmd/goose/icons/warning.png diff --git a/cmd/goose/icons.go b/cmd/goose/icons.go new file mode 100644 index 0000000..eb0f7eb --- /dev/null +++ b/cmd/goose/icons.go @@ -0,0 +1,81 @@ +package main + +import ( + _ "embed" + "log/slog" + "os" + "path/filepath" +) + +// Embed icon files at compile time for better distribution +// +//go:embed icons/goose.png +var iconGoose []byte + +//go:embed icons/popper.png +var iconPopper []byte + +//go:embed icons/smiling-face.png +var iconSmiling []byte + +//go:embed icons/lock.png +var iconLock []byte + +//go:embed icons/warning.png +var iconWarning []byte + +// IconType represents different icon states +type IconType int + +const ( + IconSmiling IconType = iota // No blocked PRs + IconGoose // Incoming PRs blocked + IconPopper // Outgoing PRs blocked + IconBoth // Both incoming and outgoing blocked + IconWarning // General error/warning + IconLock // Authentication error +) + +// getIcon returns the icon bytes for the given type +func getIcon(iconType IconType) []byte { + switch iconType { + case IconGoose: + return iconGoose + case IconPopper: + return iconPopper + case IconSmiling: + return iconSmiling + case IconWarning: + return iconWarning + case IconLock: + return iconLock + case IconBoth: + // For both, we'll use the goose icon as primary + return iconGoose + default: + return iconSmiling + } +} + +// loadIconFromFile loads an icon from the filesystem (fallback if embed fails) +func loadIconFromFile(filename string) []byte { + iconPath := filepath.Join("icons", filename) + data, err := os.ReadFile(iconPath) + if err != nil { + slog.Warn("Failed to load icon file", "path", iconPath, "error", err) + return nil + } + return data +} + +// setTrayIcon updates the system tray icon based on PR counts +func (app *App) setTrayIcon(iconType IconType) { + iconBytes := getIcon(iconType) + if iconBytes == nil || len(iconBytes) == 0 { + slog.Warn("Icon bytes are empty, skipping icon update", "type", iconType) + return + } + + app.systrayInterface.SetIcon(iconBytes) + slog.Debug("[TRAY] Setting icon", "type", iconType) +} \ No newline at end of file diff --git a/cmd/goose/icons/goose.png b/cmd/goose/icons/goose.png new file mode 100644 index 0000000000000000000000000000000000000000..0a569f35340190f37678eae3be08eae4652ff22d GIT binary patch literal 16334 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 YL1GVjrn`@kG$@mt*E7~F)^?2iKO*bYmjD0& literal 0 HcmV?d00001 diff --git a/cmd/goose/icons/lock.png b/cmd/goose/icons/lock.png new file mode 100644 index 0000000000000000000000000000000000000000..72d1e3f63b8ac074114aa5ccb9fe7547bd1134f0 GIT binary patch literal 9832 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 literal 0 HcmV?d00001 diff --git a/cmd/goose/icons/smiling-face.png b/cmd/goose/icons/smiling-face.png new file mode 100644 index 0000000000000000000000000000000000000000..ffa3a4c6b542c2e6c78e52f04b47c98ebd281a5e GIT binary patch literal 51381 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�rt7bNCcO5XprAs=P{deun!x5VYk$&k2YO&Z_K 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 Sznb_!^L+>QX76_S`+op5PIhVl literal 0 HcmV?d00001 diff --git a/cmd/goose/main.go b/cmd/goose/main.go index e7ec3d9..0691480 100644 --- a/cmd/goose/main.go +++ b/cmd/goose/main.go @@ -11,6 +11,7 @@ import ( "log/slog" "os" "path/filepath" + "runtime" "slices" "strings" "sync" @@ -192,7 +193,7 @@ func main() { Level: slog.LevelInfo, } slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, opts))) - slog.Info("Starting GitHub PR Monitor", "version", version, "commit", commit, "date", date) + slog.Info("Starting Goose", "version", version, "commit", commit, "date", date) slog.Info("Configuration", "update_interval", updateInterval, "max_retries", maxRetries, "max_delay", maxRetryDelay) slog.Info("Browser auto-open configuration", "startup_delay", browserOpenDelay, "max_per_minute", maxBrowserOpensMinute, "max_per_day", maxBrowserOpensDay) @@ -283,23 +284,87 @@ func main() { func (app *App) onReady(ctx context.Context) { slog.Info("System tray ready") + // On Linux, immediately build a minimal menu to ensure it's visible + if runtime.GOOS == "linux" { + slog.Info("[LINUX] Building initial minimal menu") + app.systrayInterface.ResetMenu() + placeholderItem := app.systrayInterface.AddMenuItem("Loading...", "Goose is starting up") + if placeholderItem != nil { + placeholderItem.Disable() + } + app.systrayInterface.AddSeparator() + quitItem := app.systrayInterface.AddMenuItem("Quit", "Quit Goose") + if quitItem != nil { + quitItem.Click(func() { + slog.Info("Quit clicked") + systray.Quit() + }) + } + } + // Set up click handlers first (needed for both success and error states) systray.SetOnClick(func(menu systray.IMenu) { slog.Debug("Icon clicked") - // Check if we can perform a forced refresh (rate limited to every 10 seconds) + // Check if we're in auth error state and should retry app.mu.RLock() - timeSinceLastSearch := time.Since(app.lastSearchAttempt) + hasAuthError := app.authError != "" app.mu.RUnlock() - if timeSinceLastSearch >= minUpdateInterval { - slog.Info("[CLICK] Forcing search refresh", "lastSearchAgo", timeSinceLastSearch) + if hasAuthError { + slog.Info("[CLICK] Auth error detected, attempting to re-authenticate") go func() { - app.updatePRs(ctx) + // Try to reinitialize clients which will attempt to get token via gh auth token + if err := app.initClients(ctx); err != nil { + slog.Warn("[CLICK] Re-authentication failed", "error", err) + app.mu.Lock() + app.authError = err.Error() + app.mu.Unlock() + } else { + // Success! Clear auth error and reload user + slog.Info("[CLICK] Re-authentication successful") + app.mu.Lock() + app.authError = "" + app.mu.Unlock() + + // Load current user + loadCurrentUser(ctx, app) + + // Update tooltip + tooltip := "Goose - Loading PRs..." + if app.targetUser != "" { + tooltip = fmt.Sprintf("Goose - Loading PRs... (@%s)", app.targetUser) + } + systray.SetTooltip(tooltip) + + // Rebuild menu to remove error state + app.rebuildMenu(ctx) + + // Start update loop if not already running + if !app.menuInitialized { + app.menuInitialized = true + go app.updateLoop(ctx) + } else { + // Just do a single update to refresh data + go app.updatePRs(ctx) + } + } }() } else { - remainingTime := minUpdateInterval - timeSinceLastSearch - slog.Debug("[CLICK] Rate limited", "lastSearchAgo", timeSinceLastSearch, "remaining", remainingTime) + // Normal operation - check if we can perform a forced refresh + app.mu.RLock() + timeSinceLastSearch := time.Since(app.lastSearchAttempt) + app.mu.RUnlock() + + if timeSinceLastSearch >= minUpdateInterval { + slog.Info("[CLICK] Forcing search refresh", "lastSearchAgo", timeSinceLastSearch) + go func() { + app.updatePRs(ctx) + }() + } else { + remainingTime := minUpdateInterval - timeSinceLastSearch + slog.Debug("[CLICK] Rate limited", "lastSearchAgo", timeSinceLastSearch, "remaining", remainingTime) + } } if menu != nil { @@ -320,8 +385,9 @@ func (app *App) onReady(ctx context.Context) { // Check if we have an auth error if app.authError != "" { - systray.SetTitle("⚠️") - systray.SetTooltip("GitHub PR Monitor - Authentication Error") + systray.SetTitle("") + app.setTrayIcon(IconLock) + systray.SetTooltip("Goose - Authentication Error") // Create initial error menu app.rebuildMenu(ctx) // Clean old cache on startup @@ -329,12 +395,13 @@ func (app *App) onReady(ctx context.Context) { return } - systray.SetTitle("Loading PRs...") + systray.SetTitle("") + app.setTrayIcon(IconSmiling) // Start with smiling icon while loading // Set tooltip based on whether we're using a custom user - tooltip := "GitHub PR Monitor" + tooltip := "Goose - Loading PRs..." if app.targetUser != "" { - tooltip = fmt.Sprintf("GitHub PR Monitor - @%s", app.targetUser) + tooltip = fmt.Sprintf("Goose - Loading PRs... (@%s)", app.targetUser) } systray.SetTooltip(tooltip) @@ -352,8 +419,9 @@ func (app *App) updateLoop(ctx context.Context) { slog.Error("PANIC in update loop", "panic", r) // Set error state in UI - systray.SetTitle("💥") - systray.SetTooltip("GitHub PR Monitor - Critical error") + systray.SetTitle("") + app.setTrayIcon(IconWarning) + systray.SetTooltip("Goose - Critical error") // Update failure count app.mu.Lock() @@ -406,23 +474,19 @@ func (app *App) updatePRs(ctx context.Context) { app.mu.Unlock() // Progressive degradation based on failure count - var title, tooltip string + var tooltip string + var iconType IconType switch { - case failureCount == 1: - title = "⚠️" - tooltip = "GitHub PR Monitor - Temporary error, retrying..." case failureCount <= minorFailureThreshold: - title = "⚠️" - tooltip = fmt.Sprintf("GitHub PR Monitor - %d consecutive failures", failureCount) - case failureCount <= majorFailureThreshold: - title = "❌" - tooltip = "GitHub PR Monitor - Multiple failures, check connection" + iconType = IconWarning + tooltip = fmt.Sprintf("Goose - %d consecutive failures", failureCount) default: - title = "💀" - tooltip = "GitHub PR Monitor - Service degraded, check authentication" + iconType = IconWarning + tooltip = "Goose - Connection failures, check network/auth" } - systray.SetTitle(title) + systray.SetTitle("") + app.setTrayIcon(iconType) // Include time since last success and user info timeSinceSuccess := "never" @@ -553,23 +617,19 @@ func (app *App) updatePRsWithWait(ctx context.Context) { app.mu.Unlock() // Progressive degradation based on failure count - var title, tooltip string + var tooltip string + var iconType IconType switch { - case failureCount == 1: - title = "⚠️" - tooltip = "GitHub PR Monitor - Temporary error, retrying..." case failureCount <= minorFailureThreshold: - title = "⚠️" - tooltip = fmt.Sprintf("GitHub PR Monitor - %d consecutive failures", failureCount) - case failureCount <= majorFailureThreshold: - title = "❌" - tooltip = "GitHub PR Monitor - Multiple failures, check connection" + iconType = IconWarning + tooltip = fmt.Sprintf("Goose - %d consecutive failures", failureCount) default: - title = "💀" - tooltip = "GitHub PR Monitor - Service degraded, check authentication" + iconType = IconWarning + tooltip = "Goose - Connection failures, check network/auth" } - systray.SetTitle(title) + systray.SetTitle("") + app.setTrayIcon(iconType) systray.SetTooltip(tooltip) // Create or update menu to show error state @@ -676,7 +736,7 @@ func (app *App) tryAutoOpenPR(ctx context.Context, pr PR, autoBrowserEnabled boo slog.Warn("Auto-open strict validation failed", "url", sanitizeForLog(pr.URL), "error", err) return } - if err := openURL(ctx, pr.URL, pr.ActionKind); err != nil { + if err := openURL(ctx, pr.URL); err != nil { slog.Error("[BROWSER] Failed to auto-open PR", "url", pr.URL, "error", err) } else { app.browserRateLimiter.RecordOpen(pr.URL) diff --git a/cmd/goose/notifications.go b/cmd/goose/notifications.go index e00126d..9f8ec4f 100644 --- a/cmd/goose/notifications.go +++ b/cmd/goose/notifications.go @@ -47,55 +47,60 @@ func (app *App) processNotifications(ctx context.Context) { slog.Info("[NOTIFY] PRs need notifications", "count", len(toNotify)) - // Send notifications for each PR - playedHonk := false - playedRocket := false - - for i := range toNotify { - pr := toNotify[i] - isIncoming := false - // Check if it's in the incoming list - for j := range incoming { - if incoming[j].URL == pr.URL { - isIncoming = true - break + // Process notifications in a goroutine to avoid blocking the UI thread + go func() { + // Send notifications for each PR + playedHonk := false + playedRocket := false + + for i := range toNotify { + pr := toNotify[i] + isIncoming := false + // Check if it's in the incoming list + for j := range incoming { + if incoming[j].URL == pr.URL { + isIncoming = true + break + } } - } - // Send notification - if isIncoming { - app.sendPRNotification(ctx, pr, "PR Blocked on You 🪿", "honk", &playedHonk) - } else { - // Add delay between different sound types - if playedHonk && !playedRocket { - time.Sleep(2 * time.Second) + // Send notification + if isIncoming { + app.sendPRNotification(ctx, pr, "PR Blocked on You 🪿", "honk", &playedHonk) + } else { + // Add delay between different sound types in goroutine to avoid blocking + if playedHonk && !playedRocket { + time.Sleep(2 * time.Second) + } + app.sendPRNotification(ctx, pr, "Your PR is Blocked 🚀", "rocket", &playedRocket) } - app.sendPRNotification(ctx, pr, "Your PR is Blocked 🚀", "rocket", &playedRocket) - } - // Auto-open if enabled - if app.enableAutoBrowser && time.Since(app.startTime) > startupGracePeriod { - app.tryAutoOpenPR(ctx, pr, app.enableAutoBrowser, app.startTime) + // Auto-open if enabled + if app.enableAutoBrowser && time.Since(app.startTime) > startupGracePeriod { + app.tryAutoOpenPR(ctx, pr, app.enableAutoBrowser, app.startTime) + } } - } - // Update menu if we sent notifications - if len(toNotify) > 0 { - slog.Debug("[NOTIFY] Updating menu after notifications") - app.updateMenu(ctx) - } + // Update menu if we sent notifications + if len(toNotify) > 0 { + slog.Debug("[NOTIFY] Updating menu after notifications") + app.updateMenu(ctx) + } + }() } // sendPRNotification sends a notification for a single PR. func (app *App) sendPRNotification(ctx context.Context, pr PR, title string, soundType string, playedSound *bool) { message := fmt.Sprintf("%s #%d: %s", pr.Repository, pr.Number, pr.Title) - // Send desktop notification - if err := beeep.Notify(title, message, ""); err != nil { - slog.Error("[NOTIFY] Failed to send notification", "url", pr.URL, "error", err) - } + // Send desktop notification in a goroutine to avoid blocking + go func() { + if err := beeep.Notify(title, message, ""); err != nil { + slog.Error("[NOTIFY] Failed to send notification", "url", pr.URL, "error", err) + } + }() - // Play sound (only once per type per cycle) + // Play sound (only once per type per cycle) - already async in playSound if !*playedSound { slog.Debug("[NOTIFY] Playing sound for PR", "soundType", soundType, "repo", pr.Repository, "number", pr.Number) app.playSound(ctx, soundType) diff --git a/cmd/goose/systray_interface.go b/cmd/goose/systray_interface.go index 4b0af61..b872698 100644 --- a/cmd/goose/systray_interface.go +++ b/cmd/goose/systray_interface.go @@ -10,6 +10,7 @@ type SystrayInterface interface { AddMenuItem(title, tooltip string) MenuItem AddSeparator() SetTitle(title string) + SetIcon(iconBytes []byte) SetOnClick(fn func(menu systray.IMenu)) Quit() } @@ -34,6 +35,10 @@ func (*RealSystray) SetTitle(title string) { systray.SetTitle(title) } +func (*RealSystray) SetIcon(iconBytes []byte) { + systray.SetIcon(iconBytes) +} + func (*RealSystray) SetOnClick(fn func(menu systray.IMenu)) { systray.SetOnClick(fn) } @@ -69,6 +74,10 @@ func (m *MockSystray) SetTitle(title string) { m.title = title } +func (*MockSystray) SetIcon(iconBytes []byte) { + // No-op for testing +} + func (*MockSystray) SetOnClick(_ func(menu systray.IMenu)) { // No-op for testing } diff --git a/cmd/goose/ui.go b/cmd/goose/ui.go index 2d82f46..15e44d8 100644 --- a/cmd/goose/ui.go +++ b/cmd/goose/ui.go @@ -20,8 +20,7 @@ import ( var _ *systray.MenuItem = nil // openURL safely opens a URL in the default browser after validation. -// action parameter is optional and specifies the expected action type for tracking. -func openURL(ctx context.Context, rawURL string, action string) error { +func openURL(ctx context.Context, rawURL string) error { // Parse and validate the URL u, err := url.Parse(rawURL) if err != nil { @@ -46,15 +45,10 @@ func openURL(ctx context.Context, rawURL string, action string) error { return errors.New("URLs with user info are not allowed") } - // Add goose parameter to track source and action for GitHub and dash URLs + // Add goose=1 parameter to track source for GitHub and dash URLs if u.Host == "github.com" || u.Host == "www.github.com" || u.Host == "dash.ready-to-review.dev" { q := u.Query() - // Use action if provided, otherwise default to "1" for backward compatibility - if action != "" { - q.Set("goose", action) - } else { - q.Set("goose", "1") - } + q.Set("goose", "1") u.RawQuery = q.Encode() rawURL = u.String() } @@ -147,31 +141,38 @@ func (app *App) countPRs() PRCounts { } } -// setTrayTitle updates the system tray title based on PR counts. +// setTrayTitle updates the system tray title and icon based on PR counts. func (app *App) setTrayTitle() { counts := app.countPRs() - // Set title based on PR state + // Set title and icon based on PR state var title string + var iconType IconType switch { case counts.IncomingBlocked == 0 && counts.OutgoingBlocked == 0: - title = "😊" + title = "" + iconType = IconSmiling case counts.IncomingBlocked > 0 && counts.OutgoingBlocked > 0: - title = fmt.Sprintf("🪿 %d 🎉 %d", counts.IncomingBlocked, counts.OutgoingBlocked) + title = fmt.Sprintf("%d / %d", counts.IncomingBlocked, counts.OutgoingBlocked) + iconType = IconBoth case counts.IncomingBlocked > 0: - title = fmt.Sprintf("🪿 %d", counts.IncomingBlocked) + title = fmt.Sprintf("%d", counts.IncomingBlocked) + iconType = IconGoose default: - title = fmt.Sprintf("🎉 %d", counts.OutgoingBlocked) + title = fmt.Sprintf("%d", counts.OutgoingBlocked) + iconType = IconPopper } // Log title change with detailed counts - slog.Debug("[TRAY] Setting title", + slog.Debug("[TRAY] Setting title and icon", "title", title, + "icon", iconType, "incoming_total", counts.IncomingTotal, "incoming_blocked", counts.IncomingBlocked, "outgoing_total", counts.OutgoingTotal, "outgoing_blocked", counts.OutgoingBlocked) app.systrayInterface.SetTitle(title) + app.setTrayIcon(iconType) } // addPRSection adds a section of PRs to the menu. @@ -290,11 +291,10 @@ func (app *App) addPRSection(ctx context.Context, prs []PR, sectionTitle string, // Create PR menu item item := app.systrayInterface.AddMenuItem(title, tooltip) - // Capture URL and action to avoid loop variable capture bug + // Capture URL to avoid loop variable capture bug prURL := sortedPRs[prIndex].URL - prAction := sortedPRs[prIndex].ActionKind item.Click(func() { - if err := openURL(ctx, prURL, prAction); err != nil { + if err := openURL(ctx, prURL); err != nil { slog.Error("failed to open url", "error", err) } }) @@ -433,7 +433,7 @@ func (app *App) rebuildMenu(ctx context.Context) { // Add error details errorMsg := app.systrayInterface.AddMenuItem(authError, "Click to see setup instructions") errorMsg.Click(func() { - if err := openURL(ctx, "https://cli.github.com/manual/gh_auth_login", ""); err != nil { + if err := openURL(ctx, "https://cli.github.com/manual/gh_auth_login"); err != nil { slog.Error("failed to open setup instructions", "error", err) } }) @@ -543,7 +543,7 @@ func (app *App) rebuildMenu(ctx context.Context) { // Add Web Dashboard link dashboardItem := app.systrayInterface.AddMenuItem("Web Dashboard", "") dashboardItem.Click(func() { - if err := openURL(ctx, "https://dash.ready-to-review.dev/", ""); err != nil { + if err := openURL(ctx, "https://dash.ready-to-review.dev/"); err != nil { slog.Error("failed to open dashboard", "error", err) } }) @@ -625,10 +625,17 @@ func (app *App) addStaticMenuItems(ctx context.Context) { // Add checkbox items for each org for _, org := range orgs { orgName := org // Capture for closure - orgItem := hideOrgsMenu.AddSubMenuItem(orgName, "") - - // Check if org is currently hidden + // Add text checkmark for Linux + var orgText string if hiddenOrgs[orgName] { + orgText = "✓ " + orgName + } else { + orgText = orgName + } + orgItem := hideOrgsMenu.AddSubMenuItem(orgText, "") + + // Check if org is currently hidden (for non-Linux) + if runtime.GOOS != "linux" && hiddenOrgs[orgName] { orgItem.Check() } @@ -636,89 +643,113 @@ func (app *App) addStaticMenuItems(ctx context.Context) { app.mu.Lock() if app.hiddenOrgs[orgName] { delete(app.hiddenOrgs, orgName) - orgItem.Uncheck() + if runtime.GOOS != "linux" { + orgItem.Uncheck() + } slog.Info("[SETTINGS] Unhiding org", "org", orgName) } else { app.hiddenOrgs[orgName] = true - orgItem.Check() + if runtime.GOOS != "linux" { + orgItem.Check() + } slog.Info("[SETTINGS] Hiding org", "org", orgName) } - // Menu always rebuilds now - no need to clear titles app.mu.Unlock() // Save settings app.saveSettings() - // Rebuild menu to reflect changes - app.rebuildMenu(ctx) + // Note: Menu needs manual refresh on Linux to see changes }) } } // Hide stale PRs - // Add 'Hide stale PRs' option - hideStaleItem := app.systrayInterface.AddMenuItem("Hide stale PRs (>90 days)", "") + // Add 'Hide stale PRs' option with text checkmark for Linux + var hideStaleText string if app.hideStaleIncoming { + hideStaleText = "✓ Hide stale PRs (>90 days)" + } else { + hideStaleText = "Hide stale PRs (>90 days)" + } + hideStaleItem := app.systrayInterface.AddMenuItem(hideStaleText, "") + if runtime.GOOS != "linux" && app.hideStaleIncoming { hideStaleItem.Check() } hideStaleItem.Click(func() { app.mu.Lock() app.hideStaleIncoming = !app.hideStaleIncoming hideStale := app.hideStaleIncoming - // Menu always rebuilds now - no need to clear titles app.mu.Unlock() - if hideStale { - hideStaleItem.Check() - } else { - hideStaleItem.Uncheck() + if runtime.GOOS != "linux" { + if hideStale { + hideStaleItem.Check() + } else { + hideStaleItem.Uncheck() + } } // Save settings to disk app.saveSettings() - // Toggle hide stale PRs setting - // Force menu rebuild since hideStaleIncoming changed - app.rebuildMenu(ctx) + // Note: Menu needs manual refresh on Linux to see changes + slog.Info("[SETTINGS] Hide stale PRs toggled", "enabled", hideStale) }) // Add login item option (macOS only) addLoginItemUI(ctx, app) // Audio cues - // Add 'Audio cues' option - audioItem := app.systrayInterface.AddMenuItem("Honks enabled", "Play sounds for notifications") + // Add 'Audio cues' option with text checkmark for Linux app.mu.RLock() + var audioText string if app.enableAudioCues { - audioItem.Check() + audioText = "✓ Honks enabled" + } else { + audioText = "Honks enabled" } + enableAudioCues := app.enableAudioCues app.mu.RUnlock() + audioItem := app.systrayInterface.AddMenuItem(audioText, "Play sounds for notifications") + if runtime.GOOS != "linux" && enableAudioCues { + audioItem.Check() + } audioItem.Click(func() { app.mu.Lock() app.enableAudioCues = !app.enableAudioCues enabled := app.enableAudioCues app.mu.Unlock() - if enabled { - audioItem.Check() - slog.Info("[SETTINGS] Audio cues enabled") - } else { - audioItem.Uncheck() - slog.Info("[SETTINGS] Audio cues disabled") + if runtime.GOOS != "linux" { + if enabled { + audioItem.Check() + } else { + audioItem.Uncheck() + } } + slog.Info("[SETTINGS] Audio cues toggled", "enabled", enabled) + // Save settings to disk app.saveSettings() }) // Auto-open blocked PRs in browser - // Add 'Auto-open PRs' option - autoOpenItem := app.systrayInterface.AddMenuItem("Auto-open incoming PRs", "Automatically open newly blocked PRs in browser (rate limited)") + // Add 'Auto-open PRs' option with text checkmark for Linux app.mu.RLock() + var autoText string if app.enableAutoBrowser { - autoOpenItem.Check() + autoText = "✓ Auto-open incoming PRs" + } else { + autoText = "Auto-open incoming PRs" } + enableAutoBrowser := app.enableAutoBrowser app.mu.RUnlock() + autoOpenItem := app.systrayInterface.AddMenuItem(autoText, "Automatically open newly blocked PRs in browser (rate limited)") + if runtime.GOOS != "linux" && enableAutoBrowser { + autoOpenItem.Check() + } autoOpenItem.Click(func() { app.mu.Lock() app.enableAutoBrowser = !app.enableAutoBrowser @@ -729,14 +760,16 @@ func (app *App) addStaticMenuItems(ctx context.Context) { } app.mu.Unlock() - if enabled { - autoOpenItem.Check() - slog.Info("[SETTINGS] Auto-open blocked PRs enabled") - } else { - autoOpenItem.Uncheck() - slog.Info("[SETTINGS] Auto-open blocked PRs disabled") + if runtime.GOOS != "linux" { + if enabled { + autoOpenItem.Check() + } else { + autoOpenItem.Uncheck() + } } + slog.Info("[SETTINGS] Auto-open blocked PRs toggled", "enabled", enabled) + // Save settings to disk app.saveSettings() }) From a9bca8a53b85eff5928f67e59a28931b44e9657f Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Wed, 24 Sep 2025 15:17:14 -0400 Subject: [PATCH 2/4] merge --- cmd/goose/main.go | 26 ++++++++++++++- cmd/goose/notifications.go | 7 +--- cmd/goose/systray_interface.go | 5 +++ cmd/goose/ui.go | 59 ++++++++++++++++++++++++++-------- 4 files changed, 76 insertions(+), 21 deletions(-) diff --git a/cmd/goose/main.go b/cmd/goose/main.go index 9a9c91b..fd71c5d 100644 --- a/cmd/goose/main.go +++ b/cmd/goose/main.go @@ -331,7 +331,31 @@ func (app *App) onReady(ctx context.Context) { app.mu.Unlock() // Load current user - loadCurrentUser(ctx, app) + if app.client != nil { + var user *github.User + err := retry.Do(func() error { + var retryErr error + user, _, retryErr = app.client.Users.Get(ctx, "") + if retryErr != nil { + slog.Warn("GitHub Users.Get failed (will retry)", "error", retryErr) + return retryErr + } + return nil + }, + retry.Attempts(maxRetries), + retry.DelayType(retry.CombineDelay(retry.BackOffDelay, retry.RandomDelay)), + retry.MaxDelay(maxRetryDelay), + retry.OnRetry(func(n uint, err error) { + slog.Debug("[RETRY] Retrying GitHub API call", "attempt", n, "error", err) + }), + ) + if err == nil && user != nil { + if app.targetUser == "" { + app.targetUser = user.GetLogin() + slog.Info("Set target user to current user", "user", app.targetUser) + } + } + } // Update tooltip tooltip := "Goose - Loading PRs..." diff --git a/cmd/goose/notifications.go b/cmd/goose/notifications.go index d64d6e0..230530b 100644 --- a/cmd/goose/notifications.go +++ b/cmd/goose/notifications.go @@ -95,12 +95,7 @@ func (app *App) processNotifications(ctx context.Context) { slog.Debug("[NOTIFY] Updating menu after notifications") app.updateMenu(ctx) } - - // Auto-open if enabled - if app.enableAutoBrowser && time.Since(app.startTime) > startupGracePeriod { - app.tryAutoOpenPR(ctx, pr, app.enableAutoBrowser, app.startTime) - } - } + }() // Update menu if we sent notifications if len(toNotify) > 0 { diff --git a/cmd/goose/systray_interface.go b/cmd/goose/systray_interface.go index b872698..cd7638f 100644 --- a/cmd/goose/systray_interface.go +++ b/cmd/goose/systray_interface.go @@ -1,6 +1,8 @@ package main import ( + "log/slog" + "github.com/energye/systray" ) @@ -19,10 +21,12 @@ type SystrayInterface interface { type RealSystray struct{} func (*RealSystray) ResetMenu() { + slog.Debug("[SYSTRAY] ResetMenu called") systray.ResetMenu() } func (*RealSystray) AddMenuItem(title, tooltip string) MenuItem { + slog.Debug("[SYSTRAY] AddMenuItem called", "title", title) item := systray.AddMenuItem(title, tooltip) return &RealMenuItem{MenuItem: item} } @@ -32,6 +36,7 @@ func (*RealSystray) AddSeparator() { } func (*RealSystray) SetTitle(title string) { + slog.Info("[SYSTRAY] SetTitle called", "title", title, "len", len(title)) systray.SetTitle(title) } diff --git a/cmd/goose/ui.go b/cmd/goose/ui.go index 3c14965..ab32213 100644 --- a/cmd/goose/ui.go +++ b/cmd/goose/ui.go @@ -193,23 +193,46 @@ func (app *App) setTrayTitle() { // Set title and icon based on PR state var title string var iconType IconType - switch { - case counts.IncomingBlocked == 0 && counts.OutgoingBlocked == 0: - title = "" - iconType = IconSmiling - case counts.IncomingBlocked > 0 && counts.OutgoingBlocked > 0: - title = fmt.Sprintf("%d / %d", counts.IncomingBlocked, counts.OutgoingBlocked) - iconType = IconBoth - case counts.IncomingBlocked > 0: - title = fmt.Sprintf("%d", counts.IncomingBlocked) - iconType = IconGoose - default: - title = fmt.Sprintf("%d", counts.OutgoingBlocked) - iconType = IconPopper + + // On Linux, always show counts if there are any PRs + // This helps since not all desktop environments show the text + if runtime.GOOS == "linux" && (counts.IncomingTotal > 0 || counts.OutgoingTotal > 0) { + // Show blocked/total format for better visibility + if counts.IncomingBlocked > 0 && counts.OutgoingBlocked > 0 { + title = fmt.Sprintf("%d/%d • %d/%d", counts.IncomingBlocked, counts.IncomingTotal, counts.OutgoingBlocked, counts.OutgoingTotal) + iconType = IconBoth + } else if counts.IncomingBlocked > 0 { + title = fmt.Sprintf("%d/%d", counts.IncomingBlocked, counts.IncomingTotal) + iconType = IconGoose + } else if counts.OutgoingBlocked > 0 { + title = fmt.Sprintf("%d/%d", counts.OutgoingBlocked, counts.OutgoingTotal) + iconType = IconPopper + } else { + // No blocked PRs but there are PRs + title = fmt.Sprintf("0/%d", counts.IncomingTotal+counts.OutgoingTotal) + iconType = IconSmiling + } + } else { + // Original behavior for other platforms + switch { + case counts.IncomingBlocked == 0 && counts.OutgoingBlocked == 0: + title = "" + iconType = IconSmiling + case counts.IncomingBlocked > 0 && counts.OutgoingBlocked > 0: + title = fmt.Sprintf("%d / %d", counts.IncomingBlocked, counts.OutgoingBlocked) + iconType = IconBoth + case counts.IncomingBlocked > 0: + title = fmt.Sprintf("%d", counts.IncomingBlocked) + iconType = IconGoose + default: + title = fmt.Sprintf("%d", counts.OutgoingBlocked) + iconType = IconPopper + } } // Log title change with detailed counts - slog.Debug("[TRAY] Setting title and icon", + slog.Info("[TRAY] Setting title and icon", + "os", runtime.GOOS, "title", title, "icon", iconType, "incoming_total", counts.IncomingTotal, @@ -533,9 +556,17 @@ func (app *App) generatePRSectionTitles(prs []PR, sectionTitle string, hiddenOrg // rebuildMenu completely rebuilds the menu from scratch. func (app *App) rebuildMenu(ctx context.Context) { // Rebuild entire menu + slog.Info("[MENU] Starting rebuildMenu", "os", runtime.GOOS) // Clear all existing menu items app.systrayInterface.ResetMenu() + slog.Info("[MENU] Called ResetMenu") + + // On Linux, add a small delay to ensure DBus properly processes the reset + // This helps prevent menu item duplication + if runtime.GOOS == "linux" { + time.Sleep(50 * time.Millisecond) + } // Check for errors (auth or connection failures) app.mu.RLock() From 3aa24aacee41f62aff954eb0558c60a361e50cb7 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Wed, 24 Sep 2025 15:26:42 -0400 Subject: [PATCH 3/4] mutex everything --- cmd/goose/main.go | 1 + cmd/goose/main_test.go | 22 ++++++++++++++++++---- cmd/goose/notifications.go | 8 ++------ cmd/goose/systray_interface.go | 10 ++++++++++ cmd/goose/ui.go | 4 ++++ 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/cmd/goose/main.go b/cmd/goose/main.go index fd71c5d..2ac9dbd 100644 --- a/cmd/goose/main.go +++ b/cmd/goose/main.go @@ -91,6 +91,7 @@ type App struct { updateInterval time.Duration consecutiveFailures int mu sync.RWMutex + menuMutex sync.Mutex // Mutex to prevent concurrent menu rebuilds enableAutoBrowser bool hideStaleIncoming bool hasPerformedInitialDiscovery bool // Track if we've done the first poll to distinguish from real state changes diff --git a/cmd/goose/main_test.go b/cmd/goose/main_test.go index 04d332d..5713df3 100644 --- a/cmd/goose/main_test.go +++ b/cmd/goose/main_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "runtime" "sync" "testing" "time" @@ -196,8 +197,15 @@ func TestTrayIconRestoredAfterNetworkRecovery(t *testing.T) { } app.setTrayTitle() initialTitle := mock.title - if initialTitle != "🪿 1" { - t.Errorf("Expected initial tray title '🪿 1', got %q", initialTitle) + + // Expected title varies by platform + expectedTitle := "1/1" // Linux format + if runtime.GOOS == "darwin" { + expectedTitle = "1" // macOS format + } + + if initialTitle != expectedTitle { + t.Errorf("Expected initial tray title %q, got %q", expectedTitle, initialTitle) } // Simulate network failure - updatePRs would set warning icon and return early @@ -213,8 +221,8 @@ func TestTrayIconRestoredAfterNetworkRecovery(t *testing.T) { // With our fix, setTrayTitle() is now called after successful fetch app.setTrayTitle() recoveredTitle := mock.title - if recoveredTitle != "🪿 1" { - t.Errorf("Expected tray title to be restored to '🪿 1' after recovery, got %q", recoveredTitle) + if recoveredTitle != expectedTitle { + t.Errorf("Expected tray title to be restored to %q after recovery, got %q", expectedTitle, recoveredTitle) } } @@ -447,15 +455,19 @@ func TestSoundPlaybackDuringTransitions(t *testing.T) { // Actual sound playback is verified through integration testing. // Set initial state + app.mu.Lock() app.incoming = tt.initialIncoming app.outgoing = tt.initialOutgoing + app.mu.Unlock() // Run first check to establish baseline app.checkForNewlyBlockedPRs(ctx) // Update to new state + app.mu.Lock() app.incoming = tt.updatedIncoming app.outgoing = tt.updatedOutgoing + app.mu.Unlock() // Run check again to detect transitions app.checkForNewlyBlockedPRs(ctx) @@ -465,6 +477,7 @@ func TestSoundPlaybackDuringTransitions(t *testing.T) { if len(tt.expectedSounds) > 0 { // Check that blocked PRs are tracked in previousBlockedPRs blocked := 0 + app.mu.RLock() for _, pr := range app.incoming { if pr.NeedsReview && app.previousBlockedPRs[pr.URL] { blocked++ @@ -475,6 +488,7 @@ func TestSoundPlaybackDuringTransitions(t *testing.T) { blocked++ } } + app.mu.RUnlock() if blocked == 0 { t.Errorf("%s: expected blocked PRs to be tracked in previousBlockedPRs", tt.description) } diff --git a/cmd/goose/notifications.go b/cmd/goose/notifications.go index 230530b..caa2c7a 100644 --- a/cmd/goose/notifications.go +++ b/cmd/goose/notifications.go @@ -90,14 +90,10 @@ func (app *App) processNotifications(ctx context.Context) { } } - // Update menu if we sent notifications - if len(toNotify) > 0 { - slog.Debug("[NOTIFY] Updating menu after notifications") - app.updateMenu(ctx) - } }() - // Update menu if we sent notifications + // Update menu immediately after sending notifications + // This needs to happen in the main thread to show the party popper emoji if len(toNotify) > 0 { slog.Info("[FLOW] Updating menu after sending notifications", "notified_count", len(toNotify)) app.updateMenu(ctx) diff --git a/cmd/goose/systray_interface.go b/cmd/goose/systray_interface.go index cd7638f..edc1223 100644 --- a/cmd/goose/systray_interface.go +++ b/cmd/goose/systray_interface.go @@ -2,6 +2,7 @@ package main import ( "log/slog" + "sync" "github.com/energye/systray" ) @@ -54,15 +55,20 @@ func (*RealSystray) Quit() { // MockSystray implements SystrayInterface for testing. type MockSystray struct { + mu sync.Mutex title string menuItems []string } func (m *MockSystray) ResetMenu() { + m.mu.Lock() + defer m.mu.Unlock() m.menuItems = nil } func (m *MockSystray) AddMenuItem(title, tooltip string) MenuItem { + m.mu.Lock() + defer m.mu.Unlock() m.menuItems = append(m.menuItems, title) // Return a MockMenuItem that won't panic when methods are called return &MockMenuItem{ @@ -72,10 +78,14 @@ func (m *MockSystray) AddMenuItem(title, tooltip string) MenuItem { } func (m *MockSystray) AddSeparator() { + m.mu.Lock() + defer m.mu.Unlock() m.menuItems = append(m.menuItems, "---") } func (m *MockSystray) SetTitle(title string) { + m.mu.Lock() + defer m.mu.Unlock() m.title = title } diff --git a/cmd/goose/ui.go b/cmd/goose/ui.go index ab32213..bf30676 100644 --- a/cmd/goose/ui.go +++ b/cmd/goose/ui.go @@ -555,6 +555,10 @@ func (app *App) generatePRSectionTitles(prs []PR, sectionTitle string, hiddenOrg // rebuildMenu completely rebuilds the menu from scratch. func (app *App) rebuildMenu(ctx context.Context) { + // Prevent concurrent menu rebuilds + app.menuMutex.Lock() + defer app.menuMutex.Unlock() + // Rebuild entire menu slog.Info("[MENU] Starting rebuildMenu", "os", runtime.GOOS) From 436d7554135dadb5701f9ec199b46437398bfece Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Mon, 29 Sep 2025 13:40:35 -0400 Subject: [PATCH 4/4] improve cross-platform behaviors --- cmd/goose/loginitem_darwin.go | 27 ++++----- cmd/goose/main_test.go | 43 +++++++------- cmd/goose/ui.go | 102 +++++++++++----------------------- 3 files changed, 62 insertions(+), 110 deletions(-) diff --git a/cmd/goose/loginitem_darwin.go b/cmd/goose/loginitem_darwin.go index 39d0052..5775c92 100644 --- a/cmd/goose/loginitem_darwin.go +++ b/cmd/goose/loginitem_darwin.go @@ -142,7 +142,7 @@ func appPath() (string, error) { } // addLoginItemUI adds the login item menu option (macOS only). -func addLoginItemUI(ctx context.Context, _ *App) { +func addLoginItemUI(ctx context.Context, app *App) { // Check if we're running from an app bundle execPath, err := os.Executable() if err != nil { @@ -163,12 +163,14 @@ func addLoginItemUI(ctx context.Context, _ *App) { return } - loginItem := systray.AddMenuItem("Start at Login", "Automatically start when you log in") - - // Set initial state + // Add text checkmark for consistency with other menu items + var loginText string if isLoginItem(ctx) { - loginItem.Check() + loginText = "✓ Start at Login" + } else { + loginText = "Start at Login" } + loginItem := systray.AddMenuItem(loginText, "Automatically start when you log in") loginItem.Click(func() { isEnabled := isLoginItem(ctx) @@ -176,20 +178,13 @@ func addLoginItemUI(ctx context.Context, _ *App) { if err := setLoginItem(ctx, newState); err != nil { slog.Error("Failed to set login item", "error", err) - // Revert the UI state on error - if isEnabled { - loginItem.Check() - } else { - loginItem.Uncheck() - } return } // Update UI state - if newState { - loginItem.Check() - } else { - loginItem.Uncheck() - } + slog.Info("[SETTINGS] Start at Login toggled", "enabled", newState) + + // Rebuild menu to update checkmark + app.rebuildMenu(ctx) }) } diff --git a/cmd/goose/main_test.go b/cmd/goose/main_test.go index 5713df3..8e0df14 100644 --- a/cmd/goose/main_test.go +++ b/cmd/goose/main_test.go @@ -199,9 +199,9 @@ func TestTrayIconRestoredAfterNetworkRecovery(t *testing.T) { initialTitle := mock.title // Expected title varies by platform - expectedTitle := "1/1" // Linux format + expectedTitle := "" // Most platforms: icon only, no text if runtime.GOOS == "darwin" { - expectedTitle = "1" // macOS format + expectedTitle = "1" // macOS: show count with icon } if initialTitle != expectedTitle { @@ -250,7 +250,7 @@ func TestTrayTitleUpdates(t *testing.T) { name: "no PRs", incoming: []PR{}, outgoing: []PR{}, - expectedTitle: "😊", + expectedTitle: "", // No count shown when no blocked PRs }, { name: "only incoming blocked", @@ -259,7 +259,7 @@ func TestTrayTitleUpdates(t *testing.T) { {Repository: "test/repo", Number: 2, NeedsReview: true, UpdatedAt: time.Now()}, }, outgoing: []PR{}, - expectedTitle: "🪿 2", + expectedTitle: "2", // macOS format: just the count }, { name: "only outgoing blocked", @@ -269,7 +269,7 @@ func TestTrayTitleUpdates(t *testing.T) { {Repository: "test/repo", Number: 4, IsBlocked: true, UpdatedAt: time.Now()}, {Repository: "test/repo", Number: 5, IsBlocked: true, UpdatedAt: time.Now()}, }, - expectedTitle: "🎉 3", + expectedTitle: "3", // macOS format: just the count }, { name: "both incoming and outgoing blocked", @@ -279,7 +279,7 @@ func TestTrayTitleUpdates(t *testing.T) { outgoing: []PR{ {Repository: "test/repo", Number: 2, IsBlocked: true, UpdatedAt: time.Now()}, }, - expectedTitle: "🪿 1 🎉 1", + expectedTitle: "1 / 1", // macOS format: "incoming / outgoing" }, { name: "mixed blocked and unblocked", @@ -291,7 +291,7 @@ func TestTrayTitleUpdates(t *testing.T) { {Repository: "test/repo", Number: 3, IsBlocked: false, UpdatedAt: time.Now()}, {Repository: "test/repo", Number: 4, IsBlocked: true, UpdatedAt: time.Now()}, }, - expectedTitle: "🪿 1 🎉 1", + expectedTitle: "1 / 1", // macOS format: "incoming / outgoing" }, { name: "hidden org filters out blocked PRs", @@ -301,7 +301,7 @@ func TestTrayTitleUpdates(t *testing.T) { }, outgoing: []PR{}, hiddenOrgs: map[string]bool{"hidden-org": true}, - expectedTitle: "🪿 1", + expectedTitle: "1", // macOS format: just the count }, { name: "stale PRs filtered when hideStaleIncoming is true", @@ -311,7 +311,7 @@ func TestTrayTitleUpdates(t *testing.T) { }, outgoing: []PR{}, hideStaleIncoming: true, - expectedTitle: "🪿 1", + expectedTitle: "1", // macOS format: just the count }, } @@ -322,22 +322,19 @@ func TestTrayTitleUpdates(t *testing.T) { app.hiddenOrgs = tt.hiddenOrgs app.hideStaleIncoming = tt.hideStaleIncoming - // Get the title that would be set - counts := app.countPRs() - var title string - switch { - case counts.IncomingBlocked == 0 && counts.OutgoingBlocked == 0: - title = "😊" - case counts.IncomingBlocked > 0 && counts.OutgoingBlocked > 0: - title = fmt.Sprintf("🪿 %d 🎉 %d", counts.IncomingBlocked, counts.OutgoingBlocked) - case counts.IncomingBlocked > 0: - title = fmt.Sprintf("🪿 %d", counts.IncomingBlocked) - default: - title = fmt.Sprintf("🎉 %d", counts.OutgoingBlocked) + // Call setTrayTitle to get the actual title + app.setTrayTitle() + actualTitle := app.systrayInterface.(*MockSystray).title + + // Adjust expected title based on platform + expectedTitle := tt.expectedTitle + if runtime.GOOS != "darwin" { + // Non-macOS platforms show icon only (no text) + expectedTitle = "" } - if title != tt.expectedTitle { - t.Errorf("Expected tray title %q, got %q", tt.expectedTitle, title) + if actualTitle != expectedTitle { + t.Errorf("Expected tray title %q, got %q", expectedTitle, actualTitle) } }) } diff --git a/cmd/goose/ui.go b/cmd/goose/ui.go index bf30676..909a015 100644 --- a/cmd/goose/ui.go +++ b/cmd/goose/ui.go @@ -194,38 +194,35 @@ func (app *App) setTrayTitle() { var title string var iconType IconType - // On Linux, always show counts if there are any PRs - // This helps since not all desktop environments show the text - if runtime.GOOS == "linux" && (counts.IncomingTotal > 0 || counts.OutgoingTotal > 0) { - // Show blocked/total format for better visibility - if counts.IncomingBlocked > 0 && counts.OutgoingBlocked > 0 { - title = fmt.Sprintf("%d/%d • %d/%d", counts.IncomingBlocked, counts.IncomingTotal, counts.OutgoingBlocked, counts.OutgoingTotal) + // On macOS, show counts with the icon + // On all other platforms (Linux, Windows, FreeBSD, etc), just show the icon + if runtime.GOOS == "darwin" { + // macOS: show counts alongside icon + switch { + case counts.IncomingBlocked == 0 && counts.OutgoingBlocked == 0: + title = "" + iconType = IconSmiling + case counts.IncomingBlocked > 0 && counts.OutgoingBlocked > 0: + title = fmt.Sprintf("%d / %d", counts.IncomingBlocked, counts.OutgoingBlocked) iconType = IconBoth - } else if counts.IncomingBlocked > 0 { - title = fmt.Sprintf("%d/%d", counts.IncomingBlocked, counts.IncomingTotal) + case counts.IncomingBlocked > 0: + title = fmt.Sprintf("%d", counts.IncomingBlocked) iconType = IconGoose - } else if counts.OutgoingBlocked > 0 { - title = fmt.Sprintf("%d/%d", counts.OutgoingBlocked, counts.OutgoingTotal) + default: + title = fmt.Sprintf("%d", counts.OutgoingBlocked) iconType = IconPopper - } else { - // No blocked PRs but there are PRs - title = fmt.Sprintf("0/%d", counts.IncomingTotal+counts.OutgoingTotal) - iconType = IconSmiling } } else { - // Original behavior for other platforms + // All other platforms: icon only, no text + title = "" switch { case counts.IncomingBlocked == 0 && counts.OutgoingBlocked == 0: - title = "" iconType = IconSmiling case counts.IncomingBlocked > 0 && counts.OutgoingBlocked > 0: - title = fmt.Sprintf("%d / %d", counts.IncomingBlocked, counts.OutgoingBlocked) iconType = IconBoth case counts.IncomingBlocked > 0: - title = fmt.Sprintf("%d", counts.IncomingBlocked) iconType = IconGoose default: - title = fmt.Sprintf("%d", counts.OutgoingBlocked) iconType = IconPopper } } @@ -788,7 +785,7 @@ func (app *App) addStaticMenuItems(ctx context.Context) { // Add checkbox items for each org for _, org := range orgs { orgName := org // Capture for closure - // Add text checkmark for Linux + // Add text checkmark for all platforms var orgText string if hiddenOrgs[orgName] { orgText = "✓ " + orgName @@ -797,24 +794,13 @@ func (app *App) addStaticMenuItems(ctx context.Context) { } orgItem := hideOrgsMenu.AddSubMenuItem(orgText, "") - // Check if org is currently hidden (for non-Linux) - if runtime.GOOS != "linux" && hiddenOrgs[orgName] { - orgItem.Check() - } - orgItem.Click(func() { app.mu.Lock() if app.hiddenOrgs[orgName] { delete(app.hiddenOrgs, orgName) - if runtime.GOOS != "linux" { - orgItem.Uncheck() - } slog.Info("[SETTINGS] Unhiding org", "org", orgName) } else { app.hiddenOrgs[orgName] = true - if runtime.GOOS != "linux" { - orgItem.Check() - } slog.Info("[SETTINGS] Hiding org", "org", orgName) } app.mu.Unlock() @@ -822,13 +808,14 @@ func (app *App) addStaticMenuItems(ctx context.Context) { // Save settings app.saveSettings() - // Note: Menu needs manual refresh on Linux to see changes + // Rebuild menu to update checkmarks + app.rebuildMenu(ctx) }) } } // Hide stale PRs - // Add 'Hide stale PRs' option with text checkmark for Linux + // Add 'Hide stale PRs' option with text checkmark for all platforms var hideStaleText string if app.hideStaleIncoming { hideStaleText = "✓ Hide stale PRs (>90 days)" @@ -836,35 +823,26 @@ func (app *App) addStaticMenuItems(ctx context.Context) { hideStaleText = "Hide stale PRs (>90 days)" } hideStaleItem := app.systrayInterface.AddMenuItem(hideStaleText, "") - if runtime.GOOS != "linux" && app.hideStaleIncoming { - hideStaleItem.Check() - } hideStaleItem.Click(func() { app.mu.Lock() app.hideStaleIncoming = !app.hideStaleIncoming hideStale := app.hideStaleIncoming app.mu.Unlock() - if runtime.GOOS != "linux" { - if hideStale { - hideStaleItem.Check() - } else { - hideStaleItem.Uncheck() - } - } - // Save settings to disk app.saveSettings() - // Note: Menu needs manual refresh on Linux to see changes slog.Info("[SETTINGS] Hide stale PRs toggled", "enabled", hideStale) + + // Rebuild menu to update checkmarks + app.rebuildMenu(ctx) }) // Add login item option (macOS only) addLoginItemUI(ctx, app) // Audio cues - // Add 'Audio cues' option with text checkmark for Linux + // Add 'Audio cues' option with text checkmark for all platforms app.mu.RLock() var audioText string if app.enableAudioCues { @@ -872,34 +850,25 @@ func (app *App) addStaticMenuItems(ctx context.Context) { } else { audioText = "Honks enabled" } - enableAudioCues := app.enableAudioCues app.mu.RUnlock() audioItem := app.systrayInterface.AddMenuItem(audioText, "Play sounds for notifications") - if runtime.GOOS != "linux" && enableAudioCues { - audioItem.Check() - } audioItem.Click(func() { app.mu.Lock() app.enableAudioCues = !app.enableAudioCues enabled := app.enableAudioCues app.mu.Unlock() - if runtime.GOOS != "linux" { - if enabled { - audioItem.Check() - } else { - audioItem.Uncheck() - } - } - slog.Info("[SETTINGS] Audio cues toggled", "enabled", enabled) // Save settings to disk app.saveSettings() + + // Rebuild menu to update checkmarks + app.rebuildMenu(ctx) }) // Auto-open blocked PRs in browser - // Add 'Auto-open PRs' option with text checkmark for Linux + // Add 'Auto-open PRs' option with text checkmark for all platforms app.mu.RLock() var autoText string if app.enableAutoBrowser { @@ -907,12 +876,8 @@ func (app *App) addStaticMenuItems(ctx context.Context) { } else { autoText = "Auto-open incoming PRs" } - enableAutoBrowser := app.enableAutoBrowser app.mu.RUnlock() autoOpenItem := app.systrayInterface.AddMenuItem(autoText, "Automatically open newly blocked PRs in browser (rate limited)") - if runtime.GOOS != "linux" && enableAutoBrowser { - autoOpenItem.Check() - } autoOpenItem.Click(func() { app.mu.Lock() app.enableAutoBrowser = !app.enableAutoBrowser @@ -923,18 +888,13 @@ func (app *App) addStaticMenuItems(ctx context.Context) { } app.mu.Unlock() - if runtime.GOOS != "linux" { - if enabled { - autoOpenItem.Check() - } else { - autoOpenItem.Uncheck() - } - } - slog.Info("[SETTINGS] Auto-open blocked PRs toggled", "enabled", enabled) // Save settings to disk app.saveSettings() + + // Rebuild menu to update checkmarks + app.rebuildMenu(ctx) }) // Quit