Presets + Custom-Moods + Sequenzen sind über CSSearchable im Spotlight + Siri-Vorschlägen auffindbar. Tippen routet via `uniqueIdentifier` (Format `mood:<id>` / `sequence:<id>`) in RootView zurück → öffnet MoodPlayerView (Moods) oder springt in Sequenzen-Tab. Sources/Core/Search/SpotlightIndexer.swift mit zwei Domains (`ev.mana.moodlit.moods`, `ev.mana.moodlit.sequences`). Domain- basiertes `deleteSearchableItems` clearen beim Logout — kein Eintrag des abgemeldeten Kontos bleibt im system-weiten Index. MoodStore-Integration: - `refreshSpotlightIndex()` läuft initial im RootView-`task` (Presets sofort findbar ohne Login) und nach jedem `loadAll`. - `clearSpotlightIndex()` beim Auth-Wechsel signedOut. RootView: - `onContinueUserActivity(CSSearchableItemActionType)` parsed den uniqueIdentifier mit prefix-Check, setzt deepLinkMoodId oder selectedTab. - `authStatusKey()`-Helper für Equatable-onChange auf AuthClient.Status (Cases mit assoziierten Werten sind nicht direkt Equatable). xcodebuild iOS-Sim + macOS BUILD SUCCEEDED; 11/11 Unit-Tests grün. ShareExt (Photo→Palette→Mood) wäre der natürliche moodlit-Use- Case, ist aber 2-3h Vision/CoreImage-Arbeit für sich — deferred auf eigenen Sprint. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
162 lines
7.2 KiB
Markdown
162 lines
7.2 KiB
Markdown
# Moodlit-Native — Status
|
||
|
||
Letzter Stand: **2026-05-18**
|
||
|
||
## Phase
|
||
|
||
**μ-7.7 ✅ Spotlight-Indexing.** Presets + Custom-Moods + Sequenzen
|
||
sind in CSSearchable. Tap im Spotlight öffnet Player oder springt
|
||
in Sequenzen-Tab. Logout cleared den Index. Build weiter grün
|
||
iOS + macOS, 11/11 Unit-Tests grün. **Bereit für TestFlight-Upload
|
||
sobald Apple-Dev-Portal-Setup steht (Till manuell).**
|
||
|
||
## Was steht — μ-7.0
|
||
|
||
- **Pure-Native Architektur** (kein WebView). SwiftUI Universal
|
||
iOS 18 + macOS 15.
|
||
- **`ManaCore` + `ManaTokens` + `ManaAuthUI`** via XcodeGen local-path-
|
||
Packages. Theme = `ManaTheme.twilight` Forward, Login-Sheets im
|
||
Moodlit-Violett-Branding.
|
||
- **`MoodlitAPI`** Actor mit allen CRUD-Endpoints (Moods, Sequences,
|
||
Preferences) via `AuthenticatedTransport`. JWT-Refresh + 401-Retry
|
||
kommen aus ManaCore.
|
||
- **24 Presets** als Swift-Konstanten in `DefaultMoods.all` (Port
|
||
von `default-moods.ts`, identische Reihenfolge + IDs).
|
||
- **21 AnimationTypes** in `AnimatedMoodView` als TimelineView mit
|
||
30-fps-Modulation (`brightness`/`opacity`/`hueRotation`/`scale`).
|
||
Eigene Implementierungen für `sunrise/sunset/sos`, der Rest ist
|
||
`sin/cos`-Formel.
|
||
- **`MoodPlayerView`** — Vollbild mit Play/Pause, 1/5/10/15/30/60min-
|
||
Timer, Favorite-Toggle, Auto-Hide-Controls nach 3s, **Idle-Timer-
|
||
Disabled** (kein Screen-Lock), Status-Bar-Hidden auf iOS.
|
||
- **`SequencePlayerView`** — **Net new gegenüber Web!** Crossfade
|
||
durch alle Moods nach `durationSec` Sekunden, `transitionSec`
|
||
Übergang, Next/Prev/Pause-Controls.
|
||
- **Cards-Pattern Auth-Gate** — Presets sichtbar ohne Login, beim
|
||
ersten Klick auf "Neues Mood" / "Neue Sequenz" springt der
|
||
`ManaAuthGate` mit Login-Sheet auf.
|
||
- **App-Group `group.ev.mana.moodlit`** für UserDefaults-Sharing
|
||
(Guest-Favoriten lokal, Widget-Daten ab μ-7.6).
|
||
|
||
## Was steht — μ-7.1
|
||
|
||
- **Hex-Color-Picker funktioniert**: `Color.toHexString()` via
|
||
PlatformColor (UIColor iOS / NSColor macOS sRGB), CreateMoodSheet
|
||
hält `[String]` (Hex) als SOT, ColorPicker + TextField binden
|
||
beidseitig konvertierend.
|
||
- **Random Hex** für „+ Farbe hinzufügen".
|
||
|
||
## Was steht — μ-7.2 (Tests)
|
||
|
||
11 Tests in `Tests/UnitTests/DomainCodingTests.swift`, alle grün:
|
||
- Mood/MoodSequence/Preferences Decode-Roundtrip gegen API-Wire-Format
|
||
- AnimationSpeed slow/normal/fast Enum-Decoding
|
||
- DefaultMoods: 24 Einträge, unique IDs, bekannte Slugs, alle
|
||
AnimationTypes vorhanden
|
||
- HexColor Parsing-Smoke
|
||
|
||
## Was steht — μ-7.3 (Widget + Deep-Links)
|
||
|
||
- **`WidgetSnapshot`** Codable-Bridge App↔Widget via App-Group-
|
||
UserDefaults (`group.ev.mana.moodlit`). Speichert Favoriten +
|
||
Last-Played mit flachen Hex-Colors statt SwiftUI Color
|
||
(Widget-Process kann keine App-Bundle-Color dereferenzieren).
|
||
- **`MoodStore.refreshWidgetSnapshot`** läuft nach jedem `loadAll`
|
||
und `toggleFavorite`, pingt `WidgetCenter.shared.reloadAllTimelines()`.
|
||
- **`MoodlitWidgetExtension`** (iOS-only app-extension,
|
||
Bundle `ev.mana.moodlit.widget`) mit 3 Größen:
|
||
- Small: Last-Played oder erstes Favorit als Glow-Tile
|
||
- Medium: 2×2-Grid mit bis zu 4 Favoriten
|
||
- Large: 3×3-Grid mit bis zu 9 Favoriten + Footer-Count
|
||
- **Deep-Links** `moodlit://play/<id>` (Custom-Scheme aus Widget-
|
||
Tap) UND `https://moodlit.mana.how/play/<id>` (Universal-Link
|
||
via AASA) öffnen `MoodPlayerView` als fullScreenCover über
|
||
RootView — funktioniert egal welcher Tab gerade aktiv ist.
|
||
- Widget-Extension korrekt in `MoodlitNative.app/PlugIns/` embedded
|
||
(verifiziert per `find /tmp/...-dd`).
|
||
|
||
## Was steht — μ-7.4 (TestFlight-Blocker behoben)
|
||
|
||
- `Sources/Resources/Assets.xcassets/AppIcon.appiconset/` mit
|
||
1024×1024 Moodlit-Glow-PNG (Python PIL: radialer Verlauf hell-
|
||
Lavendel → #7c3aed → dunkel-Violett + 8 verschwommene Strahlen).
|
||
- Contents.json mit 3 Einträgen (light/dark/tinted Pattern für
|
||
iOS 18).
|
||
- Asset-Catalog-Compiler generiert daraus automatisch alle Sizes
|
||
inklusive iPhone 120×120 und iPad 152×152, CFBundleIconName
|
||
landet im Info.plist.
|
||
|
||
## Was steht — μ-7.6 (Settings-UI)
|
||
|
||
- Neuer Settings-Tab in TabView (iOS) + Sidebar (macOS).
|
||
- Helligkeit-Slider 20–100% → `Preferences.brightness`, debounced
|
||
PATCH alle 600ms.
|
||
- Animations-Tempo Picker slow/normal/fast → `Preferences.animationSpeed`.
|
||
- Standard-Timer-Dauer (Aus/1/5/10/15/30/60 min) in App-Group-
|
||
UserDefaults — Player liest beim onAppear.
|
||
- Guest-Hinweis: lokale Werte aktiv, persistieren erst nach Login.
|
||
- `MoodStore.playerBrightness/playerSpeedMultiplier` als Convenience-
|
||
Reader für `MoodPlayerView` (über `.brightness()`-Modifier +
|
||
AnimatedMoodView-speedMultiplier-Parameter).
|
||
|
||
## Was steht — μ-7.7 (Spotlight)
|
||
|
||
- `Sources/Core/Search/SpotlightIndexer.swift` mit zwei Domains
|
||
(`ev.mana.moodlit.moods`, `ev.mana.moodlit.sequences`).
|
||
- CSSearchableItem pro Mood (title=name, description=Animation-
|
||
Display-Name, keywords=Slug+Display+Stimmung+Mood+Sequence) und
|
||
pro Sequence (title=name, description=Anzahl + Dauer/Mood).
|
||
- `MoodStore.refreshSpotlightIndex` läuft initial im RootView-`task`
|
||
(Presets sofort findbar, auch ohne Login) und nach jedem `loadAll`.
|
||
- `clearSpotlightIndex` beim Auth-Wechsel auf signedOut — keine
|
||
Einträge eines abgemeldeten Kontos bleiben im system-weiten Index.
|
||
- RootView `onContinueUserActivity(CSSearchableItemActionType)`
|
||
parsed den uniqueIdentifier (`mood:<id>` / `sequence:<id>`),
|
||
routet zu Player oder Sequenzen-Tab.
|
||
|
||
## Was noch fehlt
|
||
|
||
- **μ-7.5 Apple-Dev-Portal** — Bundle `ev.mana.moodlit` + Widget-
|
||
Bundle `ev.mana.moodlit.widget` + Capabilities (Associated
|
||
Domains, App Groups, Keychain Sharing) manuell anlegen (Till).
|
||
- **μ-7.6 ASC App-Record** + TestFlight-Upload (nach Apple-Dev-
|
||
Portal-Setup).
|
||
- **μ-7.8 Visual-Polish**: feinere Animationskurven, evtl. `Canvas`-
|
||
basierte Partikel für `sparkle`/`aurora`. Brightness-Slider
|
||
hat heute via `.brightness(b - 1.0)` einen einfachen Mapping —
|
||
visueller Test auf echter Hardware fehlt.
|
||
- **ShareExt (deferred)**: Photo → Palette-Extraktion → vorgefülltes
|
||
CreateMoodSheet wäre der natürliche moodlit-Use-Case (Sunset-Foto
|
||
→ Sunset-Mood), ist aber 2-3h Vision/CoreImage-Arbeit für sich.
|
||
Nicht in μ-7.7 enthalten.
|
||
|
||
## Build-Verification
|
||
|
||
```bash
|
||
# iOS Simulator
|
||
xcodebuild -project MoodlitNative.xcodeproj -scheme MoodlitNative \
|
||
-destination 'platform=iOS Simulator,name=iPhone 17' \
|
||
-derivedDataPath /tmp/moodlit-native-dd \
|
||
CODE_SIGNING_ALLOWED=NO build
|
||
# → ** BUILD SUCCEEDED **
|
||
|
||
# macOS
|
||
xcodebuild -project MoodlitNative.xcodeproj -scheme MoodlitNative \
|
||
-destination 'platform=macOS' \
|
||
-derivedDataPath /tmp/moodlit-native-mac \
|
||
CODE_SIGNING_ALLOWED=NO build
|
||
# → ** BUILD SUCCEEDED **
|
||
```
|
||
|
||
## Bewusst nicht gemacht
|
||
|
||
- **Hybrid mit WKWebView** — Pure-Native gewählt wegen Player-
|
||
Anforderungen (Idle-Timer-Disable, echtes Vollbild, native Effekte).
|
||
- **`autoMoodSwitch`-Random-Mode** — Schema-Feld ist in `Preferences`,
|
||
UI dafür kommt mit μ-7.7.
|
||
- **Local SwiftData-Caching** — App lebt vom Server (loadAll bei
|
||
Mount + scenePhase==.active). Offline-Read kann mit μ-9+ kommen
|
||
via mana-sync-Integration (analog Herbatrium).
|
||
- **Particle-System für `sparkle`** — Web-Version hat das auch nicht
|
||
(war im alten managarten als float-up keyframes, im Lift verworfen).
|
||
Brightness-Puls reicht für MVP.
|