Files
MWClash/lib/widgets/sheet.dart
chen08209 ed7868282a Add android separates the core process
Support core status check and force restart

Optimize proxies page and access page

Update flutter and pub dependencies

Update go version

Optimize more details
2025-09-23 15:23:58 +08:00

174 lines
4.8 KiB
Dart

import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart';
import 'scaffold.dart';
import 'side_sheet.dart';
@immutable
class SheetProps {
final double? maxWidth;
final double? maxHeight;
final bool isScrollControlled;
final bool useSafeArea;
final bool blur;
const SheetProps({
this.maxWidth,
this.maxHeight,
this.useSafeArea = true,
this.isScrollControlled = false,
this.blur = true,
});
}
@immutable
class ExtendProps {
final double? maxWidth;
final bool useSafeArea;
final bool blur;
final bool forceFull;
const ExtendProps({
this.maxWidth,
this.useSafeArea = true,
this.blur = true,
this.forceFull = false,
});
}
enum SheetType { page, bottomSheet, sideSheet }
typedef SheetBuilder = Widget Function(BuildContext context, SheetType type);
Future<T?> showSheet<T>({
required BuildContext context,
required SheetBuilder builder,
SheetProps props = const SheetProps(),
}) {
final isMobile = globalState.appState.viewMode == ViewMode.mobile;
return switch (isMobile) {
true => showModalBottomSheet<T>(
context: context,
isScrollControlled: props.isScrollControlled,
builder: (_) {
return SafeArea(child: builder(context, SheetType.bottomSheet));
},
showDragHandle: false,
useSafeArea: props.useSafeArea,
),
false => showModalSideSheet<T>(
useSafeArea: props.useSafeArea,
isScrollControlled: props.isScrollControlled,
context: context,
constraints: BoxConstraints(maxWidth: props.maxWidth ?? 360),
filter: props.blur ? commonFilter : null,
builder: (_) {
return builder(context, SheetType.sideSheet);
},
),
};
}
Future<T?> showExtend<T>(
BuildContext context, {
required SheetBuilder builder,
ExtendProps props = const ExtendProps(),
}) {
final isMobile = globalState.appState.viewMode == ViewMode.mobile;
return switch (isMobile || props.forceFull) {
true => BaseNavigator.push(context, builder(context, SheetType.page)),
false => showModalSideSheet<T>(
useSafeArea: props.useSafeArea,
context: context,
constraints: BoxConstraints(maxWidth: props.maxWidth ?? 360),
filter: props.blur ? commonFilter : null,
builder: (context) {
return builder(context, SheetType.sideSheet);
},
),
};
}
class AdaptiveSheetScaffold extends StatefulWidget {
final SheetType type;
final Widget body;
final String title;
final List<Widget> actions;
const AdaptiveSheetScaffold({
super.key,
required this.type,
required this.body,
required this.title,
this.actions = const [],
});
@override
State<AdaptiveSheetScaffold> createState() => _AdaptiveSheetScaffoldState();
}
class _AdaptiveSheetScaffoldState extends State<AdaptiveSheetScaffold> {
@override
Widget build(BuildContext context) {
final backgroundColor = context.colorScheme.surface;
final bottomSheet = widget.type == SheetType.bottomSheet;
final sideSheet = widget.type == SheetType.sideSheet;
final appBar = AppBar(
forceMaterialTransparency: bottomSheet ? true : false,
automaticallyImplyLeading: bottomSheet
? false
: widget.actions.isEmpty && sideSheet
? false
: true,
centerTitle: bottomSheet,
backgroundColor: backgroundColor,
title: Text(widget.title),
actions: genActions([
if (widget.actions.isEmpty && sideSheet) CloseButton(),
...widget.actions,
]),
);
if (bottomSheet) {
final handleSize = Size(32, 4);
return Container(
clipBehavior: Clip.hardEdge,
decoration: ShapeDecoration(
color: backgroundColor,
shape: RoundedSuperellipseBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(28.0)),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.only(top: 16),
child: Container(
alignment: Alignment.center,
height: handleSize.height,
width: handleSize.width,
decoration: ShapeDecoration(
color: context.colorScheme.onSurfaceVariant,
shape: RoundedSuperellipseBorder(
borderRadius: BorderRadius.circular(handleSize.height / 2),
),
),
),
),
appBar,
Flexible(flex: 1, child: widget.body),
],
),
);
}
return CommonScaffold(
appBar: appBar,
backgroundColor: backgroundColor,
body: widget.body,
);
}
}