Android possible
parent
b7ec276347
commit
753d6af4c5
|
@ -10,16 +10,16 @@ plugins {
|
|||
|
||||
android {
|
||||
namespace = "com.example.trainerbox"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
compileSdk = 35 // Aktualisiert auf SDK 35 für Plugin-Kompatibilität
|
||||
ndkVersion = "27.0.12077973" // Aktualisiert auf NDK 27.0.12077973 für Plugin-Kompatibilität
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_11.toString()
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
|
@ -27,21 +27,49 @@ android {
|
|||
applicationId = "com.example.trainerbox"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = flutter.minSdkVersion
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
minSdk = 21 // Mindest-SDK-Version für moderne Android-Geräte
|
||||
targetSdk = 35 // Aktualisiert auf SDK 35
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
multiDexEnabled = true // Für Apps mit vielen Dependencies
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = true // Code-Optimierung für Release-Builds
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
// 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")
|
||||
}
|
||||
}
|
||||
|
||||
// Unterstützung für verschiedene Bildschirmgrößen
|
||||
splits {
|
||||
abi {
|
||||
isEnable = true
|
||||
reset()
|
||||
include("armeabi-v7a", "arm64-v8a", "x86_64")
|
||||
isUniversalApk = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(platform("com.google.firebase:firebase-bom:32.7.2"))
|
||||
implementation("com.google.firebase:firebase-analytics")
|
||||
implementation("com.google.firebase:firebase-auth")
|
||||
implementation("com.google.firebase:firebase-firestore")
|
||||
implementation("com.android.support:multidex:1.0.3")
|
||||
implementation("androidx.core:core-ktx:1.12.0")
|
||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||
implementation("com.google.android.material:material:1.11.0")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
implementation("com.google.firebase:firebase-core:21.1.1")
|
||||
implementation("com.google.firebase:firebase-auth:22.3.1")
|
||||
implementation("com.google.firebase:firebase-firestore:24.10.2")
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<application
|
||||
android:label="TrainerBox"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="TrainerBox"
|
||||
android:usesCleartextTraffic="true">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
{
|
||||
"firestore": {
|
||||
"rules": "firestore.rules",
|
||||
"indexes": "firestore.indexes.json"
|
||||
},
|
||||
"flutter": {
|
||||
"platforms": {
|
||||
"android": {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"indexes": [],
|
||||
"fieldOverrides": []
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
rules_version = '2';
|
||||
|
||||
service cloud.firestore {
|
||||
match /databases/{database}/documents {
|
||||
// Benutzer können ihre eigenen Daten lesen und schreiben
|
||||
match /User/{userId} {
|
||||
allow read, write: if request.auth != null && request.auth.uid == userId;
|
||||
}
|
||||
|
||||
// Trainer können ihre eigenen Trainings verwalten
|
||||
match /Training/{trainingId} {
|
||||
allow read: if request.auth != null;
|
||||
allow write: if request.auth != null &&
|
||||
get(/databases/$(database)/documents/User/$(request.auth.uid)).data.role == 'trainer';
|
||||
}
|
||||
|
||||
// Übungen können von allen gelesen werden
|
||||
match /Exercise/{exerciseId} {
|
||||
allow read: if request.auth != null;
|
||||
allow write: if request.auth != null &&
|
||||
get(/databases/$(database)/documents/User/$(request.auth.uid)).data.role == 'trainer';
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
|
@ -54,6 +55,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
|
@ -49,5 +47,11 @@
|
|||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UIRequiresFullScreen</key>
|
||||
<true/>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<false/>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -23,41 +23,96 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||
Future<void> _submit() async {
|
||||
setState(() { _loading = true; _error = null; });
|
||||
try {
|
||||
print('Login-Versuch gestartet...'); // Debug
|
||||
if (_isLogin) {
|
||||
print('Login-Modus: E-Mail: ${_emailController.text.trim()}'); // Debug
|
||||
// Login
|
||||
UserCredential cred = await FirebaseAuth.instance.signInWithEmailAndPassword(
|
||||
email: _emailController.text.trim(),
|
||||
password: _passwordController.text.trim(),
|
||||
);
|
||||
// Firestore-Check
|
||||
final uid = cred.user!.uid;
|
||||
final userDoc = await FirebaseFirestore.instance.collection('User').doc(uid).get();
|
||||
if (userDoc.exists) {
|
||||
widget.onLoginSuccess();
|
||||
} else {
|
||||
setState(() { _error = 'Kein Benutzerprofil in der Datenbank gefunden!'; });
|
||||
await FirebaseAuth.instance.signOut();
|
||||
try {
|
||||
UserCredential cred = await FirebaseAuth.instance.signInWithEmailAndPassword(
|
||||
email: _emailController.text.trim(),
|
||||
password: _passwordController.text.trim(),
|
||||
);
|
||||
print('Firebase Auth erfolgreich: ${cred.user?.uid}'); // Debug
|
||||
|
||||
// Firestore-Check
|
||||
final uid = cred.user!.uid;
|
||||
print('Firestore-Check für UID: $uid'); // Debug
|
||||
|
||||
final userDoc = await FirebaseFirestore.instance.collection('User').doc(uid).get();
|
||||
print('Firestore-Dokument existiert: ${userDoc.exists}'); // Debug
|
||||
|
||||
if (userDoc.exists) {
|
||||
print('Login erfolgreich, Benutzer gefunden'); // Debug
|
||||
widget.onLoginSuccess();
|
||||
} else {
|
||||
print('Kein Benutzerprofil in Firestore gefunden'); // Debug
|
||||
setState(() { _error = 'Kein Benutzerprofil in der Datenbank gefunden!'; });
|
||||
await FirebaseAuth.instance.signOut();
|
||||
}
|
||||
} catch (e) {
|
||||
print('Fehler beim Firebase Auth: $e'); // Debug
|
||||
rethrow;
|
||||
}
|
||||
} else {
|
||||
print('Registrierungs-Modus: E-Mail: ${_emailController.text.trim()}'); // Debug
|
||||
// Registrierung
|
||||
UserCredential cred = await FirebaseAuth.instance.createUserWithEmailAndPassword(
|
||||
email: _emailController.text.trim(),
|
||||
password: _passwordController.text.trim(),
|
||||
);
|
||||
// User-Datensatz in Firestore anlegen
|
||||
final uid = cred.user!.uid;
|
||||
await FirebaseFirestore.instance.collection('User').doc(uid).set({
|
||||
'email': _emailController.text.trim(),
|
||||
'name': _nameController.text.trim(),
|
||||
'role': _isTrainer ? 'trainer' : 'player',
|
||||
'createdAt': FieldValue.serverTimestamp(),
|
||||
});
|
||||
widget.onLoginSuccess();
|
||||
try {
|
||||
UserCredential cred = await FirebaseAuth.instance.createUserWithEmailAndPassword(
|
||||
email: _emailController.text.trim(),
|
||||
password: _passwordController.text.trim(),
|
||||
);
|
||||
print('Firebase Auth Registrierung erfolgreich: ${cred.user?.uid}'); // Debug
|
||||
|
||||
// User-Datensatz in Firestore anlegen
|
||||
final uid = cred.user!.uid;
|
||||
print('Erstelle Firestore-Dokument für UID: $uid'); // Debug
|
||||
|
||||
await FirebaseFirestore.instance.collection('User').doc(uid).set({
|
||||
'email': _emailController.text.trim(),
|
||||
'name': _nameController.text.trim(),
|
||||
'role': _isTrainer ? 'trainer' : 'player',
|
||||
'createdAt': FieldValue.serverTimestamp(),
|
||||
});
|
||||
print('Firestore-Dokument erstellt'); // Debug
|
||||
|
||||
widget.onLoginSuccess();
|
||||
} catch (e) {
|
||||
print('Fehler bei der Registrierung: $e'); // Debug
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
} on FirebaseAuthException catch (e) {
|
||||
setState(() { _error = e.message ?? 'Fehler'; });
|
||||
print('FirebaseAuthException: ${e.code} - ${e.message}'); // Debug
|
||||
String errorMessage;
|
||||
switch (e.code) {
|
||||
case 'user-not-found':
|
||||
errorMessage = 'Kein Benutzer mit dieser E-Mail-Adresse gefunden.';
|
||||
break;
|
||||
case 'wrong-password':
|
||||
errorMessage = 'Falsches Passwort.';
|
||||
break;
|
||||
case 'invalid-email':
|
||||
errorMessage = 'Ungültige E-Mail-Adresse.';
|
||||
break;
|
||||
case 'user-disabled':
|
||||
errorMessage = 'Dieser Account wurde deaktiviert.';
|
||||
break;
|
||||
case 'email-already-in-use':
|
||||
errorMessage = 'Diese E-Mail-Adresse wird bereits verwendet.';
|
||||
break;
|
||||
case 'weak-password':
|
||||
errorMessage = 'Das Passwort ist zu schwach.';
|
||||
break;
|
||||
case 'operation-not-allowed':
|
||||
errorMessage = 'Diese Operation ist nicht erlaubt.';
|
||||
break;
|
||||
default:
|
||||
errorMessage = 'Ein Fehler ist aufgetreten: ${e.message}';
|
||||
}
|
||||
setState(() { _error = errorMessage; });
|
||||
} catch (e) {
|
||||
setState(() { _error = 'Unbekannter Fehler'; });
|
||||
print('Unerwarteter Fehler: $e'); // Debug
|
||||
setState(() { _error = 'Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.'; });
|
||||
} finally {
|
||||
setState(() { _loading = false; });
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class Responsive {
|
||||
static bool isMobile(BuildContext context) =>
|
||||
MediaQuery.of(context).size.width < 600;
|
||||
|
||||
static bool isTablet(BuildContext context) =>
|
||||
MediaQuery.of(context).size.width >= 600 &&
|
||||
MediaQuery.of(context).size.width < 1200;
|
||||
|
||||
static bool isDesktop(BuildContext context) =>
|
||||
MediaQuery.of(context).size.width >= 1200;
|
||||
|
||||
static double getWidth(BuildContext context) =>
|
||||
MediaQuery.of(context).size.width;
|
||||
|
||||
static double getHeight(BuildContext context) =>
|
||||
MediaQuery.of(context).size.height;
|
||||
|
||||
static double getScaledWidth(BuildContext context, double percentage) =>
|
||||
getWidth(context) * (percentage / 100);
|
||||
|
||||
static double getScaledHeight(BuildContext context, double percentage) =>
|
||||
getHeight(context) * (percentage / 100);
|
||||
|
||||
static EdgeInsets getPadding(BuildContext context) {
|
||||
if (isMobile(context)) {
|
||||
return const EdgeInsets.all(16.0);
|
||||
} else if (isTablet(context)) {
|
||||
return const EdgeInsets.all(24.0);
|
||||
} else {
|
||||
return const EdgeInsets.all(32.0);
|
||||
}
|
||||
}
|
||||
|
||||
static double getFontSize(BuildContext context, double baseSize) {
|
||||
if (isMobile(context)) {
|
||||
return baseSize;
|
||||
} else if (isTablet(context)) {
|
||||
return baseSize * 1.2;
|
||||
} else {
|
||||
return baseSize * 1.4;
|
||||
}
|
||||
}
|
||||
|
||||
static double getIconSize(BuildContext context, double baseSize) {
|
||||
if (isMobile(context)) {
|
||||
return baseSize;
|
||||
} else if (isTablet(context)) {
|
||||
return baseSize * 1.2;
|
||||
} else {
|
||||
return baseSize * 1.4;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -13,10 +13,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
|
||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.12.0"
|
||||
version: "2.13.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -101,10 +101,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
version: "1.3.3"
|
||||
file_selector_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -340,10 +340,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
|
||||
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.8"
|
||||
version: "10.0.9"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -537,10 +537,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
|
||||
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.1"
|
||||
version: "15.0.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
Loading…
Reference in New Issue