Mercurial Hosting > lang
changeset 29:505185272dd7
edit chat
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sat, 02 Aug 2025 22:39:48 -0600 |
parents | 99b71a377f2c |
children | d48f48e1b790 |
files | src/chat.html.luan src/chat.js src/lib/Chat.luan src/lib/ai/claude/Ai_chat.luan src/rename_chat.js.luan src/save_chat.js.luan src/save_rename_chat.js.luan src/site.js |
diffstat | 8 files changed, 74 insertions(+), 80 deletions(-) [+] |
line wrap: on
line diff
--- a/src/chat.html.luan Sat Aug 02 20:04:35 2025 -0600 +++ b/src/chat.html.luan Sat Aug 02 22:39:48 2025 -0600 @@ -1,5 +1,7 @@ local Luan = require "luan:Luan.luan" local error = Luan.error +local Parsers = require "luan:Parsers.luan" +local json_string = Parsers.json_string or error() local Io = require "luan:Io.luan" local Http = require "luan:http/Http.luan" local Shared = require "site:/lib/Shared.luan" @@ -27,21 +29,17 @@ <style> @import "/chat.css?s=<%=started%>"; </style> - <script> - let chatId = <%= chat.id %>; - let lang = '<%= chat.language_region %>'; - </script> <script src="/chat.js?s=<%=started%>"></script> </head> <body> <% header() %> <div content ai_container> <div top> - <h3 name><%= chat.name_html() %></h3> + <h3 name></h3> <span pulldown> <img onclick="clickMenu(this)" src="/images/menu.svg"> <div> - <span onclick="renameChat()">Rename Chat</span> + <span onclick="editChat()">Edit Chat</span> <span onclick="deleteChat()">Delete Chat</span> <span onclick="systemPrompt()">System Prompt</span> </div> @@ -60,9 +58,10 @@ </div> </div> <img waiting-ai-icon src="/images/spinner_green.gif"> - <dialog rename> - <h2>Rename Chat</h2> - <form action="javascript:saveRenameChat()"> + <dialog edit> + <h2>Edit Chat</h2> + <form onsubmit="saveChat(this)" action="javascript:"> + <input type=hidden name=chat value="<%=chat.id%>"> <p> <label>Chat name</label><br> <input name=name required><br> @@ -70,7 +69,7 @@ </p> <div buttons> <button type=button onclick="closeModal(this)">Cancel</button> - <button type=submit>Rename</button> + <button type=submit>Save</button> </div> </form> </dialog> @@ -94,7 +93,8 @@ </dialog> <input name=initialized style="display:none"> <script> - handleMarkdown(); + setChat(<%= json_string(chat.info()) %>); + handleChatMarkdown(); setTimeout(function(){ let initialized = document.querySelector('[name=initialized]'); if( !initialized.value ) {
--- a/src/chat.js Sat Aug 02 20:04:35 2025 -0600 +++ b/src/chat.js Sat Aug 02 22:39:48 2025 -0600 @@ -1,20 +1,21 @@ 'use strict'; -function openRenameChat(name) { - let dialog = document.querySelector('dialog[rename]'); - dialog.querySelector('input[name=name]').value = name; +let chat; + +function setChat(newChat) { + chat = newChat; + document.querySelector('[content] [name]').textContent = chat.name; +} + +function editChat(name) { + let dialog = document.querySelector('dialog[edit]'); + dialog.querySelector('input[name=name]').value = chat.name; dialog.showModal(); } -function renameChat() { - ajax(`rename_chat.js?chat=${chatId}`); -} - -function saveRenameChat() { - let dialog = document.querySelector('dialog[rename]'); - let name = dialog.querySelector('input[name=name]').value; - ajax(`save_rename_chat.js?chat=${chatId}&name=${encodeURIComponent(name)}`); - dialog.close(); +function saveChat(form) { + closeModal(form); + ajaxForm('save_chat.js',form); } function deleteChat() { @@ -24,7 +25,7 @@ function doDeleteChat(el) { closeModal(el); - ajax(`delete_chat.js?chat=${chatId}`); + ajax(`delete_chat.js?chat=${chat.id}`); } function systemPrompt() { @@ -48,6 +49,10 @@ } } +function handleChatMarkdown() { + handleMarkdown(chat.language_region); +} + function scrollToEnd() { window.scrollTo(0, document.body.scrollHeight); } @@ -55,7 +60,7 @@ function updateAi(html) { hideWaitingAiIcon(); document.querySelector('div[messages]').insertAdjacentHTML('beforeend',html); - handleMarkdown(); + handleChatMarkdown(); document.querySelector('textarea').focus(); scrollToEnd(); playLastMessage(); @@ -78,12 +83,12 @@ textarea.parentNode.scrollIntoViewIfNeeded(false); if( !audio ) audio = document.querySelector('div[buttons] audio'); - audio.src = `/tts.mp3?lang=${lang}&text=${encodeURIComponent(textarea.value)}`; + audio.src = `/tts.mp3?lang=${chat.language_region}&text=${encodeURIComponent(textarea.value)}`; } function askAi() { let input = document.querySelector('textarea'); - let url = `ai_ask.js?chat=${chatId}&input=${encodeURIComponent(input.value)}`; + let url = `ai_ask.js?chat=${chat.id}&input=${encodeURIComponent(input.value)}`; ajax(url); input.value = ''; fixTextarea(input);
--- a/src/lib/Chat.luan Sat Aug 02 20:04:35 2025 -0600 +++ b/src/lib/Chat.luan Sat Aug 02 22:39:48 2025 -0600 @@ -69,6 +69,14 @@ Db.delete("id:"..chat.id) end + function chat.info() + return { + id = chat.id + language_region = chat.language_region + name = chat.name + } + end + function chat.name_html() return html_encode(chat.name) end @@ -93,7 +101,7 @@ end function chat.output_messages_html() - Ai_chat.output_messages_html(chat.language_region,chat.ai_thread) + Ai_chat.output_messages_html(chat.ai_thread) end function chat.ask(input) @@ -104,7 +112,7 @@ chat.ai_thread = ai_thread chat.save() end ) - return `Ai_chat.output_messages_html(chat.language_region,ai_thread,old_thread)` + return `Ai_chat.output_messages_html(ai_thread,old_thread)` end function chat.language_name()
--- a/src/lib/ai/claude/Ai_chat.luan Sat Aug 02 20:04:35 2025 -0600 +++ b/src/lib/ai/claude/Ai_chat.luan Sat Aug 02 22:39:48 2025 -0600 @@ -27,7 +27,7 @@ %><%=system_prompt%><% end -function Ai_chat.output_messages_html(lang,thread,old_thread) +function Ai_chat.output_messages_html(thread,old_thread) if thread == nil then return end @@ -56,7 +56,7 @@ text = html_encode(text) %> <h3><%=who%></h3> - <div markdown role="<%=role%>" lang="<%=lang%>"><%=text%></div> + <div markdown role="<%=role%>"><%=text%></div> <% end local content = message.content or error()
--- a/src/rename_chat.js.luan Sat Aug 02 20:04:35 2025 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -local Luan = require "luan:Luan.luan" -local error = Luan.error -local Parsers = require "luan:Parsers.luan" -local json_string = Parsers.json_string or error() -local Io = require "luan:Io.luan" -local Http = require "luan:http/Http.luan" -local Chat = require "site:/lib/Chat.luan" -local get_chat_by_id = Chat.get_by_id or error() - - -return function() - local chat = Http.request.parameters.chat or error() - chat = get_chat_by_id(chat) or error() - Io.stdout = Http.response.text_writer() -%> - openRenameChat(<%=json_string(chat.name)%>); -<% -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/save_chat.js.luan Sat Aug 02 22:39:48 2025 -0600 @@ -0,0 +1,28 @@ +local Luan = require "luan:Luan.luan" +local error = Luan.error +local Parsers = require "luan:Parsers.luan" +local json_string = Parsers.json_string or error() +local Io = require "luan:Io.luan" +local Http = require "luan:http/Http.luan" +local Chat = require "site:/lib/Chat.luan" +local get_chat_by_id = Chat.get_by_id or error() +local User = require "site:/lib/User.luan" +local current_user = User.current or error() +local Db = require "site:/lib/Db.luan" +local run_in_transaction = Db.run_in_transaction or error() + + +return function() + local chat = Http.request.parameters.chat or error() + local name = Http.request.parameters.name or error() + run_in_transaction( function() + chat = get_chat_by_id(chat) or error() + chat.user_id == current_user().id or error() + chat.name = name + chat.save() + end ) + Io.stdout = Http.response.text_writer() +%> + setChat(<%= json_string(chat.info()) %>); +<% +end
--- a/src/save_rename_chat.js.luan Sat Aug 02 20:04:35 2025 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -local Luan = require "luan:Luan.luan" -local error = Luan.error -local Parsers = require "luan:Parsers.luan" -local json_string = Parsers.json_string or error() -local Io = require "luan:Io.luan" -local Http = require "luan:http/Http.luan" -local Chat = require "site:/lib/Chat.luan" -local get_chat_by_id = Chat.get_by_id or error() -local User = require "site:/lib/User.luan" -local current_user = User.current or error() -local Db = require "site:/lib/Db.luan" -local run_in_transaction = Db.run_in_transaction or error() - - -return function() - local chat = Http.request.parameters.chat or error() - local name = Http.request.parameters.name or error() - run_in_transaction( function() - chat = get_chat_by_id(chat) or error() - chat.user_id == current_user().id or error() - chat.name = name - chat.save() - end ) - Io.stdout = Http.response.text_writer() -%> - document.querySelector('[content] [name]').textContent = <%=json_string(name)%>; -<% -end
--- a/src/site.js Sat Aug 02 20:04:35 2025 -0600 +++ b/src/site.js Sat Aug 02 22:39:48 2025 -0600 @@ -124,21 +124,20 @@ let mdDiv = document.createElement('div'); -function handleMarkdown() { +function handleMarkdown(lang) { let converter = window.markdownit({html: true}); let divs = document.querySelectorAll('[markdown]'); for( let div of divs ) { let text = div.textContent; text = text.replace(/\{([^|}]+)\|([^|}]+)\}/g, '<ruby>$1<rt>$2</rt></ruby>'); text = converter.render(text); - if( div.getAttribute('role')==='assistant' ) { + if( lang && div.getAttribute('role')==='assistant' ) { mdDiv.innerHTML = text; let rts = mdDiv.querySelectorAll('rt'); for( let rt of rts ) { rt.remove(); } //console.log(mdDiv.textContent); - let lang = div.getAttribute('lang'); text += `\n<p><audio controls preload=none src="/tts.mp3?lang=${lang}&text=${encodeURIComponent(mdDiv.textContent)}"></audio></p>\n`; } div.innerHTML = text;