diff --git a/example/lib/pages/general_dialog_page.dart b/example/lib/pages/general_dialog_page.dart new file mode 100644 index 0000000..a619f29 --- /dev/null +++ b/example/lib/pages/general_dialog_page.dart @@ -0,0 +1,48 @@ +import 'package:adaptive_dialog/adaptive_dialog.dart'; +import 'package:example/router/router.dart'; +import 'package:example/util/logger.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +class GeneralDialogRoute extends GoRouteData { + const GeneralDialogRoute(); + @override + Widget build(BuildContext context, GoRouterState state) => + const GeneralDialogPage(); +} + +class GeneralDialogPage extends StatelessWidget { + const GeneralDialogPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(pascalCaseFromRouteName(GoRouter.of(context).location)), + ), + body: ListView( + children: [ + ListTile( + title: const Text('OK Dialog'), + onTap: () async { + final result = await showGeneralAdaptiveDialog( + context: context, + child: Container( + width: 80, + height: 80, + color: Colors.red, + child: Column( + children: const [ + Text('hello'), + ], + ), + ), + ); + logger.info(result); + }, + ), + ], + ), + ); + } +} diff --git a/example/lib/router/router.dart b/example/lib/router/router.dart index fbe9fb2..86e74f4 100644 --- a/example/lib/router/router.dart +++ b/example/lib/router/router.dart @@ -1,3 +1,4 @@ +import 'package:example/pages/general_dialog_page.dart'; import 'package:example/pages/home_page.dart'; import 'package:example/pages/text_input_dialog_page.dart'; import 'package:flutter/foundation.dart'; @@ -25,6 +26,7 @@ final routerProvider = Provider( TypedGoRoute(path: 'alert'), TypedGoRoute(path: 'sheet'), TypedGoRoute(path: 'text-input'), + TypedGoRoute(path: 'general'), TypedGoRoute(path: 'nested-navigator'), ], ) @@ -40,5 +42,6 @@ List get allRouteLocations => [ const AlertRoute().location, const SheetRoute().location, const TextInputDialogRoute().location, + const GeneralDialogRoute().location, const NestedNavigatorRoute().location, ]; diff --git a/example/lib/router/router.g.dart b/example/lib/router/router.g.dart index e841fe7..daff1ea 100644 --- a/example/lib/router/router.g.dart +++ b/example/lib/router/router.g.dart @@ -26,6 +26,10 @@ GoRoute get $homeRoute => GoRouteData.$route( path: 'text-input', factory: $TextInputDialogRouteExtension._fromState, ), + GoRouteData.$route( + path: 'general', + factory: $GeneralDialogRouteExtension._fromState, + ), GoRouteData.$route( path: 'nested-navigator', factory: $NestedNavigatorRouteExtension._fromState, @@ -40,7 +44,9 @@ extension $HomeRouteExtension on HomeRoute { '/', ); - void go(BuildContext buildContext) => buildContext.go(location, extra: this); + void go(BuildContext context) => context.go(location, extra: this); + + void push(BuildContext context) => context.push(location, extra: this); } extension $AlertRouteExtension on AlertRoute { @@ -50,7 +56,9 @@ extension $AlertRouteExtension on AlertRoute { '/alert', ); - void go(BuildContext buildContext) => buildContext.go(location, extra: this); + void go(BuildContext context) => context.go(location, extra: this); + + void push(BuildContext context) => context.push(location, extra: this); } extension $SheetRouteExtension on SheetRoute { @@ -60,7 +68,9 @@ extension $SheetRouteExtension on SheetRoute { '/sheet', ); - void go(BuildContext buildContext) => buildContext.go(location, extra: this); + void go(BuildContext context) => context.go(location, extra: this); + + void push(BuildContext context) => context.push(location, extra: this); } extension $TextInputDialogRouteExtension on TextInputDialogRoute { @@ -71,7 +81,22 @@ extension $TextInputDialogRouteExtension on TextInputDialogRoute { '/text-input', ); - void go(BuildContext buildContext) => buildContext.go(location, extra: this); + void go(BuildContext context) => context.go(location, extra: this); + + void push(BuildContext context) => context.push(location, extra: this); +} + +extension $GeneralDialogRouteExtension on GeneralDialogRoute { + static GeneralDialogRoute _fromState(GoRouterState state) => + const GeneralDialogRoute(); + + String get location => GoRouteData.$location( + '/general', + ); + + void go(BuildContext context) => context.go(location, extra: this); + + void push(BuildContext context) => context.push(location, extra: this); } extension $NestedNavigatorRouteExtension on NestedNavigatorRoute { @@ -82,5 +107,7 @@ extension $NestedNavigatorRouteExtension on NestedNavigatorRoute { '/nested-navigator', ); - void go(BuildContext buildContext) => buildContext.go(location, extra: this); + void go(BuildContext context) => context.go(location, extra: this); + + void push(BuildContext context) => context.push(location, extra: this); } diff --git a/lib/adaptive_dialog.dart b/lib/adaptive_dialog.dart index 85a3bf2..ed33cb0 100644 --- a/lib/adaptive_dialog.dart +++ b/lib/adaptive_dialog.dart @@ -1,6 +1,7 @@ export 'src/adaptive_dialog.dart'; export 'src/adaptive_style.dart'; export 'src/alert_dialog/alert_dialog.dart'; +export 'src/general_dialog/show_general_adaptive_dialog.dart'; export 'src/modal_action_sheet/modal_action_sheet.dart'; export 'src/text_input_dialog/show_text_answer_dialog.dart'; export 'src/text_input_dialog/show_text_input_dialog.dart'; diff --git a/lib/src/general_dialog/show_general_adaptive_dialog.dart b/lib/src/general_dialog/show_general_adaptive_dialog.dart new file mode 100644 index 0000000..4ff948b --- /dev/null +++ b/lib/src/general_dialog/show_general_adaptive_dialog.dart @@ -0,0 +1,131 @@ +import 'package:adaptive_dialog/adaptive_dialog.dart'; +import 'package:adaptive_dialog/src/helper/macos_theme_wrapper.dart'; +import 'package:animations/animations.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:macos_ui/macos_ui.dart'; +import 'package:meta/meta.dart'; + +@useResult +Future showGeneralAdaptiveDialog({ + required BuildContext context, + required Widget child, + GeneralAdaptiveDialogBuilder? builder, + bool barrierDismissible = true, + AdaptiveStyle? style, + bool useRootNavigator = true, + WillPopCallback? onWillPop, + Widget? macOSApplicationIcon, + RouteSettings? routeSettings, + String? okLabel, +}) { + final navigator = Navigator.of( + context, + rootNavigator: useRootNavigator, + ); + void pop(T? key) => navigator.pop(key); + final theme = Theme.of(context); + final colorScheme = theme.colorScheme; + final adaptiveStyle = style ?? AdaptiveDialog.instance.defaultStyle; + final effectiveStyle = adaptiveStyle.effectiveStyle(theme); + switch (effectiveStyle) { + // ignore: deprecated_member_use, deprecated_member_use_from_same_package + case AdaptiveStyle.cupertino: + case AdaptiveStyle.iOS: + return showCupertinoDialog( + context: context, + useRootNavigator: useRootNavigator, + routeSettings: routeSettings, + builder: (context) { + final dialog = WillPopScope( + onWillPop: onWillPop, + child: CupertinoAlertDialog( + title: child, + content: const SizedBox(), + actions: [ + CupertinoDialogAction( + isDefaultAction: true, + onPressed: () => pop(null), + child: Text( + okLabel ?? MaterialLocalizations.of(context).okButtonLabel, + ), + ), + ], + ), + ); + return builder == null + ? dialog + : builder(context, effectiveStyle, dialog); + }, + ); + case AdaptiveStyle.macOS: + return showMacosAlertDialog( + context: context, + useRootNavigator: useRootNavigator, + routeSettings: routeSettings, + builder: (context) { + final Widget dialog = MacThemeWrapper( + child: WillPopScope( + onWillPop: onWillPop, + child: MacosAlertDialog( + title: child, + message: const SizedBox.shrink(), + appIcon: macOSApplicationIcon ?? + AdaptiveDialog.instance.macOS.applicationIcon ?? + const Icon(Icons.info), + primaryButton: PushButton( + buttonSize: ButtonSize.large, + // isSecondary: isDestructiveAction || !isDefaultAction, + onPressed: () => pop(null), + child: Text( + okLabel ?? MaterialLocalizations.of(context).okButtonLabel, + ), + ), + ), + ), + ); + return builder == null + ? dialog + : builder(context, effectiveStyle, dialog); + }, + ); + case AdaptiveStyle.material: + return showModal( + context: context, + useRootNavigator: useRootNavigator, + routeSettings: routeSettings, + configuration: FadeScaleTransitionConfiguration( + barrierDismissible: barrierDismissible, + ), + builder: (context) { + final dialog = WillPopScope( + onWillPop: onWillPop, + child: AlertDialog( + content: child, + actions: [ + TextButton( + child: Text( + okLabel ?? MaterialLocalizations.of(context).okButtonLabel, + ), + onPressed: () => pop(null), + ) + ], + ), + ); + return builder == null + ? dialog + : builder(context, effectiveStyle, dialog); + }, + ); + case AdaptiveStyle.adaptive: + assert(false); + return Future.value(); + } +} + +// TODO(mono): 順番あってる? +typedef GeneralAdaptiveDialogBuilder = Widget Function( + BuildContext context, + AdaptiveStyle style, + Widget child, +);