From 0b354030960af6ae6401e349755a572f3ae9110b Mon Sep 17 00:00:00 2001 From: Sven Date: Fri, 17 Apr 2026 20:59:33 +0200 Subject: [PATCH] Share aus Chat --- nahbar/.DS_Store | Bin 6148 -> 6148 bytes nahbar/nahbar.xcodeproj/project.pbxproj | 4 + .../UserInterfaceState.xcuserstate | Bin 40173 -> 49959 bytes nahbar/nahbar/AppGroup.swift | 12 +- nahbar/nahbar/ContentView.swift | 3 +- nahbar/nahbar/LogbuchView.swift | 10 ++ nahbar/nahbar/Models.swift | 27 ++++- nahbar/nahbar/NahbarApp.swift | 2 +- nahbar/nahbar/NahbarMigration.swift | 113 ++++++++++++++++++ nahbar/nahbar/PersonDetailView.swift | 64 ++++++++-- .../ShareExtensionView.swift | 12 +- 11 files changed, 232 insertions(+), 15 deletions(-) create mode 100644 nahbar/nahbar/NahbarMigration.swift diff --git a/nahbar/.DS_Store b/nahbar/.DS_Store index e23afc69af0d0f6f0238f5acf4e63a4c9d948d57..f7aed53dd43b0e96c094f5759a236423fb502807 100644 GIT binary patch delta 49 ycmZoMXffCj&cqaCIe8+J+T?mBF4o11QlCUk?qf2Bv(zWQW#VIO*!+iyLlgkCk`clH delta 49 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 Jp3lyw{||@HoTmT) diff --git a/nahbar/nahbar/AppGroup.swift b/nahbar/nahbar/AppGroup.swift index de4e55d..8e1d4ed 100644 --- a/nahbar/nahbar/AppGroup.swift +++ b/nahbar/nahbar/AppGroup.swift @@ -36,10 +36,16 @@ enum AppGroup { /// Speichert eine Nachricht als ausstehenden Moment in der App Group. /// Die Hauptapp importiert diese beim nächsten Start. - static func enqueueMoment(personName: String, text: String, type: String) { + static func enqueueMoment(personName: String, text: String, type: String, source: String? = nil) { var queue = pendingMoments - queue.append(["personName": personName, "text": text, "type": type, - "createdAt": ISO8601DateFormatter().string(from: Date())]) + var entry: [String: String] = [ + "personName": personName, + "text": text, + "type": type, + "createdAt": ISO8601DateFormatter().string(from: Date()) + ] + if let source { entry["source"] = source } + queue.append(entry) if let data = try? JSONSerialization.data(withJSONObject: queue) { userDefaults.set(data, forKey: "pendingMoments") } diff --git a/nahbar/nahbar/ContentView.swift b/nahbar/nahbar/ContentView.swift index ff40e88..f67b5fb 100644 --- a/nahbar/nahbar/ContentView.swift +++ b/nahbar/nahbar/ContentView.swift @@ -106,8 +106,9 @@ struct ContentView: View { let text = entry["text"], let typeRaw = entry["type"] else { continue } let type_ = MomentType(rawValue: typeRaw) ?? .conversation + let source_ = entry["source"].flatMap { MomentSource(rawValue: $0) } if let person = persons.first(where: { $0.name == name }) { - let moment = Moment(text: text, type: type_, person: person) + let moment = Moment(text: text, type: type_, source: source_, person: person) modelContext.insert(moment) person.moments?.append(moment) } diff --git a/nahbar/nahbar/LogbuchView.swift b/nahbar/nahbar/LogbuchView.swift index 83dedba..c924c5d 100644 --- a/nahbar/nahbar/LogbuchView.swift +++ b/nahbar/nahbar/LogbuchView.swift @@ -1,4 +1,5 @@ import SwiftUI +import CoreData // MARK: - AI Analysis State @@ -60,6 +61,7 @@ private enum LogbuchItem: Identifiable { struct LogbuchView: View { @Environment(\.nahbarTheme) var theme + @Environment(\.dismiss) var dismiss @StateObject private var store = StoreManager.shared let person: Person @@ -92,6 +94,14 @@ struct LogbuchView: View { .navigationBarTitleDisplayMode(.inline) .themedNavBar() .sheet(isPresented: $showPaywall) { PaywallView() } + .onReceive( + NotificationCenter.default.publisher( + for: Notification.Name("NSManagedObjectContextObjectsDidChangeNotification") + ) + ) { notification in + guard notification.userInfo?[NSInvalidatedAllObjectsKey] != nil else { return } + dismiss() + } .onAppear { if let cached = AIAnalysisService.shared.loadCached(for: person) { analysisState = .result(cached.asResult, cached.analyzedAt) diff --git a/nahbar/nahbar/Models.swift b/nahbar/nahbar/Models.swift index d2f3ef8..cf75ec3 100644 --- a/nahbar/nahbar/Models.swift +++ b/nahbar/nahbar/Models.swift @@ -55,6 +55,24 @@ enum MomentType: String, CaseIterable, Codable { } } +enum MomentSource: String, CaseIterable, Codable { + case whatsapp = "WhatsApp" + case imessage = "iMessage" + case telegram = "Telegram" + case signal = "Signal" + case other = "Chat" + + var icon: String { + switch self { + case .whatsapp: return "message.fill" + case .imessage: return "message.fill" + case .telegram: return "paperplane.fill" + case .signal: return "lock.circle.fill" + case .other: return "bubble.left.fill" + } + } +} + // MARK: - Person @Model @@ -218,13 +236,15 @@ class Moment { var id: UUID = UUID() var text: String = "" var typeRaw: String = MomentType.conversation.rawValue + var sourceRaw: String? = nil var createdAt: Date = Date() var person: Person? - init(text: String, type: MomentType = .conversation, person: Person? = nil) { + init(text: String, type: MomentType = .conversation, source: MomentSource? = nil, person: Person? = nil) { self.id = UUID() self.text = text self.typeRaw = type.rawValue + self.sourceRaw = source?.rawValue self.createdAt = Date() self.person = person } @@ -233,4 +253,9 @@ class Moment { get { MomentType(rawValue: typeRaw) ?? .conversation } set { typeRaw = newValue.rawValue } } + + var source: MomentSource? { + get { sourceRaw.flatMap { MomentSource(rawValue: $0) } } + set { sourceRaw = newValue?.rawValue } + } } diff --git a/nahbar/nahbar/NahbarApp.swift b/nahbar/nahbar/NahbarApp.swift index 7becc21..6f45d03 100644 --- a/nahbar/nahbar/NahbarApp.swift +++ b/nahbar/nahbar/NahbarApp.swift @@ -43,7 +43,7 @@ struct NahbarApp: App { .onAppear { applyTabBarAppearance(activeTheme) } .onChange(of: activeThemeIDRaw) { _, _ in applyTabBarAppearance(activeTheme) } } - .modelContainer(AppGroup.makeMainContainer()) + .modelContainer(AppGroup.makeMainContainerWithMigration()) .onChange(of: scenePhase) { _, phase in if phase == .background { appLockManager.lockIfEnabled() diff --git a/nahbar/nahbar/NahbarMigration.swift b/nahbar/nahbar/NahbarMigration.swift new file mode 100644 index 0000000..0e7abd7 --- /dev/null +++ b/nahbar/nahbar/NahbarMigration.swift @@ -0,0 +1,113 @@ +import SwiftUI +import SwiftData + +// MARK: - Schema V1 (Originalschema – Moment ohne sourceRaw) +// +// Diese Typen spiegeln exakt das ursprüngliche Schema wider, bevor +// Moment.sourceRaw hinzugefügt wurde. SwiftData vergleicht das +// gespeicherte Schema-Hash mit dieser Definition und führt bei +// Übereinstimmung die Lightweight-Migration zu V2 durch. + +enum NahbarSchemaV1: VersionedSchema { + static var versionIdentifier = Schema.Version(1, 0, 0) + static var models: [any PersistentModel.Type] { + [Person.self, Moment.self, LogEntry.self] + } + + @Model final class Person { + var id: UUID = UUID() + var name: String = "" + var tagRaw: String = "Andere" + var birthday: Date? = nil + var occupation: String? = nil + var location: String? = nil + var interests: String? = nil + var generalNotes: String? = nil + var nudgeFrequencyRaw: String = "Monatlich" + var photoData: Data? = nil + var nextStep: String? = nil + var nextStepCompleted: Bool = false + var nextStepReminderDate: Date? = nil + var lastSuggestedForCall: Date? = nil + var createdAt: Date = Date() + @Relationship(deleteRule: .cascade) var moments: [Moment]? = [] + @Relationship(deleteRule: .cascade) var logEntries: [LogEntry]? = [] + + init() {} + } + + @Model final class Moment { + var id: UUID = UUID() + var text: String = "" + var typeRaw: String = "Gespräch" + var createdAt: Date = Date() + var person: Person? = nil + + init() {} + } + + @Model final class LogEntry { + var id: UUID = UUID() + var typeRaw: String = "Schritt abgeschlossen" + var title: String = "" + var loggedAt: Date = Date() + var person: Person? = nil + + init() {} + } +} + +// MARK: - Schema V2 (aktuell – Moment mit sourceRaw) + +enum NahbarSchemaV2: VersionedSchema { + static var versionIdentifier = Schema.Version(2, 0, 0) + static var models: [any PersistentModel.Type] { + // Verweist auf die aktuellen Top-Level-Modeltypen in Models.swift + [nahbar.Person.self, nahbar.Moment.self, nahbar.LogEntry.self] + } +} + +// MARK: - Migrationsplan V1 → V2 + +enum NahbarMigrationPlan: SchemaMigrationPlan { + static var schemas: [any VersionedSchema.Type] { + [NahbarSchemaV1.self, NahbarSchemaV2.self] + } + + /// Lightweight: SwiftData ergänzt sourceRaw mit nil für alle bestehenden Momente. + static var stages: [MigrationStage] { + [.lightweight(fromVersion: NahbarSchemaV1.self, toVersion: NahbarSchemaV2.self)] + } +} + +// MARK: - Container-Erstellung (nur Hauptapp, nicht Share Extension) + +extension AppGroup { + /// Erstellt den ModelContainer mit automatischer Schemamigration. + /// Bei Nutzern, die bereits Daten haben, ergänzt SwiftData das neue + /// Feld sourceRaw = nil für alle vorhandenen Momente – kein Datenverlust. + static func makeMainContainerWithMigration() -> ModelContainer { + let schema = Schema([nahbar.Person.self, nahbar.Moment.self, nahbar.LogEntry.self]) + let icloudEnabled = UserDefaults.standard.bool(forKey: icloudSyncKey) + let cloudKit: ModelConfiguration.CloudKitDatabase = icloudEnabled ? .automatic : .none + + // Versuch 1: gewünschte Konfiguration mit Migrationsplan + let config = ModelConfiguration(schema: schema, cloudKitDatabase: cloudKit) + if let container = try? ModelContainer( + for: schema, + migrationPlan: NahbarMigrationPlan.self, + configurations: [config] + ) { return container } + + // Versuch 2: lokal ohne CloudKit mit Migrationsplan + let localConfig = ModelConfiguration(schema: schema, cloudKitDatabase: .none) + if let container = try? ModelContainer( + for: schema, + migrationPlan: NahbarMigrationPlan.self, + configurations: [localConfig] + ) { return container } + + // Letzter Ausweg: nur im Speicher (sollte nie eintreten) + return try! ModelContainer(for: schema, configurations: [ModelConfiguration(isStoredInMemoryOnly: true)]) + } +} diff --git a/nahbar/nahbar/PersonDetailView.swift b/nahbar/nahbar/PersonDetailView.swift index 9801e6a..93d7814 100644 --- a/nahbar/nahbar/PersonDetailView.swift +++ b/nahbar/nahbar/PersonDetailView.swift @@ -1,10 +1,12 @@ import SwiftUI import SwiftData +import CoreData import UserNotifications struct PersonDetailView: View { @Environment(\.nahbarTheme) var theme @Environment(\.modelContext) var modelContext + @Environment(\.dismiss) var dismiss @Bindable var person: Person @State private var showingAddMoment = false @@ -51,6 +53,16 @@ struct PersonDetailView: View { .onAppear { nextStepText = person.nextStep ?? "" } + // Schützt vor Crash wenn der ModelContext durch Migration oder + // CloudKit-Sync intern reset() aufruft und Person-Objekte ungültig werden. + .onReceive( + NotificationCenter.default.publisher( + for: Notification.Name("NSManagedObjectContextObjectsDidChangeNotification") + ) + ) { notification in + guard notification.userInfo?[NSInvalidatedAllObjectsKey] != nil else { return } + dismiss() + } } // MARK: - Header @@ -412,11 +424,26 @@ struct MomentRowView: View { var body: some View { HStack(alignment: .top, spacing: 12) { - Image(systemName: moment.type.icon) - .font(.system(size: 13, weight: .light)) - .foregroundStyle(theme.contentTertiary) - .frame(width: 18) - .padding(.top, 2) + // Type icon with optional source badge overlay + ZStack(alignment: .bottomTrailing) { + Image(systemName: moment.type.icon) + .font(.system(size: 13, weight: .light)) + .foregroundStyle(theme.contentTertiary) + .frame(width: 18) + .padding(.top, 2) + + if let source = moment.source { + Image(systemName: source.icon) + .font(.system(size: 8, weight: .semibold)) + .foregroundStyle(.white) + .padding(2) + .background(sourceColor(source)) + .clipShape(Circle()) + .offset(x: 5, y: 4) + } + } + .frame(width: 18) + .padding(.top, 2) VStack(alignment: .leading, spacing: 4) { Text(moment.text) @@ -424,9 +451,20 @@ struct MomentRowView: View { .foregroundStyle(theme.contentPrimary) .fixedSize(horizontal: false, vertical: true) - Text(moment.createdAt, format: .dateTime.day().month(.abbreviated).year().locale(Locale(identifier: "de_DE"))) - .font(.system(size: 12)) - .foregroundStyle(theme.contentTertiary) + HStack(spacing: 6) { + Text(moment.createdAt, format: .dateTime.day().month(.abbreviated).year().locale(Locale(identifier: "de_DE"))) + .font(.system(size: 12)) + .foregroundStyle(theme.contentTertiary) + + if let source = moment.source { + Text("·") + .font(.system(size: 12)) + .foregroundStyle(theme.contentTertiary) + Text(source.rawValue) + .font(.system(size: 12)) + .foregroundStyle(sourceColor(source).opacity(0.8)) + } + } } Spacer() @@ -434,6 +472,16 @@ struct MomentRowView: View { .padding(.horizontal, 16) .padding(.vertical, 12) } + + private func sourceColor(_ source: MomentSource) -> Color { + switch source { + case .whatsapp: return Color(red: 0.15, green: 0.80, blue: 0.33) + case .imessage: return Color(red: 0.0, green: 0.48, blue: 1.0) + case .telegram: return Color(red: 0.17, green: 0.67, blue: 0.94) + case .signal: return Color(red: 0.23, green: 0.47, blue: 0.95) + case .other: return Color.gray + } + } } // MARK: - Info Row diff --git a/nahbar/nahbarShareExtension/ShareExtensionView.swift b/nahbar/nahbarShareExtension/ShareExtensionView.swift index b18600c..8d4baca 100644 --- a/nahbar/nahbarShareExtension/ShareExtensionView.swift +++ b/nahbar/nahbarShareExtension/ShareExtensionView.swift @@ -13,6 +13,7 @@ struct ShareExtensionView: View { @State private var text: String @State private var momentType: MomentType = .conversation + @State private var momentSource: MomentSource = .other @State private var people: [CachedPerson] = [] @State private var selectedPerson: CachedPerson? @State private var searchText = "" @@ -50,6 +51,15 @@ struct ShareExtensionView: View { .labelsHidden() } + Section("Herkunft") { + Picker("Messenger", selection: $momentSource) { + ForEach(MomentSource.allCases, id: \.self) { source in + Label(source.rawValue, systemImage: source.icon).tag(source) + } + } + .pickerStyle(.menu) + } + Section("Kontakt") { if people.isEmpty { Text("Keine Kontakte gefunden. Öffne nahbar einmal, damit die Kontakte hier erscheinen.") @@ -132,7 +142,7 @@ struct ShareExtensionView: View { let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) guard !trimmed.isEmpty else { return } isSaving = true - AppGroup.enqueueMoment(personName: person.name, text: trimmed, type: momentType.rawValue) + AppGroup.enqueueMoment(personName: person.name, text: trimmed, type: momentType.rawValue, source: momentSource.rawValue) onDismiss() } }