mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-03 17:14:06 +00:00
fix(webchat): scope attachment button input
This commit is contained in:
committed by
Peter Steinberger
parent
0c044596c5
commit
cf70bdcceb
@@ -61,6 +61,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- WebChat: summarize internal message-tool source replies so tool cards no longer duplicate the visible reply body. (#84773) Thanks @jason-allen-oneal.
|
||||
- WebChat: scope the visible attachment button to its own composer file input so clicking Upload reliably opens the file picker. (#83952, fixes #47983) Thanks @jason-allen-oneal.
|
||||
- Gateway: preserve deferred lifecycle-error cleanup across later non-terminal events so provider timeouts can persist failed session state instead of leaving sessions stuck running. (#85256, fixes #63819) Thanks @samzong.
|
||||
- Agents/subagents: report tool-only child progress during timeout summaries instead of showing no visible output.
|
||||
- Telegram/ACP: preserve explicit `:topic:` conversation suffixes when inbound ACP targets do not carry a separate thread id.
|
||||
|
||||
@@ -1070,6 +1070,26 @@ describe("chat attachment picker", () => {
|
||||
expect(getChatAttachmentDataUrl(attachments[0])).toBe(`data:image/png;base64,${base64}`);
|
||||
});
|
||||
|
||||
it("opens the scoped file input from the visible attach button", () => {
|
||||
const container = renderChatView();
|
||||
const input = requireElement(
|
||||
container,
|
||||
".agent-chat__file-input",
|
||||
"attachment file input",
|
||||
) as HTMLInputElement;
|
||||
const attachButton = requireElement(
|
||||
container,
|
||||
`[aria-label="${t("chat.composer.attachFile")}"]`,
|
||||
"attach button",
|
||||
) as HTMLButtonElement;
|
||||
const clickInput = vi.spyOn(input, "click").mockImplementation(() => undefined);
|
||||
|
||||
attachButton.click();
|
||||
|
||||
expect(attachButton.type).toBe("button");
|
||||
expect(clickInput).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("accepts and previews non-video file attachments", async () => {
|
||||
const onAttachmentsChange = vi.fn();
|
||||
const container = renderChatView({ onAttachmentsChange });
|
||||
|
||||
@@ -427,6 +427,17 @@ function focusComposerFromChrome(event: MouseEvent, connected: boolean) {
|
||||
?.focus({ preventScroll: true });
|
||||
}
|
||||
|
||||
function clickComposerFileInput(event: MouseEvent) {
|
||||
const target = event.currentTarget;
|
||||
if (!(target instanceof HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
target
|
||||
.closest(".agent-chat__input")
|
||||
?.querySelector<HTMLInputElement>(".agent-chat__file-input")
|
||||
?.click();
|
||||
}
|
||||
|
||||
function restoreHistoryCaret(target: HTMLTextAreaElement, direction: "up" | "down") {
|
||||
requestAnimationFrame(() => {
|
||||
if (document.activeElement !== target) {
|
||||
@@ -1562,10 +1573,9 @@ export function renderChat(props: ChatProps) {
|
||||
<div class="agent-chat__toolbar">
|
||||
<div class="agent-chat__toolbar-left">
|
||||
<button
|
||||
type="button"
|
||||
class="agent-chat__input-btn"
|
||||
@click=${() => {
|
||||
document.querySelector<HTMLInputElement>(".agent-chat__file-input")?.click();
|
||||
}}
|
||||
@click=${clickComposerFileInput}
|
||||
title=${t("chat.composer.attachFile")}
|
||||
aria-label=${t("chat.composer.attachFile")}
|
||||
?disabled=${!props.connected}
|
||||
|
||||
Reference in New Issue
Block a user