Commit Graph

37 Commits

Author SHA1 Message Date
Stefan Hacker 23563622f8 feat: Lock-Badge + smartes Kontextmenue in lokaler Client-Ansicht
Die lokale Dateiliste im Client zeigt jetzt pro Datei ein 🔒-Badge
mit Nutzername wenn ausgecheckt (wie Server-Ansicht + Web-GUI).
browse_sync_folder zieht den Server-Tree bei jedem Aufruf und
korreliert via Journal-Lookup (oder .cloud-Metadaten) die lokale
Datei mit dem File-Lock-Status.

Rechtsklick-Menue reagiert jetzt auf den Lock-Status:
- Frei              -> "Auschecken (sperren)"
- Eigener/fremder   -> "Entsperren (einchecken)"
Neuer Tauri-Command lock_file_cmd fuer reines Sperren ohne Oeffnen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:32:01 +02:00
Stefan Hacker 8c7a14c38f fix: Server-Ansicht aktualisiert Lock-Status sofort via SSE
Die Server-Dateiliste im Client wartete bisher auf einen abgeschlossenen
Sync-Durchlauf, bevor Lock-Aenderungen anderer Nutzer sichtbar wurden.
Ausloeser von Events ohne Datei-Download (reine Lock/Unlock-Events)
landeten teils gar nicht in der UI.

Frontend hoert jetzt direkt auf das sse-event vom Backend und ruft
loadFileTree + loadLocalFiles auf - damit Lock-Icons im Server-Tree
in Echtzeit erscheinen/verschwinden.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:18:34 +02:00
Stefan Hacker 6c9daa5783 feat: Offline-Dateien werden beim erneuten Oeffnen wieder ausgecheckt
Bisher hat der Client nur beim ersten Oeffnen (.cloud-Platzhalter ->
Download) gesperrt. Nach dem Einchecken und erneutem Doppelklick
blieb die Datei ungesperrt, weil der Open-Pfad fehlte.

Neuer Tauri-Command open_offline_file loest die Server-Datei-ID
ueber das Sync-Journal auf, sperrt auf dem Server und oeffnet
lokal mit der Standard-App. Im lokalen Dateibrowser:
- Doppelklick auf eine bereits offline vorhandene Datei checkt sie
  nun aus und oeffnet sie (vorher: keine Reaktion)
- Rechtsklick-Menue hat "Oeffnen (auschecken)" fuer Offline-Dateien

Das Lock triggert wie gehabt notify_file_change -> SSE -> Web-UI
aktualisiert den Lock-Status sofort.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:09:06 +02:00
Stefan Hacker 5f905b4925 fix: Sync-Fehler "error decoding response body" + Server-Edits
Drei Probleme in einem:

1. create_folder/get_sync_tree parsten die Response auch bei HTTP-
   Fehlern als JSON. Bei 401/409/etc. kam "error decoding response
   body" statt der eigentlichen Fehlermeldung. Status wird jetzt
   zuerst geprueft, Body-Text wird bei Fehlern zurueckgegeben.

2. Ohne Journal-Eintrag und unterschiedlichen Hashes wurde vorher
   eine Konflikt-Kopie erstellt. Fuer Server-Edits aus dem Web-UI
   (wo der Client die Datei gar nie mit Journal erfasst hatte) war
   das falsch. Nextcloud-Ansatz: beim Erstkontakt Server
   autoritativ - Download statt Konflikt-Kopie.

3. run_sync_now uebernimmt neu konfigurierte sync_paths aus dem
   State, damit manuelle Syncs auch nach add_sync_path greifen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 10:25:01 +02:00
Stefan Hacker 5ba007ef51 fix: Borrow-Checker in Background-Sync-Thread
Temporary-Drop-Order: MutexGuard hielt Referenz auf State-Binding,
das am Block-Ende schon fallen gelassen wurde. Zwischenvariable
erzwingt Drop der MutexGuard vor dem Binding.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 09:57:06 +02:00
Stefan Hacker 50385faa02 feat: Echtzeit-Sync via SSE + Journal-basierter 3-Wege-Vergleich
Desktop-Client komplett ueberarbeitet nach Nextcloud-Vorbild:
- Persistentes SQLite-Journal (journal.rs) speichert letzten bekannten
  Stand pro Datei - ueberlebt Client-Neustarts (Hauptbug behoben).
