From f867825bf3b7699bc2bd967ef46b2bb63e48b098 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sun, 26 Jul 2026 21:08:49 -0400 Subject: [PATCH] refac --- .../automations/FolderDropdown.svelte | 1 + src/lib/components/chat/Chat.svelte | 3 + .../chat/Placeholder/ChatList.svelte | 46 +++++++-- .../chat/Placeholder/FolderPlaceholder.svelte | 96 ++++++++++++++++--- 4 files changed, 127 insertions(+), 19 deletions(-) diff --git a/src/lib/components/automations/FolderDropdown.svelte b/src/lib/components/automations/FolderDropdown.svelte index dfd6421c3f..0ab80797d7 100644 --- a/src/lib/components/automations/FolderDropdown.svelte +++ b/src/lib/components/automations/FolderDropdown.svelte @@ -57,6 +57,7 @@ items={folderOptions.map((folder) => ({ value: folder.id, label: folderName(folder) }))} placeholder={$i18n.t('Choose folder')} {align} + {side} triggerClass="relative h-8 max-w-[11rem] flex items-center gap-1.5 px-2.5 py-1.5 bg-transparent rounded-2xl text-xs font-normal text-gray-600 transition hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100" contentClass="w-72 shadow-lg" maxHeight="18rem" diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 5d657e92f8..587aa9ec17 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -952,6 +952,9 @@ if ($chatId && !$temporaryChatEnabled && hasPendingAssistantLeaf()) { await loadChat(); } + if ($chatId && !$temporaryChatEnabled) { + updateLastReadAt($chatId); + } } } else if (type === 'chat:completion') { chatCompletionEventHandler(data, message, event.chat_id); diff --git a/src/lib/components/chat/Placeholder/ChatList.svelte b/src/lib/components/chat/Placeholder/ChatList.svelte index 23a99c2cd3..884d3fd6e8 100644 --- a/src/lib/components/chat/Placeholder/ChatList.svelte +++ b/src/lib/components/chat/Placeholder/ChatList.svelte @@ -2,7 +2,11 @@ import { getContext } from 'svelte'; import type { Writable } from 'svelte/store'; - const i18n: Writable = getContext('i18n'); + type ChatListI18n = { + t: (key: string, options?: Record) => string; + }; + + const i18n: Writable = getContext('i18n'); import dayjs from 'dayjs'; import localizedFormat from 'dayjs/plugin/localizedFormat'; @@ -13,11 +17,24 @@ import ChevronRight from '$lib/components/icons/ChevronRight.svelte'; import Tooltip from '$lib/components/common/Tooltip.svelte'; import Spinner from '$lib/components/common/Spinner.svelte'; - import { chatId } from '$lib/stores'; + import { chatId, socket } from '$lib/stores'; dayjs.extend(localizedFormat); - export let chats: any[] = []; + type ChatListItem = { + id: string; + title?: string; + updated_at?: number | null; + created_at?: number | null; + last_read_at?: number | null; + active?: boolean; + time_range?: string; + user_id?: string; + owner_name?: string; + [key: string]: unknown; + }; + + export let chats: ChatListItem[] = []; export let chatListLoading = false; export let showOwnerInfo = false; @@ -26,10 +43,10 @@ export let perPage = 10; export let orderBy: 'title' | 'updated_at' = 'updated_at'; export let direction: 'asc' | 'desc' = 'desc'; - export let onPageChange: Function = () => {}; - export let onSort: Function = () => {}; + export let onPageChange: (page: number) => void | Promise = () => {}; + export let onSort: (key: 'title' | 'updated_at') => void | Promise = () => {}; - let chatList: any[] | null = null; + let chatList: ChatListItem[] | null = null; let totalPages = 1; let pages: (number | 'ellipsis')[] = []; @@ -48,6 +65,22 @@ onSort(key); }; + const markChatRead = (chat: ChatListItem, unread: boolean) => { + if (!unread) { + return; + } + + const lastReadAt = Date.now() / 1000; + chatList = (chatList ?? []).map((item) => + item.id === chat.id ? { ...item, last_read_at: lastReadAt } : item + ); + + $socket?.emit('events:chat', { + chat_id: chat.id, + data: { type: 'last_read_at' } + }); + }; + const buildPages = (currentPage: number, pageCount: number): (number | 'ellipsis')[] => { if (pageCount <= 7) { return Array.from({ length: pageCount }, (_, i) => i + 1); @@ -177,6 +210,7 @@ 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" draggable="false" href={`/c/${chat.id}`} + on:click={() => markChatRead(chat, unread)} >
{#if chat.active} diff --git a/src/lib/components/chat/Placeholder/FolderPlaceholder.svelte b/src/lib/components/chat/Placeholder/FolderPlaceholder.svelte index c943f57ee0..51140881b8 100644 --- a/src/lib/components/chat/Placeholder/FolderPlaceholder.svelte +++ b/src/lib/components/chat/Placeholder/FolderPlaceholder.svelte @@ -1,19 +1,27 @@