6.0 KiB
Architektur
Überblick
FeelAloud ist eine einzelne native iOS-App ohne Backend und ohne externe Paketabhängigkeiten. Alle Produktdaten werden mit Apple-Frameworks auf dem Gerät verarbeitet. Das Xcode-Projekt enthält derzeit ein App-Target.
Komponenten
| Datei | Verantwortung |
|---|---|
FeelAloudApp.swift |
App-Einstieg, SwiftData-Container und globaler Router |
RootView.swift |
Tabs, Sheets, App-Intent-Ausführung und Follow-up-Auswahl |
HomeView.swift |
Startseite, Schnellaktionen und 7-Tage-Zusammenfassung |
EntryFlowView.swift |
Aufnahme-, Analyse-, Prüf- und Speicherablauf |
SpeechRecognizer.swift |
Mikrofon, lokale deutsche Spracherkennung und Transkript |
MoodAnalysisService.swift |
Typisierte Extraktion über Foundation Models |
MoodEntry.swift |
Datenmodell eines ausführlichen Tagebucheintrags |
MoodSnapshot.swift |
Datenmodell und Regeln eines kurzen Check-ins |
SnapshotView.swift |
Fünf-Stufen-Auswahl und spätere Kontextfrage |
SnapshotNotificationScheduler.swift |
Lokale Erinnerungen und Notification-Routing |
HistoryView.swift |
Zeitraumfilter, Diagramm, Detailansichten und Exportstart |
SettingsView.swift |
Erinnerungszeiten, KI-Status, CSV-Export und Hinweise |
XLSXExporter.swift |
OOXML-Arbeitsmappe und minimaler ZIP-Writer |
CSVExporter.swift |
Semikolon-CSV mit UTF-8-BOM für Numbers/Excel |
StartDiaryEntryIntent.swift |
Kurzbefehl und Action-Button-Integration |
ShareSheet.swift |
Übergang zum systemweiten iOS-Share-Sheet |
Datenfluss: ausführlicher Eintrag
EntryFlowViewstartetSpeechRecognizer.SpeechRecognizerfordert Mikrofon- und Speech-Berechtigung an und setztrequiresOnDeviceRecognition = true.- Nach dem Stoppen erhält
MoodAnalysisServiceausschließlich das erkannte Transkript. LanguageModelSessionerzeugt eine typisierteGeneratedDiaryEntry-Antwort.- Die Person prüft und korrigiert alle Werte im Formular.
- Erst die bestätigten Werte werden als
MoodEntryin SwiftData gespeichert.
Ist Sprache oder Foundation Models nicht verfügbar, kann die Person zur manuellen Eingabe wechseln. Die App fällt nicht auf einen eigenen Cloud-Dienst zurück.
Datenfluss: Momentaufnahme
- Ein Check-in wird manuell oder über eine lokale Mitteilung geöffnet.
- Ein Tipp erzeugt einen
MoodSnapshotmit Wert 1 bis 5 und Quelle. - Bei Sehr gut, Schlecht oder Sehr schlecht bleibt
awaitsFollowUpaktiv. - Beim nächsten normalen Aktivieren der App am selben Kalendertag sucht
RootViewden jüngsten offenen Snapshot. - Eine Antwort setzt
followUpNote; Heute nicht mehr fragen setztfollowUpDismissed.
Das direkte Öffnen aus einer Mitteilung unterdrückt genau eine sofortige Follow-up-Prüfung, damit zuerst die gewünschte Fünf-Stufen-Auswahl erscheint.
Persistenz
Der ModelContainer verwaltet zwei SwiftData-Modelle:
MoodEntry
| Feld | Zweck |
|---|---|
id, createdAt |
Eindeutigkeit und Zeitpunkt |
moodRaw |
Dreistufige Bewertung des ausführlichen Eintrags |
musicInHead, songName, earwormStrengthRaw |
Musik-/Ohrwurmangaben |
socialContact |
Sozialkontakt vorhanden |
distressRaw |
Leidensdruck durch Musik im Kopf |
countermeasures, countermeasureActivity |
Gegenmaßnahmen |
stress |
Stress, wenn keine Musik im Kopf vorhanden ist |
transcript |
Bestätigter gesprochener Text |
MoodSnapshot
| Feld | Zweck |
|---|---|
id, createdAt |
Eindeutigkeit und Zeitpunkt |
ratingRaw |
Fünfstufige Bewertung |
followUpNote |
Später ergänzter Kontext |
followUpDismissed |
Kontextfrage für diesen Snapshot verworfen |
sourceRaw |
manual oder notification |
Für zukünftige Schemaänderungen muss vor Veröffentlichung einer inkompatiblen
Version ein VersionedSchema mit SchemaMigrationPlan eingeführt werden.
Routing und Lebenszyklus
AppRouter ist ein @MainActor-gebundener, beobachtbarer Singleton. Er hält
nur flüchtigen UI-Zustand. RootView reagiert auf:
- manuelle Aktionen der Oberfläche;
StartDiaryEntryIntent;- Antworten auf lokale Mitteilungen;
- Wechsel der
scenePhasezurück zu.active.
Persistente Produktdaten liegen nicht im Router, sondern ausschließlich in
SwiftData beziehungsweise @AppStorage für Erinnerungseinstellungen.
Erinnerungen
SnapshotNotificationScheduler verwendet drei stabile Request-IDs. Beim
Ändern der Konfiguration werden bestehende Requests entfernt und neu geplant.
Die Trigger enthalten nur Stunde und Minute und wiederholen sich täglich.
Es handelt sich um lokale Notifications. APNs, Push-Zertifikate und ein Server sind nicht erforderlich.
Export
Der XLSX-Exporter erstellt drei Arbeitsblätter:
- Übersicht – Zeitraum, Anzahl, Durchschnitt und Verteilung;
- Momentaufnahmen – Zeitpunkt, Bewertung, Kontext und Quelle;
- Tagebuch – strukturierte Felder und Transkript.
Die Arbeitsmappe besteht aus OOXML-Dateien in einem unkomprimierten ZIP-Archiv. Text wird XML-escaped; ZIP-Einträge erhalten CRC32-Prüfsummen. Der CSV-Export bleibt als kompatibler Alt-Export für ausführliche Einträge erhalten.
Temporäre Exportdateien werden im temporären App-Verzeichnis erzeugt und erst nach einer ausdrücklichen Aktion an das Share-Sheet übergeben.
Fehler- und Verfügbarkeitsmodell
- Fehlende Berechtigungen werden als verständliche, lokale Fehlermeldung angezeigt.
- Fehlende lokale Spracherkennung verhindert eine versehentliche Cloud- Transkription.
- Vor jeder KI-Nutzung wird
SystemLanguageModel.default.availabilitygeprüft. - Fehler beim Speichern werden aktuell nicht sichtbar eskaliert (
try?). Vor einem öffentlichen Release sollte dafür ein zentraler Fehlerpfad ergänzt werden. - FeelAloud erteilt keine medizinischen Ratschläge und gibt dem Modell ausdrücklich nur eine Extraktionsaufgabe.
Abhängigkeiten
Es gibt keine Drittanbieterpakete. Verwendete Frameworks:
- AppIntents
- AVFoundation
- Charts
- Foundation / FoundationModels
- Observation
- Speech
- SwiftData
- SwiftUI
- UIKit
- UserNotifications