Detail panes: poster top right, title and facts left, plot below; sextant rendering

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-20 21:57:22 +02:00
co-authored by Claude Sonnet 5.5
parent 365ba9dee8
commit b4fe931fa9
15 changed files with 468 additions and 153 deletions
+18 -10
View File
@@ -25,8 +25,22 @@ func movieLabel(m radarr.Movie) string {
return label
}
// detailText is the text of a detail pane: a short head (title, facts,
// state) and the plot below it.
type detailText struct {
head, plot string
}
// String joins both parts, for places that show them as one text.
func (d detailText) String() string {
if d.plot == "" {
return d.head
}
return d.head + "\n" + d.plot
}
// movieDetails renders the detail pane text for a movie.
func movieDetails(m radarr.Movie) string {
func movieDetails(m radarr.Movie) detailText {
var b strings.Builder
title := tview.Escape(m.Title)
if m.Year > 0 {
@@ -59,10 +73,7 @@ func movieDetails(m radarr.Movie) string {
case m.InLibrary():
b.WriteString("[yellow]In library, not downloaded[-]\n")
}
if m.Overview != "" {
b.WriteString("\n" + tview.Escape(m.Overview) + "\n")
}
return b.String()
return detailText{head: b.String(), plot: tview.Escape(m.Overview)}
}
// profileIndex returns the index of the profile named name, or 0.
@@ -100,7 +111,7 @@ func seriesLabel(s sonarr.Series) string {
}
// seriesDetails renders the detail pane text for a series.
func seriesDetails(s sonarr.Series) string {
func seriesDetails(s sonarr.Series) detailText {
var b strings.Builder
title := tview.Escape(s.Title)
if s.Year > 0 {
@@ -138,10 +149,7 @@ func seriesDetails(s sonarr.Series) string {
fmt.Fprintf(&b, "[yellow]In library, %d/%d episodes downloaded[-]\n", st.EpisodeFileCount, st.EpisodeCount)
}
}
if s.Overview != "" {
b.WriteString("\n" + tview.Escape(s.Overview) + "\n")
}
return b.String()
return detailText{head: b.String(), plot: tview.Escape(s.Overview)}
}
func plural(n int) string {