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

A pull's looks sit beside the same page's look from main: before and after #3104

Merged opened this

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

Merged

scout/forge:scout/2737-a-pull-s-looks-sit-beside-the-same-page → main 4 commits fork 2 threads · 2 unresolved

  • Merged. scout/2737-a-pull-s-looks-sit-beside-the-same-page was merged into main as d638045.

Review

Sign in to review this change.
4 files changed +81 −6
docs/DESIGN.md +1 −1
@@ -385,7 +385,7 @@ gone, so this list only shrinks.
385385 - **`style/content.ts`, prose (markdown)** — table cell alignment, built by `markdown.ts` as `ta-${align}`: `.ta-c` `.ta-r`
386386 - **`style/content.ts`, diff viewer** — the diff table: its gutters, line kinds, file head and inline review comments: `.add` `.del` `.dh` `.diff` `.diff-body` `.diff-head` `.diff-note` `.diff-path` `.diff-stat` `.diff-stub` `.diff-summary` `.diff-table` `.dl` `.dl-review` `.dn` `.dn-comment` `.nonl` `.rc-body` `.rc-form` `.rc-head` `.rc-outdated` `.rc-resolved-line` `.wd`
387387 - **`style/content.ts`, review verdicts** — the body under a verdict: `.review-body`
388 - **`style/content.ts`, apps, runs, and the crew** — run pages, their logs, checks and look screenshots: `.app-url` `.check-progress` `.check-steps` `.ln-forge` `.ln-pulse` `.ln-say` `.ln-tool` `.ln-you` `.log-tail-row` `.look` `.look-attached` `.look-attached-phone` `.look-attachments` `.look-card` `.look-desktop` `.look-now` `.look-of` `.look-pair` `.look-phone` `.look-thumb` `.pinned-failures` `.pinned-slot` `.run-actions` `.run-jump` `.run-live` `.run-steer` `.run-summary` `.step-state` `.tests-bar` `.tests-words` `.txt` `.who`
388 - **`style/content.ts`, apps, runs, and the crew** — run pages, their logs, checks and look screenshots (a pull's look sets the before side, main's, sits first, then the pull's after side: a `.look-compare` of two `.look-side`): `.app-url` `.check-progress` `.check-steps` `.ln-forge` `.ln-pulse` `.ln-say` `.ln-tool` `.ln-you` `.log-tail-row` `.look` `.look-attached` `.look-attached-phone` `.look-attachments` `.look-card` `.look-compare` `.look-desktop` `.look-now` `.look-of` `.look-pair` `.look-phone` `.look-side` `.look-thumb` `.pinned-failures` `.pinned-slot` `.run-actions` `.run-jump` `.run-live` `.run-steer` `.run-summary` `.step-state` `.tests-bar` `.tests-words` `.txt` `.who`
389389 - **`style/content.ts`, the code browser: explorer beside content** — the explorer column's own parts: `.code-main` `.code-split` `.ex-empty` `.ex-find` `.ex-head` `.ex-list` `.ex-name` `.ex-ref` `.ex-twist` `.explorer-toggle`
390390 - **`style/content.ts`, the finder** — the finder's footnote: `.finder-note`
391391 - **`style/content.ts`, the editor** — the editor's parts beyond the §5 row: `.editor-mirror` `.editor-path` `.editor-preview` `.editor-stack` `.editor-tab` `.mirrored` `.ml`
src/web/pages/looks.ts +41 −5
@@ -170,7 +170,16 @@ export function lookCard(
170170 a === DEFAULT_PAGE ? -1 : b === DEFAULT_PAGE ? 1 : a.localeCompare(b),
171171 );
172172 const labelled = pages.length > 1;
173 const picture = (look: Look, kind: LookKind, page: string): Html => {
173 // What main looks like, to set each page beside: only what this viewer may fetch.
174 const mainLooks = looksForEnv(ctx.app.db, record.id, "production").filter(
175 (l) => !isAttached(l) && mayFetchLook(ctx, repo, record, l),
176 );
177 const picture = (
178 look: Look,
179 kind: LookKind,
180 page: string,
181 of = `#${pull.number}`,
182 ): Html => {
174183 const url = lookUrl(base, look);
175184 const scheme = look.theme === "dark" ? " in the dark" : "";
176185 return html`<a class="look look-${kind}" href="${url}">
@@ -180,7 +189,7 @@ export function lookCard(
180189 height="${LOOK_SIZES[kind].height}"
181190 alt="${repo.name}${page === DEFAULT_PAGE
182191 ? ""
183 : ` ${page}`} #${pull.number} on a ${kind}${scheme}"
192 : ` ${page}`} ${of} on a ${kind}${scheme}"
184193 loading="lazy"
185194 />
186195 </a>`;
@@ -206,6 +215,14 @@ export function lookCard(
206215 </p>
207216 </div>`;
208217 const moved = shown.commitOid !== headOid;
218 const mainOfPage = mainLooks.filter((l) => l.page === page);
219 const beforePhone = pictured(mainOfPage, "phone");
220 const beforeDesktop = pictured(mainOfPage, "desktop");
221 // Beside the same page at the same width: a width main lacks is left out.
222 const beforeShown = [
223 phone === undefined ? undefined : beforePhone,
224 desktop === undefined ? undefined : beforeDesktop,
225 ].filter((l): l is Look => l !== undefined);
209226 // Only the dark pictures of the commit the caption names: after a push
210227 // the light pair is retaken first, and an old head's dark pair must not
outdated

Add the commit and time of main's picture here, as look-of does for the after side.

211228 // sit under the new head's words.
@@ -216,9 +233,28 @@ export function lookCard(
216233 const darkDesktop = pictured(darkOfPage, "desktop");
217234 return html`<div class="look-group">
218235 ${label}
219 <div class="look-pair">
220 ${when(phone, (l) => picture(l, "phone", page))}
221 ${when(desktop, (l) => picture(l, "desktop", page))}
236 <div class="look-compare">
237 <div class="look-side look-before">
238 <p class="muted small">Before · main</p>
239 ${beforeShown.length === 0
240 ? html`<p class="muted small look-nobefore">
241 Main has no look of ${page} yet.
242 </p>`
243 : html`<div class="look-pair">
244 ${beforeShown.map((l) => picture(l, l.kind, page, "main"))}
245 </div>
246 <span class="muted small look-of"
247 >at ${sha(beforeShown[0]!.commitOid, `${base}/commit/${beforeShown[0]!.commitOid}`)} ·
248 ${time(beforeShown[0]!.createdAt)}</span
249 >`}
250 </div>
251 <div class="look-side look-after">
252 <p class="muted small">After · #${pull.number}</p>
253 <div class="look-pair">
254 ${when(phone, (l) => picture(l, "phone", page))}
255 ${when(desktop, (l) => picture(l, "desktop", page))}
256 </div>
257 </div>
222258 </div>
223259 ${when(darkPhone ?? darkDesktop, () =>
224260 html`<details class="quiet-details">
src/web/style/content.ts +4
@@ -873,6 +873,10 @@ form.inline { display: inline; margin-left: auto; }
873873 .look-pair { display: flex; gap: 14px; align-items: flex-start; }
874874 .look { display: block; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; background: var(--muted); }
875875 .look img { display: block; width: 100%; height: auto; }
876 .look-compare { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }

Document these classes in docs/DESIGN.md. In .look-side, let .look-pair wrap so a phone and a desktop picture are not squeezed side by side at 360px.

877 .look-side { flex: 1 1 320px; min-width: 0; }
878 .look-side > p { margin: 0 0 6px; }
879 .look-side .look-pair { flex-wrap: wrap; }
876880 .look-attachments { flex-wrap: wrap; margin-top: 10px; }
877881 .look-attached { margin: 0; display: flex; flex-direction: column; gap: 6px; flex: 1 1 200px; min-width: 0; max-width: 1280px; }
878882 .look-attached-phone { flex: 0 0 200px; }
test/looks.test.ts +35
@@ -1100,6 +1100,41 @@ describe("the look", () => {
11001100 }
11011101 });
11021102
1103 test("a pull's look of a page sits beside main's newest look of it, or says main has none", async () => {
1104 const env = previewEnv(pull.number);
1105 const oid = "a".repeat(40);
1106 const mainOid = "b".repeat(40);
1107 const put = (e: string, commitOid: string, page: string) =>
1108 recordLook(app.db, {
1109 appId: record.id,
1110 env: e,
1111 commitOid,
1112 page,
1113 kind: "phone",
1114 path: `looks/${record.id}/${e}/${commitOid}-x-phone.png`,
1115 });
1116 put(env, oid, "/map");
1117 put(env, oid, "/solo");
1118 put("production", mainOid, "/map");
1119 const text = await (
1120 await web(`/alice/hello/pulls/${pull.number}`, aliceCookie)
1121 ).text();
1122 const group = (page: string) =>
1123 text.split(`<p class="muted small look-page">${page}</p>`)[1]!.split("look-group")[0]!;
1124 const map = group("/map");
1125 expect(map).toContain(`/looks/production/${mainOid}/map-phone.png?v=`);
1126 expect(map).toContain(`/looks/${env}/${oid}/map-phone.png?v=`);
1127 expect(map.indexOf("Before")).toBeLessThan(map.indexOf("After"));
1128 expect(map.indexOf(`/looks/production/`)).toBeLessThan(
1129 map.indexOf(`/looks/${env}/`),
1130 );
1131 expect(map).not.toContain("has no look");
1132 expect(map).toContain(`/commit/${mainOid}`);
1133 const solo = group("/solo");
1134 expect(solo).toContain("Main has no look of /solo yet.");
1135 expect(solo).not.toContain("/looks/production/");
1136 });
1137
11031138 test("memory pressure is what the container truly holds, never its page cache", async () => {
11041139 const { cgroupMemoryPressure, memoryPressure } =
11051140 await import("../src/looks/service.ts");

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs