diff --git a/.gitignore b/.gitignore index 3820a95..13fc2fc 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,8 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + +# Android Release-Signing (Upload-Key + Passwörter — niemals committen) +/android/key.properties +/android/*.jks +/android/*.keystore diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 031726b..75c6fd5 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,3 +1,6 @@ +import java.io.FileInputStream +import java.util.Properties + plugins { id("com.android.application") // START: FlutterFire Configuration @@ -8,6 +11,16 @@ plugins { id("dev.flutter.flutter-gradle-plugin") } +// Release-Signing: Werte kommen aus android/key.properties (nicht im Repo, +// siehe key.properties.example). Ohne die Datei wird weiterhin mit dem +// Debug-Key signiert, damit lokale Debug-Builds unverändert funktionieren. +val keystorePropertiesFile = rootProject.file("key.properties") +val keystoreProperties = Properties() +val hasReleaseSigning = keystorePropertiesFile.exists() +if (hasReleaseSigning) { + keystoreProperties.load(FileInputStream(keystorePropertiesFile)) +} + android { namespace = "dev.leafittome.app" compileSdk = flutter.compileSdkVersion @@ -33,11 +46,26 @@ android { versionName = flutter.versionName } + signingConfigs { + if (hasReleaseSigning) { + create("release") { + keyAlias = keystoreProperties["keyAlias"] as String + keyPassword = keystoreProperties["keyPassword"] as String + storeFile = file(keystoreProperties["storeFile"] as String) + storePassword = keystoreProperties["storePassword"] as String + } + } + } + buildTypes { release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.getByName("debug") + // Nutzt den echten Upload-Key, sobald key.properties existiert; + // bis dahin Fallback auf den Debug-Key (siehe oben). + signingConfig = if (hasReleaseSigning) { + signingConfigs.getByName("release") + } else { + signingConfigs.getByName("debug") + } } } } diff --git a/android/key.properties.example b/android/key.properties.example new file mode 100644 index 0000000..c62af72 --- /dev/null +++ b/android/key.properties.example @@ -0,0 +1,4 @@ +storePassword= +keyPassword= +keyAlias=upload +storeFile=../upload-keystore.jks diff --git a/docs/firebase-einrichtung.md b/docs/firebase-einrichtung.md index 045bf65..803bfcd 100644 --- a/docs/firebase-einrichtung.md +++ b/docs/firebase-einrichtung.md @@ -182,9 +182,64 @@ Danach neu bauen (`flutter run`) und den Google-Button auf iPhone **und** Androi > - Beim Aktivieren zeigt die Konsole den Hinweis „**SHA-1-Releasefingerabdruck angeben**". Der gilt für den *nativen* Google-Flow (`google_sign_in`-Paket) — unser Browser-Flow braucht ihn nicht. Die **Debug**-Fingerabdrücke (SHA-1 + SHA-256 aus `~/.android/debug.keystore`) sind trotzdem per CLI im Projekt hinterlegt (`firebase apps:android:sha:create …`), damit später nichts fehlt (z. B. App Check). Vor einem App-Store-/Play-Store-Release muss zusätzlich der Fingerabdruck des **Release**-Schlüssels hinterlegt werden — den gibt es aber noch nicht. > - Die `GoogleService-Info.plist`/`google-services.json` müssen nicht neu heruntergeladen werden — der Flow läuft über den Auth-Handler im Web, nicht über das native Google-SDK. -## Schritt 9 und folgende (kommen mit den nächsten Blöcken) +## Schritt 9: App Check aktivieren -- **App Check** — optionale Härtung vor dem App-Store-Release: bestätigt per Play Integrity (Android) / App Attest (iOS), dass Anfragen aus der echten App kommen. Bis dahin ist die Log-Warnung „No AppCheckProvider installed" harmlos und kann ignoriert werden — die Zugriffskontrolle leisten Login + Security Rules. +**So funktioniert es:** App Check bestätigt der Firebase-Console, dass ein Function-Aufruf wirklich aus der echten App kommt (Play Integrity auf Android, App Attest auf iOS) — Schutz gegen missbrauchte API-Keys/Function-URLs von außerhalb der App. Der Client-Code ist bereits vorbereitet (`FirebaseAppCheck.instance.activate(...)` in `lib/main.dart`), läuft aber noch mit dem **Debug-Provider** und die Functions **erzwingen** App Check noch nicht — die Log-Warnung „No AppCheckProvider installed" ist bis dahin harmlos, Login + Security Rules schützen weiterhin. + +Zwei getrennte Schritte, **nacheinander**, nicht gleichzeitig (sonst sperrt man sich versehentlich selbst aus den Functions aus): + +1. **Provider registrieren (Firebase-Konsole → App Check):** + - Android-App auswählen → **Play Integrity** als Provider aktivieren (kein zusätzliches Setup in der Play Console nötig, die API ist automatisch verfügbar). + - iOS-App auswählen → **App Attest** als Provider aktivieren. + - Für Testgeräte im Debug-Modus: beim ersten Start gibt die App in der Konsole (Logcat bzw. Xcode-Log) ein Debug-Token aus — das unter *App Check → Apps → \[App\] → Debug-Token verwalten* eintragen, sonst schlagen Debug-Builds nach dem Enforcement fehl. + - **Metriken abwarten:** In der Console unter *App Check → APIs* prüfen, dass für die genutzten Functions „Verified requests" ankommen (kann nach einem frischen Build ein paar Minuten dauern). +2. **Erst wenn Schritt 1 bestätigt ist:** In `functions/src/index.ts` und `functions/src/household.ts` bei den `onCall(...)`-Funktionen (`identifyPlant`, `diagnosePlant`, `analyzeLocation`, `assessPlantFit`, `joinHousehold`, `leaveHousehold`, `removeMember`) die Option `enforceAppCheck: true` ergänzen und neu deployen. Danach lehnen die Functions Aufrufe ohne gültiges App-Check-Token ab. + +Für einen echten Release-Build sollte `main.dart` auf die Produktiv-Provider umgestellt werden (`AndroidProvider.playIntegrity` / `AppleProvider.appAttest` statt der Debug-Provider) — bis dahin reicht der Debug-Provider für eigene Testgeräte. + +## Schritt 10: TestFlight einrichten (iOS) + +Ziel: die App auf eigenen/Familien-Geräten installierbar machen, **ohne** öffentlichen Store-Eintrag oder Apple-Review (interne Tester werden nicht geprüft). + +1. **App Store Connect** (, mit dem aktiven Apple-Developer-Konto) → *Meine Apps* → „+" → **Neue App**: + - Plattform iOS, Name „LeafItToMe" (falls der Name schon vergeben ist, z. B. „LeafItToMe – Pflanzenpflege" versuchen), Bundle-ID `dev.leafittome.app` auswählen (aus der Liste, die Xcode/das Developer-Portal bereits kennt), SKU frei wählbar (z. B. `leafittome-001`). +2. **App-Informationen → Datenschutzerklärung-URL:** die gehostete Datenschutzerklärung eintragen (Entwurf liegt in `docs/legal/datenschutz.html`, Hosting-Vorschlag s. u.). +3. **App-Datenschutz (Privacy-Fragebogen):** Apple fragt nach Datentypen. Antworten passend zu `docs/legal/datenschutz.html`: + - *Kontaktdaten* → E-Mail-Adresse: ja, verknüpft mit Nutzer, für App-Funktionalität (Konto). + - *Fotos oder Videos* → ja, verknüpft mit Nutzer, für App-Funktionalität (Pflanzen-/Standort-Erkennung). + - *Nutzerinhalte* (sonstige, z. B. Pflanzendaten) → ja, verknüpft mit Nutzer, für App-Funktionalität. + - Kein Tracking, keine Daten zu Werbezwecken, keine Analyse-/Diagnosedaten (kein Analytics/Crashlytics im Projekt). +4. **Build hochladen:** `flutter build ipa` (Release-Signing über Xcode „Automatically manage signing"), dann per Xcode Organizer oder Transporter-App hochladen. +5. **TestFlight → Interne Tests:** neue Testgruppe anlegen (z. B. „Haushalt"), Tester per Apple-ID-E-Mail hinzufügen — die genannten Personen müssen als *Nutzer* im App-Store-Connect-Team stehen (bis zu 100 interne Tester, kein Review nötig, Build ist nach ein paar Minuten Verarbeitungszeit verfügbar). + +## Schritt 11: Play Internal Testing einrichten (Android) + +Ziel: dieselbe „ohne öffentlichen Store-Eintrag"-Stufe für Android. + +1. **Voraussetzung — Release-Signing:** `android/key.properties` lokal anlegen (Vorlage: `android/key.properties.example`) und den Upload-Key erzeugen: + ``` + keytool -genkey -v -keystore android/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload + ``` + **Wichtig:** Diesen Befehl bewusst selbst ausführen (per `! keytool ...` in der Eingabezeile) und die erzeugte `.jks`-Datei **sofort sichern** (Passwort-Manager + Backup außerhalb des Repos) — ein verlorener Upload-Key bedeutet, dass die App auf Play nie wieder aktualisiert werden kann. Datei und `key.properties` sind absichtlich in `.gitignore`, landen also nicht im Git-Repo. +2. **Release-APK/AAB bauen:** `flutter build appbundle --release` (nutzt automatisch den Release-Key, sobald `key.properties` existiert). +3. **Play Console** () → **App erstellen**: Name „LeafItToMe", Paketname `dev.leafittome.app` (wird beim ersten AAB-Upload festgelegt). +4. **App-Inhalte** (Pflichtabschnitte, auch für den internen Test): + - *Datenschutzerklärung:* URL zu `docs/legal/datenschutz.html` eintragen. + - *Data-Safety-Formular:* analog zum Apple-Fragebogen aus Schritt 10 — Fotos, E-Mail/Kontodaten, Nutzerinhalte werden erhoben, sind mit dem Nutzerkonto verknüpft, dienen ausschließlich der App-Funktion, keine Weitergabe zu Werbezwecken, Datenverschlüsselung bei Übertragung: ja, Löschung auf Anfrage: ja. + - *Content-Rating-Fragebogen:* Kategorie „Utility/Produktivität", keine der abgefragten Inhalte (Gewalt, Nacktheit, Glücksspiel etc.) treffen zu → niedrigste Alterseinstufung. + - *Zielgruppe:* Erwachsene/allgemein, nicht speziell an Kinder gerichtet. + - *Anzeigen:* keine Werbung in der App. +5. **Interner Test-Track:** *Testen → Interner Test* → neue Version → AAB hochladen → Tester per Google-Konto-E-Mail oder Google-Gruppe hinzufügen → Link zur Teilnahme an die Tester schicken (kein Review, Verfügbarkeit meist innerhalb weniger Minuten). + +## Hosting-Vorschlag: Datenschutzerklärung öffentlich erreichbar machen + +`docs/legal/datenschutz.html` ist bewusst eine einzelne, eigenständige HTML-Datei ohne Build-Schritt — sie kann 1:1 ausgeliefert werden. Da die eigene Domain für die App noch aussteht, als Zwischenlösung der pragmatischste Weg über den bereits laufenden Hetzner-VPS (dort läuft schon nginx als Reverse-Proxy vor Forgejo, siehe `docs/git-forgejo.md`): + +1. Datei auf den Server kopieren, z. B. nach `/var/www/leafittome-legal/datenschutz.html`. +2. Kleinen `server{}`-Block (oder `location`-Block auf einem bestehenden Host) in der nginx-Config ergänzen, der diesen Ordner statisch ausliefert — entweder unter einer neuen Subdomain (`legal.cshomelabs.work`) oder einem Pfad auf einer bestehenden Domain, je nachdem was ohne DNS-Änderung am schnellsten geht. +3. Die resultierende URL in App Store Connect (Schritt 10) und Play Console (Schritt 11) eintragen. + +Sobald die endgültige `leafittome`-Domain steht, kann die Seite dorthin umziehen — die App-Store-/Play-Einträge müssten dann nur die URL aktualisieren. ## Begriffe kurz erklärt diff --git a/docs/handoff.md b/docs/handoff.md index 76e80d7..4f57877 100644 --- a/docs/handoff.md +++ b/docs/handoff.md @@ -30,9 +30,29 @@ Private Flutter-App (iOS+Android) zur Pflanzenpflege für Haushalt + Pflanzen-Si ## Offen / Nächstes -### 1. Backlog +### 1. App-Store-Vorbereitung (läuft, 2026-08-20 begonnen) -Button „KI-Zweitmeinung" bei unbefriedigendem PlantNet-Ergebnis; Push-Anzeige auch bei App im Vordergrund; App Check vor App-Store-Release (`firebase-einrichtung.md` Schritt 9); Englisch (`app_en.arb`); `firebase-functions`-Paket-Upgrade (Deploy-Warnung, mit Breaking Changes — bei Gelegenheit). +Ziel fürs Erste: **nur TestFlight + Play-Internal-Testing**, kein öffentlicher Store-Eintrag (mit Chris abgestimmt — spart Screenshots/Store-Texte/Altersfreigabe für später). Bundle-ID bleibt bewusst `dev.leafittome.app` (eigene Domain steht noch aus, ist aber kein Blocker für TestFlight/Internal-Testing). + +**Code-seitig erledigt:** +- App Check Client-Integration (Debug-Provider, `lib/main.dart`) — Functions erzwingen es noch nicht, siehe `firebase-einrichtung.md` Schritt 9 für den zweiten Schritt (Provider in der Console registrieren, dann erst `enforceAppCheck: true`). +- iOS: `ITSAppUsesNonExemptEncryption = false` in `Info.plist` (vermeidet wiederkehrende Export-Compliance-Nachfrage bei jedem TestFlight-Upload). +- Android: Release-Signing vorbereitet (`android/app/build.gradle.kts` liest `key.properties`, Vorlage `android/key.properties.example`; Datei + `.jks` sind in `.gitignore`). **Der Upload-Key selbst existiert noch nicht** — Chris muss ihn per `keytool` erzeugen (Befehl in `firebase-einrichtung.md` Schritt 11) und sofort sichern. +- `flutter_launcher_icons` vorbereitet (`pubspec.yaml`), zeigt auf `assets/icon/icon.png` — Datei existiert noch nicht. +- Entwurf Datenschutzerklärung: `docs/legal/datenschutz.html` (Platzhalter `[Name]`/`[E-Mail-Adresse]`/`[Datum]` müssen noch von Chris ausgefüllt werden), Hosting-Vorschlag (Hetzner-VPS/nginx) in `firebase-einrichtung.md`. +- Neue Doku-Schritte in `firebase-einrichtung.md`: **Schritt 9** (App Check, konkretisiert), **Schritt 10** (TestFlight einrichten), **Schritt 11** (Play Internal Testing einrichten) — inkl. Textvorlagen für Apples App-Privacy-Fragebogen und Googles Data-Safety-Formular. + +**Noch offen (Chris' Konsolen-Schritte, alle in `firebase-einrichtung.md` Schritt 9–11 dokumentiert):** +- App-Icon: 1024×1024-Design liefern → unter `assets/icon/icon.png` ablegen → `dart run flutter_launcher_icons`. +- Datenschutzerklärung: Platzhalter ausfüllen + irgendwo öffentlich hosten (Vorschlag: Hetzner-VPS). +- Android-Upload-Key erzeugen (`keytool`, Schritt 11) und sichern. +- App Check: Play Integrity/App Attest in der Firebase-Console registrieren, Metriken abwarten, danach `enforceAppCheck: true` in den Functions + Redeploy. +- App Store Connect: App-Eintrag anlegen, Privacy-URL + App-Privacy-Fragebogen ausfüllen, Build hochladen, interne TestFlight-Gruppe + Tester. +- Play Console: App anlegen, Datenschutz-URL + Data-Safety-Formular + Content-Rating ausfüllen, internen Test-Track + Tester. + +### 2. Backlog + +Button „KI-Zweitmeinung" bei unbefriedigendem PlantNet-Ergebnis; Push-Anzeige auch bei App im Vordergrund; Englisch (`app_en.arb`); `firebase-functions`-Paket-Upgrade (Deploy-Warnung, mit Breaking Changes — bei Gelegenheit). ## Stolperfallen (teuer erkauft, nicht erneut zahlen) diff --git a/docs/legal/datenschutz.html b/docs/legal/datenschutz.html new file mode 100644 index 0000000..69528cd --- /dev/null +++ b/docs/legal/datenschutz.html @@ -0,0 +1,120 @@ + + + + + +Datenschutzerklärung – LeafItToMe + + + + +

