2022-12-15 10:02:46 +00:00
|
|
|
import 'package:flutter/cupertino.dart';
|
2023-08-21 06:50:34 +00:00
|
|
|
import "package:photo_manager/photo_manager.dart";
|
2023-06-27 11:26:16 +00:00
|
|
|
import "package:photos/core/configuration.dart";
|
2023-06-28 04:51:14 +00:00
|
|
|
import "package:photos/core/event_bus.dart";
|
2023-06-27 11:26:16 +00:00
|
|
|
import "package:photos/db/files_db.dart";
|
2023-06-28 04:51:14 +00:00
|
|
|
import "package:photos/events/collection_updated_event.dart";
|
2023-04-05 07:50:02 +00:00
|
|
|
import "package:photos/generated/l10n.dart";
|
2023-08-25 04:39:30 +00:00
|
|
|
import 'package:photos/models/collection/collection.dart';
|
|
|
|
import 'package:photos/models/file/file.dart';
|
2022-12-15 10:02:46 +00:00
|
|
|
import 'package:photos/models/selected_files.dart';
|
2023-06-27 11:26:16 +00:00
|
|
|
import "package:photos/services/collections_service.dart";
|
2022-12-15 10:02:46 +00:00
|
|
|
import 'package:photos/services/favorites_service.dart';
|
2023-06-28 06:26:43 +00:00
|
|
|
import "package:photos/services/hidden_service.dart";
|
2023-06-27 11:26:16 +00:00
|
|
|
import "package:photos/services/ignored_files_service.dart";
|
|
|
|
import "package:photos/services/remote_sync_service.dart";
|
2022-12-15 10:02:46 +00:00
|
|
|
import 'package:photos/ui/actions/collection/collection_sharing_actions.dart';
|
|
|
|
import 'package:photos/ui/common/progress_dialog.dart';
|
2023-01-05 11:17:34 +00:00
|
|
|
import 'package:photos/ui/components/action_sheet_widget.dart';
|
2023-03-10 08:08:51 +00:00
|
|
|
import 'package:photos/ui/components/buttons/button_widget.dart';
|
2023-01-05 11:17:34 +00:00
|
|
|
import 'package:photos/ui/components/models/button_type.dart';
|
2022-12-15 10:02:46 +00:00
|
|
|
import 'package:photos/utils/dialog_util.dart';
|
2023-06-28 06:26:43 +00:00
|
|
|
import "package:photos/utils/file_uploader.dart";
|
2023-06-27 11:26:16 +00:00
|
|
|
import "package:photos/utils/share_util.dart";
|
2022-12-15 10:02:46 +00:00
|
|
|
import 'package:photos/utils/toast_util.dart';
|
2023-06-27 11:26:16 +00:00
|
|
|
import "package:receive_sharing_intent/receive_sharing_intent.dart";
|
2022-12-15 10:02:46 +00:00
|
|
|
|
|
|
|
extension CollectionFileActions on CollectionActions {
|
2023-01-05 11:17:34 +00:00
|
|
|
Future<void> showRemoveFromCollectionSheetV2(
|
|
|
|
BuildContext bContext,
|
|
|
|
Collection collection,
|
|
|
|
SelectedFiles selectedFiles,
|
2023-08-28 12:57:38 +00:00
|
|
|
bool removingOthersFile, {
|
|
|
|
bool isHidden = false,
|
|
|
|
}) async {
|
2023-01-05 11:17:34 +00:00
|
|
|
final actionResult = await showActionSheet(
|
|
|
|
context: bContext,
|
|
|
|
buttons: [
|
|
|
|
ButtonWidget(
|
2023-04-05 07:50:02 +00:00
|
|
|
labelText: S.of(bContext).remove,
|
2023-02-03 00:14:49 +00:00
|
|
|
buttonType:
|
|
|
|
removingOthersFile ? ButtonType.critical : ButtonType.neutral,
|
2023-01-05 11:17:34 +00:00
|
|
|
buttonSize: ButtonSize.large,
|
|
|
|
shouldStickToDarkTheme: true,
|
|
|
|
isInAlert: true,
|
|
|
|
onTap: () async {
|
2023-01-12 04:18:57 +00:00
|
|
|
try {
|
|
|
|
await moveFilesFromCurrentCollection(
|
|
|
|
bContext,
|
|
|
|
collection,
|
|
|
|
selectedFiles.files,
|
2023-08-28 12:57:38 +00:00
|
|
|
isHidden: isHidden,
|
2023-01-12 04:18:57 +00:00
|
|
|
);
|
|
|
|
} catch (e) {
|
|
|
|
logger.severe("Failed to move files", e);
|
|
|
|
rethrow;
|
|
|
|
}
|
2023-01-05 11:17:34 +00:00
|
|
|
},
|
|
|
|
),
|
2023-04-05 07:50:02 +00:00
|
|
|
ButtonWidget(
|
|
|
|
labelText: S.of(bContext).cancel,
|
2023-01-05 11:17:34 +00:00
|
|
|
buttonType: ButtonType.secondary,
|
|
|
|
buttonSize: ButtonSize.large,
|
|
|
|
buttonAction: ButtonAction.second,
|
|
|
|
shouldStickToDarkTheme: true,
|
|
|
|
isInAlert: true,
|
|
|
|
),
|
|
|
|
],
|
2023-04-07 03:37:57 +00:00
|
|
|
title: removingOthersFile ? S.of(bContext).removeFromAlbumTitle : null,
|
2023-02-03 00:14:49 +00:00
|
|
|
body: removingOthersFile
|
2023-04-05 07:50:02 +00:00
|
|
|
? S.of(bContext).removeShareItemsWarning
|
|
|
|
: S.of(bContext).itemsWillBeRemovedFromAlbum,
|
2023-01-05 11:17:34 +00:00
|
|
|
actionSheetType: ActionSheetType.defaultActionSheet,
|
|
|
|
);
|
2023-02-09 13:18:01 +00:00
|
|
|
if (actionResult?.action != null &&
|
|
|
|
actionResult!.action == ButtonAction.error) {
|
2023-01-05 11:17:34 +00:00
|
|
|
showGenericErrorDialog(context: bContext);
|
|
|
|
} else {
|
|
|
|
selectedFiles.clearAll();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-27 11:26:16 +00:00
|
|
|
Future<bool> addToCollection(
|
|
|
|
BuildContext context,
|
|
|
|
int collectionID,
|
|
|
|
bool showProgressDialog, {
|
2023-08-24 16:56:24 +00:00
|
|
|
List<EnteFile>? selectedFiles,
|
2023-06-27 11:26:16 +00:00
|
|
|
List<SharedMediaFile>? sharedFiles,
|
2023-08-21 06:50:34 +00:00
|
|
|
List<AssetEntity>? picketAssets,
|
2023-06-27 11:26:16 +00:00
|
|
|
}) async {
|
2023-06-28 06:26:43 +00:00
|
|
|
ProgressDialog? dialog = showProgressDialog
|
2023-06-27 11:26:16 +00:00
|
|
|
? createProgressDialog(
|
|
|
|
context,
|
|
|
|
S.of(context).uploadingFilesToAlbum,
|
|
|
|
isDismissible: true,
|
|
|
|
)
|
|
|
|
: null;
|
|
|
|
await dialog?.show();
|
|
|
|
try {
|
2023-08-24 16:56:24 +00:00
|
|
|
final List<EnteFile> files = [];
|
|
|
|
final List<EnteFile> filesPendingUpload = [];
|
2023-06-27 11:26:16 +00:00
|
|
|
final int currentUserID = Configuration.instance.getUserID()!;
|
|
|
|
if (sharedFiles != null) {
|
|
|
|
filesPendingUpload.addAll(
|
|
|
|
await convertIncomingSharedMediaToFile(
|
|
|
|
sharedFiles,
|
|
|
|
collectionID,
|
|
|
|
),
|
|
|
|
);
|
2023-08-21 06:50:34 +00:00
|
|
|
} else if (picketAssets != null) {
|
2023-06-28 04:51:14 +00:00
|
|
|
filesPendingUpload.addAll(
|
2023-08-21 06:50:34 +00:00
|
|
|
await convertPicketAssets(
|
|
|
|
picketAssets,
|
2023-06-28 04:51:14 +00:00
|
|
|
collectionID,
|
|
|
|
),
|
|
|
|
);
|
2023-06-27 11:26:16 +00:00
|
|
|
} else {
|
|
|
|
for (final file in selectedFiles!) {
|
2023-08-24 16:56:24 +00:00
|
|
|
EnteFile? currentFile;
|
2023-06-27 11:26:16 +00:00
|
|
|
if (file.uploadedFileID != null) {
|
|
|
|
currentFile = file;
|
|
|
|
} else if (file.generatedID != null) {
|
|
|
|
// when file is not uploaded, refresh the state from the db to
|
|
|
|
// ensure we have latest upload status for given file before
|
|
|
|
// queueing it up as pending upload
|
|
|
|
currentFile = await (FilesDB.instance.getFile(file.generatedID!));
|
|
|
|
} else if (file.generatedID == null) {
|
|
|
|
logger.severe("generated id should not be null");
|
|
|
|
}
|
|
|
|
if (currentFile == null) {
|
|
|
|
logger.severe("Failed to find fileBy genID");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (currentFile.uploadedFileID == null) {
|
|
|
|
currentFile.collectionID = collectionID;
|
|
|
|
filesPendingUpload.add(currentFile);
|
|
|
|
} else {
|
|
|
|
files.add(currentFile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (filesPendingUpload.isNotEmpty) {
|
|
|
|
// Newly created collection might not be cached
|
|
|
|
final Collection? c =
|
|
|
|
CollectionsService.instance.getCollectionByID(collectionID);
|
|
|
|
if (c != null && c.owner!.id != currentUserID) {
|
2023-06-28 06:26:43 +00:00
|
|
|
if (!showProgressDialog) {
|
|
|
|
dialog = createProgressDialog(
|
|
|
|
context,
|
|
|
|
S.of(context).uploadingFilesToAlbum,
|
|
|
|
isDismissible: true,
|
|
|
|
);
|
|
|
|
await dialog.show();
|
|
|
|
}
|
|
|
|
final Collection uncat =
|
|
|
|
await CollectionsService.instance.getUncategorizedCollection();
|
2023-08-24 16:56:24 +00:00
|
|
|
for (EnteFile unuploadedFile in filesPendingUpload) {
|
2023-06-28 06:26:43 +00:00
|
|
|
final uploadedFile = await FileUploader.instance.forceUpload(
|
|
|
|
unuploadedFile,
|
|
|
|
uncat.id,
|
|
|
|
);
|
|
|
|
files.add(uploadedFile);
|
|
|
|
}
|
2023-06-27 11:26:16 +00:00
|
|
|
} else {
|
2023-08-28 12:57:38 +00:00
|
|
|
for (final file in filesPendingUpload) {
|
2023-08-21 06:50:34 +00:00
|
|
|
file.collectionID = collectionID;
|
|
|
|
}
|
2023-06-27 11:26:16 +00:00
|
|
|
// filesPendingUpload might be getting ignored during auto-upload
|
|
|
|
// because the user deleted these files from ente in the past.
|
|
|
|
await IgnoredFilesService.instance
|
|
|
|
.removeIgnoredMappings(filesPendingUpload);
|
|
|
|
await FilesDB.instance.insertMultiple(filesPendingUpload);
|
2023-06-28 04:51:14 +00:00
|
|
|
Bus.instance.fire(
|
|
|
|
CollectionUpdatedEvent(
|
|
|
|
collectionID,
|
|
|
|
filesPendingUpload,
|
|
|
|
"pendingFilesAdd",
|
|
|
|
),
|
|
|
|
);
|
2023-06-27 11:26:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (files.isNotEmpty) {
|
|
|
|
await CollectionsService.instance.addToCollection(collectionID, files);
|
|
|
|
}
|
|
|
|
RemoteSyncService.instance.sync(silently: true);
|
|
|
|
await dialog?.hide();
|
|
|
|
return true;
|
|
|
|
} catch (e, s) {
|
|
|
|
logger.severe("Failed to add to album", e, s);
|
|
|
|
await dialog?.hide();
|
|
|
|
showGenericErrorDialog(context: context);
|
|
|
|
rethrow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-15 10:02:46 +00:00
|
|
|
Future<bool> updateFavorites(
|
|
|
|
BuildContext context,
|
2023-08-24 16:56:24 +00:00
|
|
|
List<EnteFile> files,
|
2022-12-15 10:02:46 +00:00
|
|
|
bool markAsFavorite,
|
|
|
|
) async {
|
|
|
|
final ProgressDialog dialog = createProgressDialog(
|
|
|
|
context,
|
2023-04-05 07:50:02 +00:00
|
|
|
markAsFavorite
|
|
|
|
? S.of(context).addingToFavorites
|
|
|
|
: S.of(context).removingFromFavorites,
|
2022-12-15 10:02:46 +00:00
|
|
|
);
|
|
|
|
await dialog.show();
|
|
|
|
|
|
|
|
try {
|
2023-01-12 18:22:14 +00:00
|
|
|
await FavoritesService.instance
|
|
|
|
.updateFavorites(context, files, markAsFavorite);
|
2022-12-15 10:02:46 +00:00
|
|
|
return true;
|
|
|
|
} catch (e, s) {
|
|
|
|
logger.severe(e, s);
|
|
|
|
showShortToast(
|
|
|
|
context,
|
2023-04-05 07:50:02 +00:00
|
|
|
markAsFavorite
|
|
|
|
? S.of(context).sorryCouldNotAddToFavorites
|
|
|
|
: S.of(context).sorryCouldNotRemoveFromFavorites,
|
2022-12-15 10:02:46 +00:00
|
|
|
);
|
|
|
|
} finally {
|
|
|
|
await dialog.hide();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|