📄 src/titles.ts
import { fetchContextToken, fetchDownloadableTitleIds } from './api';

/**
 * Cache of title ids that are downloadable as PDF (the main paper — inserts
 * and bilagor are not). Warmed on page load and on demand; used to leave
 * non-downloadable issues completely untouched (native behaviour).
 */

let downloadableTitleIds: Set<string> | null = null;
let warming: Promise<void> | null = null;

/**
 * Is this title downloadable as PDF?
 * Returns null when unknown (cache cold) — callers should then intercept
 * optimistically and rely on the graceful fallback.
 */
export function isDownloadableTitle(titleId: string): boolean | null {
  if (downloadableTitleIds === null) return null;
  return downloadableTitleIds.has(titleId);
}

/** Warm the cache (best effort, silent). Safe to call repeatedly. */
export function warmTitlesCache(clientToken: string, sessionToken: string | null): Promise<void> {
  warming ??= doWarm(clientToken, sessionToken);
  return warming;
}

async function doWarm(clientToken: string, sessionToken: string | null): Promise<void> {
  try {
    if (!sessionToken) return; // not logged in — nothing to warm yet
    const contextToken = await fetchContextToken(clientToken, sessionToken);
    downloadableTitleIds = await fetchDownloadableTitleIds(contextToken);
  } catch {
    downloadableTitleIds = null; // stay cold; next click intercepts optimistically
  } finally {
    warming = null;
  }
}