diff --git a/README.md b/README.md index 431d74d..6698fd6 100644 --- a/README.md +++ b/README.md @@ -13,3 +13,22 @@ protections in place. 1. Add the package as a submodule with `git submodule add packages/` + +## Remove a package + +1. Remove the submodule entry from `.gitmodules` file +2. Remove the submodule entry from `.git/config` +3. Run `git rm --cached packages/` +4. Remove the submodule directory: `rm -rf packages/` +5. Remove the submodule directory from `.git/modules/`: `rm -rf .git/modules/packages/` +6. Commit the changes: `git commit -m "Remove submodule"` + + +## Update submodules +1. Run `git submodule update --remote --merge` +2. Commit the changes: `git commit -am "Update submodules"` +3. Push the changes: `git push origin main` +4. If you have made changes to the submodules, make sure to push those changes to their respective repositories as well. + +## Remove Local Submodules +1. Run `git submodule deinit -f -- packages/` \ No newline at end of file diff --git a/example/lib/app/app.locator.dart b/example/lib/app/app.locator.dart index fe367e5..c4c9b21 100644 --- a/example/lib/app/app.locator.dart +++ b/example/lib/app/app.locator.dart @@ -6,10 +6,10 @@ // ignore_for_file: public_member_api_docs, implementation_imports, depend_on_referenced_packages -import 'package:stacked_core/stacked_core.dart'; import 'package:stacked_services/src/bottom_sheet/bottom_sheet_service.dart'; import 'package:stacked_services/src/dialog/dialog_service.dart'; import 'package:stacked_services/src/navigation/navigation_service.dart'; +import 'package:stacked_shared/stacked_shared.dart'; import 'package:stacked_themes/src/theme_service.dart'; import '../services/epoch_service.dart'; @@ -20,8 +20,10 @@ import '../ui/bottom_nav/history/history_viewmodel.dart'; final exampleLocator = StackedLocator.instance; -Future setupExampleLocator( - {String? environment, EnvironmentFilter? environmentFilter}) async { +Future setupExampleLocator({ + String? environment, + EnvironmentFilter? environmentFilter, +}) async { // Register environments exampleLocator.registerEnvironment( environment: environment, environmentFilter: environmentFilter); diff --git a/example/lib/app/app.logger.dart b/example/lib/app/app.logger.dart index 49fa28f..26ab3f9 100644 --- a/example/lib/app/app.logger.dart +++ b/example/lib/app/app.logger.dart @@ -37,7 +37,7 @@ class SimpleLogPrinter extends LogPrinter { printCallingFunctionName && methodName != null ? ' | $methodName' : ''; var stackLog = event.stackTrace.toString(); var output = - '$emoji $className$methodNameSection - ${event.message}${printCallStack ? '\nSTACKTRACE:\n$stackLog' : ''}'; + '$emoji $className$methodNameSection - ${event.message}${event.error != null ? '\nERROR: ${event.error}\n' : ''}${printCallStack ? '\nSTACKTRACE:\n$stackLog' : ''}'; if (exludeLogsFromClasses .any((excludeClass) => className == excludeClass) || @@ -137,22 +137,6 @@ List? _formatStackTrace(StackTrace stackTrace, int methodCount) { } } -class MultipleLoggerOutput extends LogOutput { - final List logOutputs; - MultipleLoggerOutput(this.logOutputs); - - @override - void output(OutputEvent event) { - for (var logOutput in logOutputs) { - try { - logOutput.output(event); - } catch (e) { - print('Log output failed'); - } - } - } -} - Logger getLogger( String className, { bool printCallingFunctionName = true, @@ -168,7 +152,7 @@ Logger getLogger( showOnlyClass: showOnlyClass, exludeLogsFromClasses: exludeLogsFromClasses, ), - output: MultipleLoggerOutput([ + output: MultiOutput([ if (!kReleaseMode) ConsoleOutput(), ]), ); diff --git a/example/lib/app/app.router.dart b/example/lib/app/app.router.dart index 18ffc3f..fac11b3 100644 --- a/example/lib/app/app.router.dart +++ b/example/lib/app/app.router.dart @@ -1,32 +1,29 @@ // GENERATED CODE - DO NOT MODIFY BY HAND // ************************************************************************** -// StackedRouterGenerator +// StackedNavigatorGenerator // ************************************************************************** // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:example/app/custom_route_transition.dart' as _i7; -import 'package:example/datamodels/clashable_one.dart' as _i9; +import 'package:example/app/custom_route_transition.dart' as _i9; +import 'package:example/datamodels/clashable_one.dart' as _i10; import 'package:example/datamodels/clashable_two.dart' as _i11; -import 'package:example/datamodels/home_type.dart' as _i10; -import 'package:example/datamodels/home_type.dart'; -import 'package:example/ui/bottom_nav/bottom_nav_example.dart' as _i3; +import 'package:example/datamodels/home_type.dart' as _i1; +import 'package:example/ui/bottom_nav/bottom_nav_example.dart' as _i4; import 'package:example/ui/bottom_nav/favorites/favorites_view.dart' as _i12; import 'package:example/ui/bottom_nav/history/history_view.dart' as _i13; import 'package:example/ui/bottom_nav/profile/profile_view.dart' as _i14; -import 'package:example/ui/form/example_form_view.dart' as _i5; -import 'package:example/ui/home/home_view.dart' as _i2; +import 'package:example/ui/form/example_form_view.dart' as _i6; +import 'package:example/ui/home/home_view.dart' as _i3; import 'package:example/ui/multiple_futures_example/multiple_futures_example_view.dart' - as _i17; -import 'package:example/ui/nonreactive/nonreactive_view.dart' as _i6; -import 'package:example/ui/stream_view/stream_counter_view.dart' as _i4; -import 'package:flutter/cupertino.dart' as _i16; + as _i16; +import 'package:example/ui/nonreactive/nonreactive_view.dart' as _i7; +import 'package:example/ui/stream_view/stream_counter_view.dart' as _i5; +import 'package:flutter/cupertino.dart' as _i15; import 'package:flutter/material.dart' as _i8; import 'package:flutter/material.dart'; -import 'package:stacked/src/code_generation/router_annotation/transitions_builders.dart' - as _i15; -import 'package:stacked/stacked.dart' as _i1; -import 'package:stacked_services/stacked_services.dart' as _i18; +import 'package:stacked/stacked.dart' as _i2; +import 'package:stacked_services/stacked_services.dart' as _i17; class Routes { static const homeView = '/'; @@ -48,37 +45,37 @@ class Routes { }; } -class StackedRouter extends _i1.RouterBase { - final _routes = <_i1.RouteDef>[ - _i1.RouteDef( +class StackedRouter extends _i2.RouterBase { + final _routes = <_i2.RouteDef>[ + _i2.RouteDef( Routes.homeView, - page: _i2.HomeView, + page: _i3.HomeView, ), - _i1.RouteDef( + _i2.RouteDef( Routes.bottomNavExample, - page: _i3.BottomNavExample, + page: _i4.BottomNavExample, ), - _i1.RouteDef( + _i2.RouteDef( Routes.streamCounterView, - page: _i4.StreamCounterView, + page: _i5.StreamCounterView, ), - _i1.RouteDef( + _i2.RouteDef( Routes.exampleFormView, - page: _i5.ExampleFormView, + page: _i6.ExampleFormView, ), - _i1.RouteDef( + _i2.RouteDef( Routes.nonReactiveView, - page: _i6.NonReactiveView, + page: _i7.NonReactiveView, ), ]; - final _pagesMap = { - _i2.HomeView: (data) { + final _pagesMap = { + _i3.HomeView: (data) { final args = data.getArgs( orElse: () => const HomeViewArguments(), ); - return MaterialPageRoute( - builder: (context) => _i2.HomeView( + return _i8.MaterialPageRoute( + builder: (context) => _i3.HomeView( key: args.key, title: args.title, isLoggedIn: args.isLoggedIn, @@ -87,43 +84,44 @@ class StackedRouter extends _i1.RouterBase { settings: data, ); }, - _i3.BottomNavExample: (data) { - return MaterialPageRoute( - builder: (context) => const _i3.BottomNavExample(), + _i4.BottomNavExample: (data) { + return _i8.MaterialPageRoute( + builder: (context) => const _i4.BottomNavExample(), settings: data, ); }, - _i4.StreamCounterView: (data) { + _i5.StreamCounterView: (data) { final args = data.getArgs(nullOk: false); - return MaterialPageRoute( - builder: (context) => _i4.StreamCounterView( + return _i8.MaterialPageRoute( + builder: (context) => _i5.StreamCounterView( key: args.key, clashableTwo: args.clashableTwo), settings: data, ); }, - _i5.ExampleFormView: (data) { + _i6.ExampleFormView: (data) { final args = data.getArgs(nullOk: false); - return MaterialPageRoute( + return _i8.MaterialPageRoute( builder: (context) => - _i5.ExampleFormView(key: args.key, clashableOne: args.clashableOne), + _i6.ExampleFormView(key: args.key, clashableOne: args.clashableOne), settings: data, ); }, - _i6.NonReactiveView: (data) { - return PageRouteBuilder( + _i7.NonReactiveView: (data) { + return _i8.PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => - const _i6.NonReactiveView(), + const _i7.NonReactiveView(), settings: data, transitionsBuilder: - data.transition ?? _i7.CustomRouteTransition.sharedAxis, + data.transition ?? _i9.CustomRouteTransition.sharedAxis, ); }, }; @override - List<_i1.RouteDef> get routes => _routes; + List<_i2.RouteDef> get routes => _routes; + @override - Map get pagesMap => _pagesMap; + Map get pagesMap => _pagesMap; } class HomeViewArguments { @@ -132,7 +130,7 @@ class HomeViewArguments { this.title = 'hello', this.isLoggedIn = false, this.clashableGetter, - this.homeTypes = const [HomeType.apartment, HomeType.house], + this.homeTypes = const [_i1.HomeType.apartment, _i1.HomeType.house], }); final _i8.Key? key; @@ -141,14 +139,33 @@ class HomeViewArguments { final bool? isLoggedIn; - final _i9.Clashable Function(String)? clashableGetter; + final _i10.Clashable Function(String)? clashableGetter; - final List<_i10.HomeType> homeTypes; + final List<_i1.HomeType> homeTypes; @override String toString() { return '{"key": "$key", "title": "$title", "isLoggedIn": "$isLoggedIn", "clashableGetter": "$clashableGetter", "homeTypes": "$homeTypes"}'; } + + @override + bool operator ==(covariant HomeViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && + other.title == title && + other.isLoggedIn == isLoggedIn && + other.clashableGetter == clashableGetter && + other.homeTypes == homeTypes; + } + + @override + int get hashCode { + return key.hashCode ^ + title.hashCode ^ + isLoggedIn.hashCode ^ + clashableGetter.hashCode ^ + homeTypes.hashCode; + } } class StreamCounterViewArguments { @@ -165,6 +182,17 @@ class StreamCounterViewArguments { String toString() { return '{"key": "$key", "clashableTwo": "$clashableTwo"}'; } + + @override + bool operator ==(covariant StreamCounterViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && other.clashableTwo == clashableTwo; + } + + @override + int get hashCode { + return key.hashCode ^ clashableTwo.hashCode; + } } class ExampleFormViewArguments { @@ -175,20 +203,31 @@ class ExampleFormViewArguments { final _i8.Key? key; - final _i9.Clashable clashableOne; + final _i10.Clashable clashableOne; @override String toString() { return '{"key": "$key", "clashableOne": "$clashableOne"}'; } + + @override + bool operator ==(covariant ExampleFormViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && other.clashableOne == clashableOne; + } + + @override + int get hashCode { + return key.hashCode ^ clashableOne.hashCode; + } } class BottomNavExampleRoutes { - static const favoritesView = '/favorites-view'; + static const favoritesView = 'favorites-view'; - static const historyView = '/history-view'; + static const historyView = 'history-view'; - static const profileView = '/profile-view'; + static const profileView = 'profile-view'; static const all = { favoritesView, @@ -197,42 +236,42 @@ class BottomNavExampleRoutes { }; } -class BottomNavExampleRouter extends _i1.RouterBase { - final _routes = <_i1.RouteDef>[ - _i1.RouteDef( +class BottomNavExampleRouter extends _i2.RouterBase { + final _routes = <_i2.RouteDef>[ + _i2.RouteDef( BottomNavExampleRoutes.favoritesView, page: _i12.FavoritesView, ), - _i1.RouteDef( + _i2.RouteDef( BottomNavExampleRoutes.historyView, page: _i13.HistoryView, ), - _i1.RouteDef( + _i2.RouteDef( BottomNavExampleRoutes.profileView, page: _i14.ProfileView, ), ]; - final _pagesMap = { + final _pagesMap = { _i12.FavoritesView: (data) { - final args = data.getArgs( - orElse: () => const NestedFavoritesViewArguments(), + final args = data.getArgs( + orElse: () => const FavoritesViewArguments(), ); - return _i1.buildAdaptivePageRoute( + return _i2.buildAdaptivePageRoute( builder: (context) => _i12.FavoritesView(key: args.key, id: args.id), settings: data, ); }, _i13.HistoryView: (data) { - return PageRouteBuilder( + return _i8.PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => const _i13.HistoryView(), settings: data, - transitionsBuilder: data.transition ?? _i15.TransitionsBuilders.fadeIn, + transitionsBuilder: data.transition ?? _i2.TransitionsBuilders.fadeIn, ); }, _i14.ProfileView: (data) { - return _i16.CupertinoPageRoute( + return _i15.CupertinoPageRoute( builder: (context) => const _i14.ProfileView(), settings: data, ); @@ -240,13 +279,14 @@ class BottomNavExampleRouter extends _i1.RouterBase { }; @override - List<_i1.RouteDef> get routes => _routes; + List<_i2.RouteDef> get routes => _routes; + @override - Map get pagesMap => _pagesMap; + Map get pagesMap => _pagesMap; } -class NestedFavoritesViewArguments { - const NestedFavoritesViewArguments({ +class FavoritesViewArguments { + const FavoritesViewArguments({ this.key, this.id, }); @@ -259,12 +299,23 @@ class NestedFavoritesViewArguments { String toString() { return '{"key": "$key", "id": "$id"}'; } + + @override + bool operator ==(covariant FavoritesViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && other.id == id; + } + + @override + int get hashCode { + return key.hashCode ^ id.hashCode; + } } class FavoritesViewRoutes { - static const multipleFuturesExampleView = '/multiple-futures-example-view'; + static const multipleFuturesExampleView = 'multiple-futures-example-view'; - static const historyView = '/history-view'; + static const historyView = 'history-view'; static const all = { multipleFuturesExampleView, @@ -272,27 +323,27 @@ class FavoritesViewRoutes { }; } -class FavoritesViewRouter extends _i1.RouterBase { - final _routes = <_i1.RouteDef>[ - _i1.RouteDef( +class FavoritesViewRouter extends _i2.RouterBase { + final _routes = <_i2.RouteDef>[ + _i2.RouteDef( FavoritesViewRoutes.multipleFuturesExampleView, - page: _i17.MultipleFuturesExampleView, + page: _i16.MultipleFuturesExampleView, ), - _i1.RouteDef( + _i2.RouteDef( FavoritesViewRoutes.historyView, page: _i13.HistoryView, ), ]; - final _pagesMap = { - _i17.MultipleFuturesExampleView: (data) { - return MaterialPageRoute( - builder: (context) => const _i17.MultipleFuturesExampleView(), + final _pagesMap = { + _i16.MultipleFuturesExampleView: (data) { + return _i8.MaterialPageRoute( + builder: (context) => const _i16.MultipleFuturesExampleView(), settings: data, ); }, _i13.HistoryView: (data) { - return PageRouteBuilder( + return _i8.PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => const _i13.HistoryView(), settings: data, @@ -305,18 +356,22 @@ class FavoritesViewRouter extends _i1.RouterBase { }; @override - List<_i1.RouteDef> get routes => _routes; + List<_i2.RouteDef> get routes => _routes; + @override - Map get pagesMap => _pagesMap; + Map get pagesMap => _pagesMap; } -extension NavigatorStateExtension on _i18.NavigationService { +extension NavigatorStateExtension on _i17.NavigationService { Future navigateToHomeView({ _i8.Key? key, String? title = 'hello', bool? isLoggedIn = false, - _i9.Clashable Function(String)? clashableGetter, - List<_i10.HomeType> homeTypes = const [HomeType.apartment, HomeType.house], + _i10.Clashable Function(String)? clashableGetter, + List<_i1.HomeType> homeTypes = const [ + _i1.HomeType.apartment, + _i1.HomeType.house + ], int? routerId, bool preventDuplicates = true, Map? parameters, @@ -370,7 +425,7 @@ extension NavigatorStateExtension on _i18.NavigationService { Future navigateToExampleFormView({ _i8.Key? key, - required _i9.Clashable clashableOne, + required _i10.Clashable clashableOne, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -400,7 +455,7 @@ extension NavigatorStateExtension on _i18.NavigationService { transition: transition); } - Future navigateToNestedFavoritesViewInBottomNavExample({ + Future navigateToFavoritesView({ _i8.Key? key, String? id, int? routerId, @@ -410,14 +465,14 @@ extension NavigatorStateExtension on _i18.NavigationService { transition, }) async { return navigateTo(BottomNavExampleRoutes.favoritesView, - arguments: NestedFavoritesViewArguments(key: key, id: id), + arguments: FavoritesViewArguments(key: key, id: id), id: routerId, preventDuplicates: preventDuplicates, parameters: parameters, transition: transition); } - Future navigateToNestedHistoryViewInBottomNavExample([ + Future navigateToNestedHistoryViewInBottomNavExampleRouter([ int? routerId, bool preventDuplicates = true, Map? parameters, @@ -431,7 +486,7 @@ extension NavigatorStateExtension on _i18.NavigationService { transition: transition); } - Future navigateToNestedProfileViewInBottomNavExample([ + Future navigateToNestedProfileViewInBottomNavExampleRouter([ int? routerId, bool preventDuplicates = true, Map? parameters, @@ -445,7 +500,8 @@ extension NavigatorStateExtension on _i18.NavigationService { transition: transition); } - Future navigateToNestedMultipleFuturesExampleViewInFavoritesView([ + Future + navigateToNestedMultipleFuturesExampleViewInFavoritesViewRouter([ int? routerId, bool preventDuplicates = true, Map? parameters, @@ -459,7 +515,7 @@ extension NavigatorStateExtension on _i18.NavigationService { transition: transition); } - Future navigateToNestedHistoryViewInFavoritesView([ + Future navigateToNestedHistoryViewInFavoritesViewRouter([ int? routerId, bool preventDuplicates = true, Map? parameters, @@ -477,8 +533,11 @@ extension NavigatorStateExtension on _i18.NavigationService { _i8.Key? key, String? title = 'hello', bool? isLoggedIn = false, - _i9.Clashable Function(String)? clashableGetter, - List<_i10.HomeType> homeTypes = const [HomeType.apartment, HomeType.house], + _i10.Clashable Function(String)? clashableGetter, + List<_i1.HomeType> homeTypes = const [ + _i1.HomeType.apartment, + _i1.HomeType.house + ], int? routerId, bool preventDuplicates = true, Map? parameters, @@ -532,7 +591,7 @@ extension NavigatorStateExtension on _i18.NavigationService { Future replaceWithExampleFormView({ _i8.Key? key, - required _i9.Clashable clashableOne, + required _i10.Clashable clashableOne, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -562,7 +621,7 @@ extension NavigatorStateExtension on _i18.NavigationService { transition: transition); } - Future replaceWithNestedFavoritesViewInBottomNavExample({ + Future replaceWithFavoritesView({ _i8.Key? key, String? id, int? routerId, @@ -572,14 +631,14 @@ extension NavigatorStateExtension on _i18.NavigationService { transition, }) async { return replaceWith(BottomNavExampleRoutes.favoritesView, - arguments: NestedFavoritesViewArguments(key: key, id: id), + arguments: FavoritesViewArguments(key: key, id: id), id: routerId, preventDuplicates: preventDuplicates, parameters: parameters, transition: transition); } - Future replaceWithNestedHistoryViewInBottomNavExample([ + Future replaceWithNestedHistoryViewInBottomNavExampleRouter([ int? routerId, bool preventDuplicates = true, Map? parameters, @@ -593,7 +652,7 @@ extension NavigatorStateExtension on _i18.NavigationService { transition: transition); } - Future replaceWithNestedProfileViewInBottomNavExample([ + Future replaceWithNestedProfileViewInBottomNavExampleRouter([ int? routerId, bool preventDuplicates = true, Map? parameters, @@ -607,7 +666,8 @@ extension NavigatorStateExtension on _i18.NavigationService { transition: transition); } - Future replaceWithNestedMultipleFuturesExampleViewInFavoritesView([ + Future + replaceWithNestedMultipleFuturesExampleViewInFavoritesViewRouter([ int? routerId, bool preventDuplicates = true, Map? parameters, @@ -621,7 +681,7 @@ extension NavigatorStateExtension on _i18.NavigationService { transition: transition); } - Future replaceWithNestedHistoryViewInFavoritesView([ + Future replaceWithNestedHistoryViewInFavoritesViewRouter([ int? routerId, bool preventDuplicates = true, Map? parameters, diff --git a/example/lib/ui/drop_down_menu_from/select_location_view.form.dart b/example/lib/ui/drop_down_menu_from/select_location_view.form.dart index abfca4e..00a8590 100644 --- a/example/lib/ui/drop_down_menu_from/select_location_view.form.dart +++ b/example/lib/ui/drop_down_menu_from/select_location_view.form.dart @@ -28,15 +28,17 @@ final Map ProvinceValueToTitleMap = { 'North West': 'North West', }; -mixin $SelectLocationView on StatelessWidget { +mixin $SelectLocationView { /// Registers a listener on every generated controller that calls [model.setData()] /// with the latest textController values void syncFormWithViewModel(FormViewModel model) {} /// Registers a listener on every generated controller that calls [model.setData()] /// with the latest textController values - @Deprecated('Use syncFormWithViewModel instead.' - 'This feature was deprecated after 3.1.0.') + @Deprecated( + 'Use syncFormWithViewModel instead.' + 'This feature was deprecated after 3.1.0.', + ) void listenToFormUpdated(FormViewModel model) {} /// Calls dispose on all the generated controllers and focus nodes @@ -63,7 +65,6 @@ extension ValueProperties on FormViewModel { this.fieldsValidationMessages[CountryValueKey]; String? get provinceValidationMessage => this.fieldsValidationMessages[ProvinceValueKey]; - void clearForm() {} } extension Methods on FormViewModel { @@ -79,4 +80,7 @@ extension Methods on FormViewModel { this.fieldsValidationMessages[CountryValueKey] = validationMessage; setProvinceValidationMessage(String? validationMessage) => this.fieldsValidationMessages[ProvinceValueKey] = validationMessage; + + /// Clears text input fields on the Form + void clearForm() {} } diff --git a/example/lib/ui/form/example_form_view.form.dart b/example/lib/ui/form/example_form_view.form.dart index 1ecd6e1..5f98d5f 100644 --- a/example/lib/ui/form/example_form_view.form.dart +++ b/example/lib/ui/form/example_form_view.form.dart @@ -34,7 +34,7 @@ final Map _ExampleFormViewTextValidations = ShortBioValueKey: null, }; -mixin $ExampleFormView on StatelessWidget { +mixin $ExampleFormView { TextEditingController get emailController => _getFormTextEditingController(EmailValueKey, initialValue: 'Lorem'); CustomEditingController get passwordController => @@ -59,11 +59,14 @@ mixin $ExampleFormView on StatelessWidget { FocusNode get passwordFocusNode => _getFormFocusNode(PasswordValueKey); FocusNode get shortBioFocusNode => _getFormFocusNode(ShortBioValueKey); - TextEditingController _getFormTextEditingController(String key, - {String? initialValue}) { + TextEditingController _getFormTextEditingController( + String key, { + String? initialValue, + }) { if (_ExampleFormViewTextEditingControllers.containsKey(key)) { return _ExampleFormViewTextEditingControllers[key]!; } + _ExampleFormViewTextEditingControllers[key] = TextEditingController(text: initialValue); return _ExampleFormViewTextEditingControllers[key]!; @@ -87,15 +90,17 @@ mixin $ExampleFormView on StatelessWidget { /// Registers a listener on every generated controller that calls [model.setData()] /// with the latest textController values - @Deprecated('Use syncFormWithViewModel instead.' - 'This feature was deprecated after 3.1.0.') + @Deprecated( + 'Use syncFormWithViewModel instead.' + 'This feature was deprecated after 3.1.0.', + ) void listenToFormUpdated(FormViewModel model) { emailController.addListener(() => _updateFormData(model)); passwordController.addListener(() => _updateFormData(model)); shortBioController.addListener(() => _updateFormData(model)); } - final bool _autoTextFieldValidation = false; + static const bool _autoTextFieldValidation = false; bool validateFormFields(FormViewModel model) { _updateFormData(model, forceValidate: true); return model.isFormValid; @@ -111,28 +116,12 @@ mixin $ExampleFormView on StatelessWidget { ShortBioValueKey: shortBioController.text, }), ); + if (_autoTextFieldValidation || forceValidate) { - _updateValidationData(model); + updateValidationData(model); } } - /// Updates the fieldsValidationMessages on the FormViewModel - void _updateValidationData(FormViewModel model) => - model.setValidationMessages({ - EmailValueKey: _getValidationMessage(EmailValueKey), - PasswordValueKey: _getValidationMessage(PasswordValueKey), - ShortBioValueKey: _getValidationMessage(ShortBioValueKey), - }); - - /// Returns the validation message for the given key - String? _getValidationMessage(String key) { - final validatorForKey = _ExampleFormViewTextValidations[key]; - if (validatorForKey == null) return null; - String? validationMessageForKey = - validatorForKey(_ExampleFormViewTextEditingControllers[key]!.text); - return validationMessageForKey; - } - /// Calls dispose on all the generated controllers and focus nodes void disposeForm() { // The dispose function for a TextEditingController sets all listeners to null @@ -235,11 +224,6 @@ extension ValueProperties on FormViewModel { this.fieldsValidationMessages[BirthDateValueKey]; String? get doYouLoveFoodValidationMessage => this.fieldsValidationMessages[DoYouLoveFoodValueKey]; - void clearForm() { - emailValue = ''; - passwordValue = ''; - shortBioValue = ''; - } } extension Methods on FormViewModel { @@ -274,4 +258,39 @@ extension Methods on FormViewModel { this.fieldsValidationMessages[BirthDateValueKey] = validationMessage; setDoYouLoveFoodValidationMessage(String? validationMessage) => this.fieldsValidationMessages[DoYouLoveFoodValueKey] = validationMessage; + + /// Clears text input fields on the Form + void clearForm() { + emailValue = ''; + passwordValue = ''; + shortBioValue = ''; + } + + /// Validates text input fields on the Form + void validateForm() { + this.setValidationMessages({ + EmailValueKey: getValidationMessage(EmailValueKey), + PasswordValueKey: getValidationMessage(PasswordValueKey), + ShortBioValueKey: getValidationMessage(ShortBioValueKey), + }); + } } + +/// Returns the validation message for the given key +String? getValidationMessage(String key) { + final validatorForKey = _ExampleFormViewTextValidations[key]; + if (validatorForKey == null) return null; + + String? validationMessageForKey = validatorForKey( + _ExampleFormViewTextEditingControllers[key]!.text, + ); + + return validationMessageForKey; +} + +/// Updates the fieldsValidationMessages on the FormViewModel +void updateValidationData(FormViewModel model) => model.setValidationMessages({ + EmailValueKey: getValidationMessage(EmailValueKey), + PasswordValueKey: getValidationMessage(PasswordValueKey), + ShortBioValueKey: getValidationMessage(ShortBioValueKey), + }); diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 89a1240..fdfead6 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: none version: 1.0.0+1 environment: - sdk: '>=2.17.5 <3.0.0' + sdk: ">=2.17.5 <3.0.0" dependencies: flutter: @@ -23,7 +23,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.2 + cupertino_icons: ^1.0.8 # state management stacked: @@ -31,6 +31,7 @@ dependencies: stacked_hooks: stacked_themes: stacked_crashlytics: + stacked_shared: flutter_hooks: ^0.18.4 # navigation @@ -50,7 +51,7 @@ dependency_overrides: path: ../packages/crashlytics/ stacked_generator: path: ../packages/generator/ - stacked_core: + stacked_shared: path: ../packages/core/ dev_dependencies: diff --git a/packages/cli b/packages/cli index 4511e57..88e0ba0 160000 --- a/packages/cli +++ b/packages/cli @@ -1 +1 @@ -Subproject commit 4511e5745d83a9451e95c456b4612c80834eec92 +Subproject commit 88e0ba0e12953cc813d9b8c10f46c6276609a531 diff --git a/packages/core b/packages/core index b25da00..6c95968 160000 --- a/packages/core +++ b/packages/core @@ -1 +1 @@ -Subproject commit b25da001bf3157eca0a67af95090176880049446 +Subproject commit 6c959685906a05f6b0cf94d4e92a7a1c11e1a1f6 diff --git a/packages/crashlytics b/packages/crashlytics index ee31077..fafee9e 160000 --- a/packages/crashlytics +++ b/packages/crashlytics @@ -1 +1 @@ -Subproject commit ee310774cee4f4d235a0d28c3c9926714836c901 +Subproject commit fafee9e577ed3d7e44689becb5fee8d6b9d95ae8