- Engine.rs neu: 3-Wege-Vergleich Local <-> Journal <-> Server mit
  sauberer Konflikt-Kopie (inkl. Username + Zeitstempel).
- Loesch-Propagation: Lokal geloeschte Dateien landen im Server-
  Papierkorb des Owners (auch bei Freigaben). Auf dem Server
  geloeschte Dateien werden lokal entfernt.
- Lock-Flow repariert: frischer Token bei jedem Call, Fehler-Feedback.

Echtzeit-Sync:
- Backend: SSE-Endpoint /api/sync/events mit In-Memory-Broadcaster.
  Events bei Create/Update/Delete/Lock/Unlock, Zustellung an Owner
  plus alle User mit Share-Permission.
- Client: persistente SSE-Verbindung mit Auto-Reconnect. Events
  triggern sofortigen Sync (<100ms). 30s-Polling bleibt als
  Fallback fuer Netzwerk-Aussetzer.

Weitere Fixes:
- /api/sync/tree filtert is_trashed=False (Papierkorb wird nicht
  mehr an Clients gesynct).
- Web-GUI: Lock/Unlock-Buttons pro Datei, Admin darf fremde Locks
  zwangsweise loesen. Rename/Delete disabled bei fremdem Lock.
- Lock-Check im Backend bei PUT/DELETE (423 Locked Response).
- Background-Sync nur noch einmal pro Prozess gestartet, liest
  sync_paths pro Iteration neu - add/remove wirkt sofort, kein
  Client-Neustart mehr noetig.
- Watcher werden pro Sync-Pfad individuell verwaltet.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 09:50:44 +02:00
Stefan Hacker 2bd8a2e1b5 feat: Heartbeat fuer Locks - vergessene Locks laufen nach 15 Min ab
Wenn jemand vergisst zu entsperren:
- Client laeuft -> Heartbeat alle 60s -> Lock bleibt aktiv
- Client geschlossen -> kein Heartbeat -> Lock laeuft nach 15 Min ab
- Laptop zugeklappt -> gleicher Effekt -> 15 Min -> frei

Tracking: locked_files Vec merkt sich welche Dateien wir gesperrt haben.
Heartbeat laeuft im Token-Refresh Thread mit (alle 60s Heartbeat,
alle 10 Min Token-Refresh).

Lock wird beim Oeffnen getrackt, beim Entsperren/Unmark-Offline entfernt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 03:04:28 +02:00
Stefan Hacker 597dafc461 feat: File Lock beim Oeffnen + Entsperren per Rechtsklick
Beim Oeffnen einer .cloud-Datei:
- Download + Datei bleibt lokal (wie bisher)
- Lock wird auf dem Server gesetzt (andere sehen "gesperrt von X")
- Kein Auto-Unlock - Datei bleibt gesperrt bis manuell entsperrt

Rechtsklick im Datei-Browser auf Offline-Dateien:
- "Entsperren (Freigeben fuer andere)" - hebt den Lock auf
- "Nicht mehr offline" - .cloud zurueck + automatisch unlock

So bleiben Dateien gesperrt solange man daran arbeitet.
Wenn fertig: Rechtsklick -> Entsperren. Einfach und explizit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 03:03:01 +02:00
Stefan Hacker 0845659c84 refactor: Auto-Close komplett entfernt - Nextcloud-Ansatz
.cloud oeffnen = Download + Datei bleibt als echte Datei (wie Nextcloud).
Aenderungen werden automatisch vom Watcher gesynct.
"Nicht mehr offline" per Rechtsklick im Datei-Browser -> .cloud zurueck.

Entfernt:
- Auto-Close Detection (is_file_in_use, OpenedFile tracking,
  Heartbeat, Lock/Unlock beim Oeffnen)
- Lock-Kommandos (lock_file_cmd, unlock_file_cmd)
- opened_files HashMap, locked_files Vec
- is_file_in_use Funktion
- ~100 Zeilen Code weniger

Beibehalten:
- Token-Refresh Thread (alle 10 Min)
- File-Locking API im Backend (wird vom Web-UI weiterhin genutzt)
- Watcher + Sofort-Sync
- mark_offline / unmark_offline Kommandos

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 03:01:02 +02:00
Stefan Hacker 763fd4d563 fix: Auto-Close erkennt Datei-Aktivitaet statt nur File-Lock
Problem: Notepad und die meisten Editoren halten keinen File-Lock.
is_file_in_use() fand sofort "nicht in Benutzung" und raeumte die
Datei auf bevor der User sie bearbeiten konnte.

