import type { Hono } from "hono";
import { knownObjects, languageLines } from "../mirror/queries.ts";
import { setting } from "../server/db.ts";
import { type Html, html } from "./html.ts";
import { cacheFor, type PageContext, page, plural } from "./layout.ts";
import { type LibraryRepo, publicLibrary, recentSaves, repoCards } from "./library.ts";
const TICKER_ROWS = 7;
const TICKER_ITEMS = 10;
const LATEST_OFFERED = 4;
/** §21.1's front page and §21.3's browse. */
export function registerFrontPages(app: Hono, ctx: PageContext): void {
app.get("/", (c) => {
const library = publicLibrary(ctx);
const tagline = setting(ctx.kepr, "tagline") ?? "";
// §21.1: distinct objects across every public repo's real saves.
const known = new Set(library.flatMap((repo) => knownObjects(repo.mirror))).size;
const latest = library
.filter((repo) => repo.stats.updated !== null)
.sort((a, b) => (b.stats.updated ?? 0) - (a.stats.updated ?? 0))
.slice(0, LATEST_OFFERED);
cacheFor(c, false);
return c.html(
page(ctx, {
title: "",
description: tagline,
path: "/",
body: html`${ticker(library)}
${tagline}The library knows
${tagline && html`
${plural(known, "thing")}.latest offered
${repoCards(latest)}
${plural(library.length, "repo")}
${ library.length > 0 ? repoCards(library) : html`nothing public yet
` }`, }), ); }); } // Rows of recent save messages drifting at different depths; the motion is CSS, and stops under // reduced motion. Each row's messages are written twice so sliding by half its width loops. function ticker(library: LibraryRepo[]): Html { const messages = recentSaves(library, TICKER_ROWS * TICKER_ITEMS).map( ({ save }) => save.message.split("\n")[0] as string, ); if (messages.length === 0) return html``; const rows = Array.from({ length: TICKER_ROWS }, (_, row) => { const items = Array.from( { length: TICKER_ITEMS }, (_, i) => messages[(row * 3 + i) % messages.length], ); const spans = items.map((message) => html`${message}`); return html`