AkurAI Build
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) };
}