Skip to content

Commit 82bf2b8

Browse files
feat: Add cancel token for Darwin platforms (#1234)
Signed-off-by: Caijinglong <cjl_spy@163.com> Co-authored-by: Alex Li <github@alexv525.com>
1 parent f234455 commit 82bf2b8

19 files changed

+390
-99
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ To know more about breaking changes, see the [Migration Guide][].
88

99
## Unreleased
1010

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

1315
## 3.7.1
1416

README-ZH.md

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

293-
#### PMPathFilterOption
297+
#### PMPathFilterOption (2.7.0 新增)
294298

295-
自 2.7.0 版本开始提供,当前仅支持 iOS 和 macOS。
299+
> [!NOTE]
300+
> 当前仅在 iOS 和 macOS 上可用.
296301
297302
```dart
298303
final List<PMDarwinAssetCollectionType> pathTypeList = []; // 配置为你需要的类型
299304
final List<PMDarwinAssetCollectionSubtype> pathSubTypeList = []; // 配置为你需要的子类型
300305
final darwinPathFilterOption = PMDarwinPathFilter(
301-
type: pathTypeList,
302-
subType: pathSubTypeList,
303-
);
306+
type: pathTypeList,
307+
subType: pathSubTypeList,
308+
);
304309
PMPathFilter pathFilter = PMPathFilter();
305310
```
306311

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

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

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

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

434+
#### 取消加载 (3.8.0 新增)
435+
436+
> [!NOTE]
437+
> 当前仅在 iOS 和 macOS 上可用.
438+
439+
上述的 `AssetEntity` 方法均添加了 `cancelToken` 参数,
440+
可以用于取消加载过程。
441+
442+
其他方法如果也添加了 `cancelToken` 参数,同样可以用于取消加载过程。
443+
444+
```dart
445+
final PMCancelToken cancelToken = PMCancelToken();
446+
final File? file = await yourAssetEntity.loadFile(cancelToken: cancelToken);
447+
await cancelToken.cancel();
448+
```
449+
450+
`PhotoManager` 也有一个方法可以取消所有加载:
451+
452+
```dart
453+
await PhotoManager.cancelAllRequest();
454+
```
455+
429456
#### 展示资源
430457

431458
从 v3.0.0 开始,插件不再提供任何 UI 组件。

README.md

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,22 @@ see the [migration guide](MIGRATION_GUIDE.md) for detailed info.
6060
* [Limited entities access on Android](#limited-entities-access-on-android)
6161
* [Get albums/folders (`AssetPathEntity`)](#get-albumsfolders-assetpathentity)
6262
* [Params of `getAssetPathList`](#params-of-getassetpathlist)
63-
* [PMPathFilterOption](#pmpathfilteroption)
63+
* [PMPathFilterOption (Since 2.7.0)](#pmpathfilteroption-since-270)
6464
* [Get assets (`AssetEntity`)](#get-assets-assetentity)
6565
* [From `AssetPathEntity`](#from-assetpathentity)
6666
* [From `PhotoManager` (Since 2.6)](#from-photomanager-since-26)
6767
* [From ID](#from-id)
6868
* [From raw data](#from-raw-data)
6969
* [From iCloud](#from-icloud)
70+
* [Cancel loading (Since 3.8.0)](#cancel-loading-since-380)
7071
* [Display assets](#display-assets)
7172
* [Get asset files](#get-asset-files)
7273
* [Obtain "Live Photos"](#obtain-live-photos)
7374
* [Filtering only "Live Photos"](#filtering-only-live-photos)
7475
* [Obtain the video from "Live Photos"](#obtain-the-video-from-live-photos)
76+
* [Include hidden assets (iOS only)](#include-hidden-assets-ios-only)
77+
* [Using with FilterOptionGroup](#using-with-filteroptiongroup)
78+
* [Using with CustomFilter](#using-with-customfilter)
7579
* [Limitations](#limitations)
7680
* [Android 10 media location permission](#android-10-media-location-permission)
7781
* [Usage of the original data](#usage-of-the-original-data)
@@ -309,17 +313,18 @@ See [`getAssetPathList`][] for more detail.
309313
| filterOption | Used to filter resource files, see [Filtering](#filtering) for details | FilterOptionGroup() |
310314
| pathFilterOption | Only valid for iOS and macOS, for the corresponding album type. See [PMPathFilterOption](#pmpathfilteroption) for more detail. | Include all by default. |
311315

312-
#### PMPathFilterOption
316+
#### PMPathFilterOption (Since 2.7.0)
313317

314-
Provide since 2.7.0, currently only valid for iOS and macOS.
318+
> [!NOTE]
319+
> This option is only valid for iOS and macOS.
315320
316321
```dart
317322
final List<PMDarwinAssetCollectionType> pathTypeList = []; // use your need type
318323
final List<PMDarwinAssetCollectionSubtype> pathSubTypeList = []; // use your need type
319324
final darwinPathFilterOption = PMDarwinPathFilter(
320-
type: pathTypeList,
321-
subType: pathSubTypeList,
322-
);
325+
type: pathTypeList,
326+
subType: pathSubTypeList,
327+
);
323328
PMPathFilter pathFilter = PMPathFilter();
324329
```
325330

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

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

352-
First, You need get count of assets:
357+
First, You need to get count of assets:
353358

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

470+
#### Cancel loading (Since 3.8.0)
471+
472+
> [!NOTE]
473+
> This is only valid for iOS and macOS.
474+
475+
The `cancelToken` parameter has been added to various of methods for `AssetEntity`,
476+
which can be used to cancel the loading process.
477+
478+
```dart
479+
final PMCancelToken cancelToken = PMCancelToken();
480+
final File? file = await yourAssetEntity.loadFile(cancelToken: cancelToken);
481+
await cancelToken.cancel();
482+
```
483+
484+
The `PhotoManager` also has a method to cancel all loading:
485+
486+
```dart
487+
await PhotoManager.cancelAllRequest();
488+
```
489+
465490
#### Display assets
466491

467492
> Starts from v3.0.0, `AssetEntityImage` and `AssetEntityImageProvider`

ios/Classes/PMPlugin.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
@class PMManager;
66
@class PMNotificationManager;
77

8-
@interface PMPlugin : NSObject
8+
@interface PMPlugin : NSObject<FlutterPlugin>
99
@property(nonatomic, strong) PMManager *manager;
1010
@property(nonatomic, strong) PMNotificationManager *notificationManager;
1111
- (void)registerPlugin:(NSObject <FlutterPluginRegistrar> *)registrar;

ios/Classes/PMPlugin.m

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#import "PMLogUtils.h"
55
#import "PMManager.h"
66
#import "PMNotificationManager.h"
7-
#import "ResultHandler.h"
7+
#import "PMResultHandler.h"
88
#import "PMThumbLoadOption.h"
99
#import "PMProgressHandler.h"
1010
#import "PMConverter.h"
@@ -19,6 +19,12 @@ @implementation PMPlugin {
1919
BOOL isDetach;
2020
}
2121

22+
23+
+ (void)registerWithRegistrar:(nonnull NSObject<FlutterPluginRegistrar> *)registrar {
24+
PMPlugin *plugin = [PMPlugin new];
25+
[plugin registerPlugin:registrar];
26+
}
27+
2228
- (void)registerPlugin:(NSObject <FlutterPluginRegistrar> *)registrar {
2329
privateRegistrar = registrar;
2430
[self initNotificationManager:registrar];
@@ -29,8 +35,9 @@ - (void)registerPlugin:(NSObject <FlutterPluginRegistrar> *)registrar {
2935
manager.converter = [PMConverter new];
3036
[self setManager:manager];
3137

38+
__block PMPlugin *weakSelf = self; // avoid retain cycle
3239
[channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
33-
[self onMethodCall:call result:result];
40+
[weakSelf onMethodCall:call result:result];
3441
}];
3542
}
3643

@@ -119,7 +126,7 @@ - (void)onMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
119126
return;
120127
}
121128

122-
ResultHandler *handler = [ResultHandler handlerWithCall:call result:result];
129+
PMResultHandler *handler = [PMResultHandler handlerWithCall:call result:result];
123130

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

133-
- (void)handleNotNeedPermissionMethod:(ResultHandler *)handler {
140+
- (void)handleNotNeedPermissionMethod:(PMResultHandler *)handler {
134141
FlutterMethodCall *call = handler.call;
135142
NSString *method = call.method;
136143
PMManager *manager = self.manager;
@@ -154,9 +161,9 @@ - (void)handleNotNeedPermissionMethod:(ResultHandler *)handler {
154161
}
155162
}
156163

157-
- (void)getPermissionState:(ResultHandler *)handler {
164+
- (void)getPermissionState:(PMResultHandler *)handler {
158165
int requestAccessLevel = [handler.call.arguments[@"iosAccessLevel"] intValue];
159-
#if __IPHONE_14_0
166+
#if TARGET_OS_IOS
160167
if (@available(iOS 14, *)) {
161168
PHAuthorizationStatus result = [PHPhotoLibrary authorizationStatusForAccessLevel: requestAccessLevel];
162169
[handler reply: @(result)];
@@ -165,12 +172,17 @@ - (void)getPermissionState:(ResultHandler *)handler {
165172
[handler reply:@(status)];
166173
}
167174
#else
168-
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
169-
[handler reply:@(status)];
175+
if (@available(macOS 11.0, *)) {
176+
PHAuthorizationStatus result = [PHPhotoLibrary authorizationStatusForAccessLevel: requestAccessLevel];
177+
[handler reply: @(result)];
178+
} else {
179+
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
180+
[handler reply:@(status)];
181+
}
170182
#endif
171183
}
172184

173-
- (void)handleAboutPermissionMethod:(ResultHandler *)handler {
185+
- (void)handleAboutPermissionMethod:(PMResultHandler *)handler {
174186
FlutterMethodCall *call = handler.call;
175187
PMManager *manager = self.manager;
176188

@@ -182,7 +194,7 @@ - (void)handleAboutPermissionMethod:(ResultHandler *)handler {
182194
}
183195
}
184196

185-
- (void)replyPermssionResult:(ResultHandler *)handler status:(PHAuthorizationStatus)status isOnlyAdd:(BOOL)isOnlyAdd {
197+
- (void)replyPermssionResult:(PMResultHandler *)handler status:(PHAuthorizationStatus)status isOnlyAdd:(BOOL)isOnlyAdd {
186198
[handler reply:@(status)];
187199
}
188200

@@ -207,7 +219,7 @@ - (UIViewController *)getCurrentViewController {
207219
#endif
208220

209221
- (void)handlePermission:(PMManager *)manager
210-
handler:(ResultHandler *)handler
222+
handler:(PMResultHandler *)handler
211223
requestAccessLevel:(int)requestAccessLevel {
212224
#if __IPHONE_14_0
213225
if (@available(iOS 14, *)) {
@@ -245,7 +257,7 @@ - (void)requestPermissionStatus:(int)requestAccessLevel
245257
#endif
246258
}
247259

248-
- (void)presentLimited:(ResultHandler *)handler {
260+
- (void)presentLimited:(PMResultHandler *)handler {
249261
#if __IPHONE_14_0
250262
if (@available(iOS 14, *)) {
251263
UIViewController *controller = [self getCurrentViewController];
@@ -282,7 +294,7 @@ - (void)presentLimited:(ResultHandler *)handler {
282294

283295
#if TARGET_OS_OSX
284296
- (void)handlePermission:(PMManager *)manager
285-
handler:(ResultHandler*)handler
297+
handler:(PMResultHandler*)handler
286298
requestAccessLevel:(int)requestAccessLevel {
287299
#if __MAC_11_0
288300
if (@available(macOS 11.0, *)) {
@@ -320,21 +332,23 @@ - (void)requestPermissionStatus:(int)requestAccessLevel
320332
#endif
321333
}
322334

323-
- (void)presentLimited:(ResultHandler*)handler {
335+
- (void)presentLimited:(PMResultHandler*)handler {
324336
[handler replyError:@"Not supported on macOS."];
325337
}
326338

327339
#endif
328340

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

334346
- (dispatch_qos_class_t)getQosPriorityForMethod:(NSString *)method {
335347
if ([method isEqualToString:@"getThumb"] ||
336348
[method isEqualToString:@"assetExists"] ||
337-
[method isEqualToString:@"isLocallyAvailable"]) {
349+
[method isEqualToString:@"isLocallyAvailable"] ||
350+
[method isEqualToString:@"cancelRequestWithCancelToken"] ||
351+
[method isEqualToString:@"cancelAllRequest"]) {
338352
return QOS_CLASS_USER_INTERACTIVE;
339353
}
340354

@@ -367,7 +381,7 @@ - (dispatch_qos_class_t)getQosPriorityForMethod:(NSString *)method {
367381
return QOS_CLASS_DEFAULT;
368382
}
369383

370-
- (void)onAuth:(ResultHandler *)handler {
384+
- (void)onAuth:(PMResultHandler *)handler {
371385
PMManager *manager = self.manager;
372386
__block PMNotificationManager *notificationManager = self.notificationManager;
373387

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

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

387401
if ([call.method isEqualToString:@"getAssetPathList"]) {
@@ -669,6 +683,13 @@ - (void)handleMethodResultHandler:(ResultHandler *)handler manager:(PMManager *)
669683
} else if ([@"cancelCacheRequests" isEqualToString:call.method]) {
670684
[manager cancelCacheRequests];
671685
[handler reply:@YES];
686+
} else if ([@"cancelRequestWithCancelToken" isEqualToString:call.method]) {
687+
NSString *cancelToken = call.arguments[@"cancelToken"];
688+
[manager cancelRequestWithCancelToken:cancelToken];
689+
[handler reply:@YES];
690+
} else if ([@"cancelAllRequest" isEqualToString:call.method]) {
691+
[manager cancelAllRequest];
692+
[handler reply:@YES];
672693
} else {
673694
[handler notImplemented];
674695
}
@@ -692,7 +713,7 @@ - (PMProgressHandler *)getProgressHandlerFromDict:(NSDictionary *)dict {
692713
return handler;
693714
}
694715

695-
- (void)createFolder:(FlutterMethodCall *)call manager:(PMManager *)manager handler:(ResultHandler *)handler {
716+
- (void)createFolder:(FlutterMethodCall *)call manager:(PMManager *)manager handler:(PMResultHandler *)handler {
696717
NSString *name = call.arguments[@"name"];
697718
BOOL isRoot = [call.arguments[@"isRoot"] boolValue];
698719
NSString *parentId = call.arguments[@"folderId"];
@@ -709,7 +730,7 @@ - (void)createFolder:(FlutterMethodCall *)call manager:(PMManager *)manager hand
709730
}];
710731
}
711732

712-
- (void)createAlbum:(FlutterMethodCall *)call manager:(PMManager *)manager handler:(ResultHandler *)handler {
733+
- (void)createAlbum:(FlutterMethodCall *)call manager:(PMManager *)manager handler:(PMResultHandler *)handler {
713734
NSString *name = call.arguments[@"name"];
714735
BOOL isRoot = [call.arguments[@"isRoot"] boolValue];
715736
NSString *parentId = call.arguments[@"folderId"];

0 commit comments

Comments
 (0)