enh: search modal actions

This commit is contained in:
Timothy Jaeryang Baek 2025-09-24 16:29:02 -05:00
parent 9f0010e234
commit aa6f63a335
1 changed files with 72 additions and 11 deletions

View File

@ -15,11 +15,34 @@
import { user } from '$lib/stores'; import { user } from '$lib/stores';
import Messages from '../chat/Messages.svelte'; import Messages from '../chat/Messages.svelte';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import PencilSquare from '../icons/PencilSquare.svelte';
import Note from '../icons/Note.svelte';
dayjs.extend(calendar); dayjs.extend(calendar);
export let show = false; export let show = false;
export let onClose = () => {}; export let onClose = () => {};
let actions = [
{
label: 'Start a new conversation',
onClick: async () => {
await goto(`/${query ? `?q=${query}` : ''}`);
show = false;
onClose();
},
icon: PencilSquare
},
{
label: 'Create a new note',
onClick: async () => {
await goto('/notes');
show = false;
onClose();
},
icon: Note
}
];
let query = ''; let query = '';
let page = 1; let page = 1;
@ -55,7 +78,13 @@
return; return;
} }
const chatId = chatList[selectedIdx].id; const selectedChatIdx = selectedIdx - actions.length;
if (selectedChatIdx < 0) {
selectedChat = null;
return;
}
const chatId = chatList[selectedChatIdx].id;
const chat = await getChatById(localStorage.token, chatId).catch(async (error) => { const chat = await getChatById(localStorage.token, chatId).catch(async (error) => {
return null; return null;
@ -162,13 +191,13 @@
if (e.code === 'Escape') { if (e.code === 'Escape') {
show = false; show = false;
onClose(); onClose();
} else if (e.code === 'Enter' && (chatList ?? []).length > 0) { } else if (e.code === 'Enter') {
const item = document.querySelector(`[data-arrow-selected="true"]`); const item = document.querySelector(`[data-arrow-selected="true"]`);
if (item) { if (item) {
item?.click(); item?.click();
show = false;
} }
show = false;
return; return;
} else if (e.code === 'ArrowDown') { } else if (e.code === 'ArrowDown') {
const searchInput = document.getElementById('search-input'); const searchInput = document.getElementById('search-input');
@ -182,7 +211,7 @@
} }
} }
selectedIdx = Math.min(selectedIdx + 1, (chatList ?? []).length - 1); selectedIdx = Math.min(selectedIdx + 1, (chatList ?? []).length - 1 + actions.length);
} else if (e.code === 'ArrowUp') { } else if (e.code === 'ArrowUp') {
if (selectedIdx === 0) { if (selectedIdx === 0) {
const searchInput = document.getElementById('search-input'); const searchInput = document.getElementById('search-input');
@ -240,7 +269,7 @@
show = false; show = false;
return; return;
} else if (e.code === 'ArrowDown') { } else if (e.code === 'ArrowDown') {
selectedIdx = Math.min(selectedIdx + 1, (chatList ?? []).length - 1); selectedIdx = Math.min(selectedIdx + 1, (chatList ?? []).length - 1 + actions.length);
} else if (e.code === 'ArrowUp') { } else if (e.code === 'ArrowUp') {
selectedIdx = Math.max(selectedIdx - 1, 0); selectedIdx = Math.max(selectedIdx - 1, 0);
} else { } else {
@ -257,11 +286,43 @@
<div class="flex px-4 pb-1"> <div class="flex px-4 pb-1">
<div <div
class="flex flex-col overflow-y-auto h-96 md:h-[40rem] max-h-full scrollbar-hidden w-full flex-1" class="flex flex-col overflow-y-auto h-96 md:h-[40rem] max-h-full scrollbar-hidden w-full flex-1 pr-2"
> >
<div class="w-full text-xs text-gray-500 dark:text-gray-500 font-medium pb-2 px-2">
{$i18n.t('Actions')}
</div>
{#each actions as action, idx (action.label)}
<button
class=" w-full flex items-center rounded-xl text-sm py-2 px-3 hover:bg-gray-50 dark:hover:bg-gray-850 {selectedIdx ===
idx
? 'bg-gray-50 dark:bg-gray-850'
: ''}"
data-arrow-selected={selectedIdx === idx ? 'true' : undefined}
dragabble="false"
on:mouseenter={() => {
selectedIdx = idx;
}}
on:click={async () => {
await action.onClick();
}}
>
<div class="pr-2">
<svelte:component this={action.icon} />
</div>
<div class=" flex-1 text-left">
<div class="text-ellipsis line-clamp-1 w-full">
{$i18n.t(action.label)}
</div>
</div>
</button>
{/each}
{#if chatList} {#if chatList}
<hr class="border-gray-50 dark:border-gray-850 my-3" />
{#if chatList.length === 0} {#if chatList.length === 0}
<div class="text-xs text-gray-500 dark:text-gray-400 text-center px-5"> <div class="text-xs text-gray-500 dark:text-gray-400 text-center px-5 py-4">
{$i18n.t('No results found')} {$i18n.t('No results found')}
</div> </div>
{/if} {/if}
@ -296,15 +357,15 @@
{/if} {/if}
<a <a
class=" w-full flex justify-between items-center rounded-lg text-sm py-2 px-3 hover:bg-gray-50 dark:hover:bg-gray-850 {selectedIdx === class=" w-full flex justify-between items-center rounded-xl text-sm py-2 px-3 hover:bg-gray-50 dark:hover:bg-gray-850 {selectedIdx ===
idx idx + actions.length
? 'bg-gray-50 dark:bg-gray-850' ? 'bg-gray-50 dark:bg-gray-850'
: ''}" : ''}"
href="/c/{chat.id}" href="/c/{chat.id}"
draggable="false" draggable="false"
data-arrow-selected={selectedIdx === idx ? 'true' : undefined} data-arrow-selected={selectedIdx === idx + actions.length ? 'true' : undefined}
on:mouseenter={() => { on:mouseenter={() => {
selectedIdx = idx; selectedIdx = idx + actions.length;
}} }}
on:click={async () => { on:click={async () => {
await goto(`/c/${chat.id}`); await goto(`/c/${chat.id}`);