Datenschutzerklärung – LeafItToMe

+

Stand: [Datum einsetzen]

+ +

+ Hinweis für Chris (vor Veröffentlichung entfernen): + Platzhalter [Name], [E-Mail-Adresse] und [Datum] + ausfüllen. Diese Seite ist als öffentlich erreichbare, eigenständige HTML-Datei gedacht + (Hosting-Vorschlag in docs/firebase-einrichtung.md), auf die im Apple/Google- + Account bei „Datenschutzerklärung" verlinkt wird. +

+ +

Verantwortlicher

+

+ [Name]
+ E-Mail: [E-Mail-Adresse] +

+

+ LeafItToMe ist eine private, nicht kommerzielle App zur Pflanzenpflege für einen + Haushalt und die Personen, die dieser Haushalt zur Mitverwaltung oder als + Pflanzen-Sitter einlädt. Es werden keine Daten verkauft, keine Werbung + eingeblendet und keine Nutzungsdaten zu Analyse- oder Marketingzwecken erhoben. +

+ +

Welche Daten werden verarbeitet?

+ + +

Wofür werden die Daten verwendet?

+

+ Ausschließlich für die Kernfunktion der App: Pflanzen anzulegen und zu + identifizieren, Pflegepläne zu erstellen, Erinnerungen zu verschicken sowie + Krankheits- und Standort-Analysen auf Anfrage durchzuführen. Für die Foto-Analyse + werden die von dir aufgenommenen Bilder an folgende externe Dienste übermittelt: +

+ +

+ Diese Übermittlung erfolgt nur für die jeweilige Anfrage, nicht dauerhaft und + nicht zu Werbezwecken. +

+ +

Wo werden die Daten gespeichert?

+

+ Alle App-Daten (Konten, Haushalte, Pflanzen, Fotos) liegen bei + Google Firebase, Rechenzentrumsregion europe-west3 + (Frankfurt, Deutschland). Google LLC/Google Ireland Limited verarbeitet diese + Daten als Auftragsverarbeiter. +

+ +

Weitergabe an Dritte

+

+ Eine Weitergabe erfolgt nur an die oben genannten Dienste (Firebase, PlantNet, + Anthropic) im Rahmen der Auftragsverarbeitung, sowie an die Mitglieder und + Sitter deines eigenen Haushalts, die naturgemäß dieselben Haushaltsdaten sehen. + Ein Verkauf von Daten findet nicht statt. +

+ +

Speicherdauer und Löschung

+

+ Daten werden gespeichert, solange dein Konto bzw. der Haushalt besteht. + Zur Löschung deines Kontos oder einzelner Daten wende dich an + [E-Mail-Adresse]. +

+ +

Deine Rechte

+

+ Du hast das Recht auf Auskunft, Berichtigung, Löschung, Einschränkung der + Verarbeitung, Datenübertragbarkeit und Widerspruch gemäß Art. 15–21 DSGVO + sowie ein Beschwerderecht bei einer Datenschutzaufsichtsbehörde. Wende dich + dazu an [E-Mail-Adresse]. +

+ + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index c635b57..9cae123 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -24,6 +24,8 @@ ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) + ITSAppUsesNonExemptEncryption + CFBundleURLTypes diff --git a/lib/main.dart b/lib/main.dart index e6c4900..20fc056 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:firebase_app_check/firebase_app_check.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -12,6 +13,13 @@ Future main() async { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); + // Debug-Provider, bis Play Integrity (Android) / App Attest (iOS) in der + // Firebase-Console registriert sind (docs/firebase-einrichtung.md Schritt 9). + // Die Functions erzwingen App Check noch nicht — reines Vorbereiten. + await FirebaseAppCheck.instance.activate( + providerAndroid: AndroidDebugProvider(), + providerApple: AppleDebugProvider(), + ); final prefs = await SharedPreferences.getInstance(); runApp( ProviderScope( diff --git a/pubspec.lock b/pubspec.lock index f5bf28c..bf6781d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: "460e9e684edb461d85498fc166ff8416f303f22216838d302d80676b348c6a4c" + sha256: "6727cf2ced9b104abca9daa278380be2eca2b98ce33d4b46f11708e387dc6b4d" url: "https://pub.dev" source: hosted - version: "1.3.75" + version: "1.3.76" analyzer: dependency: transitive description: @@ -33,6 +33,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.13.2" + archive: + dependency: transitive + description: + name: archive + sha256: be169cf6ac481e052c4538715d88841d567150dfe1df38aaec76461a4e7b39f2 + url: "https://pub.dev" + source: hosted + version: "4.1.0" args: dependency: transitive description: @@ -73,6 +81,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" + url: "https://pub.dev" + source: hosted + version: "2.0.4" cli_config: dependency: transitive description: @@ -81,6 +97,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.0" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" clock: dependency: transitive description: @@ -273,6 +297,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+5" + firebase_app_check: + dependency: "direct main" + description: + name: firebase_app_check + sha256: d422642d973b0c636e0582127a47319d8ac9140195e7330c71965d3b6b263095 + url: "https://pub.dev" + source: hosted + version: "0.4.6" + firebase_app_check_platform_interface: + dependency: transitive + description: + name: firebase_app_check_platform_interface + sha256: "645ff25c18160a2c6e6b487d3466b247619e0bf09e2b1f641d476b2a72f92106" + url: "https://pub.dev" + source: hosted + version: "0.4.2" + firebase_app_check_web: + dependency: transitive + description: + name: firebase_app_check_web + sha256: "66c938d522c8c325515d222aa55560921b063d06791cf95aa7c405183a3a454f" + url: "https://pub.dev" + source: hosted + version: "0.2.6" firebase_auth: dependency: "direct main" description: @@ -309,26 +357,26 @@ packages: dependency: "direct main" description: name: firebase_core - sha256: "6f22d1c62e0c20976f02cd842c7b7cd3c0f561cc2052586411871045c08860c9" + sha256: "9478ca6700c02d315c6aba37e206e612317f98bb4f335bb1cbd6e0ce67dcf764" url: "https://pub.dev" source: hosted - version: "4.12.1" + version: "4.13.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - sha256: f74d1d6fabccf7743b0144c2ed363d81049e258e22428ebb6fb0faec2fa7d938 + sha256: e28f9afdcb5b0f0a8ea74ea3b322f5a7592c81cb45dd9d189913bdae08a2089a url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "8.1.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: ddab99d709b8c27dd47576eb05a1e719e07a2aa45c009a49ae92ac4d2a8ca555 + sha256: f471a288b0101a45567548322ac4a5ad31e3ecbf87a576dcc0e424e6a11e04ea url: "https://pub.dev" source: hosted - version: "3.9.1" + version: "3.10.0" firebase_messaging: dependency: "direct main" description: @@ -390,6 +438,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7" + url: "https://pub.dev" + source: hosted + version: "0.14.4" flutter_lints: dependency: "direct dev" description: @@ -485,6 +541,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.2" + image: + dependency: transitive + description: + name: image + sha256: "1976370a4df3091bb0f72409c187ad1f9132a818bc6b95ca59c0bae1c75c688e" + url: "https://pub.dev" + source: hosted + version: "4.9.2" image_picker: dependency: "direct main" description: @@ -565,6 +629,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "2a743920d81b7910627f68ee2c9ac1fc0bfee32b9fc3403587d7c6791ca12f80" + url: "https://pub.dev" + source: hosted + version: "4.12.0" leak_tracker: dependency: transitive description: @@ -741,6 +813,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.2" + posix: + dependency: transitive + description: + name: posix + sha256: bc1bad54ad2b735816e31f8d4600cfde6c7839975085ddfbca48b6c9f7c4044e + url: "https://pub.dev" + source: hosted + version: "6.5.2" pub_semver: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f717df1..b79c615 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: firebase_storage: ^13.4.5 firebase_messaging: ^16.4.3 flutter_timezone: ^5.1.0 + firebase_app_check: ^0.4.6 dev_dependencies: flutter_test: @@ -61,6 +62,7 @@ dev_dependencies: flutter_lints: ^6.0.0 fake_cloud_firestore: ^4.2.0 firebase_auth_mocks: ^0.15.2 + flutter_launcher_icons: ^0.14.4 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -104,3 +106,12 @@ flutter: # # For details regarding fonts from package dependencies, # see https://flutter.dev/to/font-from-package + +# Icon-Generierung (flutter_launcher_icons): Sobald ein echtes 1024x1024-Design +# unter assets/icon/icon.png liegt, generiert `dart run flutter_launcher_icons` +# daraus alle iOS-/Android-Icon-Größen. Bis dahin bleibt das Flutter-Standardlogo. +flutter_launcher_icons: + image_path: "assets/icon/icon.png" + android: true + ios: true + remove_alpha_ios: true