Neuer Ansatz - drei Bedingungen muessen erfuellt sein:
1. Mindestens 30 Sekunden seit dem Oeffnen (Schutzzeit)
2. Kein File-Lock UND Dateigroesse unveraendert
3. Mindestens 2 Minuten seit der letzten Aenderung/Lock

Datei-Aktivitaet wird getrackt:
- Groesse aendert sich -> Timer zuruecksetzen
- File-Lock aktiv (Office) -> Timer zuruecksetzen
- Erst nach 2 Minuten Inaktivitaet -> Auto-Close

So funktioniert es fuer alle Programme:
- Office (haelt Lock): Lock verschwindet -> 2 Min warten -> Close
- Notepad (kein Lock): Letzte Groessenaenderung -> 2 Min -> Close
- Schnell oeffnen+schliessen: 30s Schutzzeit verhindert sofortiges Close

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:57:12 +02:00
Stefan Hacker 0714d96668 fix: .cloud Platzhalter werden bei Server-Aenderung aktualisiert
Vorher: Platzhalter wurde nur erstellt wenn er nicht existierte.
Wenn sich die Datei auf dem Server aenderte (neue Groesse, neuer
Checksum), blieb der Platzhalter mit den alten Metadaten.

Jetzt: Bei jedem Sync wird der Checksum im Platzhalter mit dem
Server-Checksum verglichen. Bei Unterschied -> Platzhalter neu
schreiben mit aktueller Groesse, Checksum und Datum.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:43:09 +02:00
Stefan Hacker b6afc05148 fix: .cloud Oeffnen - besseres Error-Handling + Fallback-Dateiname
- Dateiname: Erst aus JSON "name" Feld, Fallback: .cloud von Dateiname strippen
- Alle Fehler werden jetzt gemeldet statt verschluckt (download, lock, open)
- open::that Fehler wird zurueckgegeben statt ignoriert
- Ausfuehrliches Logging: Pfade, Groesse, Lock-Status
- Pruefung ob Download-Datei existiert bevor geoeffnet wird

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:41:58 +02:00
Stefan Hacker f71103185c fix: Borrow-Checker - sync_paths klonen vor der Iteration
Kann nicht &self.sync_paths iterieren und gleichzeitig &mut self
Methoden aufrufen. Clone der Liste loest den Konflikt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:21:51 +02:00
Stefan Hacker eb49a034ed fix: &self -> &mut self fuer Methoden die known_checksums aendern
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:19:09 +02:00
Stefan Hacker 9ede2d6bdb fix: Sync-Richtung korrekt - Checksum-Tracking statt Timestamps
Problem: Timestamps waren unzuverlaessig fuer die Sync-Richtung
(Download setzt lokale mtime auf 'jetzt', Timezone-Differenzen).
Offline-markierte Dateien wurden nie vom Server aktualisiert.

Loesung: known_checksums HashMap trackt den Server-Checksum
beim letzten Sync. Bei unterschiedlichen Checksums:

| Lokal geaendert | Server geaendert | Aktion |
|-----------------|------------------|--------|
| Nein | Ja | Server->Lokal (Download) |
| Ja | Nein | Lokal->Server (Upload) |
| Ja | Ja | KONFLIKT (lokale Kopie umbenennen, Server runterladen) |

Erster Sync (kein known_checksum): Server gewinnt immer (Download).
Danach wird jeder Server-Checksum gespeichert.

Betrifft: sync_virtual, sync_upload_new, sync_full_upload

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:15:53 +02:00
Stefan Hacker b3da50e6ce fix: Server->Client Sync + File Locking repariert
Server->Client Sync:
- Server sendet Timestamps ohne Timezone (2026-04-11T12:49:24.735436)
- parse_from_rfc3339 braucht Timezone -> schlug still fehl
- Client dachte IMMER er sei neuer -> Upload statt Download
- Fix: parse_server_time() akzeptiert beides (mit/ohne Timezone)
- Probiert RFC3339, dann NaiveDateTime mit Microseconds, dann ohne

