diff --git a/packages/wyatt_bloc_helper/lib/src/bloc_base/bloc_base_provider_screen.dart b/packages/wyatt_bloc_helper/lib/src/bloc_base/bloc_base_provider_screen.dart index 26c656e2..6c3815d5 100644 --- a/packages/wyatt_bloc_helper/lib/src/bloc_base/bloc_base_provider_screen.dart +++ b/packages/wyatt_bloc_helper/lib/src/bloc_base/bloc_base_provider_screen.dart @@ -28,7 +28,7 @@ import 'package:wyatt_bloc_helper/src/utils/smart_provider.dart'; /// It automatically handles closing the instance when used with [create]. /// By default, [create] is called only when the instance is accessed. /// To override this behavior, set [lazy] to `false`. -/// +/// /// By default, it provide already provided instance found in the tree. /// To override this behavior, set [smart] to `false`. /// {@endtemplate} @@ -47,13 +47,21 @@ abstract class BlocBaseProviderScreen, final bool lazy; /// Whether this uses [SmartProvider]. - /// Defaults to `true`. But if you want to provide new [Bloc] or [Cubit] + /// Defaults to `true`. But if you want to provide new [Bloc] or [Cubit] /// of a same type in a sub-tree you may have to disable this. final bool smart; /// Creates the [Bloc] or [Cubit] to be used. Bloc create(BuildContext context); + /// Initialize the [Bloc] or [Cubit]. + /// + /// This function is useful when using with [SmartProvider], because + /// if you want to pass an initial event to your bloc you can pass it in + /// `create` function but if you re-use the bloc below in the tree this event + /// will never be re-pass. + Bloc init(BuildContext context, Bloc bloc) => bloc; + /// Creates the child [Widget] to be used. Widget builder(BuildContext context); @@ -63,6 +71,7 @@ abstract class BlocBaseProviderScreen, lazy: lazy, enable: smart, create: (_) => create(context), + init: (_, bloc) => init(context, bloc), child: Builder(builder: builder), ); } diff --git a/packages/wyatt_bloc_helper/lib/src/bloc_base/bloc_base_screen.dart b/packages/wyatt_bloc_helper/lib/src/bloc_base/bloc_base_screen.dart index 4c853af6..b061be89 100644 --- a/packages/wyatt_bloc_helper/lib/src/bloc_base/bloc_base_screen.dart +++ b/packages/wyatt_bloc_helper/lib/src/bloc_base/bloc_base_screen.dart @@ -40,7 +40,6 @@ abstract class BlocBaseScreen, /// accessed the first time, not when provided. final bool lazy; - /// Whether this uses [SmartProvider]. /// Defaults to `true`. But if you want to provide new Bloc of a same type, /// in a sub-tree you may have to disable this. @@ -49,12 +48,21 @@ abstract class BlocBaseScreen, /// Creates the [Cubit] or [Bloc] to be used. Bloc create(BuildContext context); + /// Initialize the [Bloc] or [Cubit]. + /// + /// This function is useful when using with [SmartProvider], because + /// if you want to pass an initial event to your bloc you can pass it in + /// `create` function but if you re-use the bloc below in the tree this event + /// will never be re-pass. + Bloc init(BuildContext context, Bloc bloc) => bloc; + @override Widget build(BuildContext context) => SmartProvider.bloc( - context, - lazy: lazy, - enable: smart, - create: (_) => create(context), - child: super.build(context), - ); + context, + lazy: lazy, + enable: smart, + create: (_) => create(context), + init: (_, bloc) => init(context, bloc), + child: super.build(context), + ); } diff --git a/packages/wyatt_bloc_helper/lib/src/repository/repository_provider_screen.dart b/packages/wyatt_bloc_helper/lib/src/repository/repository_provider_screen.dart index e7a8c5ce..6e1b5554 100644 --- a/packages/wyatt_bloc_helper/lib/src/repository/repository_provider_screen.dart +++ b/packages/wyatt_bloc_helper/lib/src/repository/repository_provider_screen.dart @@ -27,7 +27,7 @@ import 'package:wyatt_bloc_helper/src/utils/smart_provider.dart'; /// It automatically handles closing the instance when used with [create]. /// By default, [create] is called only when the instance is accessed. /// To override this behavior, set [lazy] to `false`. -/// +/// /// By default, it provide already provided instance found in the tree. /// To override this behavior, set [smart] to `false`. /// {@endtemplate} @@ -46,13 +46,21 @@ abstract class RepositoryBaseProviderScreen final bool lazy; /// Whether this uses [SmartProvider]. - /// Defaults to `true`. But if you want to provide new [Repository] of a + /// Defaults to `true`. But if you want to provide new [Repository] of a /// same type in a sub-tree you may have to disable this. final bool smart; /// Creates the [Repository] to be used. Repository create(BuildContext context); + /// Initialize the [Repository]. + /// + /// This function is useful when using with [SmartProvider], because + /// if you want to pass an initial call on your repository you can + /// call it in `create` function but if you re-provide the repo below in the + /// tree this action will never be call again. + Repository init(BuildContext context, Repository repository) => repository; + /// Creates the child [Widget] to be used. Widget builder(BuildContext context); @@ -62,6 +70,7 @@ abstract class RepositoryBaseProviderScreen lazy: lazy, enable: smart, create: (_) => create(context), + init: (_, repository) => init(context, repository), child: Builder(builder: builder), ); } diff --git a/packages/wyatt_bloc_helper/lib/src/utils/smart_provider.dart b/packages/wyatt_bloc_helper/lib/src/utils/smart_provider.dart index 5fdb959a..046da441 100644 --- a/packages/wyatt_bloc_helper/lib/src/utils/smart_provider.dart +++ b/packages/wyatt_bloc_helper/lib/src/utils/smart_provider.dart @@ -22,6 +22,7 @@ abstract class SmartProvider { bloc, State extends Object>( BuildContext context, { required Bloc Function(BuildContext) create, + required Bloc Function(BuildContext, Bloc) init, Widget? child, bool lazy = true, bool enable = true, @@ -29,8 +30,9 @@ abstract class SmartProvider { if (enable) { final bloc = context.read(); if (bloc != null) { + final b = bloc; return BlocProvider.value( - value: bloc, + value: init(context, b), child: child, ); } @@ -38,7 +40,7 @@ abstract class SmartProvider { return BlocProvider( lazy: lazy, - create: (_) => create(context), + create: (_) => init(context, create(context)), child: child, ); } @@ -46,6 +48,7 @@ abstract class SmartProvider { static RepositoryProvider repo( BuildContext context, { required Repository Function(BuildContext) create, + required Repository Function(BuildContext, Repository) init, Widget? child, bool lazy = true, bool enable = true, @@ -53,8 +56,9 @@ abstract class SmartProvider { if (enable) { final repo = context.read(); if (repo != null) { + final r = repo; return RepositoryProvider.value( - value: repo, + value: init(context, r), child: child, ); } @@ -62,7 +66,7 @@ abstract class SmartProvider { return RepositoryProvider( lazy: lazy, - create: (_) => create(context), + create: (_) => init(context, create(context)), child: child, ); } diff --git a/packages/wyatt_bloc_helper/lib/src/widgets/multi_provider.dart b/packages/wyatt_bloc_helper/lib/src/widgets/multi_provider.dart new file mode 100644 index 00000000..f6503928 --- /dev/null +++ b/packages/wyatt_bloc_helper/lib/src/widgets/multi_provider.dart @@ -0,0 +1,98 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +/// {@template multi_provider} +/// Merges [MultiRepositoryProvider] and [MultiBlocProvider] widgets into +/// one widget tree. +/// +/// [MultiProvider] improves the readability and eliminates the need +/// to nest multiple providers. +/// +/// By using [MultiProvider] we can go from: +/// +/// ```dart +/// MultiRepositoryProvider( +/// providers: [ +/// RepositoryProvider(create: (context) => RepositoryA()), +/// RepositoryProvider(create: (context) => RepositoryB()), +/// RepositoryProvider(create: (context) => RepositoryC()), +/// ], +/// child: +/// MultiBlocProvider( +/// providers: [ +/// BlocProvider( +/// create: (BuildContext context) => BlocA(), +/// ), +/// BlocProvider( +/// create: (BuildContext context) => BlocB(), +/// ), +/// BlocProvider( +/// create: (BuildContext context) => BlocC(), +/// ), +/// ], +/// child: ChildA(), +/// ), +/// ) +/// ``` +/// +/// to: +/// +/// ```dart +/// MultiRepositoryProvider( +/// repositoryProviders: [ +/// RepositoryProvider(create: (context) => RepositoryA()), +/// RepositoryProvider(create: (context) => RepositoryB()), +/// RepositoryProvider(create: (context) => RepositoryC()), +/// ], +/// providers: [ +/// BlocProvider(create: (context) => BlocA()), +/// BlocProvider(create: (context) => BlocB()), +/// BlocProvider(create: (context) => BlocC()), +/// ], +/// child: ChildA(), +/// ) +/// ``` +/// +/// [MultiProvider] converts the [RepositoryProvider] and [BlocProvider] lists +/// into a tree of nested provider widgets. +/// As a result, the only advantage of using [MultiProvider] is +/// improved readability due to the reduction in nesting and boilerplate. +/// {@endtemplate} +class MultiProvider extends StatelessWidget { + /// {@macro multi_provider} + const MultiProvider({ + required this.repositoryProviders, + required this.blocProviders, + required this.child, + super.key, + }); + + final List> repositoryProviders; + final List blocProviders; + final Widget child; + + @override + Widget build(BuildContext context) => MultiRepositoryProvider( + providers: repositoryProviders, + child: MultiBlocProvider( + providers: blocProviders, + child: child, + ), + ); +} diff --git a/packages/wyatt_bloc_helper/lib/wyatt_bloc_helper.dart b/packages/wyatt_bloc_helper/lib/wyatt_bloc_helper.dart index cb9a6bcf..fc6a6c47 100644 --- a/packages/wyatt_bloc_helper/lib/wyatt_bloc_helper.dart +++ b/packages/wyatt_bloc_helper/lib/wyatt_bloc_helper.dart @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +/// Your best friend for BLoC in Flutter library wyatt_bloc_helper; export 'src/bloc.dart'; export 'src/cubit.dart'; export 'src/repo.dart'; +export 'src/widgets/multi_provider.dart';