0.8.2: Auto-Recovery für hängende 0.8.0-Installationen + UpdateNotifier vor Login

- Auto-Recovery in adapter.js: wenn Cloud-Modus gesetzt + lokale Daten
  vorhanden + keine Cloud-Session → Cloud-Konfiguration wird beim
  nächsten App-Start automatisch zurückgenommen. Marker rapport_080_recovery
  verhindert wiederholte Auslösung.
- UpdateNotifier wird in allen Pre-Login-Screens gerendert (BackendChoice,
  Setup, MigrationScreen, CloudSetup, Login) — so kann ein hängender
  Wizard sich via Auto-Update selbst befreien.
- Tauri-Builds ignorieren VITE_SUPABASE_URL aus dem Build. Desktop-User
  geben die Server-URL immer aktiv im Login ein, statt eine irrelevante
  Default-IP vorgesetzt zu bekommen.
- Anon-Key bleibt aus dem Build (kein Geheimnis, pro Cloud-Instanz fix).
- BackendChoice zeigt nur dann eine vorkonfigurierte URL, wenn nicht in Tauri.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-23 19:54:14 +02:00
parent 2bd516a9ab
commit edee7b9f28
7 changed files with 74 additions and 37 deletions
+36 -20
View File
@@ -46,22 +46,37 @@ export class LocalStorageAdapter {
}
function createAdapter() {
// Build-time-Default für Web-Deploy: wenn eine Production-Build VITE_SUPABASE_URL
// gesetzt hat (z.B. via .env.production) und der User noch nichts gewählt hat,
// wird Cloud automatisch der Modus. Damit landet ein Browser, der app.rapport.kgva.ch
// öffnet, direkt im Cloud-Login (bzw. Init-Dialog wenn Server leer).
//
// Bewusst NICHT auto-cloud wenn:
// - Dev-Build (`npm run dev`) — User sieht weiterhin BackendChoice
// - lokale Daten existieren (würde bestehenden Lokal-User auf Cloud zwingen
// und seine Daten unsichtbar machen) — Bug bei 0.7→0.8-Upgrade
// - Tauri-Desktop-App (Tauri-User sollen immer aktiv wählen, nicht implizit
// aufgrund von .env.production eines Builds umgehauen werden)
if (typeof localStorage !== "undefined" && import.meta.env.PROD) {
const envUrl = import.meta.env.VITE_SUPABASE_URL;
const isTauri = typeof window !== "undefined" && !!window.__TAURI_INTERNALS__;
// Build-time-URL nur für Web-Deploy gültig. Tauri-Builds ignorieren den
// eingebrannten Wert — Desktop-User geben die Server-URL aktiv ein.
// Der Anon-Key bleibt aus dem Build, weil er pro Cloud-Instanz konstant ist
// (kein User-Geheimnis, sondern Public-Konfig).
const envUrl = isTauri ? null : import.meta.env.VITE_SUPABASE_URL;
const envKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
if (typeof localStorage !== "undefined") {
// ── Auto-Recovery für 0.8.0-Upgrade-Bug ──────────────────────────────
// 0.8.0 hat Cloud-Modus ungewollt gesetzt bei Lokal-Usern (siehe 0.8.1
// CHANGELOG). 0.8.1 verhindert das nur prospektiv, behebt aber den
// bestehenden Cloud-State nicht. Hier räumen wir nachträglich auf:
// Cloud-Modus gesetzt + lokale Daten vorhanden + keine Cloud-Session
// → Cloud-State löschen, User landet im BackendChoice oder Lokal-Modus.
const RECOVERY_MARKER = "rapport_080_recovery";
const backend = localStorage.getItem("rapport_backend");
const hasLocalData = !!localStorage.getItem(STORAGE_KEY);
const isTauri = typeof window !== "undefined" && !!window.__TAURI_INTERNALS__;
if (envUrl && !localStorage.getItem("rapport_backend_chosen") && !hasLocalData && !isTauri) {
const hasCloudSession = !!localStorage.getItem("rapport_supabase_session");
if (backend === "cloud" && hasLocalData && !hasCloudSession && !localStorage.getItem(RECOVERY_MARKER)) {
console.warn("Auto-Recovery: Cloud-Modus gesetzt, aber Lokal-Daten vorhanden und kein Cloud-Login — räume Cloud-State auf.");
localStorage.removeItem("rapport_backend");
localStorage.removeItem("rapport_backend_chosen");
localStorage.removeItem("rapport_cloud_url");
localStorage.setItem(RECOVERY_MARKER, "1");
}
// ── Auto-Cloud-Default für Web-Deploy ────────────────────────────────
// Nur wenn keine lokalen Daten existieren und der Browser auf einer
// konfigurierten Web-Instanz landet (envUrl aus build).
if (import.meta.env.PROD && envUrl && !localStorage.getItem("rapport_backend_chosen") && !hasLocalData) {
localStorage.setItem("rapport_backend_chosen", "1");
localStorage.setItem("rapport_backend", "cloud");
if (!localStorage.getItem("rapport_cloud_url")) {
@@ -73,14 +88,15 @@ function createAdapter() {
const backend = (typeof localStorage !== "undefined"
&& localStorage.getItem("rapport_backend")) || "local";
if (backend === "cloud") {
const url = import.meta.env.VITE_SUPABASE_URL;
const key = import.meta.env.VITE_SUPABASE_ANON_KEY;
if (!url || !key) {
console.warn("rapport_backend=cloud, aber VITE_SUPABASE_URL/ANON_KEY fehlen — Fallback auf LocalStorage.");
// URL kommt bevorzugt aus localStorage (vom User eingegeben). Tauri hat
// gar keine env-URL; Web-Build hat sie ggf. als Fallback.
const url = (typeof localStorage !== "undefined" && localStorage.getItem("rapport_cloud_url")) || envUrl;
if (!url || !envKey) {
console.warn("rapport_backend=cloud, aber URL oder ANON_KEY fehlen — Fallback auf LocalStorage.");
return new LocalStorageAdapter();
}
console.info("Storage-Adapter: SupabaseAdapter aktiv (URL:", url + ")");
return new SupabaseAdapter(url, key);
return new SupabaseAdapter(url, envKey);
}
return new LocalStorageAdapter();
}