magic_util.dart 4.7 KB

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