From a90007910c469b4369312085c1cc3e2ad9f2dac1 Mon Sep 17 00:00:00 2001 From: Lucio Baglione Date: Mon, 25 Mar 2024 11:05:03 +0100 Subject: [PATCH 1/6] feat: Add ResponsiveDynamicCgild widget. --- .../responsive_dynamic_child.dart | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_dynamic_child/responsive_dynamic_child.dart diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_dynamic_child/responsive_dynamic_child.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_dynamic_child/responsive_dynamic_child.dart new file mode 100644 index 00000000000..85e522d5bab --- /dev/null +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_dynamic_child/responsive_dynamic_child.dart @@ -0,0 +1,34 @@ +import 'package:catalyst_voices_shared/src/responsive_builder/responsive_breakpoint_key.dart'; +import 'package:catalyst_voices_shared/src/responsive_builder/responsive_builder.dart'; +import 'package:flutter/material.dart'; + +class ResponsiveDynamicChild extends StatelessWidget { + final Map _widgets; + + ResponsiveDynamicChild({ + super.key, + Widget? xs, + Widget? sm, + Widget? md, + Widget? lg, + required Widget other, + }) : _widgets = { + ResponsiveBreakpointKey.xs: xs, + ResponsiveBreakpointKey.sm: sm, + ResponsiveBreakpointKey.md: md, + ResponsiveBreakpointKey.lg: lg, + ResponsiveBreakpointKey.other: other, + }; + + @override + Widget build(BuildContext context) { + return ResponsiveBuilder( + builder: (context, child) => child!, + xs: _widgets[ResponsiveBreakpointKey.xs], + sm: _widgets[ResponsiveBreakpointKey.sm], + md: _widgets[ResponsiveBreakpointKey.md], + lg: _widgets[ResponsiveBreakpointKey.lg], + other: _widgets[ResponsiveBreakpointKey.other]!, + ); + } +} From e7616d281931f57b7491d3a579f64cc4b4c6fb08 Mon Sep 17 00:00:00 2001 From: Lucio Baglione Date: Mon, 25 Mar 2024 12:27:49 +0100 Subject: [PATCH 2/6] chore: Rename `ResponsiveChild` widget. --- .../responsive_child.dart} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename catalyst_voices/packages/catalyst_voices_shared/lib/src/{responsive_dynamic_child/responsive_dynamic_child.dart => responsive_child/responsive_child.dart} (92%) diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_dynamic_child/responsive_dynamic_child.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart similarity index 92% rename from catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_dynamic_child/responsive_dynamic_child.dart rename to catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart index 85e522d5bab..a936c81d1dd 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_dynamic_child/responsive_dynamic_child.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart @@ -2,10 +2,10 @@ import 'package:catalyst_voices_shared/src/responsive_builder/responsive_breakpo import 'package:catalyst_voices_shared/src/responsive_builder/responsive_builder.dart'; import 'package:flutter/material.dart'; -class ResponsiveDynamicChild extends StatelessWidget { +class ResponsiveChild extends StatelessWidget { final Map _widgets; - ResponsiveDynamicChild({ + ResponsiveChild({ super.key, Widget? xs, Widget? sm, From 0c8112d87d3ababffdfab270b7c98a89fd336652 Mon Sep 17 00:00:00 2001 From: Lucio Baglione Date: Mon, 25 Mar 2024 12:50:26 +0100 Subject: [PATCH 3/6] test: Add test cases for `ResponsiveChild`. --- .../test/src/responsive_child.dart | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child.dart diff --git a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child.dart b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child.dart new file mode 100644 index 00000000000..d1581078ae9 --- /dev/null +++ b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child.dart @@ -0,0 +1,90 @@ +import 'package:catalyst_voices_shared/src/responsive_child/responsive_child.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + Widget buildApp(Size size) => MediaQuery( + data: MediaQueryData(size: size), + child: MaterialApp( + home: Scaffold( + body: ResponsiveChild( + xs: const Text('Simple text for extra small screens.'), + sm: const Padding( + padding: EdgeInsets.all(50), + child: Text('Text with padding for small screens.'), + ), + md: const Column(children: [ + Text('This is'), + Text('a set'), + Text('of Texts'), + Text('for medium screens.'), + ],), + other: const Text('The fallback widget.'), + ), + ), + ), + ); + + group('Test screen sizes', () { + testWidgets( + 'ResponsiveChild outputs a text for extra-small screens', + (tester) async { + await tester.pumpWidget( + buildApp(const Size.fromWidth(280)), + ); + final testedElement = find.byType(Text); + expect(testedElement, findsOneWidget); + expect( + find.text('Simple text for extra small screens.'), + findsOneWidget, + ); + } + ); + testWidgets( + 'ResponsiveChild outputs a text with padding for small screens', + (tester) async { + await tester.pumpWidget( + buildApp(const Size.fromWidth(620)), + ); + final testedElement = find.byType(Text); + expect(testedElement, findsOneWidget); + expect( + find.text('Text with padding for small screens.'), + findsOneWidget, + ); + final paddingWidget = tester.widget( + find.ancestor( + of: testedElement, + matching: find.byType(Padding), + ), + ); + expect(paddingWidget.padding, const EdgeInsets.all(50)); + } + ); + testWidgets( + 'ResponsiveChild outputs four texts for medium screens', + (tester) async { + await tester.pumpWidget( + buildApp(const Size.fromWidth(1280)), + ); + final testedElements = find.byType(Text); + expect(testedElements, findsExactly(4)); + expect(find.text('This is'), findsOneWidget); + expect(find.text('a set'), findsOneWidget); + expect(find.text('of Texts'), findsOneWidget); + expect(find.text('for medium screens.'), findsOneWidget); + } + ); + testWidgets( + 'ResponsiveChild fallback to other for large screens', + (tester) async { + await tester.pumpWidget( + buildApp(const Size.fromWidth(1600)), + ); + final testedElements = find.byType(Text); + expect(testedElements, findsOneWidget); + expect(find.text('The fallback widget.'), findsOneWidget); + } + ); + }); +} From 6d06d552043beacb7d86a1e41183adc00bed8457 Mon Sep 17 00:00:00 2001 From: Lucio Baglione Date: Mon, 25 Mar 2024 12:58:42 +0100 Subject: [PATCH 4/6] docs: Add description for `ResponsiveChild`. --- .../responsive_child/responsive_child.dart | 30 +++++++++++++++++++ ..._child.dart => responsive_child_test.dart} | 14 +++++---- 2 files changed, 38 insertions(+), 6 deletions(-) rename catalyst_voices/packages/catalyst_voices_shared/test/src/{responsive_child.dart => responsive_child_test.dart} (92%) diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart index a936c81d1dd..def9313470f 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart @@ -2,6 +2,36 @@ import 'package:catalyst_voices_shared/src/responsive_builder/responsive_breakpo import 'package:catalyst_voices_shared/src/responsive_builder/responsive_builder.dart'; import 'package:flutter/material.dart'; +// A [ResponsiveChild] is a StatelessWidget that displays a Widget based on the +// current screen size. +// This is a simple wrapper around ResponsiveBuilder to simplify development and +// make it explicit for a reader. +// +// The possible arguments are [xs], [sm], [md], [lg], [other] following the +// the ResponsiveBuilder arguments. +// [other] is required and acts as fallback. +// +// Example usage: +// +// ```dart +// ResponsiveChild( +// xs: const Text('Simple text for extra small screens.'), +// sm: const Padding( +// padding: EdgeInsets.all(50), +// child: Text('Text with padding for small screens.'), +// ), +// md: const Column( +// children: [ +// Text('This is'), +// Text('a set'), +// Text('of Texts'), +// Text('for medium screens.'), +// ], +// ), +// other: const Text('The fallback widget.'), +// ); +// ``` + class ResponsiveChild extends StatelessWidget { final Map _widgets; diff --git a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child.dart b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart similarity index 92% rename from catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child.dart rename to catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart index d1581078ae9..3cf70cfe482 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart @@ -13,12 +13,14 @@ void main() { padding: EdgeInsets.all(50), child: Text('Text with padding for small screens.'), ), - md: const Column(children: [ - Text('This is'), - Text('a set'), - Text('of Texts'), - Text('for medium screens.'), - ],), + md: const Column( + children: [ + Text('This is'), + Text('a set'), + Text('of Texts'), + Text('for medium screens.'), + ], + ), other: const Text('The fallback widget.'), ), ), From a5983bf7a8c5bb97cc82ff054f1e450f50487c12 Mon Sep 17 00:00:00 2001 From: Lucio Baglione Date: Mon, 25 Mar 2024 17:21:12 +0100 Subject: [PATCH 5/6] refactor: `ResponsiveChild` manages `WidgetBuilder` instead of `Widget`. --- .../responsive_child/responsive_child.dart | 28 +++++++++---------- .../test/src/responsive_child_test.dart | 8 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart index def9313470f..8129310d0ac 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart @@ -2,8 +2,8 @@ import 'package:catalyst_voices_shared/src/responsive_builder/responsive_breakpo import 'package:catalyst_voices_shared/src/responsive_builder/responsive_builder.dart'; import 'package:flutter/material.dart'; -// A [ResponsiveChild] is a StatelessWidget that displays a Widget based on the -// current screen size. +// A [ResponsiveChild] is a StatelessWidget that selects a WidgetBuilder based +// on the current screen size and execute it. // This is a simple wrapper around ResponsiveBuilder to simplify development and // make it explicit for a reader. // @@ -15,12 +15,12 @@ import 'package:flutter/material.dart'; // // ```dart // ResponsiveChild( -// xs: const Text('Simple text for extra small screens.'), -// sm: const Padding( +// xs: (context) => const Text('Simple text for extra small screens.'), +// sm: (context) => const Padding( // padding: EdgeInsets.all(50), // child: Text('Text with padding for small screens.'), // ), -// md: const Column( +// md: (context) => const Column( // children: [ // Text('This is'), // Text('a set'), @@ -28,20 +28,20 @@ import 'package:flutter/material.dart'; // Text('for medium screens.'), // ], // ), -// other: const Text('The fallback widget.'), +// other: (context) => const Text('The fallback widget.'), // ); // ``` class ResponsiveChild extends StatelessWidget { - final Map _widgets; + final Map _widgets; ResponsiveChild({ super.key, - Widget? xs, - Widget? sm, - Widget? md, - Widget? lg, - required Widget other, + WidgetBuilder? xs, + WidgetBuilder? sm, + WidgetBuilder? md, + WidgetBuilder? lg, + required WidgetBuilder other, }) : _widgets = { ResponsiveBreakpointKey.xs: xs, ResponsiveBreakpointKey.sm: sm, @@ -52,8 +52,8 @@ class ResponsiveChild extends StatelessWidget { @override Widget build(BuildContext context) { - return ResponsiveBuilder( - builder: (context, child) => child!, + return ResponsiveBuilder( + builder: (context, childBuilder) => childBuilder!(context), xs: _widgets[ResponsiveBreakpointKey.xs], sm: _widgets[ResponsiveBreakpointKey.sm], md: _widgets[ResponsiveBreakpointKey.md], diff --git a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart index 3cf70cfe482..272c5ee6960 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart @@ -8,12 +8,12 @@ void main() { child: MaterialApp( home: Scaffold( body: ResponsiveChild( - xs: const Text('Simple text for extra small screens.'), - sm: const Padding( + xs: (context) => const Text('Simple text for extra small screens.'), + sm: (context) => const Padding( padding: EdgeInsets.all(50), child: Text('Text with padding for small screens.'), ), - md: const Column( + md: (context) => const Column( children: [ Text('This is'), Text('a set'), @@ -21,7 +21,7 @@ void main() { Text('for medium screens.'), ], ), - other: const Text('The fallback widget.'), + other: (context) => const Text('The fallback widget.'), ), ), ), From d3229e7255f429bfee2fdbdaefe07d46e655aeb5 Mon Sep 17 00:00:00 2001 From: Lucio Baglione Date: Tue, 26 Mar 2024 11:10:09 +0100 Subject: [PATCH 6/6] chore: Reorder folders. --- .../lib/src/catalyst_voices_shared.dart | 4 +++- .../responsive_breakpoint_key.dart | 0 .../responsive_builder.dart | 2 +- .../{responsive_child => responsive}/responsive_child.dart | 4 ++-- .../responsive_padding.dart | 4 ++-- .../test/src/platform_aware_builder_test.dart | 2 +- .../test/src/responsive_builder_test.dart | 2 +- .../test/src/responsive_child_test.dart | 2 +- 8 files changed, 11 insertions(+), 9 deletions(-) rename catalyst_voices/packages/catalyst_voices_shared/lib/src/{responsive_builder => responsive}/responsive_breakpoint_key.dart (100%) rename catalyst_voices/packages/catalyst_voices_shared/lib/src/{responsive_builder => responsive}/responsive_builder.dart (96%) rename catalyst_voices/packages/catalyst_voices_shared/lib/src/{responsive_child => responsive}/responsive_child.dart (91%) rename catalyst_voices/packages/catalyst_voices_shared/lib/src/{responsive_padding => responsive}/responsive_padding.dart (91%) diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/catalyst_voices_shared.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/catalyst_voices_shared.dart index 33e111668a8..de77e213859 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/catalyst_voices_shared.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/catalyst_voices_shared.dart @@ -1,3 +1,5 @@ export 'platform/catalyst_platform.dart'; export 'platform_aware_builder/platform_aware_builder.dart'; -export 'responsive_padding/responsive_padding.dart'; +export 'responsive/responsive_builder.dart'; +export 'responsive/responsive_child.dart'; +export 'responsive/responsive_padding.dart'; diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_builder/responsive_breakpoint_key.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_breakpoint_key.dart similarity index 100% rename from catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_builder/responsive_breakpoint_key.dart rename to catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_breakpoint_key.dart diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_builder/responsive_builder.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_builder.dart similarity index 96% rename from catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_builder/responsive_builder.dart rename to catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_builder.dart index 8aad594e3dc..15a7b45f11b 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_builder/responsive_builder.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_builder.dart @@ -1,4 +1,4 @@ -import 'package:catalyst_voices_shared/src/responsive_builder/responsive_breakpoint_key.dart'; +import 'package:catalyst_voices_shared/src/responsive/responsive_breakpoint_key.dart'; import 'package:flutter/widgets.dart'; // A [ResponsiveBuilder] is a StatelessWidget that is aware about the current diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_child.dart similarity index 91% rename from catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart rename to catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_child.dart index 8129310d0ac..c7330ce7ae2 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_child/responsive_child.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_child.dart @@ -1,5 +1,5 @@ -import 'package:catalyst_voices_shared/src/responsive_builder/responsive_breakpoint_key.dart'; -import 'package:catalyst_voices_shared/src/responsive_builder/responsive_builder.dart'; +import 'package:catalyst_voices_shared/src/responsive/responsive_breakpoint_key.dart'; +import 'package:catalyst_voices_shared/src/responsive/responsive_builder.dart'; import 'package:flutter/material.dart'; // A [ResponsiveChild] is a StatelessWidget that selects a WidgetBuilder based diff --git a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_padding/responsive_padding.dart b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_padding.dart similarity index 91% rename from catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_padding/responsive_padding.dart rename to catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_padding.dart index 5a26ee55cfb..2007d50299b 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive_padding/responsive_padding.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/lib/src/responsive/responsive_padding.dart @@ -1,5 +1,5 @@ -import 'package:catalyst_voices_shared/src/responsive_builder/responsive_breakpoint_key.dart'; -import 'package:catalyst_voices_shared/src/responsive_builder/responsive_builder.dart'; +import 'package:catalyst_voices_shared/src/responsive/responsive_breakpoint_key.dart'; +import 'package:catalyst_voices_shared/src/responsive/responsive_builder.dart'; import 'package:flutter/widgets.dart'; // A [ResponsivePadding] is a StatelessWidget that applies a padding based on diff --git a/catalyst_voices/packages/catalyst_voices_shared/test/src/platform_aware_builder_test.dart b/catalyst_voices/packages/catalyst_voices_shared/test/src/platform_aware_builder_test.dart index fac277aba99..0cec3272b27 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/test/src/platform_aware_builder_test.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/test/src/platform_aware_builder_test.dart @@ -1,4 +1,4 @@ -import 'package:catalyst_voices_shared/src/catalyst_voices_shared.dart'; +import 'package:catalyst_voices_shared/catalyst_voices_shared.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_builder_test.dart b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_builder_test.dart index 89ce59542c8..4cf620ce0fe 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_builder_test.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_builder_test.dart @@ -1,4 +1,4 @@ -import 'package:catalyst_voices_shared/src/responsive_builder/responsive_builder.dart'; +import 'package:catalyst_voices_shared/catalyst_voices_shared.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart index 272c5ee6960..eeb1cc5f5bf 100644 --- a/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart +++ b/catalyst_voices/packages/catalyst_voices_shared/test/src/responsive_child_test.dart @@ -1,4 +1,4 @@ -import 'package:catalyst_voices_shared/src/responsive_child/responsive_child.dart'; +import 'package:catalyst_voices_shared/catalyst_voices_shared.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart';