diff --git a/resources/logic_ui.js b/resources/logic_ui.js
index 6cb2456..6ec8db4 100644
--- a/resources/logic_ui.js
+++ b/resources/logic_ui.js
@@ -558,7 +558,7 @@ function initFilters() {
if (!activeData || activeData.length === 0) return;
// Ensure all filter Sets exist (add new ones if missing)
- const filterKeys = ['model', 'sampler', 'scheduler', 'denoise', 'lora', 'positive', 'negative', 'size', 'seed', 'steps', 'cfg', 'upscaleMethod'];
+ const filterKeys = ['model', 'sampler', 'scheduler', 'denoise', 'lora', 'positive', 'negative', 'size', 'seed', 'steps', 'cfg', 'upscaleMethod', 'mediaType'];
filterKeys.forEach(key => {
if (!filters.hasOwnProperty(key) || !(filters[key] instanceof Set)) {
filters[key] = new Set();
@@ -586,6 +586,7 @@ function initFilters() {
const shortModel = model ? String(model).replace(/\\/g, '/').split('/').pop().replace(/\.[^.]+$/, '') : '';
return shortModel ? `${mode} + ${shortModel}` : mode || 'Upscaled';
}
+ if (key === 'mediaType') return d.media_type || 'image';
return d[key];
}))].sort();
@@ -1284,14 +1285,11 @@ function createCard(d) {
Size: ${d.width}x${d.height} Seed: ${d.seed}
`;
- // For videos: hover-play, click for fullscreen, update aspect ratio once metadata loads
+ // For videos: autoplay when visible is handled by videoAutoplayObserver in logic_virtual.js.
+ // This block wires click-to-fullscreen and loadedmetadata aspect ratio update.
if (isVideo) {
const videoEl = card.querySelector('video');
if (videoEl) {
- card.addEventListener('mouseenter', function() { videoEl.play().catch(function() {}); });
- card.addEventListener('mouseleave', function() {
- if (!document.fullscreenElement) { videoEl.pause(); videoEl.currentTime = 0; }
- });
// Click: open native fullscreen with browser controls
videoEl.addEventListener('click', function(e) {
e.stopPropagation();
@@ -1301,7 +1299,7 @@ function createCard(d) {
});
// Remove controls when exiting fullscreen
videoEl.addEventListener('fullscreenchange', function() {
- if (!document.fullscreenElement) { videoEl.controls = false; videoEl.pause(); }
+ if (!document.fullscreenElement) { videoEl.controls = false; }
});
videoEl.addEventListener('loadedmetadata', function() {
if (videoEl.videoWidth && videoEl.videoHeight) {
diff --git a/resources/logic_virtual.js b/resources/logic_virtual.js
index a0f7a04..0c40fca 100644
--- a/resources/logic_virtual.js
+++ b/resources/logic_virtual.js
@@ -145,6 +145,25 @@ const imageObserver = new IntersectionObserver((entries) => {
});
}, { rootMargin: '400px' });
+// --- VIDEO AUTOPLAY OBSERVER ---
+// Autoplay videos whose cards are visible in the viewport.
+// Pauses (and resets) videos that scroll off screen to save bandwidth/CPU.
+const videoAutoplayObserver = new IntersectionObserver((entries) => {
+ entries.forEach(entry => {
+ const vid = entry.target;
+ if (entry.isIntersecting) {
+ // Ensure src is loaded (lazy loader may not have fired yet)
+ if (vid.dataset.src && !vid.src) {
+ vid.src = vid.dataset.src;
+ }
+ vid.play().catch(() => { /* browser may block until user interaction */ });
+ } else {
+ vid.pause();
+ vid.currentTime = 0;
+ }
+ });
+}, { rootMargin: '0px', threshold: 0.25 });
+
// --- CALCULATE VISIBLE RANGE ---
function calculateVisibleRange() {
const viewport = document.getElementById('viewport');
@@ -246,6 +265,12 @@ function renderVisibleItems(forcePositionUpdate = false) {
toRemove.forEach(id => {
const node = nodeMap.get(id);
if (node) {
+ // Stop observing any video in this card and pause playback
+ const vid = node.querySelector('video');
+ if (vid) {
+ try { videoAutoplayObserver.unobserve(vid); } catch (e) {}
+ vid.pause();
+ }
if (_cardPool.length < MAX_POOL_SIZE) {
// Pool the card for reuse instead of destroying
node.style.display = 'none';
@@ -309,10 +334,11 @@ function renderVisibleItems(forcePositionUpdate = false) {
img.src = img.dataset.src;
img.onload = () => img.style.opacity = '1';
}
- // Lazy-load videos too (same data-src → src pattern)
- const vid = card.querySelector('video[data-src]');
- if (vid && !vid.src) {
- vid.src = vid.dataset.src;
+ // Videos: observe for autoplay-when-visible. Observer handles
+ // lazy src loading on first intersection too.
+ const vid = card.querySelector('video');
+ if (vid) {
+ videoAutoplayObserver.observe(vid);
}
} else {