From 4bb7c08bf017de509aa7e8da2a7cd61c25a5e980 Mon Sep 17 00:00:00 2001 From: Kaj Schittecat Date: Wed, 24 Jun 2026 12:32:11 +0200 Subject: [PATCH] =?UTF-8?q?site:=20standalone=20=E2=80=94=20'install=20a?= =?UTF-8?q?=20previous=20version'=20picker=20(latest=204=20betas=20+=20not?= =?UTF-8?q?es)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collapsible version picker in the standalone install guide: a dropdown of the latest 4 betas (from the GitHub releases API — the firmware-host listing has no CORS), rendered release notes per version, and selecting a version re-points both Install buttons at that build (client-built manifest -> the CORS-enabled firmware-host -merged.bin). Defaults to latest; switching back restores the /latest/ manifest. Co-Authored-By: Claude Opus 4.8 --- deploy/site/index.html | 70 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/deploy/site/index.html b/deploy/site/index.html index e65409d..2716dc1 100644 --- a/deploy/site/index.html +++ b/deploy/site/index.html @@ -147,6 +147,22 @@ .dl:hover{background:var(--teal-ink)} .dl svg{width:15px;height:15px} .hint{max-width:760px;margin:18px auto 0;color:var(--mut);font-size:.86rem;text-align:center} + /* "install a previous version" picker */ + .verpick{max-width:760px; margin:16px auto 0; border:1px solid var(--line); border-radius:12px; background:var(--bg2); text-align:left} + .verpick summary{cursor:pointer; padding:12px 16px; font-weight:600; font-size:.92rem; color:var(--ink); list-style:none; user-select:none} + .verpick summary::-webkit-details-marker{display:none} + .verpick summary::before{content:"\25B8"; color:var(--teal); margin-right:9px; display:inline-block; transition:transform .15s} + .verpick[open] summary::before{transform:rotate(90deg)} + .verpick-body{padding:2px 16px 16px} + .verpick-row{display:flex; align-items:center; gap:10px} + .verpick-row label{font-size:.9rem; color:var(--mut)} + #verSel{font:inherit; font-size:.92rem; padding:7px 11px; border:1px solid var(--line); border-radius:8px; background:#fff; color:var(--ink); cursor:pointer} + .verpick-note{margin:9px 0 0; font-size:.86rem; color:var(--teal-ink)} + .rn{margin-top:12px; max-height:280px; overflow:auto; font-size:.88rem; color:var(--mut); line-height:1.55} + .rn .rn-h{font-size:.92rem; color:var(--ink); font-weight:700; margin:13px 0 5px} .rn .rn-h:first-child{margin-top:0} + .rn ul{margin:5px 0 0; padding-left:18px} .rn li{margin:3px 0} + .rn p{margin:6px 0} .rn code{background:#fff; border:1px solid var(--line); border-radius:5px; padding:1px 5px; font-size:.86em} + .rn a{color:var(--teal-ink)} .noserial{display:none;color:#b4631a;text-align:center;margin-top:14px} body.no-serial .noserial{display:block} @@ -312,10 +328,18 @@

Heltec V4 + TFT

ESP32-S3 with CHSC6x touch.

-
+

LilyGo T-Deck / Plus

ESP32-S3 keyboard handheld.

-
+ +
+ Install a previous version +
+
+ +
+
+
Your browser can't flash here — use Chrome or Edge on a desktop.

T-Deck not detected? Hold the trackball while tapping reset to force download mode.

@@ -497,6 +521,48 @@ We use no tracking, analytics, or advertising cookies. Our CDN and security prov const docsBtn = document.getElementById('docsBtn'); if (docsBtn) docsBtn.addEventListener('click', () => toast('Documentation — coming soon!')); + // ---- standalone: install a previous version (latest 4 betas + release notes) ---- + (function(){ + const sel = document.getElementById('verSel'); if (!sel) return; + const wrap = sel.closest('.verpick'); + const notesEl = document.getElementById('verNotes'), activeEl = document.getElementById('verActive'); + const btnH = document.getElementById('inst-heltec'), btnT = document.getElementById('inst-tdeck'); + const latestH = btnH && btnH.getAttribute('manifest'), latestT = btnT && btnT.getAttribute('manifest'); + const num = t => parseInt((String(t).match(/beta_(\d+)/) || [])[1] || '-1', 10); + let notes = {}; + const esc = s => s.replace(/&/g,'&').replace(//g,'>'); + const inl = s => esc(s).replace(/\*\*(.+?)\*\*/g,'$1').replace(/`([^`]+?)`/g,'$1') + .replace(/\[(.+?)\]\((https?:\/\/[^)\s]+)\)/g,'$1'); + function md(t){ let out='', ul=false; const close=()=>{ if(ul){ out+=''; ul=false; } }; + (t||'').split(/\r?\n/).forEach(line=>{ line=line.trim(); let m; + if(!line) close(); + else if(m=line.match(/^#{1,6}\s+(.*)/)){ close(); out+='
'+inl(m[1])+'
'; } + else if(m=line.match(/^[-*]\s+(.*)/)){ if(!ul){ out+='