fluttercandies / flutter_photo_manager

A Flutter plugin that provides images, videos, and audio abstraction management APIs without interface integration, available on Android, iOS, macOS and OpenHarmony.
https://pub.dev/packages/photo_manager
Apache License 2.0
667 stars 301 forks source link

[How to use] Sort result like Camera Roll in iOS #1162

Open dodatw opened 1 month ago

dodatw commented 1 month ago

Platforms

iOS

Description

Is there any way that can get sort result like iOS camera roll (Recent)?

My code

I tried createDate and modifiedDate. but result is not same with Camera roll.

CustomFilter.sql(
        where:
            '${CustomColumns.base.mediaType} = 2',
        orderBy: [
          OrderByItem(CustomColumns.base.createDate, false),
        ],
      )

Can I get sort result like Camera Roll ? it is no issue before photo_manager 3.1.1

dodatw commented 1 month ago

This issue is side effct when I want to upgrade photo_manager for 2.x to 3.2. https://github.com/fluttercandies/flutter_photo_manager/issues/1150

Because this behavior change, I need to add orderby for CustomFilter.sql

CustomFilter.sql(
        where:
            '${CustomColumns.base.mediaType} = 2 OR ${CustomColumns.darwin.mediaSubtypes} & 8 = 8',
        orderBy: [
          OrderByItem(CustomColumns.base.createDate, false),
        ],
      )

in photo_manager 2.8. I just use FilterOptionGroup(), the result is what I want. (same with camera roll)

ycwu0609 commented 1 month ago

I face the same issue.

The result is still unexpected after adding the OrderByItem(CustomColumns.base.createDate, false). (So as OrderByItem(CustomColumns.base.modifiedDate, false))

Process ran to getAssetListPaged would get the results with wrong order.

(NSArray<PMAssetEntity *> *)getAssetListPaged:(NSString *)id type:(int)type page:(NSUInteger)page size:(NSUInteger)size filterOption:(NSObject<PMBaseFilter> *)filterOption {
    NSMutableArray<PMAssetEntity *> *result = [NSMutableArray new];

    PHFetchOptions *options = [PHFetchOptions new];

    PHFetchResult<PHAssetCollection *> *fetchResult =
    [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[id]
                                                         options:options];
    if (fetchResult && fetchResult.count == 0) {
        return result;
    }

    PHAssetCollection *collection = fetchResult.firstObject;
    PHFetchOptions *assetOptions = [self getAssetOptions:type filterOption:filterOption];
    PHFetchResult<PHAsset *> *assetArray = [PHAsset fetchAssetsInAssetCollection:collection
                                                                         options:assetOptions];
    NSLog(@"assetOption: %@", assetOptions);
    NSLog(@"assetArray: %lu", (unsigned long)[collection obtainAssetCount:assetOptions]);

    if (assetArray.count == 0) {
        return result;
    }

    NSUInteger startIndex = page * size;
    NSUInteger endIndex = startIndex + size - 1;

    NSUInteger count = assetArray.count;
    if (endIndex >= count) {
        endIndex = count - 1;
    }

    BOOL imageNeedTitle = filterOption.needTitle;
    BOOL videoNeedTitle = filterOption.needTitle;

    for (NSUInteger i = startIndex; i <= endIndex; i++) {
        NSUInteger index = i;
        if (assetOptions.sortDescriptors == nil) {
            index = count - i - 1;
        }
        PHAsset *asset = assetArray[index];
        BOOL needTitle = NO;
        if ([asset isVideo]) {
            needTitle = videoNeedTitle;
        } else if ([asset isImage]) {
            needTitle = imageNeedTitle;
        }
        PMAssetEntity *entity = [self convertPHAssetToAssetEntity:asset needTitle:needTitle];
        [result addObject:entity];
        [cacheContainer putAssetEntity:entity];
    }

    return result;
}

It seems that getAssetOptions will return different statement. Maybe the change causes the wrong order.

CaiJingLong commented 1 month ago
image

Use the none option. (The where is empty and the filter is empty).

To add a log for next patch: changes.patch git apply changes.patch

diff --git a/example/lib/page/custom_filter/path_list.dart b/example/lib/page/custom_filter/path_list.dart
index fc08122..8fd621e 100644
--- a/example/lib/page/custom_filter/path_list.dart
+++ b/example/lib/page/custom_filter/path_list.dart
@@ -59,6 +59,9 @@ class PathList extends StatelessWidget {
                 position: ToastPosition.bottom,
               );
             });
+            for (final asset in path.filterOption.toMap().entries) {
+              print('${asset.key}: ${asset.value}');
+            }
             Navigator.push(
               context,
               MaterialPageRoute(

I get next log:

{where: , orderBy: [], needTitle: false, containsPathModified: false}


I use the example of the library:

https://github.com/user-attachments/assets/41735161-ed68-4ad0-a37b-2c64a707ba88

dodatw commented 1 month ago

@CaiJingLong thanks your reply. The problem is, aftrer photo_manager 3.2, it I want "Video + livePhoto" I need to use where to filter content. (https://github.com/fluttercandies/flutter_photo_manager/issues/1150).

Is there anyway support this case? "Video + Live Photo", order is same with cameraRoll, (order is descend).

I can get this kind result in photo_manager 3.1, but not in 3.2. (My current solution is rollback to 3.1)

Thanks.

dodatw commented 1 month ago

@CaiJingLong is it possiable ? I'm currently using photo_manager 3.1. I'm worried that one day I'll need to upgrade to flutter 3.2+, but I can't get the results I need. XD