fix(tui): track selection by site ID + q means back everywhere
Cursor tracked by site ID instead of positional index. When the list re-sorts every tick (sites change status), the selection stays on the same monitor instead of silently jumping to whatever now occupies that index position. q now means "back" in detail, history, SLA, and alert-detail views — consistent with muscle memory from navigating deeper views. Only the dashboard q quits the app. ctrl+c always quits from anywhere.
This commit was merged in pull request #113.
This commit is contained in:
@@ -105,9 +105,24 @@ func (m *Model) refreshLive() {
|
|||||||
}
|
}
|
||||||
m.sites = ordered
|
m.sites = ordered
|
||||||
m.logViewport.SetContent(strings.Join(m.engine.GetLogs(), "\n"))
|
m.logViewport.SetContent(strings.Join(m.engine.GetLogs(), "\n"))
|
||||||
|
|
||||||
|
if m.currentTab == 0 && m.selectedID != 0 {
|
||||||
|
for i, s := range m.sites {
|
||||||
|
if s.ID == m.selectedID {
|
||||||
|
m.cursor = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
m.clampCursor()
|
m.clampCursor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Model) syncSelectedID() {
|
||||||
|
if m.currentTab == 0 && m.cursor < len(m.sites) {
|
||||||
|
m.selectedID = m.sites[m.cursor].ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// clampCursor keeps the cursor and scroll offset within the current tab's list.
|
// clampCursor keeps the cursor and scroll offset within the current tab's list.
|
||||||
func (m *Model) clampCursor() {
|
func (m *Model) clampCursor() {
|
||||||
listLen := m.currentListLen()
|
listLen := m.currentListLen()
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ func (m Model) viewAlertDetailPanel() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString(m.divider() + "\n")
|
b.WriteString(m.divider() + "\n")
|
||||||
b.WriteString(m.st.subtleStyle.Render(" [i/Esc] Back [e] Edit [t] Test [q] Quit"))
|
b.WriteString(m.st.subtleStyle.Render(" [q/Esc] Back [e] Edit [t] Test"))
|
||||||
|
|
||||||
return lipgloss.NewStyle().Padding(1, 2).Render(b.String())
|
return lipgloss.NewStyle().Padding(1, 2).Render(b.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ type Model struct {
|
|||||||
state sessionState
|
state sessionState
|
||||||
currentTab int
|
currentTab int
|
||||||
cursor int
|
cursor int
|
||||||
|
selectedID int
|
||||||
tableOffset int
|
tableOffset int
|
||||||
maxTableRows int
|
maxTableRows int
|
||||||
termWidth int
|
termWidth int
|
||||||
|
|||||||
@@ -286,6 +286,7 @@ func (m *Model) handleMouse(msg tea.MouseMsg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m.syncSelectedID()
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,7 +380,7 @@ func (m *Model) handleDetailKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
return m, m.openSLAView(m.sites[m.cursor])
|
return m, m.openSLAView(m.sites[m.cursor])
|
||||||
}
|
}
|
||||||
case "q":
|
case "q":
|
||||||
return m, tea.Quit
|
m.state = stateDashboard
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
@@ -499,10 +500,8 @@ func (m *Model) handleHistoryKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
|
|
||||||
func (m *Model) handleAlertDetailKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
func (m *Model) handleAlertDetailKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
case "i", "esc":
|
case "q", "i", "esc":
|
||||||
m.state = stateDashboard
|
m.state = stateDashboard
|
||||||
case "q":
|
|
||||||
return m, tea.Quit
|
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
@@ -537,6 +536,7 @@ func (m *Model) handleDashboardKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
if m.cursor < m.tableOffset {
|
if m.cursor < m.tableOffset {
|
||||||
m.tableOffset = m.cursor
|
m.tableOffset = m.cursor
|
||||||
}
|
}
|
||||||
|
m.syncSelectedID()
|
||||||
}
|
}
|
||||||
case "down", "j":
|
case "down", "j":
|
||||||
if m.state == stateLogs {
|
if m.state == stateLogs {
|
||||||
@@ -548,6 +548,7 @@ func (m *Model) handleDashboardKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
if m.cursor >= m.tableOffset+m.maxTableRows {
|
if m.cursor >= m.tableOffset+m.maxTableRows {
|
||||||
m.tableOffset++
|
m.tableOffset++
|
||||||
}
|
}
|
||||||
|
m.syncSelectedID()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "n":
|
case "n":
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ func (m Model) viewDetailPanel() string {
|
|||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(m.divider() + "\n")
|
b.WriteString(m.divider() + "\n")
|
||||||
b.WriteString(m.st.subtleStyle.Render(" [i/Esc] Back [e] Edit [h] History [s] SLA [click] Inspect [q] Quit"))
|
b.WriteString(m.st.subtleStyle.Render(" [q/Esc] Back [e] Edit [h] History [s] SLA [click] Inspect"))
|
||||||
|
|
||||||
return lipgloss.NewStyle().Padding(1, 2).Render(b.String())
|
return lipgloss.NewStyle().Padding(1, 2).Render(b.String())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user