From 921a243b0d4f4620ea8672b54125108427e2016e Mon Sep 17 00:00:00 2001 From: perf3ct Date: Fri, 28 Mar 2025 20:16:16 +0000 Subject: [PATCH] "Chat with Notes" launcher works --- .../app/widgets/type_widgets/ai_chat.ts | 89 +++++++++++++------ src/services/hidden_subtree_launcherbar.ts | 4 +- translations/en/server.json | 3 +- 3 files changed, 68 insertions(+), 28 deletions(-) diff --git a/src/public/app/widgets/type_widgets/ai_chat.ts b/src/public/app/widgets/type_widgets/ai_chat.ts index 6386fb898..304cbcf6c 100644 --- a/src/public/app/widgets/type_widgets/ai_chat.ts +++ b/src/public/app/widgets/type_widgets/ai_chat.ts @@ -3,10 +3,12 @@ import LlmChatPanel from "../llm_chat_panel.js"; import { type EventData } from "../../components/app_context.js"; import type FNote from "../../entities/fnote.js"; import server from "../../services/server.js"; +import toastService from "../../services/toast.js"; export default class AiChatTypeWidget extends TypeWidget { private llmChatPanel: LlmChatPanel; private isInitialized: boolean = false; + private initPromise: Promise | null = null; constructor() { super(); @@ -25,28 +27,51 @@ export default class AiChatTypeWidget extends TypeWidget { } async doRefresh(note: FNote | null | undefined) { - // Initialize the chat panel if not already done - if (!this.isInitialized) { - console.log("Initializing AI Chat Panel for note:", note?.noteId); - await this.llmChatPanel.refresh(); - this.isInitialized = true; - } - - // If this is a newly created note, we can initialize the content - if (note) { - try { - const content = await note.getContent(); - // Check if content is empty - if (!content || content === '{}') { - // Initialize with empty chat history - await this.saveData({ - messages: [], - title: note.title - }); - } - } catch (e) { - console.error("Error initializing AI Chat note content:", e); + try { + // If we're already initializing, wait for that to complete + if (this.initPromise) { + await this.initPromise; + return; } + + // Only initialize once + if (!this.isInitialized) { + console.log("Initializing AI Chat Panel for note:", note?.noteId); + + // Create a promise to track initialization + this.initPromise = (async () => { + try { + await this.llmChatPanel.refresh(); + this.isInitialized = true; + } catch (e) { + console.error("Error initializing LlmChatPanel:", e); + toastService.showError("Failed to initialize chat panel. Try reloading."); + } + })(); + + await this.initPromise; + this.initPromise = null; + } + + // If this is a newly created note, we can initialize the content + if (note) { + try { + const content = await note.getContent(); + // Check if content is empty + if (!content || content === '{}') { + // Initialize with empty chat history + await this.saveData({ + messages: [], + title: note.title + }); + } + } catch (e) { + console.error("Error initializing AI Chat note content:", e); + } + } + } catch (e) { + console.error("Error in doRefresh:", e); + toastService.showError("Error refreshing chat. Please try again."); } } @@ -55,10 +80,23 @@ export default class AiChatTypeWidget extends TypeWidget { } async activeContextChangedEvent(data: EventData<"activeContextChanged">) { - // Only refresh when this becomes active and we're not initialized yet - if (this.isActive() && !this.isInitialized) { - await this.llmChatPanel.refresh(); - this.isInitialized = true; + // Only initialize if this becomes active and we're not initialized yet + if (this.isActive() && !this.isInitialized && !this.initPromise) { + try { + this.initPromise = (async () => { + try { + await this.llmChatPanel.refresh(); + this.isInitialized = true; + } catch (e) { + console.error("Error initializing LlmChatPanel:", e); + } + })(); + + await this.initPromise; + this.initPromise = null; + } catch (e) { + console.error("Error in activeContextChangedEvent:", e); + } } } @@ -74,6 +112,7 @@ export default class AiChatTypeWidget extends TypeWidget { }); } catch (e) { console.error("Error saving AI Chat data:", e); + toastService.showError("Failed to save chat data"); } } diff --git a/src/services/hidden_subtree_launcherbar.ts b/src/services/hidden_subtree_launcherbar.ts index 061b7207d..48c2600bb 100644 --- a/src/services/hidden_subtree_launcherbar.ts +++ b/src/services/hidden_subtree_launcherbar.ts @@ -70,10 +70,10 @@ export default function buildLaunchBarConfig() { { id: "_lbNoteMap", title: t("hidden-subtree.note-map-title"), type: "launcher", targetNoteId: "_globalNoteMap", icon: "bx bxs-network-chart" }, { id: "_lbLlmChat", - title: t("hidden-subtree.ai-chat-title"), + title: t("hidden-subtree.llm-chat-title"), type: "launcher", + command: "createAiChat", icon: "bx bx-bot", - builtinWidget: "aiChatLauncher", attributes: [ { type: "label", name: "desktopOnly" } ] diff --git a/translations/en/server.json b/translations/en/server.json index ee1c5a9e2..3d700286e 100644 --- a/translations/en/server.json +++ b/translations/en/server.json @@ -247,7 +247,8 @@ "advanced-title": "Advanced", "visible-launchers-title": "Visible Launchers", "user-guide": "User Guide", - "localization": "Language & Region" + "localization": "Language & Region", + "inbox-title": "Inbox" }, "notes": { "new-note": "New note",