Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 3 additions & 12 deletions github.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,9 @@ func (*App) githubToken(ctx context.Context) (string, error) {
return token, nil
}

// fetchPRs retrieves all PRs involving the current user.
// It returns GitHub data immediately and starts Turn API queries in the background.
func (app *App) fetchPRs(ctx context.Context) (incoming []PR, outgoing []PR, err error) {
return app.fetchPRsInternal(ctx, false)
}

// fetchPRsWithWait fetches PRs and waits for Turn data to complete.
func (app *App) fetchPRsWithWait(ctx context.Context) (incoming []PR, outgoing []PR, err error) {
return app.fetchPRsInternal(ctx, true)
}

// fetchPRsInternal is the common implementation for PR fetching.
// fetchPRsInternal is the implementation for PR fetching.
// It returns GitHub data immediately and starts Turn API queries in the background (when waitForTurn=false),
// or waits for Turn data to complete (when waitForTurn=true).
func (app *App) fetchPRsInternal(ctx context.Context, waitForTurn bool) (incoming []PR, outgoing []PR, err error) {
// Use targetUser if specified, otherwise use authenticated user
user := app.currentUser.GetLogin()
Expand Down
14 changes: 10 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ func (app *App) updateLoop(ctx context.Context) {
}

func (app *App) updatePRs(ctx context.Context) {
incoming, outgoing, err := app.fetchPRs(ctx)
incoming, outgoing, err := app.fetchPRsInternal(ctx, false)
if err != nil {
log.Printf("Error fetching PRs: %v", err)
app.mu.Lock()
Expand Down Expand Up @@ -531,7 +531,7 @@ func (app *App) updateMenuIfChanged(ctx context.Context) {

// updatePRsWithWait fetches PRs and waits for Turn data before building initial menu.
func (app *App) updatePRsWithWait(ctx context.Context) {
incoming, outgoing, err := app.fetchPRsWithWait(ctx)
incoming, outgoing, err := app.fetchPRsInternal(ctx, true)
if err != nil {
log.Printf("Error fetching PRs: %v", err)
app.mu.Lock()
Expand Down Expand Up @@ -566,7 +566,10 @@ func (app *App) updatePRsWithWait(ctx context.Context) {
// Still create initial menu even on error
if !app.menuInitialized {
log.Println("Creating initial menu despite error")
app.initializeMenu(ctx)
log.Print("[MENU] Initializing menu structure")
app.rebuildMenu(ctx)
app.menuInitialized = true
log.Print("[MENU] Menu initialization complete")
}
return
}
Expand Down Expand Up @@ -645,7 +648,10 @@ func (app *App) updatePRsWithWait(ctx context.Context) {
// Create initial menu after first successful data load
if !app.menuInitialized {
log.Println("Creating initial menu with Turn data")
app.initializeMenu(ctx)
log.Print("[MENU] Initializing menu structure")
app.rebuildMenu(ctx)
app.menuInitialized = true
log.Print("[MENU] Menu initialization complete")
} else {
app.updateMenuIfChanged(ctx)
}
Expand Down
57 changes: 28 additions & 29 deletions ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,16 @@ func openURL(ctx context.Context, rawURL string) error {
return nil
}

// PRCounts represents PR count information.
type PRCounts struct {
IncomingTotal int
IncomingBlocked int
OutgoingTotal int
OutgoingBlocked int
}

// countPRs counts the number of PRs that need review/are blocked.
// Returns: incomingCount, incomingBlocked, outgoingCount, outgoingBlocked
//
//nolint:revive,gocritic // 4 return values is clearer than a struct here
func (app *App) countPRs() (int, int, int, int) {
func (app *App) countPRs() PRCounts {
app.mu.RLock()
defer app.mu.RUnlock()

Expand All @@ -122,23 +127,28 @@ func (app *App) countPRs() (int, int, int, int) {
}
}
}
return incomingCount, incomingBlocked, outgoingCount, outgoingBlocked
return PRCounts{
IncomingTotal: incomingCount,
IncomingBlocked: incomingBlocked,
OutgoingTotal: outgoingCount,
OutgoingBlocked: outgoingBlocked,
}
}

// setTrayTitle updates the system tray title based on PR counts.
func (app *App) setTrayTitle() {
_, incomingBlocked, _, outgoingBlocked := app.countPRs()
counts := app.countPRs()

// Set title based on PR state
switch {
case incomingBlocked == 0 && outgoingBlocked == 0:
case counts.IncomingBlocked == 0 && counts.OutgoingBlocked == 0:
systray.SetTitle("😊")
case incomingBlocked > 0 && outgoingBlocked > 0:
systray.SetTitle(fmt.Sprintf("👀 %d 🎉 %d", incomingBlocked, outgoingBlocked))
case incomingBlocked > 0:
systray.SetTitle(fmt.Sprintf("👀 %d", incomingBlocked))
case counts.IncomingBlocked > 0 && counts.OutgoingBlocked > 0:
systray.SetTitle(fmt.Sprintf("👀 %d 🎉 %d", counts.IncomingBlocked, counts.OutgoingBlocked))
case counts.IncomingBlocked > 0:
systray.SetTitle(fmt.Sprintf("👀 %d", counts.IncomingBlocked))
default:
systray.SetTitle(fmt.Sprintf("🎉 %d", outgoingBlocked))
systray.SetTitle(fmt.Sprintf("🎉 %d", counts.OutgoingBlocked))
}
}

Expand Down Expand Up @@ -213,17 +223,6 @@ func (app *App) addPRSection(ctx context.Context, prs []PR, sectionTitle string,
}
}

// initializeMenu creates the initial menu structure.
func (app *App) initializeMenu(ctx context.Context) {
log.Print("[MENU] Initializing menu structure")

// Build the entire menu
app.rebuildMenu(ctx)

app.menuInitialized = true
log.Print("[MENU] Menu initialization complete")
}

// rebuildMenu completely rebuilds the menu from scratch.
func (app *App) rebuildMenu(ctx context.Context) {
log.Print("[MENU] Rebuilding entire menu")
Expand All @@ -246,30 +245,30 @@ func (app *App) rebuildMenu(ctx context.Context) {
systray.AddSeparator()

// Get PR counts
incomingCount, incomingBlocked, outgoingCount, outgoingBlocked := app.countPRs()
counts := app.countPRs()

// Handle "No pull requests" case
if incomingCount == 0 && outgoingCount == 0 {
if counts.IncomingTotal == 0 && counts.OutgoingTotal == 0 {
log.Print("[MENU] Creating 'No pull requests' item")
noPRs := systray.AddMenuItem("No pull requests", "")
noPRs.Disable()
} else {
// Incoming section
if incomingCount > 0 {
if counts.IncomingTotal > 0 {
app.mu.RLock()
incoming := app.incoming
app.mu.RUnlock()
app.addPRSection(ctx, incoming, "Incoming", incomingBlocked)
app.addPRSection(ctx, incoming, "Incoming", counts.IncomingBlocked)
}

systray.AddSeparator()

// Outgoing section
if outgoingCount > 0 {
if counts.OutgoingTotal > 0 {
app.mu.RLock()
outgoing := app.outgoing
app.mu.RUnlock()
app.addPRSection(ctx, outgoing, "Outgoing", outgoingBlocked)
app.addPRSection(ctx, outgoing, "Outgoing", counts.OutgoingBlocked)
}
}

Expand Down