Posters (the downloaded bytes, per size, 30 days, at most 200 MB) and casts (people.json, 7 days, at most 2000) are stored in the user's cache directory (os.UserCacheDir()/arr-tui) and used on the next start before asking the servers. Expired posters are pruned at startup, casts are written shortly after new ones arrive and on exit. Tests turn the cache off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
92 lines
2.8 KiB
Go
92 lines
2.8 KiB
Go
package ui
|
|
|
|
import (
|
|
"os"
|
|
"time"
|
|
|
|
"git.stinnesbeck.com/nils/arr-tui/internal/config"
|
|
)
|
|
|
|
// SetConfigSource tells the app which file the settings came from and what that
|
|
// file contains, so the Config view can save changes. raw is the file as
|
|
// written (see config.LoadFile), not the effective settings.
|
|
func (a *App) SetConfigSource(path string, raw *config.Config) {
|
|
a.cfgPath, a.cfgFile = path, raw
|
|
if a.settings != nil {
|
|
a.settings.describe()
|
|
}
|
|
}
|
|
|
|
// applyConfig puts new settings into effect without a restart.
|
|
func (a *App) applyConfig(c *config.Config) {
|
|
old := a.cfg
|
|
a.cfg = c
|
|
|
|
if old.Radarr.Service != c.Radarr.Service || old.Sonarr.Service != c.Sonarr.Service || old.SABnzbd != c.SABnzbd {
|
|
a.radarr.Reconfigure(c.Radarr.URL, c.Radarr.APIKey)
|
|
a.sonarr.Reconfigure(c.Sonarr.URL, c.Sonarr.APIKey)
|
|
a.sab.Reconfigure(c.SABnzbd.URL, c.SABnzbd.APIKey)
|
|
a.probeAll() // the indicators, right away
|
|
for _, f := range a.reconnect {
|
|
f()
|
|
}
|
|
}
|
|
if old.Trakt.ClientID != c.Trakt.ClientID {
|
|
a.trakt.Reconfigure(c.Trakt.ClientID)
|
|
a.people.failed = map[string]time.Time{} // casts do not depend on the client ID; failures may
|
|
for _, p := range a.panes {
|
|
p.castKey = "" // ask again the next time a title is shown
|
|
}
|
|
}
|
|
if old.Trakt.ClientID != c.Trakt.ClientID || old.Radarr.Service != c.Radarr.Service || old.Sonarr.Service != c.Sonarr.Service {
|
|
for _, v := range a.searches {
|
|
v.forgetLists()
|
|
}
|
|
}
|
|
if old.UI.RefreshSeconds != c.UI.RefreshSeconds {
|
|
a.downloads.setInterval(time.Duration(c.UI.RefreshSeconds) * time.Second)
|
|
}
|
|
a.bell = c.UI.Bell
|
|
if old.UI.Theme != c.UI.Theme {
|
|
a.setTheme(chooseTheme(c.UI.Theme, terminalAnswers()))
|
|
}
|
|
if c.UI.ShouldNotifyDownloads() != a.notifyDone {
|
|
a.setNotifyDownloads(c.UI.ShouldNotifyDownloads())
|
|
}
|
|
if old.UI.ShowCovers() != c.UI.ShowCovers() || old.UI.CoverStyle != c.UI.CoverStyle {
|
|
a.covers = c.UI.ShowCovers()
|
|
a.restyleCovers()
|
|
}
|
|
}
|
|
|
|
// restyleCovers applies a changed poster style or switch to every detail pane.
|
|
func (a *App) restyleCovers() {
|
|
blocks, graphics := resolveCovers(a.cfg.UI.CoverStyle, os.Getenv)
|
|
if a.gfx != nil {
|
|
a.gfx.deleteAll() // the terminal's copies belong to the old images
|
|
}
|
|
a.coverStyle = blocks
|
|
switch {
|
|
case graphics && a.gfx == nil:
|
|
a.gfx = a.newGraphics()
|
|
case !graphics:
|
|
a.gfx = nil
|
|
}
|
|
a.coverCache = newCoverCache() // stored copies depend on the style (their height)
|
|
for _, p := range a.panes {
|
|
p.cover.style, p.cover.gfx = blocks, a.gfx
|
|
p.cover.cells = nil
|
|
p.Show(p.detail, p.lastRef) // fetch the poster again for the new style
|
|
}
|
|
}
|
|
|
|
// forgetPane drops a detail pane that is no longer shown (a closed drill-down).
|
|
func (a *App) forgetPane(d *detailPane) {
|
|
for i, p := range a.panes {
|
|
if p == d {
|
|
a.panes = append(a.panes[:i], a.panes[i+1:]...)
|
|
return
|
|
}
|
|
}
|
|
}
|