step-23
This commit is contained in:
parent
094ca0a6eb
commit
b4cac7331a
190
lib/main.dart
190
lib/main.dart
|
@ -1,8 +1,10 @@
|
|||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:mynotes/constants/routes.dart';
|
||||
import 'package:mynotes/services/auth/auth_service.dart';
|
||||
import 'package:mynotes/services/auth/bloc/auth_bloc.dart';
|
||||
import 'package:mynotes/services/auth/bloc/auth_event.dart';
|
||||
import 'package:mynotes/services/auth/bloc/auth_state.dart';
|
||||
import 'package:mynotes/services/auth/firebase_auth_provider.dart';
|
||||
import 'package:mynotes/views/login_view.dart';
|
||||
import 'package:mynotes/views/notes/create_update_note_view.dart';
|
||||
import 'package:mynotes/views/notes/notes_view.dart';
|
||||
|
@ -17,7 +19,10 @@ void main() {
|
|||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
),
|
||||
home: const HomePage(),
|
||||
home: BlocProvider<AuthBloc>(
|
||||
create: (context) => AuthBloc(FirebaseAuthProvider()),
|
||||
child: const HomePage(),
|
||||
),
|
||||
routes: {
|
||||
loginRoute: (context) => const LoginView(),
|
||||
registerRoute: (context) => const RegisterView(),
|
||||
|
@ -29,173 +34,26 @@ void main() {
|
|||
);
|
||||
}
|
||||
|
||||
// class HomePage extends StatelessWidget {
|
||||
// const HomePage({Key? key}) : super(key: key);
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return FutureBuilder(
|
||||
// future: AuthService.firebase().initialize(),
|
||||
// builder: (context, snapshot) {
|
||||
// switch (snapshot.connectionState) {
|
||||
// case ConnectionState.done:
|
||||
// final user = AuthService.firebase().currentUser;
|
||||
// if (user != null) {
|
||||
// if (user.isEmailVerified) {
|
||||
// return const NotesView();
|
||||
// } else {
|
||||
// return const VerifyEmailView();
|
||||
// }
|
||||
// } else {
|
||||
// return const LoginView();
|
||||
// }
|
||||
// default:
|
||||
// return const CircularProgressIndicator();
|
||||
// }
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
class HomePage extends StatefulWidget {
|
||||
class HomePage extends StatelessWidget {
|
||||
const HomePage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_HomePageState createState() => _HomePageState();
|
||||
}
|
||||
|
||||
class _HomePageState extends State<HomePage> {
|
||||
late final TextEditingController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_controller = TextEditingController();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => CounterBloc(),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Testing bloc'),
|
||||
),
|
||||
body: BlocConsumer<CounterBloc, CounterState>(
|
||||
listener: (context, state) {
|
||||
_controller.clear();
|
||||
},
|
||||
builder: (context, state) {
|
||||
final invalidValue =
|
||||
(state is CounterStateInvalidNumber) ? state.invalidValue : '';
|
||||
return Column(
|
||||
children: [
|
||||
Text('Current value => ${state.value}'),
|
||||
Visibility(
|
||||
child: Text('Invalid input: $invalidValue'),
|
||||
visible: state is CounterStateInvalidNumber,
|
||||
),
|
||||
TextField(
|
||||
controller: _controller,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Enter a number here',
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context
|
||||
.read<CounterBloc>()
|
||||
.add(DecrementEvent(_controller.text));
|
||||
},
|
||||
child: const Text('-'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context
|
||||
.read<CounterBloc>()
|
||||
.add(IncrementEvent(_controller.text));
|
||||
},
|
||||
child: const Text('+'),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
context.read<AuthBloc>().add(const AuthEventInitialize());
|
||||
return BlocBuilder<AuthBloc, AuthState>(
|
||||
builder: (context, state) {
|
||||
if (state is AuthStateLoggedIn) {
|
||||
return const NotesView();
|
||||
} else if (state is AuthStateNeedsVerification) {
|
||||
return const VerifyEmailView();
|
||||
} else if (state is AuthStateLoggedOut) {
|
||||
return const LoginView();
|
||||
} else {
|
||||
return const Scaffold(
|
||||
body: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
abstract class CounterState {
|
||||
final int value;
|
||||
const CounterState(this.value);
|
||||
}
|
||||
|
||||
class CounterStateValid extends CounterState {
|
||||
const CounterStateValid(int value) : super(value);
|
||||
}
|
||||
|
||||
class CounterStateInvalidNumber extends CounterState {
|
||||
final String invalidValue;
|
||||
const CounterStateInvalidNumber({
|
||||
required this.invalidValue,
|
||||
required int previousValue,
|
||||
}) : super(previousValue);
|
||||
}
|
||||
|
||||
@immutable
|
||||
abstract class CounterEvent {
|
||||
final String value;
|
||||
const CounterEvent(this.value);
|
||||
}
|
||||
|
||||
class IncrementEvent extends CounterEvent {
|
||||
const IncrementEvent(String value) : super(value);
|
||||
}
|
||||
|
||||
class DecrementEvent extends CounterEvent {
|
||||
const DecrementEvent(String value) : super(value);
|
||||
}
|
||||
|
||||
class CounterBloc extends Bloc<CounterEvent, CounterState> {
|
||||
CounterBloc() : super(const CounterStateValid(0)) {
|
||||
on<IncrementEvent>((event, emit) {
|
||||
final integer = int.tryParse(event.value);
|
||||
if (integer == null) {
|
||||
emit(
|
||||
CounterStateInvalidNumber(
|
||||
invalidValue: event.value,
|
||||
previousValue: state.value,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
emit(CounterStateValid(state.value + integer));
|
||||
}
|
||||
});
|
||||
on<DecrementEvent>((event, emit) {
|
||||
final integer = int.tryParse(event.value);
|
||||
if (integer == null) {
|
||||
emit(
|
||||
CounterStateInvalidNumber(
|
||||
invalidValue: event.value,
|
||||
previousValue: state.value,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
emit(CounterStateValid(state.value - integer));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
import 'package:bloc/bloc.dart';
|
||||
import 'package:mynotes/services/auth/auth_provider.dart';
|
||||
import 'package:mynotes/services/auth/bloc/auth_event.dart';
|
||||
import 'package:mynotes/services/auth/bloc/auth_state.dart';
|
||||
|
||||
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
AuthBloc(AuthProvider provider) : super(const AuthStateLoading()) {
|
||||
// initialize
|
||||
on<AuthEventInitialize>((event, emit) async {
|
||||
await provider.initialize();
|
||||
final user = provider.currentUser;
|
||||
if (user == null) {
|
||||
emit(const AuthStateLoggedOut());
|
||||
} else if (!user.isEmailVerified) {
|
||||
emit(const AuthStateNeedsVerification());
|
||||
} else {
|
||||
emit(AuthStateLoggedIn(user));
|
||||
}
|
||||
});
|
||||
// log in
|
||||
on<AuthEventLogIn>((event, emit) async {
|
||||
emit(const AuthStateLoading());
|
||||
final email = event.email;
|
||||
final password = event.password;
|
||||
try {
|
||||
final user = await provider.logIn(
|
||||
email: email,
|
||||
password: password,
|
||||
);
|
||||
emit(AuthStateLoggedIn(user));
|
||||
} on Exception catch (e) {
|
||||
emit(AuthStateLoginFailure(e));
|
||||
}
|
||||
});
|
||||
// log out
|
||||
on<AuthEventLogOut>((event, emit) async {
|
||||
try {
|
||||
emit(const AuthStateLoading());
|
||||
await provider.logOut();
|
||||
emit(const AuthStateLoggedOut());
|
||||
} on Exception catch (e) {
|
||||
emit(AuthStateLogoutFailure(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import 'package:flutter/foundation.dart' show immutable;
|
||||
|
||||
@immutable
|
||||
abstract class AuthEvent {
|
||||
const AuthEvent();
|
||||
}
|
||||
|
||||
class AuthEventInitialize extends AuthEvent {
|
||||
const AuthEventInitialize();
|
||||
}
|
||||
|
||||
class AuthEventLogIn extends AuthEvent {
|
||||
final String email;
|
||||
final String password;
|
||||
const AuthEventLogIn(this.email, this.password);
|
||||
}
|
||||
|
||||
class AuthEventLogOut extends AuthEvent {
|
||||
const AuthEventLogOut();
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import 'package:flutter/foundation.dart' show immutable;
|
||||
import 'package:mynotes/services/auth/auth_user.dart';
|
||||
|
||||
@immutable
|
||||
abstract class AuthState {
|
||||
const AuthState();
|
||||
}
|
||||
|
||||
class AuthStateLoading extends AuthState {
|
||||
const AuthStateLoading();
|
||||
}
|
||||
|
||||
class AuthStateLoggedIn extends AuthState {
|
||||
final AuthUser user;
|
||||
const AuthStateLoggedIn(this.user);
|
||||
}
|
||||
|
||||
class AuthStateLoginFailure extends AuthState {
|
||||
final Exception exception;
|
||||
const AuthStateLoginFailure(this.exception);
|
||||
}
|
||||
|
||||
class AuthStateNeedsVerification extends AuthState {
|
||||
const AuthStateNeedsVerification();
|
||||
}
|
||||
|
||||
class AuthStateLoggedOut extends AuthState {
|
||||
const AuthStateLoggedOut();
|
||||
}
|
||||
|
||||
class AuthStateLogoutFailure extends AuthState {
|
||||
final Exception exception;
|
||||
const AuthStateLogoutFailure(this.exception);
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mynotes/constants/routes.dart';
|
||||
import 'package:mynotes/services/auth/auth_exceptions.dart';
|
||||
import 'package:mynotes/services/auth/auth_service.dart';
|
||||
import 'package:mynotes/services/auth/bloc/auth_bloc.dart';
|
||||
import 'package:mynotes/services/auth/bloc/auth_event.dart';
|
||||
import 'package:mynotes/utilities/dialogs/error_dialog.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class LoginView extends StatefulWidget {
|
||||
const LoginView({Key? key}) : super(key: key);
|
||||
|
@ -60,24 +62,12 @@ class _LoginViewState extends State<LoginView> {
|
|||
final email = _email.text;
|
||||
final password = _password.text;
|
||||
try {
|
||||
await AuthService.firebase().logIn(
|
||||
email: email,
|
||||
password: password,
|
||||
);
|
||||
final user = AuthService.firebase().currentUser;
|
||||
if (user?.isEmailVerified ?? false) {
|
||||
// user's email is verified
|
||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
notesRoute,
|
||||
(route) => false,
|
||||
);
|
||||
} else {
|
||||
// user's email is NOT verified
|
||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
verifyEmailRoute,
|
||||
(route) => false,
|
||||
);
|
||||
}
|
||||
context.read<AuthBloc>().add(
|
||||
AuthEventLogIn(
|
||||
email,
|
||||
password,
|
||||
),
|
||||
);
|
||||
} on UserNotFoundAuthException {
|
||||
await showErrorDialog(
|
||||
context,
|
||||
|
|
|
@ -2,10 +2,13 @@ import 'package:flutter/material.dart';
|
|||
import 'package:mynotes/constants/routes.dart';
|
||||
import 'package:mynotes/enums/menu_action.dart';
|
||||
import 'package:mynotes/services/auth/auth_service.dart';
|
||||
import 'package:mynotes/services/auth/bloc/auth_bloc.dart';
|
||||
import 'package:mynotes/services/auth/bloc/auth_event.dart';
|
||||
import 'package:mynotes/services/cloud/cloud_note.dart';
|
||||
import 'package:mynotes/services/cloud/firebase_cloud_storage.dart';
|
||||
import 'package:mynotes/utilities/dialogs/logout_dialog.dart';
|
||||
import 'package:mynotes/views/notes/notes_list_view.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart' show ReadContext;
|
||||
|
||||
class NotesView extends StatefulWidget {
|
||||
const NotesView({Key? key}) : super(key: key);
|
||||
|
@ -42,11 +45,9 @@ class _NotesViewState extends State<NotesView> {
|
|||
case MenuAction.logout:
|
||||
final shouldLogout = await showLogOutDialog(context);
|
||||
if (shouldLogout) {
|
||||
await AuthService.firebase().logOut();
|
||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
loginRoute,
|
||||
(_) => false,
|
||||
);
|
||||
context.read<AuthBloc>().add(
|
||||
const AuthEventLogOut(),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue