Add click+confirm for deleting chats in menu
This commit is contained in:
parent
cb00eea2d4
commit
3bf3db6b07
16
src/app.scss
16
src/app.scss
|
@ -179,3 +179,19 @@ $modal-background-background-color-dark: rgba($dark, 0.86) !default; // remove t
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-menu-item {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.chat-menu-item span {
|
||||||
|
display: block;
|
||||||
|
white-space:nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-mask-image: linear-gradient(to right, rgba(0,0,0,1) 75%, rgba(0,0,0,0));
|
||||||
|
mask-image: linear-gradient(to right, rgba(0,0,0,1) 75%, rgba(0,0,0,0));
|
||||||
|
}
|
||||||
|
.chat-menu-item .delete-button {
|
||||||
|
position: absolute;
|
||||||
|
right: .4em;
|
||||||
|
z-index: 200;
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { replace } from 'svelte-spa-router'
|
||||||
|
import type { Chat } from './Types.svelte'
|
||||||
|
import { apiKeyStorage, deleteChat } from './Storage.svelte'
|
||||||
|
import Fa from 'svelte-fa/src/fa.svelte'
|
||||||
|
import { faTrash, faCircleCheck } from '@fortawesome/free-solid-svg-icons/index'
|
||||||
|
|
||||||
|
export let chat:Chat
|
||||||
|
export let activeChatId:number|undefined
|
||||||
|
export let prevChat:Chat|undefined
|
||||||
|
export let nextChat:Chat|undefined
|
||||||
|
|
||||||
|
let waitingForConfirm:any = 0
|
||||||
|
|
||||||
|
function delChat () {
|
||||||
|
if (!waitingForConfirm) {
|
||||||
|
// wait a second for another click to avoid accidental deletes
|
||||||
|
waitingForConfirm = setTimeout(() => { waitingForConfirm = 0 }, 1000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
clearTimeout(waitingForConfirm)
|
||||||
|
waitingForConfirm = 0
|
||||||
|
if (activeChatId === chat.id) {
|
||||||
|
const newChat = nextChat || prevChat
|
||||||
|
if (!newChat) {
|
||||||
|
// No other chats, clear all and go to home
|
||||||
|
replace('/').then(() => { deleteChat(chat.id) })
|
||||||
|
} else {
|
||||||
|
// Delete the current chat and go to the max chatId
|
||||||
|
replace(`/chat/${newChat.id}`).then(() => { deleteChat(chat.id) })
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deleteChat(chat.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a class="chat-menu-item" href={`#/chat/${chat.id}`} class:is-waiting={waitingForConfirm} class:is-disabled={!$apiKeyStorage} class:is-active={activeChatId === chat.id}>
|
||||||
|
{#if waitingForConfirm}
|
||||||
|
<a class="is-pulled-right is-hidden px-1 py-0 greyscale has-text-weight-bold delete-button" href={'$'} on:click|preventDefault={() => delChat()}><Fa icon={faCircleCheck} /></a>
|
||||||
|
{:else}
|
||||||
|
<a class="is-pulled-right is-hidden px-1 py-0 greyscale has-text-weight-bold delete-button" href={'$'} on:click|preventDefault={() => delChat()}><Fa icon={faTrash} /></a>
|
||||||
|
{/if}
|
||||||
|
<span>{chat.name || `Chat ${chat.id}`}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
|
@ -133,6 +133,7 @@
|
||||||
class:user-message={message.role === 'user' || message.role === 'system'}
|
class:user-message={message.role === 'user' || message.role === 'system'}
|
||||||
class:assistant-message={message.role === 'error' || message.role === 'assistant'}
|
class:assistant-message={message.role === 'error' || message.role === 'assistant'}
|
||||||
class:summarized={message.summarized}
|
class:summarized={message.summarized}
|
||||||
|
class:editing={editing}
|
||||||
>
|
>
|
||||||
<div class="message-body content">
|
<div class="message-body content">
|
||||||
<div class="greyscale is-pulled-right ml-2 button-pack">
|
<div class="greyscale is-pulled-right ml-2 button-pack">
|
||||||
|
|
|
@ -1,35 +1,14 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { params, replace } from 'svelte-spa-router'
|
import { params } from 'svelte-spa-router'
|
||||||
|
import ChatMenuItem from './ChatMenuItem.svelte'
|
||||||
import { apiKeyStorage, chatsStorage, deleteChat } from './Storage.svelte'
|
import { apiKeyStorage, chatsStorage } from './Storage.svelte'
|
||||||
import Fa from 'svelte-fa/src/fa.svelte'
|
import Fa from 'svelte-fa/src/fa.svelte'
|
||||||
import { faSquarePlus, faTrash, faKey } from '@fortawesome/free-solid-svg-icons/index'
|
import { faSquarePlus, faKey } from '@fortawesome/free-solid-svg-icons/index'
|
||||||
|
|
||||||
$: sortedChats = $chatsStorage.sort((a, b) => b.id - a.id)
|
$: sortedChats = $chatsStorage.sort((a, b) => b.id - a.id)
|
||||||
|
|
||||||
$: activeChatId = $params && $params.chatId ? parseInt($params.chatId) : undefined
|
$: activeChatId = $params && $params.chatId ? parseInt($params.chatId) : undefined
|
||||||
|
|
||||||
|
|
||||||
function delChat (chatId:number) {
|
|
||||||
if (activeChatId === chatId) {
|
|
||||||
// Find the max chatId other than the current one
|
|
||||||
const newChatId = sortedChats.reduce((maxId, chat) => {
|
|
||||||
if (chat.id === chatId) return maxId
|
|
||||||
return Math.max(maxId, chat.id)
|
|
||||||
}, 0)
|
|
||||||
|
|
||||||
if (!newChatId) {
|
|
||||||
// No other chats, clear all and go to home
|
|
||||||
replace('/').then(() => { deleteChat(chatId) })
|
|
||||||
} else {
|
|
||||||
// Delete the current chat and go to the max chatId
|
|
||||||
replace(`/chat/${newChatId}`).then(() => { deleteChat(chatId) })
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
deleteChat(chatId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// let fileinput
|
// let fileinput
|
||||||
|
|
||||||
// const onFileSelected = (e) => {
|
// const onFileSelected = (e) => {
|
||||||
|
@ -49,18 +28,9 @@
|
||||||
{#if sortedChats.length === 0}
|
{#if sortedChats.length === 0}
|
||||||
<li><a href={'#'} class="is-disabled">No chats yet...</a></li>
|
<li><a href={'#'} class="is-disabled">No chats yet...</a></li>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- <li>
|
{#each sortedChats as chat, i}
|
||||||
<ul> -->
|
<ChatMenuItem activeChatId={activeChatId} chat={chat} prevChat={sortedChats[i - 1]} nextChat={sortedChats[i + 1]} />
|
||||||
{#each sortedChats as chat}
|
{/each}
|
||||||
<li>
|
|
||||||
<a class="chat-menu-item" href={`#/chat/${chat.id}`} class:is-disabled={!$apiKeyStorage} class:is-active={activeChatId === chat.id}>
|
|
||||||
<a class="is-pulled-right is-hidden px-1 py-0 greyscale has-text-weight-bold delete-button" href={'$'} on:click|preventDefault={() => delChat(chat.id)}><Fa icon={faTrash} /></a>
|
|
||||||
<span>{chat.name || `Chat ${chat.id}`}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{/each}
|
|
||||||
<!-- </ul>
|
|
||||||
</li> -->
|
|
||||||
{/if}
|
{/if}
|
||||||
</ul>
|
</ul>
|
||||||
<p class="menu-label">Actions</p>
|
<p class="menu-label">Actions</p>
|
||||||
|
@ -128,21 +98,3 @@
|
||||||
</li> -->
|
</li> -->
|
||||||
</ul>
|
</ul>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<style>
|
|
||||||
.chat-menu-item {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.chat-menu-item span {
|
|
||||||
display: block;
|
|
||||||
white-space:nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
-webkit-mask-image: linear-gradient(to right, rgba(0,0,0,1) 75%, rgba(0,0,0,0));
|
|
||||||
mask-image: linear-gradient(to right, rgba(0,0,0,1) 75%, rgba(0,0,0,0));
|
|
||||||
}
|
|
||||||
.chat-menu-item .delete-button {
|
|
||||||
position: absolute;
|
|
||||||
right: .4em;
|
|
||||||
z-index: 200;
|
|
||||||
}
|
|
||||||
</style>
|
|
Loading…
Reference in New Issue