file_actions.dart 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import "package:flutter/cupertino.dart";
  2. import "package:modal_bottom_sheet/modal_bottom_sheet.dart";
  3. import "package:photos/models/file.dart";
  4. import "package:photos/models/file_type.dart";
  5. import "package:photos/theme/colors.dart";
  6. import "package:photos/theme/ente_theme.dart";
  7. import "package:photos/ui/components/action_sheet_widget.dart";
  8. import "package:photos/ui/components/button_widget.dart";
  9. import "package:photos/ui/components/models/button_type.dart";
  10. import "package:photos/ui/viewer/file/file_info_widget.dart";
  11. import "package:photos/utils/delete_file_util.dart";
  12. import "package:photos/utils/dialog_util.dart";
  13. import "package:photos/utils/toast_util.dart";
  14. Future<void> showSingleFileDeleteSheet(
  15. BuildContext context,
  16. File file, {
  17. Function(File)? onFileRemoved,
  18. }) async {
  19. final List<ButtonWidget> buttons = [];
  20. final String fileType = file.fileType == FileType.video ? "video" : "photo";
  21. final bool isBothLocalAndRemote =
  22. file.uploadedFileID != null && file.localID != null;
  23. final bool isLocalOnly = file.uploadedFileID == null && file.localID != null;
  24. final bool isRemoteOnly = file.uploadedFileID != null && file.localID == null;
  25. const String bodyHighlight = "It will be deleted from all albums.";
  26. String body = "";
  27. if (isBothLocalAndRemote) {
  28. body = "This $fileType is in both ente and your device.";
  29. } else if (isRemoteOnly) {
  30. body = "This $fileType will be deleted from ente.";
  31. } else if (isLocalOnly) {
  32. body = "This $fileType will be deleted from your device.";
  33. } else {
  34. throw AssertionError("Unexpected state");
  35. }
  36. // Add option to delete from ente
  37. if (isBothLocalAndRemote || isRemoteOnly) {
  38. buttons.add(
  39. ButtonWidget(
  40. labelText: isBothLocalAndRemote ? "Delete from ente" : "Yes, delete",
  41. buttonType: ButtonType.neutral,
  42. buttonSize: ButtonSize.large,
  43. shouldStickToDarkTheme: true,
  44. buttonAction: ButtonAction.first,
  45. shouldSurfaceExecutionStates: true,
  46. isInAlert: true,
  47. onTap: () async {
  48. await deleteFilesFromRemoteOnly(context, [file]);
  49. showShortToast(context, "Moved to trash");
  50. if (isRemoteOnly) {
  51. Navigator.of(context, rootNavigator: true).pop();
  52. if (onFileRemoved != null) {
  53. onFileRemoved(file);
  54. }
  55. }
  56. },
  57. ),
  58. );
  59. }
  60. // Add option to delete from local
  61. if (isBothLocalAndRemote || isLocalOnly) {
  62. buttons.add(
  63. ButtonWidget(
  64. labelText: isBothLocalAndRemote ? "Delete from device" : "Yes, delete",
  65. buttonType: ButtonType.neutral,
  66. buttonSize: ButtonSize.large,
  67. shouldStickToDarkTheme: true,
  68. buttonAction: ButtonAction.second,
  69. shouldSurfaceExecutionStates: false,
  70. isInAlert: true,
  71. onTap: () async {
  72. await deleteFilesOnDeviceOnly(context, [file]);
  73. if (isLocalOnly) {
  74. Navigator.of(context, rootNavigator: true).pop();
  75. if (onFileRemoved != null) {
  76. onFileRemoved(file);
  77. }
  78. }
  79. },
  80. ),
  81. );
  82. }
  83. if (isBothLocalAndRemote) {
  84. buttons.add(
  85. ButtonWidget(
  86. labelText: "Delete from both",
  87. buttonType: ButtonType.neutral,
  88. buttonSize: ButtonSize.large,
  89. shouldStickToDarkTheme: true,
  90. buttonAction: ButtonAction.third,
  91. shouldSurfaceExecutionStates: true,
  92. isInAlert: true,
  93. onTap: () async {
  94. await deleteFilesFromEverywhere(context, [file]);
  95. Navigator.of(context, rootNavigator: true).pop();
  96. if (onFileRemoved != null) {
  97. onFileRemoved(file);
  98. }
  99. },
  100. ),
  101. );
  102. }
  103. buttons.add(
  104. const ButtonWidget(
  105. labelText: "Cancel",
  106. buttonType: ButtonType.secondary,
  107. buttonSize: ButtonSize.large,
  108. shouldStickToDarkTheme: true,
  109. buttonAction: ButtonAction.fourth,
  110. isInAlert: true,
  111. ),
  112. );
  113. final actionResult = await showActionSheet(
  114. context: context,
  115. buttons: buttons,
  116. actionSheetType: ActionSheetType.defaultActionSheet,
  117. body: body,
  118. bodyHighlight: bodyHighlight,
  119. );
  120. if (actionResult?.action != null &&
  121. actionResult!.action == ButtonAction.error) {
  122. showGenericErrorDialog(context: context);
  123. }
  124. }
  125. Future<void> showInfoSheet(BuildContext context, File file) async {
  126. final colorScheme = getEnteColorScheme(context);
  127. return showBarModalBottomSheet(
  128. topControl: const SizedBox.shrink(),
  129. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0)),
  130. backgroundColor: colorScheme.backgroundElevated,
  131. barrierColor: backdropFaintDark,
  132. context: context,
  133. builder: (BuildContext context) {
  134. return Padding(
  135. padding:
  136. EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
  137. child: FileInfoWidget(file),
  138. );
  139. },
  140. );
  141. }