From 57dde8b3f7016ef3fcb8cbaace6532ed16aa8492 Mon Sep 17 00:00:00 2001 From: Daichi Fujita <68946713+fujidaiti@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:33:56 +0900 Subject: [PATCH] Refactor (#95) To prepare for #89. --- package/analysis_options.yaml | 1 + package/lib/smooth_sheets.dart | 6 +- .../lib/src/draggable/draggable_sheet.dart | 142 +++++--- .../lib/src/draggable/sheet_draggable.dart | 9 +- .../{sheet_activity.dart => activities.dart} | 5 +- .../{animation.dart => animations.dart} | 4 +- package/lib/src/foundation/framework.dart | 10 +- .../src/foundation/keyboard_dismissible.dart | 4 +- package/lib/src/foundation/notifications.dart | 5 +- .../{sheet_physics.dart => physics.dart} | 5 +- .../foundation/sheet_content_scaffold.dart | 5 +- .../lib/src/foundation/sheet_controller.dart | 2 +- package/lib/src/foundation/sheet_extent.dart | 70 ++-- .../src/foundation/sized_content_sheet.dart | 150 -------- package/lib/src/foundation/theme.dart | 2 +- package/lib/src/modal/cupertino.dart | 6 +- package/lib/src/modal/modal_sheet.dart | 8 +- .../lib/src/navigation/navigation_route.dart | 15 +- .../lib/src/navigation/navigation_routes.dart | 322 +++++++++--------- .../lib/src/navigation/navigation_sheet.dart | 34 +- .../lib/src/scrollable/scrollable_sheet.dart | 88 +++-- .../scrollable/scrollable_sheet_extent.dart | 64 ++-- .../scrollable/scrollable_sheet_physics.dart | 4 +- 23 files changed, 487 insertions(+), 474 deletions(-) rename package/lib/src/foundation/{sheet_activity.dart => activities.dart} (98%) rename package/lib/src/foundation/{animation.dart => animations.dart} (91%) rename package/lib/src/foundation/{sheet_physics.dart => physics.dart} (99%) delete mode 100644 package/lib/src/foundation/sized_content_sheet.dart diff --git a/package/analysis_options.yaml b/package/analysis_options.yaml index 6a3866d3..1674b9f0 100644 --- a/package/analysis_options.yaml +++ b/package/analysis_options.yaml @@ -11,3 +11,4 @@ linter: flutter_style_todos: false cascade_invocations: false join_return_with_assignment: false + prefer_relative_imports: true diff --git a/package/lib/smooth_sheets.dart b/package/lib/smooth_sheets.dart index 76846e4f..db9b24c9 100644 --- a/package/lib/smooth_sheets.dart +++ b/package/lib/smooth_sheets.dart @@ -5,15 +5,15 @@ library smooth_sheets; export 'src/draggable/draggable_sheet.dart'; export 'src/draggable/sheet_draggable.dart'; -export 'src/foundation/animation.dart'; +export 'src/foundation/activities.dart'; +export 'src/foundation/animations.dart'; export 'src/foundation/framework.dart'; export 'src/foundation/keyboard_dismissible.dart'; export 'src/foundation/notifications.dart'; -export 'src/foundation/sheet_activity.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_extent.dart'; -export 'src/foundation/sheet_physics.dart'; export 'src/foundation/theme.dart'; export 'src/modal/cupertino.dart'; export 'src/modal/modal_sheet.dart'; diff --git a/package/lib/src/draggable/draggable_sheet.dart b/package/lib/src/draggable/draggable_sheet.dart index f6d2f6a0..68874834 100644 --- a/package/lib/src/draggable/draggable_sheet.dart +++ b/package/lib/src/draggable/draggable_sheet.dart @@ -1,12 +1,20 @@ import 'package:flutter/widgets.dart'; -import 'package:smooth_sheets/smooth_sheets.dart'; -import 'package:smooth_sheets/src/foundation/sized_content_sheet.dart'; + +import '../foundation/activities.dart'; +import '../foundation/framework.dart'; +import '../foundation/keyboard_dismissible.dart'; +import '../foundation/physics.dart'; +import '../foundation/sheet_controller.dart'; +import '../foundation/sheet_extent.dart'; +import '../foundation/theme.dart'; +import '../scrollable/scrollable_sheet.dart'; +import 'sheet_draggable.dart'; /// A sheet that can be dragged. /// /// Note that this widget does not work with scrollable widgets. /// Instead, use [ScrollableSheet] for this usecase. -class DraggableSheet extends SizedContentSheet { +class DraggableSheet extends StatelessWidget { /// Creates a sheet that can be dragged. /// /// The maximum height will be equal to the [child]'s height. @@ -22,79 +30,133 @@ class DraggableSheet extends SizedContentSheet { const DraggableSheet({ super.key, this.hitTestBehavior = HitTestBehavior.translucent, - super.keyboardDismissBehavior, - super.initialExtent, - super.minExtent, - super.maxExtent, - super.physics, - super.controller, - required super.child, + this.keyboardDismissBehavior, + this.initialExtent = const Extent.proportional(1), + this.minExtent = const Extent.proportional(1), + this.maxExtent = const Extent.proportional(1), + this.physics = const StretchingSheetPhysics( + parent: SnappingSheetPhysics(), + ), + required this.child, + this.controller, }); + /// The strategy to dismiss the on-screen keyboard when the sheet is dragged. + final SheetKeyboardDismissBehavior? keyboardDismissBehavior; + + /// {@macro SizedContentSheetExtent.initialExtent} + final Extent initialExtent; + + /// {@macro SheetExtent.minExtent} + final Extent minExtent; + + /// {@macro SheetExtent.maxExtent} + final Extent maxExtent; + + /// {@macro SheetExtent.physics} + final SheetPhysics physics; + + /// An object that can be used to control and observe the sheet height. + final SheetController? controller; + + /// The content of the sheet. + final Widget child; + /// How to behave during hit testing. /// /// This value will be passed to the constructor of internal [SheetDraggable]. final HitTestBehavior hitTestBehavior; @override - SizedContentSheetState createState() { - return _DraggableSheetState(); - } -} + Widget build(BuildContext context) { + final theme = SheetTheme.maybeOf(context); + final keyboardDismissBehavior = + this.keyboardDismissBehavior ?? theme?.keyboardDismissBehavior; -class _DraggableSheetState extends SizedContentSheetState { - @override - SheetExtentFactory createExtentFactory() { - return DraggableSheetExtentFactory( - initialExtent: widget.initialExtent, - minExtent: widget.minExtent, - maxExtent: widget.maxExtent, - physics: widget.physics, + Widget result = SheetContainer( + controller: controller, + config: DraggableSheetExtentConfig( + initialExtent: initialExtent, + minExtent: minExtent, + maxExtent: maxExtent, + physics: physics, + ), + child: SheetDraggable( + behavior: hitTestBehavior, + child: child, + ), ); - } - @override - Widget buildContent(BuildContext context) { - return SheetDraggable( - behavior: widget.hitTestBehavior, - child: super.buildContent(context), - ); + if (keyboardDismissBehavior != null) { + result = SheetKeyboardDismissible( + dismissBehavior: keyboardDismissBehavior, + child: result, + ); + } + + return result; } } -/// Factory of [DraggableSheetExtent]. -class DraggableSheetExtentFactory extends SizedContentSheetExtentFactory { - const DraggableSheetExtentFactory({ - required super.initialExtent, - required super.minExtent, - required super.maxExtent, - required super.physics, +/// A configuration of a [DraggableSheetExtent]. +class DraggableSheetExtentConfig extends SheetExtentConfig { + const DraggableSheetExtentConfig({ + required this.initialExtent, + required this.minExtent, + required this.maxExtent, + required this.physics, }); + /// {@macro DraggableSheetExtent.initialExtent} + final Extent initialExtent; + + /// {@macro SheetExtent.minExtent} + final Extent minExtent; + + /// {@macro SheetExtent.maxExtent} + final Extent maxExtent; + + /// {@macro SheetExtent.physics} + final SheetPhysics physics; + + @override + bool shouldRebuild(BuildContext context, SheetExtent oldExtent) { + return oldExtent is! DraggableSheetExtent || + oldExtent.minExtent != minExtent || + oldExtent.maxExtent != maxExtent || + oldExtent.initialExtent != initialExtent || + oldExtent.physics != physics; + } + @override - SheetExtent create({required SheetContext context}) { + SheetExtent build(BuildContext context, SheetContext sheetContext) { return DraggableSheetExtent( + context: sheetContext, initialExtent: initialExtent, minExtent: minExtent, maxExtent: maxExtent, physics: physics, - context: context, ); } } /// [SheetExtent] for a [DraggableSheet]. -class DraggableSheetExtent extends SizedContentSheetExtent { +class DraggableSheetExtent extends SheetExtent { DraggableSheetExtent({ required super.context, required super.physics, required super.minExtent, required super.maxExtent, - required super.initialExtent, + required this.initialExtent, }) { goIdle(); } + /// {@template DraggableSheetExtent.initialExtent} + /// The initial extent of the sheet when it is first shown. + /// {@endtemplate} + final Extent initialExtent; + @override void goIdle() { beginActivity(_IdleDraggableSheetActivity( diff --git a/package/lib/src/draggable/sheet_draggable.dart b/package/lib/src/draggable/sheet_draggable.dart index 0c361122..efd6177f 100644 --- a/package/lib/src/draggable/sheet_draggable.dart +++ b/package/lib/src/draggable/sheet_draggable.dart @@ -1,10 +1,11 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/widgets.dart'; -import 'package:smooth_sheets/src/draggable/draggable_sheet.dart'; -import 'package:smooth_sheets/src/foundation/sheet_activity.dart'; -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; -import 'package:smooth_sheets/src/scrollable/scrollable_sheet.dart'; + +import '../foundation/activities.dart'; +import '../foundation/sheet_extent.dart'; +import '../scrollable/scrollable_sheet.dart'; +import 'draggable_sheet.dart'; /// A widget that makes its child as a drag-handle for a sheet. /// diff --git a/package/lib/src/foundation/sheet_activity.dart b/package/lib/src/foundation/activities.dart similarity index 98% rename from package/lib/src/foundation/sheet_activity.dart rename to package/lib/src/foundation/activities.dart index f085b6da..bfe809b8 100644 --- a/package/lib/src/foundation/sheet_activity.dart +++ b/package/lib/src/foundation/activities.dart @@ -4,8 +4,9 @@ import 'dart:math'; import 'package:flutter/gestures.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; -import 'package:smooth_sheets/smooth_sheets.dart'; -import 'package:smooth_sheets/src/foundation/sheet_status.dart'; +import 'notifications.dart'; +import 'sheet_extent.dart'; +import 'sheet_status.dart'; abstract class SheetActivity extends ChangeNotifier { bool _mounted = false; diff --git a/package/lib/src/foundation/animation.dart b/package/lib/src/foundation/animations.dart similarity index 91% rename from package/lib/src/foundation/animation.dart rename to package/lib/src/foundation/animations.dart index 313e573a..f3ce3dc7 100644 --- a/package/lib/src/foundation/animation.dart +++ b/package/lib/src/foundation/animations.dart @@ -1,6 +1,6 @@ import 'package:flutter/animation.dart'; -import 'package:smooth_sheets/src/foundation/sheet_controller.dart'; -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; +import 'sheet_controller.dart'; +import 'sheet_extent.dart'; class ExtentDrivenAnimation extends Animation { ExtentDrivenAnimation({ diff --git a/package/lib/src/foundation/framework.dart b/package/lib/src/foundation/framework.dart index 926a523b..5c6c96bb 100644 --- a/package/lib/src/foundation/framework.dart +++ b/package/lib/src/foundation/framework.dart @@ -1,26 +1,26 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -import 'package:smooth_sheets/src/foundation/sheet_controller.dart'; -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; +import 'sheet_controller.dart'; +import 'sheet_extent.dart'; class SheetContainer extends StatelessWidget { const SheetContainer({ super.key, this.controller, this.onExtentChanged, - required this.factory, + required this.config, required this.child, }); final SheetController? controller; final ValueChanged? onExtentChanged; - final SheetExtentFactory factory; + final SheetExtentConfig config; final Widget child; @override Widget build(BuildContext context) { return SheetExtentScope( - factory: factory, + config: config, controller: controller ?? SheetControllerScope.maybeOf(context), onExtentChanged: onExtentChanged, child: Builder( diff --git a/package/lib/src/foundation/keyboard_dismissible.dart b/package/lib/src/foundation/keyboard_dismissible.dart index 7fa656bd..c96e21b1 100644 --- a/package/lib/src/foundation/keyboard_dismissible.dart +++ b/package/lib/src/foundation/keyboard_dismissible.dart @@ -1,6 +1,6 @@ import 'package:flutter/widgets.dart'; -import 'package:smooth_sheets/src/draggable/draggable_sheet.dart'; -import 'package:smooth_sheets/src/foundation/notifications.dart'; +import '../draggable/draggable_sheet.dart'; +import 'notifications.dart'; /// A widget that dismisses the on-screen keyboard when the user /// drags the sheet below this widget. diff --git a/package/lib/src/foundation/notifications.dart b/package/lib/src/foundation/notifications.dart index 9219f044..14c1d24f 100644 --- a/package/lib/src/foundation/notifications.dart +++ b/package/lib/src/foundation/notifications.dart @@ -1,6 +1,7 @@ import 'package:flutter/widgets.dart'; -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; -import 'package:smooth_sheets/src/foundation/sheet_physics.dart'; + +import 'physics.dart'; +import 'sheet_extent.dart'; /// A [Notification] that is dispatched when the sheet extent changes. /// diff --git a/package/lib/src/foundation/sheet_physics.dart b/package/lib/src/foundation/physics.dart similarity index 99% rename from package/lib/src/foundation/sheet_physics.dart rename to package/lib/src/foundation/physics.dart index e3d20728..b6c1aaff 100644 --- a/package/lib/src/foundation/sheet_physics.dart +++ b/package/lib/src/foundation/physics.dart @@ -4,8 +4,9 @@ import 'dart:ui'; import 'package:collection/collection.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/widgets.dart'; -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; -import 'package:smooth_sheets/src/internal/double_utils.dart'; + +import '../internal/double_utils.dart'; +import 'sheet_extent.dart'; const _minSettlingDuration = Duration(milliseconds: 160); const _defaultSettlingSpeed = 600.0; // logical pixels per second diff --git a/package/lib/src/foundation/sheet_content_scaffold.dart b/package/lib/src/foundation/sheet_content_scaffold.dart index 754a2804..9f2e7587 100644 --- a/package/lib/src/foundation/sheet_content_scaffold.dart +++ b/package/lib/src/foundation/sheet_content_scaffold.dart @@ -2,7 +2,10 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -import 'package:smooth_sheets/smooth_sheets.dart'; + +import '../draggable/sheet_draggable.dart'; +import 'framework.dart'; +import 'sheet_extent.dart'; class SheetContentScaffold extends StatelessWidget { const SheetContentScaffold({ diff --git a/package/lib/src/foundation/sheet_controller.dart b/package/lib/src/foundation/sheet_controller.dart index d43cf9ec..5e911e1d 100644 --- a/package/lib/src/foundation/sheet_controller.dart +++ b/package/lib/src/foundation/sheet_controller.dart @@ -2,7 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; +import 'sheet_extent.dart'; class SheetController extends ChangeNotifier implements ValueListenable { diff --git a/package/lib/src/foundation/sheet_extent.dart b/package/lib/src/foundation/sheet_extent.dart index 273c7faf..274d501c 100644 --- a/package/lib/src/foundation/sheet_extent.dart +++ b/package/lib/src/foundation/sheet_extent.dart @@ -1,7 +1,13 @@ import 'package:flutter/widgets.dart'; -import 'package:smooth_sheets/smooth_sheets.dart'; -import 'package:smooth_sheets/src/foundation/sheet_status.dart'; -import 'package:smooth_sheets/src/internal/double_utils.dart'; + +import '../draggable/draggable_sheet.dart'; +import '../internal/double_utils.dart'; +import '../scrollable/scrollable_sheet.dart'; +import '../scrollable/scrollable_sheet_extent.dart'; +import 'activities.dart'; +import 'physics.dart'; +import 'sheet_controller.dart'; +import 'sheet_status.dart'; /// A representation of a visible height of the sheet. /// @@ -630,10 +636,11 @@ abstract class SheetContext { BuildContext? get notificationContext; } -/// A factory that creates a [SheetExtent]. -abstract class SheetExtentFactory { - const SheetExtentFactory(); - SheetExtent create({required SheetContext context}); +/// Configuration of a [SheetExtent]. +abstract class SheetExtentConfig { + const SheetExtentConfig(); + SheetExtent build(BuildContext context, SheetContext sheetContext); + bool shouldRebuild(BuildContext context, SheetExtent oldExtent); } /// A widget that creates a [SheetExtent], manages its lifecycle, @@ -642,7 +649,7 @@ class SheetExtentScope extends StatefulWidget { /// Creates a widget that hosts a [SheetExtent]. const SheetExtentScope({ super.key, - required this.factory, + required this.config, this.controller, this.onExtentChanged, required this.child, @@ -651,11 +658,11 @@ class SheetExtentScope extends StatefulWidget { /// The [SheetController] that will be attached to the created [SheetExtent]. final SheetController? controller; - /// The factory that creates the [SheetExtent]. + /// The configuration of the [SheetExtent] manged by this widget. /// /// The [SheetExtentScope] will recreate the [SheetExtent] whenever - /// it is rebuilt with a [factory] that is not identical to the previous one. - final SheetExtentFactory factory; + /// it is rebuilt with a [config] that is not identical to the previous one. + final SheetExtentConfig config; /// Called whenever the [SheetExtent] changes. /// @@ -675,7 +682,7 @@ class SheetExtentScope extends StatefulWidget { /// that encloses the given context, if any. /// /// Use of this method will cause the given context to rebuild any time - /// that the [factory] property of the ancestor [SheetExtentScope] changes. + /// that the [config] property of the ancestor [SheetExtentScope] changes. // TODO: Add 'useRoot' option static SheetExtent? maybeOf(BuildContext context) { return context @@ -687,7 +694,7 @@ class SheetExtentScope extends StatefulWidget { /// that encloses the given context. /// /// Use of this method will cause the given context to rebuild any time - /// that the [factory] property of the ancestor [SheetExtentScope] changes. + /// that the [config] property of the ancestor [SheetExtentScope] changes. static SheetExtent of(BuildContext context) { return maybeOf(context)!; } @@ -696,7 +703,7 @@ class SheetExtentScope extends StatefulWidget { class _SheetExtentScopeState extends State with TickerProviderStateMixin implements SheetContext { - late SheetExtent _extent; + SheetExtent? _extent; @override TickerProvider get vsync => this; @@ -704,35 +711,41 @@ class _SheetExtentScopeState extends State @override BuildContext? get notificationContext => mounted ? context : null; - @override - void initState() { - super.initState(); - _extent = widget.factory.create(context: this); - widget.controller?.attach(_extent); - widget.onExtentChanged?.call(_extent); - } - @override void dispose() { + assert(_extent != null); widget.onExtentChanged?.call(null); widget.controller?.detach(_extent); - _extent.dispose(); + _extent!.dispose(); super.dispose(); } + @override + void didChangeDependencies() { + super.didChangeDependencies(); + final oldExtent = _extent; + if (oldExtent == null || widget.config.shouldRebuild(context, oldExtent)) { + final newExtent = widget.config.build(context, this); + widget.controller?.attach(newExtent); + widget.onExtentChanged?.call(newExtent); + _extent = newExtent; + } + } + @override void didUpdateWidget(SheetExtentScope oldWidget) { super.didUpdateWidget(oldWidget); + assert(_extent != null); + final oldExtent = _extent!; - final oldExtent = _extent; - if (widget.factory != oldWidget.factory) { - _extent = widget.factory.create(context: this)..takeOver(_extent); + if (widget.config.shouldRebuild(context, oldExtent)) { + _extent = widget.config.build(context, this)..takeOver(oldExtent); widget.onExtentChanged?.call(_extent); } if (widget.controller != oldWidget.controller || _extent != oldExtent) { oldWidget.controller?.detach(oldExtent); - widget.controller?.attach(_extent); + widget.controller?.attach(_extent!); } if (oldExtent != _extent) { @@ -742,8 +755,9 @@ class _SheetExtentScopeState extends State @override Widget build(BuildContext context) { + assert(_extent != null); return _InheritedSheetExtent( - extent: _extent, + extent: _extent!, child: widget.child, ); } diff --git a/package/lib/src/foundation/sized_content_sheet.dart b/package/lib/src/foundation/sized_content_sheet.dart deleted file mode 100644 index a9a931b3..00000000 --- a/package/lib/src/foundation/sized_content_sheet.dart +++ /dev/null @@ -1,150 +0,0 @@ -import 'package:flutter/widgets.dart'; -import 'package:smooth_sheets/src/foundation/framework.dart'; -import 'package:smooth_sheets/src/foundation/keyboard_dismissible.dart'; -import 'package:smooth_sheets/src/foundation/sheet_controller.dart'; -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; -import 'package:smooth_sheets/src/foundation/sheet_physics.dart'; -import 'package:smooth_sheets/src/foundation/theme.dart'; - -/// [SheetExtent] for a [SizedContentSheet]. -abstract class SizedContentSheetExtent extends SheetExtent { - /// Creates a [SheetExtent] for [SizedContentSheet]s. - SizedContentSheetExtent({ - required super.context, - required super.physics, - required super.minExtent, - required super.maxExtent, - required this.initialExtent, - }); - - /// {@template SizedContentSheetExtent.initialExtent} - /// The initial extent of the sheet when it is first shown. - /// {@endtemplate} - final Extent initialExtent; -} - -/// Factory of [SizedContentSheetExtent]. -abstract class SizedContentSheetExtentFactory extends SheetExtentFactory { - /// Creates a factory of [SizedContentSheetExtent]. - const SizedContentSheetExtentFactory({ - required this.initialExtent, - required this.minExtent, - required this.maxExtent, - required this.physics, - }); - - /// {@macro SizedContentSheetExtent.initialExtent} - final Extent initialExtent; - - /// {@macro SheetExtent.minExtent} - final Extent minExtent; - - /// {@macro SheetExtent.maxExtent} - final Extent maxExtent; - - /// {@macro SheetExtent.physics} - final SheetPhysics physics; -} - -/// A base class for sheets that have an explicit initial extent. -abstract class SizedContentSheet extends StatefulWidget { - /// Creates a sheet with an explicit initial extent. - const SizedContentSheet({ - super.key, - this.keyboardDismissBehavior, - this.initialExtent = const Extent.proportional(1), - this.minExtent = const Extent.proportional(1), - this.maxExtent = const Extent.proportional(1), - this.physics = const StretchingSheetPhysics( - parent: SnappingSheetPhysics(), - ), - this.controller, - required this.child, - }); - - /// The strategy to dismiss the on-screen keyboard when the sheet is dragged. - final SheetKeyboardDismissBehavior? keyboardDismissBehavior; - - /// {@macro SizedContentSheetExtent.initialExtent} - final Extent initialExtent; - - /// {@macro SheetExtent.minExtent} - final Extent minExtent; - - /// {@macro SheetExtent.maxExtent} - final Extent maxExtent; - - /// {@macro SheetExtent.physics} - final SheetPhysics physics; - - /// An object that can be used to control and observe the sheet height. - final SheetController? controller; - - /// The content of the sheet. - final Widget child; - - @override - SizedContentSheetState createState(); -} - -/// State for a [SizedContentSheet]. -abstract class SizedContentSheetState - extends State { - /// The factory of [SheetExtent] which drives this sheet. - /// - /// This is first created in [initState] and updated in [didUpdateWidget] - /// when the [SizedContentSheet] properties change. - SheetExtentFactory get factory => _factory; - late SheetExtentFactory _factory; - - /// Creates the factory of [SheetExtent] for this sheet. - SheetExtentFactory createExtentFactory(); - - @override - void initState() { - super.initState(); - _factory = createExtentFactory(); - } - - @override - void didUpdateWidget(T oldWidget) { - super.didUpdateWidget(oldWidget); - if (widget.initialExtent != oldWidget.initialExtent || - widget.minExtent != oldWidget.minExtent || - widget.maxExtent != oldWidget.maxExtent || - widget.physics != oldWidget.physics) { - _factory = createExtentFactory(); - } - } - - @override - Widget build(BuildContext context) { - final theme = SheetTheme.maybeOf(context); - final keyboardDismissBehavior = - widget.keyboardDismissBehavior ?? theme?.keyboardDismissBehavior; - - Widget result = SheetContainer( - factory: factory, - controller: widget.controller, - child: buildContent(context), - ); - - if (keyboardDismissBehavior != null) { - result = SheetKeyboardDismissible( - dismissBehavior: keyboardDismissBehavior, - child: result, - ); - } - - return result; - } - - /// Builds the content of the sheet. - /// - /// Consider overriding this method if you want to - /// insert widgets above the [SizedContentSheet.child]. - @protected - Widget buildContent(BuildContext context) { - return widget.child; - } -} diff --git a/package/lib/src/foundation/theme.dart b/package/lib/src/foundation/theme.dart index 42546d53..d54d3e9f 100644 --- a/package/lib/src/foundation/theme.dart +++ b/package/lib/src/foundation/theme.dart @@ -1,5 +1,5 @@ import 'package:flutter/widgets.dart'; -import 'package:smooth_sheets/src/foundation/keyboard_dismissible.dart'; +import 'keyboard_dismissible.dart'; /// A theme for descendant sheets. /// diff --git a/package/lib/src/modal/cupertino.dart b/package/lib/src/modal/cupertino.dart index 3a4e8a94..2df35c82 100644 --- a/package/lib/src/modal/cupertino.dart +++ b/package/lib/src/modal/cupertino.dart @@ -3,9 +3,9 @@ import 'dart:math'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -import 'package:smooth_sheets/smooth_sheets.dart'; -import 'package:smooth_sheets/src/internal/double_utils.dart'; -import 'package:smooth_sheets/src/modal/modal_sheet.dart'; + +import '../internal/double_utils.dart'; +import 'modal_sheet.dart'; const _minimizedViewportScale = 0.92; const _cupertinoBarrierColor = Color(0x18000000); diff --git a/package/lib/src/modal/modal_sheet.dart b/package/lib/src/modal/modal_sheet.dart index aa1d1ae4..aaed81f5 100644 --- a/package/lib/src/modal/modal_sheet.dart +++ b/package/lib/src/modal/modal_sheet.dart @@ -3,10 +3,10 @@ import 'dart:math'; import 'dart:ui'; import 'package:flutter/material.dart'; -import 'package:smooth_sheets/src/foundation/sheet_controller.dart'; -import 'package:smooth_sheets/src/foundation/sheet_status.dart'; -import 'package:smooth_sheets/src/internal/double_utils.dart'; -import 'package:smooth_sheets/src/internal/monodrag.dart'; +import '../foundation/sheet_controller.dart'; +import '../foundation/sheet_status.dart'; +import '../internal/double_utils.dart'; +import '../internal/monodrag.dart'; const _minFlingVelocityToDismiss = 1.0; const _minDragDistanceToDismiss = 100.0; // Logical pixels. diff --git a/package/lib/src/navigation/navigation_route.dart b/package/lib/src/navigation/navigation_route.dart index 44daf37a..64f964d7 100644 --- a/package/lib/src/navigation/navigation_route.dart +++ b/package/lib/src/navigation/navigation_route.dart @@ -1,12 +1,13 @@ import 'package:flutter/material.dart'; -import 'package:smooth_sheets/src/foundation/framework.dart'; -import 'package:smooth_sheets/src/foundation/sheet_activity.dart'; -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; -import 'package:smooth_sheets/src/foundation/sheet_status.dart'; -import 'package:smooth_sheets/src/navigation/navigation_sheet.dart'; + +import '../foundation/activities.dart'; +import '../foundation/framework.dart'; +import '../foundation/sheet_extent.dart'; +import '../foundation/sheet_status.dart'; +import 'navigation_sheet.dart'; mixin NavigationSheetRouteMixin on NavigationSheetRoute { - SheetExtentFactory get pageExtentFactory; + SheetExtentConfig get pageExtentConfig; @override NavigationSheetExtentDelegate get pageExtent => _pageExtent; @@ -39,7 +40,7 @@ mixin NavigationSheetRouteMixin on NavigationSheetRoute { Animation secondaryAnimation, ) { return SheetExtentScope( - factory: pageExtentFactory, + config: pageExtentConfig, onExtentChanged: (extent) => _pageExtent.source = extent, child: SheetContentViewport( child: buildContent(context), diff --git a/package/lib/src/navigation/navigation_routes.dart b/package/lib/src/navigation/navigation_routes.dart index 0d5d55f4..b5ec3671 100644 --- a/package/lib/src/navigation/navigation_routes.dart +++ b/package/lib/src/navigation/navigation_routes.dart @@ -1,17 +1,16 @@ import 'package:flutter/material.dart'; -import 'package:smooth_sheets/src/draggable/draggable_sheet.dart'; -import 'package:smooth_sheets/src/draggable/sheet_draggable.dart'; -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; -import 'package:smooth_sheets/src/foundation/sheet_physics.dart'; -import 'package:smooth_sheets/src/foundation/sized_content_sheet.dart'; -import 'package:smooth_sheets/src/navigation/navigation_route.dart'; -import 'package:smooth_sheets/src/navigation/navigation_sheet.dart'; -import 'package:smooth_sheets/src/scrollable/scrollable_sheet.dart'; -import 'package:smooth_sheets/src/scrollable/scrollable_sheet_extent.dart'; - -abstract class SingleChildNavigationSheetRoute - extends NavigationSheetRoute with NavigationSheetRouteMixin { - SingleChildNavigationSheetRoute({ +import '../draggable/draggable_sheet.dart'; +import '../draggable/sheet_draggable.dart'; +import '../foundation/physics.dart'; +import '../foundation/sheet_extent.dart'; +import '../scrollable/scrollable_sheet.dart'; +import '../scrollable/scrollable_sheet_extent.dart'; +import 'navigation_route.dart'; +import 'navigation_sheet.dart'; + +class ScrollableNavigationSheetRoute extends NavigationSheetRoute + with NavigationSheetRouteMixin { + ScrollableNavigationSheetRoute({ super.settings, this.maintainState = true, this.transitionDuration = const Duration(milliseconds: 300), @@ -21,7 +20,68 @@ abstract class SingleChildNavigationSheetRoute this.physics = const StretchingSheetPhysics(parent: SnappingSheetPhysics()), this.transitionsBuilder, required this.builder, - }); + }) : pageExtentConfig = ScrollableSheetExtentConfig( + initialExtent: initialExtent, + minExtent: minExtent, + maxExtent: maxExtent, + physics: physics, + ); + + @override + final ScrollableSheetExtentConfig pageExtentConfig; + + final Extent initialExtent; + final Extent minExtent; + final Extent maxExtent; + final SheetPhysics physics; + + @override + final bool maintainState; + + @override + final Duration transitionDuration; + + final RouteTransitionsBuilder? transitionsBuilder; + + final WidgetBuilder builder; + + @override + Widget buildContent(BuildContext context) { + return PrimarySheetContentScrollController( + child: builder(context), + ); + } + + @override + Widget buildTransitions( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child, + ) { + final builder = transitionsBuilder ?? super.buildTransitions; + return builder(context, animation, secondaryAnimation, child); + } +} + +class DraggableNavigationSheetRoute extends NavigationSheetRoute + with NavigationSheetRouteMixin { + DraggableNavigationSheetRoute({ + super.settings, + this.maintainState = true, + this.transitionDuration = const Duration(milliseconds: 300), + this.initialExtent = const Extent.proportional(1), + this.minExtent = const Extent.proportional(1), + this.maxExtent = const Extent.proportional(1), + this.physics = const StretchingSheetPhysics(parent: SnappingSheetPhysics()), + this.transitionsBuilder, + required this.builder, + }) : pageExtentConfig = DraggableSheetExtentConfig( + initialExtent: initialExtent, + minExtent: minExtent, + maxExtent: maxExtent, + physics: physics, + ); final Extent initialExtent; final Extent minExtent; @@ -39,7 +99,14 @@ abstract class SingleChildNavigationSheetRoute final WidgetBuilder builder; @override - SizedContentSheetExtentFactory get pageExtentFactory; + final DraggableSheetExtentConfig pageExtentConfig; + + @override + Widget buildContent(BuildContext context) { + return SheetDraggable( + child: builder(context), + ); + } @override Widget buildTransitions( @@ -53,8 +120,8 @@ abstract class SingleChildNavigationSheetRoute } } -abstract class SingleChildNavigationSheetPage extends Page { - const SingleChildNavigationSheetPage({ +class ScrollableNavigationSheetPage extends Page { + const ScrollableNavigationSheetPage({ super.key, super.name, super.arguments, @@ -84,16 +151,21 @@ abstract class SingleChildNavigationSheetPage extends Page { /// The content to be shown in the [Route] created by this page. final Widget child; + + @override + Route createRoute(BuildContext context) { + return _PageBasedScrollableNavigationSheetRoute(page: this); + } } -abstract class PageBasedSingleChildNavigationSheetRoute> +class _PageBasedScrollableNavigationSheetRoute extends NavigationSheetRoute with NavigationSheetRouteMixin { - PageBasedSingleChildNavigationSheetRoute({ - required P page, + _PageBasedScrollableNavigationSheetRoute({ + required ScrollableNavigationSheetPage page, }) : super(settings: page); - P get page => settings as P; + ScrollableNavigationSheetPage get page => + settings as ScrollableNavigationSheetPage; @override bool get maintainState => page.maintainState; @@ -102,26 +174,25 @@ abstract class PageBasedSingleChildNavigationSheetRoute page.transitionDuration; @override - SizedContentSheetExtentFactory get pageExtentFactory => _pageExtentFactory!; - SizedContentSheetExtentFactory? _pageExtentFactory; + ScrollableSheetExtentConfig get pageExtentConfig => _pageExtentConfig!; + ScrollableSheetExtentConfig? _pageExtentConfig; @override void changedInternalState() { super.changedInternalState(); - if (shouldUpdatePageExtentFactory()) { - _pageExtentFactory = createPageExtentFactory(); + if (page.initialExtent != _pageExtentConfig?.initialExtent || + page.minExtent != _pageExtentConfig?.minExtent || + page.maxExtent != _pageExtentConfig?.maxExtent || + page.physics != _pageExtentConfig?.physics) { + _pageExtentConfig = ScrollableSheetExtentConfig( + initialExtent: page.initialExtent, + minExtent: page.minExtent, + maxExtent: page.maxExtent, + physics: page.physics, + ); } } - SizedContentSheetExtentFactory createPageExtentFactory(); - - bool shouldUpdatePageExtentFactory() { - return page.initialExtent != _pageExtentFactory?.initialExtent || - page.minExtent != _pageExtentFactory?.minExtent || - page.maxExtent != _pageExtentFactory?.maxExtent || - page.physics != _pageExtentFactory?.physics; - } - @override Widget buildTransitions( BuildContext context, @@ -132,156 +203,101 @@ abstract class PageBasedSingleChildNavigationSheetRoute - extends SingleChildNavigationSheetRoute { - ScrollableNavigationSheetRoute({ - required super.builder, - super.settings, - super.maintainState, - super.transitionDuration, - super.initialExtent, - super.minExtent, - super.maxExtent, - super.physics, - super.transitionsBuilder, - }) : pageExtentFactory = ScrollableSheetExtentFactory( - initialExtent: initialExtent, - minExtent: minExtent, - maxExtent: maxExtent, - physics: physics, - ); - - @override - final ScrollableSheetExtentFactory pageExtentFactory; @override Widget buildContent(BuildContext context) { return PrimarySheetContentScrollController( - child: builder(context), - ); - } -} - -class DraggableNavigationSheetRoute - extends SingleChildNavigationSheetRoute { - DraggableNavigationSheetRoute({ - required super.builder, - super.settings, - super.maintainState, - super.transitionDuration, - super.initialExtent, - super.minExtent, - super.maxExtent, - super.physics, - super.transitionsBuilder, - }) : pageExtentFactory = DraggableSheetExtentFactory( - initialExtent: initialExtent, - minExtent: minExtent, - maxExtent: maxExtent, - physics: physics, - ); - - @override - final DraggableSheetExtentFactory pageExtentFactory; - - @override - Widget buildContent(BuildContext context) { - return SheetDraggable( - child: builder(context), + child: page.child, ); } } -class ScrollableNavigationSheetPage - extends SingleChildNavigationSheetPage { - const ScrollableNavigationSheetPage({ +class DraggableNavigationSheetPage extends Page { + const DraggableNavigationSheetPage({ super.key, super.name, super.arguments, super.restorationId, - super.maintainState, - super.transitionDuration, - super.initialExtent, - super.minExtent, - super.maxExtent, - super.physics, - super.transitionsBuilder, - required super.child, + this.maintainState = true, + this.transitionDuration = const Duration(milliseconds: 300), + this.initialExtent = const Extent.proportional(1), + this.minExtent = const Extent.proportional(1), + this.maxExtent = const Extent.proportional(1), + this.physics = const StretchingSheetPhysics(parent: SnappingSheetPhysics()), + this.transitionsBuilder, + required this.child, }); + /// {@macro flutter.widgets.ModalRoute.maintainState} + final bool maintainState; + + final Duration transitionDuration; + + final Extent initialExtent; + final Extent minExtent; + final Extent maxExtent; + + final SheetPhysics physics; + + final RouteTransitionsBuilder? transitionsBuilder; + + /// The content to be shown in the [Route] created by this page. + final Widget child; + @override Route createRoute(BuildContext context) { - return _PageBasedScrollableNavigationSheetRoute(page: this); + return _PageBasedDraggableNavigationSheetRoute(page: this); } } -class _PageBasedScrollableNavigationSheetRoute - extends PageBasedSingleChildNavigationSheetRoute> { - _PageBasedScrollableNavigationSheetRoute({required super.page}); +class _PageBasedDraggableNavigationSheetRoute extends NavigationSheetRoute + with NavigationSheetRouteMixin { + _PageBasedDraggableNavigationSheetRoute({ + required DraggableNavigationSheetPage page, + }) : super(settings: page); + + DraggableNavigationSheetPage get page => + settings as DraggableNavigationSheetPage; @override - SizedContentSheetExtentFactory createPageExtentFactory() { - return ScrollableSheetExtentFactory( - initialExtent: page.initialExtent, - minExtent: page.minExtent, - maxExtent: page.maxExtent, - physics: page.physics, - ); - } + bool get maintainState => page.maintainState; @override - Widget buildContent(BuildContext context) { - return PrimarySheetContentScrollController( - child: page.child, - ); - } -} + Duration get transitionDuration => page.transitionDuration; -class DraggableNavigationSheetPage - extends SingleChildNavigationSheetPage { - const DraggableNavigationSheetPage({ - super.key, - super.name, - super.arguments, - super.restorationId, - super.maintainState, - super.transitionDuration, - super.initialExtent, - super.minExtent, - super.maxExtent, - super.physics, - super.transitionsBuilder, - required super.child, - }); + @override + DraggableSheetExtentConfig get pageExtentConfig => _pageExtentConfig!; + DraggableSheetExtentConfig? _pageExtentConfig; @override - Route createRoute(BuildContext context) { - return _PageBasedDraggableNavigationSheetRoute(page: this); + void changedInternalState() { + super.changedInternalState(); + if (page.initialExtent != _pageExtentConfig?.initialExtent || + page.minExtent != _pageExtentConfig?.minExtent || + page.maxExtent != _pageExtentConfig?.maxExtent || + page.physics != _pageExtentConfig?.physics) { + _pageExtentConfig = DraggableSheetExtentConfig( + initialExtent: page.initialExtent, + minExtent: page.minExtent, + maxExtent: page.maxExtent, + physics: page.physics, + ); + } } -} - -class _PageBasedDraggableNavigationSheetRoute - extends PageBasedSingleChildNavigationSheetRoute> { - _PageBasedDraggableNavigationSheetRoute({required super.page}); @override - SizedContentSheetExtentFactory createPageExtentFactory() { - return DraggableSheetExtentFactory( - initialExtent: page.initialExtent, - minExtent: page.minExtent, - maxExtent: page.maxExtent, - physics: page.physics, - ); + Widget buildTransitions( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child, + ) { + final builder = page.transitionsBuilder ?? super.buildTransitions; + return builder(context, animation, secondaryAnimation, child); } @override Widget buildContent(BuildContext context) { - return SheetDraggable( - child: page.child, - ); + return SheetDraggable(child: page.child); } } diff --git a/package/lib/src/navigation/navigation_sheet.dart b/package/lib/src/navigation/navigation_sheet.dart index c69f1a26..a2d6c2f9 100644 --- a/package/lib/src/navigation/navigation_sheet.dart +++ b/package/lib/src/navigation/navigation_sheet.dart @@ -2,15 +2,16 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; -import 'package:smooth_sheets/src/foundation/framework.dart'; -import 'package:smooth_sheets/src/foundation/keyboard_dismissible.dart'; -import 'package:smooth_sheets/src/foundation/sheet_activity.dart'; -import 'package:smooth_sheets/src/foundation/sheet_controller.dart'; -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; -import 'package:smooth_sheets/src/foundation/sheet_physics.dart'; -import 'package:smooth_sheets/src/foundation/sheet_status.dart'; -import 'package:smooth_sheets/src/foundation/theme.dart'; -import 'package:smooth_sheets/src/internal/transition_observer.dart'; + +import '../foundation/activities.dart'; +import '../foundation/framework.dart'; +import '../foundation/keyboard_dismissible.dart'; +import '../foundation/physics.dart'; +import '../foundation/sheet_controller.dart'; +import '../foundation/sheet_extent.dart'; +import '../foundation/sheet_status.dart'; +import '../foundation/theme.dart'; +import '../internal/transition_observer.dart'; typedef NavigationSheetTransitionObserver = TransitionObserver; @@ -101,7 +102,7 @@ class NavigationSheetState extends State widget.keyboardDismissBehavior ?? theme?.keyboardDismissBehavior; Widget result = SheetContainer( - factory: const _NavigationSheetExtentFactory(), + config: const _NavigationSheetExtentConfig(), controller: widget.controller, onExtentChanged: (extent) { _extent = extent as _NavigationSheetExtent?; @@ -139,13 +140,18 @@ abstract class NavigationSheetExtentDelegate implements Listenable { void beginActivity(SheetActivity activity); } -class _NavigationSheetExtentFactory extends SheetExtentFactory { - const _NavigationSheetExtentFactory(); +class _NavigationSheetExtentConfig extends SheetExtentConfig { + const _NavigationSheetExtentConfig(); + + @override + bool shouldRebuild(BuildContext context, SheetExtent oldExtent) { + return oldExtent is! _NavigationSheetExtent; + } @override - SheetExtent create({required SheetContext context}) { + SheetExtent build(BuildContext context, SheetContext sheetContext) { return _NavigationSheetExtent( - context: context, + context: sheetContext, // TODO: Use more appropriate physics. physics: const ClampingSheetPhysics(), ); diff --git a/package/lib/src/scrollable/scrollable_sheet.dart b/package/lib/src/scrollable/scrollable_sheet.dart index 683b8df6..5ed0262e 100644 --- a/package/lib/src/scrollable/scrollable_sheet.dart +++ b/package/lib/src/scrollable/scrollable_sheet.dart @@ -1,44 +1,74 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; -import 'package:smooth_sheets/smooth_sheets.dart'; -import 'package:smooth_sheets/src/foundation/sized_content_sheet.dart'; -import 'package:smooth_sheets/src/scrollable/scrollable_sheet_extent.dart'; +import '../foundation/framework.dart'; +import '../foundation/keyboard_dismissible.dart'; +import '../foundation/physics.dart'; +import '../foundation/sheet_controller.dart'; +import '../foundation/sheet_extent.dart'; +import '../foundation/theme.dart'; +import 'scrollable_sheet_extent.dart'; -class ScrollableSheet extends SizedContentSheet { +class ScrollableSheet extends StatelessWidget { const ScrollableSheet({ super.key, - super.keyboardDismissBehavior, - super.initialExtent, - super.minExtent, - super.maxExtent, - super.physics, - super.controller, - required super.child, + this.keyboardDismissBehavior, + this.initialExtent = const Extent.proportional(1), + this.minExtent = const Extent.proportional(1), + this.maxExtent = const Extent.proportional(1), + this.physics = const StretchingSheetPhysics( + parent: SnappingSheetPhysics(), + ), + this.controller, + required this.child, }); - @override - SizedContentSheetState createState() { - return _ScrollableSheetState(); - } -} + /// The strategy to dismiss the on-screen keyboard when the sheet is dragged. + final SheetKeyboardDismissBehavior? keyboardDismissBehavior; -class _ScrollableSheetState extends SizedContentSheetState { - @override - SheetExtentFactory createExtentFactory() { - return ScrollableSheetExtentFactory( - initialExtent: widget.initialExtent, - minExtent: widget.minExtent, - maxExtent: widget.maxExtent, - physics: widget.physics, - ); - } + /// {@macro ScrollableSheetExtent.initialExtent} + final Extent initialExtent; + + /// {@macro SheetExtent.minExtent} + final Extent minExtent; + + /// {@macro SheetExtent.maxExtent} + final Extent maxExtent; + + /// {@macro SheetExtent.physics} + final SheetPhysics physics; + + /// An object that can be used to control and observe the sheet height. + final SheetController? controller; + + /// The content of the sheet. + final Widget child; @override - Widget buildContent(BuildContext context) { - return PrimarySheetContentScrollController( - child: super.buildContent(context), + Widget build(BuildContext context) { + final theme = SheetTheme.maybeOf(context); + final keyboardDismissBehavior = + this.keyboardDismissBehavior ?? theme?.keyboardDismissBehavior; + + Widget result = SheetContainer( + controller: controller, + config: ScrollableSheetExtentConfig( + initialExtent: initialExtent, + minExtent: minExtent, + maxExtent: maxExtent, + physics: physics, + ), + child: PrimarySheetContentScrollController(child: child), ); + + if (keyboardDismissBehavior != null) { + result = SheetKeyboardDismissible( + dismissBehavior: keyboardDismissBehavior, + child: result, + ); + } + + return result; } } diff --git a/package/lib/src/scrollable/scrollable_sheet_extent.dart b/package/lib/src/scrollable/scrollable_sheet_extent.dart index 322b07a8..8dd49902 100644 --- a/package/lib/src/scrollable/scrollable_sheet_extent.dart +++ b/package/lib/src/scrollable/scrollable_sheet_extent.dart @@ -2,38 +2,59 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:meta/meta.dart'; -import 'package:smooth_sheets/src/foundation/sheet_activity.dart'; -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; -import 'package:smooth_sheets/src/foundation/sheet_physics.dart'; -import 'package:smooth_sheets/src/foundation/sheet_status.dart'; -import 'package:smooth_sheets/src/foundation/sized_content_sheet.dart'; -import 'package:smooth_sheets/src/internal/double_utils.dart'; -import 'package:smooth_sheets/src/scrollable/delegatable_scroll_position.dart'; -import 'package:smooth_sheets/src/scrollable/scrollable_sheet_physics.dart'; - -class ScrollableSheetExtentFactory extends SizedContentSheetExtentFactory { - const ScrollableSheetExtentFactory({ - required super.initialExtent, - required super.minExtent, - required super.maxExtent, - required super.physics, + +import '../foundation/activities.dart'; +import '../foundation/physics.dart'; +import '../foundation/sheet_extent.dart'; +import '../foundation/sheet_status.dart'; +import '../internal/double_utils.dart'; +import 'delegatable_scroll_position.dart'; +import 'scrollable_sheet_physics.dart'; + +class ScrollableSheetExtentConfig extends SheetExtentConfig { + const ScrollableSheetExtentConfig({ + required this.initialExtent, + required this.minExtent, + required this.maxExtent, + required this.physics, }); + /// {@macro ScrollableSheetExtent.initialExtent} + final Extent initialExtent; + + /// {@macro SheetExtent.minExtent} + final Extent minExtent; + + /// {@macro SheetExtent.maxExtent} + final Extent maxExtent; + + /// {@macro SheetExtent.physics} + final SheetPhysics physics; + + @override + bool shouldRebuild(BuildContext context, SheetExtent oldExtent) { + return oldExtent is! ScrollableSheetExtent || + oldExtent.initialExtent != initialExtent || + oldExtent.minExtent != minExtent || + oldExtent.maxExtent != maxExtent || + oldExtent.physics != physics; + } + @override - SheetExtent create({required SheetContext context}) { + SheetExtent build(BuildContext context, SheetContext sheetContext) { return ScrollableSheetExtent( + context: sheetContext, initialExtent: initialExtent, minExtent: minExtent, maxExtent: maxExtent, physics: physics, - context: context, ); } } -class ScrollableSheetExtent extends SizedContentSheetExtent { +class ScrollableSheetExtent extends SheetExtent { ScrollableSheetExtent({ - required super.initialExtent, + required this.initialExtent, required super.minExtent, required super.maxExtent, required super.context, @@ -46,6 +67,11 @@ class ScrollableSheetExtent extends SizedContentSheetExtent { goIdle(); } + /// {@template ScrollableSheetExtent.initialExtent} + /// The initial extent of the sheet when it is first shown. + /// {@endtemplate} + final Extent initialExtent; + ScrollPositionDelegate? get _scrollPositionDelegate { return switch (activity) { final ScrollPositionDelegate delegate => delegate, diff --git a/package/lib/src/scrollable/scrollable_sheet_physics.dart b/package/lib/src/scrollable/scrollable_sheet_physics.dart index ff354886..10f7917f 100644 --- a/package/lib/src/scrollable/scrollable_sheet_physics.dart +++ b/package/lib/src/scrollable/scrollable_sheet_physics.dart @@ -1,5 +1,5 @@ -import 'package:smooth_sheets/src/foundation/sheet_extent.dart'; -import 'package:smooth_sheets/src/foundation/sheet_physics.dart'; +import '../foundation/physics.dart'; +import '../foundation/sheet_extent.dart'; class ScrollableSheetPhysics extends SheetPhysics { const ScrollableSheetPhysics({