devlog: 2 Tage geschrieben (ζ-0 + ζ-1 + Launch-Flash-Fix)
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) <noreply@anthropic.com>
This commit is contained in:
parent
cbc9af6bb0
commit
37840e6172
6 changed files with 498 additions and 0 deletions
200
devlog/2026-05-14/data.json
Normal file
200
devlog/2026-05-14/data.json
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
101
devlog/2026-05-14/macher.md
Normal file
101
devlog/2026-05-14/macher.md
Normal file
|
|
@ -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.
|
||||
43
devlog/2026-05-14/spieler.md
Normal file
43
devlog/2026-05-14/spieler.md
Normal file
|
|
@ -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.
|
||||
73
devlog/2026-05-15/data.json
Normal file
73
devlog/2026-05-15/data.json
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
62
devlog/2026-05-15/macher.md
Normal file
62
devlog/2026-05-15/macher.md
Normal file
|
|
@ -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.
|
||||
19
devlog/2026-05-15/spieler.md
Normal file
19
devlog/2026-05-15/spieler.md
Normal file
|
|
@ -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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue