diff --git a/example/lib/model/photo_provider.dart b/example/lib/model/photo_provider.dart index 8dc81fd6..c431c357 100644 --- a/example/lib/model/photo_provider.dart +++ b/example/lib/model/photo_provider.dart @@ -12,7 +12,7 @@ class PhotoProvider extends ChangeNotifier { var onlyAll = false; - Map pathProviderMap = {}; + Map pathProviderMap = {}; bool _notifying = false; @@ -144,8 +144,8 @@ class PhotoProvider extends ChangeNotifier { this.list.addAll(galleryList); } - PathProvider getOrCreatePathProvider(AssetPathEntity pathEntity) { - pathProviderMap[pathEntity] ??= PathProvider(pathEntity); + AssetPathProvider getOrCreatePathProvider(AssetPathEntity pathEntity) { + pathProviderMap[pathEntity] ??= AssetPathProvider(pathEntity); return pathProviderMap[pathEntity]; } @@ -208,13 +208,13 @@ class PhotoProvider extends ChangeNotifier { } } -class PathProvider extends ChangeNotifier { +class AssetPathProvider extends ChangeNotifier { static const loadCount = 50; bool isInit = false; final AssetPathEntity path; - PathProvider(this.path); + AssetPathProvider(this.path); List list = []; @@ -229,6 +229,7 @@ class PathProvider extends ChangeNotifier { } Future onRefresh() async { + await path.refreshPathProperties(); final list = await path.getAssetListPaged(0, loadCount); page = 0; this.list.clear(); @@ -253,13 +254,23 @@ class PathProvider extends ChangeNotifier { void delete(AssetEntity entity) async { final result = await PhotoManager.editor.deleteWithIds([entity.id]); if (result.isNotEmpty) { - await Future.delayed(Duration(seconds: 3)); + final rangeEnd = this.list.length; await provider.refreshAllGalleryProperties(); - final list = - await path.getAssetListRange(start: 0, end: this.list.length); + final list = await path.getAssetListRange(start: 0, end: rangeEnd); + this.list.clear(); + this.list.addAll(list); printListLength("deleted"); + } + } + + void removeInAlbum(AssetEntity entity) async { + if (await PhotoManager.editor.iOS.removeInAlbum(entity, path)) { + final rangeEnd = this.list.length; + await provider.refreshAllGalleryProperties(); + final list = await path.getAssetListRange(start: 0, end: rangeEnd); this.list.clear(); this.list.addAll(list); + printListLength("removeInAlbum"); } } diff --git a/example/lib/page/image_list_page.dart b/example/lib/page/image_list_page.dart index e04a7f31..6fef0329 100644 --- a/example/lib/page/image_list_page.dart +++ b/example/lib/page/image_list_page.dart @@ -30,7 +30,7 @@ class _GalleryContentListPageState extends State { PhotoProvider get photoProvider => Provider.of(context); - PathProvider get provider => + AssetPathProvider get provider => Provider.of(context).getOrCreatePathProvider(path); @override @@ -150,6 +150,7 @@ class _GalleryContentListPageState extends State { child: Text("Copy to another path"), onPressed: () => copyToAnotherPath(entity), ), + _buildRemoveInAlbumWidget(entity), ], ), ); @@ -277,4 +278,19 @@ class _GalleryContentListPageState extends State { ), ); } + + Widget _buildRemoveInAlbumWidget(AssetEntity entity) { + if (!Platform.isIOS) { + return Container(); + } + + return RaisedButton( + child: Text("Remove in album"), + onPressed: () => deleteAssetInAlbum(entity), + ); + } + + void deleteAssetInAlbum(entity) { + provider.removeInAlbum(entity); + } } diff --git a/ios/Classes/core/PMManager.h b/ios/Classes/core/PMManager.h index 901bf2fe..77e5e8fb 100644 --- a/ios/Classes/core/PMManager.h +++ b/ios/Classes/core/PMManager.h @@ -69,4 +69,6 @@ typedef void (^AssetResult)(PMAssetEntity *); - (void)createFolderWithName:(NSString *)name parentId:(NSString *)id block:(void (^)(NSString *, NSString *))block; - (void)createAlbumWithName:(NSString *)name parentId:(NSString *)id block:(void (^)(NSString *, NSString *))block; + +- (void)removeInAlbumWithAssetId:(NSArray *)id albumId:(NSString *)albumId block:(void (^)(NSString *))block; @end diff --git a/ios/Classes/core/PMManager.m b/ios/Classes/core/PMManager.m index d27de8cf..d29f24b2 100644 --- a/ios/Classes/core/PMManager.m +++ b/ios/Classes/core/PMManager.m @@ -1046,4 +1046,34 @@ - (void)createAlbumWithName:(NSString *)name parentId:(NSString *)id block:(void block(targetId, error.localizedDescription); } } + +- (void)removeInAlbumWithAssetId:(NSArray *)id albumId:(NSString *)albumId block:(void (^)(NSString *))block { + PHFetchResult *result = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[albumId] options:nil]; + PHAssetCollection *collection; + if (result && result.count > 0) { + collection = result.firstObject; + } else { + block(@"Can't found the collection."); + return; + } + + if (![collection canPerformEditOperation:PHCollectionEditOperationRemoveContent]) { + block(@"The collection cannot remove asset by user."); + return; + } + + PHFetchResult *assetResult = [PHAsset fetchAssetsWithLocalIdentifiers:id options:nil]; + NSError *error; + [PHPhotoLibrary.sharedPhotoLibrary + performChangesAndWait:^{ + PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection]; + [request removeAssets:assetResult]; + } error:&error]; + if (error) { + block([NSString stringWithFormat:@"Remove error: %@", error]); + return; + } + + block(nil); +} @end diff --git a/ios/Classes/core/PMPlugin.m b/ios/Classes/core/PMPlugin.m index d4e26e2d..1c666c71 100644 --- a/ios/Classes/core/PMPlugin.m +++ b/ios/Classes/core/PMPlugin.m @@ -257,12 +257,12 @@ - (void)onAuth:(FlutterMethodCall *)call result:(FlutterResult)result { BOOL isRoot = [call.arguments[@"isRoot"] boolValue]; NSString *parentId = call.arguments[@"folderId"]; - if(isRoot){ + if (isRoot) { parentId = nil; } - [manager createFolderWithName:name parentId:parentId block:^(NSString*id,NSString *errorMsg){ - + [manager createFolderWithName:name parentId:parentId block:^(NSString *id, NSString *errorMsg) { + [handler reply:[self convertToResult:@{@"id": id, @"errorMsg": errorMsg}]]; }]; } else if ([@"createAlbum" isEqualToString:call.method]) { @@ -270,12 +270,25 @@ - (void)onAuth:(FlutterMethodCall *)call result:(FlutterResult)result { BOOL isRoot = [call.arguments[@"isRoot"] boolValue]; NSString *parentId = call.arguments[@"folderId"]; - if(isRoot){ + if (isRoot) { parentId = nil; } - [manager createAlbumWithName:name parentId:parentId block:^(NSString*id,NSString *errorMsg){ + [manager createAlbumWithName:name parentId:parentId block:^(NSString *id, NSString *errorMsg) { + NSDictionary *dictionary = @{@"id": id, @"errorMsg": errorMsg}; + [handler reply:[self convertToResult:dictionary]]; + }]; + + } else if ([@"removeInAlbum" isEqualToString:call.method]) { + NSArray *assetId = call.arguments[@"assetId"]; + NSString *pathId = call.arguments[@"pathId"]; + [manager removeInAlbumWithAssetId:assetId albumId:pathId block:^(NSString *msg) { + if (msg) { + [handler reply:@{@"msg": msg}]; + } else { + [handler reply:@{@"success": @YES}]; + } }]; } else { @@ -285,6 +298,19 @@ - (void)onAuth:(FlutterMethodCall *)call result:(FlutterResult)result { } +- (NSDictionary *)convertToResult:(NSDictionary *)dict { + NSMutableDictionary *result = [NSMutableDictionary new]; + + for (id key in dict.allKeys) { + id value = dict[key]; + if (value) { + result[key] = value; + } + } + + return result; +} + - (unsigned long)getTimestamp:(FlutterMethodCall *)call { unsigned long timestamp = [call.arguments[@"timestamp"] unsignedLongValue]; return timestamp; diff --git a/lib/src/editor.dart b/lib/src/editor.dart index 0f23708f..8a3434cf 100644 --- a/lib/src/editor.dart +++ b/lib/src/editor.dart @@ -109,6 +109,44 @@ class IosEditor { return _plugin.iosCreateAlbum(name, false, parent); } } + + Future removeInAlbum(AssetEntity entity, AssetPathEntity path) async { + if (entity == null || path == null) { + assert(entity != null, ""); + assert(path != null, ""); + return false; + } + if (path.albumType == 2 || path.isAll) { + assert(path.albumType == 1, "The path must is album"); + assert( + !path.isAll, + "The ${path.name}'s asset can't be remove. Use PhotoManager.editor.deleteAsset", + ); + return false; + } + return _plugin.iosRemoveInAlbum([entity], path); + } + + Future removeAssetsInAlbum( + List list, AssetPathEntity path) async { + if (list == null || path == null) { + assert(list != null, ""); + assert(path != null, ""); + return false; + } + if (list.isEmpty) { + return null; + } + if (path.albumType == 2 || path.isAll) { + assert(path.albumType == 1, "The path must is album"); + assert( + !path.isAll, + "The ${path.name} can't be remove. Use PhotoManager.editor.deleteAsset", + ); + return false; + } + return _plugin.iosRemoveInAlbum(list, path); + } } class AndroidEditor {} diff --git a/lib/src/plugin.dart b/lib/src/plugin.dart index bbad04c3..ed617dcc 100644 --- a/lib/src/plugin.dart +++ b/lib/src/plugin.dart @@ -323,6 +323,11 @@ mixin IosPlugin on BasePlugin { return null; } + if (result["errorMsg"] != null) { + print("errorMsg"); + return null; + } + return AssetPathEntity() ..id = result["id"] ..name = name @@ -348,6 +353,11 @@ mixin IosPlugin on BasePlugin { return null; } + if (result["errorMsg"] != null) { + print("errorMsg"); + return null; + } + return AssetPathEntity() ..id = result["id"] ..name = name @@ -355,6 +365,24 @@ mixin IosPlugin on BasePlugin { ..assetCount = 0 ..albumType = 1; } + + Future iosRemoveInAlbum( + List entities, AssetPathEntity path) async { + final result = await _channel.invokeMethod( + "removeInAlbum", + { + "assetId": entities.map((e) => e.id).toList(), + "pathId": path.id, + }, + ); + + if (result["msg"] != null) { + print("cannot remove, cause by: ${result["msg"]}"); + return false; + } + + return true; + } } mixin AndroidPlugin on BasePlugin {}