dialog_util.dart 7.8 KB

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