fix: search lists show results of an earlier search when it answers late

Typing a search, pausing, and typing more on a slow connection could leave the list showing results for the earlier text. This hit Notes, Archived Chats, Shared Chats, the admin Users list and the # and @ lists in the message box, where Enter could then attach the wrong knowledge base. Each list now ignores answers that do not belong to the latest search.

Fixes #33756
This commit is contained in:
Classic298 2026-11-04 22:31:06 +01:00
parent f7b3029a69
commit b848ea720f
6 changed files with 38 additions and 3 deletions

View file

@ -44,6 +44,7 @@
let query = '';
let searchDebounceTimer: ReturnType<typeof setTimeout>;
let requestId = 0;
let orderBy = 'created_at'; // default sort key
let direction = 'asc'; // default sort order
@ -95,6 +96,7 @@
};
const getUserList = async () => {
const activeRequestId = ++requestId;
try {
const res = await getUsers(localStorage.token, query, orderBy, direction, page).catch(
(error) => {
@ -103,6 +105,8 @@
}
);
if (activeRequestId !== requestId) return;
if (res) {
users = res.users;
total = res.total;

View file

@ -39,6 +39,7 @@
let selectedIdx = 0;
export let filteredItems: any[] = [];
let searchDebounceTimer: ReturnType<typeof setTimeout>;
let requestId = 0;
let filesystemItems: any[] = [];
let knowledgeItems: any[] = [];
@ -101,6 +102,7 @@
});
const getItems = () => {
requestId += 1;
const terminal = getSelectedTerminal();
getFilesystemItems(terminal);
getKnowledgeItems();
@ -170,8 +172,11 @@
.filter((folder: any) => folder.name.toLowerCase().includes(query.toLowerCase()));
const getKnowledgeItems = async () => {
const activeRequestId = requestId;
const res = await searchKnowledgeBases(localStorage.token, query).catch(() => null);
if (activeRequestId !== requestId) return;
if (res) {
knowledgeItems = res.items.map((item: any) => ({
...item,
@ -181,8 +186,11 @@
};
const getKnowledgeFileItems = async () => {
const activeRequestId = requestId;
const res = await searchKnowledgeFiles(localStorage.token, query).catch(() => null);
if (activeRequestId !== requestId) return;
if (res) {
fileItems = res.items.map((item: any) => ({
...item,

View file

@ -27,6 +27,7 @@
let selectedIdx = 0;
let items = [];
let searchDebounceTimer: ReturnType<typeof setTimeout>;
let requestId = 0;
export let filteredItems = [];
let webUploadEnabled: boolean = true;
@ -86,6 +87,7 @@
});
const getItems = () => {
requestId += 1;
getKnowledgeItems();
getKnowledgeFileItems();
};
@ -100,10 +102,13 @@
.filter((folder) => folder.name.toLowerCase().includes(query.toLowerCase()));
const getKnowledgeItems = async () => {
const activeRequestId = requestId;
const res = await searchKnowledgeBases(localStorage.token, query).catch(() => {
return null;
});
if (activeRequestId !== requestId) return;
if (res) {
knowledgeItems = res.items.map((item) => {
return {
@ -115,10 +120,13 @@
};
const getKnowledgeFileItems = async () => {
const activeRequestId = requestId;
const res = await searchKnowledgeFiles(localStorage.token, query).catch(() => {
return null;
});
if (activeRequestId !== requestId) return;
if (res) {
fileItems = res.items.map((item) => {
return {

View file

@ -55,6 +55,7 @@
let allChatsLoaded = false;
let chatListLoading = false;
let searchDebounceTimeout: ReturnType<typeof setTimeout> | null = null;
let requestId = 0;
let selectedChatId: string | null = null;
let showDeleteConfirmDialog = false;
@ -67,9 +68,12 @@
});
const loadChats = async () => {
const activeRequestId = ++requestId;
page = 1;
chatList = null;
chatList = await getArchivedChatList(localStorage.token, page, getFilter());
const res = await getArchivedChatList(localStorage.token, page, getFilter());
if (activeRequestId !== requestId) return;
chatList = res;
allChatsLoaded = (chatList ?? []).length === 0;
chatCount = await getArchivedChatCount(localStorage.token);
};

View file

@ -24,6 +24,7 @@
let allChatsLoaded = false;
let chatListLoading = false;
let searchDebounceTimeout: any;
let requestId = 0;
let showUnshareAllConfirmDialog = false;
@ -47,15 +48,20 @@
clearTimeout(searchDebounceTimeout);
}
const activeRequestId = ++requestId;
page = 1;
chatList = null;
if (query === '') {
chatList = await getSharedChatList(localStorage.token, page, filter);
const res = await getSharedChatList(localStorage.token, page, filter);
if (activeRequestId !== requestId) return;
chatList = res;
allChatsLoaded = (chatList ?? []).length === 0;
} else {
searchDebounceTimeout = setTimeout(async () => {
chatList = await getSharedChatList(localStorage.token, page, filter);
const res = await getSharedChatList(localStorage.token, page, filter);
if (activeRequestId !== requestId) return;
chatList = res;
allChatsLoaded = (chatList ?? []).length === 0;
}, 500);
}

View file

@ -74,6 +74,7 @@
let query = '';
let searchDebounceTimer: ReturnType<typeof setTimeout>;
let requestId = 0;
let sortKey = 'updated_at';
let sortDirection = 'desc';
@ -158,6 +159,7 @@
};
const reset = () => {
requestId += 1;
page = 1;
items = null;
total = null;
@ -202,6 +204,7 @@
: `/notes/${note.id}`;
const getItemsPage = async () => {
const activeRequestId = requestId;
itemsLoading = true;
if (viewOption === 'created') {
@ -220,6 +223,8 @@
return [];
});
if (activeRequestId !== requestId) return res;
if (res) {
total = res.total;
const pageItems = res.items;