Files
beavergram/frontend/src/lib/components/ChatList.svelte
T

96 lines
2.7 KiB
Svelte

<script lang="ts">
import { cubicOut } from "svelte/easing";
import { fly } from "svelte/transition";
import { goto } from "$app/navigation";
import { page } from "$app/state";
import ChatListItem from "$lib/components/ChatListItem.svelte";
import EmptyState from "$lib/components/ui/EmptyState.svelte";
import Skeleton from "$lib/components/ui/Skeleton.svelte";
import { folderContains } from "$lib/format/folders";
import { accounts } from "$lib/stores/accounts.svelte";
import { chats } from "$lib/stores/chats.svelte";
import { folders } from "$lib/stores/folders.svelte";
import { toasts } from "$lib/stores/toasts.svelte";
const skeletonRows = Array.from({ length: 9 }, (_, index) => index);
const activeChatId = $derived(
page.params.chatId ? Number(page.params.chatId) : null
);
const selectedFolder = $derived(folders.selected);
const visibleChats = $derived(
selectedFolder === null
? chats.list
: chats.list.filter((chat) => folderContains(selectedFolder, chat))
);
$effect(() => {
if (accounts.selectedId === null) {
return;
}
chats.load().catch(() => toasts.error("Failed to load chats"));
folders.load().catch(() => toasts.error("Failed to load folders"));
});
</script>
<div class="chat-list custom-scroll">
{#if chats.loading && chats.list.length === 0}
{#each skeletonRows as index (index)}
<div class="row-skeleton">
<Skeleton width="3rem" height="3rem" circle />
<div class="row-skeleton-lines">
<Skeleton width="55%" height="0.875rem" />
<Skeleton width="80%" height="0.8125rem" />
</div>
</div>
{/each}
{:else if chats.list.length === 0}
<EmptyState title="No chats yet" />
{:else}
{#key folders.selectedId}
<div
class="folder-view"
in:fly={{ x: folders.direction * 24, duration: 200, easing: cubicOut }}
>
{#if visibleChats.length === 0}
<EmptyState
title="Empty folder"
description="No chats match this folder yet"
/>
{:else}
{#each visibleChats as chat (chat.chat_id)}
<ChatListItem
{chat}
selected={chat.chat_id === activeChatId}
onclick={() => goto(`/app/${chat.chat_id}`)}
/>
{/each}
{/if}
</div>
{/key}
{/if}
</div>
<style lang="scss">
.chat-list {
overflow-y: auto;
flex: 1;
padding: 0.25rem 0.4375rem;
}
.row-skeleton {
display: flex;
align-items: center;
gap: 0.625rem;
padding: 0.5625rem 0.5rem;
}
.row-skeleton-lines {
display: flex;
flex: 1;
flex-direction: column;
gap: 0.5rem;
}
</style>