styled_dialogs.dart 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import 'package:flowy_style/buttons/ok_cancel_button.dart';
  2. import 'package:flowy_style/dialog/dialog_size.dart';
  3. import 'package:flowy_style/scrolling/styled_list.dart';
  4. import 'package:flowy_style/size.dart';
  5. import 'package:flowy_style/spacing.dart';
  6. import 'package:flowy_style/text_style.dart';
  7. import 'package:flowy_style/theme.dart';
  8. import 'package:flutter/material.dart';
  9. import 'package:provider/provider.dart';
  10. // ignore: import_of_legacy_library_into_null_safe
  11. import 'package:textstyle_extensions/textstyle_extensions.dart';
  12. import 'dialog_context.dart';
  13. export 'dialog_context.dart';
  14. class Dialogs {
  15. static Future<dynamic> show(Widget child, BuildContext context) async {
  16. return await Navigator.of(context).push(
  17. StyledDialogRoute(
  18. pageBuilder: (BuildContext buildContext, Animation<double> animation,
  19. Animation<double> secondaryAnimation) {
  20. return SafeArea(child: child);
  21. },
  22. ),
  23. );
  24. /*return await showDialog(
  25. context: context ?? MainViewContext.value,
  26. builder: (context) => child,
  27. );*/
  28. }
  29. static Future<dynamic> showWithContext(
  30. DialogContext dialogContext, BuildContext context) async {
  31. return await Navigator.of(context).push(
  32. StyledDialogRoute(
  33. barrierDismissible: dialogContext.barrierDismissable,
  34. pageBuilder: (BuildContext buildContext, Animation<double> animation,
  35. Animation<double> secondaryAnimation) {
  36. return SafeArea(child: dialogContext.buildWiget(buildContext));
  37. },
  38. ),
  39. );
  40. }
  41. }
  42. class StyledDialogRoute<T> extends PopupRoute<T> {
  43. StyledDialogRoute({
  44. required RoutePageBuilder pageBuilder,
  45. bool barrierDismissible = false,
  46. String? barrierLabel,
  47. Color barrierColor = const Color(0x80000000),
  48. Duration transitionDuration = const Duration(milliseconds: 200),
  49. RouteTransitionsBuilder? transitionBuilder,
  50. RouteSettings? settings,
  51. }) : _pageBuilder = pageBuilder,
  52. _barrierDismissible = barrierDismissible,
  53. _barrierLabel = barrierLabel ?? '',
  54. _barrierColor = barrierColor,
  55. _transitionDuration = transitionDuration,
  56. _transitionBuilder = transitionBuilder,
  57. super(settings: settings);
  58. final RoutePageBuilder _pageBuilder;
  59. @override
  60. bool get barrierDismissible => _barrierDismissible;
  61. final bool _barrierDismissible;
  62. @override
  63. String get barrierLabel => _barrierLabel;
  64. final String _barrierLabel;
  65. @override
  66. Color get barrierColor => _barrierColor;
  67. final Color _barrierColor;
  68. @override
  69. Duration get transitionDuration => _transitionDuration;
  70. final Duration _transitionDuration;
  71. final RouteTransitionsBuilder? _transitionBuilder;
  72. @override
  73. Widget buildPage(BuildContext context, Animation<double> animation,
  74. Animation<double> secondaryAnimation) {
  75. return Semantics(
  76. child: _pageBuilder(context, animation, secondaryAnimation),
  77. scopesRoute: true,
  78. explicitChildNodes: true,
  79. );
  80. }
  81. @override
  82. Widget buildTransitions(BuildContext context, Animation<double> animation,
  83. Animation<double> secondaryAnimation, Widget child) {
  84. if (_transitionBuilder == null) {
  85. return FadeTransition(
  86. opacity: CurvedAnimation(parent: animation, curve: Curves.linear),
  87. child: child);
  88. } else {
  89. return _transitionBuilder!(context, animation, secondaryAnimation, child);
  90. } // Some default transition
  91. }
  92. }
  93. class StyledDialog extends StatelessWidget {
  94. final Widget child;
  95. final double? maxWidth;
  96. final double? maxHeight;
  97. final EdgeInsets? padding;
  98. final EdgeInsets? margin;
  99. final BorderRadius? borderRadius;
  100. final Color? bgColor;
  101. final bool shrinkWrap;
  102. const StyledDialog({
  103. Key? key,
  104. required this.child,
  105. this.maxWidth,
  106. this.maxHeight,
  107. this.padding,
  108. this.margin,
  109. this.bgColor,
  110. this.borderRadius,
  111. this.shrinkWrap = true,
  112. }) : super(key: key);
  113. @override
  114. Widget build(BuildContext context) {
  115. final radius = borderRadius ?? Corners.s8Border;
  116. final theme = context.watch<AppTheme>();
  117. Widget innerContent = Container(
  118. padding: padding ?? EdgeInsets.all(Insets.lGutter),
  119. color: bgColor ?? theme.surface,
  120. child: child,
  121. );
  122. if (shrinkWrap) {
  123. innerContent =
  124. IntrinsicWidth(child: IntrinsicHeight(child: innerContent));
  125. }
  126. return FocusTraversalGroup(
  127. child: Container(
  128. margin: margin ?? EdgeInsets.all(Insets.lGutter * 2),
  129. alignment: Alignment.center,
  130. child: ConstrainedBox(
  131. constraints: BoxConstraints(
  132. minWidth: DialogSize.minDialogWidth,
  133. maxHeight: maxHeight ?? double.infinity,
  134. maxWidth: maxWidth ?? double.infinity,
  135. ),
  136. child: ClipRRect(
  137. borderRadius: radius,
  138. child: SingleChildScrollView(
  139. physics: StyledScrollPhysics(),
  140. //https://medium.com/saugo360/https-medium-com-saugo360-flutter-using-overlay-to-display-floating-widgets-2e6d0e8decb9
  141. child: Material(
  142. type: MaterialType.transparency,
  143. child: innerContent,
  144. ),
  145. ),
  146. ),
  147. ),
  148. ),
  149. );
  150. }
  151. }
  152. class OkCancelDialog extends StatelessWidget {
  153. final VoidCallback? onOkPressed;
  154. final VoidCallback? onCancelPressed;
  155. final String? okTitle;
  156. final String? cancelTitle;
  157. final String? title;
  158. final String message;
  159. final double? maxWidth;
  160. const OkCancelDialog(
  161. {Key? key,
  162. this.onOkPressed,
  163. this.onCancelPressed,
  164. this.okTitle,
  165. this.cancelTitle,
  166. this.title,
  167. required this.message,
  168. this.maxWidth})
  169. : super(key: key);
  170. @override
  171. Widget build(BuildContext context) {
  172. final theme = context.watch<AppTheme>();
  173. return StyledDialog(
  174. maxWidth: maxWidth ?? 500,
  175. child: Column(
  176. crossAxisAlignment: CrossAxisAlignment.start,
  177. children: <Widget>[
  178. if (title != null) ...[
  179. Text(title!.toUpperCase(),
  180. style: TextStyles.T1.textColor(theme.accent1Darker)),
  181. VSpace(Insets.sm * 1.5),
  182. Container(color: theme.greyWeak.withOpacity(.35), height: 1),
  183. VSpace(Insets.m * 1.5),
  184. ],
  185. Text(message, style: TextStyles.Body1.textHeight(1.5)),
  186. SizedBox(height: Insets.l),
  187. OkCancelButton(
  188. onOkPressed: onOkPressed,
  189. onCancelPressed: onCancelPressed,
  190. okTitle: okTitle?.toUpperCase(),
  191. cancelTitle: cancelTitle?.toUpperCase(),
  192. )
  193. ],
  194. ),
  195. );
  196. }
  197. }