bottom_action_bar_widget.dart 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import 'dart:ui';
  2. import 'package:expandable/expandable.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:photos/models/selected_files.dart';
  5. import 'package:photos/theme/effects.dart';
  6. import 'package:photos/theme/ente_theme.dart';
  7. import 'package:photos/ui/components/bottom_action_bar/action_bar_widget.dart';
  8. import 'package:photos/ui/components/icon_button_widget.dart';
  9. import 'package:photos/ui/settings/common_settings.dart';
  10. class BottomActionBarWidget extends StatelessWidget {
  11. final String? text;
  12. final List<Widget>? iconButtons;
  13. final Widget expandedMenu;
  14. final SelectedFiles? selectedFiles;
  15. final VoidCallback? onCancel;
  16. BottomActionBarWidget({
  17. required this.expandedMenu,
  18. this.selectedFiles,
  19. this.text,
  20. this.iconButtons,
  21. this.onCancel,
  22. super.key,
  23. });
  24. final ExpandableController _expandableController =
  25. ExpandableController(initialExpanded: false);
  26. @override
  27. @override
  28. Widget build(BuildContext context) {
  29. final colorScheme = getEnteColorScheme(context);
  30. final textTheme = getEnteTextTheme(context);
  31. //todo : restrict width of column
  32. return ClipRRect(
  33. child: BackdropFilter(
  34. filter: ImageFilter.blur(sigmaX: blurBase, sigmaY: blurBase),
  35. child: Container(
  36. color: colorScheme.backdropBase,
  37. padding: const EdgeInsets.only(
  38. top: 4,
  39. // bottom: !_expandableController.expanded &&
  40. // ((widget.selectedFiles?.files.isNotEmpty) ?? false)
  41. // ? 24
  42. // : 36,
  43. bottom: 24,
  44. ),
  45. child: Column(
  46. mainAxisSize: MainAxisSize.min,
  47. children: [
  48. ExpandableNotifier(
  49. controller: _expandableController,
  50. child: ExpandablePanel(
  51. theme: getExpandableTheme(context),
  52. header: Padding(
  53. padding: EdgeInsets.symmetric(
  54. horizontal: text == null ? 12 : 0,
  55. ),
  56. child: ActionBarWidget(
  57. selectedFiles: selectedFiles,
  58. text: text,
  59. iconButtons: _iconButtons(),
  60. ),
  61. ),
  62. expanded: expandedMenu,
  63. collapsed: const SizedBox.shrink(),
  64. controller: _expandableController,
  65. ),
  66. ),
  67. GestureDetector(
  68. onTap: () {
  69. //unselect all files here
  70. //or collapse the expansion panel
  71. onCancel?.call();
  72. _expandableController.value = false;
  73. },
  74. child: Container(
  75. width: double.infinity,
  76. padding: const EdgeInsets.symmetric(
  77. horizontal: 16,
  78. vertical: 14,
  79. ),
  80. child: Center(
  81. child: Text(
  82. "Cancel",
  83. style: textTheme.bodyBold
  84. .copyWith(color: colorScheme.blurTextBase),
  85. ),
  86. ),
  87. ),
  88. )
  89. ],
  90. ),
  91. ),
  92. ),
  93. );
  94. }
  95. List<Widget> _iconButtons() {
  96. final iconButtonsWithExpansionIcon = <Widget?>[
  97. ...?iconButtons,
  98. ExpansionIconWidget(expandableController: _expandableController)
  99. ];
  100. iconButtonsWithExpansionIcon.removeWhere((element) => element == null);
  101. return iconButtonsWithExpansionIcon as List<Widget>;
  102. }
  103. }
  104. class ExpansionIconWidget extends StatefulWidget {
  105. final ExpandableController expandableController;
  106. const ExpansionIconWidget({required this.expandableController, super.key});
  107. @override
  108. State<ExpansionIconWidget> createState() => _ExpansionIconWidgetState();
  109. }
  110. class _ExpansionIconWidgetState extends State<ExpansionIconWidget> {
  111. @override
  112. void initState() {
  113. widget.expandableController.addListener(_expandableListener);
  114. super.initState();
  115. }
  116. @override
  117. void dispose() {
  118. widget.expandableController.removeListener(_expandableListener);
  119. super.dispose();
  120. }
  121. @override
  122. Widget build(BuildContext context) {
  123. return AnimatedSwitcher(
  124. duration: const Duration(milliseconds: 200),
  125. switchInCurve: Curves.easeInOutExpo,
  126. child: widget.expandableController.value
  127. ? IconButtonWidget(
  128. key: const ValueKey<bool>(false),
  129. onTap: () {
  130. widget.expandableController.value = false;
  131. setState(() {});
  132. },
  133. icon: Icons.expand_more_outlined,
  134. iconButtonType: IconButtonType.primary,
  135. )
  136. : IconButtonWidget(
  137. key: const ValueKey<bool>(true),
  138. onTap: () {
  139. widget.expandableController.value = true;
  140. setState(() {});
  141. },
  142. icon: Icons.more_horiz_outlined,
  143. iconButtonType: IconButtonType.primary,
  144. ),
  145. );
  146. }
  147. _expandableListener() {
  148. if (mounted) {
  149. setState(() {});
  150. }
  151. }
  152. }