added message draft persistence and send button

This commit is contained in:
2026-01-19 09:02:18 +01:00
parent 7a3a016683
commit d21dab57b5
2 changed files with 68 additions and 3 deletions

View File

@@ -1,10 +1,17 @@
<template> <template>
<textarea ref="textareaRef" v-model="content" @input="resize" @keydown="handleKeydown" rows="1" <div class="container-div">
<textarea ref="textareaRef" v-model="content" @input="handleInput" @keydown="handleKeydown" rows="1"
:placeholder="$t('chat-input-placeholder')"></textarea> :placeholder="$t('chat-input-placeholder')"></textarea>
<button class="send-btn" @click="submit" :disabled="!content.trim()">
<i class="fas fa-paper-plane"></i>
</button>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, nextTick } from 'vue' import { ref, nextTick, onMounted } from 'vue'
import { saveMessageDraft, getMessageDraft } from '../store'
const content = ref('') const content = ref('')
const textareaRef = ref<HTMLTextAreaElement | null>(null) const textareaRef = ref<HTMLTextAreaElement | null>(null)
@@ -17,10 +24,24 @@ defineExpose({
} }
}) })
onMounted(async () => {
const saved = await getMessageDraft()
if (saved) {
content.value = saved
resize()
}
})
function handleInput() {
resize()
saveMessageDraft(content.value)
}
function submit() { function submit() {
if (!content.value.trim()) return if (!content.value.trim()) return
emit('send', content.value) emit('send', content.value)
content.value = '' content.value = ''
saveMessageDraft('')
resize() resize()
} }
@@ -43,6 +64,9 @@ function handleKeydown(e: KeyboardEvent) {
textarea.selectionStart = textarea.selectionEnd = start + 1 textarea.selectionStart = textarea.selectionEnd = start + 1
}) })
resize() resize()
saveMessageDraft(content.value)
e.preventDefault() e.preventDefault()
} else if (!e.shiftKey && !e.altKey && e.key === 'Enter') { } else if (!e.shiftKey && !e.altKey && e.key === 'Enter') {
submit() submit()
@@ -52,6 +76,13 @@ function handleKeydown(e: KeyboardEvent) {
</script> </script>
<style scoped> <style scoped>
.container-div {
position: relative;
width: 100%;
display: flex;
align-items: flex-end;
}
textarea { textarea {
width: 100%; width: 100%;
resize: none; resize: none;
@@ -64,5 +95,26 @@ textarea {
border: none; border: none;
color: inherit; color: inherit;
outline: none; outline: none;
flex: 1;
}
.send-btn {
margin-right: 0.8rem;
background: transparent;
border: none;
cursor: pointer;
color: var(--text);
padding: 0;
transition: color 0.2s;
font-size: 1.2rem;
}
.send-btn:hover:not(:disabled) {
color: var(--accent);
}
.send-btn:disabled {
cursor: not-allowed;
opacity: 0.5;
} }
</style> </style>

View File

@@ -223,3 +223,16 @@ export async function getCompactLayoutPreference(): Promise<boolean> {
const s = await getStore(); const s = await getStore();
return (await s.get<boolean>('compact_layout')) ?? false; return (await s.get<boolean>('compact_layout')) ?? false;
} }
// ==== Message draft ====
export async function saveMessageDraft(text: string) {
const s = await getStore()
await s.set('message_draft', text)
await s.save()
}
export async function getMessageDraft(): Promise<string> {
const s = await getStore()
return (await s.get<string>('message_draft')) ?? ''
}