* chore: Spacing between sibling elements in html markup * chore: Formatting and linting rules
99 lines
2.6 KiB
Svelte
99 lines
2.6 KiB
Svelte
<script lang="ts">
|
|
import { browser } from '$app/environment';
|
|
import { goto } from '$app/navigation';
|
|
import { page } from '$app/state';
|
|
import { 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';
|
|
|
|
let searchQuery = $state('');
|
|
let searchInputRef = $state<HTMLInputElement | null>(null);
|
|
|
|
let currentChatId = $derived(page.params.id);
|
|
|
|
let filteredConversations = $derived.by(() => {
|
|
const query = searchQuery.trim().toLowerCase();
|
|
|
|
if (query.length === 0) return [];
|
|
|
|
return conversationsStore.conversations.filter((c) => c.name.toLowerCase().includes(query));
|
|
});
|
|
|
|
// Search page is intended for mobile; on desktop the sidebar already exposes
|
|
// in-place search, so bounce back to a new-chat tab without a history entry.
|
|
$effect(() => {
|
|
if (browser && !deviceStore.isMobile) {
|
|
goto(ROUTES.START, { replaceState: true });
|
|
}
|
|
});
|
|
|
|
async function selectConversation(id: string) {
|
|
await goto(RouterService.chat(id));
|
|
}
|
|
|
|
async function handleEditConversation(id: string) {
|
|
const conversation = conversationsStore.conversations.find((c) => c.id === id);
|
|
|
|
if (!conversation) return;
|
|
|
|
const newName = window.prompt('Rename conversation', conversation.name);
|
|
|
|
if (newName && newName.trim()) {
|
|
await conversationsStore.updateConversationName(id, newName.trim());
|
|
}
|
|
}
|
|
|
|
async 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.`
|
|
);
|
|
|
|
if (!confirmed) return;
|
|
|
|
await conversationsStore.deleteConversation(id, { deleteWithForks: false });
|
|
}
|
|
|
|
function handleStopGeneration(id: string) {
|
|
chatStore.stopGenerationForChat(id);
|
|
}
|
|
|
|
function handleBack() {
|
|
if (history.length > 1) {
|
|
history.back();
|
|
} else {
|
|
conversationsStore.openNewChat();
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>Search · llama.cpp</title>
|
|
</svelte:head>
|
|
|
|
<div class="fixed top-0 z-10 left-0 right-0 p-2">
|
|
<SearchInput
|
|
bind:ref={searchInputRef}
|
|
bind:value={searchQuery}
|
|
autofocus
|
|
onClose={handleBack}
|
|
placeholder="Search conversations..."
|
|
/>
|
|
</div>
|
|
|
|
<div class="p-2 pt-16">
|
|
<SidebarNavigationSearchResults
|
|
{currentChatId}
|
|
{filteredConversations}
|
|
onDelete={handleDeleteConversation}
|
|
onEdit={handleEditConversation}
|
|
onSelect={selectConversation}
|
|
onStop={handleStopGeneration}
|
|
{searchQuery}
|
|
/>
|
|
</div>
|