From 04e0266a4e02faceacecfa5e338b6ac9db480fbc Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:19:50 +0200 Subject: [PATCH] sidebar: ai: add suggestions for save/load --- .../quickshell/modules/sidebarLeft/AiChat.qml | 44 +++++++++++++++++-- .config/quickshell/services/Ai.qml | 26 +++++++++-- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/modules/sidebarLeft/AiChat.qml index 26d0636cf..b6ef48c10 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/modules/sidebarLeft/AiChat.qml @@ -382,11 +382,11 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) background: null onTextChanged: { // Handle suggestions - if(messageInputField.text.length === 0) { + if (messageInputField.text.length === 0) { root.suggestionQuery = "" root.suggestionList = [] return - } else if(messageInputField.text.startsWith(`${root.commandPrefix}model`)) { + } else if (messageInputField.text.startsWith(`${root.commandPrefix}model`)) { root.suggestionQuery = messageInputField.text.split(" ")[1] ?? "" const modelResults = Fuzzy.go(root.suggestionQuery, Ai.modelList.map(model => { return { @@ -404,7 +404,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) description: `${Ai.models[model.target].description}`, } }) - } else if(messageInputField.text.startsWith(`${root.commandPrefix}prompt`)) { + } else if (messageInputField.text.startsWith(`${root.commandPrefix}prompt`)) { root.suggestionQuery = messageInputField.text.split(" ")[1] ?? "" const promptFileResults = Fuzzy.go(root.suggestionQuery, Ai.promptFiles.map(file => { return { @@ -422,6 +422,44 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) description: `Load prompt from ${file.target}`, } }) + } else if (messageInputField.text.startsWith(`${root.commandPrefix}save`)) { + root.suggestionQuery = messageInputField.text.split(" ")[1] ?? "" + const promptFileResults = Fuzzy.go(root.suggestionQuery, Ai.savedChats.map(file => { + return { + name: Fuzzy.prepare(file), + obj: file, + } + }), { + all: true, + key: "name" + }) + root.suggestionList = promptFileResults.map(file => { + const chatName = FileUtils.trimFileExt(FileUtils.fileNameForPath(file.target)).trim() + return { + name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "save ") : ""}${chatName}`, + displayName: `${chatName}`, + description: `Save chat from ${chatName}`, + } + }) + } else if (messageInputField.text.startsWith(`${root.commandPrefix}load`)) { + root.suggestionQuery = messageInputField.text.split(" ")[1] ?? "" + const promptFileResults = Fuzzy.go(root.suggestionQuery, Ai.savedChats.map(file => { + return { + name: Fuzzy.prepare(file), + obj: file, + } + }), { + all: true, + key: "name" + }) + root.suggestionList = promptFileResults.map(file => { + const chatName = FileUtils.trimFileExt(FileUtils.fileNameForPath(file.target)).trim() + return { + name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "load ") : ""}${chatName}`, + displayName: `${chatName}`, + description: `Load chat from ${file.target}`, + } + }) } else if(messageInputField.text.startsWith(root.commandPrefix)) { root.suggestionQuery = messageInputField.text root.suggestionList = root.allCommands.filter(cmd => cmd.name.startsWith(messageInputField.text.substring(1))).map(cmd => { diff --git a/.config/quickshell/services/Ai.qml b/.config/quickshell/services/Ai.qml index 7ab1eb731..639ae936d 100644 --- a/.config/quickshell/services/Ai.qml +++ b/.config/quickshell/services/Ai.qml @@ -39,6 +39,7 @@ Singleton { property list defaultPrompts: [] property list userPrompts: [] property list promptFiles: [...defaultPrompts, ...userPrompts] + property list savedChats: [] // Model properties: // - name: Name of the model @@ -292,6 +293,20 @@ Singleton { } } + Process { + id: getSavedChats + running: true + command: ["ls", "-1", Directories.aiChats] + stdout: StdioCollector { + onStreamFinished: { + if (text.length === 0) return; + root.savedChats = text.split("\n") + .filter(fileName => fileName.endsWith(".json")) + .map(fileName => `${Directories.aiChats}/${fileName}`) + } + } + } + FileView { id: promptLoader watchChanges: false; @@ -797,6 +812,7 @@ Singleton { id: chatSaveFile property string chatName: "chat" path: `${Directories.aiChats}/${chatName}.json` + blockLoading: true } /** @@ -804,9 +820,10 @@ Singleton { * @param chatName name of the chat */ function saveChat(chatName) { - chatSaveFile.chatName = chatName + chatSaveFile.chatName = chatName.trim() const saveContent = JSON.stringify(root.chatToJson()) chatSaveFile.setText(saveContent) + getSavedChats.running = true; } /** @@ -815,9 +832,10 @@ Singleton { */ function loadChat(chatName) { try { - chatSaveFile.chatName = chatName + chatSaveFile.chatName = chatName.trim() + chatSaveFile.reload() const saveContent = chatSaveFile.text() - console.log(saveContent) + // console.log(saveContent) const saveData = JSON.parse(saveContent) root.clearMessages() root.messageIDs = saveData.map((_, i) => { @@ -843,6 +861,8 @@ Singleton { } } catch (e) { console.log("[AI] Could not load chat: ", e); + } finally { + getSavedChats.running = true; } } }