Édition des messages de l'utilsateur

This commit is contained in:
Sylvain Philip 2024-09-10 09:16:22 +02:00
parent e757074056
commit 0e5aff407d
2 changed files with 78 additions and 28 deletions

View File

@ -7,7 +7,6 @@
import AssistantForm from './AssistantForm.svelte'; import AssistantForm from './AssistantForm.svelte';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
// export let apiKey = '';
export let proxyBaseUrl = ''; export let proxyBaseUrl = '';
export let model_list = []; export let model_list = [];
@ -17,7 +16,7 @@
let assistants = []; let assistants = [];
let messages = []; let messages = [];
let newMessage = ''; let chatInput; // Reference to the chat input textarea
let chatContainer; let chatContainer;
let assistantForm; // Reference to the AssistantForm component let assistantForm; // Reference to the AssistantForm component
let modal; // Reference to the Modal component let modal; // Reference to the Modal component
@ -129,7 +128,7 @@
return readStream(response.body, progressCallback); return readStream(response.body, progressCallback);
} }
function sendMessage() { function sendMessage(newMessage) {
if (newMessage.trim() === '') return; if (newMessage.trim() === '') return;
if (!messages.length && assistant) { if (!messages.length && assistant) {
@ -169,6 +168,12 @@
} }
} }
function handleChatInputKey(event) {
if (event.key === 'Enter') {
sendMessage(chatInput.value);
}
}
function clearMessages() { function clearMessages() {
messages = []; messages = [];
} }
@ -383,30 +388,14 @@
reader.readAsText(file); reader.readAsText(file);
} }
/* function handleEditMessage(event) {
import { onMount } from 'svelte'; const { index, content } = event.detail;
import { writable } from 'svelte/store'; messages[index].content = content;
messages = messages.slice(0, index);
let messages = writable([]); sendMessage(content);
let newMessage = writable(""); }
const sendMessage = () => {
if ($newMessage.trim() !== "") {
messages.update(msgs => [...msgs, { role: 'user', content: $newMessage }]);
newMessage.set("");
}
};
// Sample function to simulate receiving a message from the AI
const receiveMessage = (content) => {
messages.update(msgs => [...msgs, { role: 'assistant', content }]);
};
onMount(() => {
// Simulate receiving an initial message from the AI
receiveMessage("Hello! How can I assist you today?");
});
*/
</script> </script>
<header> <header>
@ -448,15 +437,17 @@
<main> <main>
<div class="chat-container" bind:this="{chatContainer}" > <div class="chat-container" bind:this="{chatContainer}" >
{#each messages as message, index (index)} {#each messages as message, index (index)}
<ChatMessage message="{message}" container="{chatContainer.parentElement}" markdown={md} /> <ChatMessage message="{message}"
message_index={index} on:editMessage="{handleEditMessage}"
container="{chatContainer.parentElement}" markdown={md} />
{/each} {/each}
</div> </div>
</main> </main>
<footer> <footer>
<textarea class="chat-input" rows="1" <textarea class="chat-input" rows="1"
bind:value="{newMessage}" bind:this="{chatInput}"
on:keyup={e => { if (e.key === 'Enter') sendMessage(); }} on:keyup={handleChatInputKey}
placeholder="Saisissez votre message ici..." placeholder="Saisissez votre message ici..."
aria-label="Chat with AI"></textarea> aria-label="Chat with AI"></textarea>
</footer> </footer>

View File

@ -1,12 +1,20 @@
<script> <script>
import { beforeUpdate, afterUpdate } from 'svelte'; import { beforeUpdate, afterUpdate } from 'svelte';
import { createEventDispatcher } from 'svelte';
export let message; export let message;
export let container; export let container;
export let markdown; export let markdown;
export let message_index;
const dispatch = createEventDispatcher();
let autoscroll; let autoscroll;
let renderedContent = ''; let renderedContent = '';
let editableElement;
// Track whether the user is editing the message
let isEditing = false;
$: renderedContent = markdown.render(message.content); $: renderedContent = markdown.render(message.content);
@ -17,7 +25,37 @@
afterUpdate(() => { afterUpdate(() => {
if (autoscroll) container.scrollTo(0, container.scrollHeight); if (autoscroll) container.scrollTo(0, container.scrollHeight);
if (isEditing && editableElement) {
editableElement.focus();
}
}); });
function handleKeyDown(event) {
if (event.key === 'Enter' && event.shiftKey) {
// Allow the default behavior of adding a new line
return;
}
switch (event.key) {
case 'Escape':
isEditing = false;
break;
case 'Enter':
event.preventDefault();
const editedContent = event.target.innerText.trim();
if (editedContent) {
dispatch('editMessage', {
index: message_index,
content: editedContent
});
}
isEditing = false;
break;
}
}
</script> </script>
<style> <style>
@ -32,6 +70,27 @@
{#if message.role != 'system'} {#if message.role != 'system'}
<div class={message.role + ' message'}> <div class={message.role + ' message'}>
{#if isEditing}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div bind:this={editableElement}
class="editable-message"
contenteditable="true"
on:keydown={handleKeyDown}>{message.content}</div>
{:else}
{@html renderedContent} {@html renderedContent}
<div class="toolbar">
{#if message.role == 'user'}
<button class="btn btn-primary btn-sm" title="Modifier" on:click={() => {isEditing = true}}>
<span class="icon-edit"></span>
</button>
{:else if message.role == 'assistant'}
<button class="btn btn-primary btn-sm" title="Copier"><span class="icon-content_copy"></span></button>
<button class="btn btn-primary btn-sm" title="Régénérer"><span class="icon-loop"></span></button>
<button class="btn btn-primary btn-sm" title="Supprimer le message"><span class="icon-delete"></span></button>
{/if}
</div>
{/if}
</div> </div>
{/if} {/if}