diff --git a/web/src/hooks/logic-hooks/use-change-search.ts b/web/src/hooks/logic-hooks/use-change-search.ts index c404456ccf..66a3f42ffd 100644 --- a/web/src/hooks/logic-hooks/use-change-search.ts +++ b/web/src/hooks/logic-hooks/use-change-search.ts @@ -10,5 +10,5 @@ export const useHandleSearchStrChange = () => { [], ); - return { handleInputChange, searchString }; + return { handleInputChange, searchString, setSearchString }; }; diff --git a/web/src/hooks/use-chat-request.ts b/web/src/hooks/use-chat-request.ts index b57378f2b3..ff057b4d71 100644 --- a/web/src/hooks/use-chat-request.ts +++ b/web/src/hooks/use-chat-request.ts @@ -273,7 +273,8 @@ export const useFetchChat = () => { export const useFetchSessionList = () => { const { id } = useParams(); - const { searchString, handleInputChange } = useHandleSearchStrChange(); + const { searchString, handleInputChange, setSearchString } = + useHandleSearchStrChange(); const { data, @@ -299,7 +300,14 @@ export const useFetchSessionList = () => { }, }); - return { data, loading, refetch, searchString, handleInputChange }; + return { + data, + loading, + refetch, + searchString, + handleInputChange, + setSearchString, + }; }; export function useFetchSessionManually() { diff --git a/web/src/pages/next-chats/chat/sessions.tsx b/web/src/pages/next-chats/chat/sessions.tsx index 9bbd6c1bbd..740247f2bc 100644 --- a/web/src/pages/next-chats/chat/sessions.tsx +++ b/web/src/pages/next-chats/chat/sessions.tsx @@ -83,10 +83,22 @@ export function Sessions({ handleConversationCardClick }: SessionProps) { }); }, []); + // Selected items that are still visible under the current search filter. + // Batch deletion and the selected count must act on this set — selectedIds + // alone would include items filtered out of view by the search. + const visibleSelectedIds = useMemo( + () => + conversationList.filter((x) => selectedIds.has(x.id)).map((x) => x.id), + [conversationList, selectedIds], + ); + // Toggle select all const toggleSelectAll = useCallback(() => { setSelectedIds((prev) => { - if (prev.size === conversationList.length) { + const allVisibleSelected = + conversationList.length > 0 && + conversationList.every((x) => prev.has(x.id)); + if (allVisibleSelected) { return new Set(); } return new Set(conversationList.map((x) => x.id)); @@ -95,20 +107,19 @@ export function Sessions({ handleConversationCardClick }: SessionProps) { // Batch delete const handleBatchDelete = useCallback(async () => { - if (selectedIds.size === 0) { + if (visibleSelectedIds.length === 0) { return; } - const selectedIdList = Array.from(selectedIds); const currentConversationDeleted = conversationId - ? selectedIdList.includes(conversationId) + ? visibleSelectedIds.includes(conversationId) : false; const temporaryIdSet = new Set( conversationList.filter((item) => item.is_new).map((item) => item.id), ); const persistedIds: string[] = []; - selectedIdList.forEach((id) => { + visibleSelectedIds.forEach((id) => { if (temporaryIdSet.has(id)) { removeTemporaryConversation(id); } else { @@ -131,7 +142,7 @@ export function Sessions({ handleConversationCardClick }: SessionProps) { } exitSelectionMode(); }, [ - selectedIds, + visibleSelectedIds, conversationId, conversationList, setConversationBoth, @@ -140,7 +151,7 @@ export function Sessions({ handleConversationCardClick }: SessionProps) { exitSelectionMode, ]); - const selectedCount = useMemo(() => selectedIds.size, [selectedIds]); + const selectedCount = visibleSelectedIds.length; const { id } = useParams(); const { showEmbedModal, hideEmbedModal, embedVisible, beta } = diff --git a/web/src/pages/next-chats/hooks/use-select-conversation-list.ts b/web/src/pages/next-chats/hooks/use-select-conversation-list.ts index 754869d6f2..e1fa8f2b1f 100644 --- a/web/src/pages/next-chats/hooks/use-select-conversation-list.ts +++ b/web/src/pages/next-chats/hooks/use-select-conversation-list.ts @@ -30,6 +30,7 @@ export const useSelectDerivedConversationList = () => { loading, handleInputChange, searchString, + setSearchString, } = useFetchSessionList(); const { id: dialogId } = useParams(); @@ -38,6 +39,9 @@ export const useSelectDerivedConversationList = () => { const addTemporaryConversation = useCallback(() => { const conversationId = generateConversationId(); + // Clear the search keyword, otherwise the newly created session will be + // filtered out by the search after it is persisted and refetched. + setSearchString(''); setList((pre) => { if (dialogId) { setConversationBoth(conversationId, 'true'); @@ -61,7 +65,14 @@ export const useSelectDerivedConversationList = () => { return pre; }); - }, [dialogId, setConversationBoth, t, prologue, conversationList]); + }, [ + dialogId, + setConversationBoth, + t, + prologue, + conversationList, + setSearchString, + ]); const removeTemporaryConversation = useCallback((conversationId: string) => { setList((prevList) => {