accounts: infinite scroll for performance

Found out the bottleneck when ~2000 or more elements are loaded isn't
the search or sort or anything, but the DOM. An infinite scroll
implementation is added, where elements are added to the DOM as you
scroll. May still be a little buggy, and can't yet cope with screen
resizes. Also, the "shown" indicator is broken.
This commit is contained in:
Harvey Tindall
2025-05-22 21:08:25 +01:00
parent 3299398806
commit d09ee59a1a
7 changed files with 216 additions and 67 deletions

View File

@@ -269,8 +269,12 @@ export class DateQuery extends Query {
export interface SearchableItem {
matchesSearch: (query: string) => boolean;
// FIXME: SearchableItem should really be ListItem or something, this isn't for search!
asElement: () => HTMLElement;
}
export const SearchableItemDataAttribute = "data-search-item";
export type SearchableItems = { [id: string]: SearchableItem };
export class Search {
@@ -294,6 +298,9 @@ export class Search {
}
}
// Intended to be set from the JS console, if true searches are timed.
timeSearches: boolean = false;
private _serverSearchButtons: HTMLElement[];
static tokenizeSearch = (query: string): string[] => {
@@ -398,6 +405,7 @@ export class Search {
// Returns a list of identifiers (used as keys in items, values in ordering).
search = (query: string): string[] => {
let timer = this.timeSearches ? performance.now() : null;
this._c.filterArea.textContent = "";
let result: string[] = [...this._ordering];
@@ -460,6 +468,10 @@ export class Search {
this._queries = queries;
this._searchTerms = searchTerms;
if (this.timeSearches) {
const totalTime = performance.now() - timer;
console.log(`Search took ${totalTime}ms`);
}
return result;
}
@@ -528,10 +540,8 @@ export class Search {
this._c.notFoundLocallyText.classList.remove("unfocused");
}
if (visible) {
console.log("showing not found panel");
this._c.notFoundPanel.classList.remove("unfocused");
} else {
console.log("hiding not found panel");
this._c.notFoundPanel.classList.add("unfocused");
}
}
@@ -644,10 +654,6 @@ export class Search {
}
constructor(c: SearchConfiguration) {
// FIXME: Remove!
if (c.search.id.includes("activity")) {
(window as any).s = this;
}
this._c = c;
this._c.search.oninput = () => {