Fix: Add viewport scrolling to operation history
PROBLEM: - History displayed ALL entries at once - With many backups, first entries scroll off screen - Cursor navigation worked but selection was invisible - User had to "blindly" navigate 5+ entries to see anything SOLUTION: - Added viewport with max 15 visible items at once - Viewport auto-scrolls to follow cursor position - Scroll indicators show when there are more entries: * "▲ More entries above..." * "▼ X more entries below..." - Cursor always visible within viewport RESULT: - ✅ Always see current selection - ✅ Works with any number of history entries - ✅ Clear visual feedback with scroll indicators - ✅ Smooth navigation experience
This commit is contained in:
Binary file not shown.
@ -19,6 +19,7 @@ type HistoryViewModel struct {
|
|||||||
parent tea.Model
|
parent tea.Model
|
||||||
history []HistoryEntry
|
history []HistoryEntry
|
||||||
cursor int
|
cursor int
|
||||||
|
viewOffset int // For scrolling large lists
|
||||||
}
|
}
|
||||||
|
|
||||||
type HistoryEntry struct {
|
type HistoryEntry struct {
|
||||||
@ -35,7 +36,8 @@ func NewHistoryView(cfg *config.Config, log logger.Logger, parent tea.Model) His
|
|||||||
logger: log,
|
logger: log,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
history: loadHistory(cfg),
|
history: loadHistory(cfg),
|
||||||
cursor: 0, // Start at first item
|
cursor: 0,
|
||||||
|
viewOffset: 0, // Start at top
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,11 +106,20 @@ func (m HistoryViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
case "up", "k":
|
case "up", "k":
|
||||||
if m.cursor > 0 {
|
if m.cursor > 0 {
|
||||||
m.cursor--
|
m.cursor--
|
||||||
|
// Scroll viewport up if cursor moves above visible area
|
||||||
|
if m.cursor < m.viewOffset {
|
||||||
|
m.viewOffset = m.cursor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case "down", "j":
|
case "down", "j":
|
||||||
if m.cursor < len(m.history)-1 {
|
if m.cursor < len(m.history)-1 {
|
||||||
m.cursor++
|
m.cursor++
|
||||||
|
// Scroll viewport down if cursor moves below visible area
|
||||||
|
maxVisible := 15 // Show max 15 items at once
|
||||||
|
if m.cursor >= m.viewOffset+maxVisible {
|
||||||
|
m.viewOffset = m.cursor - maxVisible + 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,10 +137,26 @@ func (m HistoryViewModel) View() string {
|
|||||||
s.WriteString(infoStyle.Render("📭 No backup history found"))
|
s.WriteString(infoStyle.Render("📭 No backup history found"))
|
||||||
s.WriteString("\n\n")
|
s.WriteString("\n\n")
|
||||||
} else {
|
} else {
|
||||||
|
maxVisible := 15 // Show max 15 items at once
|
||||||
|
|
||||||
|
// Calculate visible range
|
||||||
|
start := m.viewOffset
|
||||||
|
end := start + maxVisible
|
||||||
|
if end > len(m.history) {
|
||||||
|
end = len(m.history)
|
||||||
|
}
|
||||||
|
|
||||||
s.WriteString(fmt.Sprintf("Found %d backup operations (Viewing %d/%d):\n\n",
|
s.WriteString(fmt.Sprintf("Found %d backup operations (Viewing %d/%d):\n\n",
|
||||||
len(m.history), m.cursor+1, len(m.history)))
|
len(m.history), m.cursor+1, len(m.history)))
|
||||||
|
|
||||||
for i, entry := range m.history {
|
// Show scroll indicators
|
||||||
|
if start > 0 {
|
||||||
|
s.WriteString(infoStyle.Render(" ▲ More entries above...\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display only visible entries
|
||||||
|
for i := start; i < end; i++ {
|
||||||
|
entry := m.history[i]
|
||||||
line := fmt.Sprintf("[%s] %s - %s (%s)",
|
line := fmt.Sprintf("[%s] %s - %s (%s)",
|
||||||
entry.Timestamp.Format("2006-01-02 15:04"),
|
entry.Timestamp.Format("2006-01-02 15:04"),
|
||||||
entry.Type,
|
entry.Type,
|
||||||
@ -144,6 +171,12 @@ func (m HistoryViewModel) View() string {
|
|||||||
}
|
}
|
||||||
s.WriteString("\n")
|
s.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show scroll indicator if more entries below
|
||||||
|
if end < len(m.history) {
|
||||||
|
s.WriteString(infoStyle.Render(fmt.Sprintf(" ▼ %d more entries below...\n", len(m.history)-end)))
|
||||||
|
}
|
||||||
|
|
||||||
s.WriteString("\n")
|
s.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user