From 75f70d8316591188bcd5f5279fdcff6a7b2f0bac Mon Sep 17 00:00:00 2001 From: kotelnikov-aa Date: Tue, 7 Jun 2022 18:40:28 +0700 Subject: [PATCH] hw_lesson20/kotelnikov MobX -> Bloc --- .idea/epic_flutter.iml | 9 +- .idea/libraries/Dart_Packages.xml | 1220 +++++++++++++++++ .idea/libraries/Dart_SDK.xml | 27 + flutter_base/lib/mobx/form/form_store.dart | 2 +- .../lib/mobx/form_bloc/form_bloc.dart | 114 ++ flutter_base/lib/mobx/form_bloc/main.dart | 92 ++ flutter_base/pubspec.lock | 68 +- 7 files changed, 1496 insertions(+), 36 deletions(-) create mode 100644 .idea/libraries/Dart_Packages.xml create mode 100644 .idea/libraries/Dart_SDK.xml create mode 100644 flutter_base/lib/mobx/form_bloc/form_bloc.dart create mode 100644 flutter_base/lib/mobx/form_bloc/main.dart diff --git a/.idea/epic_flutter.iml b/.idea/epic_flutter.iml index 2ce7fb4..b946f02 100644 --- a/.idea/epic_flutter.iml +++ b/.idea/epic_flutter.iml @@ -1,5 +1,10 @@ + + + + + @@ -10,7 +15,9 @@ - + + + \ No newline at end of file diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml new file mode 100644 index 0000000..b07fba4 --- /dev/null +++ b/.idea/libraries/Dart_Packages.xml @@ -0,0 +1,1220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Dart_SDK.xml b/.idea/libraries/Dart_SDK.xml new file mode 100644 index 0000000..c6628b5 --- /dev/null +++ b/.idea/libraries/Dart_SDK.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/flutter_base/lib/mobx/form/form_store.dart b/flutter_base/lib/mobx/form/form_store.dart index 6f39e91..bb34688 100644 --- a/flutter_base/lib/mobx/form/form_store.dart +++ b/flutter_base/lib/mobx/form/form_store.dart @@ -41,7 +41,7 @@ abstract class _FormStore with Store { @action void validateEmail(String value) { - error.email = isEmail(value) ? 'Not a valid email' : null; + error.email = !isEmail(value) ? 'Not a valid email' : null; } @action diff --git a/flutter_base/lib/mobx/form_bloc/form_bloc.dart b/flutter_base/lib/mobx/form_bloc/form_bloc.dart new file mode 100644 index 0000000..ab181b6 --- /dev/null +++ b/flutter_base/lib/mobx/form_bloc/form_bloc.dart @@ -0,0 +1,114 @@ +import 'package:bloc/bloc.dart'; +import 'package:validators2/validators.dart'; + +abstract class ValidateEvent {} + +class ValidateUsernameEvent extends ValidateEvent { + final String username; + ValidateUsernameEvent(this.username); +} + +class ValidatePasswordEvent extends ValidateEvent { + final String password; + ValidatePasswordEvent(this.password); +} + +class ValidateEmailEvent extends ValidateEvent { + final String email; + ValidateEmailEvent(this.email); +} + +class FormErrorState { + final String? errorUsername; + final String? errorEmail; + final String? errorPassword; + + FormErrorState({ + required this.errorUsername, + required this.errorEmail, + required this.errorPassword, + }); + + bool get hasErrors => errorUsername != null || errorEmail != null || errorPassword != null; + +} + +class ValidateBloc extends Bloc { + ValidateBloc() + : super( + FormErrorState( + errorUsername: null, + errorEmail: null, + errorPassword: null, + ), + ) { + on((ValidateUsernameEvent event, Emitter emit) async { + if (isNull(event.username) || event.username.isEmpty) { + emit(FormErrorState( + errorUsername: 'Field is required', + errorEmail: state.errorEmail, + errorPassword: state.errorPassword)); + return; + } + try { + emit( + FormErrorState( + errorUsername: null, + errorEmail: state.errorEmail, + errorPassword: state.errorPassword), + ); + final isValid = await checkValidUsername(event.username); + if (!isValid) { + emit( + FormErrorState( + errorUsername: 'Username cannot be "admin"', + errorEmail: state.errorEmail, + errorPassword: state.errorPassword), + ); + return; + } + } catch (_) { + emit( + FormErrorState( + errorUsername: null, + errorEmail: state.errorEmail, + errorPassword: state.errorPassword), + ); + } + }); + on((ValidatePasswordEvent event, Emitter emit) { + if (!isNull(event.password) && event.password.isNotEmpty) { + emit(FormErrorState( + errorUsername: state.errorUsername, + errorEmail: state.errorEmail, + errorPassword: null)); + } else { + emit(FormErrorState( + errorUsername: state.errorUsername, + errorEmail: state.errorEmail, + errorPassword: 'Field is required')); + } + }); + on((ValidateEmailEvent event, Emitter emit) { + if (isEmail(event.email)) { + emit(FormErrorState( + errorUsername: state.errorUsername, + errorEmail: null, + errorPassword: state.errorPassword)); + } else { + emit(FormErrorState( + errorUsername: state.errorUsername, + errorEmail: 'Not a valid email', + errorPassword: state.errorPassword)); + } + }); + } + + +} //close bloc + +Future checkValidUsername(String value) async { + await Future.delayed(const Duration(seconds: 1)); + + return value != 'admin'; +} diff --git a/flutter_base/lib/mobx/form_bloc/main.dart b/flutter_base/lib/mobx/form_bloc/main.dart new file mode 100644 index 0000000..1cf7577 --- /dev/null +++ b/flutter_base/lib/mobx/form_bloc/main.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'form_bloc.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: BlocProvider( + create: (context) => ValidateBloc(), + child: const AppForm(), + ), + ); + } +} + +class AppForm extends StatefulWidget { + const AppForm({Key? key}) : super(key: key); + @override + State createState() => _AppFormState(); +} + +class _AppFormState extends State { + + @override + Widget build(BuildContext context) { + ValidateBloc bloc = BlocProvider.of(context); + return Scaffold( + appBar: AppBar( + title: const Text('Signum form'), + ), + body: Form( + child: Padding( + padding: const EdgeInsets.all(10), + child: Column( + children: [ + BlocBuilder( + bloc: bloc, + builder: (context, state) => TextField( + onChanged: (value) { + bloc.add(ValidateUsernameEvent(value)); + }, + decoration: InputDecoration( + labelText: 'Username', + hintText: 'Pick a username', + errorText: state.errorUsername, + ), + ), + ), + BlocBuilder( + bloc: bloc, + builder: (context, state) => TextField( + onChanged: (value) { + bloc.add(ValidateEmailEvent(value)); + }, + decoration: InputDecoration( + labelText: 'Email', + hintText: 'Enter your email address', + errorText: state.errorEmail, + ), + ), + ), + BlocBuilder( + bloc: bloc, + builder: (context, state) => TextField( + onChanged: (value) { + bloc.add(ValidatePasswordEvent(value)); + }, + decoration: InputDecoration( + labelText: 'Password', + hintText: 'Set a password', + errorText: state.errorPassword, + ), + ), + ), + ElevatedButton( + onPressed: () {}, + child: const Text('Sign up'), + ), + ], + ), + ), + ), + ); + } +} diff --git a/flutter_base/pubspec.lock b/flutter_base/pubspec.lock index c9940bc..8a8b282 100644 --- a/flutter_base/pubspec.lock +++ b/flutter_base/pubspec.lock @@ -84,7 +84,7 @@ packages: name: build_resolvers url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.0.9" build_runner: dependency: "direct dev" description: @@ -119,7 +119,7 @@ packages: name: cached_network_image url: "https://pub.dartlang.org" source: hosted - version: "3.2.0" + version: "3.2.1" cached_network_image_platform_interface: dependency: transitive description: @@ -189,14 +189,14 @@ packages: name: convert url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" cross_file: dependency: transitive description: name: cross_file url: "https://pub.dartlang.org" source: hosted - version: "0.3.3" + version: "0.3.3+1" crypto: dependency: transitive description: @@ -210,7 +210,7 @@ packages: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.0.5" dart_style: dependency: transitive description: @@ -245,7 +245,7 @@ packages: name: ffi url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "1.2.1" file: dependency: transitive description: @@ -259,7 +259,7 @@ packages: name: file_picker url: "https://pub.dartlang.org" source: hosted - version: "4.5.1" + version: "4.6.1" fixnum: dependency: transitive description: @@ -285,7 +285,7 @@ packages: name: flutter_blurhash url: "https://pub.dartlang.org" source: hosted - version: "0.6.8" + version: "0.7.0" flutter_cache_manager: dependency: transitive description: @@ -320,7 +320,7 @@ packages: name: flutter_form_builder url: "https://pub.dartlang.org" source: hosted - version: "7.1.1" + version: "7.2.1" flutter_keyboard_visibility: dependency: transitive description: @@ -374,7 +374,7 @@ packages: name: flutter_rating_bar url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.0.1" flutter_test: dependency: "direct dev" description: flutter @@ -475,7 +475,7 @@ packages: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.0.1" image: dependency: transitive description: @@ -496,7 +496,7 @@ packages: name: image_picker_android url: "https://pub.dartlang.org" source: hosted - version: "0.8.4+13" + version: "0.8.5" image_picker_for_web: dependency: transitive description: @@ -510,7 +510,7 @@ packages: name: image_picker_ios url: "https://pub.dartlang.org" source: hosted - version: "0.8.5+2" + version: "0.8.5+5" image_picker_platform_interface: dependency: transitive description: @@ -622,7 +622,7 @@ packages: name: octo_image url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.0.2" package_config: dependency: transitive description: @@ -643,49 +643,49 @@ packages: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "2.0.9" + version: "2.0.11" path_provider_android: dependency: transitive description: name: path_provider_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.13" + version: "2.0.14" path_provider_ios: dependency: transitive description: name: path_provider_ios url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.0.9" path_provider_linux: dependency: transitive description: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" + version: "2.1.7" path_provider_macos: dependency: transitive description: name: path_provider_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.6" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" path_provider_windows: dependency: transitive description: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.7" pedantic: dependency: transitive description: @@ -776,7 +776,7 @@ packages: name: provider url: "https://pub.dartlang.org" source: hosted - version: "6.0.2" + version: "6.0.3" pub_semver: dependency: transitive description: @@ -804,42 +804,42 @@ packages: name: rxdart url: "https://pub.dartlang.org" source: hosted - version: "0.27.3" + version: "0.27.4" shared_preferences: dependency: "direct main" description: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.0.13" + version: "2.0.15" shared_preferences_android: dependency: transitive description: name: shared_preferences_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.0.12" shared_preferences_ios: dependency: transitive description: name: shared_preferences_ios url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" shared_preferences_platform_interface: dependency: transitive description: @@ -853,14 +853,14 @@ packages: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" shelf: dependency: transitive description: @@ -881,7 +881,7 @@ packages: name: signature url: "https://pub.dartlang.org" source: hosted - version: "5.0.0" + version: "5.0.1" sky_engine: dependency: transitive description: flutter @@ -977,7 +977,7 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.1" uuid: dependency: transitive description: @@ -1026,7 +1026,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.5.2" + version: "2.6.1" xdg_directories: dependency: transitive description: @@ -1050,4 +1050,4 @@ packages: version: "3.1.1" sdks: dart: ">=2.17.0 <3.0.0" - flutter: ">=2.8.1" + flutter: ">=3.0.0"