Fix player page now playing updates and spectrum analyzer MUTED indicator
- Execute scripts after AJAX navigation to enable dynamic content updates - Fix spectrum analyzer audio element reference across navigation - Stop and restart spectrum analyzer when re-initializing after AJAX load - Find audio element in parent frame for frameset mode - Clear all intervals/timeouts before navigation to prevent errors - Add status-content.ctml placeholder page - Remove debug logging from spectrum analyzer Fixes: - Now playing panel updates on player page after navigation - MUTED indicator appears correctly across all pages - No console errors from abandoned intervals - Clean resource cleanup on page transitions
This commit is contained in:
parent
3a8827f442
commit
ca07b6e670
|
|
@ -607,6 +607,13 @@
|
||||||
:top-artist-3 ""
|
:top-artist-3 ""
|
||||||
:top-artist-3-plays ""))
|
:top-artist-3-plays ""))
|
||||||
|
|
||||||
|
;; Status content frame (for frameset mode)
|
||||||
|
(define-page status-content #@"/status-content" ()
|
||||||
|
"Status page content (displayed in content frame)"
|
||||||
|
(clip:process-to-string
|
||||||
|
(load-template "status-content")
|
||||||
|
:title "📡 Asteroid Radio - Status"))
|
||||||
|
|
||||||
;; Configure static file serving for other files
|
;; Configure static file serving for other files
|
||||||
;; BUT exclude ParenScript-compiled JS files
|
;; BUT exclude ParenScript-compiled JS files
|
||||||
(define-page static #@"/static/(.*)" (:uri-groups (path))
|
(define-page static #@"/static/(.*)" (:uri-groups (path))
|
||||||
|
|
|
||||||
|
|
@ -43,24 +43,22 @@
|
||||||
(let ((audio-element nil)
|
(let ((audio-element nil)
|
||||||
(canvas-element (ps:chain document (get-element-by-id "spectrum-canvas"))))
|
(canvas-element (ps:chain document (get-element-by-id "spectrum-canvas"))))
|
||||||
|
|
||||||
;; Try to find audio element in current frame first
|
;; Try current document first
|
||||||
(setf audio-element (or (ps:chain document (get-element-by-id "live-audio"))
|
(setf audio-element (or (ps:chain document (get-element-by-id "live-audio"))
|
||||||
(ps:chain document (get-element-by-id "persistent-audio"))))
|
(ps:chain document (get-element-by-id "persistent-audio"))))
|
||||||
|
|
||||||
;; If not found and we're in a frame, try to access from parent frameset
|
;; If not found and we're in a frame, try parent frame (frameset mode)
|
||||||
(when (and (not audio-element)
|
(when (and (not audio-element)
|
||||||
(ps:@ window parent)
|
(ps:@ window parent)
|
||||||
(not (eq (ps:@ window parent) window)))
|
(not (eq (ps:@ window parent) window)))
|
||||||
(ps:chain console (log "Trying to access audio from parent frame..."))
|
|
||||||
(ps:try
|
(ps:try
|
||||||
(progn
|
(let ((player-frame (ps:getprop (ps:@ window parent frames) "player-frame")))
|
||||||
;; Try accessing via parent.frames
|
(when player-frame
|
||||||
(let ((player-frame (ps:getprop (ps:@ window parent) "player-frame")))
|
(setf audio-element (ps:chain player-frame document (get-element-by-id "persistent-audio")))
|
||||||
(when player-frame
|
(when audio-element
|
||||||
(setf audio-element (ps:chain player-frame document (get-element-by-id "persistent-audio")))
|
(ps:chain console (log "Found persistent-audio in player-frame")))))
|
||||||
(ps:chain console (log "Found audio in player-frame:" audio-element)))))
|
|
||||||
(:catch (e)
|
(:catch (e)
|
||||||
(ps:chain console (log "Cross-frame access error:" e)))))
|
(ps:chain console (log "Could not access parent frame:" e)))))
|
||||||
|
|
||||||
(when (and audio-element canvas-element)
|
(when (and audio-element canvas-element)
|
||||||
;; Store current audio element
|
;; Store current audio element
|
||||||
|
|
@ -218,49 +216,72 @@
|
||||||
"Return array of available visualization styles"
|
"Return array of available visualization styles"
|
||||||
(array "bars" "wave" "dots"))
|
(array "bars" "wave" "dots"))
|
||||||
|
|
||||||
;; Initialize when audio starts playing
|
(defun initialize-spectrum-analyzer ()
|
||||||
(ps:chain document (add-event-listener "DOMContentLoaded"
|
"Initialize or re-initialize the spectrum analyzer (can be called after AJAX navigation)"
|
||||||
(lambda ()
|
;; Stop existing analyzer if running
|
||||||
;; Load saved theme and style preferences
|
(when *animation-id*
|
||||||
(let ((saved-theme (ps:chain local-storage (get-item "spectrum-theme")))
|
(ps:chain window (cancel-animation-frame *animation-id*))
|
||||||
(saved-style (ps:chain local-storage (get-item "spectrum-style"))))
|
(setf *animation-id* nil))
|
||||||
(when (and saved-theme (ps:getprop *themes* saved-theme))
|
|
||||||
(setf *current-theme* saved-theme))
|
;; Load saved theme and style preferences
|
||||||
(when (and saved-style (or (= saved-style "bars") (= saved-style "wave") (= saved-style "dots")))
|
(let ((saved-theme (ps:chain local-storage (get-item "spectrum-theme")))
|
||||||
(setf *current-style* saved-style))
|
(saved-style (ps:chain local-storage (get-item "spectrum-style"))))
|
||||||
|
(when (and saved-theme (ps:getprop *themes* saved-theme))
|
||||||
;; Update UI selectors, canvas border, and dropdown colors
|
(setf *current-theme* saved-theme))
|
||||||
(let ((theme-selector (ps:chain document (get-element-by-id "spectrum-theme-selector")))
|
(when (and saved-style (or (= saved-style "bars") (= saved-style "wave") (= saved-style "dots")))
|
||||||
(style-selector (ps:chain document (get-element-by-id "spectrum-style-selector")))
|
(setf *current-style* saved-style))
|
||||||
(canvas (ps:chain document (get-element-by-id "spectrum-canvas")))
|
|
||||||
(theme (ps:getprop *themes* *current-theme*)))
|
|
||||||
(when theme-selector
|
|
||||||
(setf (ps:@ theme-selector value) *current-theme*)
|
|
||||||
(setf (ps:@ theme-selector style color) (ps:@ theme top))
|
|
||||||
(setf (ps:@ theme-selector style border-color) (ps:@ theme top)))
|
|
||||||
(when style-selector
|
|
||||||
(setf (ps:@ style-selector value) *current-style*)
|
|
||||||
(setf (ps:@ style-selector style color) (ps:@ theme top))
|
|
||||||
(setf (ps:@ style-selector style border-color) (ps:@ theme top)))
|
|
||||||
|
|
||||||
;; Set initial canvas border color
|
|
||||||
(when canvas
|
|
||||||
(setf (ps:@ canvas style border-color) (ps:@ theme top)))))
|
|
||||||
|
|
||||||
(let ((audio-element (or (ps:chain document (get-element-by-id "live-audio"))
|
;; Update UI selectors, canvas border, and dropdown colors
|
||||||
(ps:chain document (get-element-by-id "persistent-audio")))))
|
(let ((theme-selector (ps:chain document (get-element-by-id "spectrum-theme-selector")))
|
||||||
|
(style-selector (ps:chain document (get-element-by-id "spectrum-style-selector")))
|
||||||
|
(canvas (ps:chain document (get-element-by-id "spectrum-canvas")))
|
||||||
|
(theme (ps:getprop *themes* *current-theme*)))
|
||||||
|
(when theme-selector
|
||||||
|
(setf (ps:@ theme-selector value) *current-theme*)
|
||||||
|
(setf (ps:@ theme-selector style color) (ps:@ theme top))
|
||||||
|
(setf (ps:@ theme-selector style border-color) (ps:@ theme top)))
|
||||||
|
(when style-selector
|
||||||
|
(setf (ps:@ style-selector value) *current-style*)
|
||||||
|
(setf (ps:@ style-selector style color) (ps:@ theme top))
|
||||||
|
(setf (ps:@ style-selector style border-color) (ps:@ theme top)))
|
||||||
|
|
||||||
;; If not found and we're in a frame, try parent
|
;; Set initial canvas border color
|
||||||
(when (and (not audio-element)
|
(when canvas
|
||||||
(ps:@ window parent)
|
(setf (ps:@ canvas style border-color) (ps:@ theme top)))))
|
||||||
(not (eq (ps:@ window parent) window)))
|
|
||||||
(ps:try
|
(let ((audio-element nil))
|
||||||
(let ((player-frame (ps:getprop (ps:@ window parent) "player-frame")))
|
|
||||||
(when player-frame
|
;; Try current document first
|
||||||
(setf audio-element (ps:chain player-frame document (get-element-by-id "persistent-audio")))))
|
(setf audio-element (or (ps:chain document (get-element-by-id "live-audio"))
|
||||||
(:catch (e)
|
(ps:chain document (get-element-by-id "persistent-audio"))))
|
||||||
(ps:chain console (log "Event listener cross-frame error:" e)))))
|
|
||||||
|
;; If not found and we're in a frame, try parent frame (frameset mode)
|
||||||
|
(when (and (not audio-element)
|
||||||
|
(ps:@ window parent)
|
||||||
|
(not (eq (ps:@ window parent) window)))
|
||||||
|
(ps:try
|
||||||
|
(let ((player-frame (ps:getprop (ps:@ window parent frames) "player-frame")))
|
||||||
|
(when player-frame
|
||||||
|
(setf audio-element (ps:chain player-frame document (get-element-by-id "persistent-audio")))
|
||||||
|
(when audio-element
|
||||||
|
(ps:chain console (log "Found persistent-audio in player-frame")))))
|
||||||
|
(:catch (e)
|
||||||
|
(ps:chain console (log "Could not access parent frame:" e)))))
|
||||||
|
|
||||||
|
(when audio-element
|
||||||
|
;; Store reference for muted detection
|
||||||
|
(setf *current-audio-element* audio-element)
|
||||||
|
(ps:chain audio-element (add-event-listener "play" init-spectrum-analyzer))
|
||||||
|
(ps:chain audio-element (add-event-listener "pause" stop-spectrum-analyzer))
|
||||||
|
|
||||||
(when audio-element
|
;; If audio is already playing, restart the analyzer with new reference
|
||||||
(ps:chain audio-element (add-event-listener "play" init-spectrum-analyzer))
|
(when (and (not (ps:@ audio-element paused))
|
||||||
(ps:chain audio-element (add-event-listener "pause" stop-spectrum-analyzer)))))))))
|
(ps:chain document (get-element-by-id "spectrum-canvas")))
|
||||||
|
(ps:chain console (log "Audio already playing, restarting spectrum analyzer"))
|
||||||
|
(init-spectrum-analyzer)))))
|
||||||
|
|
||||||
|
;; Make initialization function globally accessible
|
||||||
|
(setf (ps:@ window |initializeSpectrumAnalyzer|) initialize-spectrum-analyzer)
|
||||||
|
|
||||||
|
;; Initialize when audio starts playing
|
||||||
|
(ps:chain document (add-event-listener "DOMContentLoaded" initialize-spectrum-analyzer))))
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,13 @@
|
||||||
const url = link.href;
|
const url = link.href;
|
||||||
console.log('Loading via AJAX:', url);
|
console.log('Loading via AJAX:', url);
|
||||||
|
|
||||||
|
// Clear all intervals to prevent old page scripts from running
|
||||||
|
const highestId = window.setTimeout(() => {}, 0);
|
||||||
|
for (let i = 0; i < highestId; i++) {
|
||||||
|
window.clearInterval(i);
|
||||||
|
window.clearTimeout(i);
|
||||||
|
}
|
||||||
|
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.text())
|
.then(response => response.text())
|
||||||
.then(html => {
|
.then(html => {
|
||||||
|
|
@ -41,6 +48,23 @@
|
||||||
document.write(html);
|
document.write(html);
|
||||||
document.close();
|
document.close();
|
||||||
|
|
||||||
|
// Execute scripts in the new content
|
||||||
|
const scripts = document.querySelectorAll('script');
|
||||||
|
scripts.forEach(oldScript => {
|
||||||
|
const newScript = document.createElement('script');
|
||||||
|
if (oldScript.src) {
|
||||||
|
newScript.src = oldScript.src;
|
||||||
|
} else {
|
||||||
|
newScript.textContent = oldScript.textContent;
|
||||||
|
}
|
||||||
|
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Re-initialize spectrum analyzer after navigation
|
||||||
|
if (window.initializeSpectrumAnalyzer) {
|
||||||
|
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||||
|
}
|
||||||
|
|
||||||
if (window.history && window.history.pushState) {
|
if (window.history && window.history.pushState) {
|
||||||
window.history.pushState({}, '', url);
|
window.history.pushState({}, '', url);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,13 @@
|
||||||
const url = link.href;
|
const url = link.href;
|
||||||
console.log('Loading via AJAX:', url);
|
console.log('Loading via AJAX:', url);
|
||||||
|
|
||||||
|
// Clear all intervals to prevent old page scripts from running
|
||||||
|
const highestId = window.setTimeout(() => {}, 0);
|
||||||
|
for (let i = 0; i < highestId; i++) {
|
||||||
|
window.clearInterval(i);
|
||||||
|
window.clearTimeout(i);
|
||||||
|
}
|
||||||
|
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.text())
|
.then(response => response.text())
|
||||||
.then(html => {
|
.then(html => {
|
||||||
|
|
@ -47,6 +54,23 @@
|
||||||
document.write(html);
|
document.write(html);
|
||||||
document.close();
|
document.close();
|
||||||
|
|
||||||
|
// Execute scripts in the new content
|
||||||
|
const scripts = document.querySelectorAll('script');
|
||||||
|
scripts.forEach(oldScript => {
|
||||||
|
const newScript = document.createElement('script');
|
||||||
|
if (oldScript.src) {
|
||||||
|
newScript.src = oldScript.src;
|
||||||
|
} else {
|
||||||
|
newScript.textContent = oldScript.textContent;
|
||||||
|
}
|
||||||
|
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Re-initialize spectrum analyzer after navigation
|
||||||
|
if (window.initializeSpectrumAnalyzer) {
|
||||||
|
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||||
|
}
|
||||||
|
|
||||||
// Update browser history
|
// Update browser history
|
||||||
if (window.history && window.history.pushState) {
|
if (window.history && window.history.pushState) {
|
||||||
window.history.pushState({}, '', url);
|
window.history.pushState({}, '', url);
|
||||||
|
|
@ -101,13 +125,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="nav">
|
<nav class="nav">
|
||||||
<a href="/asteroid/content" target="content-frame">Home</a>
|
<a href="/asteroid/content" target="content-frame" onclick="return loadInFrame(this)">Home</a>
|
||||||
<a href="/asteroid/player-content" target="content-frame">Player</a>
|
<a href="/asteroid/player-content" target="content-frame" onclick="return loadInFrame(this)">Player</a>
|
||||||
<a href="/asteroid/status" target="content-frame">Status</a>
|
<a href="/asteroid/status-content" target="content-frame" onclick="return loadInFrame(this)">Status</a>
|
||||||
<a href="/asteroid/profile" target="content-frame" data-show-if-logged-in>Profile</a>
|
<a href="/asteroid/profile-content" target="content-frame" data-show-if-logged-in onclick="return loadInFrame(this)">Profile</a>
|
||||||
<a href="/asteroid/admin" target="content-frame" data-show-if-admin>Admin</a>
|
<a href="/asteroid/admin-content" target="content-frame" data-show-if-admin onclick="return loadInFrame(this)">Admin</a>
|
||||||
<a href="/asteroid/login-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Login</a>
|
<a href="/asteroid/login-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Login</a>
|
||||||
<a href="/asteroid/register" target="content-frame" data-show-if-logged-out>Register</a>
|
<a href="/asteroid/register-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Register</a>
|
||||||
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout" onclick="handleLogout(); return false;">Logout</a>
|
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout" onclick="handleLogout(); return false;">Logout</a>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,13 @@
|
||||||
const url = link.href;
|
const url = link.href;
|
||||||
console.log('Loading via AJAX:', url);
|
console.log('Loading via AJAX:', url);
|
||||||
|
|
||||||
|
// Clear all intervals to prevent old page scripts from running
|
||||||
|
const highestId = window.setTimeout(() => {}, 0);
|
||||||
|
for (let i = 0; i < highestId; i++) {
|
||||||
|
window.clearInterval(i);
|
||||||
|
window.clearTimeout(i);
|
||||||
|
}
|
||||||
|
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.text())
|
.then(response => response.text())
|
||||||
.then(html => {
|
.then(html => {
|
||||||
|
|
@ -21,6 +28,23 @@
|
||||||
document.write(html);
|
document.write(html);
|
||||||
document.close();
|
document.close();
|
||||||
|
|
||||||
|
// Execute scripts in the new content
|
||||||
|
const scripts = document.querySelectorAll('script');
|
||||||
|
scripts.forEach(oldScript => {
|
||||||
|
const newScript = document.createElement('script');
|
||||||
|
if (oldScript.src) {
|
||||||
|
newScript.src = oldScript.src;
|
||||||
|
} else {
|
||||||
|
newScript.textContent = oldScript.textContent;
|
||||||
|
}
|
||||||
|
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Re-initialize spectrum analyzer after navigation
|
||||||
|
if (window.initializeSpectrumAnalyzer) {
|
||||||
|
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||||
|
}
|
||||||
|
|
||||||
if (window.history && window.history.pushState) {
|
if (window.history && window.history.pushState) {
|
||||||
window.history.pushState({}, '', url);
|
window.history.pushState({}, '', url);
|
||||||
}
|
}
|
||||||
|
|
@ -74,9 +98,9 @@
|
||||||
<span>ASTEROID RADIO - LOGIN</span>
|
<span>ASTEROID RADIO - LOGIN</span>
|
||||||
</h1>
|
</h1>
|
||||||
<nav class="nav">
|
<nav class="nav">
|
||||||
<a href="/asteroid/content" target="content-frame">Home</a>
|
<a href="/asteroid/content" target="content-frame" onclick="return loadInFrame(this)">Home</a>
|
||||||
<a href="/asteroid/status" target="content-frame">Status</a>
|
<a href="/asteroid/status-content" target="content-frame" onclick="return loadInFrame(this)">Status</a>
|
||||||
<a href="/asteroid/register-content" target="content-frame">Register</a>
|
<a href="/asteroid/register-content" target="content-frame" onclick="return loadInFrame(this)">Register</a>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,13 @@
|
||||||
const url = link.href;
|
const url = link.href;
|
||||||
console.log('Loading via AJAX:', url);
|
console.log('Loading via AJAX:', url);
|
||||||
|
|
||||||
|
// Clear all intervals to prevent old page scripts from running
|
||||||
|
const highestId = window.setTimeout(() => {}, 0);
|
||||||
|
for (let i = 0; i < highestId; i++) {
|
||||||
|
window.clearInterval(i);
|
||||||
|
window.clearTimeout(i);
|
||||||
|
}
|
||||||
|
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.text())
|
.then(response => response.text())
|
||||||
.then(html => {
|
.then(html => {
|
||||||
|
|
@ -43,6 +50,23 @@
|
||||||
document.write(html);
|
document.write(html);
|
||||||
document.close();
|
document.close();
|
||||||
|
|
||||||
|
// Execute scripts in the new content
|
||||||
|
const scripts = document.querySelectorAll('script');
|
||||||
|
scripts.forEach(oldScript => {
|
||||||
|
const newScript = document.createElement('script');
|
||||||
|
if (oldScript.src) {
|
||||||
|
newScript.src = oldScript.src;
|
||||||
|
} else {
|
||||||
|
newScript.textContent = oldScript.textContent;
|
||||||
|
}
|
||||||
|
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Re-initialize spectrum analyzer after navigation
|
||||||
|
if (window.initializeSpectrumAnalyzer) {
|
||||||
|
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||||
|
}
|
||||||
|
|
||||||
// Update browser history
|
// Update browser history
|
||||||
if (window.history && window.history.pushState) {
|
if (window.history && window.history.pushState) {
|
||||||
window.history.pushState({}, '', url);
|
window.history.pushState({}, '', url);
|
||||||
|
|
@ -95,11 +119,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="nav">
|
<div class="nav">
|
||||||
<a href="/asteroid/content" target="content-frame">Home</a>
|
<a href="/asteroid/content" target="content-frame" onclick="return loadInFrame(this)">Home</a>
|
||||||
<a href="/asteroid/profile" target="content-frame" data-show-if-logged-in>Profile</a>
|
<a href="/asteroid/profile-content" target="content-frame" data-show-if-logged-in onclick="return loadInFrame(this)">Profile</a>
|
||||||
<a href="/asteroid/admin" target="content-frame" data-show-if-admin>Admin</a>
|
<a href="/asteroid/admin-content" target="content-frame" data-show-if-admin onclick="return loadInFrame(this)">Admin</a>
|
||||||
<a href="/asteroid/login-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Login</a>
|
<a href="/asteroid/login-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Login</a>
|
||||||
<a href="/asteroid/register" target="content-frame" data-show-if-logged-out>Register</a>
|
<a href="/asteroid/register-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Register</a>
|
||||||
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout" onclick="handleLogout(); return false;">Logout</a>
|
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout" onclick="handleLogout(); return false;">Logout</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,13 @@
|
||||||
const url = link.href;
|
const url = link.href;
|
||||||
console.log('Loading via AJAX:', url);
|
console.log('Loading via AJAX:', url);
|
||||||
|
|
||||||
|
// Clear all intervals to prevent old page scripts from running
|
||||||
|
const highestId = window.setTimeout(() => {}, 0);
|
||||||
|
for (let i = 0; i < highestId; i++) {
|
||||||
|
window.clearInterval(i);
|
||||||
|
window.clearTimeout(i);
|
||||||
|
}
|
||||||
|
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.text())
|
.then(response => response.text())
|
||||||
.then(html => {
|
.then(html => {
|
||||||
|
|
@ -41,6 +48,23 @@
|
||||||
document.write(html);
|
document.write(html);
|
||||||
document.close();
|
document.close();
|
||||||
|
|
||||||
|
// Execute scripts in the new content
|
||||||
|
const scripts = document.querySelectorAll('script');
|
||||||
|
scripts.forEach(oldScript => {
|
||||||
|
const newScript = document.createElement('script');
|
||||||
|
if (oldScript.src) {
|
||||||
|
newScript.src = oldScript.src;
|
||||||
|
} else {
|
||||||
|
newScript.textContent = oldScript.textContent;
|
||||||
|
}
|
||||||
|
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Re-initialize spectrum analyzer after navigation
|
||||||
|
if (window.initializeSpectrumAnalyzer) {
|
||||||
|
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||||
|
}
|
||||||
|
|
||||||
if (window.history && window.history.pushState) {
|
if (window.history && window.history.pushState) {
|
||||||
window.history.pushState({}, '', url);
|
window.history.pushState({}, '', url);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Asteroid Radio - Status</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" type="text/css" href="/asteroid/static/asteroid.css">
|
||||||
|
<script src="/asteroid/static/js/auth-ui.js"></script>
|
||||||
|
<script>
|
||||||
|
// Handle logout without navigation
|
||||||
|
function handleLogout() {
|
||||||
|
fetch('/asteroid/logout', {
|
||||||
|
method: 'GET',
|
||||||
|
redirect: 'manual'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Reload the current page content to show logged-out state
|
||||||
|
fetch(window.location.href)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(html => {
|
||||||
|
document.open();
|
||||||
|
document.write(html);
|
||||||
|
document.close();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Logout failed:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load content via AJAX to prevent audio interruption
|
||||||
|
function loadInFrame(link) {
|
||||||
|
const url = link.href;
|
||||||
|
console.log('Loading via AJAX:', url);
|
||||||
|
|
||||||
|
// Clear all intervals to prevent old page scripts from running
|
||||||
|
const highestId = window.setTimeout(() => {}, 0);
|
||||||
|
for (let i = 0; i < highestId; i++) {
|
||||||
|
window.clearInterval(i);
|
||||||
|
window.clearTimeout(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(url)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(html => {
|
||||||
|
document.open();
|
||||||
|
document.write(html);
|
||||||
|
document.close();
|
||||||
|
|
||||||
|
// Execute scripts in the new content
|
||||||
|
const scripts = document.querySelectorAll('script');
|
||||||
|
scripts.forEach(oldScript => {
|
||||||
|
const newScript = document.createElement('script');
|
||||||
|
if (oldScript.src) {
|
||||||
|
newScript.src = oldScript.src;
|
||||||
|
} else {
|
||||||
|
newScript.textContent = oldScript.textContent;
|
||||||
|
}
|
||||||
|
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Re-initialize spectrum analyzer after navigation
|
||||||
|
if (window.initializeSpectrumAnalyzer) {
|
||||||
|
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.history && window.history.pushState) {
|
||||||
|
window.history.pushState({}, '', url);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Failed to load content:', error);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>📡 SYSTEM STATUS</h1>
|
||||||
|
<div class="nav">
|
||||||
|
<a href="/asteroid/content" target="content-frame" onclick="return loadInFrame(this)">Home</a>
|
||||||
|
<a href="/asteroid/player-content" target="content-frame" onclick="return loadInFrame(this)">Player</a>
|
||||||
|
<a href="/asteroid/profile-content" target="content-frame" data-show-if-logged-in onclick="return loadInFrame(this)">Profile</a>
|
||||||
|
<a href="/asteroid/admin-content" target="content-frame" data-show-if-admin onclick="return loadInFrame(this)">Admin</a>
|
||||||
|
<a href="/asteroid/login-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Login</a>
|
||||||
|
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout" onclick="handleLogout(); return false;">Logout</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="admin-section">
|
||||||
|
<h2>Server Status</h2>
|
||||||
|
<p>Status page coming soon...</p>
|
||||||
|
<p>For now, administrators can view detailed status information in the <a href="/asteroid/admin-content" target="content-frame" onclick="return loadInFrame(this)">Admin Dashboard</a>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Reference in New Issue