From 3d229d42cea1b51a836a34ef6ae94a93e2d06ed6 Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 30 May 2026 14:30:21 +0200 Subject: [PATCH] =?UTF-8?q?App-Store=20Vorbereitung:=20Privacy-Manifest=20?= =?UTF-8?q?+=20Konto-L=C3=B6schen=20+=20Region=20de?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PrivacyInfo.xcprivacy: NSPrivacyTracking=false, deklariert gesammelte Daten (Email, Name, User-ID, präziser/grober Standort, Fotos, Fitness, Sonstiger Nutzerinhalt) — alle linked to user, kein Tracking, nur AppFunctionality. Required-Reason APIs: UserDefaults (CA92.1), FileTimestamp (C617.1), DiskSpace (E174.1), SystemBootTime (35F9.1). - SettingsView: Section 'Konto löschen' mit zwei Bestätigungs-Alerts → DELETE /api/profile/account → automatischer logout. Erfüllt Apple- Pflicht seit iOS 16.4 (in-App-Löschung statt Web-Redirect). - Info.plist: CFBundleDevelopmentRegion explizit 'de' (statt der $(DEVELOPMENT_LANGUAGE)-Variable, die sonst 'en' auflöst) → Store zeigt App als deutschsprachig an. - NSHealthShareUsageDescription präziser formuliert (Reviewer-Hint). --- BanYaroGo-Info.plist | 4 +- BanYaroGo/PrivacyInfo.xcprivacy | 144 +++++++++++++++++++++++++++++ BanYaroGo/Views/SettingsView.swift | 50 ++++++++++ 3 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 BanYaroGo/PrivacyInfo.xcprivacy diff --git a/BanYaroGo-Info.plist b/BanYaroGo-Info.plist index a15a288..d6e4fb7 100644 --- a/BanYaroGo-Info.plist +++ b/BanYaroGo-Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) + de CFBundleDisplayName Ban Yaro Go CFBundleExecutable @@ -51,7 +51,7 @@ NSCameraUsageDescription Für Fotos während deiner Gassi-Tour brauchen wir Zugriff auf die Kamera. NSHealthShareUsageDescription - Wir lesen keine Daten aus Apple Health. + Ban Yaro Go liest keine Daten aus Apple Health. Diese Berechtigung wird vom System nur als Vorab-Bestätigung abgefragt, bevor die App Gassi-Touren in Health schreiben kann. NSHealthUpdateUsageDescription Auf Wunsch speichern wir deine Gassi-Touren als Spaziergang-Workout mit Route in Apple Health. UIBackgroundModes diff --git a/BanYaroGo/PrivacyInfo.xcprivacy b/BanYaroGo/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..1eab8fd --- /dev/null +++ b/BanYaroGo/PrivacyInfo.xcprivacy @@ -0,0 +1,144 @@ + + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeEmailAddress + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeName + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeUserID + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypePreciseLocation + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeCoarseLocation + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypePhotosorVideos + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeFitness + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeOtherUserContent + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryDiskSpace + NSPrivacyAccessedAPITypeReasons + + E174.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + + + + diff --git a/BanYaroGo/Views/SettingsView.swift b/BanYaroGo/Views/SettingsView.swift index 25906e3..5438e79 100644 --- a/BanYaroGo/Views/SettingsView.swift +++ b/BanYaroGo/Views/SettingsView.swift @@ -5,6 +5,10 @@ struct SettingsView: View { @AppStorage("autoPauseEnabled") private var autoPauseEnabled = true @AppStorage("healthKitSyncEnabled") private var healthKitSyncEnabled = false @State private var showHealthPermissionAlert = false + @State private var showDeleteConfirm1 = false + @State private var showDeleteConfirm2 = false + @State private var isDeleting = false + @State private var deleteError: String? var body: some View { NavigationStack { @@ -145,6 +149,26 @@ struct SettingsView: View { } } + Section { + Button(role: .destructive) { + showDeleteConfirm1 = true + } label: { + if isDeleting { + HStack { ProgressView(); Text("Wird gelöscht…") } + } else { + Label("Konto unwiderruflich löschen", systemImage: "trash") + } + } + .disabled(isDeleting) + if let deleteError { + Text(deleteError).font(.footnote).foregroundStyle(.red) + } + } header: { + Text("Konto löschen") + } footer: { + Text("Löscht dein banyaro-Konto, alle Hunde, Touren, Tagebuch-Einträge, Ausgaben und Fotos endgültig. Das gilt App-übergreifend (auch für banyaro.app im Browser). Die Aktion kann nicht rückgängig gemacht werden.") + } + Section("Über") { Text("Ban Yaro Go ist die native iOS-Ergänzung zur banyaro.app PWA. Phase 1: deine Touren ansehen.") .font(.footnote) @@ -158,6 +182,32 @@ struct SettingsView: View { } message: { Text("Du kannst die Berechtigung in den iOS-Einstellungen unter Datenschutz & Sicherheit → Health → Ban Yaro Go nachträglich ändern.") } + .alert("Konto wirklich löschen?", isPresented: $showDeleteConfirm1) { + Button("Abbrechen", role: .cancel) {} + Button("Weiter", role: .destructive) { showDeleteConfirm2 = true } + } message: { + Text("Alle Hunde, Touren, Tagebuch, Ausgaben und Fotos werden endgültig gelöscht — App und banyaro.app gleichermaßen. Diese Aktion kann nicht rückgängig gemacht werden.") + } + .alert("Letzte Bestätigung", isPresented: $showDeleteConfirm2) { + Button("Abbrechen", role: .cancel) {} + Button("Endgültig löschen", role: .destructive) { + Task { await deleteAccount() } + } + } message: { + Text("Bist du dir sicher? Dein Konto und alle Daten werden jetzt sofort und unwiderruflich entfernt.") + } + } + } + + private func deleteAccount() async { + isDeleting = true + deleteError = nil + defer { isDeleting = false } + do { + try await APIClient.shared.delete("/api/profile/account") + auth.logout() + } catch { + deleteError = error.localizedDescription } }