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>
This commit is contained in:
Stefan Hacker
2026-04-12 01:11:42 +02:00
parent 81574c8991
commit ac5a0a3367
5 changed files with 158 additions and 2 deletions
+29
View File
@@ -223,6 +223,35 @@ function formatSize(b) {
}
onMounted(async () => {
// Try auto-login with saved credentials
try {
const saved = await invoke("load_saved_config");
if (saved.has_credentials) {
loginLoading.value = true;
serverUrl.value = saved.server_url;
username.value = saved.username;
try {
const result = await invoke("auto_login");
userInfo.value = result;
screen.value = "main";
syncStatus.value = `Verbunden als ${result.username}`;
syncPaths.value = (await invoke("get_sync_paths"));
await loadFileTree();
// Auto-start sync if paths configured
if (syncPaths.value.length > 0) {
await startSync();
}
} catch (err) {
syncStatus.value = "Auto-Login fehlgeschlagen";
// Show login screen with pre-filled fields
}
loginLoading.value = false;
} else if (saved.has_config) {
serverUrl.value = saved.server_url;
username.value = saved.username;
}
} catch { /* no saved config */ }
unlistenStatus = await listen("sync-status", e => {
syncing.value = e.payload === "syncing";
syncStatus.value = e.payload === "syncing" ? "Synchronisiere..." : "Synchronisiert";