Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ To know more about breaking changes, see the [Migration Guide][].

## Unreleased

*None.*
- Add `cancelToken` parameter to `AssetEntity.loadFile`.
- Add `cancelAllRequest` method to `PhotoManager`.
- The `AssetEntity.getFile` and `AssetEntity.getOriginBytes` methods are public.

## 3.7.1

Expand Down
43 changes: 35 additions & 8 deletions README-ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,22 @@ that can be found in the LICENSE file. -->
* [Android 受限的资源权限](#android-受限的资源权限)
* [获取相簿或图集 (`AssetPathEntity`)](#获取相簿或图集-assetpathentity)
* [`getAssetPathList` 方法的参数](#getassetpathlist-方法的参数)
* [PMPathFilterOption](#pmpathfilteroption)
* [PMPathFilterOption (2.7.0 新增)](#pmpathfilteroption-270-新增)
* [获取资源 (`AssetEntity`)](#获取资源-assetentity)
* [通过 `AssetPathEntity` 获取](#通过-assetpathentity-获取)
* [通过 `PhotoManager` 方法 (2.6.0+) 获取](#通过-photomanager-方法-260-获取)
* [通过 ID 获取](#通过-id-获取)
* [通过原始数据获取](#通过原始数据获取)
* [通过 iCloud 获取](#通过-icloud-获取)
* [取消加载 (3.8.0 新增)](#取消加载-380-新增)
* [展示资源](#展示资源)
* [获取文件](#获取文件)
* [获取「实况照片」](#获取实况照片)
* [仅过滤「实况照片」](#仅过滤实况照片)
* [获取「实况照片」的视频](#获取实况照片的视频)
* [包含隐藏资源(仅 iOS 平台有效)](#包含隐藏资源仅-ios-平台有效)
* [与 FilterOptionGroup 一起使用](#与-filteroptiongroup-一起使用)
* [与 CustomFilter 一起使用](#与-customfilter-一起使用)
* [限制](#限制)
* [Android 10 媒体位置权限](#android-10-媒体位置权限)
* [原始数据的使用](#原始数据的使用)
Expand Down Expand Up @@ -290,23 +294,24 @@ final List<AssetPathEntity> paths = await PhotoManager.getAssetPathList();
| filterOption | 用于筛选 AssetEntity,详情请参阅 [过滤资源](#过滤资源) | FilterOptionGroup() |
| pathFilterOption | 只对 iOS 和 macOS生效,对应原生中的相册类型,详情请参阅 [PMPathFilterOption](#pmpathfilteroption)。 | 默认为包含所有 |

#### PMPathFilterOption
#### PMPathFilterOption (2.7.0 新增)

自 2.7.0 版本开始提供,当前仅支持 iOS 和 macOS。
> [!NOTE]
> 当前仅在 iOS 和 macOS 上可用.

```dart
final List<PMDarwinAssetCollectionType> pathTypeList = []; // 配置为你需要的类型
final List<PMDarwinAssetCollectionSubtype> pathSubTypeList = []; // 配置为你需要的子类型
final darwinPathFilterOption = PMDarwinPathFilter(
type: pathTypeList,
subType: pathSubTypeList,
);
type: pathTypeList,
subType: pathSubTypeList,
);
PMPathFilter pathFilter = PMPathFilter();
```

`PMDarwinAssetCollectionType`的枚举值一一对应 [PHAssetCollectionType | 苹果官网文档](https://developer.apple.com/documentation/photokit/phassetcollectiontype?language=objc).
`PMDarwinAssetCollectionType`的枚举值一一对应 [PHAssetCollectionType | 苹果官网文档](https://developer.apple.com/documentation/photokit/phassetcollectiontype?language=objc).

`PMDarwinAssetCollectionSubtype` 的枚举值一一对应 [PHAssetCollectionSubType | 苹果官网文档](https://developer.apple.com/documentation/photokit/phassetcollectionsubtype?language=objc).
`PMDarwinAssetCollectionSubtype` 的枚举值一一对应 [PHAssetCollectionSubType | 苹果官网文档](https://developer.apple.com/documentation/photokit/phassetcollectionsubtype?language=objc).

### 获取资源 (`AssetEntity`)

Expand Down Expand Up @@ -426,6 +431,28 @@ iCloud 文件只能在设备上的 Apple ID 正常登录时获取。
当账号要求重新输入密码验证时,未缓存在本地的 iCloud 文件将无法访问,
此时相关方法会抛出 `CloudPhotoLibraryErrorDomain` 错误。

#### 取消加载 (3.8.0 新增)

> [!NOTE]
> 当前仅在 iOS 和 macOS 上可用.

上述的 `AssetEntity` 方法均添加了 `cancelToken` 参数,
可以用于取消加载过程。

其他方法如果也添加了 `cancelToken` 参数,同样可以用于取消加载过程。

```dart
final PMCancelToken cancelToken = PMCancelToken();
final File? file = await yourAssetEntity.loadFile(cancelToken: cancelToken);
await cancelToken.cancel();
```

`PhotoManager` 也有一个方法可以取消所有加载:

```dart
await PhotoManager.cancelAllRequest();
```

#### 展示资源

从 v3.0.0 开始,插件不再提供任何 UI 组件。
Expand Down
39 changes: 32 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,22 @@ see the [migration guide](MIGRATION_GUIDE.md) for detailed info.
* [Limited entities access on Android](#limited-entities-access-on-android)
* [Get albums/folders (`AssetPathEntity`)](#get-albumsfolders-assetpathentity)
* [Params of `getAssetPathList`](#params-of-getassetpathlist)
* [PMPathFilterOption](#pmpathfilteroption)
* [PMPathFilterOption (Since 2.7.0)](#pmpathfilteroption-since-270)
* [Get assets (`AssetEntity`)](#get-assets-assetentity)
* [From `AssetPathEntity`](#from-assetpathentity)
* [From `PhotoManager` (Since 2.6)](#from-photomanager-since-26)
* [From ID](#from-id)
* [From raw data](#from-raw-data)
* [From iCloud](#from-icloud)
* [Cancel loading (Since 3.8.0)](#cancel-loading-since-380)
* [Display assets](#display-assets)
* [Get asset files](#get-asset-files)
* [Obtain "Live Photos"](#obtain-live-photos)
* [Filtering only "Live Photos"](#filtering-only-live-photos)
* [Obtain the video from "Live Photos"](#obtain-the-video-from-live-photos)
* [Include hidden assets (iOS only)](#include-hidden-assets-ios-only)
* [Using with FilterOptionGroup](#using-with-filteroptiongroup)
* [Using with CustomFilter](#using-with-customfilter)
* [Limitations](#limitations)
* [Android 10 media location permission](#android-10-media-location-permission)
* [Usage of the original data](#usage-of-the-original-data)
Expand Down Expand Up @@ -309,17 +313,18 @@ See [`getAssetPathList`][] for more detail.
| filterOption | Used to filter resource files, see [Filtering](#filtering) for details | FilterOptionGroup() |
| pathFilterOption | Only valid for iOS and macOS, for the corresponding album type. See [PMPathFilterOption](#pmpathfilteroption) for more detail. | Include all by default. |

#### PMPathFilterOption
#### PMPathFilterOption (Since 2.7.0)

Provide since 2.7.0, currently only valid for iOS and macOS.
> [!NOTE]
> This option is only valid for iOS and macOS.

```dart
final List<PMDarwinAssetCollectionType> pathTypeList = []; // use your need type
final List<PMDarwinAssetCollectionSubtype> pathSubTypeList = []; // use your need type
final darwinPathFilterOption = PMDarwinPathFilter(
type: pathTypeList,
subType: pathSubTypeList,
);
type: pathTypeList,
subType: pathSubTypeList,
);
PMPathFilter pathFilter = PMPathFilter();
```

Expand Down Expand Up @@ -349,7 +354,7 @@ final List<AssetEntity> entities = await path.getAssetListRange(start: 0, end: 8

#### From `PhotoManager` (Since 2.6)

First, You need get count of assets:
First, You need to get count of assets:

```dart
final int count = await PhotoManager.getAssetCount();
Expand Down Expand Up @@ -462,6 +467,26 @@ When the account requires to re-enter the password to verify, iCloud files that
locally available are not allowed to be fetched. The photo library will throws
`CloudPhotoLibraryErrorDomain` in this circumstance.

#### Cancel loading (Since 3.8.0)

> [!NOTE]
> This is only valid for iOS and macOS.

The `cancelToken` parameter has been added to various of methods for `AssetEntity`,
which can be used to cancel the loading process.

```dart
final PMCancelToken cancelToken = PMCancelToken();
final File? file = await yourAssetEntity.loadFile(cancelToken: cancelToken);
await cancelToken.cancel();
```

The `PhotoManager` also has a method to cancel all loading:

```dart
await PhotoManager.cancelAllRequest();
```

#### Display assets

> Starts from v3.0.0, `AssetEntityImage` and `AssetEntityImageProvider`
Expand Down
2 changes: 1 addition & 1 deletion ios/Classes/PMPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
@class PMManager;
@class PMNotificationManager;

@interface PMPlugin : NSObject
@interface PMPlugin : NSObject<FlutterPlugin>
@property(nonatomic, strong) PMManager *manager;
@property(nonatomic, strong) PMNotificationManager *notificationManager;
- (void)registerPlugin:(NSObject <FlutterPluginRegistrar> *)registrar;
Expand Down
61 changes: 41 additions & 20 deletions ios/Classes/PMPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#import "PMLogUtils.h"
#import "PMManager.h"
#import "PMNotificationManager.h"
#import "ResultHandler.h"
#import "PMResultHandler.h"
#import "PMThumbLoadOption.h"
#import "PMProgressHandler.h"
#import "PMConverter.h"
Expand All @@ -19,6 +19,12 @@ @implementation PMPlugin {
BOOL isDetach;
}


+ (void)registerWithRegistrar:(nonnull NSObject<FlutterPluginRegistrar> *)registrar {
PMPlugin *plugin = [PMPlugin new];
[plugin registerPlugin:registrar];
}

- (void)registerPlugin:(NSObject <FlutterPluginRegistrar> *)registrar {
privateRegistrar = registrar;
[self initNotificationManager:registrar];
Expand All @@ -29,8 +35,9 @@ - (void)registerPlugin:(NSObject <FlutterPluginRegistrar> *)registrar {
manager.converter = [PMConverter new];
[self setManager:manager];

__block PMPlugin *weakSelf = self; // avoid retain cycle
[channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
[self onMethodCall:call result:result];
[weakSelf onMethodCall:call result:result];
}];
}

Expand Down Expand Up @@ -119,7 +126,7 @@ - (void)onMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
return;
}

ResultHandler *handler = [ResultHandler handlerWithCall:call result:result];
PMResultHandler *handler = [PMResultHandler handlerWithCall:call result:result];

if ([self isNotNeedPermissionMethod:call.method]) {
[self handleNotNeedPermissionMethod:handler];
Expand All @@ -130,7 +137,7 @@ - (void)onMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
}
}

- (void)handleNotNeedPermissionMethod:(ResultHandler *)handler {
- (void)handleNotNeedPermissionMethod:(PMResultHandler *)handler {
FlutterMethodCall *call = handler.call;
NSString *method = call.method;
PMManager *manager = self.manager;
Expand All @@ -154,9 +161,9 @@ - (void)handleNotNeedPermissionMethod:(ResultHandler *)handler {
}
}

- (void)getPermissionState:(ResultHandler *)handler {
- (void)getPermissionState:(PMResultHandler *)handler {
int requestAccessLevel = [handler.call.arguments[@"iosAccessLevel"] intValue];
#if __IPHONE_14_0
#if TARGET_OS_IOS
if (@available(iOS 14, *)) {
PHAuthorizationStatus result = [PHPhotoLibrary authorizationStatusForAccessLevel: requestAccessLevel];
[handler reply: @(result)];
Expand All @@ -165,12 +172,17 @@ - (void)getPermissionState:(ResultHandler *)handler {
[handler reply:@(status)];
}
#else
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
[handler reply:@(status)];
if (@available(macOS 11.0, *)) {
PHAuthorizationStatus result = [PHPhotoLibrary authorizationStatusForAccessLevel: requestAccessLevel];
[handler reply: @(result)];
} else {
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
[handler reply:@(status)];
}
#endif
}

- (void)handleAboutPermissionMethod:(ResultHandler *)handler {
- (void)handleAboutPermissionMethod:(PMResultHandler *)handler {
FlutterMethodCall *call = handler.call;
PMManager *manager = self.manager;

Expand All @@ -182,7 +194,7 @@ - (void)handleAboutPermissionMethod:(ResultHandler *)handler {
}
}

- (void)replyPermssionResult:(ResultHandler *)handler status:(PHAuthorizationStatus)status isOnlyAdd:(BOOL)isOnlyAdd {
- (void)replyPermssionResult:(PMResultHandler *)handler status:(PHAuthorizationStatus)status isOnlyAdd:(BOOL)isOnlyAdd {
[handler reply:@(status)];
}

Expand All @@ -207,7 +219,7 @@ - (UIViewController *)getCurrentViewController {
#endif

- (void)handlePermission:(PMManager *)manager
handler:(ResultHandler *)handler
handler:(PMResultHandler *)handler
requestAccessLevel:(int)requestAccessLevel {
#if __IPHONE_14_0
if (@available(iOS 14, *)) {
Expand Down Expand Up @@ -245,7 +257,7 @@ - (void)requestPermissionStatus:(int)requestAccessLevel
#endif
}

- (void)presentLimited:(ResultHandler *)handler {
- (void)presentLimited:(PMResultHandler *)handler {
#if __IPHONE_14_0
if (@available(iOS 14, *)) {
UIViewController *controller = [self getCurrentViewController];
Expand Down Expand Up @@ -282,7 +294,7 @@ - (void)presentLimited:(ResultHandler *)handler {

#if TARGET_OS_OSX
- (void)handlePermission:(PMManager *)manager
handler:(ResultHandler*)handler
handler:(PMResultHandler*)handler
requestAccessLevel:(int)requestAccessLevel {
#if __MAC_11_0
if (@available(macOS 11.0, *)) {
Expand Down Expand Up @@ -320,21 +332,23 @@ - (void)requestPermissionStatus:(int)requestAccessLevel
#endif
}

- (void)presentLimited:(ResultHandler*)handler {
- (void)presentLimited:(PMResultHandler*)handler {
[handler replyError:@"Not supported on macOS."];
}

#endif

- (void)runInBackground:(dispatch_block_t)block withHandler:(ResultHandler *)handler {
- (void)runInBackground:(dispatch_block_t)block withHandler:(PMResultHandler *)handler {
dispatch_qos_class_t priority = [self getQosPriorityForMethod:handler.call.method];
dispatch_async(dispatch_get_global_queue(priority, 0), block);
}

- (dispatch_qos_class_t)getQosPriorityForMethod:(NSString *)method {
if ([method isEqualToString:@"getThumb"] ||
[method isEqualToString:@"assetExists"] ||
[method isEqualToString:@"isLocallyAvailable"]) {
[method isEqualToString:@"isLocallyAvailable"] ||
[method isEqualToString:@"cancelRequestWithCancelToken"] ||
[method isEqualToString:@"cancelAllRequest"]) {
return QOS_CLASS_USER_INTERACTIVE;
}

Expand Down Expand Up @@ -367,7 +381,7 @@ - (dispatch_qos_class_t)getQosPriorityForMethod:(NSString *)method {
return QOS_CLASS_DEFAULT;
}

- (void)onAuth:(ResultHandler *)handler {
- (void)onAuth:(PMResultHandler *)handler {
PMManager *manager = self.manager;
__block PMNotificationManager *notificationManager = self.notificationManager;

Expand All @@ -381,7 +395,7 @@ - (void)onAuth:(ResultHandler *)handler {
} withHandler:handler];
}

- (void)handleMethodResultHandler:(ResultHandler *)handler manager:(PMManager *)manager notificationManager:(PMNotificationManager *)notificationManager {
- (void)handleMethodResultHandler:(PMResultHandler *)handler manager:(PMManager *)manager notificationManager:(PMNotificationManager *)notificationManager {
FlutterMethodCall *call = handler.call;

if ([call.method isEqualToString:@"getAssetPathList"]) {
Expand Down Expand Up @@ -669,6 +683,13 @@ - (void)handleMethodResultHandler:(ResultHandler *)handler manager:(PMManager *)
} else if ([@"cancelCacheRequests" isEqualToString:call.method]) {
[manager cancelCacheRequests];
[handler reply:@YES];
} else if ([@"cancelRequestWithCancelToken" isEqualToString:call.method]) {
NSString *cancelToken = call.arguments[@"cancelToken"];
[manager cancelRequestWithCancelToken:cancelToken];
[handler reply:@YES];
} else if ([@"cancelAllRequest" isEqualToString:call.method]) {
[manager cancelAllRequest];
[handler reply:@YES];
} else {
[handler notImplemented];
}
Expand All @@ -692,7 +713,7 @@ - (PMProgressHandler *)getProgressHandlerFromDict:(NSDictionary *)dict {
return handler;
}

- (void)createFolder:(FlutterMethodCall *)call manager:(PMManager *)manager handler:(ResultHandler *)handler {
- (void)createFolder:(FlutterMethodCall *)call manager:(PMManager *)manager handler:(PMResultHandler *)handler {
NSString *name = call.arguments[@"name"];
BOOL isRoot = [call.arguments[@"isRoot"] boolValue];
NSString *parentId = call.arguments[@"folderId"];
Expand All @@ -709,7 +730,7 @@ - (void)createFolder:(FlutterMethodCall *)call manager:(PMManager *)manager hand
}];
}

- (void)createAlbum:(FlutterMethodCall *)call manager:(PMManager *)manager handler:(ResultHandler *)handler {
- (void)createAlbum:(FlutterMethodCall *)call manager:(PMManager *)manager handler:(PMResultHandler *)handler {
NSString *name = call.arguments[@"name"];
BOOL isRoot = [call.arguments[@"isRoot"] boolValue];
NSString *parentId = call.arguments[@"folderId"];
Expand Down
Loading
Loading