204 lines
No EOL
6.1 KiB
JavaScript
204 lines
No EOL
6.1 KiB
JavaScript
// ===============================
|
|
// 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; |