fix(tui): show live spinner while waiting on QR init, clear stale banner - #67
Merged
Merged
Conversation
The 'Scan with Amber' screen said 'Generating QR code...' both while loading AND after the QR appeared — two bugs that together read as a stuck screen with no progress indication. Bug 1: m.message was set to 'Generating QR code...' in handleLoginEnter and never cleared when qrGeneratedMsg arrived. View() always appends m.message if non-empty, so the QR rendered correctly above a contradictory 'still generating' banner. On terminals too short to show both, the user only saw the 'still generating' line and concluded the program was hung. Bug 2: 'Generating...' was static text. With no animation the user had no way to tell the program was doing work — it looked frozen. Fix: - Add a spinner.Model field on the TUI Model, initialized with the ASCII-only Line frame set so it renders even on dumb terminals. - Init() now batches textinput.Blink with the spinner tick. - Update forwards every message to the spinner and batches the resulting tick cmd into the returned cmd so the spinner animates regardless of which Update branch runs. - viewQRLogin now renders 'spinner.View() + Generating QR code...' while loading, both before AND after the URI is known but the rendered QR isn't available yet. - The qrGeneratedMsg handler clears m.message (and the message style) so the leftover banner doesn't appear under the rendered QR. Tests: - New TestQRFlowsThroughLoginMenuEndToEnd drives the full path a user takes: pick the QR menu item, wait for initQR, deliver the qrGeneratedMsg, and assert the View no longer contains the word 'Generating'. - Subtest 'loading state shows spinner' pumps a TickMsg and asserts the loading view contains an active spinner frame character. Verified locally: 'go test -count=1 ./...' passes; the e2e test captures a View where the QR is followed by the 'Waiting for connection...' footer (no stale Generating text). go.mod / go.sum: go mod tidy promoted bubbles, bubbletea, lipgloss, go-runewidth, qrterminal, and modernc.org/sqlite from indirect to direct deps since this change imports them as such. No new versions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The 'Scan with Amber' (NIP-46) screen said 'Generating QR code…' both while waiting AND after the QR had rendered — two real bugs that together looked like a hung program.
What was wrong
Bug 1 (the actual cause of "never loads"):
handleLoginEntersetsm.message = "Generating QR code..."when the user picks the QR menu item. TheqrGeneratedMsghandler storedm.qrDataandm.qrReadycorrectly, but never clearedm.message.View()always appendsm.messageif non-empty. Result: the QR rendered correctly above a stale "Generating QR code…" banner. On a 24-line terminal where the QR is ~30 lines tall afterlipgloss.Placecentering, only the lower part of the screen is visible at any time — so most of the time the user sees the stale banner, never the QR, and concludes the program is stuck.Bug 2 (the "no loading indication" complaint): the loading text was static. No animation, no spinner — nothing changed frame to frame — so even when the program genuinely was waiting on the network, there was no feedback that anything was happening.
Fix
tui/tui.go:spinner.Modelfield onModel, initialized inNewModelwith the ASCII-onlyspinner.Lineframe set (so it works on dumb terminals too).Init()now returnstea.Batch(textinput.Blink, m.spinner.Tick).Update()forwards every message to the spinner and batches the spinner'sTickcmd into the returned cmd, so the spinner animates regardless of which branch fires.viewQRLoginnow rendersm.spinner.View() + " Generating QR code..."while loading (both before and afterqrDatais known).qrGeneratedMsghandler now clearsm.messageandm.messageStyleso the leftover banner doesn't appear under the rendered QR.Tests
New
tui/tui_qr_e2e_test.go:TestQRFlowsThroughLoginMenuEndToEnd— drives the full user flow: pick the QR menu item (cursor=1, no-profiles branch), wait for theinitQRcmd, deliver theqrGeneratedMsg, drain a few ticks, and assert the rendered View does not contain the word "Generating". This is the symptom the user reported.loading state shows spinner— delivers aspinner.TickMsgbefore the URI arrives and asserts the loading view contains an active spinner frame char (|///-/\) along with the "Generating" text. Catches any regression that swaps the spinner back out for static text.Local verification:
go test -count=1 ./...passes. The end-to-end View dump no longer shows "Generating QR code..." after the QR arrives.Files
tui/tui.go— spinner wiring, message clearing, animated loading view.tui/tui_qr_e2e_test.go— new tests.go.mod/go.sum—go mod tidypromotedbubbles,bubbletea,lipgloss,go-runewidth,qrterminal, andmodernc.org/sqlitefrom indirect to direct deps (they're now directly imported); no new versions.PR #66 handled the QR rendering width. This PR handles the loading-state UX around it.