magic_util.dart 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import 'package:flutter/material.dart';
  2. import 'package:logging/logging.dart';
  3. import 'package:path/path.dart';
  4. import 'package:photos/core/event_bus.dart';
  5. import 'package:photos/events/force_reload_home_gallery_event.dart';
  6. import 'package:photos/models/collection.dart';
  7. import 'package:photos/models/file.dart';
  8. import 'package:photos/models/magic_metadata.dart';
  9. import 'package:photos/services/collections_service.dart';
  10. import 'package:photos/services/file_magic_service.dart';
  11. import 'package:photos/ui/common/progress_dialog.dart';
  12. import 'package:photos/ui/common/rename_dialog.dart';
  13. import 'package:photos/utils/dialog_util.dart';
  14. import 'package:photos/utils/toast_util.dart';
  15. final _logger = Logger('MagicUtil');
  16. Future<void> changeVisibility(
  17. BuildContext context,
  18. List<File> files,
  19. int newVisibility,
  20. ) async {
  21. final dialog = createProgressDialog(
  22. context,
  23. newVisibility == visibilityArchive
  24. ? "Archiving..."
  25. : "Unarchiving..."
  26. "...",
  27. );
  28. await dialog.show();
  29. try {
  30. await FileMagicService.instance.changeVisibility(files, newVisibility);
  31. showShortToast(
  32. context,
  33. newVisibility == visibilityArchive
  34. ? "Successfully archived"
  35. : "Successfully unarchived",
  36. );
  37. await dialog.hide();
  38. } catch (e, s) {
  39. _logger.severe("failed to update file visibility", e, s);
  40. await dialog.hide();
  41. rethrow;
  42. }
  43. }
  44. Future<void> changeCollectionVisibility(
  45. BuildContext context,
  46. Collection collection,
  47. int newVisibility,
  48. ) async {
  49. final dialog = createProgressDialog(
  50. context,
  51. newVisibility == visibilityArchive ? "Archiving..." : "Unarchiving...",
  52. );
  53. await dialog.show();
  54. try {
  55. final Map<String, dynamic> update = {magicKeyVisibility: newVisibility};
  56. await CollectionsService.instance.updateMagicMetadata(collection, update);
  57. // Force reload home gallery to pull in the now unarchived files
  58. Bus.instance.fire(ForceReloadHomeGalleryEvent("CollectionArchiveChange"));
  59. showShortToast(
  60. context,
  61. newVisibility == visibilityArchive
  62. ? "Successfully archived"
  63. : "Successfully unarchived",
  64. );
  65. await dialog.hide();
  66. } catch (e, s) {
  67. _logger.severe("failed to update collection visibility", e, s);
  68. await dialog.hide();
  69. rethrow;
  70. }
  71. }
  72. Future<bool> editTime(
  73. BuildContext context,
  74. List<File> files,
  75. int editedTime,
  76. ) async {
  77. try {
  78. await _updatePublicMetadata(
  79. context,
  80. files,
  81. pubMagicKeyEditedTime,
  82. editedTime,
  83. );
  84. return true;
  85. } catch (e) {
  86. showShortToast(context, 'something went wrong');
  87. return false;
  88. }
  89. }
  90. Future<bool> editFilename(
  91. BuildContext context,
  92. File file,
  93. ) async {
  94. try {
  95. final fileName = file.displayName;
  96. final nameWithoutExt = basenameWithoutExtension(fileName);
  97. final extName = extension(fileName);
  98. var result = await showDialog<String>(
  99. context: context,
  100. builder: (BuildContext context) {
  101. return RenameDialog(nameWithoutExt, 'file', maxLength: 50);
  102. },
  103. barrierColor: Colors.black.withOpacity(0.85),
  104. );
  105. if (result == null || result.trim() == nameWithoutExt.trim()) {
  106. return true;
  107. }
  108. result = result + extName;
  109. await _updatePublicMetadata(
  110. context,
  111. List.of([file]),
  112. pubMagicKeyEditedName,
  113. result,
  114. );
  115. return true;
  116. } catch (e) {
  117. showShortToast(context, 'Something went wrong');
  118. return false;
  119. }
  120. }
  121. Future<bool> editFileCaption(
  122. BuildContext? context,
  123. File file,
  124. String caption,
  125. ) async {
  126. try {
  127. await _updatePublicMetadata(
  128. context,
  129. [file],
  130. pubMagicKeyCaption,
  131. caption,
  132. showDoneToast: false,
  133. );
  134. return true;
  135. } catch (e) {
  136. if (context != null) {
  137. showShortToast(context, "Something went wrong");
  138. }
  139. return false;
  140. }
  141. }
  142. Future<void> _updatePublicMetadata(
  143. BuildContext? context,
  144. List<File> files,
  145. String key,
  146. dynamic value, {
  147. bool showDoneToast = true,
  148. }) async {
  149. if (files.isEmpty) {
  150. return;
  151. }
  152. ProgressDialog? dialog;
  153. if (context != null) {
  154. dialog = createProgressDialog(context, 'Please wait...');
  155. await dialog.show();
  156. }
  157. try {
  158. final Map<String, dynamic> update = {key: value};
  159. await FileMagicService.instance.updatePublicMagicMetadata(files, update);
  160. if (context != null) {
  161. if (showDoneToast) {
  162. showShortToast(context, 'Done');
  163. }
  164. await dialog?.hide();
  165. }
  166. if (_shouldReloadGallery(key)) {
  167. Bus.instance.fire(ForceReloadHomeGalleryEvent("FileMetadataChange-$key"));
  168. }
  169. } catch (e, s) {
  170. _logger.severe("failed to update $key = $value", e, s);
  171. if (context != null) {
  172. await dialog?.hide();
  173. }
  174. rethrow;
  175. }
  176. }
  177. bool _shouldReloadGallery(String key) {
  178. return key == pubMagicKeyEditedTime;
  179. }