error message
This commit is contained in:
@@ -6,6 +6,7 @@ let hasNextPage = true;
|
|||||||
let isLoading = false;
|
let isLoading = false;
|
||||||
let hlsPlayer = null;
|
let hlsPlayer = null;
|
||||||
let currentLoadController = null;
|
let currentLoadController = null;
|
||||||
|
let errorToastTimer = null;
|
||||||
|
|
||||||
// 2. Observer Definition (Must be defined before initApp uses it)
|
// 2. Observer Definition (Must be defined before initApp uses it)
|
||||||
const observer = new IntersectionObserver((entries) => {
|
const observer = new IntersectionObserver((entries) => {
|
||||||
@@ -198,6 +199,14 @@ async function initApp() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const errorToastClose = document.getElementById('error-toast-close');
|
||||||
|
if (errorToastClose) {
|
||||||
|
errorToastClose.onclick = () => {
|
||||||
|
const toast = document.getElementById('error-toast');
|
||||||
|
if (toast) toast.classList.remove('show');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
ensureViewportFilled();
|
ensureViewportFilled();
|
||||||
});
|
});
|
||||||
@@ -212,6 +221,20 @@ function applyTheme() {
|
|||||||
if (select) select.value = theme;
|
if (select) select.value = theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showError(message) {
|
||||||
|
const toast = document.getElementById('error-toast');
|
||||||
|
const text = document.getElementById('error-toast-text');
|
||||||
|
if (!toast || !text) return;
|
||||||
|
text.textContent = message;
|
||||||
|
toast.classList.add('show');
|
||||||
|
if (errorToastTimer) {
|
||||||
|
clearTimeout(errorToastTimer);
|
||||||
|
}
|
||||||
|
errorToastTimer = setTimeout(() => {
|
||||||
|
toast.classList.remove('show');
|
||||||
|
}, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
async function openPlayer(url) {
|
async function openPlayer(url) {
|
||||||
const modal = document.getElementById('video-modal');
|
const modal = document.getElementById('video-modal');
|
||||||
const video = document.getElementById('player');
|
const video = document.getElementById('player');
|
||||||
@@ -253,16 +276,28 @@ async function openPlayer(url) {
|
|||||||
hlsPlayer.on(window.Hls.Events.MANIFEST_PARSED, function() {
|
hlsPlayer.on(window.Hls.Events.MANIFEST_PARSED, function() {
|
||||||
video.play();
|
video.play();
|
||||||
});
|
});
|
||||||
|
hlsPlayer.on(window.Hls.Events.ERROR, function(event, data) {
|
||||||
|
if (data && data.fatal) {
|
||||||
|
showError('Unable to play this stream.');
|
||||||
|
closePlayer();
|
||||||
|
}
|
||||||
|
});
|
||||||
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
||||||
video.src = streamUrl;
|
video.src = streamUrl;
|
||||||
} else {
|
} else {
|
||||||
console.error("HLS not supported in this browser.");
|
console.error("HLS not supported in this browser.");
|
||||||
|
showError('HLS is not supported in this browser.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
video.src = streamUrl;
|
video.src = streamUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
video.onerror = () => {
|
||||||
|
showError('Video failed to load.');
|
||||||
|
closePlayer();
|
||||||
|
};
|
||||||
|
|
||||||
modal.style.display = 'flex';
|
modal.style.display = 'flex';
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
}
|
}
|
||||||
@@ -274,6 +309,7 @@ function closePlayer() {
|
|||||||
hlsPlayer.destroy();
|
hlsPlayer.destroy();
|
||||||
hlsPlayer = null;
|
hlsPlayer = null;
|
||||||
}
|
}
|
||||||
|
video.onerror = null;
|
||||||
video.pause();
|
video.pause();
|
||||||
video.src = '';
|
video.src = '';
|
||||||
modal.style.display = 'none';
|
modal.style.display = 'none';
|
||||||
|
|||||||
@@ -93,6 +93,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="error-toast" class="error-toast" role="alert" aria-live="assertive">
|
||||||
|
<span id="error-toast-text"></span>
|
||||||
|
<button id="error-toast-close" type="button" aria-label="Close">✕</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src="static/app.js"></script>
|
<script src="static/app.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
|
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -768,6 +768,47 @@ video {
|
|||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-toast {
|
||||||
|
position: fixed;
|
||||||
|
right: 20px;
|
||||||
|
bottom: 20px;
|
||||||
|
max-width: min(360px, 90vw);
|
||||||
|
background: rgba(0, 0, 0, 0.85);
|
||||||
|
color: #ffffff;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
|
||||||
|
z-index: 3000;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateY(8px);
|
||||||
|
transition: opacity 0.2s ease, transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-toast.show {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-toast button {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.theme-light .error-toast {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
color: #000000;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
/* Scrollbar styling */
|
/* Scrollbar styling */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
|
|||||||
Reference in New Issue
Block a user