Add truncate and send button to messages
This commit is contained in:
parent
e2b9c57164
commit
58c78a2840
|
@ -10,7 +10,8 @@
|
|||
updateChatSettings,
|
||||
updateRunningTotal,
|
||||
checkStateChange,
|
||||
showSetChatSettings
|
||||
showSetChatSettings,
|
||||
submitExitingPromptsNow
|
||||
} from './Storage.svelte'
|
||||
import { getRequestSettingList, defaultModel } from './Settings.svelte'
|
||||
import {
|
||||
|
@ -75,10 +76,14 @@
|
|||
$showSetChatSettings = false
|
||||
showSettingsModal()
|
||||
}
|
||||
if ($submitExitingPromptsNow) {
|
||||
$submitExitingPromptsNow = false
|
||||
submitForm(false, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$: onStateChange($checkStateChange, $showSetChatSettings)
|
||||
$: onStateChange($checkStateChange, $showSetChatSettings, $submitExitingPromptsNow)
|
||||
|
||||
// Make sure chat object is ready to go
|
||||
updateChatSettings(chatId)
|
||||
|
|
|
@ -54,11 +54,6 @@
|
|||
showProfileMenu = false
|
||||
$checkStateChange++
|
||||
showSettingsModal = 0
|
||||
// if (chat.startSession) {
|
||||
// chat.startSession = false
|
||||
// saveChatStore()
|
||||
// // submitForm(false, true)
|
||||
// }
|
||||
}
|
||||
|
||||
const clearSettings = () => {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<script lang="ts">
|
||||
import Code from './Code.svelte'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import { deleteMessage, chatsStorage, deleteSummaryMessage } from './Storage.svelte'
|
||||
import { deleteMessage, chatsStorage, deleteSummaryMessage, truncateFromMessage, submitExitingPromptsNow } from './Storage.svelte'
|
||||
import { getPrice } from './Stats.svelte'
|
||||
import SvelteMarkdown from 'svelte-markdown'
|
||||
import type { Message, Model, Chat } from './Types.svelte'
|
||||
import Fa from 'svelte-fa/src/fa.svelte'
|
||||
import { faTrash, faDiagramPredecessor, faDiagramNext } from '@fortawesome/free-solid-svg-icons/index'
|
||||
import { faTrash, faDiagramPredecessor, faDiagramNext, faCircleCheck, faPaperPlane } from '@fortawesome/free-solid-svg-icons/index'
|
||||
import { scrollIntoViewWithOffset } from './Util.svelte'
|
||||
|
||||
export let message:Message
|
||||
|
@ -44,30 +44,6 @@
|
|||
}, 0)
|
||||
}
|
||||
|
||||
const checkDelete = () => {
|
||||
if (message.summarized) {
|
||||
// is in a summary, so we're summarized
|
||||
window.alert('Sorry, you can\'t delete a summarized message')
|
||||
return
|
||||
}
|
||||
if (message.summary) {
|
||||
// We're linked to messages we're a summary of
|
||||
if (window.confirm('Are you sure you want to delete this summary?\nYour session may be too long to submit again after you do.')) {
|
||||
try {
|
||||
deleteSummaryMessage(chatId, message.uuid)
|
||||
} catch (e) {
|
||||
window.alert('Unable to delete summary:\n' + e.message)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
try {
|
||||
deleteMessage(chatId, message.uuid)
|
||||
} catch (e) {
|
||||
window.alert('Unable to delete:\n' + e.message)
|
||||
}
|
||||
}
|
||||
|
||||
let dbnc
|
||||
const update = () => {
|
||||
clearTimeout(dbnc)
|
||||
|
@ -103,7 +79,7 @@
|
|||
}
|
||||
const el = document.getElementById('message-' + uuid)
|
||||
if (el) {
|
||||
scrollIntoViewWithOffset(el, 60)
|
||||
scrollIntoViewWithOffset(el, 80)
|
||||
} else {
|
||||
console.error("Can't find element with message ID", uuid)
|
||||
}
|
||||
|
@ -119,7 +95,66 @@
|
|||
}
|
||||
lastTap = new Date().getTime()
|
||||
}
|
||||
|
||||
|
||||
let waitingForDeleteConfirm:any = 0
|
||||
|
||||
const checkDelete = () => {
|
||||
clearTimeout(waitingForTruncateConfirm); waitingForTruncateConfirm = 0
|
||||
if (!waitingForDeleteConfirm) {
|
||||
// wait a second for another click to avoid accidental deletes
|
||||
waitingForDeleteConfirm = setTimeout(() => { waitingForDeleteConfirm = 0 }, 1000)
|
||||
return
|
||||
}
|
||||
clearTimeout(waitingForDeleteConfirm)
|
||||
waitingForDeleteConfirm = 0
|
||||
if (message.summarized) {
|
||||
// is in a summary, so we're summarized
|
||||
window.alert('Sorry, you can\'t delete a summarized message')
|
||||
return
|
||||
}
|
||||
if (message.summary) {
|
||||
// We're linked to messages we're a summary of
|
||||
if (window.confirm('Are you sure you want to delete this summary?\nYour session may be too long to submit again after you do.')) {
|
||||
try {
|
||||
deleteSummaryMessage(chatId, message.uuid)
|
||||
} catch (e) {
|
||||
window.alert('Unable to delete summary:\n' + e.message)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
try {
|
||||
deleteMessage(chatId, message.uuid)
|
||||
} catch (e) {
|
||||
window.alert('Unable to delete:\n' + e.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let waitingForTruncateConfirm:any = 0
|
||||
|
||||
const checkTruncate = () => {
|
||||
clearTimeout(waitingForDeleteConfirm); waitingForDeleteConfirm = 0
|
||||
if (!waitingForTruncateConfirm) {
|
||||
// wait a second for another click to avoid accidental deletes
|
||||
waitingForTruncateConfirm = setTimeout(() => { waitingForTruncateConfirm = 0 }, 1000)
|
||||
return
|
||||
}
|
||||
clearTimeout(waitingForTruncateConfirm)
|
||||
waitingForTruncateConfirm = 0
|
||||
if (message.summarized) {
|
||||
// is in a summary, so we're summarized
|
||||
window.alert('Sorry, you can\'t truncate a summarized message')
|
||||
return
|
||||
}
|
||||
try {
|
||||
truncateFromMessage(chatId, message.uuid)
|
||||
$submitExitingPromptsNow = true
|
||||
} catch (e) {
|
||||
window.alert('Unable to delete:\n' + e.message)
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
{#key message.uuid}
|
||||
|
@ -136,39 +171,61 @@
|
|||
class:editing={editing}
|
||||
>
|
||||
<div class="message-body content">
|
||||
<div class="greyscale is-pulled-right ml-2 button-pack">
|
||||
<div class="button-pack">
|
||||
{#if message.summarized}
|
||||
<a
|
||||
href={'#'}
|
||||
class="msg-summary-button"
|
||||
title="Jump to summary"
|
||||
class="msg-summary-button button is-small is-info"
|
||||
on:click|preventDefault={() => {
|
||||
scrollToMessage(message.summarized)
|
||||
}}
|
||||
>
|
||||
<Fa icon={faDiagramNext} />
|
||||
<span class="icon"><Fa icon={faDiagramNext} /></span>
|
||||
</a>
|
||||
{/if}
|
||||
{#if message.summary}
|
||||
<a
|
||||
href={'#'}
|
||||
class="msg-summarized-button"
|
||||
title="Jump to summarized"
|
||||
class="msg-summarized-button button is-small is-info"
|
||||
on:click|preventDefault={() => {
|
||||
scrollToMessage(message.summary)
|
||||
}}
|
||||
>
|
||||
<Fa icon={faDiagramPredecessor} />
|
||||
<span class="icon"><Fa icon={faDiagramPredecessor} /></span>
|
||||
</a>
|
||||
{/if}
|
||||
{#if !message.summarized}
|
||||
<a
|
||||
href={'#'}
|
||||
class=" msg-delete-button"
|
||||
title="Delete this message"
|
||||
class=" msg-delete-button button is-small is-warning"
|
||||
on:click|preventDefault={() => {
|
||||
// messages.splice(i, 1)
|
||||
checkDelete()
|
||||
}}
|
||||
>
|
||||
<Fa icon={faTrash} />
|
||||
{#if waitingForDeleteConfirm}
|
||||
<span class="icon"><Fa icon={faCircleCheck} /></span>
|
||||
{:else}
|
||||
<span class="icon"><Fa icon={faTrash} /></span>
|
||||
{/if}
|
||||
</a>
|
||||
{/if}
|
||||
{#if !message.summarized}
|
||||
<a
|
||||
href={'#'}
|
||||
title="Truncate all and submit"
|
||||
class=" msg-delete-button button is-small is-danger"
|
||||
on:click|preventDefault={() => {
|
||||
checkTruncate()
|
||||
}}
|
||||
>
|
||||
{#if waitingForTruncateConfirm}
|
||||
<span class="icon"><Fa icon={faCircleCheck} /></span>
|
||||
{:else}
|
||||
<span class="icon"><Fa icon={faPaperPlane} /></span>
|
||||
{/if}
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -216,17 +273,25 @@
|
|||
min-width: 100px;
|
||||
min-height: 30px;
|
||||
}
|
||||
.button-pack .button {
|
||||
display: block;
|
||||
margin: 4px;
|
||||
border-radius: 10px;
|
||||
opacity: .8;
|
||||
}
|
||||
.button-pack .button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.button-pack {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 2px;
|
||||
right: -20px;
|
||||
top: -20px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.assistant-message .button-pack {
|
||||
right: auto;
|
||||
left: 5px;
|
||||
top: 2px;
|
||||
left: -20px;
|
||||
}
|
||||
.message {
|
||||
position: relative;
|
||||
|
|
|
@ -9,17 +9,6 @@
|
|||
|
||||
$: activeChatId = $params && $params.chatId ? parseInt($params.chatId) : undefined
|
||||
|
||||
// let fileinput
|
||||
|
||||
// const onFileSelected = (e) => {
|
||||
// const image = e.target.files[0]
|
||||
// const reader = new FileReader()
|
||||
// reader.readAsText(image)
|
||||
// reader.onload = e => {
|
||||
// const json = (e.target || {}).result as string
|
||||
// addChatFromJSON(json)
|
||||
// }
|
||||
// }
|
||||
</script>
|
||||
|
||||
<aside class="menu">
|
||||
|
@ -48,53 +37,5 @@
|
|||
>
|
||||
</li>
|
||||
{/if}
|
||||
<!-- <li>
|
||||
<a class="panel-block"
|
||||
href="{'#/'}"
|
||||
class:is-disabled={!$apiKeyStorage}
|
||||
on:click|preventDefault={() => {
|
||||
const confirmDelete = window.confirm('Are you sure you want to delete all your chats?')
|
||||
if (confirmDelete) {
|
||||
replace('#/').then(() => clearChats())
|
||||
}
|
||||
}}><span class="greyscale mr-2"><Fa icon={faTrash} /></span> Clear chats</a
|
||||
>
|
||||
</li>
|
||||
{#if activeChatId}
|
||||
<li>
|
||||
<a
|
||||
href={'#/'}
|
||||
class="panel-block"
|
||||
class:is-disabled={!apiKeyStorage}
|
||||
on:click|preventDefault={() => {
|
||||
if (activeChatId) {
|
||||
exportAsMarkdown(activeChatId)
|
||||
}
|
||||
}}><span class="greyscale mr-2"><Fa icon={faFileExport} /></span> Export chat</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href={'#/'}
|
||||
class="panel-block"
|
||||
class:is-disabled={!apiKeyStorage}
|
||||
on:click|preventDefault={() => {
|
||||
if (activeChatId) {
|
||||
exportChatAsJSON(activeChatId)
|
||||
}
|
||||
}}><span class="greyscale mr-2"><Fa icon={faDownload} /></span> Save chat</a
|
||||
>
|
||||
</li>
|
||||
|
||||
{/if} -->
|
||||
<!-- <li>
|
||||
<a
|
||||
href={'#/'}
|
||||
class="panel-block"
|
||||
class:is-disabled={!apiKeyStorage}
|
||||
on:click|preventDefault={() => { fileinput.click() }}><span class="greyscale mr-2"><Fa icon={faUpload} /></span> Load chat</a
|
||||
>
|
||||
<input style="display:none" type="file" accept=".json" on:change={(e) => onFileSelected(e)} bind:this={fileinput} >
|
||||
</li> -->
|
||||
</ul>
|
||||
</aside>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
export const apiKeyStorage = persisted('apiKey', '' as string)
|
||||
export let checkStateChange = writable(0) // Trigger for Chat
|
||||
export let showSetChatSettings = writable(false) //
|
||||
export let submitExitingPromptsNow = writable(false) // for them to go now. Will not submit anything in the input
|
||||
|
||||
const chatDefaults = getChatDefaults()
|
||||
|
||||
|
@ -219,6 +220,20 @@
|
|||
chatsStorage.set(chats)
|
||||
}
|
||||
|
||||
export const truncateFromMessage = (chatId: number, uuid: string) => {
|
||||
const chats = get(chatsStorage)
|
||||
const chat = chats.find((chat) => chat.id === chatId) as Chat
|
||||
const index = chat.messages.findIndex((m) => m.uuid === uuid)
|
||||
const message = getMessage(chat, uuid)
|
||||
if (message && message.summarized) throw new Error('Unable to truncate from a summarized message')
|
||||
// const found = chat.messages.filter((m) => m.uuid === uuid)
|
||||
if (index < 0) {
|
||||
throw new Error(`Unable to find message with ID: ${uuid}`)
|
||||
}
|
||||
chat.messages.splice(index + 1) // remove every item after
|
||||
chatsStorage.set(chats)
|
||||
}
|
||||
|
||||
export const clearMessages = (chatId: number) => {
|
||||
const chats = get(chatsStorage)
|
||||
const chat = chats.find((chat) => chat.id === chatId) as Chat
|
||||
|
|
Loading…
Reference in New Issue