Public: anyone can read this; the crew can change it.
The terminal's Adapter screen lists the last pull runs #10155
Check · Review · Land · Live done — Landed and live in production.
mason/forge:mason/10128-the-terminal-s-adapter-screen-lists-the → main 3 commits fork 1 thread · 1 unresolved
2 files
changed +35
−6
src/tui/screens/adapter.ts +12 −6
| @@ -19,7 +19,7 @@ import type { Command } from "../app/palette.ts"; | ||
| 19 | 19 | import type { Session } from "../session.ts"; |
| 20 | 20 | import { style } from "../term/style.ts"; |
| 21 | 21 | import { truncate } from "../term/width.ts"; |
| 22 | import { drawFacts } from "./common.ts"; | |
| 22 | import { Scroll, drawFacts, drawLines } from "./common.ts"; | |
| 23 | 23 | |
| 24 | 24 | const mayRead = (f: Session, repo: Repo): boolean => canSeeOwnerFacts(f.db, repo, f.user); |
| 25 | 25 | |
| @@ -46,7 +46,9 @@ export function adapterScreen( | ||
| 46 | 46 | ): Screen { |
| 47 | 47 | const mayPull = (): boolean => f.user !== undefined && canWrite(f.db, repo, f.user); |
| 48 | 48 | let pulling = false; |
| 49 | const scroll = new Scroll(); | |
| 49 | 50 | let rows: Array<[string, string]> | undefined; |
| 51 | let runRows: Array<[string, string]> = []; | |
| 50 | 52 | let loaded = false; |
| 51 | 53 | const load = (): void => { |
| 52 | 54 | const record = mayRead(f, repo) ? getAppByRepo(f.db, repo.id) : undefined; |
| @@ -59,11 +61,8 @@ export function adapterScreen( | ||
| 59 | 61 | rows = |
| 60 | 62 | read === undefined |
| 61 | 63 | ? undefined |
| 62 | : [ | |
| 63 | ...adapterRows(read), | |
| 64 | ["Pull runs", (read.runs ?? []).length === 0 ? NO_RUNS_WORDS : ""], | |
| 65 | ...adapterRunRows(read), | |
| 66 | ]; | |
| 64 | : [...adapterRows(read), ["Pull runs", (read.runs ?? []).length === 0 ? NO_RUNS_WORDS : ""]]; | |
| 65 | runRows = read === undefined ? [] : adapterRunRows(read); | |
| 67 | 66 | loaded = true; |
| 68 | 67 | ctx.invalidate(); |
| 69 | 68 | }, |
| @@ -87,8 +86,15 @@ export function adapterScreen( | ||
| 87 | 86 | return; |
| 88 | 87 | } |
| 89 | 88 | drawFacts(s, area, c, rows); |
| 89 | const top = rows.length; | |
| 90 | if (top >= area.h || runRows.length === 0) return; | |
| 91 | const lines = runRows.map(([when, words]) => [ | |
| 92 | { text: truncate(`${when.slice(0, 16).replace("T", " ")} ${words}`, Math.max(0, area.w - 1)), style: style(c.fg, c.bg) }, | |
| 93 | ]); | |
| 94 | drawLines(s, { ...area, y: area.y + top, h: area.h - top }, c, scroll, lines); | |
| 90 | 95 | }, |
| 91 | 96 | key(e) { |
| 97 | if (rows !== undefined && scroll.key(e, runRows.length)) return true; | |
| 92 | 98 | if (e.key !== "p" || !mayPull()) return false; |
| 93 | 99 | if (pulling) return true; |
| 94 | 100 | pulling = true; |
test/adapter-tui.test.ts +23
| @@ -172,3 +172,26 @@ test("a reader is shown no key and p does nothing", async () => { | ||
| 172 | 172 | expect(calls).toEqual([]); |
| 173 | 173 | expect(t.toasts).toEqual([]); |
| 174 | 174 | }); |
| 175 | ||
| 176 | test("j scrolls the runs when they overflow, and the facts stay", async () => { | |
| 177 | const many = { ...facts, runs: Array.from({ length: 10 }, (_, i) => ({ ...facts.runs![0]!, id: `r${i}`, error: `boom ${i}` })) }; | |
| 178 | const terminal = headlessTerminal(100, 12); | |
| 179 | const { app: tui, session } = createForgeApp( | |
| 180 | app, | |
| 181 | { sshUsername: olive.username, remoteAddress: "127.0.0.1", fingerprint: "SHA256:test", user: olive }, | |
| 182 | { terminal, exitHooks: false }, | |
| 183 | ); | |
| 184 | tui.start(); | |
| 185 | const screen = adapterScreen(session, tui.ctx, repo, async () => many); | |
| 186 | tui.ctx.push(screen); | |
| 187 | await settleApp(tui); | |
| 188 | await settleApp(tui); | |
| 189 | expect(tui.screen.toText()).toContain("boom 0"); | |
| 190 | for (let i = 0; i < 3; i++) expect(screen.key?.({ key: "j" } as never)).toBe(true); | |
| 191 | tui.ctx.invalidate(); | |
| 192 | await settleApp(tui); | |
| 193 | const text = tui.screen.toText(); | |
| 194 | expect(text).not.toContain("boom 0"); | |
| 195 | expect(text).toContain("Shop API"); | |
| 196 | tui.stop?.(); | |
| 197 | }); |
Only claim j/k when runRows overflow the space below the facts; otherwise return false.