You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.6 KiB
Dart
117 lines
3.6 KiB
Dart
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
Future<T?> showModalActionPopup<T>({
|
|
required BuildContext context,
|
|
required List<AdaptiveModalAction<T>> actions,
|
|
String? title,
|
|
String? message,
|
|
String? cancelLabel,
|
|
bool useRootNavigator = true,
|
|
}) {
|
|
final theme = Theme.of(context);
|
|
|
|
switch (theme.platform) {
|
|
case TargetPlatform.android:
|
|
case TargetPlatform.fuchsia:
|
|
case TargetPlatform.windows:
|
|
case TargetPlatform.linux:
|
|
return showModalBottomSheet(
|
|
isScrollControlled: true,
|
|
useRootNavigator: useRootNavigator,
|
|
context: context,
|
|
clipBehavior: Clip.hardEdge,
|
|
constraints: BoxConstraints(
|
|
maxWidth: 512,
|
|
maxHeight: MediaQuery.of(context).size.height - 32,
|
|
),
|
|
builder: (context) => ListView(
|
|
shrinkWrap: true,
|
|
children: [
|
|
if (title != null || message != null) ...[
|
|
ListTile(
|
|
title: title == null
|
|
? null
|
|
: Text(
|
|
title,
|
|
style: theme.textTheme.labelSmall,
|
|
),
|
|
subtitle: message == null ? null : Text(message),
|
|
),
|
|
const Divider(height: 1),
|
|
],
|
|
...actions.map(
|
|
(action) => ListTile(
|
|
leading: action.icon,
|
|
title: Text(
|
|
action.label,
|
|
maxLines: 1,
|
|
style: action.isDestructive
|
|
? TextStyle(
|
|
color: theme.colorScheme.error,
|
|
fontWeight:
|
|
action.isDefaultAction ? FontWeight.bold : null,
|
|
)
|
|
: null,
|
|
),
|
|
onTap: () => Navigator.of(context).pop<T>(action.value),
|
|
),
|
|
),
|
|
if (cancelLabel != null) ...[
|
|
const Divider(height: 1),
|
|
ListTile(
|
|
title: Text(cancelLabel),
|
|
onTap: () => Navigator.of(context).pop(null),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
);
|
|
case TargetPlatform.iOS:
|
|
case TargetPlatform.macOS:
|
|
return showCupertinoModalPopup<T>(
|
|
context: context,
|
|
useRootNavigator: useRootNavigator,
|
|
builder: (context) => ConstrainedBox(
|
|
constraints: const BoxConstraints(maxWidth: 512),
|
|
child: CupertinoActionSheet(
|
|
title: title == null ? null : Text(title),
|
|
message: message == null ? null : Text(message),
|
|
cancelButton: cancelLabel == null
|
|
? null
|
|
: CupertinoActionSheetAction(
|
|
onPressed: () => Navigator.of(context).pop(null),
|
|
child: Text(cancelLabel),
|
|
),
|
|
actions: actions
|
|
.map(
|
|
(action) => CupertinoActionSheetAction(
|
|
isDestructiveAction: action.isDestructive,
|
|
isDefaultAction: action.isDefaultAction,
|
|
onPressed: () => Navigator.of(context).pop<T>(action.value),
|
|
child: Text(action.label, maxLines: 1),
|
|
),
|
|
)
|
|
.toList(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class AdaptiveModalAction<T> {
|
|
final String label;
|
|
final T value;
|
|
Icon? icon;
|
|
final bool isDefaultAction;
|
|
final bool isDestructive;
|
|
|
|
AdaptiveModalAction({
|
|
required this.label,
|
|
required this.value,
|
|
this.icon,
|
|
this.isDefaultAction = false,
|
|
this.isDestructive = false,
|
|
});
|
|
}
|