File Locking:
- open_cloud_file nutzte API-Clone vom SyncEngine (evtl. alter Token)
- Jetzt direkt state.api (immer aktueller Token nach Refresh)
- Lock wird zuverlaessig gesetzt beim Oeffnen von .cloud Dateien

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:05:10 +02:00
Stefan Hacker a445256d86 fix: Alle Rust-Warnings bereinigt
- unused variables: Underscore-Prefix (_real_path, _had_changes, _file_id)
- dead_code: #[allow(dead_code)] fuer zukuenftige Methoden
  (open_cloud_file, close_cloud_file, get_changes, LockResponse, SyncChangesResponse)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:02:53 +02:00
Stefan Hacker 0d1fc67287 fix: use std::path::Path Import fuer is_file_in_use
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:55:56 +02:00
Stefan Hacker 86545ca405 feat: Minimiert starten + kein Fenster-Popup bei .cloud Oeffnung
- .cloud Doppelklick oeffnet Datei im Hintergrund ohne das Client-
  Fenster aufzupoppen (war nervig)
- Neue Einstellung "Minimiert starten (direkt im System-Tray)"
  als Checkbox im Einstellungen-Bereich
- Wird in config.json gespeichert, bleibt bei Updates erhalten
- Bei aktiviertem Haken: Client startet unsichtbar im Tray,
  Sync laeuft im Hintergrund, Fenster nur per Tray-Doppelklick

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:50:09 +02:00
Stefan Hacker e9638cc6ed fix: Lock verschwindet nicht mehr - Token-Refresh + laengerer Timeout
Problem: Lock verschwand nach 5 Minuten weil:
1. JWT-Token nach 15 Min ablief -> Heartbeat schlug still fehl
2. Server gab Lock nach 5 Min ohne Heartbeat frei

Fix Client:
- Token-Refresh alle 10 Minuten (vor dem 15-Min-Ablauf)
- Aktualisiert den Token in der shared API-Instanz
- Heartbeat nutzt immer den aktuellen Token

Fix Backend:
- Lock-Timeout von 5 auf 15 Minuten erhoeht
- Genug Puffer fuer Netzwerk-Probleme oder kurze Unterbrechungen

Timeline:
  0s    -> Lock + Heartbeat alle 10s
  600s  -> Token-Refresh
  900s  -> Lock wuerde erst jetzt ablaufen (15 Min ohne Heartbeat)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:45:52 +02:00
Stefan Hacker b937351556 feat: Auto-Unlock wenn Datei geschlossen wird
Problem: Nach Oeffnen einer .cloud-Datei blieb die Sperre auf dem
Server bestehen, auch wenn Word/Excel geschlossen wurde.

Loesung: Hintergrund-Thread prueft alle 10 Sekunden ob geoeffnete
Dateien noch von einem Prozess benutzt werden:

Windows: Versucht exklusiven Schreibzugriff - wenn erfolgreich ist
  die Datei nicht mehr in Benutzung (Office gibt den Lock frei)
Linux/Mac: lsof prueft ob ein Prozess die Datei offen hat

Wenn Datei geschlossen:
1. Aenderungen werden zum Server hochgeladen
2. Server-Lock wird aufgehoben
3. .cloud Platzhalter wird neu erstellt (mit aktuellem Checksum)
4. Lokale Kopie wird geloescht
5. UI zeigt "Geschlossen + entsperrt: datei.cloud"

Tracking: opened_files HashMap speichert file_id -> Pfad + Cloud-Name
fuer alle via .cloud geoeffneten Dateien.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:44:40 +02:00
Stefan Hacker 4673423e2f fix: Sync vergleicht Timestamps - Server-Aenderungen nicht ueberschreiben
Problem: Wenn eine Datei auf dem Server geaendert wurde, hat der
Client sie trotzdem mit der lokalen (alten) Version ueberschrieben.
Der Sync hat nur Checksums verglichen aber nicht geprueft wer neuer ist.

Fix: Bei unterschiedlichen Checksums wird jetzt der Timestamp verglichen:
- Server neuer (updated_at > lokales modified) -> Download vom Server
- Lokal neuer (modified > Server updated_at) -> Upload zum Server
- Log zeigt "Server->Lokal" oder "Lokal->Server" statt nur "Aktualisiert"

Betrifft alle drei Sync-Methoden:
- sync_virtual (Offline-markierte Dateien)
- sync_upload_new (Virtual Mode Upload)
- sync_full_upload (Full Sync Upload)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:42:46 +02:00
Stefan Hacker b653f9657a fix: Single-Instance per User (Terminalserver-kompatibel)
Lock-File liegt in %APPDATA% (Windows) bzw ~/.config (Linux) -
das ist pro User verschieden. Auf Terminalservern kann jeder
User seine eigene Instanz haben.

