1919 styleDim = lipgloss .NewStyle ().Faint (true )
2020 styleWhite = lipgloss .NewStyle ().Foreground (lipgloss .Color ("7" ))
2121
22- selLine = lipgloss .NewStyle (). Bold ( true ).Background (lipgloss .Color ("238" ))
22+ selBg = lipgloss .NewStyle ().Background (lipgloss .Color ("238" ))
2323 helpStyle = lipgloss .NewStyle ().Faint (true )
2424
2525 // Palette of distinguishable ANSI-256 colors for repo/author hashing.
@@ -44,9 +44,10 @@ func nameColor(name string) lipgloss.Style {
4444}
4545
4646type model struct {
47- items []ClassifiedPR
48- cursor int
49- dismissed map [string ]bool
47+ items []ClassifiedPR
48+ cursor int
49+ dismissed map [string ]bool
50+ dismissedRepos map [string ]bool
5051 cols colWidths
5152 width int
5253 height int
@@ -55,8 +56,8 @@ type model struct {
5556 me string
5657 myTeams map [string ]bool
5758
58- showSelf bool
59- showMine bool
59+ showAuthored bool
60+ showAssigned bool
6061 showAuthor bool
6162 sortMode SortMode
6263
@@ -72,8 +73,8 @@ type modelConfig struct {
7273 rawPRs []PRNode
7374 me string
7475 myTeams map [string ]bool
75- showSelf bool
76- showMine bool
76+ showAuthored bool
77+ showAssigned bool
7778 showAuthor bool
7879 sortMode SortMode
7980 loading bool
@@ -135,12 +136,13 @@ func fetchDataCmd(org string, limit int) tea.Cmd {
135136
136137func newModel (cfg modelConfig ) model {
137138 m := model {
138- dismissed : make (map [string ]bool ),
139+ dismissed : make (map [string ]bool ),
140+ dismissedRepos : make (map [string ]bool ),
139141 rawPRs : cfg .rawPRs ,
140142 me : cfg .me ,
141143 myTeams : cfg .myTeams ,
142- showSelf : cfg .showSelf ,
143- showMine : cfg .showMine ,
144+ showAuthored : cfg .showAuthored ,
145+ showAssigned : cfg .showAssigned ,
144146 showAuthor : cfg .showAuthor ,
145147 sortMode : cfg .sortMode ,
146148 loading : cfg .loading ,
@@ -158,13 +160,13 @@ func (m *model) reclassify() {
158160 m .items = classifyAllAuthor (m .rawPRs , m .me , m .sortMode )
159161 } else {
160162 var filter func (PRNode ) bool
161- if m .showMine {
163+ if m .showAssigned {
162164 me , teams := m .me , m .myTeams
163165 filter = func (pr PRNode ) bool {
164166 return isRequestedReviewer (pr , me , teams )
165167 }
166168 }
167- m .items = classifyAll (m .rawPRs , m .me , m .showSelf , filter , m .sortMode )
169+ m .items = classifyAll (m .rawPRs , m .me , m .showAuthored , filter , m .sortMode )
168170 }
169171 m .cols = computeColumns (m .items )
170172}
@@ -227,13 +229,13 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
227229 m .cursor = 0
228230 case "s" :
229231 if ! m .showAuthor {
230- m .showSelf = ! m .showSelf
232+ m .showAuthored = ! m .showAuthored
231233 m .reclassify ()
232234 m .cursor = 0
233235 }
234- case "m " :
236+ case "f " :
235237 if ! m .showAuthor {
236- m .showMine = ! m .showMine
238+ m .showAssigned = ! m .showAssigned
237239 m .reclassify ()
238240 m .cursor = 0
239241 }
@@ -259,6 +261,15 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
259261 m .cursor --
260262 }
261263 }
264+ case "D" :
265+ if pr , ok := m .selectedPR (); ok {
266+ m .dismissedRepos [pr .RepoName ] = true
267+ m .statusMsg = fmt .Sprintf ("Dismissed repo %s" , pr .RepoName )
268+ vis := m .visibleItems ()
269+ if m .cursor >= len (vis ) && m .cursor > 0 {
270+ m .cursor = len (vis ) - 1
271+ }
272+ }
262273 case "c" :
263274 if pr , ok := m .selectedPR (); ok {
264275 m .statusMsg = fmt .Sprintf ("Commenting on %s#%d..." , pr .RepoName , pr .Number )
@@ -293,7 +304,7 @@ func (m model) View() string {
293304 if m .showAuthor {
294305 return "No open PRs authored by you. Press a to switch to reviewer mode.\n "
295306 }
296- return "No PRs match current filters. Press s/m to adjust, or a for author mode.\n "
307+ return "No PRs match current filters. Press s/f to adjust, or a for author mode.\n "
297308 }
298309
299310 var b strings.Builder
@@ -322,7 +333,13 @@ func (m model) View() string {
322333
323334 for i := start ; i < end ; i ++ {
324335 pr := vis [i ]
325- indicators := formatIndicators (pr , m .showAuthor )
336+ selected := i == m .cursor
337+ var bg * lipgloss.Style
338+ if selected {
339+ bg = & selBg
340+ }
341+
342+ indicators := formatIndicators (pr , m .showAuthor , bg )
326343 repoCol := fmt .Sprintf ("%-*s" , m .cols .repo , fmt .Sprintf ("%s#%d" , pr .RepoName , pr .Number ))
327344 authorCol := fmt .Sprintf ("%-*s" , m .cols .author , pr .Author )
328345
@@ -340,16 +357,24 @@ func (m model) View() string {
340357 }
341358 }
342359
343- coloredRepo := nameColor (pr .RepoName ).Render (repoCol )
344- coloredAuthor := nameColor (pr .Author ).Render (authorCol )
345- line := fmt .Sprintf ("%s %s %s %s" , indicators , coloredRepo , coloredAuthor , titleText )
346-
347- if i == m .cursor {
348- style := selLine
360+ var coloredRepo , coloredAuthor , line string
361+ if selected {
362+ coloredRepo = nameColor (pr .RepoName ).Inherit (selBg ).Render (repoCol )
363+ coloredAuthor = nameColor (pr .Author ).Inherit (selBg ).Render (authorCol )
364+ sep := selBg .Render (" " )
365+ titleRendered := selBg .Render (titleText )
366+ line = indicators + selBg .Render (" " ) + coloredRepo + sep + coloredAuthor + sep + titleRendered
367+ // Pad to full width
349368 if m .width > 0 {
350- style = style .Width (m .width )
369+ lineLen := lipgloss .Width (line )
370+ if lineLen < m .width {
371+ line += selBg .Render (strings .Repeat (" " , m .width - lineLen ))
372+ }
351373 }
352- line = style .Render (line )
374+ } else {
375+ coloredRepo = nameColor (pr .RepoName ).Render (repoCol )
376+ coloredAuthor = nameColor (pr .Author ).Render (authorCol )
377+ line = fmt .Sprintf ("%s %s %s %s" , indicators , coloredRepo , coloredAuthor , titleText )
353378 }
354379 b .WriteString (line )
355380 b .WriteString ("\n " )
@@ -368,21 +393,21 @@ func (m model) View() string {
368393 var help string
369394 if m .showAuthor {
370395 help = helpStyle .Render (fmt .Sprintf (
371- "j/k: navigate enter: open d: dismiss c: @claude o: %s a: %s r: refresh ?: legend q: quit" ,
396+ "j/k: navigate enter: open d/D : dismiss PR/repo c: @claude o: %s a: %s r: refresh ?: legend q: quit" ,
372397 sortLabel , authorLabel ,
373398 ))
374399 } else {
375- selfLabel := "self :off"
376- if m .showSelf {
377- selfLabel = "self :on"
400+ authoredLabel := "authored :off"
401+ if m .showAuthored {
402+ authoredLabel = "authored :on"
378403 }
379- mineLabel := "mine :off"
380- if m .showMine {
381- mineLabel = "mine :on"
404+ assignedLabel := "assigned :off"
405+ if m .showAssigned {
406+ assignedLabel = "assigned :on"
382407 }
383408 help = helpStyle .Render (fmt .Sprintf (
384- "j/k: navigate enter: open d: dismiss c: @claude s: %s m : %s o: %s a: %s r: refresh ?: legend q: quit" ,
385- selfLabel , mineLabel , sortLabel , authorLabel ,
409+ "j/k: navigate enter: open d/D : dismiss PR/repo c: @claude s: %s f : %s o: %s a: %s r: refresh ?: legend q: quit" ,
410+ authoredLabel , assignedLabel , sortLabel , authorLabel ,
386411 ))
387412 }
388413 if m .statusMsg != "" {
@@ -422,9 +447,10 @@ func (m model) renderLegend() string {
422447func (m model ) visibleItems () []ClassifiedPR {
423448 var vis []ClassifiedPR
424449 for _ , pr := range m .items {
425- if ! m .dismissed [pr .URL ] {
426- vis = append ( vis , pr )
450+ if m .dismissed [pr .URL ] || m . dismissedRepos [ pr . RepoName ] {
451+ continue
427452 }
453+ vis = append (vis , pr )
428454 }
429455 return vis
430456}
@@ -437,53 +463,64 @@ func (m model) selectedPR() (ClassifiedPR, bool) {
437463 return vis [m .cursor ], true
438464}
439465
440- func formatIndicators (pr ClassifiedPR , authorMode bool ) string {
466+ func withBg (s lipgloss.Style , bg * lipgloss.Style ) lipgloss.Style {
467+ if bg != nil {
468+ return s .Inherit (* bg )
469+ }
470+ return s
471+ }
472+
473+ func formatIndicators (pr ClassifiedPR , authorMode bool , bg * lipgloss.Style ) string {
441474 var col1 , col2 , col3 string
442475
443476 if authorMode {
444477 if pr .IsDraft {
445- col1 = styleDim .Render ("○" )
478+ col1 = withBg ( styleDim , bg ) .Render ("○" )
446479 } else {
447- col1 = styleWhite .Render ("●" )
480+ col1 = withBg ( styleWhite , bg ) .Render ("●" )
448481 }
449482 } else {
450483 switch pr .MyReview {
451484 case MyNone :
452- col1 = styleDim .Render ("·" )
485+ col1 = withBg ( styleDim , bg ) .Render ("·" )
453486 case MyApproved :
454- col1 = styleGreen .Render ("✓" )
487+ col1 = withBg ( styleGreen , bg ) .Render ("✓" )
455488 case MyChanges :
456- col1 = styleRed .Render ("✗" )
489+ col1 = withBg ( styleRed , bg ) .Render ("✗" )
457490 case MyStale :
458- col1 = styleDim .Render ("~" )
491+ col1 = withBg ( styleDim , bg ) .Render ("~" )
459492 default :
460- col1 = styleDim .Render ("·" )
493+ col1 = withBg ( styleDim , bg ) .Render ("·" )
461494 }
462495 }
463496
464497 switch pr .OthReview {
465498 case OthNone :
466- col2 = styleDim .Render ("·" )
499+ col2 = withBg ( styleDim , bg ) .Render ("·" )
467500 case OthApproved :
468- col2 = styleGreen .Render ("✓" )
501+ col2 = withBg ( styleGreen , bg ) .Render ("✓" )
469502 case OthChanges :
470- col2 = styleRed .Render ("✗" )
503+ col2 = withBg ( styleRed , bg ) .Render ("✗" )
471504 case OthMixed :
472- col2 = styleYellow .Render ("±" )
505+ col2 = withBg ( styleYellow , bg ) .Render ("±" )
473506 default :
474- col2 = styleDim .Render ("·" )
507+ col2 = withBg ( styleDim , bg ) .Render ("·" )
475508 }
476509
477510 switch pr .Activity {
478511 case ActNone :
479- col3 = styleDim .Render ("·" )
512+ col3 = withBg ( styleDim , bg ) .Render ("·" )
480513 case ActOthers :
481- col3 = styleWhite .Render ("○" )
514+ col3 = withBg ( styleWhite , bg ) .Render ("○" )
482515 case ActMine :
483- col3 = styleCyan .Render ("●" )
516+ col3 = withBg ( styleCyan , bg ) .Render ("●" )
484517 default :
485- col3 = styleDim .Render ("·" )
518+ col3 = withBg ( styleDim , bg ) .Render ("·" )
486519 }
487520
488- return col1 + " " + col2 + " " + col3
521+ sep := " "
522+ if bg != nil {
523+ sep = bg .Render (" " )
524+ }
525+ return col1 + sep + col2 + sep + col3
489526}
0 commit comments