Config: pick the default quality profile and root folder from the server
The two defaults of Radarr and Sonarr are dropdowns filled from the server with the address and key in the fields: when the view opens, on Revert, and shortly after either is changed. A configured value the server does not list stays selectable, marked "(not on the server)". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019reK4DUGYqDUjniWYJvwUW
This commit is contained in:
+56
-18
@@ -120,17 +120,23 @@ type settingsView struct {
|
||||
groups []*tview.Form // keyboard order: the fields, then the buttons
|
||||
status *tview.TextView
|
||||
|
||||
inputs map[string]*tview.InputField // by setting key, e.g. "radarr.url"
|
||||
refresh *tview.InputField
|
||||
covers *tview.Checkbox
|
||||
style *tview.DropDown
|
||||
theme *tview.DropDown
|
||||
notify *tview.Checkbox
|
||||
bell *tview.Checkbox
|
||||
showKeys *tview.Checkbox
|
||||
overridden map[string]string
|
||||
dirty bool
|
||||
filling bool // set while the fields are filled, so that does not count as an edit
|
||||
inputs map[string]*tview.InputField // by setting key, e.g. "radarr.url"
|
||||
choices map[string]*serverChoice // "radarr.profile", "radarr.folder", ...
|
||||
|
||||
// Loading the choices from the servers, per service.
|
||||
choiceTimers map[string]*time.Timer
|
||||
choiceGen map[string]int
|
||||
choiceErr map[string]string // last error reported, so it is not repeated
|
||||
refresh *tview.InputField
|
||||
covers *tview.Checkbox
|
||||
style *tview.DropDown
|
||||
theme *tview.DropDown
|
||||
notify *tview.Checkbox
|
||||
bell *tview.Checkbox
|
||||
showKeys *tview.Checkbox
|
||||
overridden map[string]string
|
||||
dirty bool
|
||||
filling bool // set while the fields are filled, so that does not count as an edit
|
||||
}
|
||||
|
||||
func settingsHints() string {
|
||||
@@ -138,7 +144,13 @@ func settingsHints() string {
|
||||
}
|
||||
|
||||
func newSettingsView(app *App) *settingsView {
|
||||
v := &settingsView{app: app, inputs: map[string]*tview.InputField{}, overridden: config.Overrides(os.Getenv)}
|
||||
v := &settingsView{app: app, inputs: map[string]*tview.InputField{}, overridden: config.Overrides(os.Getenv),
|
||||
choices: map[string]*serverChoice{}, choiceTimers: map[string]*time.Timer{}, choiceGen: map[string]int{}, choiceErr: map[string]string{}}
|
||||
quiet := func() func() {
|
||||
was := v.filling
|
||||
v.filling = true
|
||||
return func() { v.filling = was }
|
||||
}
|
||||
|
||||
// One form with every field below the other: ↑↓ moves through all of them
|
||||
// and the form scrolls to keep the focused field in view.
|
||||
@@ -156,17 +168,28 @@ func newSettingsView(app *App) *settingsView {
|
||||
in.SetLabel(label + " (env)")
|
||||
in.SetDisabled(true)
|
||||
}
|
||||
in.SetChangedFunc(func(string) { v.edited() })
|
||||
in.SetChangedFunc(func(string) {
|
||||
v.edited()
|
||||
// New address or key: ask that server for its profiles and folders.
|
||||
if service, field, _ := strings.Cut(key, "."); service != "sabnzbd" && !v.filling && (field == "url" || field == "apikey") {
|
||||
v.scheduleChoices(service)
|
||||
}
|
||||
})
|
||||
f.AddFormItem(in)
|
||||
v.inputs[key] = in
|
||||
}
|
||||
choice := func(label, key string) {
|
||||
c := newServerChoice(label, quiet, v.edited)
|
||||
f.AddFormItem(c)
|
||||
v.choices[key] = c
|
||||
}
|
||||
service := func(title, name string, withDefaults bool) {
|
||||
f.AddFormItem(newFormHeading(title))
|
||||
input("Address", name+".url")
|
||||
input("API key", name+".apikey")
|
||||
if withDefaults {
|
||||
input("Default quality profile", name+".profile")
|
||||
input("Default root folder", name+".folder")
|
||||
choice("Default quality profile", name+".profile")
|
||||
choice("Default root folder", name+".folder")
|
||||
}
|
||||
}
|
||||
service("Radarr", "radarr", true)
|
||||
@@ -290,13 +313,19 @@ func (v *settingsView) fill(s settingsValues) {
|
||||
v.filling = true
|
||||
defer func() { v.filling = false }()
|
||||
set := map[string]string{
|
||||
"radarr.url": s.radarrURL, "radarr.apikey": s.radarrKey, "radarr.profile": s.radarrProfile, "radarr.folder": s.radarrFolder,
|
||||
"sonarr.url": s.sonarrURL, "sonarr.apikey": s.sonarrKey, "sonarr.profile": s.sonarrProfile, "sonarr.folder": s.sonarrFolder,
|
||||
"radarr.url": s.radarrURL, "radarr.apikey": s.radarrKey,
|
||||
"sonarr.url": s.sonarrURL, "sonarr.apikey": s.sonarrKey,
|
||||
"sabnzbd.url": s.sabURL, "sabnzbd.apikey": s.sabKey,
|
||||
}
|
||||
for key, value := range set {
|
||||
v.inputs[key].SetText(value)
|
||||
}
|
||||
for key, value := range map[string]string{
|
||||
"radarr.profile": s.radarrProfile, "radarr.folder": s.radarrFolder,
|
||||
"sonarr.profile": s.sonarrProfile, "sonarr.folder": s.sonarrFolder,
|
||||
} {
|
||||
v.choices[key].set(value)
|
||||
}
|
||||
v.refresh.SetText(s.refresh)
|
||||
v.covers.SetChecked(s.covers)
|
||||
for i, name := range coverStyles {
|
||||
@@ -316,7 +345,12 @@ func (v *settingsView) fill(s settingsValues) {
|
||||
|
||||
// read collects the values from the fields.
|
||||
func (v *settingsView) read() settingsValues {
|
||||
text := func(key string) string { return v.inputs[key].GetText() }
|
||||
text := func(key string) string {
|
||||
if c, ok := v.choices[key]; ok {
|
||||
return c.value
|
||||
}
|
||||
return v.inputs[key].GetText()
|
||||
}
|
||||
i, _ := v.style.GetCurrentOption()
|
||||
style := "auto"
|
||||
if i >= 0 && i < len(coverStyles) {
|
||||
@@ -363,6 +397,8 @@ func (v *settingsView) activate() {
|
||||
if !v.dirty {
|
||||
v.fill(settingsFrom(v.app.cfg))
|
||||
}
|
||||
v.loadChoices("radarr")
|
||||
v.loadChoices("sonarr")
|
||||
v.focusGroup(0, false)
|
||||
}
|
||||
|
||||
@@ -374,6 +410,8 @@ func (v *settingsView) report(line string) {
|
||||
|
||||
func (v *settingsView) revert() {
|
||||
v.fill(settingsFrom(v.app.cfg))
|
||||
v.loadChoices("radarr")
|
||||
v.loadChoices("sonarr")
|
||||
v.describe()
|
||||
v.report("[green]Reverted to the saved settings.[-]")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user