|
|
@@ -1,6 +1,7 @@
|
|
|
<script lang="ts">
|
|
|
- import { Trash2, Pencil, MoreHorizontal, Download, Loader2 } from '@lucide/svelte';
|
|
|
+ import { Trash2, Pencil, MoreHorizontal, Download, Loader2, Square } from '@lucide/svelte';
|
|
|
import { ActionDropdown } from '$lib/components/app';
|
|
|
+ import * as Tooltip from '$lib/components/ui/tooltip';
|
|
|
import { getAllLoadingChats } from '$lib/stores/chat.svelte';
|
|
|
import { conversationsStore } from '$lib/stores/conversations.svelte';
|
|
|
import { onMount } from 'svelte';
|
|
|
@@ -12,6 +13,7 @@
|
|
|
onDelete?: (id: string) => void;
|
|
|
onEdit?: (id: string) => void;
|
|
|
onSelect?: (id: string) => void;
|
|
|
+ onStop?: (id: string) => void;
|
|
|
}
|
|
|
|
|
|
let {
|
|
|
@@ -20,6 +22,7 @@
|
|
|
onDelete,
|
|
|
onEdit,
|
|
|
onSelect,
|
|
|
+ onStop,
|
|
|
isActive = false
|
|
|
}: Props = $props();
|
|
|
|
|
|
@@ -38,8 +41,14 @@
|
|
|
onDelete?.(conversation.id);
|
|
|
}
|
|
|
|
|
|
+ function handleStop(event: Event) {
|
|
|
+ event.stopPropagation();
|
|
|
+ onStop?.(conversation.id);
|
|
|
+ }
|
|
|
+
|
|
|
function handleGlobalEditEvent(event: Event) {
|
|
|
const customEvent = event as CustomEvent<{ conversationId: string }>;
|
|
|
+
|
|
|
if (customEvent.detail.conversationId === conversation.id && isActive) {
|
|
|
handleEdit(event);
|
|
|
}
|
|
|
@@ -88,8 +97,28 @@
|
|
|
>
|
|
|
<div class="flex min-w-0 flex-1 items-center gap-2">
|
|
|
{#if isLoading}
|
|
|
- <Loader2 class="h-3.5 w-3.5 shrink-0 animate-spin text-muted-foreground" />
|
|
|
+ <Tooltip.Root>
|
|
|
+ <Tooltip.Trigger>
|
|
|
+ <div
|
|
|
+ class="stop-button flex h-4 w-4 shrink-0 cursor-pointer items-center justify-center rounded text-muted-foreground transition-colors hover:text-foreground"
|
|
|
+ onclick={handleStop}
|
|
|
+ onkeydown={(e) => e.key === 'Enter' && handleStop(e)}
|
|
|
+ role="button"
|
|
|
+ tabindex="0"
|
|
|
+ aria-label="Stop generation"
|
|
|
+ >
|
|
|
+ <Loader2 class="loading-icon h-3.5 w-3.5 animate-spin" />
|
|
|
+
|
|
|
+ <Square class="stop-icon hidden h-3 w-3 fill-current text-destructive" />
|
|
|
+ </div>
|
|
|
+ </Tooltip.Trigger>
|
|
|
+
|
|
|
+ <Tooltip.Content>
|
|
|
+ <p>Stop generation</p>
|
|
|
+ </Tooltip.Content>
|
|
|
+ </Tooltip.Root>
|
|
|
{/if}
|
|
|
+
|
|
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
|
<span class="truncate text-sm font-medium" onclick={handleMobileSidebarItemClick}>
|
|
|
@@ -147,5 +176,25 @@
|
|
|
opacity: 1 !important;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ .stop-button {
|
|
|
+ :global(.stop-icon) {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ :global(.loading-icon) {
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &:is(:hover) .stop-button {
|
|
|
+ :global(.stop-icon) {
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+
|
|
|
+ :global(.loading-icon) {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|