Add activity indicator for chat operations

Shows a pulsing dot with status text during workflow execution, LLM
thinking, and tool use. Disables the input and send button while active
to prevent duplicate submissions. Also restructures the chat layout to
use flexbox with the input container locked at the bottom.
This commit is contained in:
2026-05-21 10:48:07 +02:00
parent db96858222
commit 949e7d77ff
3 changed files with 187 additions and 11 deletions
+55 -1
View File
@@ -10885,6 +10885,8 @@ var ChatView = class extends import_obsidian5.ItemView {
this.removeLogListener = null;
this.showLogsClickHandler = null;
this.chatScrollHandler = null;
// Activity indicator
this.activityIndicatorEl = null;
this.messages = [];
this.lastMessageEl = null;
this.newChatButton = null;
@@ -11182,9 +11184,27 @@ var ChatView = class extends import_obsidian5.ItemView {
} else {
inputContainer.appendChild(this.sendButton);
}
if (!this.activityIndicatorEl) {
this.activityIndicatorEl = inputContainer.createEl("div", {
cls: "ollama-activity-indicator"
});
this.activityIndicatorEl.createEl("span", { cls: "ollama-activity-dot" });
this.activityIndicatorEl.createEl("span", {
cls: "ollama-activity-text",
text: ""
});
this.hideActivityIndicator();
} else {
inputContainer.appendChild(this.activityIndicatorEl);
}
if (this.contentEl.addClass) {
this.contentEl.addClass("ollama-chat-view-content");
} else {
this.contentEl.classList?.add("ollama-chat-view-content");
}
this.contentEl.appendChild(newChatContainer);
this.contentEl.appendChild(inputContainer);
this.contentEl.appendChild(container);
this.contentEl.appendChild(inputContainer);
if (this.shouldAutoScroll && container) {
container.scrollTop = container.scrollHeight;
}
@@ -11940,11 +11960,14 @@ ${action.preview.after.slice(0, 500)}`
this.lastMessageEl = previousStreamingEl;
}
if (isWorkflowCommand) {
this.showActivityIndicator("Running workflow\u2026");
await this.handleWorkflowRequest(actualMessage, assistantMessageId);
this.hideActivityIndicator();
this.cleanupStreamingResources();
return;
}
try {
this.showActivityIndicator("Thinking\u2026");
const noteContext = await this.noteContextBuilder.buildContext(
actualMessage,
this.settings.vaultSearchLimit,
@@ -12003,6 +12026,7 @@ ${actualMessage}` : actualMessage;
durationMs: llmDurationMs
});
if (toolCalls.length > 0) {
this.showActivityIndicator("Using tools\u2026");
await this.processToolCalls(
toolCalls,
messagesWithMemory,
@@ -12016,6 +12040,7 @@ ${actualMessage}` : actualMessage;
if (toolCalls.length === 0 && toolCapableModes.includes(this.currentAgentMode) && fullResponse.trim().length > 0) {
shouldFallbackToReadTools = this.shouldAutoRunReadTools(fullResponse);
if (shouldFallbackToReadTools) {
this.showActivityIndicator("Thinking\u2026");
const nudgeMessages = [
...messagesWithMemory,
{ role: "assistant", content: fullResponse },
@@ -12041,6 +12066,7 @@ ${actualMessage}` : actualMessage;
}
}
if (toolCalls.length > 0) {
this.showActivityIndicator("Using tools\u2026");
await this.processToolCalls(
toolCalls,
nudgeMessages,
@@ -12057,6 +12083,7 @@ ${actualMessage}` : actualMessage;
if (toolCalls.length === 0 && shouldFallbackToReadTools) {
const autoToolCalls = this.buildAutomaticReadToolCalls(actualMessage, tools);
if (autoToolCalls.length > 0) {
this.showActivityIndicator("Using tools\u2026");
toolCalls = autoToolCalls;
fullResponse = "";
await this.processToolCalls(
@@ -12120,6 +12147,7 @@ ${actualMessage}` : actualMessage;
});
this.syncMessagesToSession();
} finally {
this.hideActivityIndicator();
this.cleanupStreamingResources();
}
}
@@ -12182,6 +12210,32 @@ ${actualMessage}` : actualMessage;
}
return message.replace(/\bplease\b/gi, "").replace(/\bcontinue\b/gi, "").replace(/\bimplement\b/gi, "").replace(/\bcreate\b/gi, "").replace(/\bmove\b/gi, "").replace(/\bnotes?\b/gi, "").replace(/\bfolders?\b/gi, "").replace(/\bstructure\b/gi, "").replace(/\s+/g, " ").trim();
}
showActivityIndicator(text) {
if (!this.activityIndicatorEl) return;
const textEl = this.activityIndicatorEl.querySelector(".ollama-activity-text");
if (textEl) {
textEl.textContent = text;
}
this.activityIndicatorEl.style.display = "flex";
if (this.sendButton && this.sendButton instanceof HTMLButtonElement) {
this.sendButton.disabled = true;
this.sendButton.textContent = "Working\u2026";
}
if (this.inputEl) {
this.inputEl.disabled = true;
}
}
hideActivityIndicator() {
if (!this.activityIndicatorEl) return;
this.activityIndicatorEl.style.display = "none";
if (this.sendButton && this.sendButton instanceof HTMLButtonElement) {
this.sendButton.disabled = false;
this.sendButton.textContent = "Send";
}
if (this.inputEl) {
this.inputEl.disabled = false;
}
}
createOllamaClient(model, settings) {
return new OllamaClient(settings.ollamaUrl, model, void 0, settings.cacheConfig);
}