file_selection_actions_widget.dart 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. import 'package:flutter/cupertino.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:page_transition/page_transition.dart';
  4. import 'package:photos/core/configuration.dart';
  5. import 'package:photos/models/collection.dart';
  6. import 'package:photos/models/device_collection.dart';
  7. import 'package:photos/models/gallery_type.dart';
  8. import 'package:photos/models/magic_metadata.dart';
  9. import 'package:photos/models/selected_file_breakup.dart';
  10. import 'package:photos/models/selected_files.dart';
  11. import 'package:photos/services/collections_service.dart';
  12. import 'package:photos/services/hidden_service.dart';
  13. import 'package:photos/theme/ente_theme.dart';
  14. import 'package:photos/ui/actions/collection/collection_file_actions.dart';
  15. import 'package:photos/ui/actions/collection/collection_sharing_actions.dart';
  16. import 'package:photos/ui/components/blur_menu_item_widget.dart';
  17. import 'package:photos/ui/components/bottom_action_bar/expanded_menu_widget.dart';
  18. import 'package:photos/ui/create_collection_page.dart';
  19. import 'package:photos/utils/delete_file_util.dart';
  20. import 'package:photos/utils/magic_util.dart';
  21. class FileSelectionActionWidget extends StatefulWidget {
  22. final GalleryType type;
  23. final Collection? collection;
  24. final DeviceCollection? deviceCollection;
  25. final SelectedFiles selectedFiles;
  26. const FileSelectionActionWidget(
  27. this.type,
  28. this.selectedFiles, {
  29. Key? key,
  30. this.collection,
  31. this.deviceCollection,
  32. }) : super(key: key);
  33. @override
  34. State<FileSelectionActionWidget> createState() =>
  35. _FileSelectionActionWidgetState();
  36. }
  37. class _FileSelectionActionWidgetState extends State<FileSelectionActionWidget> {
  38. late int currentUserID;
  39. late SelectedFileSplit split;
  40. late CollectionActions collectionActions;
  41. @override
  42. void initState() {
  43. currentUserID = Configuration.instance.getUserID()!;
  44. split = widget.selectedFiles.split(currentUserID);
  45. widget.selectedFiles.addListener(_selectFileChangeListener);
  46. collectionActions = CollectionActions(CollectionsService.instance);
  47. super.initState();
  48. }
  49. @override
  50. void dispose() {
  51. widget.selectedFiles.removeListener(_selectFileChangeListener);
  52. super.dispose();
  53. }
  54. void _selectFileChangeListener() {
  55. split = widget.selectedFiles.split(currentUserID);
  56. if (mounted) {
  57. setState(() => {});
  58. }
  59. }
  60. @override
  61. Widget build(BuildContext context) {
  62. final bool showPrefix =
  63. split.pendingUploads.isNotEmpty || split.ownedByOtherUsers.isNotEmpty;
  64. final String suffix = showPrefix
  65. ? " (${split.ownedByCurrentUser.length})"
  66. ""
  67. : "";
  68. debugPrint('$runtimeType building $mounted');
  69. final colorScheme = getEnteColorScheme(context);
  70. final List<List<BlurMenuItemWidget>> items = [];
  71. final List<BlurMenuItemWidget> firstList = [];
  72. if (widget.type.showAddToAlbum()) {
  73. firstList.add(
  74. BlurMenuItemWidget(
  75. leadingIcon: Icons.add_outlined,
  76. labelText: "Add to album$suffix",
  77. menuItemColor: colorScheme.fillFaint,
  78. onTap: _addToAlbum,
  79. ),
  80. );
  81. }
  82. if (widget.type.showMoveToAlbum()) {
  83. firstList.add(
  84. BlurMenuItemWidget(
  85. leadingIcon: Icons.arrow_forward_outlined,
  86. labelText: "Move to album$suffix",
  87. menuItemColor: colorScheme.fillFaint,
  88. onTap: _moveFiles,
  89. ),
  90. );
  91. }
  92. if (widget.type.showRemoveFromAlbum()) {
  93. firstList.add(
  94. BlurMenuItemWidget(
  95. leadingIcon: Icons.remove_outlined,
  96. labelText: "Remove from album$suffix",
  97. menuItemColor: colorScheme.fillFaint,
  98. onTap: _removeFilesFromAlbum,
  99. ),
  100. );
  101. }
  102. if (widget.type.showDeleteOption()) {
  103. firstList.add(
  104. BlurMenuItemWidget(
  105. leadingIcon: Icons.delete_outline,
  106. labelText: "Delete$suffix",
  107. menuItemColor: colorScheme.fillFaint,
  108. onTap: _onDeleteClick,
  109. ),
  110. );
  111. }
  112. if (widget.type.showHideOption()) {
  113. firstList.add(
  114. BlurMenuItemWidget(
  115. leadingIcon: Icons.visibility_off_outlined,
  116. labelText: "Hide$suffix",
  117. menuItemColor: colorScheme.fillFaint,
  118. onTap: _onHideClick,
  119. ),
  120. );
  121. } else if (widget.type.showUnHideOption()) {
  122. firstList.add(
  123. BlurMenuItemWidget(
  124. leadingIcon: Icons.visibility_off_outlined,
  125. labelText: "Unhide$suffix",
  126. menuItemColor: colorScheme.fillFaint,
  127. onTap: _onUnhideClick,
  128. ),
  129. );
  130. }
  131. if (widget.type.showArchiveOption()) {
  132. firstList.add(
  133. BlurMenuItemWidget(
  134. leadingIcon: Icons.archive_outlined,
  135. labelText: "Archive$suffix",
  136. menuItemColor: colorScheme.fillFaint,
  137. onTap: _onArchiveClick,
  138. ),
  139. );
  140. } else if (widget.type.showUnArchiveOption()) {
  141. firstList.add(
  142. BlurMenuItemWidget(
  143. leadingIcon: Icons.unarchive_outlined,
  144. labelText: "Unarchive$suffix",
  145. menuItemColor: colorScheme.fillFaint,
  146. onTap: _onUnArchiveClick,
  147. ),
  148. );
  149. }
  150. if (widget.type.showFavoriteOption()) {
  151. firstList.add(
  152. BlurMenuItemWidget(
  153. leadingIcon: Icons.favorite_border_rounded,
  154. labelText: "Favorite$suffix",
  155. menuItemColor: colorScheme.fillFaint,
  156. onTap: _onFavoriteClick,
  157. ),
  158. );
  159. } else if (widget.type.showUnFavoriteOption()) {
  160. firstList.add(
  161. BlurMenuItemWidget(
  162. leadingIcon: Icons.favorite,
  163. labelText: "Remove from favorite$suffix",
  164. menuItemColor: colorScheme.fillFaint,
  165. onTap: _onUnFavoriteClick,
  166. ),
  167. );
  168. }
  169. if (firstList.isNotEmpty) {
  170. items.add(firstList);
  171. }
  172. return ExpandedMenuWidget(
  173. items: items,
  174. );
  175. }
  176. Future<void> _moveFiles() async {
  177. if (split.pendingUploads.isNotEmpty || split.ownedByOtherUsers.isNotEmpty) {
  178. widget.selectedFiles
  179. .unSelectAll(split.pendingUploads.toSet(), skipNotify: true);
  180. widget.selectedFiles
  181. .unSelectAll(split.ownedByOtherUsers.toSet(), skipNotify: true);
  182. }
  183. await _selectionCollectionForAction(CollectionActionType.moveFiles);
  184. }
  185. Future<void> _addToAlbum() async {
  186. if (split.ownedByOtherUsers.isNotEmpty) {
  187. widget.selectedFiles
  188. .unSelectAll(split.ownedByOtherUsers.toSet(), skipNotify: true);
  189. }
  190. await _selectionCollectionForAction(CollectionActionType.addFiles);
  191. }
  192. Future<void> _onDeleteClick() async {
  193. showDeleteSheet(context, widget.selectedFiles);
  194. }
  195. Future<void> _removeFilesFromAlbum() async {
  196. await collectionActions.showRemoveFromCollectionSheet(
  197. context,
  198. widget.collection!,
  199. widget.selectedFiles,
  200. );
  201. }
  202. Future<void> _onFavoriteClick() async {
  203. final result = await collectionActions.updateFavorites(
  204. context,
  205. split.ownedByCurrentUser,
  206. true,
  207. );
  208. if (result) {
  209. widget.selectedFiles.clearAll();
  210. }
  211. }
  212. Future<void> _onUnFavoriteClick() async {
  213. final result = await collectionActions.updateFavorites(
  214. context,
  215. split.ownedByCurrentUser,
  216. false,
  217. );
  218. if (result) {
  219. widget.selectedFiles.clearAll();
  220. }
  221. }
  222. Future<void> _onArchiveClick() async {
  223. await changeVisibility(
  224. context,
  225. split.ownedByCurrentUser,
  226. visibilityArchive,
  227. );
  228. widget.selectedFiles.clearAll();
  229. }
  230. Future<void> _onUnArchiveClick() async {
  231. await changeVisibility(
  232. context,
  233. split.ownedByCurrentUser,
  234. visibilityVisible,
  235. );
  236. widget.selectedFiles.clearAll();
  237. }
  238. Future<void> _onHideClick() async {
  239. await CollectionsService.instance.hideFiles(
  240. context,
  241. split.ownedByCurrentUser,
  242. );
  243. widget.selectedFiles.clearAll();
  244. }
  245. Future<void> _onUnhideClick() async {
  246. if (split.pendingUploads.isNotEmpty || split.ownedByOtherUsers.isNotEmpty) {
  247. widget.selectedFiles
  248. .unSelectAll(split.pendingUploads.toSet(), skipNotify: true);
  249. widget.selectedFiles
  250. .unSelectAll(split.ownedByOtherUsers.toSet(), skipNotify: true);
  251. }
  252. await _selectionCollectionForAction(CollectionActionType.unHide);
  253. }
  254. Future<Object?> _selectionCollectionForAction(
  255. CollectionActionType type,
  256. ) async {
  257. return Navigator.push(
  258. context,
  259. PageTransition(
  260. type: PageTransitionType.bottomToTop,
  261. child: CreateCollectionPage(
  262. widget.selectedFiles,
  263. null,
  264. actionType: type,
  265. ),
  266. ),
  267. );
  268. }
  269. }