prime8dev

prime8dev
git clone https://git.prime8.dev/prime8dev.git
Log | Files | Refs | README | LICENSE

commit 3d6f3ef46761df8d2cade4dba2a74ded8fc75301
parent e5f78550b431ffd6e06b6e8fdb2d4996aacd231d
Author: Damian Myrda <damian@prime8.dev>
Date:   Thu, 22 Oct 2026 01:34:11 +0000

tui: blink re-renders the prompt; cursor solid after a tab switch

The viewport keeps a rendered copy of the page, so the blink tick never
reached the screen and a switch could freeze the cursor in its off phase.

Diffstat:
Minternal/tui/shell_test.go | 15+++++++++++++++
Minternal/tui/update.go | 8++++++++
2 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/internal/tui/shell_test.go b/internal/tui/shell_test.go @@ -308,3 +308,18 @@ func TestChromeUsesTerminalPalette(t *testing.T) { } } } + +func TestCursorShownAfterTabSwitch(t *testing.T) { + m := testModel(t, 120, 40) + m.shell.lastKey = time.Now().Add(-cursorBlink * 3) // mid "off" phase + m.activateTab(tabProjects) + m.activateTab(tabAbout) + if out := plainView(m); !strings.Contains(out, "█") { + t.Fatalf("cursor missing after switching back to about") + } + m.shell.lastKey = time.Now().Add(-cursorBlink * 3) + next, _ := m.Update(cursorBlinkMsg{}) + if out := plainView(next.(portfolioModel)); strings.Contains(out, "█") { + t.Fatalf("blink tick did not re-render the prompt (cursor stuck on)") + } +} diff --git a/internal/tui/update.go b/internal/tui/update.go @@ -51,6 +51,12 @@ func (m portfolioModel) update(msg tea.Msg) (tea.Model, tea.Cmd) { m.syncViewport() return m, m.refreshDataCmd() case cursorBlinkMsg: + // The viewport holds a rendered copy of the page, so the prompt line + // has to be re-rendered for the blink to show. SetContent keeps the + // scroll offset. + if m.activeTab == tabAbout && !m.bootActive { + m.viewport.SetContent(m.detailContent()) + } return m, cursorBlinkCmd() case tickMsg: m.now = time.Time(msg) @@ -207,6 +213,8 @@ func (m *portfolioModel) activateTab(tab int) tea.Cmd { m.activeTab = tab m.projectReadmeScroll = false + // coming back to a tab shows the cursor solid, like a fresh keystroke + m.shell.lastKey = time.Now() m.resetViewport() return m.refreshDataCmd()