Base Flutter App

This commit is contained in:
2021-01-06 16:12:32 -05:00
parent 24c4adf910
commit f59a5c06ba
48 changed files with 1566 additions and 185 deletions

View File

@@ -0,0 +1,68 @@
import 'package:flutter/widgets.dart';
import 'package:imagini/bloc/bloc-prov.dart';
/// A Flutter [Widget] that merges multiple [BlocProvider] widgets into one widget tree.
///
/// [BlocProviderTree] improves the readability and eliminates the need
/// to nest multiple [BlocProviders].
///
/// By using [BlocProviderTree] we can go from:
///
/// ```dart
/// BlocProvider<BlocA>(
/// bloc: BlocA(),
/// child: BlocProvider<BlocB>(
/// bloc: BlocB(),
/// child: BlocProvider<BlocC>(
/// value: BlocC(),
/// child: ChildA(),
/// )
/// )
/// )
/// ```
///
/// to:
///
/// ```dart
/// BlocProviderTree(
/// blocProviders: [
/// BlocProvider<BlocA>(bloc: BlocA()),
/// BlocProvider<BlocB>(bloc: BlocB()),
/// BlocProvider<BlocC>(bloc: BlocC()),
/// ],
/// child: ChildA(),
/// )
/// ```
///
/// [BlocProviderTree] converts the [BlocProvider] list
/// into a tree of nested [BlocProvider] widgets.
/// As a result, the only advantage of using [BlocProviderTree] is improved
/// readability due to the reduction in nesting and boilerplate.
class BlocProviderTree extends StatelessWidget {
/// The [BlocProvider] list which is converted into a tree of [BlocProvider] widgets.
/// The tree of [BlocProvider] widgets is created in order meaning the first [BlocProvider]
/// will be the top-most [BlocProvider] and the last [BlocProvider] will be a direct ancestor
/// of the `child` [Widget].
final List<BlocProvider> blocProviders;
/// The [Widget] and its descendants which will have access to every [Bloc] provided by `blocProviders`.
/// This [Widget] will be a direct descendent of the last [BlocProvider] in `blocProviders`.
final Widget child;
const BlocProviderTree({
Key key,
@required this.blocProviders,
@required this.child,
}) : assert(blocProviders != null),
assert(child != null),
super(key: key);
@override
Widget build(BuildContext context) {
Widget tree = child;
for (final blocProvider in blocProviders.reversed) {
tree = blocProvider.copyWith(tree);
}
return tree;
}
}

View File

@@ -0,0 +1,60 @@
import 'package:flutter/widgets.dart';
import 'package:imagini/bloc/bloc.dart';
/// A Flutter widget which provides a bloc to its children via `BlocProvider.of(context)`.
/// It is used as a DI widget so that a single instance of a bloc can be provided
/// to multiple widgets within a subtree.
class BlocProvider<T extends Bloc> extends InheritedWidget {
/// The [Bloc] which is to be made available throughout the subtree
final T bloc;
/// The [Widget] and its descendants which will have access to the [Bloc].
final Widget child;
BlocProvider({
Key key,
@required this.bloc,
this.child,
}) : assert(bloc != null),
super(key: key, child: child);
/// Method that allows widgets to access the bloc as long as their `BuildContext`
/// contains a `BlocProvider` instance.
static T of<T extends Bloc>(BuildContext context) {
final type = _typeOf<BlocProvider<T>>();
final BlocProvider<T> provider = context
.ancestorInheritedElementForWidgetOfExactType(type)
?.widget as BlocProvider<T>;
if (provider == null) {
throw FlutterError(
"""
BlocProvider.of() called with a context that does not contain a Bloc of type $T.
No ancestor could be found starting from the context that was passed to BlocProvider.of<$T>().
This can happen if the context you use comes from a widget above the BlocProvider.
This can also happen if you used BlocProviderTree and didn\'t explicity provide
the BlocProvider types: BlocProvider(bloc: $T()) instead of BlocProvider<$T>(bloc: $T()).
The context used was: $context
""",
);
}
return provider?.bloc;
}
/// Clone the current [BlocProvider] with a new child [Widget].
/// All other values, including [Key] and [Bloc] are preserved.
BlocProvider<T> copyWith(Widget child) {
return BlocProvider<T>(
key: key,
bloc: bloc,
child: child,
);
}
/// Necessary to obtain generic [Type]
/// https://github.com/dart-lang/sdk/issues/11923
static Type _typeOf<T>() => T;
@override
bool updateShouldNotify(BlocProvider oldWidget) => false;
}

View File

@@ -0,0 +1 @@
abstract class Bloc {}