diff options
| author | Joe Mou <dev@mou.fo> | 2026-07-21 17:46:58 -0400 |
|---|---|---|
| committer | Joe Mou <dev@mou.fo> | 2026-07-22 23:25:26 -0400 |
| commit | 6240cf1c6b73b7ed34ff5816b53333382c229f5c (patch) | |
| tree | 4e8a8e379aa466c8a0d1d298266700a589b1a445 /cgithub/public/static/refs.js | |
| parent | 9b556ffe6c0c0528697e15f7f4f35107de212ce1 (diff) | |
Add async branch/tag dropdown and latest-commit bar
Adds two lazily-fetched UI pieces to match vanilla GitHub while keeping
initial page loads plain server-rendered HTML: a branch/tag selector
(native <dialog>, CSS anchor-positioned to its button, light-dismissed
via closedby="any") and a latest-commit bar above the file listing.
Both are populated by new /api/:owner/:repo/refs/:type and
/api/:owner/:repo/latest-commit/:branch/:path routes; the latter calls
GitHub's own /latest-commit JSON endpoint (the same one the React UI
uses) rather than scraping the full commit history page.
Diffstat (limited to 'cgithub/public/static/refs.js')
| -rw-r--r-- | cgithub/public/static/refs.js | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/cgithub/public/static/refs.js b/cgithub/public/static/refs.js new file mode 100644 index 0000000..28b8373 --- /dev/null +++ b/cgithub/public/static/refs.js @@ -0,0 +1,60 @@ +// Progressive enhancement for two bits of data GitHub itself loads lazily: +// the branch/tag dropdown and the latest-commit bar above a file listing. +// Both degrade gracefully without JS: the button's command/commandfor still +// opens the (empty) dialog natively; the commit placeholder just never fills +// in. +document.addEventListener("DOMContentLoaded", () => { + const dialog = document.querySelector(".ref-selector-menu"); + if (dialog) { + const list = dialog.querySelector(".ref-selector-list"); + const { owner, repo } = dialog.dataset; + const cache = {}; + + async function load(type) { + if (Object.prototype.hasOwnProperty.call(cache, type)) { + list.innerHTML = cache[type]; + return; + } + list.textContent = "Loading…"; + try { + const res = await fetch(`/api/${owner}/${repo}/refs/${type}`); + const html = res.ok ? await res.text() : ""; + cache[type] = html || "Failed to load."; + list.innerHTML = cache[type]; + } catch { + list.textContent = "Failed to load."; + } + } + + let opened = false; + dialog.addEventListener("toggle", () => { + if (dialog.open && !opened) { + opened = true; + load("branches"); + } + }); + + for (const tab of dialog.querySelectorAll("[data-ref-type]")) { + tab.addEventListener("click", () => { + for (const other of dialog.querySelectorAll("[data-ref-type]")) { + other.classList.toggle("active", other === tab); + } + load(tab.dataset.refType); + }); + } + } + + const commitPlaceholder = document.querySelector(".latest-commit-placeholder"); + if (commitPlaceholder) { + fetch(commitPlaceholder.dataset.src) + .then((res) => (res.ok ? res.text() : "")) + .then((html) => { + if (html.trim()) { + commitPlaceholder.outerHTML = html; + } else { + commitPlaceholder.remove(); + } + }) + .catch(() => commitPlaceholder.remove()); + } +}); |
