dialog_widget.dart 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import 'dart:math';
  2. import 'package:flutter/material.dart';
  3. import 'package:photos/core/constants.dart';
  4. import 'package:photos/theme/colors.dart';
  5. import 'package:photos/theme/effects.dart';
  6. import 'package:photos/theme/ente_theme.dart';
  7. import 'package:photos/ui/components/button_widget.dart';
  8. import 'package:photos/ui/components/models/button_type.dart';
  9. import 'package:photos/utils/separators_util.dart';
  10. Future<ButtonAction?> showNewChoiceDialog({
  11. required BuildContext context,
  12. required String title,
  13. required String body,
  14. required String firstButtonLabel,
  15. String secondButtonLabel = "Cancel",
  16. ButtonType firstButtonType = ButtonType.neutral,
  17. ButtonType secondButtonType = ButtonType.secondary,
  18. ButtonAction firstButtonAction = ButtonAction.first,
  19. ButtonAction secondButtonAction = ButtonAction.cancel,
  20. FutureVoidCallback? firstButtonOnTap,
  21. FutureVoidCallback? secondButtonOnTap,
  22. bool isCritical = false,
  23. IconData? icon,
  24. }) async {
  25. final buttons = [
  26. ButtonWidget(
  27. buttonType: isCritical ? ButtonType.critical : firstButtonType,
  28. labelText: firstButtonLabel,
  29. isInAlert: true,
  30. onTap: firstButtonOnTap,
  31. buttonAction: firstButtonAction,
  32. ),
  33. ButtonWidget(
  34. buttonType: secondButtonType,
  35. labelText: secondButtonLabel,
  36. isInAlert: true,
  37. onTap: secondButtonOnTap,
  38. buttonAction: secondButtonAction,
  39. ),
  40. ];
  41. return showDialogWidget(
  42. context: context,
  43. title: title,
  44. body: body,
  45. buttons: buttons,
  46. );
  47. }
  48. Future<ButtonAction?> showDialogWidget({
  49. required BuildContext context,
  50. required String title,
  51. required String body,
  52. required List<ButtonWidget> buttons,
  53. IconData? icon,
  54. }) {
  55. return showDialog(
  56. barrierDismissible: false,
  57. barrierColor: backdropFaintDark,
  58. context: context,
  59. builder: (context) {
  60. final widthOfScreen = MediaQuery.of(context).size.width;
  61. final isMobileSmall = widthOfScreen <= mobileSmallThreshold;
  62. return Padding(
  63. padding: EdgeInsets.symmetric(horizontal: isMobileSmall ? 8 : 0),
  64. child: Dialog(
  65. insetPadding: EdgeInsets.zero,
  66. child: DialogWidget(
  67. title: title,
  68. body: body,
  69. buttons: buttons,
  70. isMobileSmall: isMobileSmall,
  71. icon: icon,
  72. ),
  73. ),
  74. );
  75. },
  76. );
  77. }
  78. class DialogWidget extends StatelessWidget {
  79. final String title;
  80. final String body;
  81. final List<ButtonWidget> buttons;
  82. final IconData? icon;
  83. final bool isMobileSmall;
  84. const DialogWidget({
  85. required this.title,
  86. required this.body,
  87. required this.buttons,
  88. required this.isMobileSmall,
  89. this.icon,
  90. super.key,
  91. });
  92. @override
  93. Widget build(BuildContext context) {
  94. final widthOfScreen = MediaQuery.of(context).size.width;
  95. final colorScheme = getEnteColorScheme(context);
  96. return Container(
  97. width: min(widthOfScreen, 320),
  98. padding: isMobileSmall
  99. ? const EdgeInsets.all(0)
  100. : const EdgeInsets.fromLTRB(6, 8, 6, 6),
  101. decoration: BoxDecoration(
  102. color: colorScheme.backgroundElevated,
  103. boxShadow: shadowFloatLight,
  104. borderRadius: const BorderRadius.all(Radius.circular(8)),
  105. ),
  106. child: Padding(
  107. padding: const EdgeInsets.all(16),
  108. child: Column(
  109. mainAxisSize: MainAxisSize.min,
  110. children: [
  111. ContentContainer(
  112. title: title,
  113. body: body,
  114. icon: icon,
  115. ),
  116. const SizedBox(height: 36),
  117. Actions(buttons),
  118. ],
  119. ),
  120. ),
  121. );
  122. }
  123. }
  124. class ContentContainer extends StatelessWidget {
  125. final String title;
  126. final String body;
  127. final IconData? icon;
  128. const ContentContainer({
  129. required this.title,
  130. required this.body,
  131. this.icon,
  132. super.key,
  133. });
  134. @override
  135. Widget build(BuildContext context) {
  136. final textTheme = getEnteTextTheme(context);
  137. final colorScheme = getEnteColorScheme(context);
  138. return Column(
  139. mainAxisSize: MainAxisSize.min,
  140. crossAxisAlignment: CrossAxisAlignment.stretch,
  141. children: [
  142. icon == null
  143. ? const SizedBox.shrink()
  144. : Row(
  145. children: [
  146. Icon(
  147. icon,
  148. size: 48,
  149. ),
  150. ],
  151. ),
  152. icon == null ? const SizedBox.shrink() : const SizedBox(height: 19),
  153. Text(title, style: textTheme.h3Bold),
  154. const SizedBox(height: 19),
  155. Text(
  156. body,
  157. style: textTheme.body.copyWith(color: colorScheme.textMuted),
  158. ),
  159. ],
  160. );
  161. }
  162. }
  163. class Actions extends StatelessWidget {
  164. final List<ButtonWidget> buttons;
  165. const Actions(this.buttons, {super.key});
  166. @override
  167. Widget build(BuildContext context) {
  168. return Column(
  169. children: addSeparators(
  170. buttons,
  171. const SizedBox(
  172. height: 8,
  173. ),
  174. ),
  175. );
  176. }
  177. }