action_sheet_widget.dart 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import 'dart:ui';
  2. import 'package:flutter/material.dart';
  3. import 'package:modal_bottom_sheet/modal_bottom_sheet.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/utils/separators_util.dart';
  8. enum ActionSheetType {
  9. defaultActionSheet,
  10. iconOnly,
  11. }
  12. void showActionSheet({
  13. required BuildContext context,
  14. required List<Widget> buttons,
  15. required ActionSheetType actionSheetType,
  16. bool isCheckIconGreen = false,
  17. String? title,
  18. String? body,
  19. }) {
  20. showMaterialModalBottomSheet(
  21. backgroundColor: Colors.transparent,
  22. barrierColor: backdropMutedDark,
  23. useRootNavigator: true,
  24. context: context,
  25. builder: (_) {
  26. return ActionSheetWidget(
  27. title: title,
  28. body: body,
  29. actionButtons: buttons,
  30. actionSheetType: actionSheetType,
  31. isCheckIconGreen: isCheckIconGreen,
  32. );
  33. },
  34. );
  35. }
  36. class ActionSheetWidget extends StatelessWidget {
  37. final String? title;
  38. final String? body;
  39. final List<Widget> actionButtons;
  40. final ActionSheetType actionSheetType;
  41. final bool isCheckIconGreen;
  42. const ActionSheetWidget({
  43. required this.actionButtons,
  44. required this.actionSheetType,
  45. required this.isCheckIconGreen,
  46. this.title,
  47. this.body,
  48. super.key,
  49. });
  50. @override
  51. Widget build(BuildContext context) {
  52. final isTitleAndBodyNull = title == null && body == null;
  53. final blur = MediaQuery.of(context).platformBrightness == Brightness.light
  54. ? blurMuted
  55. : blurBase;
  56. return Padding(
  57. padding: const EdgeInsets.fromLTRB(12, 12, 12, 32),
  58. child: Container(
  59. decoration: BoxDecoration(boxShadow: shadowMenuLight),
  60. child: ClipRRect(
  61. borderRadius: const BorderRadius.all(Radius.circular(8)),
  62. child: BackdropFilter(
  63. filter: ImageFilter.blur(sigmaX: blur, sigmaY: blur),
  64. child: Container(
  65. color: backdropBaseDark,
  66. child: Padding(
  67. padding: EdgeInsets.fromLTRB(
  68. 24,
  69. 24,
  70. 24,
  71. isTitleAndBodyNull ? 24 : 28,
  72. ),
  73. child: Column(
  74. mainAxisSize: MainAxisSize.min,
  75. children: [
  76. isTitleAndBodyNull
  77. ? const SizedBox.shrink()
  78. : Padding(
  79. padding: const EdgeInsets.only(bottom: 36),
  80. child: ContentContainerWidget(
  81. title: title,
  82. body: body,
  83. actionSheetType: actionSheetType,
  84. isCheckIconGreen: isCheckIconGreen,
  85. ),
  86. ),
  87. ActionButtons(
  88. actionButtons,
  89. ),
  90. ],
  91. ),
  92. ),
  93. ),
  94. ),
  95. ),
  96. ),
  97. );
  98. }
  99. }
  100. class ContentContainerWidget extends StatelessWidget {
  101. final String? title;
  102. final String? body;
  103. final ActionSheetType actionSheetType;
  104. final bool isCheckIconGreen;
  105. const ContentContainerWidget({
  106. required this.actionSheetType,
  107. required this.isCheckIconGreen,
  108. this.title,
  109. this.body,
  110. super.key,
  111. });
  112. @override
  113. Widget build(BuildContext context) {
  114. final textTheme = getEnteTextTheme(context);
  115. return Column(
  116. mainAxisSize: MainAxisSize.min,
  117. //todo: set cross axis to center when icon should be shown in place of body
  118. crossAxisAlignment: actionSheetType == ActionSheetType.defaultActionSheet
  119. ? CrossAxisAlignment.stretch
  120. : CrossAxisAlignment.center,
  121. children: [
  122. title == null
  123. ? const SizedBox.shrink()
  124. : Text(
  125. title!,
  126. style: textTheme.h3Bold
  127. .copyWith(color: textBaseDark), //constant color
  128. ),
  129. title == null || body == null
  130. ? const SizedBox.shrink()
  131. : const SizedBox(height: 19),
  132. actionSheetType == ActionSheetType.defaultActionSheet
  133. ? body == null
  134. ? const SizedBox.shrink()
  135. : Text(
  136. body!,
  137. style: textTheme.body
  138. .copyWith(color: textMutedDark), //constant color
  139. )
  140. : Icon(Icons.check_outlined,
  141. size: 48,
  142. color: isCheckIconGreen
  143. ? getEnteColorScheme(context).primary700
  144. : strokeBaseDark)
  145. ],
  146. );
  147. }
  148. }
  149. class ActionButtons extends StatelessWidget {
  150. final List<Widget> actionButtons;
  151. const ActionButtons(this.actionButtons, {super.key});
  152. @override
  153. Widget build(BuildContext context) {
  154. final actionButtonsWithSeparators = actionButtons;
  155. return Column(
  156. children:
  157. //Separator height is 8pts in figma. -2pts here as the action
  158. //buttons are 2pts extra in height in code compared to figma because
  159. //of the border(1pt top + 1pt bottom) of action buttons.
  160. addSeparators(actionButtonsWithSeparators, const SizedBox(height: 6)),
  161. );
  162. }
  163. }