Verbesserungen:
- Prueft ob der Prozess aus dem Lock-File noch lebt (PID-Check)
  statt nur ob die Datei existiert
- Windows: tasklist /FI "PID eq X"
- Linux: /proc/PID existiert?
- Stale Lock-Files (Prozess abgestuerzt) werden ueberschrieben
- Ohne .cloud Argument + andere Instanz laeuft -> sofort beenden
- Mit .cloud Argument + andere Instanz -> delegieren und beenden

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:28:39 +02:00
Stefan Hacker 4cc8de8a1a fix: Settings persistent (kein Keyring) + Single-Instance
Config-Persistenz:
- Passwort wird base64-kodiert in config.json gespeichert
  (statt OS-Keyring der beim Cross-Compile nicht funktioniert)
- Config-Pfad wird beim Laden/Speichern geloggt fuer Debugging
- Keyring-Dependency entfernt, base64 hinzugefuegt

Single-Instance:
- Lock-File in Config-Dir verhindert doppelte Instanz
- Wenn .cloud Datei doppelgeklickt wird und Client laeuft:
  Pfad wird in open_request.txt geschrieben und 2. Instanz beendet sich
- Laufende Instanz pollt open_request.txt und oeffnet die Datei
- Fenster wird automatisch in den Vordergrund geholt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:27:03 +02:00
Stefan Hacker c354682905 fix: Tray-Icon API kompatibel (kein Image::from_bytes)
Nutzt default_window_icon() statt Image::from_bytes das in
dieser Tauri-Version nicht existiert.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:15:02 +02:00
Stefan Hacker ac5a0a3367 feat: Settings persistent + Auto-Login + Installer Update-Modus
Settings-Persistenz:
- Config wird in OS-AppData gespeichert
  (Windows: %APPDATA%/MiniCloud Sync/config.json,
   Linux: ~/.config/MiniCloud Sync/config.json,
   Mac: ~/Library/Application Support/MiniCloud Sync/config.json)
- Gespeichert werden: Server-URL, Username, Sync-Pfade
- Passwort wird im OS-Keychain gespeichert (Windows Credential Manager,
  macOS Keychain, Linux Secret Service) - nicht in der Config-Datei

Auto-Login:
- Beim Start wird gespeicherte Config geladen
- Wenn Credentials im Keychain vorhanden: automatischer Login
- Wenn Sync-Pfade konfiguriert: Sync startet sofort automatisch
- Bei Fehler: Login-Screen mit vorausgefuellten Feldern

Config ueberlebt Updates:
- Config liegt ausserhalb des Installationsverzeichnisses
- NSIS-Installer ueberschreibt nur App-Dateien, nicht AppData
- installMode: "both" erlaubt per-User und per-Machine Installation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:11:42 +02:00
Stefan Hacker 81574c8991 fix: Virtual Mode laedt neue lokale Dateien jetzt hoch
Problem: Im Virtual Mode wurden nur .cloud Platzhalter fuer
Server-Dateien erstellt, aber neue lokale Dateien wurden nie
hochgeladen. Der Watcher hat die Aenderung erkannt aber der
Sync hat sie ignoriert.

Fix: sync_upload_new() wird jetzt auch im Virtual Mode aufgerufen.
Scannt den lokalen Ordner nach Dateien die auf dem Server nicht
existieren und laedt sie hoch. Auch geaenderte lokale Dateien
(Checksum-Vergleich) werden aktualisiert. Gesperrte Dateien
werden zurueckgehalten.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:04:03 +02:00
Stefan Hacker 607d18a7e2 feat: Lokaler Datei-Browser mit Offline-Markierung + Kontextmenue
Datei-Browser im Client:
- Zeigt lokalen Sync-Ordner mit allen Dateien an
- Ordner navigierbar mit Breadcrumb
- Status pro Datei: ☁ Cloud (Platzhalter) / 📄 Offline (echte Datei)
- Badges: blaues "Cloud" oder gruenes "Offline"
- Cloud-Dateien zeigen Originalgroesse aus .cloud-Metadaten
- Aktualisiert sich automatisch nach jedem Sync

