// =============================================== // JWT PARSER // =============================================== function parseJwt(token) { if (!token) return {}; try { const base64 = token.split('.')[1]; const json = atob(base64); return JSON.parse(json); } catch (e) { console.error("parseJwt error:", e); return {}; } } // =============================================== // GET PHOTO BY ID — con log puliti // =============================================== async function getPhotoById(id) { const token = localStorage.getItem("token"); const payload = parseJwt(token); const user = payload.name || "Common"; const url = `${BASE_URL}/photos/byIds?id=${encodeURIComponent(id)}&user=${encodeURIComponent(user)}`; console.log(`📥 [getPhotoById] Richiedo foto id=${id}`); let res; try { res = await fetch(url, { headers: { "Authorization": "Bearer " + token } }); } catch (e) { console.error("❌ [getPhotoById] ERRORE FETCH:", e); return []; } if (!res.ok) { console.error("❌ [getPhotoById] ERRORE HTTP:", res.status, res.statusText); return []; } try { const json = await res.json(); console.log(`📤 [getPhotoById] id=${id} → trovate ${json.length} foto`); return json; } catch (e) { console.error("❌ [getPhotoById] ERRORE JSON:", e); return []; } } // =============================================== // INCREMENTAL SYNC — versione completa e pulita // =============================================== async function incrementalSync() { console.log("=============================================="); console.log("🚀 incrementalSync() START"); const payload = parseJwt(localStorage.getItem("token")); const user = payload.name || "Common"; let lastSync = getLastSync(); const currentPhotos = getLocalPhotos(); console.log(`👤 Utente: ${user}`); console.log(`🕒 lastSync: ${lastSync}`); console.log(`📸 Foto locali attuali: ${currentPhotos.length}`); // ============================================================ // 1) FULL LOAD // ============================================================ if (!lastSync || currentPhotos.length === 0) { console.log("🟦 FULL LOAD → caricamento completo del DB"); try { const photos = await getAllPhotos(); console.log(`📥 FULL LOAD → ricevute ${photos.length} foto`); saveLocalState(); refreshGallery(); const now = new Date().toISOString(); setLastSync(now); console.log(`🕒 FULL LOAD → setLastSync = ${now}`); console.log("🏁 incrementalSync() COMPLETATO (fullLoad)"); console.log("=============================================="); return; } catch (err) { console.error("❌ [incrementalSync] ERRORE in fullLoad:", err); return; } } // ============================================================ // 2) SYNC INCREMENTALE // ============================================================ console.log("🟩 INCREMENTAL SYNC → controllo cambiamenti"); let changes; try { changes = await getChanges(lastSync, user); } catch (err) { console.error("❌ [incrementalSync] ERRORE getChanges:", err); return; } console.log(`📥 Cambiamenti ricevuti: ${changes?.changes?.length || 0}`); if (!changes || !changes.changes || changes.changes.length === 0) { console.log("🟨 Nessun cambiamento → lastSync NON aggiornato"); return; } // ============================================================ // 3) APPLICA CAMBIAMENTI // ============================================================ for (const ch of changes.changes) { console.log("----------------------------------------------"); console.log(`🔄 Cambio:`, ch); // FOTO AGGIUNTA if (ch.change_type === "added") { console.log(`🟢 Foto aggiunta → id=${ch.photo_id}`); try { const arr = await getPhotoById(ch.photo_id); if (arr.length) { console.log(`📸 Aggiungo foto id=${ch.photo_id} a localPhotos`); addPhotoLocal(arr[0]); } else { console.warn(`⚠️ Foto NON trovata nel server remoto per id=${ch.photo_id}`); } } catch (err) { console.error("❌ [incrementalSync] ERRORE getPhotoById:", err); } } // FOTO RIMOSSA if (ch.change_type === "removed") { console.log(`🔴 Foto rimossa → id=${ch.photo_id}`); removePhotoLocal(ch.photo_id); const el = document.getElementById("photo_" + ch.photo_id); if (el) { console.log(`🗑️ Rimuovo elemento DOM: ${el.id}`); el.remove(); } } } console.log(`📸 Foto locali dopo sync: ${getLocalPhotos().length}`); // ============================================================ // 4) REFRESH UI // ============================================================ console.log("🔄 refreshGallery()"); refreshGallery(); // ============================================================ // 5) AGGIORNA lastSync // ============================================================ const lastTimestamp = changes.changes.at(-1).timestamp || new Date().toISOString(); console.log(`🕒 Aggiorno lastSync → ${lastTimestamp}`); setLastSync(lastTimestamp); console.log("🏁 incrementalSync() COMPLETATO"); console.log("=============================================="); } // =============================================== // WEBSOCKET REAL-TIME — versione pulita // =============================================== function startWebSocket() { const token = localStorage.getItem("token"); if (!token) { console.error("❌ [WS] Nessun token JWT trovato"); return; } const payload = parseJwt(token); const user = payload.name || "Common"; console.log("🔌 [WS] Connessione a wss://prova-ws.patachina.it ..."); const ws = new WebSocket("wss://prova-ws.patachina.it"); ws.onopen = () => { console.log("🟢 [WS] Connesso → invio token JWT"); ws.send(JSON.stringify({ type: "auth", token })); }; ws.onmessage = async (ev) => { let msg; try { msg = JSON.parse(ev.data); } catch (e) { console.error("❌ [WS] Errore parsing JSON:", e); return; } console.log("📩 [WS] Messaggio ricevuto:", msg); if (msg.type === "photo_added") { console.log(`🟢 [WS] Foto aggiunta → id=${msg.photo_id}`); try { const arr = await getPhotoById(msg.photo_id); if (arr.length) { console.log("📸 [WS] Foto trovata → aggiorno localPhotos"); addPhotoLocal(arr[0]); refreshGallery(); } else { console.warn("⚠️ [WS] Foto non trovata nel server remoto"); } } catch (err) { console.error("❌ [WS] Errore getPhotoById:", err); } } }; ws.onclose = () => { console.warn("❌ [WS] Connessione chiusa → ritento tra 3s..."); setTimeout(startWebSocket, 3000); }; ws.onerror = (err) => { console.error("⚠️ [WS] Errore WebSocket:", err); }; } // Avvio automatico del WebSocket startWebSocket(); window.incrementalSync = incrementalSync; window.parseJwt = parseJwt;