enhanced watch page
This commit is contained in:
205
views/watch.html
205
views/watch.html
@@ -25,30 +25,30 @@
|
||||
</a>
|
||||
</header>
|
||||
|
||||
<div class="ui-scale">
|
||||
|
||||
<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>
|
||||
<div class="ui-scale-wrapper">
|
||||
<main class="watch-container">
|
||||
|
||||
<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="anime-title-details">Loading...</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>
|
||||
<br>
|
||||
<p id="detail-description" class="details-description">Loading description...</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="player-section">
|
||||
|
||||
<div class="player-toolbar">
|
||||
|
||||
<div class="control-group">
|
||||
<div class="sd-toggle" id="sd-toggle" data-state="sub" onclick="toggleAudioMode()">
|
||||
<div class="sd-bg"></div>
|
||||
@@ -56,7 +56,6 @@
|
||||
<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>
|
||||
@@ -65,15 +64,6 @@
|
||||
<option value="" disabled selected>Source...</option>
|
||||
</select>
|
||||
</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">
|
||||
@@ -86,96 +76,113 @@
|
||||
|
||||
<div class="episode-controls">
|
||||
<div class="episode-info">
|
||||
<h1 id="anime-title">Loading...</h1>
|
||||
<h1 id="anime-title-details2">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>
|
||||
<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>
|
||||
|
||||
<div class="episode-carousel-compact">
|
||||
<div class="carousel-header">
|
||||
<h2>Episodes</h2>
|
||||
<div class="carousel-nav">
|
||||
<button class="carousel-arrow-mini" id="ep-prev-mini"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M15 18l-6-6 6-6"/></svg></button>
|
||||
<button class="carousel-arrow-mini" id="ep-next-mini"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M9 6l6 6-6 6"/></svg></button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="episode-carousel" class="episode-carousel-compact-list">
|
||||
</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>
|
||||
|
||||
<section class="anime-extra-content">
|
||||
<div class="content-container">
|
||||
<div class="characters-section">
|
||||
<div class="characters-header">
|
||||
<h2>Cast & Characters</h2>
|
||||
<button id="expand-characters-btn" class="expand-btn" data-expanded="false">
|
||||
<span>Show All</span>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 15l-6 6-6-6"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<div id="characters-list" class="characters-carousel">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</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;
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const carousel = document.getElementById('episode-carousel');
|
||||
if (!carousel) return;
|
||||
|
||||
function isDesktop() {
|
||||
return window.innerWidth > DESKTOP_BREAKPOINT;
|
||||
}
|
||||
const prevBtn = document.getElementById('ep-prev-mini');
|
||||
const nextBtn = document.getElementById('ep-next-mini');
|
||||
|
||||
const toggleSidebar = () => {
|
||||
const isOpen = sidebar.classList.contains('sidebar-open') ||
|
||||
!watchContainer.classList.contains('sidebar-hidden');
|
||||
const scrollAmount = 150;
|
||||
|
||||
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'));
|
||||
}
|
||||
};
|
||||
prevBtn?.addEventListener('click', () => {
|
||||
carousel.scrollBy({ left: -scrollAmount, behavior: 'smooth' });
|
||||
});
|
||||
|
||||
toggleBtn.addEventListener('click', toggleSidebar);
|
||||
nextBtn?.addEventListener('click', () => {
|
||||
carousel.scrollBy({ left: scrollAmount, behavior: 'smooth' });
|
||||
});
|
||||
|
||||
const updateArrows = () => {
|
||||
if (!prevBtn || !nextBtn) return;
|
||||
|
||||
prevBtn.style.opacity = carousel.scrollLeft <= 10 ? '0.3' : '1';
|
||||
prevBtn.style.pointerEvents = carousel.scrollLeft <= 10 ? 'none' : 'auto';
|
||||
|
||||
const atEnd = carousel.scrollLeft + carousel.clientWidth >= carousel.scrollWidth - 10;
|
||||
nextBtn.style.opacity = atEnd ? '0.3' : '1';
|
||||
nextBtn.style.pointerEvents = atEnd ? 'none' : 'auto';
|
||||
};
|
||||
|
||||
carousel.addEventListener('scroll', updateArrows);
|
||||
window.addEventListener('resize', updateArrows);
|
||||
|
||||
const observer = new MutationObserver((mutations, obs) => {
|
||||
updateArrows();
|
||||
obs.disconnect();
|
||||
|
||||
});
|
||||
observer.observe(carousel, { childList: true });
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const expandBtn = document.getElementById('expand-characters-btn');
|
||||
const characterList = document.getElementById('characters-list');
|
||||
const btnText = expandBtn?.querySelector('span');
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
handleResize();
|
||||
if (!expandBtn || !characterList) return;
|
||||
|
||||
expandBtn.addEventListener('click', () => {
|
||||
const isExpanded = expandBtn.getAttribute('data-expanded') === 'true';
|
||||
|
||||
if (isExpanded) {
|
||||
|
||||
characterList.classList.remove('expanded');
|
||||
expandBtn.setAttribute('data-expanded', 'false');
|
||||
if (btnText) btnText.innerText = 'Show All';
|
||||
} else {
|
||||
|
||||
characterList.classList.add('expanded');
|
||||
expandBtn.setAttribute('data-expanded', 'true');
|
||||
if (btnText) btnText.innerText = 'Show Less';
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user