Commit f5892ca5a for llama.cpp
commit f5892ca5ad32685d0b1e6a54bd3e423756ea8077
Author: Aleksander Grygier <aleksander.grygier@gmail.com>
Date: Tue Oct 27 06:45:53 2026 +0100
ui: use shared confirmation dialog for conversation deletion (#31187)
Extract the keyboard-shortcut delete confirmation into DialogConversationDelete
and reuse it in the sidebar and mobile search page instead of the native
window.confirm prompt.
Assisted-by: Claude (Opus 5.5 Medium)
diff --git a/tools/ui/src/lib/components/app/chat/ChatScreen/ChatScreenDialogsAndAlerts.svelte b/tools/ui/src/lib/components/app/chat/ChatScreen/ChatScreenDialogsAndAlerts.svelte
index feba9ee35..d8ff0d2ee 100644
--- a/tools/ui/src/lib/components/app/chat/ChatScreen/ChatScreenDialogsAndAlerts.svelte
+++ b/tools/ui/src/lib/components/app/chat/ChatScreen/ChatScreenDialogsAndAlerts.svelte
@@ -1,8 +1,7 @@
<script lang="ts">
- import { Trash2 } from '@lucide/svelte';
import {
DialogChatError,
- DialogConfirmation,
+ DialogConversationDelete,
DialogEmptyFileAlert,
DialogFileUploadError
} from '$lib/components/app';
@@ -24,16 +23,10 @@
fileErrorData={fileUpload.fileErrorData}
/>
-<DialogConfirmation
+<DialogConversationDelete
bind:open={showDeleteDialog}
- cancelText="Cancel"
- confirmText="Delete"
- description="Are you sure you want to delete this conversation? This action cannot be undone and will permanently remove all messages in this conversation."
- icon={Trash2}
onCancel={() => (showDeleteDialog = false)}
onConfirm={handleDeleteConfirm}
- title="Delete Conversation"
- variant="destructive"
/>
<DialogEmptyFileAlert
diff --git a/tools/ui/src/lib/components/app/dialogs/DialogConversationDelete.svelte b/tools/ui/src/lib/components/app/dialogs/DialogConversationDelete.svelte
new file mode 100644
index 000000000..b25259f63
--- /dev/null
+++ b/tools/ui/src/lib/components/app/dialogs/DialogConversationDelete.svelte
@@ -0,0 +1,24 @@
+<script lang="ts">
+ import { Trash2 } from '@lucide/svelte';
+ import { DialogConfirmation } from '$lib/components/app';
+
+ interface Props {
+ open: boolean;
+ onConfirm: () => void;
+ onCancel: () => void;
+ }
+
+ let { onCancel, onConfirm, open = $bindable() }: Props = $props();
+</script>
+
+<DialogConfirmation
+ bind:open
+ cancelText="Cancel"
+ confirmText="Delete"
+ description="Are you sure you want to delete this conversation? This action cannot be undone and will permanently remove all messages in this conversation."
+ icon={Trash2}
+ {onCancel}
+ {onConfirm}
+ title="Delete Conversation"
+ variant="destructive"
+/>
diff --git a/tools/ui/src/lib/components/app/dialogs/index.ts b/tools/ui/src/lib/components/app/dialogs/index.ts
index 5c6a56f00..ff287ec18 100644
--- a/tools/ui/src/lib/components/app/dialogs/index.ts
+++ b/tools/ui/src/lib/components/app/dialogs/index.ts
@@ -119,6 +119,23 @@ export { default as DialogConfirmation } from './DialogConfirmation.svelte';
*/
export { default as DialogConfirmDownload } from './DialogConfirmDownload.svelte';
+/**
+ * **DialogConversationDelete** - Confirm deleting a conversation
+ *
+ * Destructive confirmation shared by every conversation delete entry point
+ * (keyboard shortcut, sidebar, mobile search).
+ *
+ * @example
+ * ```svelte
+ * <DialogConversationDelete
+ * bind:open={showDelete}
+ * onConfirm={handleDelete}
+ * onCancel={() => (showDelete = false)}
+ * />
+ * ```
+ */
+export { default as DialogConversationDelete } from './DialogConversationDelete.svelte';
+
/**
* **DialogConversationRename** - Rename a conversation
*
diff --git a/tools/ui/src/lib/components/app/navigation/SidebarNavigation/SidebarNavigation.svelte b/tools/ui/src/lib/components/app/navigation/SidebarNavigation/SidebarNavigation.svelte
index 9fb451361..4430de50c 100644
--- a/tools/ui/src/lib/components/app/navigation/SidebarNavigation/SidebarNavigation.svelte
+++ b/tools/ui/src/lib/components/app/navigation/SidebarNavigation/SidebarNavigation.svelte
@@ -4,6 +4,7 @@
import { page } from '$app/state';
import {
ActionIcon,
+ DialogConversationDelete,
DialogConversationRename,
DialogDiscoverModels,
DialogMcpServers,
@@ -280,20 +281,32 @@
renameOriginalTitle = '';
}
- async function handleDeleteConversation(id: string) {
+ let deleteDialogOpen = $state(false);
+ let deleteTargetId = $state<string | null>(null);
+
+ function handleDeleteConversation(id: string) {
const conversation = conversationsStore.conversations.find((conv) => conv.id === id);
if (!conversation) return;
- const confirmed = window.confirm(
- `Delete "${conversation.name}"? This action cannot be undone.`
- );
+ deleteTargetId = conversation.id;
+ deleteDialogOpen = true;
+ }
+
+ async function handleDeleteConfirm() {
+ const id = deleteTargetId;
- if (!confirmed) return;
+ deleteDialogOpen = false;
+
+ if (!id) return;
await conversationsStore.deleteConversation(id, { deleteWithForks: false });
}
+ function handleDeleteCancel() {
+ deleteDialogOpen = false;
+ }
+
function handleStopGeneration(id: string) {
chatStore.stopGenerationForChat(id);
}
@@ -617,6 +630,12 @@
onConfirm={handleRenameConfirm}
/>
+<DialogConversationDelete
+ bind:open={deleteDialogOpen}
+ onCancel={handleDeleteCancel}
+ onConfirm={handleDeleteConfirm}
+/>
+
<DialogSettingsChat bind:open={settingsDialogOpen} />
<DialogMcpServers bind:open={mcpDialogOpen} />
diff --git a/tools/ui/src/routes/search/+page.svelte b/tools/ui/src/routes/search/+page.svelte
index 5b68d267f..cd4626881 100644
--- a/tools/ui/src/routes/search/+page.svelte
+++ b/tools/ui/src/routes/search/+page.svelte
@@ -2,7 +2,11 @@
import { browser } from '$app/environment';
import { goto } from '$app/navigation';
import { page } from '$app/state';
- import { SearchInput, SidebarNavigationSearchResults } from '$lib/components/app';
+ import {
+ DialogConversationDelete,
+ SearchInput,
+ SidebarNavigationSearchResults
+ } from '$lib/components/app';
import { ROUTES } from '$lib/constants';
import { RouterService } from '$lib/services/router.service';
import { chatStore, conversationsStore, deviceStore } from '$lib/stores';
@@ -44,20 +48,32 @@
}
}
- async function handleDeleteConversation(id: string) {
+ let deleteDialogOpen = $state(false);
+ let deleteTargetId = $state<string | null>(null);
+
+ function handleDeleteConversation(id: string) {
const conversation = conversationsStore.conversations.find((c) => c.id === id);
if (!conversation) return;
- const confirmed = window.confirm(
- `Delete "${conversation.name}"? This action cannot be undone.`
- );
+ deleteTargetId = conversation.id;
+ deleteDialogOpen = true;
+ }
+
+ async function handleDeleteConfirm() {
+ const id = deleteTargetId;
+
+ deleteDialogOpen = false;
- if (!confirmed) return;
+ if (!id) return;
await conversationsStore.deleteConversation(id, { deleteWithForks: false });
}
+ function handleDeleteCancel() {
+ deleteDialogOpen = false;
+ }
+
function handleStopGeneration(id: string) {
chatStore.stopGenerationForChat(id);
}
@@ -96,3 +112,9 @@
{searchQuery}
/>
</div>
+
+<DialogConversationDelete
+ bind:open={deleteDialogOpen}
+ onCancel={handleDeleteCancel}
+ onConfirm={handleDeleteConfirm}
+/>