Compare commits

..

6 Commits

Author SHA1 Message Date
Will Tatam
f08b8b648f Change 'Latest release' to 'Latest version' in update.htm 2026-05-06 08:57:43 +01:00
Will Tatam
81b588f1e4 Improve update page UX and rename OTA button for consistency
- Release name on update page links directly to the matching bin on download.wled.me
- Badge links to GitHub releases page as 'View latest'
- Auto-update button renamed to 'Auto update'
- Manual upload section gets its own subheading; submit button renamed to 'Upload'
- 'Manual OTA Update' button in security settings renamed to 'Update WLED' to match info menu wording
2026-05-06 08:57:43 +01:00
Will Tatam
09384e4bdb Automatically download the right bin for the latest release and install 2026-05-06 08:57:43 +01:00
Will Tatam
6922938e15 Remove usermods from release 2026-05-06 08:57:43 +01:00
Frank Möhle
362fc664aa Add guideline for providing verifiable citations
Anti-hallucination rule: Emphasize the importance of providing verifiable citations in analyses or recommendations.
2026-05-05 14:53:16 +02:00
Will Tatam
527edf3283 16.0.1-dev 2026-05-03 21:31:45 +01:00
5 changed files with 73 additions and 11 deletions

View File

@@ -4,7 +4,7 @@
; Copied to platformio_release.ini by the release CI workflow
; (.github/workflows/release.yml -> build.yml with `release: true`)
; in order to extend the matrix of `default_envs` built and published
; for tagged releases.
; for tagged releases and remove the debugging usersmods env
;
; This file overrides `[platformio].default_envs` from platformio.ini via
; `extra_configs`. It MUST list every env that should be released - including
@@ -35,7 +35,6 @@ default_envs = nodemcuv2
esp32s3dev_8MB_opi
esp32s3dev_8MB_qspi
esp32s3_4M_qspi
usermods
; HUB75 release-only envs
esp32dev_hub75
esp32dev_hub75_forum_pinout

View File

@@ -182,3 +182,4 @@ No automated linting is configured. Match existing code style in files you edit.
- Changes to `platformio.ini` require maintainer approval
- Remove dead/unused code — justify or delete it
- Verify feature-flag spelling exactly (misspellings are silently ignored by preprocessor)
- Provide references when making analyses or recommendations. Support factual claims with verifiable citations, references or concrete evidence; **never fabricate citations**.

View File

@@ -1,6 +1,6 @@
{
"name": "wled",
"version": "16.0.0",
"version": "16.0.1-dev",
"description": "Tools for WLED project",
"main": "tools/cdata.js",
"directories": {

View File

@@ -62,7 +62,7 @@
</div>
<div class="sec" id="OTA">
<h3>Software Update</h3>
<button type="button" onclick="U()">Manual OTA Update</button><br>
<button type="button" onclick="U()">Update WLED</button><br>
<div id="aOTA">Enable ArduinoOTA: <input type="checkbox" name="AO"></div>
Only allow update from same network/WiFi: <input type="checkbox" name="SU"><br>
<i class="warn">&#9888; If you are using multiple VLANs (i.e. IoT or guest network) either set PIN or disable this option.<br>

View File

@@ -7,6 +7,7 @@
<script>
function B() { window.history.back(); }
var cnfr = false;
var deviceInfo = null;
function cR() {
if (!cnfr) {
var bt = gId('rev');
@@ -22,15 +23,30 @@
fetch(getURL('/json/info'))
.then(response => response.json())
.then(data => {
deviceInfo = data;
document.querySelector('.installed-version').textContent = `${data.brand} ${data.ver} (${data.vid})`;
const repoUrl = data.repo && data.repo !== "unknown" ? "https://github.com/" + data.repo + "/releases/latest" : null;
document.querySelector('.release-name').textContent = data.release;
// assemble update URL and update release badge
if (data.repo && data.repo !== "unknown") {
const repoUrl = "https://github.com/" + data.repo + "/releases/latest";
if (repoUrl) {
const badgeUrl = "https://img.shields.io/github/release/" + data.repo + ".svg?style=flat-square";
document.querySelector('.release-repo').href = repoUrl;
document.querySelector('.release-badge').src = badgeUrl;
toggle('release-download'); // only show release download item after receiving a valid data.repo
// fetch latest release from GitHub to build direct bin download link
fetch(`https://api.github.com/repos/${data.repo}/releases/latest`)
.then(r => r.json())
.then(gh => {
const ver = gh.tag_name.replace(/^v/, '');
const suffix = `_${ver}_${data.release}.bin`;
const asset = gh.assets.find(a => a.name.endsWith(suffix));
if (asset) {
const binUrl = asset.browser_download_url.replace(/^https?:\/\/[^/]+/, 'https://download.wled.me');
const el = document.querySelector('.release-name');
el.innerHTML = `<a href="${binUrl}">${data.release}</a>`;
}
})
.catch(() => {}); // silently ignore if GitHub API unavailable
} else {
gId('Norelease-download').classList.add("hide"); // repo invalid -> hide everything
}
@@ -60,6 +76,48 @@
gId('bootupd').classList.add("hide");
toggle('upd');
}
async function autoUpdate() {
const btn = gId('autoUpdBtn');
const status = gId('autoUpdStatus');
btn.disabled = true;
status.textContent = '';
try {
const info = deviceInfo;
if (!info || !info.repo || info.repo === 'unknown') {
status.textContent = 'No release repository available for this build.';
btn.disabled = false;
return;
}
status.textContent = 'Checking GitHub for latest release...';
const ghResp = await fetch(`https://api.github.com/repos/${info.repo}/releases/latest`);
if (!ghResp.ok) throw new Error(`GitHub API error: ${ghResp.status}`);
const ghRelease = await ghResp.json();
const releaseVer = ghRelease.tag_name.replace(/^v/, '');
const assetSuffix = `_${releaseVer}_${info.release}.bin`;
const asset = ghRelease.assets.find(a => a.name.endsWith(assetSuffix));
if (!asset) {
const available = ghRelease.assets.map(a => a.name).join(', ');
status.textContent = `Firmware not found (*${assetSuffix}). Available: ${available}`;
btn.disabled = false;
return;
}
status.textContent = `Downloading ${asset.name} (${Math.round(asset.size/1024)} KB)...`;
const fwUrl = asset.browser_download_url.replace(/^https?:\/\/[^/]+/, 'https://download.wled.me');
const fwResp = await fetch(fwUrl);
if (!fwResp.ok) throw new Error(`Download failed: ${fwResp.status}`);
const blob = await fwResp.blob();
const file = new File([blob], asset.name, {type: 'application/octet-stream'});
const dt = new DataTransfer();
dt.items.add(file);
document.querySelector('input[name="update"]').files = dt.files;
status.textContent = `Downloaded ${asset.name}. Uploading to device...`;
hideforms();
gId('upd').submit();
} catch(e) {
status.textContent = 'Auto-update failed: ' + e.message;
btn.disabled = false;
}
}
</script>
<style>
@import url("style.css");
@@ -77,18 +135,22 @@
<p>
Installed version: <span class="sip installed-version">Loading...</span><br>
Release: <span class="sip release-name">Loading...</span><br>
<span id="Norelease-download">Latest binary: Checking...<br></span>
<span id="Norelease-download">Latest release: Checking...<br></span>
<span id="release-download" class="hide">
Download the latest binary: <a class="release-repo" href="https://github.com/wled/WLED/releases/latest" target="_blank" rel="noopener noreferrer"
Latest version: <a class="release-repo" href="https://github.com/wled/WLED/releases/latest" target="_blank" rel="noopener noreferrer"
style="vertical-align: text-bottom; display: inline-flex;">
<img class="release-badge" alt="badge"></a><br> <!-- start with an empty placeholder, src will be filled after fetching /json/info -->
<img class="release-badge" alt="View latest"></a><br>
<button type="button" id="autoUpdBtn" onclick="autoUpdate()">Auto update</button>
<span id="autoUpdStatus" style="display:block;margin-top:4px;font-size:13px;"></span>
</span>
</p>
<hr class="sml">
<h3>Manual upload</h3>
<input type="hidden" name="skipValidation" value="" id="sV">
<input type='file' name='update' required><br> <!--should have accept='.bin', but it prevents file upload from android app-->
<input type='checkbox' onchange="sV.value=checked?1:''" id="skipValidation">
<label for='skipValidation'>Ignore firmware validation</label><br>
<button type="submit">Update WLED!</button><br>
<button type="submit">Upload</button><br>
<span id="rev">
<hr class="sml">
<button type="button" onclick="cR()">Revert update</button><br>
@@ -107,4 +169,4 @@
<div id="Noupd" class="hide sec"><b>Updating...</b><br>Please do not close or refresh the page :)</div>
<p><button id="backbtn" type="button" onclick="B()">Back</button></p>
</body>
</html>
</html>