content: import 'dart:ui';
  
  import 'package:fl_clash/common/color.dart';
  import 'package:flutter/material.dart';
  import 'package:flutter/rendering.dart';
  
  const Duration _bottomSheetEnterDuration = Duration(milliseconds: 300);
  const Duration _bottomSheetExitDuration = Duration(milliseconds: 200);
  const Curve _modalBottomSheetCurve = Easing.standardDecelerate;
  const double _defaultScrollControlDisabledMaxHeightRatio = 9.0 / 16.0;
  
  class SideSheet extends StatefulWidget {
    const SideSheet({
      super.key,
      this.animationController,
      this.enableDrag = true,
      this.showDragHandle,
      this.dragHandleColor,
      this.dragHandleSize,
      this.onDragStart,
      this.onDragEnd,
      this.backgroundColor,
      this.shadowColor,
      this.elevation,
      this.shape,
      this.clipBehavior,
      this.constraints,
      required this.onClosing,
      required this.builder,
    }) : assert(elevation == null || elevation >= 0.0);
  
    final AnimationController? animationController;
  
    final VoidCallback onClosing;
  
    final WidgetBuilder builder;
  
    final bool enableDrag;
  
    final bool? showDragHandle;
  
    final Color? dragHandleColor;
  
    final Size? dragHandleSize;
  
    final BottomSheetDragStartHandler? onDragStart;
  
    final BottomSheetDragEndHandler? onDragEnd;
  
    final Color? backgroundColor;
  
    final Color? shadowColor;
  
    final double? elevation;
  
    final ShapeBorder? shape;
  
    final Clip? clipBehavior;
  
    final BoxConstraints? constraints;
  
    @override
    State<SideSheet> createState() => _SideSheetState();
  
    static AnimationController createAnimationController(TickerProvider vsync) {
      return AnimationController(
        duration: _bottomSheetEnterDuration,
        reverseDuration: _bottomSheetExitDuration,
        debugLabel: 'SideSheet',
        vsync: vsync,
      );
    }
  }
  
  class _SideSheetState extends State<SideSheet> {
    final GlobalKey _childKey = GlobalKey(debugLabel: 'SideSheet child');
  
    @override
    Widget build(BuildContext context) {
      final colorScheme = Theme.of(context).colorScheme;
      final Color color = widget.backgroundColor ?? colorScheme.surface;
      final Color surfaceTintColor = colorScheme.surfaceTint;
      final Color shadowColor = widget.shadowColor ?? Colors.transparent;
      final double elevation = widget.elevation ?? 0;
      final ShapeBorder shape = widget.shape ??
          RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(0),
          );
  
      final BoxConstraints constraints = widget.constraints ??
          const BoxConstraints(maxWidth: 320, minWidth: 320);
  
      final Clip clipBehavior = widget.clipBehavior ?? Clip.none;
  
      Widget sideSheet = Material(
        key: _childKey,
        color: color,
        elevation: elevation,
        surfaceTintColor: surfaceTintColor,
        shadowColor: shadowColor,
        shape: shape,
        clipBehavior: clipBehavior,
        child: widget.builder(context),
      );
  
      return ConstrainedBox(
        constraints: constraints,
        child: sideSheet,
      );
    }
  }
  
  typedef _SizeChangeCallback<Size> = void Function(Size);
  
  class _SideSheetLayoutWithSizeListener extends SingleChildRenderObjectWidget {
    const _SideSheetLayoutWithSizeListener({
      required this.onChildSizeChanged,
      required this.animationValue,
      required this.isScrollControlled,
      required this.scrollControlDisabledMaxHeightRatio,
      super.child,
    });
  
    final _SizeChangeCallback<Size> onChildSizeChanged;
    final double animationValue;
    final bool isScrollControlled;
    final double scrollControlDisabledMaxHeightRatio;
  
    @override
    _RenderSideSheetLayoutWithSizeListener createRenderObject(
        BuildContext context) {
      return _RenderSideSheetLayoutWithSizeListener(
        onChildSizeChanged: onChildSizeChanged,
        animationValue: animationValue,
        isScrollControlled: isScrollControlled,
        scrollControlDisabledMaxHeightRatio: scrollControlDisabledMaxHeightRatio,
      );
    }
  
    @override
    void updateRenderObject(BuildContext context,
        _RenderSideSheetLayoutWithSizeListener renderObject) {
      renderObject.onChildSizeChanged = onChildSizeChanged;
      renderObject.animationValue = animationValue;
      renderObject.isScrollControlled = isScrollControlled;
      renderObject.scrollControlDisabledMaxHeightRatio =
          scrollControlDisabledMaxHeightRatio;
    }
  }
  
  class _RenderSideSheetLayoutWithSizeListener extends RenderShiftedBox {
    _RenderSideSheetLayoutWithSizeListener({
      RenderBox? child,
      required _SizeChangeCallback<Size> onChildSizeChanged,
      required double animationValue,
      required bool isScrollControlled,
      required double scrollControlDisabledMaxHeightRatio,
    })  : _onChildSizeChanged = onChildSizeChanged,
          _animationValue = animationValue,
          _isScrollControlled = isScrollControlled,
          _scrollControlDisabledMaxHeightRatio =
              scrollControlDisabledMaxHeightRatio,
          super(child);
  
    Size _lastSize = Size.zero;
  
    _SizeChangeCallback<Size> get onChildSizeChanged => _onChildSizeChanged;
    _SizeChangeCallback<Size> _onChildSizeChanged;
  
    set onChildSizeChanged(_SizeChangeCallback<Size> newCallback) {
      if (_onChildSizeChanged == newCallback) {
        return;
      }
  
      _onChildSizeChanged = newCallback;
      markNeedsLayout();
    }
  
    double get animationValue => _animationValue;
    double _animationValue;
  
    set animationValue(double newValue) {
      if (_animationValue == newValue) {
        return;
      }
  
      _animationValue = newValue;
      markNeedsLayout();
    }
  
    bool get isScrollControlled => _isScrollControlled;
    bool _isScrollControlled;
  
    set isScrollControlled(bool newValue) {
      if (_isScrollControlled == newValue) {
        return;
      }
  
      _isScrollControlled = newValue;
      markNeedsLayout();
    }
  
    double get scrollControlDisabledMaxHeightRatio =>
        _scrollControlDisabledMaxHeightRatio;
    double _scrollControlDisabledMaxHeightRatio;
  
    set scrollControlDisabledMaxHeightRatio(double newValue) {
      if (_scrollControlDisabledMaxHeightRatio == newValue) {
        return;
      }
  
      _scrollControlDisabledMaxHeightRatio = newValue;
      markNeedsLayout();
    }
  
    Size _getSize(BoxConstraints constraints) {
      return constraints.constrain(constraints.biggest);
    }
  
    @override
    double computeMinIntrinsicWidth(double height) {
      final double width =
          _getSize(BoxConstraints.tightForFinite(height: height)).width;
      if (width.isFinite) {
        return width;
      }
      return 0.0;
    }
  
    @override
    double computeMaxIntrinsicWidth(double height) {
      final double width =
          _getSize(BoxConstraints.tightForFinite(height: height)).width;
      if (width.isFinite) {
        return width;
      }
      return 0.0;
    }
  
    @override
    double computeMinIntrinsicHeight(double width) {
      final double height =
          _getSize(BoxConstraints.tightForFinite(width: width)).height;
      if (height.isFinite) {
        return height;
      }
      return 0.0;
    }
  
    @override
    double computeMaxIntrinsicHeight(double width) {
      final double height =
          _getSize(BoxConstraints.tightForFinite(width: width)).height;
      if (height.isFinite) {
        return height;
      }
      return 0.0;
    }
  
    @override
    Size computeDryLayout(BoxConstraints constraints) {
      return _getSize(constraints);
    }
  
    BoxConstraints _getConstraintsForChild(BoxConstraints constraints) {
      return BoxConstraints(
        maxHeight: constraints.maxHeight,
      );
    }
  
    Offset _getPositionForChild(Size size, Size childSize) {
      return Offset(size.width - childSize.width * animationValue, 0.0);
    }
  
    @override
    void performLayout() {
      size = _getSize(constraints);
      if (child != null) {
        final BoxConstraints childConstraints =
            _getConstraintsForChild(constraints);
        assert(childConstraints.debugAssertIsValid(isAppliedConstraint: true));
        child!.layout(
          childConstraints,
          parentUsesSize: !childConstraints.isTight,
        );
        final BoxParentData childParentData = child!.parentData! as BoxParentData;
        childParentData.offset = _getPositionForChild(
          size,
          childConstraints.isTight ? childConstraints.smallest : child!.size,
        );
        final Size childSize =
            childConstraints.isTight ? childConstraints.smallest : child!.size;
  
        if (_lastSize != childSize) {
          _lastSize = childSize;
          _onChildSizeChanged.call(_lastSize);
        }
      }
    }
  }
  
  class _ModalSideSheet<T> extends StatefulWidget {
    const _ModalSideSheet({
      super.key,
      required this.route,
      this.backgroundColor,
      this.elevation,
      this.shape,
      this.clipBehavior,
      this.constraints,
      this.isScrollControlled = false,
      this.scrollControlDisabledMaxHeightRatio =
          _defaultScrollControlDisabledMaxHeightRatio,
      this.enableDrag = true,
      this.showDragHandle = false,
    });
  
    final ModalSideSheetRoute<T> route;
    final bool isScrollControlled;
    final double scrollControlDisabledMaxHeightRatio;
    final Color? backgroundColor;
    final double? elevation;
    final ShapeBorder? shape;
    final Clip? clipBehavior;
    final BoxConstraints? constraints;
    final bool enableDrag;
    final bool showDragHandle;
  
    @override
    _ModalSideSheetState<T> createState() => _ModalSideSheetState<T>();
  }
  
  class _ModalSideSheetState<T> extends State<_ModalSideSheet<T>> {
    ParametricCurve<double> animationCurve = _modalBottomSheetCurve;
  
    String _getRouteLabel(MaterialLocalizations localizations) {
      switch (Theme.of(context).platform) {
        case TargetPlatform.iOS:
        case TargetPlatform.macOS:
          return '';
        case TargetPlatform.android:
        case TargetPlatform.fuchsia:
        case TargetPlatform.linux:
        case TargetPlatform.windows:
          return localizations.dialogLabel;
      }
    }
  
    EdgeInsets _getNewClipDetails(Size topLayerSize) {
      return EdgeInsets.fromLTRB(0, 0, 0, topLayerSize.height);
    }
  
    @override
    Widget build(BuildContext context) {
      assert(debugCheckHasMediaQuery(context));
      assert(debugCheckHasMaterialLocalizations(context));
      final MaterialLocalizations localizations =
          MaterialLocalizations.of(context);
      final String routeLabel = _getRouteLabel(localizations);
  
      return AnimatedBuilder(
        animation: widget.route.animation!,
        child: SideSheet(
          animationController: widget.route._animationController,
          onClosing: () {
            if (widget.route.isCurrent) {
              Navigator.pop(context);
            }
          },
          builder: widget.route.builder,
          backgroundColor: widget.backgroundColor,
          elevation: widget.elevation,
          shape: widget.shape,
          clipBehavior: widget.clipBehavior,
          constraints: widget.constraints,
          enableDrag: widget.enableDrag,
          showDragHandle: widget.showDragHandle,
        ),
        builder: (BuildContext context, Widget? child) {
          final double animationValue = animationCurve.transform(
            widget.route.animation!.value,
          );
          return Semantics(
            scopesRoute: true,
            namesRoute: true,
            label: routeLabel,
            explicitChildNodes: true,
            child: ClipRect(
              child: _SideSheetLayoutWithSizeListener(
                onChildSizeChanged: (Size size) {
                  widget.route._didChangeBarrierSemanticsClip(
                    _getNewClipDetails(size),
                  );
                },
                animationValue: animationValue,
                isScrollControlled: widget.isScrollControlled,
                scrollControlDisabledMaxHeightRatio:
                    widget.scrollControlDisabledMaxHeightRatio,
                child: child,
              ),
            ),
          );
        },
      );
    }
  }
  
  class ModalSideSheetRoute<T> extends PopupRoute<T> {
    ModalSideSheetRoute(
        {required this.builder,
        this.capturedThemes,
        this.barrierLabel,
        this.barrierOnTapHint,
        this.backgroundColor,
        this.elevation,
        this.shape,
        this.clipBehavior,
        this.constraints,
        this.modalBarrierColor,
        this.isDismissible = true,
        this.isScrollControlled = false,
        this.scrollControlDisabledMaxHeightRatio =
            _defaultScrollControlDisabledMaxHeightRatio,
        super.settings,
        this.transitionAnimationController,
        this.anchorPoint,
        this.useSafeArea = false,
        super.filter});
  
    final WidgetBuilder builder;
  
    final CapturedThemes? capturedThemes;
  
    final bool isScrollControlled;
  
    final double scrollControlDisabledMaxHeightRatio;
  
    final Color? backgroundColor;
  
    final double? elevation;
  
    final ShapeBorder? shape;
  
    final Clip? clipBehavior;
  
    final BoxConstraints? constraints;
  
    final Color? modalBarrierColor;
  
    final bool isDismissible;
  
    final AnimationController? transitionAnimationController;
  
    final Offset? anchorPoint;
  
    final bool useSafeArea;
  
    final String? barrierOnTapHint;
  
    final ValueNotifier<EdgeInsets> _clipDetailsNotifier =
        ValueNotifier<EdgeInsets>(EdgeInsets.zero);
  
    @override
    void dispose() {
      _clipDetailsNotifier.dispose();
      super.dispose();
    }
  
    bool _didChangeBarrierSemanticsClip(EdgeInsets newClipDetails) {
      if (_clipDetailsNotifier.value == newClipDetails) {
        return false;
      }
      _clipDetailsNotifier.value = newClipDetails;
      return true;
    }
  
    @override
    Duration get transitionDuration => _bottomSheetEnterDuration;
  
    @override
    Duration get reverseTransitionDuration => _bottomSheetExitDuration;
  
    @override
    bool get barrierDismissible => isDismissible;
  
    @override
    final String? barrierLabel;
  
    @override
    Color get barrierColor => modalBarrierColor ?? Colors.black54;
  
    AnimationController? _animationController;
  
    @override
    AnimationController createAnimationController() {
      assert(_animationController == null);
      if (transitionAnimationController != null) {
        _animationController = transitionAnimationController;
        willDisposeAnimationController = false;
      } else {
        _animationController = SideSheet.createAnimationController(navigator!);
      }
      return _animationController!;
    }
  
    @override
    Widget buildPage(BuildContext context, Animation<double> animation,
        Animation<double> secondaryAnimation) {
      final Widget content = DisplayFeatureSubScreen(
        anchorPoint: anchorPoint,
        child: Builder(
          builder: (BuildContext context) {
            final colorScheme = Theme.of(context).colorScheme;
            return _ModalSideSheet<T>(
              route: this,
              backgroundColor: backgroundColor ?? colorScheme.surface,
              elevation: elevation ?? 0,
              shape: shape,
              clipBehavior: clipBehavior,
              constraints: constraints,
              isScrollControlled: isScrollControlled,
              scrollControlDisabledMaxHeightRatio:
                  scrollControlDisabledMaxHeightRatio,
            );
          },
        ),
      );
  
      final Widget sideSheet = content;
  
      return capturedThemes?.wrap(sideSheet) ?? sideSheet;
    }
  
    @override
    Widget buildModalBarrier() {
      if (barrierColor.alpha != 0 && !offstage) {
        assert(barrierColor != barrierColor.opacity0);
        final Animation<Color?> color = animation!.drive(
          ColorTween(
            begin: barrierColor.opacity0,
            end: barrierColor,
          ).chain(
            CurveTween(curve: barrierCurve),
          ),
        );
        return AnimatedModalBarrier(
          color: color,
          dismissible: barrierDismissible,
          semanticsLabel: barrierLabel,
          barrierSemanticsDismissible: semanticsDismissible,
          clipDetailsNotifier: _clipDetailsNotifier,
          semanticsOnTapHint: barrierOnTapHint,
        );
      } else {
        return ModalBarrier(
          dismissible: barrierDismissible,
          semanticsLabel: barrierLabel,
          barrierSemanticsDismissible: semanticsDismissible,
          clipDetailsNotifier: _clipDetailsNotifier,
          semanticsOnTapHint: barrierOnTapHint,
        );
      }
    }
  }
  
  Future<T?> showModalSideSheet<T>({
    required BuildContext context,
    required WidgetBuilder builder,
    Color? backgroundColor,
    String? barrierLabel,
    double? elevation,
    ShapeBorder? shape,
    Clip? clipBehavior,
    BoxConstraints? constraints,
    Color? barrierColor,
    bool isScrollControlled = false,
    double scrollControlDisabledMaxHeightRatio =
        _defaultScrollControlDisabledMaxHeightRatio,
    bool useRootNavigator = false,
    bool isDismissible = true,
    bool useSafeArea = false,
    RouteSettings? routeSettings,
    AnimationController? transitionAnimationController,
    Offset? anchorPoint,
    ImageFilter? filter,
  }) {
    assert(debugCheckHasMediaQuery(context));
    assert(debugCheckHasMaterialLocalizations(context));
  
    final NavigatorState navigator =
        Navigator.of(context, rootNavigator: useRootNavigator);
    final MaterialLocalizations localizations = MaterialLocalizations.of(context);
    return navigator.push(ModalSideSheetRoute<T>(
      builder: builder,
      filter: filter,
      capturedThemes:
          InheritedTheme.capture(from: context, to: navigator.context),
      isScrollControlled: isScrollControlled,
      scrollControlDisabledMaxHeightRatio: scrollControlDisabledMaxHeightRatio,
      barrierLabel: barrierLabel ?? localizations.scrimLabel,
      barrierOnTapHint:
          localizations.scrimOnTapHint(localizations.bottomSheetLabel),
      backgroundColor: backgroundColor,
      elevation: elevation,
      shape: shape,
      clipBehavior: clipBehavior,
      constraints: constraints,
      isDismissible: isDismissible,
      modalBarrierColor:
          barrierColor ?? Theme.of(context).bottomSheetTheme.modalBarrierColor,
      settings: routeSettings,
      transitionAnimationController: transitionAnimationController,
      anchorPoint: anchorPoint,
      useSafeArea: useSafeArea,
    ));
  }
  
  // class ModalAppBar extends StatelessWidget {
  //   final String title;
  //
  //   const ModalAppBar({
  //     super.key,
  //     required this.title,
  //   });
  //
  //   @override
  //   Widget build(BuildContext context) {
  //     return AppBar(
  //       automaticallyImplyLeading: false,
  //       title: Text(title),
  //       centerTitle: false,
  //       actions: const [
  //         SizedBox(
  //           height: kToolbarHeight,
  //           width: kToolbarHeight,
  //           child: CloseButton(),
  //         )
  //       ],
  //     );
  //   }
  // }
  