diff options
| author | sigoden <sigoden@gmail.com> | 2024-05-20 09:09:42 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-20 09:09:42 +0800 |
| commit | 7d7caf7479777af23c9a68a6ee151e93cf14f393 (patch) | |
| tree | 061e1023eb9e42fcf26b74b4b907b0c076952aba /assets | |
| parent | 482822da5358a052761dda3767a6cdddca72ac59 (diff) | |
| download | aichat-7d7caf7479777af23c9a68a6ee151e93cf14f393.tar.gz | |
refactor: webui enhence input textarea and copy message (#526)
Diffstat (limited to 'assets')
| -rw-r--r-- | assets/arena.html | 71 | ||||
| -rw-r--r-- | assets/playground.html | 72 |
2 files changed, 65 insertions, 78 deletions
diff --git a/assets/arena.html b/assets/arena.html index 8c6a86f..7565070 100644 --- a/assets/arena.html +++ b/assets/arena.html @@ -14,7 +14,6 @@ <script src="//unpkg.com/@highlightjs/cdn-assets@11.9.0/highlight.min.js"></script> <script src="//unpkg.com/marked@12.0.2/lib/marked.umd.js" defer></script> <script src="//unpkg.com/alpinejs@3.13.10/dist/cdn.min.js" defer></script> - <script src="//unpkg.com/clipboard@2.0.1/dist/clipboard.min.js" def></script> <style> :root { --fg-primary: #1652f1; @@ -238,7 +237,9 @@ border: none; outline: none; resize: none; - overflow: hidden; + max-height: 500px; + overflow-x: hidden; + overflow-y: auto; } .input-toolbox { @@ -440,10 +441,7 @@ <!-- toolbox --> <template x-if="messageIndex == chat.hoveredMessageIndex"> <div class="message-toolbox"> - <div :id="'copy-message-btn-' + index" class="copy-message-btn" - :data-clipboard-text="message.content" - x-init="copyMessageClipboard = new ClipboardJS('#copy-message-btn-' + index); copyMessageClipboard.on('success', () => {toast('Copied Message')})" - title="Copy"> + <div class="copy-message-btn" @click="handleCopyMessage(message.content)" title="Copy"> <svg fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M4 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1zM2 5a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1h1v1a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h1v1z" /> @@ -479,8 +477,7 @@ </div> <div class="input-panel"> <div class="input-panel-inner"> - <textarea id="chat-input" rows="2" x-model="input" x-ref="input" - @keydown.enter.prevent="!$event.shiftKey && handleAsk()" @keydown.enter.shift="handleNewlineInput" + <textarea id="chat-input" x-model="input" x-ref="input" @keydown.enter="handleEnterKeydown" placeholder="Enter to send, Shift + Enter to wrap"></textarea> <div class="input-image-bar" x-show="images.length > 0"> <template x-for="(image, index) in images"> @@ -559,7 +556,6 @@ model_id: "", messages: [], hoveredMessageIndex: null, - copyMessageClipboard: null, askAbortController: null, shouldScrollChatBodyToBottom: true, isShowScrollToBottomBtn: false, @@ -587,7 +583,7 @@ } $scrollToBottomBtns[i].style.left = offsets[i]; } - this.$watch("input", () => this.autoScrollAndHeightOnInput(this.$refs.input)); + this.$watch("input", () => this.autosizeInput(this.$refs.input)); new ResizeObserver(() => { this.autoHeightChatPanel(); }).observe($inputPanel) @@ -695,18 +691,11 @@ chat.shouldScrollChatBodyToBottom = true; }, - handleNewlineInput(event) { - event.preventDefault(); - const $input = event.target; - const start = $input.selectionStart; - const end = $input.selectionEnd; - const text = $input.value; - const before = text.substring(0, start); - const after = text.substring(end); - - $input.value = before + '\n' + after; - $input.selectionStart = $input.selectionEnd = start + 1; - this.input = $input.value; + handleEnterKeydown(event) { + if (event.shiftKey) { + return; + } + this.handleAsk(); }, handleCopyCode(event) { @@ -723,6 +712,21 @@ } }, + handleCopyMessage(content) { + if (Array.isArray(content)) { + content = content.map(v => v.text || "").join(""); + } + + const $tempTextArea = document.createElement("textarea"); + $tempTextArea.value = content; + document.body.appendChild($tempTextArea); + $tempTextArea.select(); + $tempTextArea.setSelectionRange(0, 99999); // For mobile devices + document.execCommand("copy"); + document.body.removeChild($tempTextArea); + toast("Copied Message") + }, + async handleImageUpload(event) { const files = event.target.files; if (!files || files.length === 0) { @@ -751,29 +755,18 @@ } }, - autoScrollAndHeightOnInput($input) { - if (!$input.value) { - $input.style.overflowY = "hidden"; - $input.style.height = "51px"; - } else if ($input.scrollHeight < 500) { - $input.style.overflowY = "hidden"; - $input.style.height = "auto"; - $input.style.height = $input.scrollHeight + "px"; - } else { - $input.style.overflowY = "auto"; - $input.style.height = "500px" - const lineHeight = 19; - const cursorTop = Math.floor(($input.selectionStart + 1) / $input.cols) * lineHeight; - if (cursorTop < $input.scrollTop || cursorTop > ($input.scrollTop + $input.clientHeight - lineHeight)) { - $input.scrollTop = cursorTop; - } - } + autosizeInput($input) { + $input.style.height = 'auto'; + $input.style.height = $input.scrollHeight + 'px'; }, async ask(index) { const chat = this.chats[index]; chat.askAbortController = new AbortController(); chat.shouldScrollChatBodyToBottom = true; + this.$nextTick(() => { + this.autoScrollChatBodyToBottom(index); + }); const lastMessage = chat.messages[chat.messages.length - 1]; const body = this.buildBody(index); let succeed = false; diff --git a/assets/playground.html b/assets/playground.html index ccbc488..aab5146 100644 --- a/assets/playground.html +++ b/assets/playground.html @@ -14,7 +14,6 @@ <script src="//unpkg.com/@highlightjs/cdn-assets@11.9.0/highlight.min.js"></script> <script src="//unpkg.com/marked@12.0.2/lib/marked.umd.js" defer></script> <script src="//unpkg.com/alpinejs@3.13.10/dist/cdn.min.js" defer></script> - <script src="//unpkg.com/clipboard@2.0.1/dist/clipboard.min.js" def></script> <style> :root { --fg-primary: #1652f1; @@ -317,7 +316,9 @@ border: none; outline: none; resize: none; - overflow: hidden; + max-height: 500px; + overflow-x: hidden; + overflow-y: auto; } .input-toolbox { @@ -602,9 +603,7 @@ <!-- toolbox --> <template x-if="index == hoveredMessageIndex"> <div class="message-toolbox"> - <div class="copy-message-btn" :data-clipboard-text="message.content" - x-init="copyMessageClipboard = new ClipboardJS('.copy-message-btn'); copyMessageClipboard.on('success', () => {toast('Copied Message')})" - title="Copy"> + <div class="copy-message-btn" @click="handleCopyMessage(message.content)" title=" Copy"> <svg fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M4 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1zM2 5a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1h1v1a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h1v1z" /> @@ -634,8 +633,7 @@ </div> <div class="input-panel"> <div class="input-panel-inner"> - <textarea id="chat-input" rows="2" x-model="input" x-ref="input" - @keydown.enter.prevent="!$event.shiftKey && handleAsk()" @keydown.enter.shift="handleNewlineInput" + <textarea id="chat-input" x-model="input" x-ref="input" @keydown.enter="handleEnterKeydown" placeholder="Enter to send, Shift + Enter to wrap"></textarea> <div class="input-image-bar" x-show="images.length > 0"> <template x-for="(image, index) in images"> @@ -710,7 +708,7 @@ temperature: null, top_p: null, enable_session: true, - compress_threshold: 2000, + compress_threshold: 4000, }; try { const persistSettings = JSON.parse(localStorage.getItem(SETTINGS_STORAGE_KEY)) || {}; @@ -729,7 +727,6 @@ currentModel: {}, messages: [], hoveredMessageIndex: null, - copyMessageClipboard: null, skipMessageId: -1, input: "", images: [], @@ -749,7 +746,7 @@ } catch (err) { console.error(err); } - this.$watch("input", () => this.autoScrollAndHeightOnInput(this.$refs.input)); + this.$watch("input", () => this.autosizeInput(this.$refs.input)); this.$watch("settings", () => { localStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(this.settings)); }); @@ -856,18 +853,11 @@ this.$refs["main-panel"].style.display = this.$refs["main-panel"]._display; }, - handleNewlineInput(event) { - event.preventDefault(); - const $input = event.target; - const start = $input.selectionStart; - const end = $input.selectionEnd; - const text = $input.value; - const before = text.substring(0, start); - const after = text.substring(end); - - $input.value = before + '\n' + after; - $input.selectionStart = $input.selectionEnd = start + 1; - this.input = $input.value; + handleEnterKeydown(event) { + if (event.shiftKey) { + return; + } + this.handleAsk(); }, handleCopyCode(event) { @@ -884,6 +874,21 @@ } }, + handleCopyMessage(content) { + if (Array.isArray(content)) { + content = content.map(v => v.text || "").join(""); + } + + const $tempTextArea = document.createElement("textarea"); + $tempTextArea.value = content; + document.body.appendChild($tempTextArea); + $tempTextArea.select(); + $tempTextArea.setSelectionRange(0, 99999); // For mobile devices + document.execCommand("copy"); + document.body.removeChild($tempTextArea); + toast("Copied Message") + }, + async handleImageUpload(event) { const files = event.target.files; if (!files || files.length === 0) { @@ -904,28 +909,17 @@ } }, - autoScrollAndHeightOnInput($input) { - if (!$input.value) { - $input.style.overflowY = "hidden"; - $input.style.height = "51px"; - } else if ($input.scrollHeight < 500) { - $input.style.overflowY = "hidden"; - $input.style.height = "auto"; - $input.style.height = $input.scrollHeight + "px"; - } else { - $input.style.overflowY = "auto"; - $input.style.height = "500px" - const lineHeight = 19; - const cursorTop = Math.floor(($input.selectionStart + 1) / $input.cols) * lineHeight; - if (cursorTop < $input.scrollTop || cursorTop > ($input.scrollTop + $input.clientHeight - lineHeight)) { - $input.scrollTop = cursorTop; - } - } + autosizeInput($input) { + $input.style.height = 'auto'; + $input.style.height = $input.scrollHeight + 'px'; }, async ask() { this.askAbortController = new AbortController(); this.shouldScrollChatBodyToBottom = true; + this.$nextTick(() => { + this.autoScrollChatBodyToBottom(); + }); const lastMessage = this.messages[this.messages.length - 1]; const body = this.buildBody(); let succeed = false; |
