package ui import ( "fmt" "strconv" "strings" "github.com/rivo/tview" "git.stinnesbeck.com/nils/arr-tui/internal/arr" "git.stinnesbeck.com/nils/arr-tui/internal/radarr" "git.stinnesbeck.com/nils/arr-tui/internal/sonarr" ) // movieLabel is the one-line list entry for a movie. func movieLabel(m radarr.Movie) string { label := tview.Escape(m.Title) if m.Year > 0 { label += fmt.Sprintf(" (%d)", m.Year) } if m.InLibrary() { label += " [green]✓[-]" } return label } // movieDetails renders the detail pane text for a movie. func movieDetails(m radarr.Movie) string { var b strings.Builder title := tview.Escape(m.Title) if m.Year > 0 { title += fmt.Sprintf(" (%d)", m.Year) } fmt.Fprintf(&b, "[::b]%s[::-]\n", title) var facts []string if r := m.Rating(); r > 0 { facts = append(facts, fmt.Sprintf("★ %.1f", r)) } if m.Runtime > 0 { facts = append(facts, fmt.Sprintf("%dh%02dm", m.Runtime/60, m.Runtime%60)) } if len(m.Genres) > 0 { facts = append(facts, tview.Escape(strings.Join(m.Genres, ", "))) } if len(facts) > 0 { b.WriteString(strings.Join(facts, " · ") + "\n") } if m.Studio != "" { fmt.Fprintf(&b, "Studio: %s\n", tview.Escape(m.Studio)) } if m.Status != "" { fmt.Fprintf(&b, "Status: %s\n", tview.Escape(m.Status)) } switch { case m.HasFile: b.WriteString("[green]In library, downloaded[-]\n") 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() } // profileIndex returns the index of the profile named name, or 0. func profileIndex(profiles []arr.QualityProfile, name string) int { for i, p := range profiles { if strings.EqualFold(p.Name, name) { return i } } return 0 } // folderIndex returns the index of the root folder at path, or 0. func folderIndex(folders []arr.RootFolder, path string) int { for i, f := range folders { if strings.TrimRight(f.Path, "/") == strings.TrimRight(path, "/") { return i } } return 0 } func itoa(n int) string { return strconv.Itoa(n) } // seriesLabel is the one-line list entry for a series. func seriesLabel(s sonarr.Series) string { label := tview.Escape(s.Title) if s.Year > 0 { label += fmt.Sprintf(" (%d)", s.Year) } if s.InLibrary() { label += " [green]✓[-]" } return label } // seriesDetails renders the detail pane text for a series. func seriesDetails(s sonarr.Series) string { var b strings.Builder title := tview.Escape(s.Title) if s.Year > 0 { title += fmt.Sprintf(" (%d)", s.Year) } fmt.Fprintf(&b, "[::b]%s[::-]\n", title) var facts []string if s.Ratings.Value > 0 { facts = append(facts, fmt.Sprintf("★ %.1f", s.Ratings.Value)) } if n := s.SeasonCount(); n > 0 { facts = append(facts, fmt.Sprintf("%d season%s", n, plural(n))) } if s.Runtime > 0 { facts = append(facts, fmt.Sprintf("%d min", s.Runtime)) } if len(s.Genres) > 0 { facts = append(facts, tview.Escape(strings.Join(s.Genres, ", "))) } if len(facts) > 0 { b.WriteString(strings.Join(facts, " · ") + "\n") } if s.Network != "" { fmt.Fprintf(&b, "Network: %s\n", tview.Escape(s.Network)) } if s.Status != "" { fmt.Fprintf(&b, "Status: %s\n", tview.Escape(s.Status)) } if s.InLibrary() { st := s.Statistics if st.EpisodeCount > 0 && st.EpisodeFileCount >= st.EpisodeCount { b.WriteString("[green]In library, all episodes downloaded[-]\n") } else { 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() } func plural(n int) string { if n == 1 { return "" } return "s" }