photo_server_json_flutter_c.../public/js/gallery.js

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;