Add SABnzbd client and Downloads view (M4)
SABnzbd client (queue, history, pause/resume, delete, retry) with lenient number decoding and API-key-safe errors. Downloads view polls while visible, shows queue and history, and supports pause, delete (with confirmation) and retry. Add dev/ with pinned Radarr/Sonarr/SABnzbd containers wired together for manual testing. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
|
||||
@@ -149,3 +150,47 @@ func plural(n int) string {
|
||||
}
|
||||
return "s"
|
||||
}
|
||||
|
||||
// formatSpeed renders a transfer rate given in KiB/s.
|
||||
func formatSpeed(kbPerSec float64) string {
|
||||
switch {
|
||||
case kbPerSec >= 1024:
|
||||
return fmt.Sprintf("%.1f MB/s", kbPerSec/1024)
|
||||
case kbPerSec >= 1:
|
||||
return fmt.Sprintf("%.0f KB/s", kbPerSec)
|
||||
}
|
||||
return "0 KB/s"
|
||||
}
|
||||
|
||||
// progressBar renders pct (0-100) as a bar of the given width, followed by the percentage.
|
||||
func progressBar(pct float64, width int) string {
|
||||
pct = min(max(pct, 0), 100)
|
||||
filled := int(pct / 100 * float64(width))
|
||||
return strings.Repeat("█", filled) + strings.Repeat("░", width-filled) + fmt.Sprintf(" %3.0f%%", pct)
|
||||
}
|
||||
|
||||
// formatAge renders a unix timestamp relative to now ("5m ago", "3d ago").
|
||||
func formatAge(unix int64, now time.Time) string {
|
||||
if unix <= 0 {
|
||||
return ""
|
||||
}
|
||||
d := now.Sub(time.Unix(unix, 0))
|
||||
switch {
|
||||
case d < time.Minute:
|
||||
return "just now"
|
||||
case d < time.Hour:
|
||||
return fmt.Sprintf("%dm ago", int(d.Minutes()))
|
||||
case d < 48*time.Hour:
|
||||
return fmt.Sprintf("%dh ago", int(d.Hours()))
|
||||
}
|
||||
return fmt.Sprintf("%dd ago", int(d.Hours()/24))
|
||||
}
|
||||
|
||||
// truncate shortens s to at most n runes, ending in "…" if it was cut.
|
||||
func truncate(s string, n int) string {
|
||||
r := []rune(s)
|
||||
if len(r) <= n {
|
||||
return s
|
||||
}
|
||||
return string(r[:n-1]) + "…"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user