dialog_util.dart 7.3 KB

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