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) | ||||
|     } | ||||
|  | @ -120,6 +96,65 @@ | |||
|     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
	
	 Webifi
						Webifi