showAlertDialog<T> function

  1. @useResult
Future<T?> showAlertDialog<T>({
  1. required BuildContext context,
  2. String? title,
  3. String? message,
  4. List<AlertDialogAction<T>> actions = const [],
  5. bool barrierDismissible = true,
  6. AdaptiveStyle? style,
  7. @Deprecated('Use `useActionSheetForIOS` instead. Will be removed in v2.') bool useActionSheetForCupertino = false,
  8. bool useActionSheetForIOS = false,
  9. bool useRootNavigator = true,
  10. VerticalDirection actionsOverflowDirection = VerticalDirection.up,
  11. @Deprecated('Will be removed in v3') bool fullyCapitalizedForMaterial = false,
  12. bool canPop = true,
  13. PopInvokedWithResultCallback<T>? onPopInvokedWithResult,
  14. AdaptiveDialogBuilder? builder,
  15. Widget? macOSApplicationIcon,
  16. RouteSettings? routeSettings,
  17. AdaptiveSelectionMode? selectionMode,
})

Show alert dialog, whose appearance is adaptive according to platform

barrierDismissible (default: true) only works for Material style. useActionSheetForIOS (default: false) only works for iOS style. If it is set to true, showModalActionSheet is called instead. actionsOverflowDirection works only for Material style currently.

Implementation

