From 2d1c40cd2ea1ed01103298be45cf51f91edc415c Mon Sep 17 00:00:00 2001 From: Cagatay Ulusoy Date: Sun, 11 Aug 2024 17:06:07 +0300 Subject: [PATCH 1/2] Expose page list and current page --- .../lib/demo_ui_components.dart | 1 + .../wolt_modal_sheet_close_or_next_sab.dart | 27 +++++++++++++++++++ lib/src/wolt_modal_sheet.dart | 18 ++++++++++--- .../lib/home/pages/root_sheet_page.dart | 19 ++++++------- .../pages/sheet_page_with_custom_top_bar.dart | 16 +++-------- .../sheet_page_with_forced_max_height.dart | 14 +++------- .../pages/sheet_page_with_hero_image.dart | 15 +++-------- .../sheet_page_with_in_app_navigation.dart | 2 +- .../home/pages/sheet_page_with_lazy_list.dart | 19 ++++--------- .../pages/sheet_page_with_min_height.dart | 15 +++-------- ...age_with_no_page_title_and_no_top_bar.dart | 14 +++------- .../pages/sheet_page_with_text_field.dart | 3 ++- .../sheet_page_with_update_page_method.dart | 12 +++------ 13 files changed, 80 insertions(+), 95 deletions(-) create mode 100644 demo_ui_components/lib/src/button/wolt_modal_sheet_close_or_next_sab.dart diff --git a/demo_ui_components/lib/demo_ui_components.dart b/demo_ui_components/lib/demo_ui_components.dart index c02e2fcc..b18834c9 100644 --- a/demo_ui_components/lib/demo_ui_components.dart +++ b/demo_ui_components/lib/demo_ui_components.dart @@ -1,5 +1,6 @@ export 'src/button/wolt_modal_sheet_back_button.dart'; export 'src/button/wolt_circular_elevated_button.dart'; +export 'src/button/wolt_modal_sheet_close_or_next_sab.dart'; export 'src/button/wolt_modal_sheet_close_button.dart'; export 'src/button/wolt_elevated_button.dart'; export 'src/colors/wolt_colors.dart'; diff --git a/demo_ui_components/lib/src/button/wolt_modal_sheet_close_or_next_sab.dart b/demo_ui_components/lib/src/button/wolt_modal_sheet_close_or_next_sab.dart new file mode 100644 index 00000000..e33c4b90 --- /dev/null +++ b/demo_ui_components/lib/src/button/wolt_modal_sheet_close_or_next_sab.dart @@ -0,0 +1,27 @@ +import 'package:demo_ui_components/demo_ui_components.dart'; +import 'package:flutter/material.dart'; +import 'package:wolt_modal_sheet/wolt_modal_sheet.dart'; + +class WoltModalSheetCloseOrNextSab extends StatelessWidget { + const WoltModalSheetCloseOrNextSab({ + this.colorName = WoltColorName.blue, + super.key, + }); + + final WoltColorName colorName; + + @override + Widget build(BuildContext context) { + final totalPageCount = WoltModalSheet.of(context).pages.length; + final currentPageIndex = WoltModalSheet.of(context).currentPageIndex; + final bool isAtLastPage = WoltModalSheet.of(context).isAtLastPage; + return WoltElevatedButton( + onPressed: isAtLastPage + ? Navigator.of(context).pop + : WoltModalSheet.of(context).showNext, + child: Text(isAtLastPage + ? "Close" + : "Next (${currentPageIndex + 1}/$totalPageCount)"), + ); + } +} diff --git a/lib/src/wolt_modal_sheet.dart b/lib/src/wolt_modal_sheet.dart index 064b6bd5..9aa2f550 100644 --- a/lib/src/wolt_modal_sheet.dart +++ b/lib/src/wolt_modal_sheet.dart @@ -272,6 +272,21 @@ class WoltModalSheet extends StatefulWidget { class WoltModalSheetState extends State { List _pages = []; + /// The list of pages in the modal sheet. + List get pages => _pages; + + /// The current page displayed in the modal sheet. + SliverWoltModalSheetPage get currentPage => _pages[_currentPageIndex]; + + /// The index of the currently displayed page in the in-modal navigation stack. + int get currentPageIndex => _currentPageIndex; + + /// Returns true if the current page is the first page in the stack. + bool get isAtFirstPage => _currentPageIndex == 0; + + /// Returns true if the current page is the last page in the stack. + bool get isAtLastPage => _currentPageIndex == _pages.length - 1; + final GlobalKey _childKey = GlobalKey(debugLabel: 'Modal sheet child'); static const barrierLayoutId = 'barrierLayoutId'; @@ -888,9 +903,6 @@ class WoltModalSheetState extends State { } return false; } - - /// The index of the currently displayed page in the in-modal navigation stack. - int get currentPageIndex => _currentPageIndex; } class _WoltModalMultiChildLayoutDelegate extends MultiChildLayoutDelegate { diff --git a/playground/lib/home/pages/root_sheet_page.dart b/playground/lib/home/pages/root_sheet_page.dart index 3bb5dec8..640c4840 100644 --- a/playground/lib/home/pages/root_sheet_page.dart +++ b/playground/lib/home/pages/root_sheet_page.dart @@ -21,17 +21,14 @@ class RootSheetPage { static List _constructAllPagesAfterRootPage( BuildContext context) => [ - SheetPageWithForcedMaxHeight.build( - Theme.of(context).brightness, - isLastPage: false, - ), - SheetPageWithHeroImage.build(isLastPage: false), - SheetPageWithLazyList.build(isLastPage: false), - SheetPageWithTextField.build(isLastPage: false), - SheetPageWithMinHeight.build(isLastPage: false), - SheetPageWithInAppNavigation.build(isLastPage: false), - SheetPageWithCustomTopBar.build(isLastPage: false), - SheetPageWithNoPageTitleNoTopBar.build(isLastPage: false), + SheetPageWithForcedMaxHeight.build(Theme.of(context).brightness), + SheetPageWithHeroImage.build(), + SheetPageWithLazyList.build(), + SheetPageWithTextField.build(), + SheetPageWithMinHeight.build(), + SheetPageWithInAppNavigation.build(), + SheetPageWithCustomTopBar.build(), + SheetPageWithNoPageTitleNoTopBar.build(), SheetPageWithUpdatePage.build(context, isLastPage: true), ]; diff --git a/playground/lib/home/pages/sheet_page_with_custom_top_bar.dart b/playground/lib/home/pages/sheet_page_with_custom_top_bar.dart index 9f7dc0bd..fc6e52bf 100644 --- a/playground/lib/home/pages/sheet_page_with_custom_top_bar.dart +++ b/playground/lib/home/pages/sheet_page_with_custom_top_bar.dart @@ -13,22 +13,14 @@ class SheetPageWithCustomTopBar { static const ModalPageName pageId = ModalPageName.customTopBar; /// Builds and returns a [WoltModalSheetPage] with custom top bar. - static WoltModalSheetPage build({bool isLastPage = true}) { + static WoltModalSheetPage build() { return WoltModalSheetPage( id: pageId, backgroundColor: WoltColors.blue8, forceMaxHeight: true, - stickyActionBar: Padding( - padding: const EdgeInsets.all(16.0), - child: Builder(builder: (context) { - return WoltElevatedButton( - onPressed: isLastPage - ? Navigator.of(context).pop - : WoltModalSheet.of(context).showNext, - colorName: WoltColorName.blue, - child: Text(isLastPage ? "Close" : "Next"), - ); - }), + stickyActionBar: const Padding( + padding: EdgeInsets.all(16.0), + child: WoltModalSheetCloseOrNextSab(), ), trailingNavBarWidget: const WoltModalSheetCloseButton(), isTopBarLayerAlwaysVisible: false, diff --git a/playground/lib/home/pages/sheet_page_with_forced_max_height.dart b/playground/lib/home/pages/sheet_page_with_forced_max_height.dart index 0f2f8e7a..b53fb191 100644 --- a/playground/lib/home/pages/sheet_page_with_forced_max_height.dart +++ b/playground/lib/home/pages/sheet_page_with_forced_max_height.dart @@ -19,17 +19,9 @@ class SheetPageWithForcedMaxHeight { : WoltColors.green64, hasSabGradient: false, forceMaxHeight: true, - stickyActionBar: Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: Builder(builder: (context) { - return WoltElevatedButton( - onPressed: isLastPage - ? Navigator.of(context).pop - : WoltModalSheet.of(context).showNext, - colorName: WoltColorName.green, - child: Text(isLastPage ? "Close" : "Next"), - ); - }), + stickyActionBar: const Padding( + padding: EdgeInsets.fromLTRB(16, 0, 16, 16), + child: WoltModalSheetCloseOrNextSab(colorName: WoltColorName.green), ), pageTitle: const ModalSheetTitle( 'Page with forced max height and background color'), diff --git a/playground/lib/home/pages/sheet_page_with_hero_image.dart b/playground/lib/home/pages/sheet_page_with_hero_image.dart index b6929b3b..2ec7f65a 100644 --- a/playground/lib/home/pages/sheet_page_with_hero_image.dart +++ b/playground/lib/home/pages/sheet_page_with_hero_image.dart @@ -8,23 +8,16 @@ class SheetPageWithHeroImage { static const ModalPageName pageId = ModalPageName.heroImage; - static WoltModalSheetPage build({bool isLastPage = true}) { + static WoltModalSheetPage build() { return WoltModalSheetPage( id: pageId, heroImage: const Image( image: AssetImage('lib/assets/images/hero_image.jpg'), fit: BoxFit.cover, ), - stickyActionBar: Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: Builder(builder: (context) { - return WoltElevatedButton( - onPressed: isLastPage - ? Navigator.of(context).pop - : WoltModalSheet.of(context).showNext, - child: Text(isLastPage ? "Close" : "Next"), - ); - }), + stickyActionBar: const Padding( + padding: EdgeInsets.fromLTRB(16, 0, 16, 16), + child: WoltModalSheetCloseOrNextSab(), ), pageTitle: const ModalSheetTitle('Page with a hero image'), leadingNavBarWidget: const WoltModalSheetBackButton(), diff --git a/playground/lib/home/pages/sheet_page_with_in_app_navigation.dart b/playground/lib/home/pages/sheet_page_with_in_app_navigation.dart index ff193990..790f32f1 100644 --- a/playground/lib/home/pages/sheet_page_with_in_app_navigation.dart +++ b/playground/lib/home/pages/sheet_page_with_in_app_navigation.dart @@ -9,7 +9,7 @@ class SheetPageWithInAppNavigation { static const ModalPageName pageId = ModalPageName.inAppNavigation; - static WoltModalSheetPage build({bool isLastPage = true}) { + static WoltModalSheetPage build() { return WoltModalSheetPage( id: pageId, leadingNavBarWidget: const WoltModalSheetBackButton(), diff --git a/playground/lib/home/pages/sheet_page_with_lazy_list.dart b/playground/lib/home/pages/sheet_page_with_lazy_list.dart index a2e186e1..61515529 100644 --- a/playground/lib/home/pages/sheet_page_with_lazy_list.dart +++ b/playground/lib/home/pages/sheet_page_with_lazy_list.dart @@ -8,25 +8,16 @@ class SheetPageWithLazyList { static const ModalPageName pageId = ModalPageName.lazyLoadingList; - static SliverWoltModalSheetPage build({bool isLastPage = true}) { + static SliverWoltModalSheetPage build() { final colors = allMaterialColors; const titleText = 'Material Colors'; const heroImageHeight = 200.0; return SliverWoltModalSheetPage( id: pageId, - stickyActionBar: isLastPage - ? null - : Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: Builder(builder: (context) { - return WoltElevatedButton( - onPressed: isLastPage - ? Navigator.of(context).pop - : WoltModalSheet.of(context).showNext, - child: const Text("Next"), - ); - }), - ), + stickyActionBar: const Padding( + padding: EdgeInsets.fromLTRB(16, 0, 16, 16), + child: WoltModalSheetCloseOrNextSab(), + ), topBarTitle: const ModalSheetTopBarTitle(titleText), heroImageHeight: heroImageHeight, heroImage: const Stack( diff --git a/playground/lib/home/pages/sheet_page_with_min_height.dart b/playground/lib/home/pages/sheet_page_with_min_height.dart index 6a7defca..1b31b495 100644 --- a/playground/lib/home/pages/sheet_page_with_min_height.dart +++ b/playground/lib/home/pages/sheet_page_with_min_height.dart @@ -8,20 +8,13 @@ class SheetPageWithMinHeight { static const ModalPageName pageId = ModalPageName.minHeight; - static WoltModalSheetPage build({bool isLastPage = true}) { + static WoltModalSheetPage build() { return WoltModalSheetPage( id: pageId, hasTopBarLayer: false, - stickyActionBar: Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: Builder(builder: (context) { - return WoltElevatedButton( - onPressed: isLastPage - ? Navigator.of(context).pop - : WoltModalSheet.of(context).showNext, - child: Text(isLastPage ? "Close" : "Next"), - ); - }), + stickyActionBar: const Padding( + padding: EdgeInsets.fromLTRB(16, 0, 16, 16), + child: WoltModalSheetCloseOrNextSab(), ), child: const Padding( padding: EdgeInsets.only(bottom: 100, top: 16, left: 16, right: 16), diff --git a/playground/lib/home/pages/sheet_page_with_no_page_title_and_no_top_bar.dart b/playground/lib/home/pages/sheet_page_with_no_page_title_and_no_top_bar.dart index dbd94cbb..e5b31372 100644 --- a/playground/lib/home/pages/sheet_page_with_no_page_title_and_no_top_bar.dart +++ b/playground/lib/home/pages/sheet_page_with_no_page_title_and_no_top_bar.dart @@ -15,17 +15,9 @@ class SheetPageWithNoPageTitleNoTopBar { id: pageId, backgroundColor: WoltColors.green8, forceMaxHeight: true, - stickyActionBar: Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: Builder(builder: (context) { - return WoltElevatedButton( - onPressed: isLastPage - ? Navigator.of(context).pop - : WoltModalSheet.of(context).showNext, - colorName: WoltColorName.green, - child: Text(isLastPage ? "Close" : "Next"), - ); - }), + stickyActionBar: const Padding( + padding: EdgeInsets.fromLTRB(16, 0, 16, 16), + child: WoltModalSheetCloseOrNextSab(colorName: WoltColorName.green), ), hasTopBarLayer: false, child: const Padding( diff --git a/playground/lib/home/pages/sheet_page_with_text_field.dart b/playground/lib/home/pages/sheet_page_with_text_field.dart index 8cde8820..15115ba1 100644 --- a/playground/lib/home/pages/sheet_page_with_text_field.dart +++ b/playground/lib/home/pages/sheet_page_with_text_field.dart @@ -8,7 +8,7 @@ class SheetPageWithTextField { static const ModalPageName pageId = ModalPageName.textField; - static WoltModalSheetPage build({bool isLastPage = true}) { + static WoltModalSheetPage build() { ValueNotifier isButtonEnabledNotifier = ValueNotifier(false); final textEditingController = TextEditingController(); textEditingController.addListener(() { @@ -19,6 +19,7 @@ class SheetPageWithTextField { stickyActionBar: ValueListenableBuilder( valueListenable: isButtonEnabledNotifier, builder: (context, isEnabled, __) { + final isLastPage = WoltModalSheet.of(context).isAtLastPage; return Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), child: WoltElevatedButton( diff --git a/playground/lib/home/pages/sheet_page_with_update_page_method.dart b/playground/lib/home/pages/sheet_page_with_update_page_method.dart index 0a25cd0f..a0149b99 100644 --- a/playground/lib/home/pages/sheet_page_with_update_page_method.dart +++ b/playground/lib/home/pages/sheet_page_with_update_page_method.dart @@ -20,15 +20,9 @@ class SheetPageWithUpdatePage { enableDrag: enableDrag, hasTopBarLayer: hasTopBarLayer, stickyActionBar: Builder(builder: (context) { - return Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: WoltElevatedButton( - onPressed: isLastPage - ? Navigator.of(context).pop - : WoltModalSheet.of(context).showNext, - colorName: WoltColorName.green, - child: Text(isLastPage ? "Close" : "Next"), - ), + return const Padding( + padding: EdgeInsets.fromLTRB(16, 0, 16, 16), + child: WoltModalSheetCloseOrNextSab(colorName: WoltColorName.green), ); }), isTopBarLayerAlwaysVisible: hasTopBarLayer, From 81a0ac30203256d0a4a252f7145a18cedef26263 Mon Sep 17 00:00:00 2001 From: Cagatay Ulusoy Date: Sun, 11 Aug 2024 17:22:56 +0300 Subject: [PATCH 2/2] Add widget tests --- test/wolt_modal_sheet_test.dart | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/wolt_modal_sheet_test.dart b/test/wolt_modal_sheet_test.dart index bd55a484..b580e2d2 100644 --- a/test/wolt_modal_sheet_test.dart +++ b/test/wolt_modal_sheet_test.dart @@ -277,5 +277,45 @@ void main() { equals(const Size(524.0, 86.0)), ); }); + + testWidgets('getters return the correct page, page index and list of pages', + (tester) async { + const page1Id = 'page1'; + const page2Id = 'page2'; + final page1 = + WoltModalSheetPage(child: const Text('Page 1'), id: page1Id); + final page2 = + WoltModalSheetPage(child: const Text('Page 2'), id: page2Id); + + await tester.pumpWidget(buildSheetWithShow( + pageListBuilder: (_) => [page1, page2], + )); + + await tester.tap(find.text('Open sheet')); + await tester.pumpAndSettle(); + + final WoltModalSheetState modal = + WoltModalSheet.of(tester.element(find.text('Page 1'))); + + expect(modal.pages.length, 2); + expect(modal.pages[0].id, page1Id); + expect(modal.pages[1].id, page2Id); + expect(modal.currentPage, page1); + expect(modal.currentPageIndex, 0); + expect(modal.isAtFirstPage, isTrue); + expect(modal.isAtLastPage, isFalse); + + // Go to next page + modal.showNext(); + await tester.pumpAndSettle(); + + expect(modal.pages.length, 2); + expect(modal.pages[0].id, page1Id); + expect(modal.pages[1].id, page2Id); + expect(modal.currentPage, page2); + expect(modal.currentPageIndex, 1); + expect(modal.isAtFirstPage, isFalse); + expect(modal.isAtLastPage, isTrue); + }); }); }