Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions internal/tui/banner.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,15 +289,23 @@ func renderHome(l layout, loggedIn, hasKey bool, mood mascotMood) string {
key := lipgloss.NewStyle().Foreground(lipgloss.Color(brandVioletText)).Bold(true)
desc := lipgloss.NewStyle().Foreground(cGray)

b.WriteString(l.indent + section.Render("Getting around") + "\n\n")
// One blank line after the header, not two: "The tabs" below already does
// it this way, and the row that buys is what the sign-out line needs to fit
// a 24-row terminal.
b.WriteString(l.indent + section.Render("Getting around") + "\n")

keys := []struct{ k, d string }{
{"←/→", "move between tabs"},
{"↑/↓", "scroll the tab you are on"},
{"r", "refresh it"},
{"?", "every shortcut, including the ones for Setup"},
{"q", "quit"},
}
if loggedIn {
keys = append(keys, struct{ k, d string }{"o", "sign out of this account"})
}
keys = append(keys,
struct{ k, d string }{"?", "every shortcut, including the ones for Setup"},
struct{ k, d string }{"q", "quit"},
)
tabs := []struct{ k, d string }{
{"Usage", "what you have spent, over 24 hours, 30 days and all time"},
{"Models", "what your key can call, and what you have spent on each"},
Expand Down
31 changes: 31 additions & 0 deletions internal/tui/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1653,3 +1653,34 @@ func TestSigningOutStartsTheSetupAgain(t *testing.T) {
t.Errorf("after signing out the panel is at %v, want the first step", out.wizard)
}
}

// Signing out was only behind `?`, which is a place you look for something if
// you already suspect it is there. Reported as exactly that: "en ningún lado
// aparece que pulsando o dos veces te deslogeas".
func TestSigningOutIsAdvertisedWhereItIsLookedFor(t *testing.T) {
// The account screen, which is where a person goes for account things.
profile := renderProfile(map[string]any{"handle": "bperez"}, newLayout(90, 30))
if !strings.Contains(profile, "sign out") {
t.Error("the Profile tab does not offer to sign out")
}
if !strings.Contains(profile, "twice") {
t.Error("Profile does not say it takes two presses, which is the surprising half")
}

// The Setup tab footer, next to the other keys it lists.
m := setupModel(t, &session.Session{Token: "t", APIKey: testKey})
m.lay = newLayout(96, 40)
if out := m.renderSetup(m.lay); !strings.Contains(out, "o sign out") {
t.Error("the Setup tab lists its keys and leaves this one out")
}

// Home, where the keys are introduced.
if out := renderHome(newLayout(96, 40), true, true, moodNormal); !strings.Contains(out, "sign out") {
t.Error("Home lists the keys and leaves this one out")
}

// And not offered to somebody who has no session to end.
if out := renderHome(newLayout(96, 40), false, false, moodNormal); strings.Contains(out, "sign out") {
t.Error("Home offers to sign out of a session that is not there")
}
}
15 changes: 13 additions & 2 deletions internal/tui/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,9 @@ func renderTabBar(active int, l layout) string {

// ── profile renderer ──────────────────────────────────────────────────────────

// renderProfile also carries the sign-out, because the account screen is where
// somebody goes looking for it. It was only behind `?`, which is a place you
// find something in if you already suspect it is there.
func renderProfile(data map[string]any, l layout) string {
var b strings.Builder
kStyle := lipgloss.NewStyle().Foreground(cGray).Width(l.keyW)
Expand All @@ -991,6 +994,10 @@ func renderProfile(data map[string]any, l layout) string {
val := censor(k, fmt.Sprintf("%v", v))
b.WriteString(l.indent + kStyle.Render(humanKey(k)+":") + vStyle.Render(val) + "\n")
}

b.WriteString("\n" + l.indent +
lipgloss.NewStyle().Foreground(cCyan).Bold(true).Render("o") +
lipgloss.NewStyle().Foreground(cGray).Render(" sign out of this account, twice to confirm") + "\n")
return b.String()
}

Expand Down Expand Up @@ -2726,15 +2733,19 @@ func (m model) renderSetup(l layout) string {
if m.sess.APIKey == "" {
b.WriteString(l.indent + dimStyle.Render("Set an API key first (e).") + "\n")
} else {
b.WriteString(l.indent + dimStyle.Render("↑/↓ navigate space toggle c configure selected") + "\n")
keys := "↑/↓ navigate space toggle c configure selected"
if m.sess.Token != "" {
keys += " o sign out"
}
b.WriteString(l.indent + dimStyle.Render(keys) + "\n")
}

return b.String()
}

// ── about renderer ───────────────────────────────────────────────────────────

const Version = "0.1.16"
const Version = "0.1.17"

func renderAbout(l layout) string {
var b strings.Builder
Expand Down
2 changes: 1 addition & 1 deletion scripts/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ function Get-LatestVersion {
could not work out the latest version from the GitHub API
it rate limits unauthenticated requests, so this is usually temporary
wait a few minutes, or pick a version yourself:
& ([scriptblock]::Create((irm https://nan.builders/install.ps1))) -Version v0.1.16
& ([scriptblock]::Create((irm https://nan.builders/install.ps1))) -Version v0.1.17
the releases are at https://github.com/$Repo/releases
"@
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ require_version() {
err "could not work out the latest version from the GitHub API"
err "it rate limits unauthenticated requests, so this is usually temporary"
err "wait a few minutes, or pick a version yourself:"
printf " VERSION=v0.1.16 curl -fsSL https://nan.builders/install | bash
printf " VERSION=v0.1.17 curl -fsSL https://nan.builders/install | bash
" >&2
err "the releases are at https://github.com/$REPO/releases"
exit 1
Expand Down
Loading