web/repo: a page loaded as a document draws the ticket count the session's last page drew, instead of … until the counts arrive
Signed-off-by: dawn <dawn@tangled.org>
8 unmodified lines910111213141516171819202122232425262761 unmodified lines89909192939495969798991001011021031041051061077 unmodified lines11511611711897119120121122123124125 unmodified linesExpand all8 unmodified lines ) { strip.scrollLeft = left + current.offsetWidth - strip.clientWidth; } };
// the html carries no count, so a page draws the one the session's last page drew, if any export const showKeptCount = (strip: HTMLElement) => { const n = strip.querySelector<HTMLElement>("[data-count]"); try { const kept = n && sessionStorage.getItem(`tab-count:${n.dataset.count}`); if (n && kept !== null) n.textContent = kept; } catch { // blocked storage keeps the skeleton } };</script>
<script lang="ts"> import { resolve } from "$app/paths";61 unmodified lines const ticketCount = (c: RepoCounts) => c.issues === undefined && c.pulls === undefined ? "" : formatCount((c.issues ?? 0) + (c.pulls ?? 0));
$effect(() => { const key = `tab-count:${base}`; void Promise.resolve(counts).then((c) => { try { sessionStorage.setItem(key, ticketCount(c)); } catch { // a full or blocked storage only costs the next page its count's first frames } }); });</script>
<nav class="bar" aria-label="repository sections"> <span class="y-rb tabs" {@attach showCurrent}>7 unmodified lines >{tab.label}{#if tab.count} <Pending> {#snippet skeleton()}<span class="n">…</span>{/snippet} {@const c = await counts} <!-- a prerender has no count yet, its skeleton keeps the room the count lands in --> <span class="n">{prerender() ? "…" : ticketCount(c)}</span> <span class="n" data-count={base}>{prerender() ? "…" : ticketCount(c)}</span > </Pending>{/if}</a > {/each} {#if extra}125 unmodified linesExpand all4 unmodified lines56789910111213148 unmodified linesExpand all162163164165166167166167168169170171458 unmodified linesExpand all4 unmodified lines import { afterNavigate, goto, onNavigate } from "$app/navigation"; import { resolve } from "$app/paths"; import { navigating, page } from "$app/state"; import RepoChrome from "#lib/components/repo/RepoChrome.svelte"; import { scrollToCurrent } from "#lib/components/repo/RepoTabs.svelte"; import { scrollToCurrent, showKeptCount } from "#lib/components/repo/RepoTabs.svelte"; import RepoSidebar from "#lib/components/repo/sidebar/RepoSidebar.svelte"; import AccountCorner from "#lib/components/shell/AccountCorner.svelte"; import PageBar from "#lib/components/repo/PageBar.svelte"; import PaneError from "#lib/components/svfe/PaneError.svelte";148 unmodified linesExpand all // html[data-suspended]). a page loaded as a document keeps it from the old page until the // new one's app is up (app.html) const loading = $derived(!!navigating.to); // runs as the html parses, once the row is whole, so a page loaded as a document paints with // its open tab in view instead of scrolling to it when the app starts const SCROLL_TABS = `<script>(${scrollToCurrent})(document.currentScript.parentElement.querySelector(".tabs"))</${"script"}>`; // its open tab in view and the session's ticket count, instead of the app changing both const SCROLL_TABS = `<script>(() => { const tabs = document.currentScript.parentElement.querySelector(".tabs"); (${showKeptCount})(tabs); (${scrollToCurrent})(tabs); })()</${"script"}>`; // a client navigation renders the new page in one long task: a frame first, so the strip shows onNavigate( () => new Promise<void>((resolve) => requestAnimationFrame(() => setTimeout(resolve))) );458 unmodified linesExpand all