Rechtsklick-Kontextmenue:
- .cloud Datei: "Oeffnen (herunterladen)" + "Offline verfuegbar machen"
- Echte Datei: "Nicht mehr offline (Platzhalter)"
- Doppelklick auf Ordner = navigieren
- Doppelklick auf .cloud = herunterladen + oeffnen

Rust-Backend:
- browse_sync_folder: Listet lokale Dateien mit Status auf
  (is_cloud, is_offline, cloud_size aus JSON-Metadaten)
- Sortierung: Ordner zuerst, dann alphabetisch

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:02:21 +02:00
Stefan Hacker adaa19a1ef fix: Durchsuchen-Button, Tray-Icon, Minimize statt Close, .cloud Handler
1. Durchsuchen-Button: dialog:allow-open Permission in capabilities
2. Tray-Icon: Nutzt das App-Icon (32x32.png) statt leer
3. Close = Minimize: Fenster wird versteckt statt App beendet,
   Doppelklick auf Tray-Icon oeffnet wieder
4. .cloud Datei-Handler:
   - fileAssociations in tauri.conf.json registriert .cloud Extension
   - NSIS-Installer registriert den Handler automatisch
   - Doppelklick auf .cloud -> App startet, laedt Datei runter,
     oeffnet mit Standard-App (Word/Excel/etc.)
   - Wenn App laeuft: Event wird emitted, Frontend verarbeitet es

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:57:18 +02:00
Stefan Hacker 505545f26c feat: Watcher triggert sofort Sync + Offline-Markierung pro Datei
Sofort-Sync statt 30s-Polling:
- Filesystem-Watcher erkennt lokale Aenderungen sofort
- 3 Sekunden Debounce (wartet ob noch mehr kommt)
- Dann sofortiger Sync-Trigger statt auf den naechsten 30s-Zyklus zu warten
- .cloud-Dateien werden vom Watcher ignoriert (kein Loop)
- Fallback: alle 60s Sync auch ohne Aenderungen (Server-Aenderungen holen)
- UI zeigt "→ Sync ausgeloest" bei Watcher-Trigger

Offline-Markierung:
- mark_offline: .cloud -> echte Datei runterladen, bleibt permanent lokal
- unmark_offline: echte Datei -> zurueck zu .cloud Platzhalter
- Offline-Dateien werden bei jedem Sync automatisch aktualisiert
  (Checksum-Vergleich in sync_virtual)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:44:57 +02:00
Stefan Hacker e32a64ba83 fix: fehlende npm-Dependencies fuer Tauri-Plugins (dialog, notification)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:40:25 +02:00
Stefan Hacker 16d514f7f1 feat: Virtual Files, Multi-Sync-Pfade, Full Sync, Ordner-Dialog
Virtual Files System:
- .cloud Platzhalter-Dateien (JSON mit ID, Name, Groesse, Checksum)
- 0 Bytes Speicherverbrauch pro Datei
- Doppelklick auf .cloud -> Download + Oeffnen mit Standard-App + Lock
- Nach Schliessen: Sync zurueck, lokale Kopie entfernen, .cloud neu
- Offline-Markierung: Echte Dateien bleiben lokal (kein .cloud)
- Server-Dateien loeschen -> .cloud wird automatisch entfernt

Multi-Sync-Pfade (wie Nextcloud):
- Beliebig viele Server-Ordner auf lokale Ordner mappen
- z.B. /Projekte/2026 -> ~/Projekte oder /Shared/Team -> ~/Team
- Freigegebene Ordner von anderen Benutzern sync-bar
- Jeder Pfad hat eigenen Modus (Virtual oder Full)
- Hinzufuegen/Entfernen/Modus wechseln in der UI

Full Sync:
- Pro Sync-Pfad waehlbar: Virtual oder Full
- Full = alle Dateien lokal spiegeln (bidirektional)
- Virtual = .cloud Platzhalter (Standard)
- Klick auf Modus-Badge zum Umschalten

Ordner-Dialog:
- "Durchsuchen..." Button oeffnet nativen Ordner-Auswahl-Dialog
- Server-Ordner per Dropdown aus Dateibaum waehlen
- Ordner werden automatisch erstellt wenn noetig

UI:
- Sync-Pfade als Karten: ☁ /Server/Pfad → 📁 /Lokaler/Pfad
- Modus-Badge (Virtual/Full) mit Klick zum Wechseln
- Tray-Menue: "Jetzt synchronisieren" Eintrag

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:34:03 +02:00
Stefan Hacker 714ce1ae53 feat: Desktop-Client komplett - Auto-Sync, Watcher, Locking, Tray
Alles eingebunden was vorher nur als unused code existierte:

