mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 11:41:04 +00:00
fix(desktop): lighten conversation timeline surfaces
This commit is contained in:
parent
5d678331d8
commit
ffd20b98a5
4 changed files with 468 additions and 36 deletions
|
|
@ -86,6 +86,8 @@ async function main() {
|
|||
await saveScreenshot('resolved-tool-activity.png');
|
||||
await assertAssistantMessageActions('assistant-message-actions.json');
|
||||
await saveScreenshot('assistant-message-actions.png');
|
||||
await assertConversationSurfaceFidelity('conversation-surface-fidelity.json');
|
||||
await saveScreenshot('conversation-surface-fidelity.png');
|
||||
await setElectronWindowBounds(target.id, compactWindowBounds);
|
||||
await assertCompactDenseConversationLayout(
|
||||
'compact-dense-conversation.json',
|
||||
|
|
@ -1133,6 +1135,242 @@ async function assertAssistantMessageActions(fileName) {
|
|||
}
|
||||
}
|
||||
|
||||
async function assertConversationSurfaceFidelity(fileName) {
|
||||
await waitForSelector('[data-testid="conversation-changes-summary"]');
|
||||
const snapshot = await evaluate(`(() => {
|
||||
const rectFor = (element) => {
|
||||
if (!element) {
|
||||
return null;
|
||||
}
|
||||
const rect = element.getBoundingClientRect();
|
||||
return {
|
||||
top: rect.top,
|
||||
right: rect.right,
|
||||
bottom: rect.bottom,
|
||||
left: rect.left,
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
};
|
||||
};
|
||||
const alphaFromColor = (color) => {
|
||||
if (!color || color === 'transparent') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const match = color.match(/rgba?\\(([^)]+)\\)/u);
|
||||
if (!match) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const parts = match[1].split(',').map((part) => part.trim());
|
||||
if (parts.length < 4) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const alpha = Number(parts[3]);
|
||||
return Number.isFinite(alpha) ? alpha : 1;
|
||||
};
|
||||
const numberFromPixel = (value) => {
|
||||
const number = Number.parseFloat(value);
|
||||
return Number.isFinite(number) ? number : 0;
|
||||
};
|
||||
const styleFor = (element) => {
|
||||
if (!element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const style = window.getComputedStyle(element);
|
||||
return {
|
||||
backgroundColor: style.backgroundColor,
|
||||
backgroundAlpha: alphaFromColor(style.backgroundColor),
|
||||
borderColor: style.borderTopColor,
|
||||
borderAlpha: alphaFromColor(style.borderTopColor),
|
||||
borderTopWidth: numberFromPixel(style.borderTopWidth),
|
||||
borderRightWidth: numberFromPixel(style.borderRightWidth),
|
||||
borderBottomWidth: numberFromPixel(style.borderBottomWidth),
|
||||
borderLeftWidth: numberFromPixel(style.borderLeftWidth),
|
||||
borderRadius: style.borderTopLeftRadius
|
||||
};
|
||||
};
|
||||
const assistantMessage = [
|
||||
...document.querySelectorAll('[data-testid="assistant-message"]')
|
||||
].find((candidate) =>
|
||||
candidate.innerText.includes('E2E fake ACP response received')
|
||||
);
|
||||
const userMessage = document.querySelector('.chat-message-user');
|
||||
const summary = document.querySelector(
|
||||
'[data-testid="conversation-changes-summary"]'
|
||||
);
|
||||
const summaryAction = summary?.querySelector(
|
||||
'button[aria-label="Review Changes"]'
|
||||
);
|
||||
const firstSummaryRow = summary?.querySelector(
|
||||
'.conversation-changes-list li'
|
||||
);
|
||||
const timeline = document.querySelector('.chat-timeline');
|
||||
const actionButtons = assistantMessage
|
||||
? [
|
||||
...assistantMessage.querySelectorAll(
|
||||
'[data-testid="assistant-message-actions"] button'
|
||||
)
|
||||
]
|
||||
: [];
|
||||
|
||||
return {
|
||||
assistant: {
|
||||
rect: rectFor(assistantMessage),
|
||||
style: styleFor(assistantMessage)
|
||||
},
|
||||
user: {
|
||||
rect: rectFor(userMessage),
|
||||
style: styleFor(userMessage)
|
||||
},
|
||||
summary: {
|
||||
rect: rectFor(summary),
|
||||
style: styleFor(summary),
|
||||
actionRect: rectFor(summaryAction),
|
||||
rowStyle: styleFor(firstSummaryRow)
|
||||
},
|
||||
timeline: rectFor(timeline),
|
||||
actionButtons: actionButtons.map((button) => ({
|
||||
label: button.getAttribute('aria-label') || '',
|
||||
rect: rectFor(button),
|
||||
style: styleFor(button)
|
||||
})),
|
||||
document: {
|
||||
viewportWidth: window.innerWidth,
|
||||
scrollWidth: document.documentElement.scrollWidth
|
||||
}
|
||||
};
|
||||
})()`);
|
||||
|
||||
await writeFile(
|
||||
join(artifactDir, fileName),
|
||||
`${JSON.stringify(snapshot, null, 2)}\n`,
|
||||
'utf8',
|
||||
);
|
||||
|
||||
if (
|
||||
!snapshot.assistant.rect ||
|
||||
!snapshot.assistant.style ||
|
||||
!snapshot.user.rect ||
|
||||
!snapshot.user.style ||
|
||||
!snapshot.summary.rect ||
|
||||
!snapshot.summary.style ||
|
||||
!snapshot.summary.actionRect ||
|
||||
!snapshot.summary.rowStyle ||
|
||||
!snapshot.timeline
|
||||
) {
|
||||
throw new Error(
|
||||
`Conversation surface fidelity metrics are missing: ${JSON.stringify(
|
||||
snapshot,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
const assistantBorders = [
|
||||
snapshot.assistant.style.borderTopWidth,
|
||||
snapshot.assistant.style.borderRightWidth,
|
||||
snapshot.assistant.style.borderBottomWidth,
|
||||
snapshot.assistant.style.borderLeftWidth,
|
||||
];
|
||||
if (assistantBorders.some((width) => width > 0)) {
|
||||
throw new Error(
|
||||
`Assistant message should render as unframed timeline prose: ${JSON.stringify(
|
||||
snapshot.assistant.style,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (snapshot.assistant.style.backgroundAlpha > 0.02) {
|
||||
throw new Error(
|
||||
`Assistant message background is too card-like: ${JSON.stringify(
|
||||
snapshot.assistant.style,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
snapshot.assistant.rect.left < snapshot.timeline.left ||
|
||||
snapshot.assistant.rect.right > snapshot.timeline.right + 1
|
||||
) {
|
||||
throw new Error('Assistant message escaped the conversation timeline.');
|
||||
}
|
||||
|
||||
if (
|
||||
snapshot.user.rect.width > 620 ||
|
||||
snapshot.user.style.backgroundAlpha < 0.05 ||
|
||||
snapshot.user.style.borderTopWidth < 1
|
||||
) {
|
||||
throw new Error(
|
||||
`User prompt bubble lost compact bubble treatment: ${JSON.stringify(
|
||||
snapshot.user,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
snapshot.summary.style.borderAlpha > 0.14 ||
|
||||
snapshot.summary.style.backgroundAlpha > 0.045
|
||||
) {
|
||||
throw new Error(
|
||||
`Changed-files summary surface is too visually heavy: ${JSON.stringify(
|
||||
snapshot.summary.style,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (snapshot.summary.rect.height > 158) {
|
||||
throw new Error(
|
||||
`Changed-files summary should stay compact: ${JSON.stringify(
|
||||
snapshot.summary.rect,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (snapshot.summary.rowStyle.backgroundAlpha > 0.04) {
|
||||
throw new Error(
|
||||
`Changed-files rows should not look like nested cards: ${JSON.stringify(
|
||||
snapshot.summary.rowStyle,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (snapshot.summary.actionRect.height > 34) {
|
||||
throw new Error(
|
||||
`Changed-files action is too tall: ${JSON.stringify(
|
||||
snapshot.summary.actionRect,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
for (const button of snapshot.actionButtons) {
|
||||
if (!button.rect || !button.style) {
|
||||
throw new Error(
|
||||
`Assistant action button metrics are missing: ${JSON.stringify(
|
||||
button,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (button.rect.width > 32 || button.rect.height > 32) {
|
||||
throw new Error(
|
||||
`Assistant action button should remain compact: ${JSON.stringify(
|
||||
button,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (snapshot.document.scrollWidth > snapshot.document.viewportWidth + 4) {
|
||||
throw new Error(
|
||||
`Conversation surface introduced horizontal document overflow: ${JSON.stringify(
|
||||
snapshot.document,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function assertCompactDenseConversationLayout(fileName) {
|
||||
await waitFor(
|
||||
'compact dense conversation viewport',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue