aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/firebase/auth.dart34
-rw-r--r--lib/main.dart81
-rw-r--r--lib/screens/dashboard_screen.dart5
-rw-r--r--lib/screens/login_screen.dart67
-rw-r--r--lib/screens/onboarding_screen.dart2
-rw-r--r--lib/screens/register_screen.dart49
-rw-r--r--lib/settings/preferences.dart9
-rw-r--r--pubspec.lock8
-rw-r--r--pubspec.yaml1
9 files changed, 185 insertions, 71 deletions
diff --git a/lib/firebase/auth.dart b/lib/firebase/auth.dart
index 35da5bf..da64fb5 100644
--- a/lib/firebase/auth.dart
+++ b/lib/firebase/auth.dart
@@ -1,5 +1,6 @@
import 'dart:io';
+import 'package:dartz/dartz.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:linkchat/firebase/database.dart';
@@ -17,7 +18,7 @@ class Auth {
User? get currentUser => _auth.currentUser;
Stream<User?> get userChanges => _auth.userChanges();
- Future<bool> createUserWithEmailAndPassword({
+ Future<Either<User?, FirebaseException>> createUserWithEmailAndPassword({
required String email,
required String password,
required String displayName,
@@ -28,6 +29,10 @@ class Auth {
email: email,
password: password,
);
+
+ // Enviar correo de verificación
+ await cred.user?.sendEmailVerification();
+
User? user = cred.user;
if (user != null) {
String photoUrl = await Storage().uploadAvatar(user.uid, avatar);
@@ -41,46 +46,47 @@ class Auth {
email: user.email!,
));
}
- return true;
+ return Left(user);
} catch (e) {
if (kDebugMode) print(e);
- return false;
+ return Right(e as FirebaseException);
}
}
- Future<bool> signInWithEmailAndPassword({
+ Future<Either<User?, FirebaseException>> signInWithEmailAndPassword({
required String email,
required String password,
}) async {
try {
+ await _auth.signOut();
UserCredential cred = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
- return cred.user?.emailVerified == true;
+ return Left(cred.user);
} catch (e) {
if (kDebugMode) print(e);
- return false;
+ return Right(e as FirebaseException);
}
}
- Future<bool> signInWithGoogle() async {
+ Future<Either<User?, FirebaseException>> signInWithGoogle() async {
try {
- await _auth.signInWithProvider(_googleAuthProvider);
- return true;
+ UserCredential cred = await _auth.signInWithProvider(_googleAuthProvider);
+ return Left(cred.user);
} catch (e) {
if (kDebugMode) print(e);
- return false;
+ return Right(e as FirebaseException);
}
}
- Future<bool> signInWithGithub() async {
+ Future<Either<User?, FirebaseException>> signInWithGithub() async {
try {
- await _auth.signInWithProvider(_githubProvider);
- return true;
+ UserCredential cred = await _auth.signInWithProvider(_githubProvider);
+ return Left(cred.user);
} catch (e) {
if (kDebugMode) print(e);
- return false;
+ return Right(e as FirebaseException);
}
}
diff --git a/lib/main.dart b/lib/main.dart
index b067b07..fa51f9e 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,8 +1,12 @@
import 'package:dynamic_color/dynamic_color.dart';
+import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:linkchat/screens/dashboard_screen.dart';
import 'package:linkchat/screens/login_screen.dart';
+import 'package:linkchat/screens/onboarding_screen.dart';
+import 'package:linkchat/settings/preferences.dart';
+import 'package:linkchat/widgets/loading_modal_widget.dart';
import 'package:provider/provider.dart';
import 'firebase/auth.dart';
@@ -54,32 +58,55 @@ class LinkChat extends StatelessWidget {
final ThemeEnum themeEnum = provider.theme;
return StreamBuilder(
- stream: _auth.userChanges,
- builder: (context, snapshot) =>
- DynamicColorBuilder(builder: (lightDynamic, darkDynamic) {
- provider.syncFromPrefs();
- ThemeData lightTheme = ThemeSettings.lightTheme(lightDynamic);
- ThemeData darkTheme = ThemeSettings.darkTheme(darkDynamic);
- ThemeData? theme;
- switch (themeEnum) {
- case ThemeEnum.light:
- theme = lightTheme;
- case ThemeEnum.dark:
- theme = darkTheme;
- case ThemeEnum.auto:
- theme = null;
- }
- return MaterialApp(
- theme: theme ?? lightTheme,
- darkTheme: theme ?? darkTheme,
- //theme: theme ?? ThemeSettings.lightTheme(lightDynamic),
- //darkTheme: theme ?? ThemeSettings.darkTheme(darkDynamic),
- themeMode: ThemeMode.system,
- routes: getApplicationRoutes(),
- home: (snapshot.hasData && !snapshot.data!.isAnonymous)
- ? const DashboardScreen()
- : const LoginScreen(),
- );
- }));
+ stream: _auth.userChanges,
+ builder: (context, authSnapshot) => DynamicColorBuilder(
+ builder: (lightDynamic, darkDynamic) {
+ provider.syncFromPrefs();
+ ThemeData lightTheme = ThemeSettings.lightTheme(lightDynamic);
+ ThemeData darkTheme = ThemeSettings.darkTheme(darkDynamic);
+ ThemeData? theme;
+ switch (themeEnum) {
+ case ThemeEnum.light:
+ theme = lightTheme;
+ case ThemeEnum.dark:
+ theme = darkTheme;
+ case ThemeEnum.auto:
+ theme = null;
+ }
+ return MaterialApp(
+ theme: theme ?? lightTheme,
+ darkTheme: theme ?? darkTheme,
+ themeMode: ThemeMode.system,
+ routes: getApplicationRoutes(),
+ home: FutureBuilder(
+ initialData: const LoadingModal(),
+ future: getHomeScreen(context, authSnapshot.data),
+ builder: (context, homeSnapshot) {
+ if (homeSnapshot.hasData) {
+ return homeSnapshot.data!;
+ } else if (homeSnapshot.hasError) {
+ return const LoginScreen();
+ } else {
+ return const LoadingModal();
+ }
+ },
+ ),
+ );
+ },
+ ),
+ );
+ }
+
+ Future<Widget> getHomeScreen(BuildContext context, User? user) async {
+ if (user != null && !user.isAnonymous && user.emailVerified) {
+ bool showOnboarding = await Preferences.getShowOnboarding();
+ if (showOnboarding) {
+ return const OnboardingScreen();
+ } else {
+ return const DashboardScreen();
+ }
+ } else {
+ return const LoginScreen();
+ }
}
}
diff --git a/lib/screens/dashboard_screen.dart b/lib/screens/dashboard_screen.dart
index be3aca0..72bbab7 100644
--- a/lib/screens/dashboard_screen.dart
+++ b/lib/screens/dashboard_screen.dart
@@ -109,11 +109,6 @@ class _DashboardScreenState extends State<DashboardScreen> {
}
void signOut(BuildContext context) {
- /*_auth.signOut().then((success) {
- if (success) {
- Navigator.of(context).popUntil(ModalRoute.withName('/login'));
- }
- });*/
_auth.signOut().then((success) {
if (success) {
Navigator.of(context).pushReplacementNamed('/login');
diff --git a/lib/screens/login_screen.dart b/lib/screens/login_screen.dart
index f00328b..c98a565 100644
--- a/lib/screens/login_screen.dart
+++ b/lib/screens/login_screen.dart
@@ -1,4 +1,6 @@
+import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
+import 'package:linkchat/settings/preferences.dart';
import 'package:social_login_buttons/social_login_buttons.dart';
import '../firebase/auth.dart';
@@ -19,6 +21,7 @@ class _LoginScreenState extends State<LoginScreen>
final Auth _auth = Auth();
bool isLoading = false;
+ bool isInit = false;
final padding = 16.0;
final spacer = const SizedBox(height: 16.0);
@@ -107,42 +110,84 @@ class _LoginScreenState extends State<LoginScreen>
);
void onLoginClicked(BuildContext context) {
+ setState(() {
+ isLoading = true;
+ });
_auth
.signInWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
)
- .then((success) {
+ .then((result) {
setState(() {
isLoading = false;
});
- // TODO: checar si el resultado es true
- Navigator.of(context).pushReplacementNamed('/dash');
+ result.fold(
+ (user) {
+ if (user != null && user.emailVerified == false) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text('El correo no está verificado')),
+ );
+ } else {
+ Preferences.getShowOnboarding().then((show) {
+ Navigator.of(context)
+ .pushReplacementNamed(show ? '/onboard' : '/dash');
+ });
+ }
+ },
+ (error) => handleError(error),
+ );
});
}
void onGoogleLoginClicked(BuildContext context) {
- _auth.signInWithGoogle().then((success) {
+ setState(() {
+ isLoading = true;
+ });
+ _auth.signInWithGoogle().then((result) {
setState(() {
isLoading = false;
});
- if (success) {
- Navigator.of(context).pushReplacementNamed('/dash');
- }
+ result.fold(
+ (user) {},
+ (error) => handleError(error),
+ );
});
}
void onGithubLoginClicked(BuildContext context) {
- _auth.signInWithGithub().then((success) {
+ setState(() {
+ isLoading = true;
+ });
+ _auth.signInWithGithub().then((result) {
setState(() {
isLoading = false;
});
- if (success) {
- Navigator.of(context).pushReplacementNamed('/dash');
- }
+ result.fold(
+ (user) {},
+ (error) => handleError(error),
+ );
});
}
+ void handleError(FirebaseException error) {
+ String message;
+ switch (error.code) {
+ case 'invalid-email':
+ message = 'El correo electrónico es inválido';
+ case 'user-disabled':
+ message = 'El usuario está desactivado';
+ case 'user-not-found':
+ message = 'El usuario no existe';
+ case 'wrong-password':
+ message = 'La contraseña es incorrecta.';
+ default:
+ message = 'Ocurrió un error desconocido';
+ }
+ ScaffoldMessenger.of(context)
+ .showSnackBar(SnackBar(content: Text(message)));
+ }
+
@override
Widget build(BuildContext context) {
return Scaffold(
diff --git a/lib/screens/onboarding_screen.dart b/lib/screens/onboarding_screen.dart
index e1755c4..5d1ff7a 100644
--- a/lib/screens/onboarding_screen.dart
+++ b/lib/screens/onboarding_screen.dart
@@ -1,5 +1,6 @@
import 'package:concentric_transition/concentric_transition.dart';
import 'package:flutter/material.dart';
+import 'package:linkchat/settings/preferences.dart';
import 'package:lottie/lottie.dart';
import '../widgets/responsive.dart';
@@ -95,6 +96,7 @@ class OnboardingScreen extends StatelessWidget {
);
},
onFinish: () {
+ Preferences.setShowOnboarding(false);
Navigator.of(context).pushNamed('/dash');
},
),
diff --git a/lib/screens/register_screen.dart b/lib/screens/register_screen.dart
index 9a11923..0ba0cf9 100644
--- a/lib/screens/register_screen.dart
+++ b/lib/screens/register_screen.dart
@@ -158,21 +158,42 @@ class _RegisterScreenState extends State<RegisterScreen> {
void onRegisterClicked(BuildContext context) {
setState(() {
- isLoading = false;
- if (validateForm()) {
- Auth()
- .createUserWithEmailAndPassword(
- email: _emailController.text,
- password: _passwordController.text,
- displayName: _nameController.text,
- avatar: File(_avatar!.path),
- )
- .then((success) {
- if (success) {
- Navigator.of(context).pushReplacementNamed('/onboard');
+ isLoading = true;
+ });
+
+ if (validateForm()) {
+ Auth()
+ .createUserWithEmailAndPassword(
+ email: _emailController.text,
+ password: _passwordController.text,
+ displayName: _nameController.text,
+ avatar: File(_avatar!.path),
+ )
+ .then((result) {
+ setState(() {
+ isLoading = false;
+ });
+ result.fold((user) {
+ Navigator.of(context).pushReplacementNamed('/login');
+ }, (error) {
+ String message;
+ switch (error.code) {
+ case 'email-already-in-use':
+ message = 'El correo electrónico ya se encuentra en uso';
+ case 'invalid-email':
+ message = 'El correo electrónico es inválido';
+ case 'operation-not-allowed':
+ message = 'La operación no está permitida';
+ case 'weak-password':
+ message = 'La contraseña es muy débil';
+ default:
+ message = 'Ocurrió un error desconocido';
}
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(content: Text(message)),
+ );
});
- }
- });
+ });
+ }
}
}
diff --git a/lib/settings/preferences.dart b/lib/settings/preferences.dart
index 9cfbf6a..715225a 100644
--- a/lib/settings/preferences.dart
+++ b/lib/settings/preferences.dart
@@ -31,4 +31,13 @@ class Preferences {
}
});
}
+
+ static Future<bool> getShowOnboarding() async =>
+ (await prefs).getBool('show-onboarding') ?? true;
+
+ static void setShowOnboarding(bool show) {
+ prefs.then((p) {
+ p.setBool('show-onboarding', show);
+ });
+ }
}
diff --git a/pubspec.lock b/pubspec.lock
index 69c79fb..4244d07 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -161,6 +161,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
+ dartz:
+ dependency: "direct main"
+ description:
+ name: dartz
+ sha256: e6acf34ad2e31b1eb00948692468c30ab48ac8250e0f0df661e29f12dd252168
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.10.1"
dynamic_color:
dependency: "direct main"
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index d6b9076..9b1573f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -13,6 +13,7 @@ dependencies:
dynamic_color: ^1.6.5
provider: ^6.0.5
shared_preferences: ^2.1.1
+ dartz: ^0.10.1
lottie: ^2.3.2
concentric_transition: ^1.0.3
social_login_buttons: ^1.0.7