@@ -51,6 +51,7 @@ const (
5151type PR struct {
5252 UpdatedAt time.Time
5353 TurnDataAppliedAt time.Time
54+ FirstBlockedAt time.Time // When this PR was first detected as blocked
5455 Title string
5556 URL string
5657 Repository string
@@ -72,29 +73,30 @@ type TurnResult struct {
7273// App holds the application state.
7374type App struct {
7475 lastSuccessfulFetch time.Time
76+ startTime time.Time
7577 client * github.Client
7678 turnClient * turn.Client
7779 currentUser * github.User
7880 previousBlockedPRs map [string ]bool
81+ blockedPRTimes map [string ]time.Time
82+ browserRateLimiter * BrowserRateLimiter
7983 targetUser string
8084 cacheDir string
8185 authError string
86+ pendingTurnResults []TurnResult
87+ lastMenuTitles []string
8288 incoming []PR
8389 outgoing []PR
84- lastMenuTitles []string
85- pendingTurnResults []TurnResult
8690 updateInterval time.Duration
8791 consecutiveFailures int
8892 mu sync.RWMutex
89- noCache bool
90- hideStaleIncoming bool
9193 loadingTurnData bool
9294 menuInitialized bool
9395 initialLoadComplete bool
9496 enableAudioCues bool
9597 enableAutoBrowser bool
96- browserRateLimiter * BrowserRateLimiter
97- startTime time. Time
98+ hideStaleIncoming bool
99+ noCache bool
98100}
99101
100102func loadCurrentUser (ctx context.Context , app * App ) {
@@ -208,6 +210,7 @@ func main() {
208210 cacheDir : cacheDir ,
209211 hideStaleIncoming : true ,
210212 previousBlockedPRs : make (map [string ]bool ),
213+ blockedPRTimes : make (map [string ]time.Time ),
211214 targetUser : targetUser ,
212215 noCache : noCache ,
213216 updateInterval : updateInterval ,
@@ -557,6 +560,7 @@ func (app *App) notifyWithSound(ctx context.Context, pr PR, isIncoming bool, pla
557560
558561 // Play sound only once per refresh cycle
559562 if ! * playedSound {
563+ log .Printf ("[SOUND] Playing %s sound for PR: %s #%d - %s" , soundType , pr .Repository , pr .Number , pr .Title )
560564 app .playSound (ctx , soundType )
561565 * playedSound = true
562566 }
@@ -568,22 +572,43 @@ func (app *App) checkForNewlyBlockedPRs(ctx context.Context) {
568572 incoming := app .incoming
569573 outgoing := app .outgoing
570574 previousBlocked := app .previousBlockedPRs
575+ blockedTimes := app .blockedPRTimes
571576 autoBrowserEnabled := app .enableAutoBrowser
572577 startTime := app .startTime
578+ hideStaleIncoming := app .hideStaleIncoming
573579 app .mu .RUnlock ()
574580
575581 currentBlocked := make (map [string ]bool )
582+ newBlockedTimes := make (map [string ]time.Time )
576583 playedHonk := false
577584 playedJet := false
585+ now := time .Now ()
586+ staleThreshold := now .Add (- stalePRThreshold )
578587
579588 // Check incoming PRs
580589 for i := range incoming {
581590 if incoming [i ].NeedsReview {
582591 currentBlocked [incoming [i ].URL ] = true
583- // Notify if newly blocked
584- if ! previousBlocked [incoming [i ].URL ] {
585- app .notifyWithSound (ctx , incoming [i ], true , & playedHonk )
586- app .tryAutoOpenPR (ctx , incoming [i ], autoBrowserEnabled , startTime )
592+ // Track when first blocked
593+ if blockedTime , exists := blockedTimes [incoming [i ].URL ]; exists {
594+ newBlockedTimes [incoming [i ].URL ] = blockedTime
595+ incoming [i ].FirstBlockedAt = blockedTime
596+ } else if ! previousBlocked [incoming [i ].URL ] {
597+ // Newly blocked PR
598+ newBlockedTimes [incoming [i ].URL ] = now
599+ incoming [i ].FirstBlockedAt = now
600+
601+ // Skip sound and auto-open for stale PRs when hideStaleIncoming is enabled
602+ isStale := incoming [i ].UpdatedAt .Before (staleThreshold )
603+ if hideStaleIncoming && isStale {
604+ log .Printf ("[BLOCKED] New incoming PR blocked (stale, skipping): %s #%d - %s" ,
605+ incoming [i ].Repository , incoming [i ].Number , incoming [i ].Title )
606+ } else {
607+ log .Printf ("[BLOCKED] New incoming PR blocked: %s #%d - %s" ,
608+ incoming [i ].Repository , incoming [i ].Number , incoming [i ].Title )
609+ app .notifyWithSound (ctx , incoming [i ], true , & playedHonk )
610+ app .tryAutoOpenPR (ctx , incoming [i ], autoBrowserEnabled , startTime )
611+ }
587612 }
588613 }
589614 }
@@ -592,19 +617,39 @@ func (app *App) checkForNewlyBlockedPRs(ctx context.Context) {
592617 for i := range outgoing {
593618 if outgoing [i ].IsBlocked {
594619 currentBlocked [outgoing [i ].URL ] = true
595- // Notify if newly blocked
596- if ! previousBlocked [outgoing [i ].URL ] {
597- // Add delay if we already played honk sound
598- if playedHonk && ! playedJet {
599- time .Sleep (2 * time .Second )
620+ // Track when first blocked
621+ if blockedTime , exists := blockedTimes [outgoing [i ].URL ]; exists {
622+ newBlockedTimes [outgoing [i ].URL ] = blockedTime
623+ outgoing [i ].FirstBlockedAt = blockedTime
624+ } else if ! previousBlocked [outgoing [i ].URL ] {
625+ // Newly blocked PR
626+ newBlockedTimes [outgoing [i ].URL ] = now
627+ outgoing [i ].FirstBlockedAt = now
628+
629+ // Skip sound and auto-open for stale PRs when hideStaleIncoming is enabled
630+ isStale := outgoing [i ].UpdatedAt .Before (staleThreshold )
631+ if hideStaleIncoming && isStale {
632+ log .Printf ("[BLOCKED] New outgoing PR blocked (stale, skipping): %s #%d - %s" ,
633+ outgoing [i ].Repository , outgoing [i ].Number , outgoing [i ].Title )
634+ } else {
635+ // Add delay if we already played honk sound
636+ if playedHonk && ! playedJet {
637+ time .Sleep (2 * time .Second )
638+ }
639+ log .Printf ("[BLOCKED] New outgoing PR blocked: %s #%d - %s" ,
640+ outgoing [i ].Repository , outgoing [i ].Number , outgoing [i ].Title )
641+ app .notifyWithSound (ctx , outgoing [i ], false , & playedJet )
642+ app .tryAutoOpenPR (ctx , outgoing [i ], autoBrowserEnabled , startTime )
600643 }
601- app .notifyWithSound (ctx , outgoing [i ], false , & playedJet )
602- app .tryAutoOpenPR (ctx , outgoing [i ], autoBrowserEnabled , startTime )
603644 }
604645 }
605646 }
606647
607648 app .mu .Lock ()
608649 app .previousBlockedPRs = currentBlocked
650+ app .blockedPRTimes = newBlockedTimes
651+ // Update the PR lists with FirstBlockedAt times
652+ app .incoming = incoming
653+ app .outgoing = outgoing
609654 app .mu .Unlock ()
610655}
0 commit comments