feat(chat): preserve message drafts in session temp store

This commit is contained in:
2026-10-15 17:45:17 +02:00
parent e933782731
commit 697f538b6e
8 changed files with 426 additions and 16 deletions

View File

@@ -10,6 +10,71 @@ export const useTempStore = defineStore('temp', () => {
const pages = ref({})
const settings = ref({})
// Drafts stay local: temp_config is also returned in tenant profile lists.
const chatDrafts = ref({})
const sendingChatDrafts = ref({})
const loadedChatDrafts = new Set()
const draftStoragePrefix = 'fedeo:chat-draft:v1:'
const toast = useToast()
let draftStorageWarningShown = false
function getChatDraft(key) {
if (!loadedChatDrafts.has(key)) {
loadedChatDrafts.add(key)
try {
const saved = JSON.parse(sessionStorage.getItem(draftStoragePrefix + key) || 'null')
if (saved && typeof saved.text === 'string' && typeof saved.clientId === 'string'
&& saved.text.length <= 10000 && (!saved.image || (
typeof saved.image.name === 'string' && typeof saved.image.dataUrl === 'string'
&& saved.image.dataUrl.length <= 480000
&& /^data:image\/(jpeg|png|webp);base64,[A-Za-z0-9+/=]+$/.test(saved.image.dataUrl)
))) chatDrafts.value[key] = saved
} catch { /* Disabled storage or an invalid entry must not block the chat. */ }
}
return chatDrafts.value[key] || null
}
function setChatDraft(key, draft) {
loadedChatDrafts.add(key)
if (draft) chatDrafts.value[key] = draft
else delete chatDrafts.value[key]
try {
if (draft) sessionStorage.setItem(draftStoragePrefix + key, JSON.stringify(draft))
else sessionStorage.removeItem(draftStoragePrefix + key)
} catch {
// Do not restore an older version after a failed storage update.
try { sessionStorage.removeItem(draftStoragePrefix + key) } catch {}
if (!draftStorageWarningShown) {
draftStorageWarningShown = true
toast.add({ title: 'Entwurf nur vorübergehend gespeichert', description: 'Der Browserspeicher ist voll oder gesperrt. Bis zum Neuladen bleibt dein Entwurf im Chat erhalten.', color: 'warning' })
}
}
}
function isChatDraftSending(key) {
return !!sendingChatDrafts.value[key]
}
function startChatDraftSend(key, clientId) {
sendingChatDrafts.value[key] = clientId
}
function finishChatDraftSend(key, clientId) {
if (sendingChatDrafts.value[key] === clientId) delete sendingChatDrafts.value[key]
}
watch(() => auth.user?.id || auth.user?.user_id, (user, previous) => {
if (!previous || user === previous) return
chatDrafts.value = {}
sendingChatDrafts.value = {}
loadedChatDrafts.clear()
try {
for (const key of Object.keys(sessionStorage)) {
if (key.startsWith(draftStoragePrefix)) sessionStorage.removeItem(key)
}
} catch { /* Storage may be unavailable. In-memory drafts are still cleared. */ }
}, { flush: 'sync' })
const storeTempConfig = async () => {
const config = {
searchStrings: searchStrings.value,
@@ -92,6 +157,11 @@ export const useTempStore = defineStore('temp', () => {
}
return {
getChatDraft,
setChatDraft,
isChatDraftSending,
startChatDraftSend,
finishChatDraftSend,
setStoredTempConfig,
searchStrings,
modifySearchString,