Menu
Public repository / 0d7f5f902b20084326479f36d4ccf2b55ee890c0
AkurAI-Mail / src/lib/webmail/virtual.ts
Latest change 22202d1bde69be4ace8a299dffd91f8ff24378df - Recover deployed webmail frontend (frontend parity with EC2 a6afffc) by Ólafur Búi Ólafsson
/** Variable-height list windowing for the message list. */
/** Prefix sums: offsets[i] is the top of item i; offsets[n] is the total height. */
export function threadOffsets<T>(items: T[], height: (item: T) => number) {
const offsets = new Array<number>(items.length + 1);
offsets[0] = 0;
for (let i = 0; i < items.length; i++) offsets[i + 1] = offsets[i]! + height(items[i]!);
return offsets;
}
/** Index of the item containing pixel `y`. */
export function indexAt(offsets: number[], y: number) {
const count = offsets.length - 1;
let low = 0;
let high = count - 1;
while (low < high) {
const mid = (low + high) >> 1;
if (offsets[mid + 1]! > y) high = mid;
else low = mid + 1;
}
return count ? low : 0;
}
/** Items to render for a viewport, padded by `overscan` items on each side. */
export function visibleRange(offsets: number[], scrollTop: number, viewportHeight: number, overscan: number) {
const count = offsets.length - 1;
const start = Math.max(0, indexAt(offsets, scrollTop) - overscan);
const bottom = scrollTop + viewportHeight;
let end = start;
while (end < count && offsets[end]! < bottom) end++;
return { start, end: Math.min(count, end + overscan) };
}