dialog_util.dart 7.1 KB

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