diff --git a/android/src/main/kotlin/com/morbit/photogallery/PhotoGalleryPlugin.kt b/android/src/main/kotlin/com/morbit/photogallery/PhotoGalleryPlugin.kt index 9717566..f08d1dc 100644 --- a/android/src/main/kotlin/com/morbit/photogallery/PhotoGalleryPlugin.kt +++ b/android/src/main/kotlin/com/morbit/photogallery/PhotoGalleryPlugin.kt @@ -90,13 +90,14 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { "listMedia" -> { val albumId = call.argument("albumId") val mediumType = call.argument("mediumType") + val newest = call.argument("newest") val total = call.argument("total") val skip = call.argument("skip") val take = call.argument("take") BackgroundAsyncTask({ when (mediumType) { - imageType -> listImages(albumId!!, total!!, skip, take) - videoType -> listVideos(albumId!!, total!!, skip, take) + imageType -> listImages(albumId!!, newest!!, total!!, skip, take) + videoType -> listVideos(albumId!!, newest!!, total!!, skip, take) else -> null } }, { v -> @@ -278,7 +279,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { return listOf() } - private fun listImages(albumId: String, total: Int, skip: Int?, take: Int?): Map { + private fun listImages(albumId: String, newest: Boolean, total: Int, skip: Int?, take: Int?): Map { val media = mutableListOf>() val offset = skip ?: 0 val limit = take ?: (total - offset) @@ -304,7 +305,11 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { ) putInt( android.content.ContentResolver.QUERY_ARG_SORT_DIRECTION, - android.content.ContentResolver.QUERY_SORT_DIRECTION_DESCENDING + if (newest) { + android.content.ContentResolver.QUERY_SORT_DIRECTION_DESCENDING + } else { + android.content.ContentResolver.QUERY_SORT_DIRECTION_ASCENDING + } ) // Selection if (albumId != allAlbumId) { @@ -332,13 +337,14 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { } return mapOf( + "newest" to newest, "start" to offset, "total" to total, "items" to media ) } - private fun listVideos(albumId: String, total: Int, skip: Int?, take: Int?): Map { + private fun listVideos(albumId: String, newest: Boolean, total: Int, skip: Int?, take: Int?): Map { val media = mutableListOf>() val offset = skip ?: 0 val limit = take ?: (total - offset) @@ -364,7 +370,11 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { ) putInt( android.content.ContentResolver.QUERY_ARG_SORT_DIRECTION, - android.content.ContentResolver.QUERY_SORT_DIRECTION_DESCENDING + if (newest) { + android.content.ContentResolver.QUERY_SORT_DIRECTION_DESCENDING + } else { + android.content.ContentResolver.QUERY_SORT_DIRECTION_ASCENDING + } ) // Selection if (albumId != allAlbumId) { @@ -392,6 +402,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler { } return mapOf( + "newest" to newest, "start" to offset, "total" to total, "items" to media diff --git a/ios/Classes/SwiftPhotoGalleryPlugin.swift b/ios/Classes/SwiftPhotoGalleryPlugin.swift index 1ac00dc..281b4e0 100644 --- a/ios/Classes/SwiftPhotoGalleryPlugin.swift +++ b/ios/Classes/SwiftPhotoGalleryPlugin.swift @@ -21,9 +21,10 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin { let arguments = call.arguments as! Dictionary let albumId = arguments["albumId"] as! String let mediumType = arguments["mediumType"] as! String + let newest = arguments["newest"] as! Bool let skip = arguments["skip"] as? NSNumber let take = arguments["take"] as? NSNumber - result(listMedia(albumId: albumId, skip: skip, take: take, mediumType: mediumType)) + result(listMedia(albumId: albumId, mediumType: mediumType, newest: newest, skip: skip, take: take)) } else if(call.method == "getMedium") { let arguments = call.arguments as! Dictionary @@ -168,11 +169,11 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin { return PHAsset.fetchAssets(in: collection ?? PHAssetCollection.init(), options: options).count } - private func listMedia(albumId: String, skip: NSNumber?, take: NSNumber?, mediumType: String) -> NSDictionary { + private func listMedia(albumId: String, mediumType: String, newest: Bool, skip: NSNumber?, take: NSNumber?) -> NSDictionary { let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [ - NSSortDescriptor(key: "creationDate", ascending: false), - NSSortDescriptor(key: "modificationDate", ascending: false) + NSSortDescriptor(key: "creationDate", ascending: newest ? false : true), + NSSortDescriptor(key: "modificationDate", ascending: newest ? false : true) ] fetchOptions.predicate = predicateFromMediumType(mediumType: mediumType) @@ -193,6 +194,7 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin { } return [ + "newest": newest, "start": start, "total": total, "items": items, @@ -271,7 +273,10 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin { if (mediumType != nil) { fetchOptions.predicate = self.predicateFromMediumType(mediumType: mediumType!) } - fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)] + fetchOptions.sortDescriptors = [ + NSSortDescriptor(key: "creationDate", ascending: false), + NSSortDescriptor(key: "modificationDate", ascending: false) + ] if #available(iOS 9, *) { fetchOptions.fetchLimit = 1 } diff --git a/lib/photo_gallery.dart b/lib/photo_gallery.dart index f543388..abf8aea 100644 --- a/lib/photo_gallery.dart +++ b/lib/photo_gallery.dart @@ -35,6 +35,7 @@ class PhotoGallery { /// List all available media in a specific album, support pagination of media static Future _listMedia({ required Album album, + bool newest = true, required int total, int? skip, int? take, @@ -42,6 +43,7 @@ class PhotoGallery { final json = await _channel.invokeMethod('listMedia', { 'albumId': album.id, 'mediumType': mediumTypeToJson(album.mediumType), + 'newest': newest, 'total': total, 'skip': skip, 'take': take, diff --git a/lib/src/models/album.dart b/lib/src/models/album.dart index 3425a25..1c3bc20 100644 --- a/lib/src/models/album.dart +++ b/lib/src/models/album.dart @@ -30,11 +30,13 @@ class Album { /// Pagination can be controlled out of [skip] (defaults to `0`) and /// [take] (defaults to ``). Future listMedia({ + bool newest = true, int? skip, int? take, }) { return PhotoGallery._listMedia( album: this, + newest: newest, total: this.count, skip: skip, take: take, diff --git a/lib/src/models/media_page.dart b/lib/src/models/media_page.dart index c286dc5..48e617b 100644 --- a/lib/src/models/media_page.dart +++ b/lib/src/models/media_page.dart @@ -5,6 +5,9 @@ part of photogallery; class MediaPage { final Album album; + /// The sort direction is newest or not + final bool newest; + /// The start offset for those media. final int start; @@ -22,7 +25,8 @@ class MediaPage { /// Creates a range of media from platform channel protocol. MediaPage.fromJson(this.album, dynamic json) - : start = json['start'], + : newest = json['newest'], + start = json['start'], total = json['total'], items = json['items'].map((x) => Medium.fromJson(x)).toList(); @@ -31,6 +35,7 @@ class MediaPage { assert(!isLast); return PhotoGallery._listMedia( album: album, + newest: newest, total: total, skip: end, take: items.length, diff --git a/test/photo_gallery_test.dart b/test/photo_gallery_test.dart index 41ba21c..275f4b9 100644 --- a/test/photo_gallery_test.dart +++ b/test/photo_gallery_test.dart @@ -29,6 +29,7 @@ void main() { test('list media', () async { MediumType mediumType = MediumType.image; + bool newest = true; int skip = 0; int take = 1; List albums = await PhotoGallery.listAlbums(mediumType: mediumType); @@ -37,6 +38,7 @@ void main() { MediaPage expected = Generator.generateMediaPage( album: allAlbum, mediumType: mediumType, + newest: newest, total: allAlbum.count, skip: skip, take: take, diff --git a/test/utils/generator.dart b/test/utils/generator.dart index b9e81e3..3675750 100644 --- a/test/utils/generator.dart +++ b/test/utils/generator.dart @@ -30,6 +30,7 @@ class Generator { static dynamic generateMediaPageJson({ required String albumId, MediumType? mediumType, + bool newest = true, int total = 10, int? skip, int? take, @@ -46,6 +47,7 @@ class Generator { } return { + "newest": newest, "start": skip, "total": total, "items": items, @@ -71,6 +73,7 @@ class Generator { static MediaPage generateMediaPage({ required Album album, MediumType? mediumType, + bool newest = true, required int total, int? skip, int? take, @@ -78,6 +81,7 @@ class Generator { dynamic json = generateMediaPageJson( albumId: album.id, mediumType: mediumType, + newest: newest, total: total, skip: skip, take: take, diff --git a/test/utils/mock_handler.dart b/test/utils/mock_handler.dart index f2b104d..589a48f 100644 --- a/test/utils/mock_handler.dart +++ b/test/utils/mock_handler.dart @@ -12,12 +12,14 @@ Future mockMethodCallHandler(MethodCall call) async { } else if (call.method == "listMedia") { String albumId = call.arguments['albumId']; MediumType? mediumType = jsonToMediumType(call.arguments['mediumType']); + bool newest = call.arguments['newest']; int? total = call.arguments['total']; int? skip = call.arguments['skip']; int? take = call.arguments['take']; dynamic mediaPage = Generator.generateMediaPageJson( albumId: albumId, mediumType: mediumType, + newest: newest, total: total ?? 10, skip: skip, take: take,