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}
 | 
					 | 
				
			||||||
            <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}
 | 
					      {/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