webui: Prevent sending messages while uploads are in progress
This fixes an issue where users could press Enter immediately after pasting an image,
which would submit the message with just the '[Uploading image.png...]' placeholder text.
Now the system:
1. Tracks uploads in progress
2. Prevents message submission while uploads are active
3. Shows visual feedback to the user
4. Disables the send button during uploads
diff --git a/webui/src/web-components/sketch-chat-input.ts b/webui/src/web-components/sketch-chat-input.ts
index 69dd44c..ca6afbf 100644
--- a/webui/src/web-components/sketch-chat-input.ts
+++ b/webui/src/web-components/sketch-chat-input.ts
@@ -9,6 +9,12 @@
@state()
isDraggingOver: boolean = false;
+ @state()
+ uploadsInProgress: number = 0;
+
+ @state()
+ showUploadInProgressMessage: boolean = false;
+
// See https://lit.dev/docs/components/styles/ for how lit-element handles CSS.
// Note that these styles only apply to the scope of this web component's
// shadow DOM node, so they won't leak out or collide with CSS declared in
@@ -62,6 +68,11 @@
background-color: #0d8bf2;
}
+ #sendChatButton:disabled {
+ background-color: #b0b0b0;
+ cursor: not-allowed;
+ }
+
/* Drop zone styling */
.drop-zone-overlay {
position: absolute;
@@ -79,13 +90,37 @@
pointer-events: none;
}
- .drop-zone-message {
+ .drop-zone-message,
+ .upload-progress-message {
background-color: #ffffff;
padding: 15px 20px;
border-radius: 4px;
font-weight: 600;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
+
+ .upload-progress-message {
+ position: absolute;
+ bottom: 70px;
+ left: 50%;
+ transform: translateX(-50%);
+ background-color: #fff9c4;
+ border: 1px solid #fbc02d;
+ z-index: 20;
+ font-size: 14px;
+ animation: fadeIn 0.3s ease-in-out;
+ }
+
+ @keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: translateX(-50%) translateY(10px);
+ }
+ to {
+ opacity: 1;
+ transform: translateX(-50%) translateY(0);
+ }
+ }
`;
constructor() {
@@ -108,10 +143,13 @@
const textBefore = this.content.substring(0, insertPosition);
const textAfter = this.content.substring(insertPosition);
- // Add a loading indicator
- const loadingText = `[Uploading ${file.name}...]`;
+ // Add a loading indicator with a visual cue
+ const loadingText = `[🔄 Uploading ${file.name}...]`;
this.content = `${textBefore}${loadingText}${textAfter}`;
+ // Increment uploads in progress counter
+ this.uploadsInProgress++;
+
// Adjust spacing immediately to show loading indicator
requestAnimationFrame(() => this.adjustChatSpacing());
@@ -159,6 +197,9 @@
});
throw error;
+ } finally {
+ // Always decrement the counter, even if there was an error
+ this.uploadsInProgress--;
}
}
@@ -260,15 +301,35 @@
}
sendChatMessage() {
- const event = new CustomEvent("send-chat", {
- detail: { message: this.content },
- bubbles: true,
- composed: true,
- });
- this.dispatchEvent(event);
+ // Prevent sending if there are uploads in progress
+ if (this.uploadsInProgress > 0) {
+ console.log(
+ `Message send prevented: ${this.uploadsInProgress} uploads in progress`,
+ );
- // TODO(philip?): Ideally we only clear the content if the send is successful.
- this.content = ""; // Clear content after sending
+ // Show message to user
+ this.showUploadInProgressMessage = true;
+
+ // Hide the message after 3 seconds
+ setTimeout(() => {
+ this.showUploadInProgressMessage = false;
+ }, 3000);
+
+ return;
+ }
+
+ // Only send if there's actual content (not just whitespace)
+ if (this.content.trim()) {
+ const event = new CustomEvent("send-chat", {
+ detail: { message: this.content },
+ bubbles: true,
+ composed: true,
+ });
+ this.dispatchEvent(event);
+
+ // TODO(philip?): Ideally we only clear the content if the send is successful.
+ this.content = ""; // Clear content after sending
+ }
}
adjustChatSpacing() {
@@ -351,8 +412,12 @@
@input="${this._chatInputChanged}"
.value=${this.content || ""}
></textarea>
- <button @click="${this._sendChatClicked}" id="sendChatButton">
- Send
+ <button
+ @click="${this._sendChatClicked}"
+ id="sendChatButton"
+ ?disabled=${this.uploadsInProgress > 0}
+ >
+ ${this.uploadsInProgress > 0 ? "Uploading..." : "Send"}
</button>
</div>
${this.isDraggingOver
@@ -362,6 +427,13 @@
</div>
`
: ""}
+ ${this.showUploadInProgressMessage
+ ? html`
+ <div class="upload-progress-message">
+ Please wait for file upload to complete before sending
+ </div>
+ `
+ : ""}
</div>
`;
}