Library: keep the place after removing a title
The list is reloaded after a removal and the selection follows the selected title by id; the removed title is gone, so it fell back to the top. Now a title that has left the library hands its row to the one that moved up into it (or the new last one). A title that is only filtered out still starts the list from the top. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019reK4DUGYqDUjniWYJvwUW
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
- **Library:** after removing a title the selection stays at its place (on the title that moved
|
||||
up into it, or the new last one) instead of jumping to the top of the list.
|
||||
- **Config (F6):** the default quality profile and root folder are chosen from the lists Radarr
|
||||
and Sonarr have, loaded with the address and API key in the fields (when the view opens, and
|
||||
again shortly after either is changed, before saving). A configured value the server does not
|
||||
|
||||
+18
-2
@@ -391,9 +391,9 @@ func (v *libraryView) render() {
|
||||
}
|
||||
|
||||
func (v *libraryView) renderPane(p *libPane) {
|
||||
selID := -1
|
||||
selID, prevRow := -1, 0
|
||||
if r, _ := p.table.GetSelection(); r >= 1 && r <= len(p.shown) {
|
||||
selID = p.shown[r-1].id
|
||||
selID, prevRow = p.shown[r-1].id, r
|
||||
}
|
||||
p.shown = filterItems(p.all, p.filter, p.text, p.attr)
|
||||
|
||||
@@ -408,6 +408,13 @@ func (v *libraryView) renderPane(p *libPane) {
|
||||
selRow = i + 1
|
||||
}
|
||||
}
|
||||
if selRow == 0 && selID != -1 && !containsItem(p.all, selID) {
|
||||
// The selected title is gone from the library (removed): stay at its
|
||||
// place, on the title that moved up into it (or the new last one),
|
||||
// instead of jumping to the top. A title that is only filtered out
|
||||
// still starts the list from the top.
|
||||
selRow = min(prevRow, len(p.shown))
|
||||
}
|
||||
placeholder := "Nothing matches the filter"
|
||||
switch {
|
||||
case p.err != nil && !p.loaded:
|
||||
@@ -437,6 +444,15 @@ func (v *libraryView) renderPane(p *libPane) {
|
||||
p.table.SetTitle(title + " ")
|
||||
}
|
||||
|
||||
func containsItem(items []libItem, id int) bool {
|
||||
for _, it := range items {
|
||||
if it.id == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (v *libraryView) renderDetails() {
|
||||
if it, ok := v.selected(); ok {
|
||||
v.details.Show(it.details, it.cover)
|
||||
|
||||
@@ -209,3 +209,51 @@ func TestListedValues(t *testing.T) {
|
||||
t.Errorf("empty pool: %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemovingATitleKeepsThePlace(t *testing.T) {
|
||||
a := newTestApp(t)
|
||||
v := newLibraryView(a, a.radarr, a.sonarr)
|
||||
p := v.panes[0]
|
||||
items := func(ids ...int) []libItem {
|
||||
var out []libItem
|
||||
for _, id := range ids {
|
||||
out = append(out, libItem{id: id, title: string(rune('A' + id)), label: string(rune('A' + id))})
|
||||
}
|
||||
return out
|
||||
}
|
||||
selectedID := func() int {
|
||||
r, _ := p.table.GetSelection()
|
||||
return p.shown[r-1].id
|
||||
}
|
||||
p.all, p.loaded = items(1, 2, 3, 4, 5), true
|
||||
v.renderPane(p)
|
||||
|
||||
// Remove the third title: the fourth moves up into its place and is selected.
|
||||
p.table.Select(3, 0)
|
||||
p.all = items(1, 2, 4, 5)
|
||||
v.renderPane(p)
|
||||
if r, _ := p.table.GetSelection(); r != 3 || selectedID() != 4 {
|
||||
t.Errorf("after removing the third: row %d, title %d", r, selectedID())
|
||||
}
|
||||
// Remove the last title: the new last one is selected.
|
||||
p.table.Select(4, 0)
|
||||
p.all = items(1, 2, 4)
|
||||
v.renderPane(p)
|
||||
if r, _ := p.table.GetSelection(); r != 3 || selectedID() != 4 {
|
||||
t.Errorf("after removing the last: row %d, title %d", r, selectedID())
|
||||
}
|
||||
// A reload that keeps the title keeps it selected, wherever it is now.
|
||||
p.table.Select(2, 0) // title 2
|
||||
p.all = items(0, 1, 2, 4)
|
||||
v.renderPane(p)
|
||||
if selectedID() != 2 {
|
||||
t.Errorf("kept title not followed: %d", selectedID())
|
||||
}
|
||||
// A title that is only filtered out still starts the list from the top.
|
||||
p.table.Select(4, 0) // title 4
|
||||
p.text = "B" // title 1 only: 4 is filtered out, not removed
|
||||
v.renderPane(p)
|
||||
if r, _ := p.table.GetSelection(); r != 1 {
|
||||
t.Errorf("filtered out: row %d, want the top", r)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user