Add Sonarr client and series search/add flow (M3)
Sonarr client with lookup, add series (monitor modes) and search. Refactor the movie view into a generic search view driven by a backend interface so Movies and Series share one implementation. Add F1-F4 / Alt+1-4 view switching that works while typing. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
+27
-3
@@ -8,6 +8,8 @@ import (
|
||||
"github.com/rivo/tview"
|
||||
|
||||
"git.stinnesbeck.com/nils/arr-tui/internal/config"
|
||||
"git.stinnesbeck.com/nils/arr-tui/internal/radarr"
|
||||
"git.stinnesbeck.com/nils/arr-tui/internal/sonarr"
|
||||
)
|
||||
|
||||
const modalPage = "modal"
|
||||
@@ -42,8 +44,8 @@ func New(cfg *config.Config) *App {
|
||||
}
|
||||
|
||||
a.views = []view{
|
||||
{'1', "Movies", newMoviesView(a, cfg.Radarr).root},
|
||||
{'2', "Series", placeholder("Series search (M3)")},
|
||||
{'1', "Movies", newSearchView(a, radarrBackend{radarr.NewClient(cfg.Radarr.URL, cfg.Radarr.APIKey)}, cfg.Radarr).root},
|
||||
{'2', "Series", newSearchView(a, sonarrBackend{sonarr.NewClient(cfg.Sonarr.URL, cfg.Sonarr.APIKey)}, cfg.Sonarr).root},
|
||||
{'3', "Downloads", placeholder("Downloads (M4/M5)")},
|
||||
{'4', "Library", placeholder("Library (v0.2)")},
|
||||
}
|
||||
@@ -81,7 +83,7 @@ func (a *App) Run() error {
|
||||
}
|
||||
|
||||
func (a *App) renderStatus() {
|
||||
hints := "[gray]q quit · Tab/1-4 views"
|
||||
hints := "[gray]q quit · Tab/1-4/F1-F4 views · / search"
|
||||
if a.message == "" {
|
||||
a.status.SetText(hints)
|
||||
return
|
||||
@@ -128,6 +130,13 @@ func (a *App) handleKey(ev *tcell.EventKey) *tcell.EventKey {
|
||||
a.app.Stop()
|
||||
return nil
|
||||
}
|
||||
// View switching that also works while typing in a search box. Not while a dialog is open.
|
||||
if !a.modalOpen {
|
||||
if i := a.viewShortcut(ev); i >= 0 && i < len(a.views) {
|
||||
a.switchTo(i)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if a.typing() {
|
||||
return ev
|
||||
}
|
||||
@@ -153,6 +162,21 @@ func (a *App) handleKey(ev *tcell.EventKey) *tcell.EventKey {
|
||||
return ev
|
||||
}
|
||||
|
||||
// viewShortcut returns the view index for F1-F4 or Alt+1-4, or -1.
|
||||
func (a *App) viewShortcut(ev *tcell.EventKey) int {
|
||||
if ev.Key() >= tcell.KeyF1 && ev.Key() <= tcell.KeyF12 {
|
||||
return int(ev.Key() - tcell.KeyF1)
|
||||
}
|
||||
if ev.Key() == tcell.KeyRune && ev.Modifiers()&tcell.ModAlt != 0 {
|
||||
for i, v := range a.views {
|
||||
if ev.Rune() == v.key {
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (a *App) switchTo(i int) {
|
||||
a.active = i
|
||||
a.pages.SwitchToPage(a.views[i].name)
|
||||
|
||||
Reference in New Issue
Block a user