Perfetto Fabio — ti preparo **la guida completa, chiara e pratica** per integrare il tuo **viewer Flutter Android** con il **WebSocket del tuo server Node.js**, così come funziona oggi nel tuo backend. Ti spiego: 1. **Come si autentica il client Flutter** 2. **Come si connette al WebSocket** 3. **Quali messaggi riceve** (formato esatto) 4. **Come deve rispondere** 5. **Come integrare tutto nel viewer** Tutto basato sul tuo backend reale. --- # ⭐ 1. COME SI AUTENTICA IL CLIENT FLUTTER Il tuo server usa JWT. ### Passi: 1. Flutter fa login via HTTP: ``` POST /auth/login { "email": "...", "password": "..." } ``` 2. Il server risponde: ```json { "token": "", "name": "Fabio" } ``` 3. Flutter salva il token. 4. **Ogni chiamata HTTP successiva** deve avere: ``` Authorization: Bearer ``` --- # ⭐ 2. COME SI CONNETTE AL WEBSOCKET Il tuo server WebSocket accetta connessioni così: ``` ws://:/?token= ``` Quindi in Flutter: ```dart import 'package:web_socket_channel/web_socket_channel.dart'; final channel = WebSocketChannel.connect( Uri.parse("ws://192.168.1.10:4000/?token=$jwt"), ); ``` ### Importante: - Devi passare **lo stesso JWT** usato per le API HTTP. - Il server autentica il token e associa la connessione all’utente. --- # ⭐ 3. QUALI MESSAGGI RICEVE FLUTTER (FORMATO ESATTO) Il tuo backend invia questi eventi: ### 📌 Quando una foto viene aggiunta ```json { "type": "added", "id": "12345" } ``` ### 📌 Quando una foto viene rimossa (DEL) ```json { "type": "removed", "id": "12345" } ``` ### 📌 Quando una cartella viene aggiunta (ADD_DIR) ```json { "type": "add_dir", "folder": "Vacanze/2024" } ``` ### 📌 Quando una cartella viene rimossa (DEL_DIR) ```json { "type": "del_dir", "folder": "Vacanze/2024" } ``` ### 📌 Quando una foto viene soft-deleted / restored ```json { "type": "updated", "id": "12345", "deleted_at": "2026-03-31T10:00:00Z" // oppure null } ``` --- # ⭐ 4. COME FLUTTER DEVE GESTIRE I MESSAGGI Esempio completo: ```dart channel.stream.listen((message) { final data = jsonDecode(message); switch (data["type"]) { case "added": // Scarica la foto via /photos/:id fetchPhoto(data["id"]); break; case "removed": // Rimuovi la foto dalla UI removePhotoFromUI(data["id"]); break; case "updated": // Aggiorna soft delete updatePhotoState(data["id"], data["deleted_at"]); break; case "add_dir": // Aggiorna lista cartelle addFolderToUI(data["folder"]); break; case "del_dir": // Rimuovi cartella dalla UI removeFolderFromUI(data["folder"]); break; } }); ``` --- # ⭐ 5. COME DEVE RISPONDERE FLUTTER AL SERVER Il tuo server **non richiede risposte** dal client WebSocket. È **one-way**: - Il server invia eventi - Il client li riceve - Il client aggiorna la UI Flutter **non deve inviare nulla** al WebSocket. --- # ⭐ 6. COME INTEGRARE TUTTO NEL VIEWER ### Al login: - fai login HTTP - salva il JWT - apri il WebSocket ### All’avvio del viewer: 1. Carica tutte le foto via: ``` GET /photos ``` 2. Avvia il WebSocket 3. Applica in tempo reale: - added → aggiungi foto - removed → rimuovi foto - updated → aggiorna stato - add_dir → aggiungi cartella - del_dir → rimuovi cartella ### Dopo 2 minuti (quando WS non è più affidabile): - usa progressive sync: ``` GET /photos/changes?since= GET /photos/deleted_hard?since= ``` ---