gallery_app_bar_widget.dart 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import 'dart:async';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:photos/core/configuration.dart';
  5. import 'package:photos/core/event_bus.dart';
  6. import 'package:photos/events/user_authenticated_event.dart';
  7. import 'package:photos/models/selected_files.dart';
  8. import 'package:photos/services/collections_service.dart';
  9. import 'package:photos/ui/email_entry_page.dart';
  10. import 'package:photos/ui/passphrase_entry_page.dart';
  11. import 'package:photos/ui/passphrase_reentry_page.dart';
  12. import 'package:photos/ui/settings_page.dart';
  13. import 'package:photos/ui/share_folder_widget.dart';
  14. import 'package:photos/utils/dialog_util.dart';
  15. import 'package:photos/utils/file_util.dart';
  16. import 'package:photos/utils/share_util.dart';
  17. enum GalleryAppBarType {
  18. homepage,
  19. local_folder,
  20. shared_collection,
  21. search_results,
  22. }
  23. class GalleryAppBarWidget extends StatefulWidget
  24. implements PreferredSizeWidget {
  25. final GalleryAppBarType type;
  26. final String title;
  27. final SelectedFiles selectedFiles;
  28. final String path;
  29. GalleryAppBarWidget(
  30. this.type,
  31. this.title,
  32. this.selectedFiles, [
  33. this.path,
  34. ]);
  35. @override
  36. _GalleryAppBarWidgetState createState() => _GalleryAppBarWidgetState();
  37. @override
  38. Size get preferredSize => Size.fromHeight(60.0);
  39. }
  40. class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
  41. StreamSubscription _userAuthEventSubscription;
  42. @override
  43. void initState() {
  44. widget.selectedFiles.addListener(() {
  45. setState(() {});
  46. });
  47. _userAuthEventSubscription =
  48. Bus.instance.on<UserAuthenticatedEvent>().listen((event) {
  49. setState(() {});
  50. });
  51. super.initState();
  52. }
  53. @override
  54. void dispose() {
  55. _userAuthEventSubscription.cancel();
  56. super.dispose();
  57. }
  58. @override
  59. Widget build(BuildContext context) {
  60. if (widget.selectedFiles.files.isEmpty) {
  61. return AppBar(
  62. title: Text(widget.title),
  63. actions: _getDefaultActions(context),
  64. );
  65. }
  66. return AppBar(
  67. leading: IconButton(
  68. icon: Icon(Icons.close),
  69. onPressed: () {
  70. _clearSelectedFiles();
  71. },
  72. ),
  73. title: Text(widget.selectedFiles.files.length.toString()),
  74. actions: _getActions(context),
  75. );
  76. }
  77. List<Widget> _getDefaultActions(BuildContext context) {
  78. List<Widget> actions = List<Widget>();
  79. if (Configuration.instance.hasConfiguredAccount()) {
  80. if (widget.type == GalleryAppBarType.homepage) {
  81. actions.add(IconButton(
  82. icon: Icon(Icons.settings),
  83. onPressed: () {
  84. Navigator.of(context).push(
  85. MaterialPageRoute(
  86. builder: (BuildContext context) {
  87. return SettingsPage();
  88. },
  89. ),
  90. );
  91. },
  92. ));
  93. } else if (widget.type == GalleryAppBarType.local_folder) {
  94. actions.add(IconButton(
  95. icon: Icon(Icons.share),
  96. onPressed: () {
  97. _showShareCollectionDialog();
  98. },
  99. ));
  100. }
  101. } else {
  102. actions.add(IconButton(
  103. icon: Icon(Icons.sync_disabled),
  104. onPressed: () {
  105. var page;
  106. if (Configuration.instance.getToken() == null) {
  107. page = EmailEntryPage();
  108. } else {
  109. // No key
  110. if (Configuration.instance.getKey() == null) {
  111. // Yet to decrypt the key
  112. page = PassphraseReentryPage();
  113. } else {
  114. // Never had a key
  115. page = PassphraseEntryPage();
  116. }
  117. }
  118. Navigator.of(context).push(
  119. MaterialPageRoute(
  120. builder: (BuildContext context) {
  121. return page;
  122. },
  123. ),
  124. );
  125. },
  126. ));
  127. }
  128. return actions;
  129. }
  130. Future<void> _showShareCollectionDialog() async {
  131. return showDialog<void>(
  132. context: context,
  133. builder: (BuildContext context) {
  134. return ShareFolderWidget(
  135. widget.title,
  136. widget.path,
  137. collection:
  138. CollectionsService.instance.getCollectionForPath(widget.path),
  139. );
  140. },
  141. );
  142. }
  143. List<Widget> _getActions(BuildContext context) {
  144. List<Widget> actions = List<Widget>();
  145. if (widget.selectedFiles.files.isNotEmpty) {
  146. if (widget.type != GalleryAppBarType.shared_collection &&
  147. widget.type != GalleryAppBarType.search_results) {
  148. actions.add(IconButton(
  149. icon: Icon(Icons.delete),
  150. onPressed: () {
  151. _showDeleteSheet(context);
  152. },
  153. ));
  154. }
  155. actions.add(IconButton(
  156. icon: Icon(Icons.share),
  157. onPressed: () {
  158. _shareSelected(context);
  159. },
  160. ));
  161. }
  162. return actions;
  163. }
  164. void _shareSelected(BuildContext context) {
  165. shareMultiple(context, widget.selectedFiles.files.toList());
  166. }
  167. void _showDeleteSheet(BuildContext context) {
  168. final action = CupertinoActionSheet(
  169. title: Text("Delete file?"),
  170. actions: <Widget>[
  171. CupertinoActionSheetAction(
  172. child: Text("Delete"),
  173. isDestructiveAction: true,
  174. onPressed: () async {
  175. await _deleteSelected();
  176. },
  177. ),
  178. ],
  179. cancelButton: CupertinoActionSheetAction(
  180. child: Text("Cancel"),
  181. onPressed: () {
  182. Navigator.of(context, rootNavigator: true).pop();
  183. },
  184. ),
  185. );
  186. showCupertinoModalPopup(context: context, builder: (_) => action);
  187. }
  188. _deleteSelected() async {
  189. Navigator.of(context, rootNavigator: true).pop();
  190. final dialog = createProgressDialog(context, "Deleting...");
  191. await dialog.show();
  192. await deleteFiles(widget.selectedFiles.files.toList());
  193. _clearSelectedFiles();
  194. await dialog.hide();
  195. }
  196. void _clearSelectedFiles() {
  197. widget.selectedFiles.clearAll();
  198. }
  199. }