Add video viewer modal for gallery videos
All checks were successful
Build and Push Frontend Docker Image / build (push) Successful in 30s
All checks were successful
Build and Push Frontend Docker Image / build (push) Successful in 30s
- Click on video thumbnail to open in large viewer - Video plays on hover, pauses when mouse leaves - Close viewer by clicking X or clicking outside video Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -427,7 +427,7 @@ function renderGallery(container, items) {
|
||||
<div class="gallery-item">
|
||||
<div class="gallery-item-media">
|
||||
${item.status === 'completed'
|
||||
? `<video src="/api/content/${item.id}/stream" muted loop onmouseenter="this.play()" onmouseleave="this.pause()"></video>`
|
||||
? `<video src="/api/content/${item.id}/stream" muted loop data-content-id="${item.id}"></video>`
|
||||
: '<div style="display:flex;align-items:center;justify-content:center;height:100%;color:var(--gray-500)">' + item.status + '</div>'
|
||||
}
|
||||
<span class="gallery-item-status ${item.status}">${item.status}</span>
|
||||
@@ -445,6 +445,19 @@ function renderGallery(container, items) {
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
// Video hover play/pause and click to view
|
||||
container.querySelectorAll('.gallery-item-media video').forEach(video => {
|
||||
video.addEventListener('mouseenter', () => video.play());
|
||||
video.addEventListener('mouseleave', () => {
|
||||
video.pause();
|
||||
video.currentTime = 0;
|
||||
});
|
||||
video.addEventListener('click', () => {
|
||||
const contentId = video.dataset.contentId;
|
||||
openVideoViewer(`/api/content/${contentId}/stream`);
|
||||
});
|
||||
});
|
||||
|
||||
container.querySelectorAll('.delete-content-btn').forEach(btn => {
|
||||
btn.addEventListener('click', async function() {
|
||||
const contentId = parseInt(this.dataset.contentId, 10);
|
||||
@@ -673,6 +686,28 @@ document.getElementById('modal-overlay').addEventListener('click', (e) => {
|
||||
if (e.target === e.currentTarget) hideModal();
|
||||
});
|
||||
|
||||
// Video Viewer
|
||||
const videoViewer = document.getElementById('video-viewer');
|
||||
const videoViewerPlayer = document.getElementById('video-viewer-player');
|
||||
const videoViewerClose = document.getElementById('video-viewer-close');
|
||||
|
||||
function openVideoViewer(src) {
|
||||
videoViewerPlayer.src = src;
|
||||
videoViewer.classList.remove('hidden');
|
||||
videoViewerPlayer.play();
|
||||
}
|
||||
|
||||
function closeVideoViewer() {
|
||||
videoViewerPlayer.pause();
|
||||
videoViewerPlayer.src = '';
|
||||
videoViewer.classList.add('hidden');
|
||||
}
|
||||
|
||||
videoViewerClose.addEventListener('click', closeVideoViewer);
|
||||
videoViewer.addEventListener('click', (e) => {
|
||||
if (e.target === videoViewer) closeVideoViewer();
|
||||
});
|
||||
|
||||
// Pagination
|
||||
function renderPagination(container, pagination, loadFn) {
|
||||
const { page, totalPages } = pagination;
|
||||
|
||||
Reference in New Issue
Block a user