From 0a14ff93ae9c60956572a356abf1d8d72a7fdee0 Mon Sep 17 00:00:00 2001 From: fujidaiti Date: Mon, 22 Apr 2024 20:53:22 +0900 Subject: [PATCH] Attach default controller to sheet if not explicitly specified --- package/lib/smooth_sheets.dart | 5 +-- .../lib/src/draggable/draggable_sheet.dart | 27 ++++++++------ package/lib/src/foundation/framework.dart | 8 +++-- .../lib/src/foundation/sheet_controller.dart | 35 +++++++++++++++++++ .../lib/src/navigation/navigation_sheet.dart | 15 +++++--- .../lib/src/scrollable/scrollable_sheet.dart | 21 ++++++----- 6 files changed, 82 insertions(+), 29 deletions(-) diff --git a/package/lib/smooth_sheets.dart b/package/lib/smooth_sheets.dart index db9b24c9..daeeb19c 100644 --- a/package/lib/smooth_sheets.dart +++ b/package/lib/smooth_sheets.dart @@ -1,6 +1,6 @@ /// Comprehensive bottom sheet library supporting imperative and declarative /// navigation APIs, nested navigation, persistent and modal styles (including -/// the iOS flavor), and more. +/// the iOS flavor), and more. library smooth_sheets; export 'src/draggable/draggable_sheet.dart'; @@ -12,7 +12,8 @@ export 'src/foundation/keyboard_dismissible.dart'; export 'src/foundation/notifications.dart'; export 'src/foundation/physics.dart'; export 'src/foundation/sheet_content_scaffold.dart'; -export 'src/foundation/sheet_controller.dart' hide SheetControllerScope; +export 'src/foundation/sheet_controller.dart' + hide ImplicitSheetControllerScope, SheetControllerScope; export 'src/foundation/sheet_extent.dart'; export 'src/foundation/theme.dart'; export 'src/modal/cupertino.dart'; diff --git a/package/lib/src/draggable/draggable_sheet.dart b/package/lib/src/draggable/draggable_sheet.dart index 8c96d330..574d71fa 100644 --- a/package/lib/src/draggable/draggable_sheet.dart +++ b/package/lib/src/draggable/draggable_sheet.dart @@ -71,18 +71,23 @@ class DraggableSheet extends StatelessWidget { final keyboardDismissBehavior = this.keyboardDismissBehavior ?? theme?.keyboardDismissBehavior; - Widget result = SheetContainer( + Widget result = ImplicitSheetControllerScope( controller: controller, - config: DraggableSheetExtentConfig( - initialExtent: initialExtent, - minExtent: minExtent, - maxExtent: maxExtent, - physics: physics, - ), - child: SheetDraggable( - behavior: hitTestBehavior, - child: child, - ), + builder: (context, controller) { + return SheetContainer( + controller: controller, + config: DraggableSheetExtentConfig( + initialExtent: initialExtent, + minExtent: minExtent, + maxExtent: maxExtent, + physics: physics, + ), + child: SheetDraggable( + behavior: hitTestBehavior, + child: child, + ), + ); + }, ); if (keyboardDismissBehavior != null) { diff --git a/package/lib/src/foundation/framework.dart b/package/lib/src/foundation/framework.dart index 5c6c96bb..2d06711c 100644 --- a/package/lib/src/foundation/framework.dart +++ b/package/lib/src/foundation/framework.dart @@ -1,18 +1,20 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; + import 'sheet_controller.dart'; import 'sheet_extent.dart'; class SheetContainer extends StatelessWidget { const SheetContainer({ super.key, - this.controller, this.onExtentChanged, + required this.controller, required this.config, required this.child, }); - final SheetController? controller; + final SheetController controller; final ValueChanged? onExtentChanged; final SheetExtentConfig config; final Widget child; @@ -21,7 +23,7 @@ class SheetContainer extends StatelessWidget { Widget build(BuildContext context) { return SheetExtentScope( config: config, - controller: controller ?? SheetControllerScope.maybeOf(context), + controller: controller, onExtentChanged: onExtentChanged, child: Builder( builder: (context) { diff --git a/package/lib/src/foundation/sheet_controller.dart b/package/lib/src/foundation/sheet_controller.dart index 5e911e1d..c108b7d4 100644 --- a/package/lib/src/foundation/sheet_controller.dart +++ b/package/lib/src/foundation/sheet_controller.dart @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; + import 'sheet_extent.dart'; class SheetController extends ChangeNotifier @@ -113,6 +114,40 @@ class SheetControllerScope extends InheritedWidget { } } +/// A widget that ensures that a [SheetController] is available in the subtree. +/// +/// The [builder] callback will be called with the [controller] if it is +/// explicitly provided and is not null, or a [SheetController] that is hosted +/// in the nearest ancestor [SheetControllerScope]. If neither is found, a newly +/// created [SheetController] hosted in a [DefaultSheetController] will be +/// used as a fallback. +@internal +class ImplicitSheetControllerScope extends StatelessWidget { + const ImplicitSheetControllerScope({ + super.key, + this.controller, + required this.builder, + }); + + final SheetController? controller; + final Widget Function(BuildContext, SheetController) builder; + + @override + Widget build(BuildContext context) { + return switch (controller ?? DefaultSheetController.maybeOf(context)) { + final controller? => builder(context, controller), + null => DefaultSheetController( + child: Builder( + builder: (context) { + final controller = DefaultSheetController.of(context); + return builder(context, controller); + }, + ), + ), + }; + } +} + class DefaultSheetController extends StatefulWidget { const DefaultSheetController({ super.key, diff --git a/package/lib/src/navigation/navigation_sheet.dart b/package/lib/src/navigation/navigation_sheet.dart index a2d6c2f9..7ab7a324 100644 --- a/package/lib/src/navigation/navigation_sheet.dart +++ b/package/lib/src/navigation/navigation_sheet.dart @@ -101,13 +101,18 @@ class NavigationSheetState extends State final keyboardDismissBehavior = widget.keyboardDismissBehavior ?? theme?.keyboardDismissBehavior; - Widget result = SheetContainer( - config: const _NavigationSheetExtentConfig(), + Widget result = ImplicitSheetControllerScope( controller: widget.controller, - onExtentChanged: (extent) { - _extent = extent as _NavigationSheetExtent?; + builder: (context, controller) { + return SheetContainer( + config: const _NavigationSheetExtentConfig(), + controller: widget.controller ?? DefaultSheetController.of(context), + onExtentChanged: (extent) { + _extent = extent as _NavigationSheetExtent?; + }, + child: widget.child, + ); }, - child: widget.child, ); if (keyboardDismissBehavior != null) { diff --git a/package/lib/src/scrollable/scrollable_sheet.dart b/package/lib/src/scrollable/scrollable_sheet.dart index eb8d0266..31f4a48f 100644 --- a/package/lib/src/scrollable/scrollable_sheet.dart +++ b/package/lib/src/scrollable/scrollable_sheet.dart @@ -49,15 +49,20 @@ class ScrollableSheet extends StatelessWidget { final keyboardDismissBehavior = this.keyboardDismissBehavior ?? theme?.keyboardDismissBehavior; - Widget result = SheetContainer( + Widget result = ImplicitSheetControllerScope( controller: controller, - config: ScrollableSheetExtentConfig( - initialExtent: initialExtent, - minExtent: minExtent, - maxExtent: maxExtent, - physics: physics, - ), - child: PrimarySheetContentScrollController(child: child), + builder: (context, controller) { + return SheetContainer( + controller: controller, + config: ScrollableSheetExtentConfig( + initialExtent: initialExtent, + minExtent: minExtent, + maxExtent: maxExtent, + physics: physics, + ), + child: PrimarySheetContentScrollController(child: child), + ); + }, ); if (keyboardDismissBehavior != null) {