gui: the page is first drawn in its saved theme, not the system's (seg-contrast failed in Chromium on the release branch: in dark the view shown read at 3.96:1, the other views at 4.69:1) — the saved theme was put on the page by app.js, at the foot of index.html, so a window kept dark under a light system had its header parsed and styled light first, and its buttons' colour transitions (the switch's views, Sync, Settings) then faded them to dark as the page loaded; the test read them mid-way, the more so as #471 made the page longer to parse. theme.js, run in the head after boot.js and before the styles, sets it from bootPrefs (or ?theme=) for the first paint; app.js still sets it as before. seg-contrast.test.cjs now holds app.js back and checks the page was already drawn in its theme (fails without theme.js, Chromium and WebKit, en and zh, dark), and reads colours once the page's transitions are over. old-webkit lets theme.js (ES5, URLSearchParams) run before compat.js; api-key-theme, from the release branch, expects a text button in --ctl-fg as #477 set. seg-contrast, settings-sections, header-zoom-fit, header-centre, click-scroll, old-webkit, api-key-theme, omarchy, agent-grip, web-page, gateway-fold, sessions-toolbar pass; go vet, go build -tags nogui, go test ./internal/gui pass.
This commit is contained in:
5 files changed
+38
-9
No files matched your search
@@ -6,6 +6,7 @@
|
||||
<title>magpie</title>
|
||||
<link rel="icon" href="icons/favicon.svg" type="image/svg+xml">
|
||||
<script src="boot.js"></script>
|
||||
<script src="theme.js"></script>
|
||||
<script src="omarchy.js"></script>
|
||||
<link rel="stylesheet" href="app.css">
|
||||
<link rel="stylesheet" href="routing.css">
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// The saved theme (boot.js), or one the page's address asks for, on the page
|
||||
// before its styles first apply: set only once app.js ran, at the foot of the
|
||||
// page, a window kept dark under a light system was first drawn light, and
|
||||
// the header's buttons faded from light to dark as it loaded. app.js sets it
|
||||
// again; this one is for the first paint.
|
||||
(function () {
|
||||
var asked = new URLSearchParams(location.search).get("theme");
|
||||
var saved = window.bootPrefs && window.bootPrefs.theme;
|
||||
var theme = asked || (saved && saved !== "system" ? saved : "");
|
||||
if (theme) document.documentElement.dataset.theme = theme;
|
||||
})();
|
||||
@@ -12,7 +12,7 @@ async function palette(page, selectors) {
|
||||
const hex = root.getPropertyValue(name).trim();
|
||||
return `rgb(${[1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16)).join(", ")})`;
|
||||
};
|
||||
const colors = Object.fromEntries(["bg", "card", "card-2", "fg", "fg-2", "muted", "pill", "line", "accent", "accent-fg"]
|
||||
const colors = Object.fromEntries(["bg", "card", "card-2", "fg", "fg-2", "muted", "ctl-fg", "pill", "line", "accent", "accent-fg"]
|
||||
.map((name) => [name, rgb("--" + name)]));
|
||||
const elements = Object.fromEntries(Object.entries(selectors).map(([name, selector]) => {
|
||||
const s = getComputedStyle(document.querySelector(selector));
|
||||
@@ -60,7 +60,7 @@ for (const engine of (process.env.BROWSER ? [process.env.BROWSER] : ["chromium",
|
||||
assert.equal(input.bg, c.card, "key inputs must not use the browser's default background");
|
||||
assert.equal(input.color, c.fg);
|
||||
}
|
||||
assert.equal(e.rotate.color, c.muted);
|
||||
assert.equal(e.rotate.color, c["ctl-fg"]); // a text button, in a control's quiet text (#477)
|
||||
assert.equal(e.keyPick.bg, "rgba(0, 0, 0, 0)");
|
||||
assert.equal(e.create.bg, c.accent);
|
||||
assert.equal(e.create.color, c["accent-fg"]);
|
||||
|
||||
@@ -132,10 +132,12 @@ test("no built-in newer than Safari 15.0 unless compat.js fills it in", async ()
|
||||
|
||||
test("compat.js is the first of the page's own scripts", async () => {
|
||||
const html = await read("index.html");
|
||||
// boot.js and omarchy.js run in the head, before the first paint:
|
||||
// omarchy.js does nothing off Omarchy, whose WebKitGTK is a current one
|
||||
// boot.js, theme.js and omarchy.js run in the head, before the first
|
||||
// paint: theme.js is ES5 with nothing newer than Safari 10.1's
|
||||
// URLSearchParams, and omarchy.js does nothing off Omarchy, whose
|
||||
// WebKitGTK is a current one
|
||||
const all = [...html.matchAll(/<script\s+src="([^"]+)"/g)].map((m) => m[1]);
|
||||
const srcs = all.filter((s) => s !== "boot.js" && s !== "omarchy.js");
|
||||
const srcs = all.filter((s) => s !== "boot.js" && s !== "theme.js" && s !== "omarchy.js");
|
||||
assert.equal(srcs[0], "compat.js", "loaded first: " + srcs.join(", "));
|
||||
for (const f of await scripts()) assert(all.includes(f), f + " is not loaded by index.html");
|
||||
});
|
||||
|
||||
@@ -8,7 +8,11 @@
|
||||
// browser computed them, each background laid over the ones under it: the
|
||||
// other views and a text button on the page, a card and the inset editor
|
||||
// read at 4.5:1 with some margin to spare (4.7), the view shown on its thumb
|
||||
// too, and the thumb is told from the track by more than it was. Chromium
|
||||
// too, and the thumb is told from the track by more than it was. They are
|
||||
// read once the page's transitions are over; and the page is first drawn in
|
||||
// its theme, before app.js runs: a window kept dark under a light system was
|
||||
// first drawn light, its header's buttons fading to dark as they were read,
|
||||
// so they measured mid-way (3.96:1 for the view shown). Chromium
|
||||
// and WebKit, English and Chinese; no backend, the API is faked here.
|
||||
const assert = require("node:assert/strict");
|
||||
const fs = require("node:fs/promises");
|
||||
@@ -18,9 +22,10 @@ const { chromium, webkit } = require("playwright");
|
||||
|
||||
const assets = path.resolve(__dirname, "../assets");
|
||||
|
||||
function server(lang, theme) {
|
||||
function server(lang, theme, gate) {
|
||||
return async (route) => {
|
||||
const url = new URL(route.request().url());
|
||||
if (url.pathname === "/app.js") await gate;
|
||||
if (url.pathname === "/boot.js") return route.fulfill({ contentType: "text/javascript", body: `window.bootPrefs = {lang:"${lang}",theme:"${theme}",web:false};` });
|
||||
if (url.pathname === "/wails/runtime.js") return route.fulfill({ contentType: "text/javascript", body: "export const Window = {};" });
|
||||
if (url.pathname === "/api/state") return route.fulfill({ json: { agents: [], profiles: [], settings: { lang, theme } } });
|
||||
@@ -101,10 +106,20 @@ for (const engine of (process.env.BROWSER ? [process.env.BROWSER] : ["chromium",
|
||||
const ctx = await browser.newContext({ viewport: { width: 1000, height: 640 }, colorScheme: scheme });
|
||||
const page = await ctx.newPage();
|
||||
page.on("pageerror", (e) => errors.push(e.message));
|
||||
await page.route("**/*", server(lang, theme));
|
||||
await page.goto("http://magpie.test/");
|
||||
let release;
|
||||
const gate = new Promise((r) => { release = r; });
|
||||
await page.route("**/*", server(lang, theme, gate));
|
||||
// the page as first drawn, app.js held back: already in its theme
|
||||
const loaded = page.goto("http://magpie.test/");
|
||||
await page.waitForSelector("#nav", { state: "attached" });
|
||||
const first = await page.evaluate(() => getComputedStyle(document.body).backgroundColor);
|
||||
release();
|
||||
await loaded;
|
||||
await page.waitForSelector("#nav button.on");
|
||||
await page.waitForFunction(() => document.querySelector("#nav .thumb")?.getBoundingClientRect().width > 0);
|
||||
assert.equal(first, await page.evaluate(() => getComputedStyle(document.body).backgroundColor), "the page was first drawn in another theme");
|
||||
// what is drawn once it has settled, not a colour on its way
|
||||
await page.evaluate(() => Promise.all(document.getAnimations().filter((a) => a.transitionProperty).map((a) => a.finished.catch(() => {}))));
|
||||
const r = await ratios(page), at = JSON.stringify(r);
|
||||
for (const [what, v] of Object.entries(r)) {
|
||||
if (what === "thumb against the track") continue;
|
||||
|
||||
Reference in new issue
Block a user