// =============================== // GALLERY — con SYNC INCREMENTALE + REFRESH DA .ENV // =============================== let currentUser = null; let refreshSeconds = 30; // =============================== // 3. ORDINAMENTO // =============================== function sortByDate(photos, direction = "desc") { return photos.slice().sort((a, b) => { const da = a?.taken_at ? new Date(a.taken_at) : 0; const db = b?.taken_at ? new Date(b.taken_at) : 0; return direction === "asc" ? (da - db) : (db - da); }); } // =============================== // 4. FILTRI // =============================== function applyFilters(photos) { if (!window.currentFilter) return photos; switch (window.currentFilter) { case "folder": return photos.filter(p => p.cartella); case "location": return photos.filter(p => p.lat && p.lon); case "type": return photos.filter(p => p?.mime_type?.startsWith("image/")); default: return photos; } } // =============================== // 5. RAGGRUPPAMENTO // =============================== function groupByDate(photos, mode = "auto") { const sections = []; const now = new Date(); function getLabel(photo) { const date = photo?.taken_at ? new Date(photo.taken_at) : null; if (!date || isNaN(+date)) return "Senza data"; const diffDays = Math.floor((now - date) / (1000 * 60 * 60 * 24)); if (mode === "day") return formatDay(date); if (mode === "month") return formatMonth(date); if (mode === "year") return date.getFullYear().toString(); if (diffDays === 0) return "Oggi"; if (diffDays === 1) return "Ieri"; if (diffDays <= 7) return "Questa settimana"; if (diffDays <= 14) return "La settimana scorsa"; if (diffDays <= 30) return "Questo mese"; if (diffDays <= 60) return "Mese scorso"; if (date.getFullYear() === now.getFullYear()) return formatMonth(date); return date.getFullYear().toString(); } photos.forEach(photo => { const label = getLabel(photo); let section = sections.find(s => s.label === label); if (!section) { section = { label, photos: [] }; sections.push(section); } section.photos.push(photo); }); return sections; } // =============================== // 6. FORMATTATORI // =============================== function formatDay(date) { return date.toLocaleDateString("it-IT", { weekday: "long", day: "numeric", month: "long" }); } function formatMonth(date) { return date.toLocaleDateString("it-IT", { month: "long", year: "numeric" }); } // =============================== // 7. RENDER GALLERY // =============================== function renderGallery(sections) { const gallery = document.getElementById("gallery"); if (!gallery) return; gallery.innerHTML = ""; sections.forEach(section => { const h = document.createElement("h2"); h.className = "gallery-section-title"; h.textContent = section.label; gallery.appendChild(h); const container = document.createElement("div"); container.className = "gallery-section"; section.photos.forEach((photo, idx) => { const thumbDiv = document.createElement("div"); thumbDiv.className = "thumb"; thumbDiv.id = "photo_" + photo.id; let th1 = photo?.thub1; let th2 = photo?.thub2 || photo?.thub1; let original = photo?.path; const img = document.createElement("img"); img.src = th1 || th2 || original || ""; img.alt = photo?.name || ""; img.loading = "lazy"; thumbDiv.appendChild(img); if (photo?.mime_type?.startsWith("video/")) { const play = document.createElement("div"); play.className = "play-icon"; play.textContent = "▶"; thumbDiv.appendChild(play); } thumbDiv.addEventListener("click", () => { window.closeBottomSheet?.(); if (typeof window.openModalFromList === "function") { window.openModalFromList(section.photos, idx); } else { window.openModal?.(original, th2, photo); } }); container.appendChild(thumbDiv); }); gallery.appendChild(container); }); } // =============================== // 8. REFRESH GALLERY // =============================== function refreshGallery() { const photos = getLocalPhotos(); // 🔥 USO DELLO STATO UNICO console.log("[refreshGallery] numero foto:", photos.length); const filtered = applyFilters(photos); const sorted = sortByDate(filtered, "desc"); const sections = groupByDate(sorted, "auto"); renderGallery(sections); } // =============================== // 9. INIZIALIZZAZIONE GALLERY // =============================== async function initGallery() { console.log("=== INIT GALLERY ==="); console.log("[initGallery] Chiamo /config..."); const cfg = await fetch("/config").then(r => r.json()); console.log("[initGallery] /config RISPOSTA:", cfg); window.PATH_FULL = cfg.pathFull; currentUser = cfg?.user || "Common"; refreshSeconds = cfg.galleryRefreshSeconds || 30; console.log("[initGallery] currentUser =", currentUser); console.log("[initGallery] refreshSeconds =", refreshSeconds); console.log("[initGallery] Avvio incrementalSync() iniziale..."); await incrementalSync(); console.log("[initGallery] incrementalSync() iniziale COMPLETATO"); // =============================================== // 🛟 POLLING DI SICUREZZA (configurabile da .env) // =============================================== if (refreshSeconds > 0) { console.log(`[initGallery] Polling attivo ogni ${refreshSeconds} secondi...`); setInterval(async () => { console.log(">>> TIMER: chiamata incrementalSync()"); console.log(">>> lastSync attuale =", getLastSync()); await incrementalSync(); console.log(">>> incrementalSync() COMPLETATO (timer)"); }, refreshSeconds * 1000); } else { console.log("[initGallery] Polling disattivato (refreshSeconds = 0)"); } } window.addEventListener("DOMContentLoaded", initGallery); // EXPORT window.sortByDate = sortByDate; window.applyFilters = applyFilters; window.groupByDate = groupByDate; window.renderGallery = renderGallery; window.refreshGallery = refreshGallery;