// filePreview.js import { escapeHTML, showToast } from './domUtils.js?v={{APP_QVER}}'; import { t } from './i18n.js?v={{APP_QVER}}'; import { fileData, setFileProgressBadge, setFileWatchedBadge } from './fileListView.js?v={{APP_QVER}}'; // Build a preview URL that always goes through the API layer (respects ACLs/UPLOAD_DIR) export function buildPreviewUrl(folder, name) { const f = (!folder || folder === '') ? 'root' : String(folder); return `/api/file/download.php?folder=${encodeURIComponent(f)}&file=${encodeURIComponent(name)}&inline=1&t=${Date.now()}`; } // New: build a download URL (attachment) export function buildDownloadUrl(folder, name) { const f = (!folder || folder === '') ? 'root' : String(folder); const params = new URLSearchParams({ folder: f, file: name, inline: '0', t: String(Date.now()) }); return `/api/file/download.php?${params.toString()}`; } const MEDIA_VOLUME_KEY = 'frMediaVolume'; const MEDIA_MUTED_KEY = 'frMediaMuted'; function loadSavedMediaVolume(el) { if (!el) return; try { const v = localStorage.getItem(MEDIA_VOLUME_KEY); if (v !== null) { const vol = parseFloat(v); if (!Number.isNaN(vol)) { el.volume = Math.max(0, Math.min(1, vol)); } } const m = localStorage.getItem(MEDIA_MUTED_KEY); if (m !== null) { el.muted = (m === '1'); } } catch { // ignore storage errors } } function attachVolumePersistence(el) { if (!el) return; try { el.addEventListener('volumechange', () => { try { localStorage.setItem(MEDIA_VOLUME_KEY, String(el.volume)); localStorage.setItem(MEDIA_MUTED_KEY, el.muted ? '1' : '0'); } catch { // ignore storage errors } }); } catch { // ignore } } /* -------------------------------- Share modal (existing) -------------------------------- */ export function openShareModal(file, folder) { const existing = document.getElementById("shareModal"); if (existing) existing.remove(); const modal = document.createElement("div"); modal.id = "shareModal"; modal.classList.add("modal"); modal.innerHTML = `
`; document.body.appendChild(modal); modal.style.display = "block"; document.getElementById("closeShareModal").addEventListener("click", () => modal.remove()); document.getElementById("shareExpiration").addEventListener("change", e => { const container = document.getElementById("customExpirationContainer"); container.style.display = e.target.value === "custom" ? "block" : "none"; }); document.getElementById("generateShareLinkBtn").addEventListener("click", () => { const sel = document.getElementById("shareExpiration"); let value, unit; if (sel.value === "custom") { value = parseInt(document.getElementById("customExpirationValue").value, 10); unit = document.getElementById("customExpirationUnit").value; } else { value = parseInt(sel.value, 10); unit = "minutes"; } const password = document.getElementById("sharePassword").value; fetch("/api/file/createShareLink.php", { method: "POST", credentials: "include", headers: { "Content-Type": "application/json", "X-CSRF-Token": window.csrfToken }, body: JSON.stringify({ folder, file: file.name, expirationValue: value, expirationUnit: unit, password }) }) .then(res => res.json()) .then(data => { if (data.token) { const url = `${window.location.origin}/api/file/share.php?token=${encodeURIComponent(data.token)}`; document.getElementById("shareLinkInput").value = url; document.getElementById("shareLinkDisplay").style.display = "block"; } else { showToast(t("error_generating_share") + ": " + (data.error || "Unknown")); } }) .catch(err => { console.error(err); showToast(t("error_generating_share")); }); }); document.getElementById("copyShareLinkBtn").addEventListener("click", () => { const input = document.getElementById("shareLinkInput"); input.select(); document.execCommand("copy"); showToast(t("link_copied")); }); } /* -------------------------------- Media modal viewer -------------------------------- */ // Images that are safe to inline in