Allow sending current conversation state

This commit is contained in:
dwrz
2026-06-13 00:44:01 +00:00
parent 0c1346bd77
commit 4b629a2bc7

View File

@@ -120,6 +120,7 @@ class Odidere {
this.#clearAttachments(); this.#clearAttachments();
this.$textInput.value = ''; this.$textInput.value = '';
this.$textInput.style.height = 'auto'; this.$textInput.style.height = 'auto';
this.#updateSendButtonState();
} }
// ==================== // ====================
@@ -258,6 +259,7 @@ class Odidere {
// Render the active path. // Render the active path.
const activePath = this.getActivePath(); const activePath = this.getActivePath();
this.#renderMessages(activePath); this.#renderMessages(activePath);
this.#updateSendButtonState();
} catch (e) { } catch (e) {
console.error('failed to load history:', e); console.error('failed to load history:', e);
this.messagesMap.clear(); this.messagesMap.clear();
@@ -349,6 +351,7 @@ class Odidere {
} }
this.#saveToStorage(); this.#saveToStorage();
this.#updateSendButtonState();
return messages; return messages;
} }
@@ -449,6 +452,7 @@ class Odidere {
} }
this.#saveToStorage(); this.#saveToStorage();
this.#updateSendButtonState();
} }
/** /**
@@ -572,6 +576,7 @@ class Odidere {
const maxHeight = parseFloat(computed.maxHeight); const maxHeight = parseFloat(computed.maxHeight);
const newHeight = Math.min(textarea.scrollHeight, maxHeight); const newHeight = Math.min(textarea.scrollHeight, maxHeight);
textarea.style.height = `${newHeight}px`; textarea.style.height = `${newHeight}px`;
this.#updateSendButtonState();
}; };
/** /**
@@ -592,6 +597,7 @@ class Odidere {
this.attachments.push(file); this.attachments.push(file);
} }
this.#renderAttachments(); this.#renderAttachments();
this.#updateSendButtonState();
this.$fileInput.value = ''; this.$fileInput.value = '';
} }
@@ -1025,9 +1031,6 @@ class Odidere {
*/ */
async #submitText() { async #submitText() {
const text = this.$textInput.value.trim(); const text = this.$textInput.value.trim();
const hasContent = text || this.attachments.length > 0;
if (!hasContent) return;
if (this.isProcessing) return; if (this.isProcessing) return;
this.#stopCurrentAudio(); this.#stopCurrentAudio();
@@ -1060,20 +1063,25 @@ class Odidere {
this.currentController = new AbortController(); this.currentController = new AbortController();
try { try {
// Build the user message with text and attachments. const hasNewInput = text || this.attachments.length > 0 || audio;
const userMessage = await this.#buildUserMessage(text, this.attachments);
const hasContent = text || this.attachments.length > 0 || audio;
if (!hasContent) {
this.#setLoadingState(false);
return;
}
// Build messages array from active path + current user message. // Build messages array from active path + current user message.
const activePath = this.getActivePath(); const activePath = this.getActivePath();
const messages = [ let messages;
...activePath.map(({ parent, children, id, meta, ...msg }) => msg), let userMessage;
userMessage,
]; if (hasNewInput) {
userMessage = await this.#buildUserMessage(text, this.attachments);
messages = [
...activePath.map(({ parent, children, id, meta, ...msg }) => msg),
userMessage,
];
} else {
// Continue conversation: send existing history without a new user message.
messages = activePath.map(
({ parent, children, id, meta, ...msg }) => msg,
);
}
const payload = { const payload = {
messages, messages,
@@ -1091,9 +1099,9 @@ class Odidere {
// Clear attachments after building payload (before async operations). // Clear attachments after building payload (before async operations).
this.#clearAttachments(); this.#clearAttachments();
// For text-only requests (no audio), add to history and render // For text-only requests with new input, add to history and render
// immediately. Use the returned messages (with IDs) for rendering. // immediately. Skip when continuing conversation (no new user message).
if (!audio) { if (!audio && hasNewInput) {
const appended = this.#appendHistory([userMessage]); const appended = this.#appendHistory([userMessage]);
this.#renderMessages(appended); this.#renderMessages(appended);
} }
@@ -1310,6 +1318,23 @@ class Odidere {
// ==================== // ====================
// STATE // STATE
// ==================== // ====================
/**
* #updateSendButtonState enables the send button when there is text,
* attachments, or at least one message in the conversation history,
* and disables it otherwise.
*/
#updateSendButtonState() {
const hasText = this.$textInput.value.trim().length > 0;
const hasAttachments = this.attachments.length > 0;
const hasHistory = this.messagesMap.size > 0;
const enabled = hasText || hasAttachments || hasHistory;
this.$send.disabled = !enabled;
this.$send.setAttribute(
'aria-label',
enabled ? 'Send message' : 'Start a conversation to enable send',
);
}
/** /**
* #setLoadingState updates UI to reflect loading state. * #setLoadingState updates UI to reflect loading state.
* @param {boolean} loading * @param {boolean} loading
@@ -1813,6 +1838,7 @@ class Odidere {
#removeAttachment(index) { #removeAttachment(index) {
this.attachments.splice(index, 1); this.attachments.splice(index, 1);
this.#renderAttachments(); this.#renderAttachments();
this.#updateSendButtonState();
} }
/** /**