dialog_util.dart 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. import 'dart:math';
  2. import 'package:confetti/confetti.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:photos/core/constants.dart';
  5. import 'package:photos/ui/common/loading_widget.dart';
  6. import 'package:photos/ui/common/progress_dialog.dart';
  7. import 'package:photos/ui/components/button_widget.dart';
  8. import 'package:photos/ui/components/dialog_widget.dart';
  9. import 'package:photos/ui/components/models/button_type.dart';
  10. typedef DialogBuilder = DialogWidget Function(BuildContext context);
  11. ///Will return null if dismissed by tapping outside
  12. Future<ButtonAction?> showErrorDialog(
  13. BuildContext context,
  14. String title,
  15. String? body, {
  16. bool isDismissable = true,
  17. }) async {
  18. return showDialogWidget(
  19. context: context,
  20. title: title,
  21. body: body,
  22. isDismissible: isDismissable,
  23. buttons: const [
  24. ButtonWidget(
  25. buttonType: ButtonType.secondary,
  26. labelText: "OK",
  27. isInAlert: true,
  28. buttonAction: ButtonAction.first,
  29. ),
  30. ],
  31. );
  32. }
  33. ///Will return null if dismissed by tapping outside
  34. Future<ButtonAction?> showGenericErrorDialog({
  35. required BuildContext context,
  36. bool isDismissible = true,
  37. }) async {
  38. return showDialogWidget(
  39. context: context,
  40. title: "Error",
  41. icon: Icons.error_outline_outlined,
  42. body: "It looks like something went wrong. Please try again.",
  43. isDismissible: isDismissible,
  44. buttons: const [
  45. ButtonWidget(
  46. buttonType: ButtonType.secondary,
  47. labelText: "OK",
  48. isInAlert: true,
  49. ),
  50. ],
  51. );
  52. }
  53. DialogWidget choiceDialog({
  54. required String title,
  55. String? body,
  56. required String firstButtonLabel,
  57. String secondButtonLabel = "Cancel",
  58. ButtonType firstButtonType = ButtonType.neutral,
  59. ButtonType secondButtonType = ButtonType.secondary,
  60. ButtonAction firstButtonAction = ButtonAction.first,
  61. ButtonAction secondButtonAction = ButtonAction.cancel,
  62. FutureVoidCallback? firstButtonOnTap,
  63. FutureVoidCallback? secondButtonOnTap,
  64. bool isCritical = false,
  65. IconData? icon,
  66. }) {
  67. final buttons = [
  68. ButtonWidget(
  69. buttonType: isCritical ? ButtonType.critical : firstButtonType,
  70. labelText: firstButtonLabel,
  71. isInAlert: true,
  72. onTap: firstButtonOnTap,
  73. buttonAction: firstButtonAction,
  74. ),
  75. ButtonWidget(
  76. buttonType: secondButtonType,
  77. labelText: secondButtonLabel,
  78. isInAlert: true,
  79. onTap: secondButtonOnTap,
  80. buttonAction: secondButtonAction,
  81. ),
  82. ];
  83. return DialogWidget(title: title, body: body, buttons: buttons, icon: icon);
  84. }
  85. ///Will return null if dismissed by tapping outside
  86. Future<ButtonAction?> showNewChoiceDialog({
  87. required BuildContext context,
  88. required String title,
  89. String? body,
  90. required String firstButtonLabel,
  91. String secondButtonLabel = "Cancel",
  92. ButtonType firstButtonType = ButtonType.neutral,
  93. ButtonType secondButtonType = ButtonType.secondary,
  94. ButtonAction firstButtonAction = ButtonAction.first,
  95. ButtonAction secondButtonAction = ButtonAction.cancel,
  96. FutureVoidCallback? firstButtonOnTap,
  97. FutureVoidCallback? secondButtonOnTap,
  98. bool isCritical = false,
  99. IconData? icon,
  100. bool isDismissible = true,
  101. }) async {
  102. final buttons = [
  103. ButtonWidget(
  104. buttonType: isCritical ? ButtonType.critical : firstButtonType,
  105. labelText: firstButtonLabel,
  106. isInAlert: true,
  107. onTap: firstButtonOnTap,
  108. buttonAction: firstButtonAction,
  109. ),
  110. ButtonWidget(
  111. buttonType: secondButtonType,
  112. labelText: secondButtonLabel,
  113. isInAlert: true,
  114. onTap: secondButtonOnTap,
  115. buttonAction: secondButtonAction,
  116. ),
  117. ];
  118. return showDialogWidget(
  119. context: context,
  120. title: title,
  121. body: body,
  122. buttons: buttons,
  123. icon: icon,
  124. isDismissible: isDismissible,
  125. );
  126. }
  127. ProgressDialog createProgressDialog(
  128. BuildContext context,
  129. String message, {
  130. isDismissible = false,
  131. }) {
  132. final dialog = ProgressDialog(
  133. context,
  134. type: ProgressDialogType.normal,
  135. isDismissible: isDismissible,
  136. barrierColor: Colors.black12,
  137. );
  138. dialog.style(
  139. message: message,
  140. messageTextStyle: Theme.of(context).textTheme.caption,
  141. backgroundColor: Theme.of(context).dialogTheme.backgroundColor,
  142. progressWidget: const EnteLoadingWidget(),
  143. borderRadius: 10,
  144. elevation: 10.0,
  145. insetAnimCurve: Curves.easeInOut,
  146. );
  147. return dialog;
  148. }
  149. Future<ButtonAction?> showConfettiDialog<T>({
  150. required BuildContext context,
  151. required DialogBuilder dialogBuilder,
  152. bool barrierDismissible = true,
  153. Color? barrierColor,
  154. bool useSafeArea = true,
  155. bool useRootNavigator = true,
  156. RouteSettings? routeSettings,
  157. Alignment confettiAlignment = Alignment.center,
  158. }) {
  159. final widthOfScreen = MediaQuery.of(context).size.width;
  160. final isMobileSmall = widthOfScreen <= mobileSmallThreshold;
  161. final pageBuilder = Builder(
  162. builder: dialogBuilder,
  163. );
  164. final ConfettiController confettiController =
  165. ConfettiController(duration: const Duration(seconds: 1));
  166. confettiController.play();
  167. return showDialog(
  168. context: context,
  169. builder: (BuildContext buildContext) {
  170. return Padding(
  171. padding: EdgeInsets.symmetric(horizontal: isMobileSmall ? 8 : 0),
  172. child: Stack(
  173. children: [
  174. Align(alignment: Alignment.center, child: pageBuilder),
  175. Align(
  176. alignment: confettiAlignment,
  177. child: ConfettiWidget(
  178. confettiController: confettiController,
  179. blastDirection: pi / 2,
  180. emissionFrequency: 0,
  181. numberOfParticles: 100,
  182. // a lot of particles at once
  183. gravity: 1,
  184. blastDirectionality: BlastDirectionality.explosive,
  185. ),
  186. ),
  187. ],
  188. ),
  189. );
  190. },
  191. barrierDismissible: barrierDismissible,
  192. barrierColor: barrierColor,
  193. useSafeArea: useSafeArea,
  194. useRootNavigator: useRootNavigator,
  195. routeSettings: routeSettings,
  196. );
  197. }