release(v2.3.2): fix media preview URLs and tighten hover card layout

This commit is contained in:
Ryan
2025-12-03 01:25:20 -05:00
committed by GitHub
parent 909baed16c
commit 39e69882e5
4 changed files with 257 additions and 212 deletions

View File

@@ -1,5 +1,18 @@
# Changelog # Changelog
## Changes 12/3/2025 (v2.3.2)
release(v2.3.2): fix media preview URLs and tighten hover card layout
- Reuse the working preview URL as a base when stepping between images/videos
so next/prev navigation keeps using the same inline/download endpoint
- Preserve video progress tracking and watched badges while fixing black-screen
playback issues across browsers
- Slightly shrink the file hover preview card (width/height, grid columns,
gaps, snippet/props heights) for a more compact, less intrusive peek
---
## Changes 12/3/2025 (v2.3.1) ## Changes 12/3/2025 (v2.3.1)
release(v2.3.1): polish file list actions & hover preview peak release(v2.3.1): polish file list actions & hover preview peak

View File

@@ -393,17 +393,17 @@ function ensureHoverPreviewEl() {
const propsEl = el.querySelector(".hover-preview-props"); const propsEl = el.querySelector(".hover-preview-props");
if (card) { if (card) {
card.style.minWidth = "420px"; card.style.minWidth = "380px"; // was 420
card.style.maxWidth = "640px"; card.style.maxWidth = "600px"; // was 640
card.style.minHeight = "220px"; card.style.minHeight = "200px"; // was 220
card.style.padding = "10px 12px"; card.style.padding = "8px 10px"; // slightly tighter padding
card.style.overflow = "hidden"; card.style.overflow = "hidden";
} }
if (grid) { if (grid) {
grid.style.display = "grid"; grid.style.display = "grid";
grid.style.gridTemplateColumns = "220px minmax(260px, 1fr)"; grid.style.gridTemplateColumns = "200px minmax(240px, 1fr)"; // both columns ~9% smaller
grid.style.gap = "12px"; grid.style.gap = "10px";
grid.style.alignItems = "center"; grid.style.alignItems = "center";
} }
@@ -426,13 +426,14 @@ function ensureHoverPreviewEl() {
thumb.style.display = "flex"; thumb.style.display = "flex";
thumb.style.alignItems = "center"; thumb.style.alignItems = "center";
thumb.style.justifyContent = "center"; thumb.style.justifyContent = "center";
thumb.style.minHeight = "140px"; thumb.style.minHeight = "120px"; // was 140
thumb.style.marginBottom = "6px"; thumb.style.marginBottom = "4px"; // slightly tighter
} }
if (snippet) { if (snippet) {
snippet.style.marginTop = "4px"; snippet.style.marginTop = "4px";
snippet.style.maxHeight = "140px"; snippet.style.maxHeight = "120px";
snippet.style.overflow = "auto"; snippet.style.overflow = "auto";
snippet.style.fontSize = "0.78rem"; snippet.style.fontSize = "0.78rem";
snippet.style.whiteSpace = "pre-wrap"; snippet.style.whiteSpace = "pre-wrap";
@@ -464,9 +465,9 @@ function ensureHoverPreviewEl() {
} }
if (propsEl) { if (propsEl) {
propsEl.style.fontSize = "0.78rem"; propsEl.style.fontSize = "0.76rem";
propsEl.style.lineHeight = "1.3"; propsEl.style.lineHeight = "1.3";
propsEl.style.maxHeight = "160px"; propsEl.style.maxHeight = "140px";
propsEl.style.overflow = "auto"; propsEl.style.overflow = "auto";
propsEl.style.paddingRight = "4px"; propsEl.style.paddingRight = "4px";
propsEl.style.wordBreak = "break-word"; propsEl.style.wordBreak = "break-word";

View File

@@ -503,6 +503,23 @@ export function previewFile(fileUrl, fileName) {
const isVideo = VID_RE.test(lower); const isVideo = VID_RE.test(lower);
const isAudio = AUD_RE.test(lower); const isAudio = AUD_RE.test(lower);
// Base preview URL from the link we clicked
const baseUrl = fileUrl;
// Use the same preview endpoint, just swap the "file" param.
function siblingPreviewUrl(newName) {
try {
const u = new URL(baseUrl, window.location.origin);
u.searchParams.set('file', newName);
// cache-bust so we dont get stale frames
u.searchParams.set('t', String(Date.now()));
return u.toString();
} catch {
// Fallback: go through generic download/inline endpoint
return buildPreviewUrl(folder, newName);
}
}
setTitle(overlay, name); setTitle(overlay, name);
if (isSvg) { if (isSvg) {
const downloadBtn = makeDownloadButton(folder, () => name); const downloadBtn = makeDownloadButton(folder, () => name);
@@ -582,7 +599,7 @@ const navigate = (dir) => {
img.dataset.scale = 1; img.dataset.scale = 1;
img.dataset.rotate = 0; img.dataset.rotate = 0;
img.style.transform = 'scale(1) rotate(0deg)'; img.style.transform = 'scale(1) rotate(0deg)';
img.src = buildPreviewUrl(folder, newFile); img.src = siblingPreviewUrl(newFile); // <-- changed
}; };
if (images.length > 1) { if (images.length > 1) {
@@ -611,7 +628,7 @@ const navigate = (dir) => {
} }
/* -------------------- VIDEOS -------------------- */ /* -------------------- VIDEOS -------------------- */
if (isVideo) { if (isVideo) {
let video = document.createElement("video"); let video = document.createElement("video");
video.controls = true; video.controls = true;
video.preload = 'auto'; // hint browser to start fetching quickly video.preload = 'auto'; // hint browser to start fetching quickly
@@ -624,28 +641,42 @@ const navigate = (dir) => {
loadSavedMediaVolume(video); loadSavedMediaVolume(video);
attachVolumePersistence(video); attachVolumePersistence(video);
// Top-right action icons (Material icons, theme-aware)
const markBtnIcon = makeTopIcon('check_circle', t("mark_as_viewed") || "Mark as viewed"); const markBtnIcon = makeTopIcon('check_circle', t("mark_as_viewed") || "Mark as viewed");
const clearBtnIcon = makeTopIcon('restart_alt', t("clear_progress") || "Clear progress"); const clearBtnIcon = makeTopIcon('restart_alt', t("clear_progress") || "Clear progress");
// Track which file is currently active // Track which file is currently active
let currentName = name; let currentName = name;
const downloadBtn = makeDownloadButton(folder, () => currentName); // Use the URL we were passed in (old behavior) for the *first* video,
// fall back to API URL if for some reason it's empty.
const initialUrl = fileUrl && fileUrl.trim()
? fileUrl
: buildPreviewUrl(folder, name);
// Order: Download | Mark | Reset const downloadBtn = makeDownloadButton(folder, () => currentName);
actionWrap.appendChild(downloadBtn);
actionWrap.appendChild(markBtnIcon);
actionWrap.appendChild(clearBtnIcon);
const videos = (Array.isArray(fileData) ? fileData : []).filter(f => VID_RE.test(f.name)); // Order: Download | Mark | Reset
overlay.mediaType = 'video'; actionWrap.appendChild(downloadBtn);
overlay.mediaList = videos; actionWrap.appendChild(markBtnIcon);
overlay.mediaIndex = Math.max(0, videos.findIndex(f => f.name === name)); actionWrap.appendChild(clearBtnIcon);
setNavVisibility(overlay, videos.length > 1, videos.length > 1);
const videos = (Array.isArray(fileData) ? fileData : []).filter(f => VID_RE.test(f.name));
overlay.mediaType = 'video';
overlay.mediaList = videos;
overlay.mediaIndex = Math.max(0, videos.findIndex(f => f.name === name));
setNavVisibility(overlay, videos.length > 1, videos.length > 1);
// Helper: set src for a given video name
const setVideoSrc = (nm) => { const setVideoSrc = (nm) => {
currentName = nm; currentName = nm;
video.src = buildPreviewUrl(folder, nm);
// For the current file, reuse the original working URL.
// For other files (next/prev), go through the API.
const url = (nm === name) ? initialUrl : buildPreviewUrl(folder, nm);
video.src = url;
video.src = siblingPreviewUrl(nm);
setTitle(overlay, nm); setTitle(overlay, nm);
}; };
@@ -790,7 +821,6 @@ setNavVisibility(overlay, videos.length > 1, videos.length > 1);
if (!overlay.mediaList || overlay.mediaList.length < 2) return; if (!overlay.mediaList || overlay.mediaList.length < 2) return;
overlay.mediaIndex = (overlay.mediaIndex + dir + overlay.mediaList.length) % overlay.mediaList.length; overlay.mediaIndex = (overlay.mediaIndex + dir + overlay.mediaList.length) % overlay.mediaList.length;
const nm = overlay.mediaList[overlay.mediaIndex].name; const nm = overlay.mediaList[overlay.mediaIndex].name;
currentName = nm; // keep download button in sync
setVideoSrc(nm); setVideoSrc(nm);
renderStatus(null); renderStatus(null);
}; };
@@ -810,11 +840,12 @@ setNavVisibility(overlay, videos.length > 1, videos.length > 1);
overlay._onKey = onKey; overlay._onKey = onKey;
} }
// Kick off first video using the original working URL
setVideoSrc(name); setVideoSrc(name);
renderStatus(null); renderStatus(null);
overlay.style.display = "flex"; overlay.style.display = "flex";
return; return;
} }
/* -------------------- AUDIO / OTHER -------------------- */ /* -------------------- AUDIO / OTHER -------------------- */
if (isAudio) { if (isAudio) {

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# === Update FileRise to v2.1.0 (safe rsync, no composer on demo) === # === Update FileRise to v2.3.2 (safe rsync, no composer on demo) ===
set -Eeuo pipefail set -Eeuo pipefail
VER="v2.1.0" VER="v2.3.2"
ASSET="FileRise-${VER}.zip" # matches GitHub release asset name ASSET="FileRise-${VER}.zip" # matches GitHub release asset name
WEBROOT="/var/www" WEBROOT="/var/www"