summaryrefslogtreecommitdiffstats
path: root/assets
diff options
context:
space:
mode:
authorsigoden <sigoden@gmail.com>2024-05-20 09:09:42 +0800
committerGitHub <noreply@github.com>2024-05-20 09:09:42 +0800
commit7d7caf7479777af23c9a68a6ee151e93cf14f393 (patch)
tree061e1023eb9e42fcf26b74b4b907b0c076952aba /assets
parent482822da5358a052761dda3767a6cdddca72ac59 (diff)
downloadaichat-7d7caf7479777af23c9a68a6ee151e93cf14f393.tar.gz
refactor: webui enhence input textarea and copy message (#526)
Diffstat (limited to 'assets')
-rw-r--r--assets/arena.html71
-rw-r--r--assets/playground.html72
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;