fixes for extension sources & tweaks

This commit is contained in:
2025-11-29 22:11:42 +01:00
parent 655ab9c987
commit 7625c52017
17 changed files with 1103 additions and 463 deletions

View File

@@ -6,69 +6,176 @@
<base href="/">
<title>WaifuBoard Watch</title>
<link rel="stylesheet" href="/views/css/anime/watch.css">
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<link rel="stylesheet" href="https://cdn.plyr.io/3.7.8/plyr.css" />
<script src="https://cdn.plyr.io/3.7.8/plyr.js"></script>
<link rel="icon" href="/public/assets/waifuboards.ico" type="image/x-icon">
<link rel="icon" href="/public/assets/waifuboards.ico">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
</head>
<body>
<div class="top-bar">
<header class="top-bar">
<a href="#" id="back-link" class="back-btn">
<svg width="20" height="20" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M15 19l-7-7 7-7"/></svg>
Back to Series
<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24">
<path d="M15 19l-7-7 7-7"/>
</svg>
<span>Back to Series</span>
</a>
</div>
</header>
<div class="theater-container">
<div class="ui-scale">
<div class="player-toolbar">
<div class="sd-toggle" id="sd-toggle" data-state="sub" style="display: none;" onclick="toggleAudioMode()">
<div class="sd-bg"></div>
<div class="sd-option active" id="opt-sub">Sub</div>
<div class="sd-option" id="opt-dub">Dub</div>
<section class="anime-details">
<div class="details-container">
<div class="details-cover">
<img id="detail-cover-image" src="" alt="Anime Cover" class="cover-image">
</div>
<div class="details-content">
<h1 id="detail-anime-title"></h1>
<div class="details-meta">
<span id="detail-format" class="meta-badge">--</span>
<span id="detail-season" class="meta-badge">--</span>
<span id="detail-score" class="meta-badge meta-score">--</span>
</div>
<p id="detail-description" class="details-description">Loading description...</p>
</div>
</div>
</section>
<main class="watch-container">
<select id="server-select" class="extension-select" style="display:none;" onchange="loadStream()">
<section class="player-section">
</select>
<div class="player-toolbar">
<select id="extension-select" class="extension-select" onchange="onExtensionChange()">
<option value="" disabled selected>Source...</option>
</select>
</div>
<div class="control-group">
<div class="sd-toggle" id="sd-toggle" data-state="sub" onclick="toggleAudioMode()">
<div class="sd-bg"></div>
<div class="sd-option active" id="opt-sub">Sub</div>
<div class="sd-option" id="opt-dub">Dub</div>
</div>
</div>
<div class="control-group">
<select id="server-select" class="source-select" onchange="loadStream()" style="display:none;">
<option value="">Server...</option>
</select>
<select id="extension-select" class="source-select" onchange="onExtensionChange()">
<option value="" disabled selected>Source...</option>
</select>
</div>
<div class="video-wrapper">
<video id="player" controls crossorigin playsinline poster=""></video>
<div id="loading-overlay" class="loading-overlay">
<div class="spinner"></div>
<span id="loading-text">Select a source...</span>
</div>
</div>
<button id="toggle-episodes" class="toggle-episodes-btn">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="4" width="18" height="3" rx="1"/>
<rect x="3" y="10.5" width="18" height="3" rx="1"/>
<rect x="3" y="17" width="18" height="3" rx="1"/>
</svg>
<span>Episodes</span>
</button>
</div>
<div class="video-container">
<video id="player" controls crossorigin playsinline></video>
<div id="loading-overlay" class="loading-overlay">
<div class="spinner"></div>
<p id="loading-text">Select a source...</p>
</div>
</div>
<div class="controls-area">
<div class="episode-info">
<h2 id="anime-title">Loading...</h2>
<span id="episode-label">Episode --</span>
</div>
<div class="episode-controls">
<div class="episode-info">
<h1 id="anime-title">Loading...</h1>
<p id="episode-label">Episode --</p>
</div>
<div class="navigation-buttons">
<button class="nav-btn prev-btn" id="prev-btn">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M15 19l-7-7 7-7"/>
</svg>
<span>Previous</span>
</button>
<button class="nav-btn next-btn" id="next-btn">
<span>Next</span>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M9 5l7 7-7 7"/>
</svg>
</button>
</div>
</div>
</section>
<aside id="episodes-sidebar" class="episodes-sidebar">
<div class="sidebar-header">
<h3>Episodes</h3>
<button id="close-sidebar" class="close-sidebar-btn" aria-label="Close episodes">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 6L6 18M6 6l12 12"/>
</svg>
</button>
</div>
<div class="sidebar-search">
<input type="text" id="episode-search" class="episode-search-input" placeholder="Search episode..." oninput="filterEpisodes()">
</div>
<div id="episode-list" class="episode-list"></div>
</aside>
</main>
<div class="nav-controls">
<button class="nav-btn" id="prev-btn">
<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M15 19l-7-7 7-7"/></svg>
Prev
</button>
<button class="nav-btn" id="next-btn">
Next
<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M9 5l7 7-7 7"/></svg>
</button>
</div>
</div>
</div>
<script src="../src/scripts/anime/player.js"></script>
<script>
const watchContainer = document.querySelector('.watch-container');
const sidebar = document.getElementById('episodes-sidebar');
const toggleBtn = document.getElementById('toggle-episodes');
const closeBtn = document.getElementById('close-sidebar');
const DESKTOP_BREAKPOINT = 1100;
function isDesktop() {
return window.innerWidth > DESKTOP_BREAKPOINT;
}
const toggleSidebar = () => {
const isOpen = sidebar.classList.contains('sidebar-open') ||
!watchContainer.classList.contains('sidebar-hidden');
if (isDesktop()) {
watchContainer.classList.toggle('sidebar-hidden');
toggleBtn.classList.toggle('active', !watchContainer.classList.contains('sidebar-hidden'));
} else {
sidebar.classList.toggle('sidebar-open');
toggleBtn.classList.toggle('active', sidebar.classList.contains('sidebar-open'));
}
};
toggleBtn.addEventListener('click', toggleSidebar);
closeBtn.addEventListener('click', () => {
if (isDesktop()) {
watchContainer.classList.add('sidebar-hidden');
toggleBtn.classList.remove('active');
} else {
sidebar.classList.remove('sidebar-open');
toggleBtn.classList.remove('active');
}
});
function handleResize() {
if (isDesktop()) {
sidebar.classList.remove('sidebar-open');
if (!watchContainer.classList.contains('sidebar-hidden')) {
toggleBtn.classList.add('active');
}
} else {
watchContainer.classList.remove('sidebar-hidden');
sidebar.classList.remove('sidebar-open');
toggleBtn.classList.remove('active');
}
}
window.addEventListener('resize', handleResize);
handleResize();
</script>
</body>
</html>