diff --git a/mobile/lib/ui/tools/free_space_page.dart b/mobile/lib/ui/tools/free_space_page.dart index a8d6a42742..cae35185e6 100644 --- a/mobile/lib/ui/tools/free_space_page.dart +++ b/mobile/lib/ui/tools/free_space_page.dart @@ -167,6 +167,14 @@ class _FreeSpacePageState extends State { Future _freeStorage(BackupStatus status) async { bool result = await deleteLocalFiles(context, status.localIDs); + + if (result == false) { + result = await deleteLocalFilesAfterRemovingAlreadyDeletedIDs( + context, + status.localIDs, + ); + } + if (result == false && Platform.isAndroid) { result = await retryFreeUpSpaceAfterRemovingNonExistingAssets(context); } diff --git a/mobile/lib/utils/delete_file_util.dart b/mobile/lib/utils/delete_file_util.dart index 0147441f7b..6e5c65a4da 100644 --- a/mobile/lib/utils/delete_file_util.dart +++ b/mobile/lib/utils/delete_file_util.dart @@ -19,6 +19,7 @@ import 'package:photos/models/file/file.dart'; import "package:photos/models/files_split.dart"; import 'package:photos/models/selected_files.dart'; import "package:photos/service_locator.dart"; +import "package:photos/services/files_service.dart"; import "package:photos/services/sync/local_sync_service.dart"; import 'package:photos/services/sync/remote_sync_service.dart'; import 'package:photos/services/sync/sync_service.dart'; @@ -326,6 +327,69 @@ Future emptyTrash(BuildContext context) async { Future deleteLocalFiles( BuildContext context, List localIDs, +) async { + final List deletedIDs = []; + final List localAssetIDs = []; + final List localSharedMediaIDs = []; + try { + for (String id in localIDs) { + if (id.startsWith(oldSharedMediaIdentifier) || + id.startsWith(sharedMediaIdentifier)) { + localSharedMediaIDs.add(id); + } else { + localAssetIDs.add(id); + } + } + deletedIDs.addAll(await _tryDeleteSharedMediaFiles(localSharedMediaIDs)); + + final bool shouldDeleteInBatches = + await isAndroidSDKVersionLowerThan(android11SDKINT); + if (shouldDeleteInBatches) { + _logger.info("Deleting in batches"); + deletedIDs + .addAll(await deleteLocalFilesInBatches(context, localAssetIDs)); + } else { + _logger.info("Deleting in one shot"); + deletedIDs + .addAll(await _deleteLocalFilesInOneShot(context, localAssetIDs)); + } + // In IOS, the library returns no error and fail to delete any file is + // there's any shared file. As a stop-gap solution, we initiate deletion in + // batches. Similar in Android, for large number of files, we have observed + // that the library fails to delete any file. So, we initiate deletion in + // batches. + if (deletedIDs.isEmpty && Platform.isIOS) { + deletedIDs.addAll( + await _iosDeleteLocalFilesInBatchesFallback(context, localAssetIDs), + ); + } + + if (deletedIDs.isNotEmpty) { + final deletedFiles = await FilesDB.instance.getLocalFiles(deletedIDs); + await FilesDB.instance.deleteLocalFiles(deletedIDs); + _logger.info(deletedFiles.length.toString() + " files deleted locally"); + Bus.instance.fire( + LocalPhotosUpdatedEvent(deletedFiles, source: "deleteLocal"), + ); + return true; + } else { + //On android 10, even if files were deleted, deletedIDs is empty. + //This is a workaround so that users are not shown an error message on + //android 10 + if (!await isAndroidSDKVersionLowerThan(android11SDKINT)) { + return false; + } + return true; + } + } catch (e, s) { + _logger.severe("Could not delete local files", e, s); + return false; + } +} + +Future deleteLocalFilesAfterRemovingAlreadyDeletedIDs( + BuildContext context, + List localIDs, ) async { final files = await FilesDB.instance.getLocalFiles(localIDs, dedupeByLocalID: true); @@ -388,7 +452,6 @@ Future deleteLocalFiles( //This is a workaround so that users are not shown an error message on //android 10 if (!await isAndroidSDKVersionLowerThan(android11SDKINT)) { - showToast(context, S.of(context).couldNotFreeUpSpace); return false; } return true; @@ -423,7 +486,7 @@ Future retryFreeUpSpaceAfterRemovingNonExistingAssets( final List deletedIDs = []; final List localAssetIDs = []; final List localSharedMediaIDs = []; - status = await SyncService.instance.getBackupStatus(); + status = await FilesService.instance.getBackupStatus(); for (String localID in status.localIDs) { if (localID.startsWith(oldSharedMediaIdentifier) ||