diff --git a/aarch64/app/html/index.html b/aarch64/app/html/index.html index cf9edf6..3674167 100644 --- a/aarch64/app/html/index.html +++ b/aarch64/app/html/index.html @@ -359,6 +359,9 @@
-
+
+ +
@@ -437,16 +440,35 @@ tsIP = allIPs.length ? allIPs[allIPs.length - 1] : null; } - var nodeMatch = txt.match(/popBrowserAuthNow\("([^"]+)"\)/); - if (!nodeMatch) nodeMatch = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/); - var node = nodeMatch ? nodeMatch[1] : null; + var nodeMatches = txt.match(/popBrowserAuthNow\("([^"]+)"\)/g); + if (!nodeMatches) nodeMatches = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/g); + var node = null; + if (nodeMatches) { + var nm = nodeMatches[nodeMatches.length - 1].match(/"([^"]+)"/); + if (nm) node = nm[1]; + } + if (!node) { + var hostMatches = txt.match(/^\S+\s+(\S+)\s+\[\s*INFO/gm); + if (hostMatches) { + var hm = hostMatches[hostMatches.length - 1].match(/^\S+\s+(\S+)/); + if (hm) node = hm[1]; + } + } - var loginMatch = txt.match(/active login:\s+(\S+)/); - var tailnet = loginMatch ? loginMatch[1] : null; + var loginMatches = txt.match(/active login:\s+\S+/g); + var tailnet = null; + if (loginMatches) { + var lm = loginMatches[loginMatches.length - 1].match(/active login:\s+(\S+)/); + if (lm) tailnet = lm[1]; + } - var versionMatch = txt.match(/Program starting: v(\d+\.\d+\.\d+)/); - if (!versionMatch) versionMatch = txt.match(/tailscaled[\s_](\d+\.\d+\.\d+)/); - var version = versionMatch ? versionMatch[1] : null; + var versionMatches = txt.match(/Program starting: v(\d+\.\d+\.\d+)/g); + var version = null; + if (versionMatches) { + var last = versionMatches[versionMatches.length - 1]; + var vm = last.match(/v(\d+\.\d+\.\d+)/); + if (vm) version = vm[1]; + } var stateLines = txt.match(/Switching ipn state [^\n]+/g) || []; var lastState = stateLines.length ? stateLines[stateLines.length - 1] : ''; @@ -542,10 +564,15 @@ setInterval(refresh, 5000); // Check for updates from GitHub - var latestChecked = false; - function checkForUpdate(currentVersion) { - if (!currentVersion || latestChecked) return; - latestChecked = true; + var installedVersion = null; + var autoChecked = false; + function checkForUpdate(currentVersion, manual) { + if (!currentVersion) return; + installedVersion = currentVersion; + if (!manual && autoChecked) return; + if (!manual) autoChecked = true; + var btn = document.getElementById('check-update-btn'); + if (manual && btn) btn.textContent = 'Checking...'; fetch('https://api.github.com/repos/Mo3he/Axis_Cam_Tailscale/releases/latest') .then(function(r) { return r.json(); }) .then(function(data) { @@ -555,11 +582,22 @@ document.getElementById('update-version').textContent = 'v' + tag; document.getElementById('update-banner').classList.add('visible'); document.getElementById('ts-version').textContent = currentVersion + ' (outdated)'; + if (btn) btn.textContent = 'Update Available'; + } else { + if (manual && btn) btn.textContent = 'Up to date'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); } }) - .catch(function() {}); + .catch(function() { + if (manual && btn) btn.textContent = 'Check failed'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); + }); } + document.getElementById('check-update-btn').addEventListener('click', function() { + if (installedVersion) checkForUpdate(installedVersion, true); + }); + function compareVersions(a, b) { var pa = a.split('.').map(Number); var pb = b.split('.').map(Number); diff --git a/aarch64/app/lib/tailscale b/aarch64/app/lib/tailscale index 65b96b6..f16af6f 100755 Binary files a/aarch64/app/lib/tailscale and b/aarch64/app/lib/tailscale differ diff --git a/aarch64/app/lib/tailscaled b/aarch64/app/lib/tailscaled index 7a9ba48..ba9c26d 100755 Binary files a/aarch64/app/lib/tailscaled and b/aarch64/app/lib/tailscaled differ diff --git a/aarch64_ROOT/app/html/index.html b/aarch64_ROOT/app/html/index.html index cf9edf6..3674167 100644 --- a/aarch64_ROOT/app/html/index.html +++ b/aarch64_ROOT/app/html/index.html @@ -359,6 +359,9 @@
-
+
+ +
@@ -437,16 +440,35 @@ tsIP = allIPs.length ? allIPs[allIPs.length - 1] : null; } - var nodeMatch = txt.match(/popBrowserAuthNow\("([^"]+)"\)/); - if (!nodeMatch) nodeMatch = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/); - var node = nodeMatch ? nodeMatch[1] : null; + var nodeMatches = txt.match(/popBrowserAuthNow\("([^"]+)"\)/g); + if (!nodeMatches) nodeMatches = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/g); + var node = null; + if (nodeMatches) { + var nm = nodeMatches[nodeMatches.length - 1].match(/"([^"]+)"/); + if (nm) node = nm[1]; + } + if (!node) { + var hostMatches = txt.match(/^\S+\s+(\S+)\s+\[\s*INFO/gm); + if (hostMatches) { + var hm = hostMatches[hostMatches.length - 1].match(/^\S+\s+(\S+)/); + if (hm) node = hm[1]; + } + } - var loginMatch = txt.match(/active login:\s+(\S+)/); - var tailnet = loginMatch ? loginMatch[1] : null; + var loginMatches = txt.match(/active login:\s+\S+/g); + var tailnet = null; + if (loginMatches) { + var lm = loginMatches[loginMatches.length - 1].match(/active login:\s+(\S+)/); + if (lm) tailnet = lm[1]; + } - var versionMatch = txt.match(/Program starting: v(\d+\.\d+\.\d+)/); - if (!versionMatch) versionMatch = txt.match(/tailscaled[\s_](\d+\.\d+\.\d+)/); - var version = versionMatch ? versionMatch[1] : null; + var versionMatches = txt.match(/Program starting: v(\d+\.\d+\.\d+)/g); + var version = null; + if (versionMatches) { + var last = versionMatches[versionMatches.length - 1]; + var vm = last.match(/v(\d+\.\d+\.\d+)/); + if (vm) version = vm[1]; + } var stateLines = txt.match(/Switching ipn state [^\n]+/g) || []; var lastState = stateLines.length ? stateLines[stateLines.length - 1] : ''; @@ -542,10 +564,15 @@ setInterval(refresh, 5000); // Check for updates from GitHub - var latestChecked = false; - function checkForUpdate(currentVersion) { - if (!currentVersion || latestChecked) return; - latestChecked = true; + var installedVersion = null; + var autoChecked = false; + function checkForUpdate(currentVersion, manual) { + if (!currentVersion) return; + installedVersion = currentVersion; + if (!manual && autoChecked) return; + if (!manual) autoChecked = true; + var btn = document.getElementById('check-update-btn'); + if (manual && btn) btn.textContent = 'Checking...'; fetch('https://api.github.com/repos/Mo3he/Axis_Cam_Tailscale/releases/latest') .then(function(r) { return r.json(); }) .then(function(data) { @@ -555,11 +582,22 @@ document.getElementById('update-version').textContent = 'v' + tag; document.getElementById('update-banner').classList.add('visible'); document.getElementById('ts-version').textContent = currentVersion + ' (outdated)'; + if (btn) btn.textContent = 'Update Available'; + } else { + if (manual && btn) btn.textContent = 'Up to date'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); } }) - .catch(function() {}); + .catch(function() { + if (manual && btn) btn.textContent = 'Check failed'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); + }); } + document.getElementById('check-update-btn').addEventListener('click', function() { + if (installedVersion) checkForUpdate(installedVersion, true); + }); + function compareVersions(a, b) { var pa = a.split('.').map(Number); var pb = b.split('.').map(Number); diff --git a/aarch64_ROOT/app/lib/tailscale b/aarch64_ROOT/app/lib/tailscale index 65b96b6..f16af6f 100755 Binary files a/aarch64_ROOT/app/lib/tailscale and b/aarch64_ROOT/app/lib/tailscale differ diff --git a/aarch64_ROOT/app/lib/tailscaled b/aarch64_ROOT/app/lib/tailscaled index 7a9ba48..ba9c26d 100755 Binary files a/aarch64_ROOT/app/lib/tailscaled and b/aarch64_ROOT/app/lib/tailscaled differ diff --git a/aarch64_custom/app/html/index.html b/aarch64_custom/app/html/index.html index 6706651..cdb10e8 100644 --- a/aarch64_custom/app/html/index.html +++ b/aarch64_custom/app/html/index.html @@ -359,6 +359,9 @@
-
+
+ +
@@ -437,16 +440,35 @@ tsIP = allIPs.length ? allIPs[allIPs.length - 1] : null; } - var nodeMatch = txt.match(/popBrowserAuthNow\("([^"]+)"\)/); - if (!nodeMatch) nodeMatch = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/); - var node = nodeMatch ? nodeMatch[1] : null; + var nodeMatches = txt.match(/popBrowserAuthNow\("([^"]+)"\)/g); + if (!nodeMatches) nodeMatches = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/g); + var node = null; + if (nodeMatches) { + var nm = nodeMatches[nodeMatches.length - 1].match(/"([^"]+)"/); + if (nm) node = nm[1]; + } + if (!node) { + var hostMatches = txt.match(/^\S+\s+(\S+)\s+\[\s*INFO/gm); + if (hostMatches) { + var hm = hostMatches[hostMatches.length - 1].match(/^\S+\s+(\S+)/); + if (hm) node = hm[1]; + } + } - var loginMatch = txt.match(/active login:\s+(\S+)/); - var tailnet = loginMatch ? loginMatch[1] : null; + var loginMatches = txt.match(/active login:\s+\S+/g); + var tailnet = null; + if (loginMatches) { + var lm = loginMatches[loginMatches.length - 1].match(/active login:\s+(\S+)/); + if (lm) tailnet = lm[1]; + } - var versionMatch = txt.match(/Program starting: v(\d+\.\d+\.\d+)/); - if (!versionMatch) versionMatch = txt.match(/tailscaled[\s_](\d+\.\d+\.\d+)/); - var version = versionMatch ? versionMatch[1] : null; + var versionMatches = txt.match(/Program starting: v(\d+\.\d+\.\d+)/g); + var version = null; + if (versionMatches) { + var last = versionMatches[versionMatches.length - 1]; + var vm = last.match(/v(\d+\.\d+\.\d+)/); + if (vm) version = vm[1]; + } var stateLines = txt.match(/Switching ipn state [^\n]+/g) || []; var lastState = stateLines.length ? stateLines[stateLines.length - 1] : ''; @@ -542,10 +564,15 @@ setInterval(refresh, 5000); // Check for updates from GitHub - var latestChecked = false; - function checkForUpdate(currentVersion) { - if (!currentVersion || latestChecked) return; - latestChecked = true; + var installedVersion = null; + var autoChecked = false; + function checkForUpdate(currentVersion, manual) { + if (!currentVersion) return; + installedVersion = currentVersion; + if (!manual && autoChecked) return; + if (!manual) autoChecked = true; + var btn = document.getElementById('check-update-btn'); + if (manual && btn) btn.textContent = 'Checking...'; fetch('https://api.github.com/repos/Mo3he/Axis_Cam_Tailscale/releases/latest') .then(function(r) { return r.json(); }) .then(function(data) { @@ -555,11 +582,22 @@ document.getElementById('update-version').textContent = 'v' + tag; document.getElementById('update-banner').classList.add('visible'); document.getElementById('ts-version').textContent = currentVersion + ' (outdated)'; + if (btn) btn.textContent = 'Update Available'; + } else { + if (manual && btn) btn.textContent = 'Up to date'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); } }) - .catch(function() {}); + .catch(function() { + if (manual && btn) btn.textContent = 'Check failed'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); + }); } + document.getElementById('check-update-btn').addEventListener('click', function() { + if (installedVersion) checkForUpdate(installedVersion, true); + }); + function compareVersions(a, b) { var pa = a.split('.').map(Number); var pb = b.split('.').map(Number); diff --git a/aarch64_custom/app/lib/tailscale b/aarch64_custom/app/lib/tailscale index 65b96b6..f16af6f 100755 Binary files a/aarch64_custom/app/lib/tailscale and b/aarch64_custom/app/lib/tailscale differ diff --git a/aarch64_custom/app/lib/tailscaled b/aarch64_custom/app/lib/tailscaled index 7a9ba48..ba9c26d 100755 Binary files a/aarch64_custom/app/lib/tailscaled and b/aarch64_custom/app/lib/tailscaled differ diff --git a/arm/app/html/index.html b/arm/app/html/index.html index cf9edf6..3674167 100644 --- a/arm/app/html/index.html +++ b/arm/app/html/index.html @@ -359,6 +359,9 @@
-
+
+ +
@@ -437,16 +440,35 @@ tsIP = allIPs.length ? allIPs[allIPs.length - 1] : null; } - var nodeMatch = txt.match(/popBrowserAuthNow\("([^"]+)"\)/); - if (!nodeMatch) nodeMatch = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/); - var node = nodeMatch ? nodeMatch[1] : null; + var nodeMatches = txt.match(/popBrowserAuthNow\("([^"]+)"\)/g); + if (!nodeMatches) nodeMatches = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/g); + var node = null; + if (nodeMatches) { + var nm = nodeMatches[nodeMatches.length - 1].match(/"([^"]+)"/); + if (nm) node = nm[1]; + } + if (!node) { + var hostMatches = txt.match(/^\S+\s+(\S+)\s+\[\s*INFO/gm); + if (hostMatches) { + var hm = hostMatches[hostMatches.length - 1].match(/^\S+\s+(\S+)/); + if (hm) node = hm[1]; + } + } - var loginMatch = txt.match(/active login:\s+(\S+)/); - var tailnet = loginMatch ? loginMatch[1] : null; + var loginMatches = txt.match(/active login:\s+\S+/g); + var tailnet = null; + if (loginMatches) { + var lm = loginMatches[loginMatches.length - 1].match(/active login:\s+(\S+)/); + if (lm) tailnet = lm[1]; + } - var versionMatch = txt.match(/Program starting: v(\d+\.\d+\.\d+)/); - if (!versionMatch) versionMatch = txt.match(/tailscaled[\s_](\d+\.\d+\.\d+)/); - var version = versionMatch ? versionMatch[1] : null; + var versionMatches = txt.match(/Program starting: v(\d+\.\d+\.\d+)/g); + var version = null; + if (versionMatches) { + var last = versionMatches[versionMatches.length - 1]; + var vm = last.match(/v(\d+\.\d+\.\d+)/); + if (vm) version = vm[1]; + } var stateLines = txt.match(/Switching ipn state [^\n]+/g) || []; var lastState = stateLines.length ? stateLines[stateLines.length - 1] : ''; @@ -542,10 +564,15 @@ setInterval(refresh, 5000); // Check for updates from GitHub - var latestChecked = false; - function checkForUpdate(currentVersion) { - if (!currentVersion || latestChecked) return; - latestChecked = true; + var installedVersion = null; + var autoChecked = false; + function checkForUpdate(currentVersion, manual) { + if (!currentVersion) return; + installedVersion = currentVersion; + if (!manual && autoChecked) return; + if (!manual) autoChecked = true; + var btn = document.getElementById('check-update-btn'); + if (manual && btn) btn.textContent = 'Checking...'; fetch('https://api.github.com/repos/Mo3he/Axis_Cam_Tailscale/releases/latest') .then(function(r) { return r.json(); }) .then(function(data) { @@ -555,11 +582,22 @@ document.getElementById('update-version').textContent = 'v' + tag; document.getElementById('update-banner').classList.add('visible'); document.getElementById('ts-version').textContent = currentVersion + ' (outdated)'; + if (btn) btn.textContent = 'Update Available'; + } else { + if (manual && btn) btn.textContent = 'Up to date'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); } }) - .catch(function() {}); + .catch(function() { + if (manual && btn) btn.textContent = 'Check failed'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); + }); } + document.getElementById('check-update-btn').addEventListener('click', function() { + if (installedVersion) checkForUpdate(installedVersion, true); + }); + function compareVersions(a, b) { var pa = a.split('.').map(Number); var pb = b.split('.').map(Number); diff --git a/arm/app/lib/tailscale b/arm/app/lib/tailscale index 8cdfd9f..bd9b6e4 100755 Binary files a/arm/app/lib/tailscale and b/arm/app/lib/tailscale differ diff --git a/arm/app/lib/tailscaled b/arm/app/lib/tailscaled index aaf6810..2d21522 100755 Binary files a/arm/app/lib/tailscaled and b/arm/app/lib/tailscaled differ diff --git a/arm_ROOT/app/html/index.html b/arm_ROOT/app/html/index.html index cf9edf6..3674167 100644 --- a/arm_ROOT/app/html/index.html +++ b/arm_ROOT/app/html/index.html @@ -359,6 +359,9 @@
-
+
+ +
@@ -437,16 +440,35 @@ tsIP = allIPs.length ? allIPs[allIPs.length - 1] : null; } - var nodeMatch = txt.match(/popBrowserAuthNow\("([^"]+)"\)/); - if (!nodeMatch) nodeMatch = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/); - var node = nodeMatch ? nodeMatch[1] : null; + var nodeMatches = txt.match(/popBrowserAuthNow\("([^"]+)"\)/g); + if (!nodeMatches) nodeMatches = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/g); + var node = null; + if (nodeMatches) { + var nm = nodeMatches[nodeMatches.length - 1].match(/"([^"]+)"/); + if (nm) node = nm[1]; + } + if (!node) { + var hostMatches = txt.match(/^\S+\s+(\S+)\s+\[\s*INFO/gm); + if (hostMatches) { + var hm = hostMatches[hostMatches.length - 1].match(/^\S+\s+(\S+)/); + if (hm) node = hm[1]; + } + } - var loginMatch = txt.match(/active login:\s+(\S+)/); - var tailnet = loginMatch ? loginMatch[1] : null; + var loginMatches = txt.match(/active login:\s+\S+/g); + var tailnet = null; + if (loginMatches) { + var lm = loginMatches[loginMatches.length - 1].match(/active login:\s+(\S+)/); + if (lm) tailnet = lm[1]; + } - var versionMatch = txt.match(/Program starting: v(\d+\.\d+\.\d+)/); - if (!versionMatch) versionMatch = txt.match(/tailscaled[\s_](\d+\.\d+\.\d+)/); - var version = versionMatch ? versionMatch[1] : null; + var versionMatches = txt.match(/Program starting: v(\d+\.\d+\.\d+)/g); + var version = null; + if (versionMatches) { + var last = versionMatches[versionMatches.length - 1]; + var vm = last.match(/v(\d+\.\d+\.\d+)/); + if (vm) version = vm[1]; + } var stateLines = txt.match(/Switching ipn state [^\n]+/g) || []; var lastState = stateLines.length ? stateLines[stateLines.length - 1] : ''; @@ -542,10 +564,15 @@ setInterval(refresh, 5000); // Check for updates from GitHub - var latestChecked = false; - function checkForUpdate(currentVersion) { - if (!currentVersion || latestChecked) return; - latestChecked = true; + var installedVersion = null; + var autoChecked = false; + function checkForUpdate(currentVersion, manual) { + if (!currentVersion) return; + installedVersion = currentVersion; + if (!manual && autoChecked) return; + if (!manual) autoChecked = true; + var btn = document.getElementById('check-update-btn'); + if (manual && btn) btn.textContent = 'Checking...'; fetch('https://api.github.com/repos/Mo3he/Axis_Cam_Tailscale/releases/latest') .then(function(r) { return r.json(); }) .then(function(data) { @@ -555,11 +582,22 @@ document.getElementById('update-version').textContent = 'v' + tag; document.getElementById('update-banner').classList.add('visible'); document.getElementById('ts-version').textContent = currentVersion + ' (outdated)'; + if (btn) btn.textContent = 'Update Available'; + } else { + if (manual && btn) btn.textContent = 'Up to date'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); } }) - .catch(function() {}); + .catch(function() { + if (manual && btn) btn.textContent = 'Check failed'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); + }); } + document.getElementById('check-update-btn').addEventListener('click', function() { + if (installedVersion) checkForUpdate(installedVersion, true); + }); + function compareVersions(a, b) { var pa = a.split('.').map(Number); var pb = b.split('.').map(Number); diff --git a/arm_ROOT/app/lib/tailscale b/arm_ROOT/app/lib/tailscale index 8cdfd9f..bd9b6e4 100755 Binary files a/arm_ROOT/app/lib/tailscale and b/arm_ROOT/app/lib/tailscale differ diff --git a/arm_ROOT/app/lib/tailscaled b/arm_ROOT/app/lib/tailscaled index aaf6810..2d21522 100755 Binary files a/arm_ROOT/app/lib/tailscaled and b/arm_ROOT/app/lib/tailscaled differ diff --git a/arm_custom/app/html/index.html b/arm_custom/app/html/index.html index 6706651..cdb10e8 100644 --- a/arm_custom/app/html/index.html +++ b/arm_custom/app/html/index.html @@ -359,6 +359,9 @@
-
+
+ +
@@ -437,16 +440,35 @@ tsIP = allIPs.length ? allIPs[allIPs.length - 1] : null; } - var nodeMatch = txt.match(/popBrowserAuthNow\("([^"]+)"\)/); - if (!nodeMatch) nodeMatch = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/); - var node = nodeMatch ? nodeMatch[1] : null; + var nodeMatches = txt.match(/popBrowserAuthNow\("([^"]+)"\)/g); + if (!nodeMatches) nodeMatches = txt.match(/StartLoginInteractiveAs\("([^"]+)"\)/g); + var node = null; + if (nodeMatches) { + var nm = nodeMatches[nodeMatches.length - 1].match(/"([^"]+)"/); + if (nm) node = nm[1]; + } + if (!node) { + var hostMatches = txt.match(/^\S+\s+(\S+)\s+\[\s*INFO/gm); + if (hostMatches) { + var hm = hostMatches[hostMatches.length - 1].match(/^\S+\s+(\S+)/); + if (hm) node = hm[1]; + } + } - var loginMatch = txt.match(/active login:\s+(\S+)/); - var tailnet = loginMatch ? loginMatch[1] : null; + var loginMatches = txt.match(/active login:\s+\S+/g); + var tailnet = null; + if (loginMatches) { + var lm = loginMatches[loginMatches.length - 1].match(/active login:\s+(\S+)/); + if (lm) tailnet = lm[1]; + } - var versionMatch = txt.match(/Program starting: v(\d+\.\d+\.\d+)/); - if (!versionMatch) versionMatch = txt.match(/tailscaled[\s_](\d+\.\d+\.\d+)/); - var version = versionMatch ? versionMatch[1] : null; + var versionMatches = txt.match(/Program starting: v(\d+\.\d+\.\d+)/g); + var version = null; + if (versionMatches) { + var last = versionMatches[versionMatches.length - 1]; + var vm = last.match(/v(\d+\.\d+\.\d+)/); + if (vm) version = vm[1]; + } var stateLines = txt.match(/Switching ipn state [^\n]+/g) || []; var lastState = stateLines.length ? stateLines[stateLines.length - 1] : ''; @@ -542,10 +564,15 @@ setInterval(refresh, 5000); // Check for updates from GitHub - var latestChecked = false; - function checkForUpdate(currentVersion) { - if (!currentVersion || latestChecked) return; - latestChecked = true; + var installedVersion = null; + var autoChecked = false; + function checkForUpdate(currentVersion, manual) { + if (!currentVersion) return; + installedVersion = currentVersion; + if (!manual && autoChecked) return; + if (!manual) autoChecked = true; + var btn = document.getElementById('check-update-btn'); + if (manual && btn) btn.textContent = 'Checking...'; fetch('https://api.github.com/repos/Mo3he/Axis_Cam_Tailscale/releases/latest') .then(function(r) { return r.json(); }) .then(function(data) { @@ -555,11 +582,22 @@ document.getElementById('update-version').textContent = 'v' + tag; document.getElementById('update-banner').classList.add('visible'); document.getElementById('ts-version').textContent = currentVersion + ' (outdated)'; + if (btn) btn.textContent = 'Update Available'; + } else { + if (manual && btn) btn.textContent = 'Up to date'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); } }) - .catch(function() {}); + .catch(function() { + if (manual && btn) btn.textContent = 'Check failed'; + setTimeout(function() { if (btn) btn.textContent = 'Check for Updates'; }, 3000); + }); } + document.getElementById('check-update-btn').addEventListener('click', function() { + if (installedVersion) checkForUpdate(installedVersion, true); + }); + function compareVersions(a, b) { var pa = a.split('.').map(Number); var pb = b.split('.').map(Number); diff --git a/docs/index.html b/docs/index.html index 0bb2e14..0f3ce0d 100644 --- a/docs/index.html +++ b/docs/index.html @@ -403,11 +403,11 @@

Standard (Non-Root)

For Axis OS 12 and newer. Runs in user-space networking mode without root privileges.

- + AARCH64 - + ARM @@ -419,11 +419,11 @@

Custom Server

Supports custom Tailscale control servers and auth keys. Ideal for self-hosted Headscale setups.

- + AARCH64 - + ARM @@ -435,11 +435,11 @@

Root (Full Networking)

For Axis OS older than 12. Requires root access but provides full Tailscale networking features.

- + AARCH64 - + ARM @@ -526,6 +526,37 @@ applyTheme(e.matches ? 'light' : 'dark'); } }); + + // Rewrite download links to point directly to latest release assets + fetch('https://api.github.com/repos/Mo3he/Axis_Cam_Tailscale/releases/latest') + .then(function(r) { return r.json(); }) + .then(function(data) { + var assets = data.assets || []; + var buttons = document.querySelectorAll('a[data-asset]'); + for (var i = 0; i < buttons.length; i++) { + var btn = buttons[i]; + var type = btn.getAttribute('data-asset'); + var arch = btn.getAttribute('data-arch'); + for (var j = 0; j < assets.length; j++) { + var name = assets[j].name.toLowerCase(); + var archMatch = name.indexOf(arch) !== -1; + var typeMatch = false; + if (type === 'Tailscale_VPN') { + typeMatch = name.indexOf('custom') === -1 && name.indexOf('root') === -1; + } else if (type === 'custom') { + typeMatch = name.indexOf('custom') !== -1; + } else if (type === 'ROOT') { + typeMatch = name.indexOf('root') !== -1; + } + if (archMatch && typeMatch) { + btn.href = assets[j].browser_download_url; + btn.removeAttribute('target'); + break; + } + } + } + }) + .catch(function() {}); })();