Initial commit

This commit is contained in:
admin1
2026-07-14 11:11:36 +08:00
commit 656499cf94
604 changed files with 119518 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
import 'package:flutter/material.dart';
import 'package:forui/forui.dart';
import '../constants/breakpoints.dart';
import '../theme/app_theme_scope.dart';
Future<T?> showAdaptiveModal<T>({
required BuildContext context,
required WidgetBuilder builder,
double maxWidth = 520,
double? maxHeight,
double compactMaxHeightFactor = 0.92,
double? compactHeightFactor,
bool barrierDismissible = true,
bool useRootNavigator = false,
}) {
final isCompact = Breakpoints.isCompact(MediaQuery.sizeOf(context).width);
if (isCompact) {
return showModalBottomSheet<T>(
context: context,
isScrollControlled: true,
useSafeArea: true,
useRootNavigator: useRootNavigator,
isDismissible: barrierDismissible,
showDragHandle: true,
backgroundColor: Colors.transparent,
barrierColor: Colors.black54,
builder: (sheetContext) => AppThemeScope(
child: _AdaptiveBottomSheet(
maxHeightFactor: compactMaxHeightFactor,
heightFactor: compactHeightFactor,
child: builder(sheetContext),
),
),
);
}
const insetPadding = EdgeInsets.symmetric(horizontal: 40, vertical: 32);
return showFDialog<T>(
context: context,
useRootNavigator: useRootNavigator,
barrierDismissible: barrierDismissible,
builder: (dialogContext, _, animation) {
final screenHeight = MediaQuery.sizeOf(dialogContext).height;
return AppThemeScope(
child: FDialog.raw(
animation: animation,
clipBehavior: Clip.antiAlias,
constraints: BoxConstraints(
maxWidth: maxWidth,
maxHeight: maxHeight ?? screenHeight - insetPadding.vertical,
),
builder: (_, _) => builder(dialogContext),
),
);
},
);
}
class _AdaptiveBottomSheet extends StatelessWidget {
final Widget child;
final double maxHeightFactor;
final double? heightFactor;
const _AdaptiveBottomSheet({
required this.child,
required this.maxHeightFactor,
required this.heightFactor,
});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final size = MediaQuery.sizeOf(context);
final viewInsets = MediaQuery.viewInsetsOf(context);
final fixedHeight = heightFactor == null
? null
: size.height * heightFactor!;
final maxHeight = size.height * maxHeightFactor;
Widget sheet = Material(
color: theme.colorScheme.surface,
clipBehavior: Clip.antiAlias,
borderRadius: const BorderRadius.vertical(top: Radius.circular(24)),
child: SafeArea(
top: false,
child: Column(
mainAxisSize: fixedHeight == null
? MainAxisSize.min
: MainAxisSize.max,
children: [
if (fixedHeight == null)
Flexible(fit: FlexFit.loose, child: child)
else
Expanded(child: child),
],
),
),
);
sheet = ConstrainedBox(
constraints: BoxConstraints(maxHeight: maxHeight),
child: fixedHeight == null
? sheet
: SizedBox(height: fixedHeight, child: sheet),
);
return AnimatedPadding(
duration: const Duration(milliseconds: 220),
curve: Curves.easeOutCubic,
padding: EdgeInsets.only(bottom: viewInsets.bottom),
child: Align(alignment: Alignment.bottomCenter, child: sheet),
);
}
}