This commit is contained in:
Timothy Jaeryang Baek
2026-07-26 23:54:16 -04:00
parent ba7c95f7ef
commit e5a08d5220
6 changed files with 106 additions and 1 deletions
+28
View File
@@ -913,6 +913,34 @@ export const markChatUnreadById = async (token: string, id: string) => {
return res;
};
export const markChatsRead = async (token: string) => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/chats/read`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...(token && { authorization: `Bearer ${token}` })
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
error = 'detail' in err ? err.detail : err;
console.error(err);
return null;
});
if (error) {
throw error;
}
return res;
};
export const cloneChatById = async (token: string, id: string, title?: string) => {
let error = null;
+46 -1
View File
@@ -31,6 +31,7 @@
loadNextChatListPage,
refreshChatList,
registerFolderRefreshHandler,
setAllChatsRead,
setChatActive,
setChatReadAt
} from '$lib/stores/chatList';
@@ -47,7 +48,8 @@
updateChatFolderIdById,
importChats,
deleteAllChats,
getChatListBySearchText
getChatListBySearchText,
markChatsRead
} from '$lib/apis/chats';
import {
createNewFolder,
@@ -86,6 +88,10 @@
import WorkspaceIcon from './Sidebar/icons/Workspace.svelte';
import { slide } from 'svelte/transition';
import HotkeyHint from '../common/HotkeyHint.svelte';
import Dropdown from '../common/Dropdown.svelte';
import DropdownMenu from '../common/DropdownMenu.svelte';
import CheckIcon from '../icons/Check.svelte';
import MoreHorizontalIcon from './Sidebar/icons/MoreHorizontal.svelte';
const BREAKPOINT = 768;
const DEFAULT_PINNED_ITEMS = ['notes', 'workspace'];
@@ -121,6 +127,7 @@
let showChannels = false;
let showFolders = false;
let showSharedFolders = false;
let showChatsMenu = false;
let folders = {};
let folderRegistry: Record<
@@ -440,6 +447,17 @@
}
};
const markAllChatsReadHandler = async () => {
const res = await markChatsRead(localStorage.token).catch((error) => {
toast.error(`${error}`);
return null;
});
if (!res) return;
showChatsMenu = false;
setAllChatsRead();
};
const importChatHandler = async (items, pinned = false, folderId = null) => {
if (!canImportChats) {
toast.error($i18n.t('Access prohibited'));
@@ -1434,6 +1452,33 @@
}
}}
>
<svelte:fragment slot="action">
<Dropdown bind:show={showChatsMenu} align="end">
<Tooltip content={$i18n.t('More')}>
<button
type="button"
class="flex items-center justify-center w-7 h-7 rounded-lg text-gray-300 hover:text-gray-500 dark:text-gray-600 dark:hover:text-gray-400 transition-colors duration-100"
aria-label={$i18n.t('More')}
on:pointerup|stopPropagation
>
<MoreHorizontalIcon className="size-3.5" strokeWidth="2" />
</button>
</Tooltip>
<div slot="content">
<DropdownMenu className="min-w-[170px]">
<button
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] select-none cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40"
on:click={markAllChatsReadHandler}
>
<CheckIcon className="size-3.5" />
<div class="flex items-center">{$i18n.t('Mark all as read')}</div>
</button>
</DropdownMenu>
</div>
</Dropdown>
</svelte:fragment>
{#if $pinnedChats.length > 0}
<div class="mb-1">
<div class="flex flex-col space-y-1 rounded-xl">
@@ -143,6 +143,8 @@
</span>
</button>
<slot name="action" />
{#if onAdd}
<button
type="button"
+7
View File
@@ -138,6 +138,13 @@ export const setChatReadAt = (chatId: string, lastReadAt: number): boolean => {
return found;
};
export const setAllChatsRead = () => {
const updateChat = (chat: ChatListItem) => ({ ...chat, last_read_at: chat.updated_at });
chatsStore.update((items) => (items ? items.map(updateChat) : items));
pinnedChatsStore.update((items) => items.map(updateChat));
};
export const resetChatListState = () => {
requestGeneration += 1;
currentPage = 1;