@useResult
Future<T?> showAlertDialog<T>({
  required BuildContext context,
  String? title,
  String? message,
  List<AlertDialogAction<T>> actions = const [],
  bool barrierDismissible = true,
  AdaptiveStyle? style,
  @Deprecated('Use `useActionSheetForIOS` instead. Will be removed in v2.')
  bool useActionSheetForCupertino = false,
  bool useActionSheetForIOS = false,
  bool useRootNavigator = true,
  VerticalDirection actionsOverflowDirection = VerticalDirection.up,
  @Deprecated('Will be removed in v3') bool fullyCapitalizedForMaterial = false,
  bool canPop = true,
  PopInvokedWithResultCallback<T>? onPopInvokedWithResult,
  AdaptiveDialogBuilder? builder,
  Widget? macOSApplicationIcon,
  RouteSettings? routeSettings,
  AdaptiveSelectionMode? selectionMode,
}) {
  void pop({required BuildContext context, required T? key}) => Navigator.of(
    context,
    rootNavigator: useRootNavigator,
  ).pop(key);

  final theme = Theme.of(context);
  final colorScheme = theme.colorScheme;
  final adaptiveStyle = style ?? AdaptiveDialog.instance.defaultStyle;
  final isIOSStyle = adaptiveStyle.effectiveStyle(theme) == AdaptiveStyle.iOS;
  if (isIOSStyle && (useActionSheetForCupertino || useActionSheetForIOS)) {
    return showModalActionSheet(
      context: context,
      title: title,
      message: message,
      cancelLabel: actions.findCancelLabel(),
      actions: actions.convertToSheetActions(),
      style: style,
      useRootNavigator: useRootNavigator,
      canPop: canPop,
      onPopInvokedWithResult: onPopInvokedWithResult,
      builder: builder,
      routeSettings: routeSettings,
      selectionMode: selectionMode,
    );
  }

  final titleText = title == null
      ? null
      : AdaptiveSelectionArea(
          mode: selectionMode,
          child: Text(title),
        );
  final messageText = message == null
      ? null
      : AdaptiveSelectionArea(
          mode: selectionMode,
          child: Text(message),
        );

  final effectiveStyle = adaptiveStyle.effectiveStyle(theme);
  final shortcutBindings = {
    const SingleActivator(LogicalKeyboardKey.enter): () {
      final defaultAction = actions.firstWhereOrNull(
        (a) => a.isDefaultAction,
      );
      if (defaultAction != null) {
        pop(context: context, key: defaultAction.key);
      }
    },
    const SingleActivator(LogicalKeyboardKey.escape): () {
      final cancelAction = actions.firstWhereOrNull(
        (a) => a.key == OkCancelResult.cancel,
      );
      if (cancelAction != null) {
        pop(context: context, key: cancelAction.key);
      } else if (canPop ||
          (effectiveStyle == AdaptiveStyle.material && barrierDismissible)) {
        pop(context: context, key: null);
      }
    },
  };
  switch (effectiveStyle) {
    case AdaptiveStyle.cupertino:
    case AdaptiveStyle.iOS:
      return showCupertinoDialog(
        context: context,
        useRootNavigator: useRootNavigator,
        routeSettings: routeSettings,
        builder: (context) {
          final dialog = CallbackShortcuts(
            bindings: shortcutBindings,
            child: Focus(
              autofocus: true,
              child: PopScope(
                canPop: canPop,
                onPopInvokedWithResult: onPopInvokedWithResult,
                child: CupertinoAlertDialog(
                  title: titleText,
                  content: messageText,
                  actions: actions
                      .map(
                        (a) => a.convertToIOSDialogAction(
                          onPressed: (key) => pop(context: context, key: key),
                        ),
                      )
                      .toList(),
                  // TODO(mono): Set actionsOverflowDirection if available
                  // https://twitter.com/_mono/status/1261122914218160128
                ),
              ),
            ),
          );
          return builder == null ? dialog : builder(context, dialog);
        },
      );
    case AdaptiveStyle.macOS:
      final buttons = actions
          .map(
            (a) => a.convertToMacOSDialogAction(
              onPressed: (key) => pop(context: context, key: key),
            ),
          )
          .intersperse(const SizedBox(height: 8))
          .toList()
          .reversed
          .toList();
      return showMacosAlertDialog(
        context: context,
        useRootNavigator: useRootNavigator,
        routeSettings: routeSettings,
        builder: (context) {
          final Widget dialog = MacThemeWrapper(
            child: CallbackShortcuts(
              bindings: shortcutBindings,
              child: Focus(
                autofocus: true,
                child: PopScope(
                  canPop: canPop,
                  onPopInvokedWithResult: onPopInvokedWithResult,
                  child: MacosAlertDialog(
                    title: titleText ?? const SizedBox.shrink(),
                    message: messageText ?? const SizedBox.shrink(),
                    primaryButton: const _DummyEmptyMacosPushButton(),
                    suppress: Column(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: buttons,
                    ),
                    appIcon:
                        macOSApplicationIcon ??
                        AdaptiveDialog.instance.macOS.applicationIcon ??
                        const Icon(Icons.info),
                  ),
                ),
              ),
            ),
          );
          return builder == null ? dialog : builder(context, dialog);
        },
      );
    case AdaptiveStyle.material:
      return showModal(
        context: context,
        useRootNavigator: useRootNavigator,
        routeSettings: routeSettings,
        configuration: FadeScaleTransitionConfiguration(
          barrierDismissible: barrierDismissible,
        ),
        builder: (context) {
          final dialog = CallbackShortcuts(
            bindings: shortcutBindings,
            child: Focus(
              autofocus: true,
              child: PopScope(
                canPop: canPop,
                onPopInvokedWithResult: onPopInvokedWithResult,
                child: AlertDialog(
                  title: titleText,
                  content: messageText,
                  actions: actions
                      .map(
                        (a) => a.convertToMaterialDialogAction(
                          onPressed: (key) => pop(context: context, key: key),
                          destructiveColor: colorScheme.error,
                          fullyCapitalized: fullyCapitalizedForMaterial,
                        ),
                      )
                      .toList(),
                  actionsOverflowDirection: actionsOverflowDirection,
                  scrollable: true,
                ),
              ),
            ),
          );
          return builder == null ? dialog : builder(context, dialog);
        },
      );
    case AdaptiveStyle.adaptive:
      assert(false);
      return Future.value();
  }
}