From 37840e6172b4fd1f88c205a9fcb6163219154517 Mon Sep 17 00:00:00 2001 From: Till JS Date: Fri, 15 May 2026 22:22:49 +0200 Subject: [PATCH] =?UTF-8?q?devlog:=202=20Tage=20geschrieben=20(=CE=B6-0=20?= =?UTF-8?q?+=20=CE=B6-1=20+=20Launch-Flash-Fix)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tag 1: Hybrid SwiftUI + WKWebView, ζ-0 + ζ-1 + Teile ζ-2. Tag 2: dreilagiger weißer Flash beim App-Start gefixt. Co-Authored-By: Claude Opus 4.7 (1M context) --- devlog/2026-05-14/data.json | 200 +++++++++++++++++++++++++++++++++++ devlog/2026-05-14/macher.md | 101 ++++++++++++++++++ devlog/2026-05-14/spieler.md | 43 ++++++++ devlog/2026-05-15/data.json | 73 +++++++++++++ devlog/2026-05-15/macher.md | 62 +++++++++++ devlog/2026-05-15/spieler.md | 19 ++++ 6 files changed, 498 insertions(+) create mode 100644 devlog/2026-05-14/data.json create mode 100644 devlog/2026-05-14/macher.md create mode 100644 devlog/2026-05-14/spieler.md create mode 100644 devlog/2026-05-15/data.json create mode 100644 devlog/2026-05-15/macher.md create mode 100644 devlog/2026-05-15/spieler.md diff --git a/devlog/2026-05-14/data.json b/devlog/2026-05-14/data.json new file mode 100644 index 0000000..0d89056 --- /dev/null +++ b/devlog/2026-05-14/data.json @@ -0,0 +1,200 @@ +{ + "date": "2026-05-14", + "day_number": 1, + "weekday": "Donnerstag", + "commits": 11, + "authors": [ + { + "name": "Till", + "count": 11 + } + ], + "additions": 3130, + "deletions": 226, + "net_lines": 2904, + "files_changed": 36, + "new_files": 0, + "deleted_files": 0, + "session": { + "first_commit_at": "2026-05-14T10:15:22.000Z", + "last_commit_at": "2026-05-14T19:45:25.000Z", + "total_span_minutes": 570, + "active_minutes": 37, + "pauses": [ + { + "from": "12:15", + "to": "12:56", + "minutes": 41 + }, + { + "from": "13:16", + "to": "20:51", + "minutes": 455 + }, + { + "from": "21:02", + "to": "21:38", + "minutes": 37 + } + ], + "longest_focus_minutes": 20 + }, + "top_dirs": [ + { + "path": "Sources/Features/WebShell", + "pct": 15 + }, + { + "path": "Sources/Resources/Assets.xcassets", + "pct": 9 + }, + { + "path": "project.yml", + "pct": 9 + }, + { + "path": "PLAN.md", + "pct": 8 + }, + { + "path": "Sources/App/RootView.swift", + "pct": 6 + } + ], + "top_extensions": [ + { + "ext": ".swift", + "count": 40 + }, + { + "ext": ".md", + "count": 8 + }, + { + "ext": ".yml", + "count": 7 + }, + { + "ext": ".json", + "count": 4 + }, + { + "ext": ".xcstrings", + "count": 2 + }, + { + "ext": ".png", + "count": 2 + } + ], + "tags": [ + "icon", + "dark-mode" + ], + "commits_list": [ + { + "hash": "0bd59ed", + "short": "ζ-0 Setup: Repo-Skelett, iOS-Build grün, Healthz live", + "type": null, + "scope": null, + "additions": 1468, + "deletions": 0, + "timestamp": "2026-05-14T12:15:22+02:00" + }, + { + "hash": "75b5e71", + "short": "ζ-1: WebShellView + Universal-Link-Routing", + "type": null, + "scope": null, + "additions": 466, + "deletions": 77, + "timestamp": "2026-05-14T12:56:05+02:00" + }, + { + "hash": "dd10f85", + "short": "ζ-1 abgeschlossen: DeepLinkRouter + Web-Header-Hide", + "type": null, + "scope": null, + "additions": 166, + "deletions": 36, + "timestamp": "2026-05-14T13:06:37+02:00" + }, + { + "hash": "c89d48c", + "short": "ζ-2 native: SwiftData-Snapshot-Cache + DailyQuoteWidget", + "type": null, + "scope": null, + "additions": 597, + "deletions": 45, + "timestamp": "2026-05-14T13:16:05+02:00" + }, + { + "hash": "03e2f04", + "short": "ζ-1 Polish: robuster Header-Selektor + zitare.mana.how als 2. UL-Domain", + "type": null, + "scope": null, + "additions": 35, + "deletions": 5, + "timestamp": "2026-05-14T20:51:03+02:00" + }, + { + "hash": "c0260fa", + "short": "docs: Cloudflare-TODO (DNS-CNAME + CNAME-Cleanup) + PLAN.md externe Blocker", + "type": null, + "scope": null, + "additions": 119, + "deletions": 0, + "timestamp": "2026-05-14T20:52:13+02:00" + }, + { + "hash": "7b4cb13", + "short": "fix(icon): TestFlight-Validation grün — Icon + CFBundleIconName", + "type": "fix", + "scope": "icon", + "additions": 188, + "deletions": 18, + "timestamp": "2026-05-14T21:00:24+02:00" + }, + { + "hash": "10644ff", + "short": "icon: vereinfachte Anführungszeichen-Glyphe als Platzhalter", + "type": null, + "scope": null, + "additions": 27, + "deletions": 40, + "timestamp": "2026-05-14T21:02:17+02:00" + }, + { + "hash": "bc01c0f", + "short": "ui: Mac-Window + Konto-Header nach erstem TestFlight-Build", + "type": null, + "scope": null, + "additions": 20, + "deletions": 3, + "timestamp": "2026-05-14T21:38:48+02:00" + }, + { + "hash": "f65b949", + "short": "build: CFBundleVersion 2 für nächsten TestFlight-Upload", + "type": null, + "scope": null, + "additions": 1, + "deletions": 1, + "timestamp": "2026-05-14T21:39:18+02:00" + }, + { + "hash": "2616c4f", + "short": "fix(dark-mode): WebView folgt System statt eigener localStorage-Toggle", + "type": "fix", + "scope": "dark-mode", + "additions": 43, + "deletions": 1, + "timestamp": "2026-05-14T21:45:25+02:00" + } + ], + "review_state": "auto", + "llm": { + "model": null, + "generated_at": null + } +} diff --git a/devlog/2026-05-14/macher.md b/devlog/2026-05-14/macher.md new file mode 100644 index 0000000..962ab78 --- /dev/null +++ b/devlog/2026-05-14/macher.md @@ -0,0 +1,101 @@ +--- +date: 2026-05-14 +day: 1 +view: macher +weekday: Donnerstag +commits: 11 +review: written +--- +# Donnerstag, 2026-05-14 — Tag 1 (Macher-Sicht) + +Sonderfall im Native-Stack: Hybrid SwiftUI + WKWebView. Zitare hat +keinen Hardware-USP gegenüber dem Browser — Native bringt nur +Widget, ShareExtension, Spotlight, Submit. Lesen bleibt im Web. +Phasen ζ-0 + ζ-1 + Teile von ζ-2 in einer Schicht. + +## Stats + +11 Commits, +3 130 / −226 LoC, 36 Files. 40× `.swift`, 7× `.yml`, +8× `.md`. Top-Dirs `Sources/Features/WebShell` (15 %), +Assets (9 %). Tags: `icon`, `dark-mode`. Session 10:15 → 21:45, +37 aktive Minuten in 3 Blöcken (Vormittag + Abend). + +## Phasen + +- **ζ-0 — Setup.** Repo-Skelett, `project.yml` (XcodeGen), ManaCore + + ManaTokens als Package-Dependency, leerer Build im Simulator + grün, `/healthz`-Probe gegen `zitare-api.mana.how`. +- **ζ-1 — WebShellView.** `WKWebView` als `UIViewRepresentable`/ + `NSViewRepresentable`-Bridge, Universal-Link-Routing, Cookie-SSO- + Bridge (`mana.access` auf `.mana.how`). +- **ζ-1 abgeschlossen** — `DeepLinkRouter` + Web-Header-Hide via + injizierter CSS. Header + Footer der Website werden in der App + ausgeblendet, weil App-Chrome reicht. +- **ζ-2 native** — `SwiftData`-Snapshot-Cache + `DailyQuoteWidget` + vorbereitet. Snapshot kommt von `https://zitare.com/index-min.json`, + App-Group `group.ev.mana.zitare` reicht es an Widget durch. +- **ζ-1 Polish** — robuster Header-Selektor (DOM-Drift-Tolerant), + `zitare.mana.how` als zweite UL-Domain. +- **Cloudflare-TODO + PLAN.md externe Blocker.** + `zitare.mana.how`-DNS-Record + CNAME-Cleanup nötig, sonst + AASA-Validation flapsig. +- **TestFlight-Validation grün** — Icon-Asset + `CFBundleIconName` + korrekt gesetzt. Erste Upload-Versuche scheiterten an iconAsset. +- **Icon-Platzhalter** — vereinfachte Anführungszeichen-Glyphe, + Pixel-Render. Echtes Icon kommt vor Submit. +- **Mac-Window + Konto-Header** nach erstem TestFlight-Build. +- **CFBundleVersion 2** für nächsten Upload-Roundtrip. +- **Dark-Mode-Fix** — WebView folgt System-`prefers-color-scheme` + statt zitare.com-localStorage-Toggle. Vorher hat man im App-Modus + unbeabsichtigt den Web-Schalter umgestellt. + +## Architektur-Entscheidungen + +- **Hybrid ausnahmsweise.** Lese-Surfaces via `WKWebView`, Native- + Surfaces (Widget, ShareExt, Submit, Spotlight) pure SwiftUI. + Trennung ist fest — keine schleichende Native-Re-Implementation + von Read-Routes (CLAUDE.md Invariante 1, „Don't do"). +- **AASA-Domain `zitare.com`**, nicht `zitare.mana.how`. Public-URL + trägt die App, mana.how ist API/Backstage. +- **Cookie-SSO-Bridge** statt JWT-Header in WebView. Domain + `.mana.how` setzt Cookie, WebView lädt `zitare.mana.how` mit + Cookie automatisch. +- **Snapshot lokal für Widget + Spotlight**, nicht für WebView. + WebView lädt live, Widget/Spotlight können nicht live laden + (Background-Refresh-Budget). +- **Header-Hide via injizierter CSS**, statt eigene App-Routes. + Selektor robust gegen DOM-Drift; bricht im worst case lautlos, + zeigt aber dann Header — kein Crash. +- **Theme: `paper`-Variant** aus `@mana/themes/paper`, lokal in + `ZitareTheme.swift` nachgebaut. Match zur Website. + +## Trade-offs + +- **WebView-Hybrid** spart Native-Read-Surface-Aufwand komplett, + aber: WebView-DOM ist nicht App-DOM. Selektor-Drift, Cookie- + Sync-Edge-Cases, Performance-Regressions im JS sind Web-Sorgen, + nicht App-Sorgen — und wir merken sie hier später. +- **`zitare.com` als AASA-Domain + `zitare.mana.how` als zweite**: + doppelte Universal-Link-Logik. Wenn Web-Routing sich ändert, + muss App + AASA + Web nachziehen. +- **Snapshot-Pull bei Launch** macht App schneller-startend gegen + Widget-Daten, kostet aber bei jedem Cold-Start 11+ Quotes + Bandbreite. Bei 50 k Quotes-Korpus später Schmerz; heute + irrelevant. +- **TestFlight-Roundtrip** kostet Iterationen — `CFBundleIconName` + fehlte, `Icon`-Asset hatte falsche Größe, dadurch zwei Failed- + Validations. Standard für native App-Erstbuilds. + +## Offene Punkte + +- **DNS-CNAME für `zitare.mana.how`** in Cloudflare setzen, alter + CNAME entfernen. +- **Echtes AppIcon** statt vereinfachter Anführungszeichen-Glyphe. +- **ζ-3 Submit-View** in SwiftUI mit ManaAuthGate (Action-Level- + Login-Eskalation). Pending. +- **ζ-4 Spotlight + ShareExtension + App Intents.** Pending. +- **ζ-5 Polish** — iPad-Split-Layout, Accessibility. +- **ζ-6 App-Store-Submission** — Bundle `ev.mana.zitare`, Team + registriert. +- **DailyQuoteWidget auf echtem Gerät** testen — Simulator zeigt's, + echtes iPhone-Widget-Behavior ist gelegentlich anders. diff --git a/devlog/2026-05-14/spieler.md b/devlog/2026-05-14/spieler.md new file mode 100644 index 0000000..8e66c90 --- /dev/null +++ b/devlog/2026-05-14/spieler.md @@ -0,0 +1,43 @@ +--- +date: 2026-05-14 +day: 1 +view: spieler +weekday: Donnerstag +commits: 11 +review: written +--- +# Donnerstag, 2026-05-14 — Tag 1 + +Zitare bekommt eine eigene App. Anders als bei Memoro, Cards oder +Manaspur **bringt sie nicht alles neu**: Lesen, Suchen und Stöbern +machst du weiterhin auf der Website (zitare.com), die App schält sich +nur drumherum — und legt obendrauf Sachen, die nur am iPhone oder +Mac Sinn ergeben. + +## Was die App heute schon kann + +- **zitare.com lädt als App auf, ohne Browser-Drumherum.** Header und + Footer werden ausgeblendet, weil dein Telefon sie nicht braucht. +- **Universal-Links** funktionieren: Wer einen Zitat-Link in + Messenger/Mail tippt, landet direkt in der App, nicht im Browser. +- **Zitat-des-Tages-Widget** auf dem Home-Screen oder Sperrbildschirm + (in Vorbereitung — Datenbasis lokal gespiegelt, Widget-Surface + steht). +- **System-Dunkelmodus** — die App folgt deinem iPhone, kein eigener + Schalter. + +## Was offen ist + +- **Eigene Zitate einsenden** — die Submit-Maske kommt als nächstes, + inkl. Anmeldung über deinen Verein-Account. +- **Aus anderer App teilen → Zitare** (Share-Extension) — vorbereitet, + nicht aktiv. +- **System-weite Suche (Spotlight)** — vorbereitet, nicht aktiv. +- **TestFlight** läuft, aber wartet noch auf den endgültigen Domain- + Switch (`zitare.mana.how` wird ergänzt). + +## Hintergrund + +Zitare ist Lese-App, keine Tipp-App. Die Website kann das gut, die +App soll sich nicht in den Weg stellen. Deshalb: dünne Hülle um das +Web plus Widget, Suche und „in Zitare schicken" — sonst nichts. diff --git a/devlog/2026-05-15/data.json b/devlog/2026-05-15/data.json new file mode 100644 index 0000000..bde5f27 --- /dev/null +++ b/devlog/2026-05-15/data.json @@ -0,0 +1,73 @@ +{ + "date": "2026-05-15", + "day_number": 2, + "weekday": "Freitag", + "commits": 1, + "authors": [ + { + "name": "Till JS", + "count": 1 + } + ], + "additions": 54, + "deletions": 1, + "net_lines": 53, + "files_changed": 3, + "new_files": 0, + "deleted_files": 0, + "session": { + "first_commit_at": "2026-05-15T11:59:49.000Z", + "last_commit_at": "2026-05-15T11:59:49.000Z", + "total_span_minutes": 0, + "active_minutes": 0, + "pauses": [], + "longest_focus_minutes": 0 + }, + "top_dirs": [ + { + "path": "Sources/Features/WebShell", + "pct": 33 + }, + { + "path": "Sources/Resources/Assets.xcassets", + "pct": 33 + }, + { + "path": "project.yml", + "pct": 33 + } + ], + "top_extensions": [ + { + "ext": ".swift", + "count": 1 + }, + { + "ext": ".json", + "count": 1 + }, + { + "ext": ".yml", + "count": 1 + } + ], + "tags": [ + "launch" + ], + "commits_list": [ + { + "hash": "cbc9af6", + "short": "fix(launch): drei Layer weißen Flash beim Start gefixt", + "type": "fix", + "scope": "launch", + "additions": 54, + "deletions": 1, + "timestamp": "2026-05-15T13:59:49+02:00" + } + ], + "review_state": "auto", + "llm": { + "model": null, + "generated_at": null + } +} diff --git a/devlog/2026-05-15/macher.md b/devlog/2026-05-15/macher.md new file mode 100644 index 0000000..6c67342 --- /dev/null +++ b/devlog/2026-05-15/macher.md @@ -0,0 +1,62 @@ +--- +date: 2026-05-15 +day: 2 +view: macher +weekday: Freitag +commits: 1 +review: written +--- +# Freitag, 2026-05-15 — Tag 2 (Macher-Sicht) + +Ein-Commit-Tag: drei aufeinanderfolgende weiße Flashes beim App- +Start gefixt. Klassisch unauffällig, aber spürbar polish. + +## Stats + +1 Commit, +54 / −1 LoC, 3 Files (Launch-Screen, Asset-Catalog, +`project.yml`). Tag `launch`. Active-Time 0 Min (Single-Commit). + +## Was passierte + +Drei Layer waren weiß, bis der WebView-Content da war: + +1. **Launch-Screen** war Default (System-Weiß). +2. **App-Window-Background** war `.systemBackground` ohne explizite + Override → folgte zwar Dark-Mode, aber zeigte Weiß im Light- + Mode. +3. **WebView-Background** war default-weiß, bis die geladene + Seite ihre Background-Farbe ausspielen konnte (typisch 200–400 ms + auf 4G). + +Fix: + +- **Launch-Screen** mit dunklem Paper-Theme-Background. +- **App-Window-Background** auf `ZitareTheme.background` festgesetzt, + Hintergrund matched System-Theme. +- **WebView.isOpaque = false** + `backgroundColor` = Theme- + Background. Browser-Engine rendert auf transparenten Hintergrund, + sodass App-Background durchscheint bis der Web-Background da ist. + +## Architektur-Bemerkung + +WebShell hat damit erstmals einen sauberen „App-Frame", der nicht +vom Web-Content abhängt. Künftige Features (Pull-to-Refresh-Indicator, +Bottom-Toolbar) können sich auf den Frame verlassen, ohne sich am +Web-Rendering-Zeitpunkt zu orientieren. + +## Trade-offs + +- **WebView-Transparenz** ist in seltenen WebKit-Versionen eine + Render-Quelle für Tearing. Acceptable; falls Reports kommen, + zurück auf opaque mit synchron gesetztem Background. +- **Hardcoded Background-Farbe** in 3 Stellen (LaunchScreen, App- + Window, WebView). Wenn Theme-Switch kommt, müssen alle 3 + nachziehen. ZitareTheme-Bridge sollte das später kapseln. + +## Offene Punkte + +- **Hardcoded-Theme-Background-Trio** in eine Bridge ziehen vor + Theme-Variants-Release. +- **ζ-3 Submit-View** bleibt offen (Tag 1 nicht angefangen). +- **TestFlight-Build** mit dem Fix raus — externe Validation steht + noch aus. diff --git a/devlog/2026-05-15/spieler.md b/devlog/2026-05-15/spieler.md new file mode 100644 index 0000000..e9ee9a8 --- /dev/null +++ b/devlog/2026-05-15/spieler.md @@ -0,0 +1,19 @@ +--- +date: 2026-05-15 +day: 2 +view: spieler +weekday: Freitag +commits: 1 +review: written +--- +# Freitag, 2026-05-15 — Tag 2 + +Kleine, aber spürbare Änderung: **kein weißes Aufblitzen mehr beim +App-Start**. Wenn du Zitare öffnest, geht der Bildschirm sauber von +dunkel in den Inhalt, ohne kurz weiß zu sein. + +## Hintergrund + +Ein App-Start war eine Kette aus drei kurzen weißen Bildschirmen +(Launch-Screen, App-Background, WebView, bevor die Seite gerendert +ist). Das ist heute behoben. Beim nächsten Update merkst du es.