From adede5480da2de56173bcc1aafb9a9c1c8d7894f Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Fri, 25 Oct 2024 21:31:18 -0700 Subject: [PATCH] enh: rich text input toggle option --- src/lib/components/chat/MessageInput.svelte | 267 +++++++++++++++--- .../chat/MessageInput/Commands/Prompts.svelte | 7 +- src/lib/components/chat/Placeholder.svelte | 9 +- .../components/chat/Settings/Interface.svelte | 29 ++ 4 files changed, 262 insertions(+), 50 deletions(-) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index d135004cf..6875dea53 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -509,54 +509,202 @@ -
- + 0 || + navigator.msMaxTouchPoints > 0 + )} + on:enter={async (e) => { + if (prompt !== '') { + dispatch('submit', prompt); + } + }} + on:input={async (e) => { + if (chatInputContainerElement) { + chatInputContainerElement.style.height = ''; + chatInputContainerElement.style.height = + Math.min(chatInputContainerElement.scrollHeight, 200) + 'px'; + } + }} + on:focus={async (e) => { + if (chatInputContainerElement) { + chatInputContainerElement.style.height = ''; + chatInputContainerElement.style.height = + Math.min(chatInputContainerElement.scrollHeight, 200) + 'px'; + } + }} + on:keypress={(e) => { + e = e.detail.event; + }} + on:keydown={async (e) => { + e = e.detail.event; + + if (chatInputContainerElement) { + chatInputContainerElement.style.height = ''; + chatInputContainerElement.style.height = + Math.min(chatInputContainerElement.scrollHeight, 200) + 'px'; + } + + const isCtrlPressed = e.ctrlKey || e.metaKey; // metaKey is for Cmd key on Mac + const commandsContainerElement = + document.getElementById('commands-container'); + + // Command/Ctrl + Shift + Enter to submit a message pair + if (isCtrlPressed && e.key === 'Enter' && e.shiftKey) { + e.preventDefault(); + createMessagePair(prompt); + } + + // Check if Ctrl + R is pressed + if (prompt === '' && isCtrlPressed && e.key.toLowerCase() === 'r') { + e.preventDefault(); + console.log('regenerate'); + + const regenerateButton = [ + ...document.getElementsByClassName('regenerate-response-button') + ]?.at(-1); + + regenerateButton?.click(); + } + + if (prompt === '' && e.key == 'ArrowUp') { + e.preventDefault(); + + const userMessageElement = [ + ...document.getElementsByClassName('user-message') + ]?.at(-1); + + const editButton = [ + ...document.getElementsByClassName('edit-user-message-button') + ]?.at(-1); + + console.log(userMessageElement); + + userMessageElement.scrollIntoView({ block: 'center' }); + editButton?.click(); + } + + if (commandsContainerElement && e.key === 'ArrowUp') { + e.preventDefault(); + commandsElement.selectUp(); + + const commandOptionButton = [ + ...document.getElementsByClassName('selected-command-option-button') + ]?.at(-1); + commandOptionButton.scrollIntoView({ block: 'center' }); + } + + if (commandsContainerElement && e.key === 'ArrowDown') { + e.preventDefault(); + commandsElement.selectDown(); + + const commandOptionButton = [ + ...document.getElementsByClassName('selected-command-option-button') + ]?.at(-1); + commandOptionButton.scrollIntoView({ block: 'center' }); + } + + if (commandsContainerElement && e.key === 'Enter') { + e.preventDefault(); + + const commandOptionButton = [ + ...document.getElementsByClassName('selected-command-option-button') + ]?.at(-1); + + if (e.shiftKey) { + prompt = `${prompt}\n`; + } else if (commandOptionButton) { + commandOptionButton?.click(); + } else { + document.getElementById('send-message-button')?.click(); + } + } + + if (commandsContainerElement && e.key === 'Tab') { + e.preventDefault(); + + const commandOptionButton = [ + ...document.getElementsByClassName('selected-command-option-button') + ]?.at(-1); + + commandOptionButton?.click(); + } + + if (e.key === 'Escape') { + console.log('Escape'); + atSelectedModel = undefined; + } + }} + on:paste={async (e) => { + e = e.detail.event; + console.log(e); + + const clipboardData = e.clipboardData || window.clipboardData; + + if (clipboardData && clipboardData.items) { + for (const item of clipboardData.items) { + if (item.type.indexOf('image') !== -1) { + const blob = item.getAsFile(); + const reader = new FileReader(); + + reader.onload = function (e) { + files = [ + ...files, + { + type: 'image', + url: `${e.target.result}` + } + ]; + }; + + reader.readAsDataURL(blob); + } + } + } + }} + /> +
+ {:else} +