docs(18-03): complete Web-Oberflaeche fuer Desktop-App plan
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
---
|
||||
phase: 18-desktop-client-fertigstellen
|
||||
plan: 03
|
||||
subsystem: ui
|
||||
tags: [next-intl, react, desktop-distribution, i18n]
|
||||
|
||||
# Dependency graph
|
||||
requires:
|
||||
- phase: 18-01
|
||||
provides: "GET /desktop/latest, GET /desktop/download/:platform (beide @Public()), DesktopLatestResponse-Form"
|
||||
provides:
|
||||
- "apps/web/src/lib/desktop.ts (loadDesktopLatest, desktopDownloadUrl, formatFileSize)"
|
||||
- "DesktopDownloadLinks — unauffaelliger Link-Block auf der Anmeldeseite (D-12)"
|
||||
- "DesktopAppSettings + Route /settings/general/desktop — Version, Download-Knoepfe, Dateigroesse, Erklaerung"
|
||||
- "Seitenleisteneintrag Desktop-App unter Allgemein"
|
||||
affects: [18-04-client-updateprüfung, 18-06-browser-gegenprobe]
|
||||
|
||||
actuals:
|
||||
tokens: 6993
|
||||
tasks: 2
|
||||
commits: 2
|
||||
plan_head_before: 2164cd537a8645f39a055bfa3cff77b8ef02822d
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "memoisiertes Single-Promise-Laden (Modul-Ebene), still bei Fehler -> null, konsumiert per useEffect+useState mit active-Schutz (Muster app-version.ts/AppVersionBadge, jetzt zweimal wiederverwendet: Login-Link und Einstellungsseite)"
|
||||
- "Linkziel immer aus API_URL plus relativem url-Feld gebaut, nie eine absolute Adresse aus der Antwort uebernommen (T-18-07)"
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- apps/web/src/lib/desktop.ts
|
||||
- apps/web/src/lib/desktop.test.ts
|
||||
- apps/web/src/components/desktop/desktop-download-links.tsx
|
||||
- apps/web/src/components/desktop/desktop-download-links.test.tsx
|
||||
- "apps/web/src/app/(portal)/settings/general/desktop/page.tsx"
|
||||
- apps/web/src/components/settings/desktop-app-settings.tsx
|
||||
- apps/web/src/components/settings/desktop-app-settings.test.tsx
|
||||
modified:
|
||||
- "apps/web/src/app/(auth)/login/page.tsx"
|
||||
- apps/web/src/components/settings/settings-sidebar.tsx
|
||||
- apps/web/src/messages/de.json
|
||||
- apps/web/src/messages/en.json
|
||||
- apps/web/src/messages/umlaut-dictionary.ts
|
||||
|
||||
key-decisions:
|
||||
- "useLocale() aus der Anmeldeseiten-Komponente entfernt (Plan-Text erwaehnte es, aber der Link-Block zeigt keine Dateigroesse — nur die Einstellungsseite braucht locale fuer formatFileSize); vermeidet eine ungenutzte Variable."
|
||||
- "'neuere' zur UMLAUT_ALLOWLIST ergaenzt — der bestehende Waechter-Test flaggte das Wort faelschlich, weil es zufaellig die Buchstabenfolge 'ue' enthaelt, obwohl die Schreibweise bereits korrekt ist (kein Substitutionsfehler)."
|
||||
|
||||
patterns-established: []
|
||||
|
||||
requirements-completed: [DESK-03]
|
||||
|
||||
coverage:
|
||||
- id: D1
|
||||
description: "Anmeldeseite zeigt Download-Link(s) nur wenn /desktop/latest antwortet, Windows fuehrt, Linux als Kurzlink bei beiden Paketen"
|
||||
requirement: "DESK-03"
|
||||
verification:
|
||||
- kind: unit
|
||||
ref: "apps/web/src/lib/desktop.test.ts#Test 1-5"
|
||||
status: pass
|
||||
- kind: unit
|
||||
ref: "apps/web/src/components/desktop/desktop-download-links.test.tsx#Test 1-3"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D2
|
||||
description: "Einstellungsseite Desktop-App: Version, zwei Primaerknoepfe mit Symbol, Dateiname/Groesse, Beta-Hinweis, vier erklaerende Saetze, Hinweistext ohne Pakete"
|
||||
requirement: "DESK-03"
|
||||
verification:
|
||||
- kind: unit
|
||||
ref: "apps/web/src/components/settings/desktop-app-settings.test.tsx#Test 1-3"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D3
|
||||
description: "Seitenleiste zeigt den Eintrag Desktop-App unter Allgemein mit aria-current auf der Route"
|
||||
requirement: "DESK-03"
|
||||
verification:
|
||||
- kind: other
|
||||
ref: "grep -c 'href=\"/settings/general/desktop\"' apps/web/src/components/settings/settings-sidebar.tsx (=1)"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D4
|
||||
description: "de/en vollstaendig fuer auth.desktopDownload.* und settings.desktop.*/categoryDesktopApp, deutsche Texte mit echten Umlauten"
|
||||
requirement: "DESK-03"
|
||||
verification:
|
||||
- kind: other
|
||||
ref: "node i18n-Paritaets-/Umlautskript aus 18-03-PLAN.md <verify> -> 'i18n OK'"
|
||||
status: pass
|
||||
- kind: unit
|
||||
ref: "apps/web/src/messages/umlaut-guard.spec.ts"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D5
|
||||
description: "Alle Downloads laufen ueber die Tessera-API (API_URL + relatives url-Feld), keine feste Server-/Firmenadresse im Code"
|
||||
requirement: "DESK-03"
|
||||
verification:
|
||||
- kind: unit
|
||||
ref: "apps/web/src/lib/desktop.test.ts#Test 4 (desktopDownloadUrl)"
|
||||
status: pass
|
||||
- kind: other
|
||||
ref: "grep -v '^\\s*//' apps/web/src/lib/desktop.ts | grep -c 'process.env.NEXT_PUBLIC_API_URL' (=1)"
|
||||
status: pass
|
||||
human_judgment: true
|
||||
rationale: "Der End-zu-Ende-Beweis (Browser klickt echten Download bis zum tatsaechlichen Dateidownload) ist die geplante Browser-Gegenprobe am Phasenende (18-06) — hier nur die Unit-/Text-Ebene automatisiert bewiesen."
|
||||
|
||||
duration: 20min
|
||||
completed: 2026-09-16
|
||||
status: complete
|
||||
---
|
||||
|
||||
# Phase 18 Plan 03: Desktop-App in der Web-Oberflaeche Summary
|
||||
|
||||
**Unauffaelliger Download-Link auf der Anmeldeseite und eine vollstaendige Einstellungsseite "Desktop-App" (Version, zwei Primaerknoepfe mit Plattform-Symbol, Dateigroesse, Beta-Hinweis, vier erklaerende Saetze) — beide lesen `GET /desktop/latest` und blenden sich ohne Pakete aus.**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** 20 min (geschaetzt)
|
||||
- **Started:** 2026-09-16T14:10:00Z (geschaetzt)
|
||||
- **Completed:** 2026-09-16T14:30:47Z
|
||||
- **Tasks:** 2
|
||||
- **Files modified:** 12
|
||||
|
||||
## Accomplishments
|
||||
- `apps/web/src/lib/desktop.ts`: `loadDesktopLatest()` memoisiert (ein Fetch je Modulinstanz, still bei Fehler -> `null`, kein `credentials: 'include'` — die Anmeldeseite hat noch kein Cookie), `desktopDownloadUrl()` (baut die Adresse ausschliesslich aus `API_URL` plus dem relativen `url`-Feld, T-18-07), `formatFileSize()` (lokalisierte MB-Werte, `Intl.NumberFormat`).
|
||||
- `DesktopDownloadLinks` auf der Anmeldeseite: rendert nichts ohne Daten oder ohne Plattform in `files`; Windows fuehrt als Hauptlink, Linux folgt als kleiner Zusatzlink, wenn beide Pakete vorliegen; darunter die Versionszeile.
|
||||
- `DesktopAppSettings` unter `/settings/general/desktop`: vier erklaerende Saetze in Sie-Form (Was ist die App, Erststart, Tray-Verhalten, Update-Hinweis), Versionszeile, Beta-Kanal-Zusatzhinweis mit Commit, zwei Primaerknoepfe (`bg-primary`, inline-SVG-Plattformsymbol, `download`-Attribut) mit Dateiname+Groesse darunter, und ein Hinweistext statt der Knoepfe, wenn die API `null` liefert.
|
||||
- Seitenleiste: neuer Eintrag "Desktop-App" unter "Allgemein" mit identischem `aria-current`-Muster wie "Konto".
|
||||
- `de.json`/`en.json`: `auth.desktopDownload.*` und `settings.desktop.*`/`settings.categoryDesktopApp` vollstaendig, deutsche Texte mit echten Umlauten.
|
||||
|
||||
## Task Commits
|
||||
|
||||
Each task was committed atomically:
|
||||
|
||||
1. **Task 1: Fetch-Helfer und der Download-Link auf der Anmeldeseite** - `026d9c3` (feat)
|
||||
2. **Task 2: Einstellungsseite "Desktop-App" mit Knoepfen, Groesse und Erklaerung** - `e96d460` (feat)
|
||||
|
||||
**Plan metadata:** commit pending (this SUMMARY + STATE.md/ROADMAP.md/REQUIREMENTS.md)
|
||||
|
||||
## Files Created/Modified
|
||||
- `apps/web/src/lib/desktop.ts` - `DesktopPlatform`/`DesktopFileInfo`/`DesktopLatestInfo`, `loadDesktopLatest`, `desktopDownloadUrl`, `formatFileSize`
|
||||
- `apps/web/src/lib/desktop.test.ts` - 5 Tests (memoisiert, still bei ok=false/Netzfehler, URL-Bau, Groessenformatierung)
|
||||
- `apps/web/src/components/desktop/desktop-download-links.tsx` - Link-Block der Anmeldeseite
|
||||
- `apps/web/src/components/desktop/desktop-download-links.test.tsx` - 3 Tests (leer, beide Plattformen, nur Linux)
|
||||
- `apps/web/src/app/(auth)/login/page.tsx` - `DesktopDownloadLinks` nach dem Formular eingebaut
|
||||
- `apps/web/src/app/(portal)/settings/general/desktop/page.tsx` - Route, delegiert an `DesktopAppSettings`
|
||||
- `apps/web/src/components/settings/desktop-app-settings.tsx` - Version, Knoepfe, Groesse, Saetze, Hinweisfall
|
||||
- `apps/web/src/components/settings/desktop-app-settings.test.tsx` - 3 Tests (beide Plattformen, Beta-Hinweis, keine Pakete)
|
||||
- `apps/web/src/components/settings/settings-sidebar.tsx` - Eintrag "Desktop-App" ergaenzt
|
||||
- `apps/web/src/messages/de.json` / `en.json` - `auth.desktopDownload.*`, `settings.desktop.*`, `settings.categoryDesktopApp`
|
||||
- `apps/web/src/messages/umlaut-dictionary.ts` - `neuere` zur Allowlist ergaenzt (Deviation, siehe unten)
|
||||
|
||||
## Decisions Made
|
||||
- `useLocale()` in `DesktopDownloadLinks` weggelassen: der Link-Block der Anmeldeseite zeigt keine Dateigroesse, nur die Version — `formatFileSize` wird ausschliesslich auf der Einstellungsseite gebraucht. Eine ungenutzte Variable haette keinen Wert gehabt.
|
||||
- Die vier erklaerenden Saetze und die Download-Bloecke bleiben eine einzige Client-Komponente (`DesktopAppSettings`) statt mehrerer Unterkomponenten — passend zur Groesse des Inhalts und zum bestehenden `account`/`smtp`-Seitenmuster (eine Komponente pro Einstellungsseite).
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 1 - Bug] Umlaut-Waechter-Test schlug auf "neuere" fehl**
|
||||
- **Found during:** Task 2 (voller `pnpm --filter @tessera/web exec vitest run` nach dem i18n-Block)
|
||||
- **Issue:** `src/messages/umlaut-guard.spec.ts` flaggte `settings.desktop.update: "neuere"` als vermeintlich falsche ASCII-Umschrift, weil das Wort die Buchstabenfolge "ue" enthaelt (n-e-**ue**-r-e) — die Schreibweise ist aber bereits korrektes Deutsch, keine Substitution noetig.
|
||||
- **Fix:** `neuere` zur `UMLAUT_ALLOWLIST` in `apps/web/src/messages/umlaut-dictionary.ts` ergaenzt (neben den bereits vorhandenen `neue`/`neuen`/`Neue`/`Neues`).
|
||||
- **Files modified:** `apps/web/src/messages/umlaut-dictionary.ts`
|
||||
- **Verification:** `pnpm --filter @tessera/web exec vitest run` — vollstaendige Suite gruen (365/365).
|
||||
- **Committed in:** `e96d460` (Task 2 commit)
|
||||
|
||||
---
|
||||
|
||||
**Total deviations:** 1 auto-fixed (1 bug)
|
||||
**Impact on plan:** Reine Testinfrastruktur-Korrektur, kein Verhaltensunterschied im Produktionscode. Keine Ausweitung des Umfangs.
|
||||
|
||||
## Issues Encountered
|
||||
None.
|
||||
|
||||
## User Setup Required
|
||||
None - no external service configuration required.
|
||||
|
||||
## Next Phase Readiness
|
||||
- Die Web-Oberflaeche liest `GET /desktop/latest` an beiden vorgesehenen Stellen (Anmeldeseite, Einstellungen) und blendet sich korrekt aus, wenn keine Pakete hinterlegt sind — 18-04 (Client-Versionspruefung) kann auf demselben Endpunkt aufbauen, ohne die Web-Seite zu beruehren.
|
||||
- Die Browser-Gegenprobe (echter Klick, echter Download) ist bewusst auf 18-06 verschoben (siehe Plan-`<verification>` Punkt 4); alle automatisierten Ebenen (Unit-Tests, Typpruefung, i18n-Paritaet/Umlaute, volle Web-Suite) sind gruen.
|
||||
- Kein Blocker.
|
||||
|
||||
---
|
||||
*Phase: 18-desktop-client-fertigstellen*
|
||||
*Completed: 2026-09-16*
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
All created files verified on disk (`apps/web/src/lib/desktop.ts`, `desktop.test.ts`, `apps/web/src/components/desktop/desktop-download-links.tsx`, `desktop-download-links.test.tsx`, `apps/web/src/app/(portal)/settings/general/desktop/page.tsx`, `apps/web/src/components/settings/desktop-app-settings.tsx`, `desktop-app-settings.test.tsx`). Both task commits found in `git log` (`026d9c3`, `e96d460`). All plan-level `<verification>` items re-run and passing: `pnpm --filter @tessera/web exec vitest run` (365/365 green, baseline 354 + 11 new), `pnpm --filter @tessera/web type-check` (clean), i18n parity/umlaut script -> `i18n OK`. Browser-Gegenprobe bleibt fuer 18-06 (Plan-`<verification>` Punkt 4, ausserhalb dieses Plans).
|
||||
Reference in New Issue
Block a user