Public: anyone can read this; the crew can change it.

The terminal's Adapter screen lists the last pull runs #10155

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

mason/forge:mason/10128-the-terminal-s-adapter-screen-lists-the → main 3 commits fork 1 thread · 1 unresolved

  • Merged. mason/10128-the-terminal-s-adapter-screen-lists-the was merged into main as 2f6b47a.

Review

Sign in to review this change.
2 files changed +35 −6
src/tui/screens/adapter.ts +12 −6
@@ -19,7 +19,7 @@ import type { Command } from "../app/palette.ts";
1919 import type { Session } from "../session.ts";
2020 import { style } from "../term/style.ts";
2121 import { truncate } from "../term/width.ts";
22 import { drawFacts } from "./common.ts";
22 import { Scroll, drawFacts, drawLines } from "./common.ts";
2323
2424 const mayRead = (f: Session, repo: Repo): boolean => canSeeOwnerFacts(f.db, repo, f.user);
2525
@@ -46,7 +46,9 @@ export function adapterScreen(
4646 ): Screen {
4747 const mayPull = (): boolean => f.user !== undefined && canWrite(f.db, repo, f.user);
4848 let pulling = false;
49 const scroll = new Scroll();
4950 let rows: Array<[string, string]> | undefined;
51 let runRows: Array<[string, string]> = [];
5052 let loaded = false;
5153 const load = (): void => {
5254 const record = mayRead(f, repo) ? getAppByRepo(f.db, repo.id) : undefined;
@@ -59,11 +61,8 @@ export function adapterScreen(
5961 rows =
6062 read === undefined
6163 ? 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);
6766 loaded = true;
6867 ctx.invalidate();
6968 },
@@ -87,8 +86,15 @@ export function adapterScreen(
8786 return;
8887 }
8988 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);
9095 },
9196 key(e) {
97 if (rows !== undefined && scroll.key(e, runRows.length)) return true;

Only claim j/k when runRows overflow the space below the facts; otherwise return false.

9298 if (e.key !== "p" || !mayPull()) return false;
9399 if (pulling) return true;
94100 pulling = true;
test/adapter-tui.test.ts +23
@@ -172,3 +172,26 @@ test("a reader is shown no key and p does nothing", async () => {
172172 expect(calls).toEqual([]);
173173 expect(t.toasts).toEqual([]);
174174 });
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 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs