moodlit-native/STATUS.md
till 206fff422e μ-7.7: Spotlight-Indexing für Moods + Sequenzen
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>
2026-05-18 15:39:42 +02:00

7.2 KiB
Raw Permalink Blame History

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.
  • SequencePlayerViewNet 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
  • 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 20100% → 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

# 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.