Movies view with debounced Radarr lookup, detail pane, and an add dialog (quality profile, root folder, monitored, search now). Global shortcuts are suspended while typing or in a dialog. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
84 lines
1.9 KiB
Go
84 lines
1.9 KiB
Go
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/rivo/tview"
|
|
|
|
"git.stinnesbeck.com/nils/arr-tui/internal/arr"
|
|
"git.stinnesbeck.com/nils/arr-tui/internal/radarr"
|
|
)
|
|
|
|
// 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
|
|
}
|