Repository: flutter/flutter
File: packages/flutter/lib/src/cupertino/sheet.dart (Dart)

Code before:

  static _CupertinoSheetScope? maybeOf(BuildContext context) {
    return context.getInheritedWidgetOfExactType<_CupertinoSheetScope>();
  }

  @override
  bool updateShouldNotify(_CupertinoSheetScope oldWidget) => false;
}

/// A mixin that replaces the entire screen with an iOS sheet transition for a
/// [PageRoute].
///
/// See also:
///
///  * [CupertinoSheetRoute], which is a [PageRoute] that leverages this mixin.
mixin _CupertinoSheetRouteTransitionMixin<T> on PageRoute<T> {
  /// Builds the primary contents of the route.
  @protected
  Widget buildContent(BuildContext context);

  @override
  Duration get transitionDuration => const Duration(milliseconds: 500);

  @override
  DelegatedTransitionBuilder? get delegatedTransition =>
      (
        BuildContext context,
        Animation<double> animation,
        Animation<double> secondaryAnimation,
        bool allowSnapshotting,
        Widget? child,
      ) => CupertinoSheetTransition.delegateTransition(
        context,
        animation,
        secondaryAnimation,
        allowSnapshotting,
        child,
        topGap: topGap,
      );

  /// Determines whether the content can be dragged.
  ///
  /// If `true`, dragging is enabled; otherwise, it remains fixed.
  bool get enableDrag;

  /// The gap between the top of the screen and the top of the sheet as a ratio
  /// of the screen height (0.0 to 1.0). If null, defaults to [_kTopGapRatio].
  double? get topGap;

  @override
  Widget buildPage(

Review comment (bug):
This change is causing the test to fail. Since it's no longer directly referencing a static method and is created a new method, two sheets cannot see that they are equivalent to each other, so stacked sheets are incorrectly moving the previous sheet down as if they where a normal full screen route.

I'm not sure what the best way to handle this is for this change.

Code after:
class CupertinoSheetRoute<T> extends PageRoute<T> with _CupertinoSheetRouteTransitionMixin<T> {
  /// Creates a page route that displays an iOS styled sheet.
  CupertinoSheetRoute({
    super.settings,
    required this.builder,
    this.enableDrag = true,
    double? topGap,
  }) : assert(
         topGap == null || (topGap >= 0.0 && topGap <= 0.9),
         'topGap must be between 0.0 and 0.9',
       ),
       _topGap = topGap;

  /// Builds the primary contents of the sheet route.
  final WidgetBuilder builder;

  @override
  final bool enableDrag;

  // The gap between the top of the screen and the top of the sheet.
  final double? _topGap;

  @override
  double get topGap => _topGap ?? _kTopGapRatio;

  @override
  bool get _hasCustomTopGap => _topGap != null;

  @override
  Widget buildContent(BuildContext context) {
    return MediaQuery.removePadding(
      context: context,
      removeTop: true,
      child: ClipRSuperellipse(
        borderRadius: const BorderRadius.vertical(top: Radius.circular(12)),
        child: CupertinoUserInterfaceLevel(
          data: CupertinoUserInterfaceLevelData.elevated,
          child: _CupertinoSheetScope(child: builder(context)),
        ),
      ),
    );
  }

  /// Checks if a Cupertino sheet view exists in the widget tree above the current
  /// context.
  static bool hasParentSheet(BuildContext context) {
    return _CupertinoSheetScope.maybeOf(context) != null;
  }

  /// Pops the entire [CupertinoSheetRoute], if a sheet route exists in the stack.
  ///