Auto-Sync:
- Nach erstem Sync laeuft alle 30s ein Delta-Sync im Hintergrund
- Status-Badge zeigt live: Synchronisiert / Synchronisiere... / Fehler
- Sync-Protokoll mit Timestamps

File-Watcher:
- Ueberwacht den Sync-Ordner auf lokale Aenderungen (Erstellt/Geaendert/Geloescht)
- Aenderungen werden im UI unter "Lokale Aenderungen" angezeigt
- Filtert temp/hidden files automatisch

File-Locking:
- lock_file_cmd / unlock_file_cmd Tauri-Kommandos
- Heartbeat-Thread sendet alle 60s Heartbeat fuer gesperrte Dateien
- locked_files Liste im State

System-Tray:
- Tray-Icon mit "Mini-Cloud Sync" Tooltip
- Rechtsklick-Menue: Oeffnen / Beenden
- "Oeffnen" zeigt das Hauptfenster

UI:
- Status-Badge mit Farbe (gruen=synced, orange=syncing, rot=error)
- Spinning-Icon waehrend Sync
- "Auto-Sync aktiv" Hinweis nach erstem Sync
- Sync-Ordner wird nach Start gesperrt (nicht mehr aenderbar)
- Lokale Aenderungen und Sync-Log mit Timestamps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:54:54 +02:00
Stefan Hacker 8342cbfa17 fix: main.rs lib-Name auf minicloud_sync_lib korrigiert
War noch tauri_app_lib vom Template, muss minicloud_sync_lib heissen
(wie in Cargo.toml definiert).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:47:18 +02:00
Stefan Hacker 10e6211820 fix: Rust MutexGuard ueber await - delta_sync Send-Fehler
MutexGuard wird jetzt vor dem .await gedroppt (take + put back),
damit der Future Send-kompatibel ist wie Tauri es erfordert.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:42:28 +02:00
Stefan Hacker 48a46cbc79 feat: Build-Script + Docker-Build fuer alle Plattformen
build.sh - baut Clients via Docker (kein lokales Setup noetig):
  ./build.sh linux        # Linux Desktop (.deb + .AppImage)
  ./build.sh windows      # Windows Desktop (.msi + .exe) Cross-Compile
  ./build.sh mac          # macOS Desktop (.dmg) - nur auf macOS
  ./build.sh android      # Android App (.apk) via Docker
  ./build.sh ios          # iOS App (.ipa) - nur auf macOS
  ./build.sh all-desktop  # Linux + Windows zusammen
  ./build.sh clean        # Build-Cache loeschen

Dockerfile.build: Multi-stage Container mit Rust, Node.js, Tauri-Deps,
  Windows Cross-Compile Tools (mingw-w64)

Output landet in build-output/ (gitignored)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:29:58 +02:00
Stefan Hacker 06ad65dbb3 feat: Desktop Sync Client (Tauri) - Grundgeruest
Tauri 2 Desktop-Client mit:

Rust-Backend:
- MiniCloudApi: Login, Token-Refresh, Upload, Download, Sync-Tree,
  Sync-Changes, File-Locking (Lock/Unlock/Heartbeat)
- SyncEngine: Full-Sync (Server-Tree vs. lokales Dateisystem),
  Delta-Sync (nur Aenderungen seit letztem Sync), bidirektionaler
  Abgleich mit SHA-256 Checksummen, Ordner-Erstellung,
  Lock-Status-Pruefung vor Upload, Konflikt-Erkennung
- FileWatcher: Filesystem-Watcher (notify crate) fuer Echtzeit-
  Erkennung lokaler Aenderungen, filtert temp/hidden files

Vue-Frontend:
- Login-Screen: Server-URL, Benutzername, Passwort
- Main-Screen: Sync-Ordner setzen, Sync starten, Dateiliste mit
  Lock-Status, Sync-Protokoll
- Dark-Mode Support

Tauri-Kommandos: login, set_sync_dir, start_sync, delta_sync,
  get_status, get_file_tree

Zum Bauen (Linux):
  sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev
  cd clients/desktop && npm install && npm run tauri build

Windows/Mac: Tauri Voraussetzungen installieren, dann gleicher Befehl

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:26:57 +02:00