Skip to content

Commit

Permalink
Merge pull request #55 from icapps/feature/ProviderValue
Browse files Browse the repository at this point in the history
Feature/provider value
  • Loading branch information
NicolaVerbeeck committed Sep 29, 2021
2 parents 10f72e2 + 2833de5 commit 6e67cb2
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 29 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Changelog
## [0.4.3] - 2021-09-29
### Added
- Add .value constructor for BaseProviderWidget

## [0.4.2] - 2021-09-02
### Fixed
- Expose the SimpleKeyValueStorage interface
Expand Down
79 changes: 52 additions & 27 deletions lib/src/widget/provider/provider_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:provider/provider.dart';

class BaseProviderWidget<T extends ChangeNotifier, Theme, Localization>
extends StatelessWidget {
final T? value;
final T Function() create;
final Widget? child;
final Widget Function(
Expand All @@ -27,39 +28,63 @@ class BaseProviderWidget<T extends ChangeNotifier, Theme, Localization>
this.consumerChild,
this.childBuilderWithViewModel,
this.lazy = true,
});
}) : this.value = null;

const BaseProviderWidget.value({
required this.value,
this.child,
this.childBuilder,
this.consumer,
this.consumerWithThemeAndLocalization,
this.consumerChild,
this.childBuilderWithViewModel,
}) : this.lazy = false,
this.create = _notImplemented;

@override
Widget build(BuildContext context) {
final consumerCreator = Builder(
builder: (context) {
if (consumerWithThemeAndLocalization != null || consumer != null) {
return Consumer<T>(
child: consumerChild ?? Container(),
builder: consumer ??
(context, t, widget) => consumerWithThemeAndLocalization!(
context,
t,
widget,
themeLookup(context),
localizationLookup(context)),
);
} else if (child != null) {
return child!;
} else if (childBuilder != null) {
return childBuilder!(
context, themeLookup(context), localizationLookup(context));
} else if (childBuilderWithViewModel != null) {
return childBuilderWithViewModel!(context, Provider.of<T>(context),
themeLookup(context), localizationLookup(context));
}
throw ArgumentError(
'child, childBuilder, childBuilderWithViewModel, consumer or consumerWithThemeAndLocalization should be passed');
},
);

if (value != null) {
return ChangeNotifierProvider.value(
value: value,
child: consumerCreator,
);
}

return ChangeNotifierProvider<T>(
lazy: lazy,
child: LayoutBuilder(
builder: (context, constraints) {
if (consumerWithThemeAndLocalization != null || consumer != null) {
return Consumer<T>(
child: consumerChild ?? Container(),
builder: consumer ??
(context, t, widget) => consumerWithThemeAndLocalization!(
context,
t,
widget,
themeLookup(context),
localizationLookup(context)),
);
} else if (child != null) {
return child!;
} else if (childBuilder != null) {
return childBuilder!(
context, themeLookup(context), localizationLookup(context));
} else if (childBuilderWithViewModel != null) {
return childBuilderWithViewModel!(context, Provider.of<T>(context),
themeLookup(context), localizationLookup(context));
}
throw ArgumentError(
'child, childBuilder, childBuilderWithViewModel, consumer or consumerWithThemeAndLocalization should be passed');
},
),
child: consumerCreator,
create: (context) => create(),
);
}

static T _notImplemented<T>() {
throw UnimplementedError();
}
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: icapps architecture components for flutter projects. Contains commo
homepage: https://github.com/icapps/flutter-icapps-architecture
repository: https://github.com/icapps/flutter-icapps-architecture

version: 0.4.2
version: 0.4.3

environment:
sdk: '>=2.12.0 <3.0.0'
Expand Down
5 changes: 4 additions & 1 deletion test/provider/change_notifier_ex_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ void main() {
verify(subscription.cancel()).called(1);
});
test('Double dispose throws', () {
expect(() => TestableChangeNotifier()..dispose()..dispose(),
expect(
() => TestableChangeNotifier()
..dispose()
..dispose(),
throwsA(isInstanceOf<FlutterError>()));
});
});
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions test/widget/provider/provider_widget_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,29 @@ class ProviderWidget<T extends ChangeNotifier>
consumerWithThemeAndLocalization: consumerWithThemeAndLocalization,
lazy: lazy,
);

ProviderWidget.value({
required T value,
Widget? child,
Widget Function(BuildContext context, Theme theme, Locale localization)?
childBuilder,
Widget Function(BuildContext context, T viewModel, Theme theme,
Locale localization)?
childBuilderWithViewModel,
Widget? consumerChild,
Widget Function(BuildContext context, T viewModel, Widget? child)? consumer,
Widget Function(BuildContext context, T viewModel, Widget? child,
Theme theme, Locale localization)?
consumerWithThemeAndLocalization,
}) : super.value(
value: value,
child: child,
childBuilder: childBuilder,
childBuilderWithViewModel: childBuilderWithViewModel,
consumerChild: consumerChild,
consumer: consumer,
consumerWithThemeAndLocalization: consumerWithThemeAndLocalization,
);
}

LocaleT getLocale<LocaleT>(BuildContext _) => Locale() as LocaleT;
Expand Down Expand Up @@ -81,6 +104,29 @@ void main() {
await TestUtil.takeScreenshot(tester, 'provider_widget_child_builder');
});

testWidgets('ProviderWidget.value should show childbuilder with viewmodel',
(tester) async {
final sut = ProviderWidget<TestViewModel>.value(
childBuilderWithViewModel: (context, item, _, __) =>
const Material(child: Text('Test')),
value: TestViewModel(),
);

await TestUtil.loadWidgetWithText(tester, sut);
await TestUtil.takeScreenshot(
tester, 'provider_widget_value_child_builder');
});

testWidgets('ProviderWidget.value create should throw', (tester) async {
final sut = ProviderWidget<TestViewModel>.value(
childBuilderWithViewModel: (context, item, _, __) =>
const Material(child: Text('Test')),
value: TestViewModel(),
);

expect(() => sut.create(), throwsA(isInstanceOf<UnimplementedError>()));
});

testWidgets('ProviderWidget should show childbuilder with consumer',
(tester) async {
final sut = ProviderWidget<TestViewModel>(
Expand Down

0 comments on commit 6e67cb2

Please sign in to comment.