mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 17:10:43 -10:00
fix(studio): the pin button hides until its row is hovered, a pinned row keeps a marker, and the model menu's image badge no longer wraps
.ds-row .sesspin-action set display: grid in a later rule of equal specificity than the one hiding it, so every row showed the button at rest. A pinned row shows .ds-pin at rest when quick actions are on, as it already did when they are off. The badge in the model menu could shrink to one character per line beside a long name; it is now flex: none. Both are held by perf scripts and a rows.css rule test.
This commit is contained in:
1 parent
3db2fc12a6
commit
03943d8a84
7 files changed
+106
-10
No files matched your search
@@ -0,0 +1,28 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { chromium } from "playwright";
|
||||
|
||||
const PAGE = process.env.PERF_URL ?? "http://localhost:4399/perf.html?pref=zh";
|
||||
const browser = await chromium.launch();
|
||||
try {
|
||||
const page = await browser.newPage({ viewport: { width: 1300, height: 900 } });
|
||||
const errors = [];
|
||||
page.on("pageerror", (error) => errors.push(error.message));
|
||||
await page.goto(PAGE, { waitUntil: "networkidle" });
|
||||
await page.waitForSelector(".model-picker");
|
||||
await page.locator(".model-picker").first().click();
|
||||
await page.waitForSelector(".studio-model-menu .studio-item-line");
|
||||
const sizes = await page.evaluate(() => {
|
||||
const lines = [...document.querySelectorAll(".studio-model-menu .studio-item-line")].filter((line) => line.querySelector(".studio-item-badge"));
|
||||
for (const line of lines) line.querySelector(".lb").textContent = "workbuddy/deepseek-v4.1-flash-preview-extended";
|
||||
return lines.map((line) => {
|
||||
const badge = line.querySelector(".studio-item-badge").getBoundingClientRect();
|
||||
return { width: Math.round(badge.width), height: Math.round(badge.height) };
|
||||
});
|
||||
});
|
||||
assert.ok(sizes.length > 0, "the menu has a model that reads images");
|
||||
for (const size of sizes) assert.ok(size.height <= 20, `a long model name leaves the badge on one line (${JSON.stringify(size)})`);
|
||||
assert.deepEqual(errors, []);
|
||||
console.log(`PASS model menu badge stays on one line beside a long name (${sizes.length} rows)`);
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { chromium } from "playwright";
|
||||
|
||||
const PAGE = process.env.PERF_URL ?? "http://localhost:4399/perf.html?pref=zh";
|
||||
const browser = await chromium.launch();
|
||||
try {
|
||||
const page = await browser.newPage({ viewport: { width: 1300, height: 900 } });
|
||||
const errors = [];
|
||||
page.on("pageerror", (error) => errors.push(error.message));
|
||||
await page.addInitScript(() => localStorage.setItem("rx-session-quick-actions", "on"));
|
||||
await page.goto(PAGE, { waitUntil: "networkidle" });
|
||||
await page.waitForSelector(".ds-row.sessrow");
|
||||
await page.waitForTimeout(500);
|
||||
const shown = (row, selector) =>
|
||||
row.evaluate((el, sel) => {
|
||||
const node = el.querySelector(sel);
|
||||
return !!node && getComputedStyle(node).display !== "none" && node.getBoundingClientRect().width > 0;
|
||||
}, selector);
|
||||
const rows = page.locator(".ds-row.sessrow");
|
||||
await page.mouse.move(700, 450);
|
||||
for (let i = 0; i < Math.min(await rows.count(), 5); i++) {
|
||||
assert.equal(await shown(rows.nth(i), ".sesspin-action"), false, `row ${i}: a resting row shows no pin button`);
|
||||
assert.equal(await shown(rows.nth(i), ".sesspin-marker"), false, `row ${i}: an unpinned row shows no pin marker`);
|
||||
}
|
||||
const first = rows.first();
|
||||
await first.hover();
|
||||
assert.equal(await shown(first, ".sesspin-action"), true, "hovering a row offers the pin button");
|
||||
await first.locator(".sesspin-action").click();
|
||||
await page.waitForTimeout(400);
|
||||
await page.evaluate(() => document.activeElement?.blur());
|
||||
await page.mouse.move(700, 450);
|
||||
await page.waitForTimeout(200);
|
||||
const pinned = page.locator('.ds-row.sessrow:has(.sesspin-marker)').first();
|
||||
assert.equal(await shown(pinned, ".sesspin-marker"), true, "a pinned row keeps its marker while the pointer is away");
|
||||
assert.equal(await shown(pinned, ".sesspin-action"), false, "and still hides the button");
|
||||
await pinned.hover();
|
||||
assert.equal(await shown(pinned, ".sesspin-marker"), false, "the marker gives way to the button under the pointer");
|
||||
assert.equal(await shown(pinned, ".sesspin-action"), true);
|
||||
assert.deepEqual(errors, []);
|
||||
console.log("PASS session row pin button and marker");
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
@@ -132,6 +132,7 @@
|
||||
:root .composer-menu.studio-model-menu .studio-item-line { flex-wrap: nowrap; align-items: center; gap: 8px; }
|
||||
:root .composer-menu.studio-model-menu .studio-item-line > .lb { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--w-med) var(--fs-ui)/1.3 var(--ui); }
|
||||
:root .composer-menu.studio-model-menu .studio-item-meta { flex: none; color: var(--faint); font: var(--w-reg) var(--fs-micro)/1.3 var(--ui); white-space: nowrap; }
|
||||
:root .composer-menu.studio-model-menu .studio-item-badge { flex: none; white-space: nowrap; }
|
||||
:root .composer-menu.studio-model-menu .mi[data-on]::after { color: var(--net-ink); }
|
||||
:root .composer-menu.studio-effort-menu .mi.head { padding: 12px 14px 8px; }
|
||||
:root .composer-menu.studio-effort-menu .mi.head:first-child .lb { color: var(--text); font: var(--w-semi) var(--fs-ui)/1.3 var(--ui); }
|
||||
|
||||
@@ -48,8 +48,10 @@
|
||||
@media (hover: none) { .ds-row .ds-more { display: grid; } }
|
||||
.ds-row .ds-pin { width: 12px; height: 12px; flex: none; }
|
||||
.ds-row .sessquick, .ds-row .sesspin-action { flex: none; display: none; }
|
||||
.ds-row:is(:hover, :focus-within) .sessquick, .ds-row:is(:hover, :focus-within) .sesspin-action { display: flex; }
|
||||
.ds-row .sessquick > button, .ds-row .sesspin-action { width: 24px; height: 28px; padding: 0; display: grid; place-items: center; border: 0; border-radius: var(--r-xs); background: transparent; color: var(--faint); cursor: pointer; }
|
||||
.ds-row:is(:hover, :focus-within) .sessquick { display: flex; }
|
||||
.ds-row:is(:hover, :focus-within) .sesspin-action { display: grid; }
|
||||
.ds-row .sessquick > button, .ds-row .sesspin-action { width: 24px; height: 28px; padding: 0; place-items: center; border: 0; border-radius: var(--r-xs); background: transparent; color: var(--faint); cursor: pointer; }
|
||||
.ds-row .sessquick > button { display: grid; }
|
||||
.ds-row .sessquick > button:hover, .ds-row .sesspin-action:hover { background: var(--raised); color: var(--text); }
|
||||
.ds-row .sessquick > button:disabled, .ds-row .sesspin-action:disabled { opacity: .35; cursor: default; }
|
||||
.ds-row .sessquick .studio-icon, .ds-row .sesspin-action .studio-icon { width: 14px; height: 14px; }
|
||||
|
||||
@@ -32,4 +32,10 @@ describe("session and project rows follow the board", () => {
|
||||
expect(rule(".ds-row:is(:hover, :focus-within) > :is(.ds-meta, .ds-pin)")).toMatch(/display:\s*none/);
|
||||
expect(rule(".ds-row:is(:hover, :focus-within) .ds-more")).toMatch(/display:\s*grid/);
|
||||
});
|
||||
|
||||
it("keeps the pin button hidden until the row is hovered or focused", () => {
|
||||
expect(rule(".ds-row .sessquick, .ds-row .sesspin-action")).toMatch(/display:\s*none/);
|
||||
expect(rule(".ds-row .sessquick > button, .ds-row .sesspin-action")).not.toMatch(/display:/);
|
||||
expect(rule(".ds-row:is(:hover, :focus-within) .sesspin-action")).toMatch(/display:\s*grid/);
|
||||
});
|
||||
});
|
||||
@@ -12,14 +12,18 @@ export function SessionPinAction({ target, title, pinned, enabled, disabled, onP
|
||||
enabled: boolean;
|
||||
onPin: () => void;
|
||||
}) {
|
||||
if (!enabled) return pinned ? <StudioIcon name="pin" className="sesspin-marker ds-pin" aria-label={t("session.pinned")} /> : null;
|
||||
return <button className="sesspin-action" data-action="session.pin" data-target={target}
|
||||
aria-pressed={pinned} disabled={disabled}
|
||||
title={t(pinned ? "common.unpin" : "common.pin_session")}
|
||||
aria-label={t(pinned ? "session.unpin_session_title" : "session.pin_session_title", { title })}
|
||||
onClick={(event) => { event.stopPropagation(); onPin(); }}>
|
||||
<StudioIcon name="pin" aria-label={pinned ? t("session.pinned") : undefined} />
|
||||
</button>;
|
||||
const marker = pinned ? <StudioIcon name="pin" className="sesspin-marker ds-pin" aria-label={enabled ? undefined : t("session.pinned")} aria-hidden={enabled ? true : undefined} /> : null;
|
||||
if (!enabled) return marker;
|
||||
return <>
|
||||
{marker}
|
||||
<button className="sesspin-action" data-action="session.pin" data-target={target}
|
||||
aria-pressed={pinned} disabled={disabled}
|
||||
title={t(pinned ? "common.unpin" : "common.pin_session")}
|
||||
aria-label={t(pinned ? "session.unpin_session_title" : "session.pin_session_title", { title })}
|
||||
onClick={(event) => { event.stopPropagation(); onPin(); }}>
|
||||
<StudioIcon name="pin" aria-label={pinned ? t("session.pinned") : undefined} />
|
||||
</button>
|
||||
</>;
|
||||
}
|
||||
|
||||
export function SessionArchiveAction({ target, title, archived, disabled, onArchive }: Target & {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
## 修复
|
||||
|
||||
- 修复 2.58.0 里,开着「会话行快捷按钮」时,侧栏每一行会话都一直显示一个置顶图标(不管有没有置顶):现在这个按钮只在鼠标移上去或键盘聚焦时才出现;已置顶的会话在没悬停时会一直显示一个小图钉,方便一眼看出(#15012)。
|
||||
- 修复输入框右下角的模型选单里,模型名字较长时,右边的「读图」标签被挤成两行竖着排的问题;现在标签始终在一行里完整显示(#15012)。
|
||||
|
||||
---
|
||||
<!-- lang:en -->
|
||||
|
||||
## Fixed
|
||||
|
||||
- With "Quick buttons on session rows" turned on, every session row in the sidebar showed a pin icon all the time, pinned or not (2.58.0). The button now appears only when the pointer is over the row or it has keyboard focus, and a pinned session keeps a small pin on the row while nothing is hovered (#15012).
|
||||
- In the model menu next to the message box, the "reads images" tag was squeezed into two stacked characters beside a long model name; it now stays whole on one line (#15012).
|
||||
Reference in new issue
Block a user