add sorting photos by date ascending or descending functionality

This commit is contained in:
Wenqi Li 2021-04-04 20:34:05 +08:00
parent 4b8a457fa9
commit 6baf8cfb0c
8 changed files with 45 additions and 12 deletions

View File

@ -90,13 +90,14 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
"listMedia" -> { "listMedia" -> {
val albumId = call.argument<String>("albumId") val albumId = call.argument<String>("albumId")
val mediumType = call.argument<String>("mediumType") val mediumType = call.argument<String>("mediumType")
val newest = call.argument<Boolean>("newest")
val total = call.argument<Int>("total") val total = call.argument<Int>("total")
val skip = call.argument<Int>("skip") val skip = call.argument<Int>("skip")
val take = call.argument<Int>("take") val take = call.argument<Int>("take")
BackgroundAsyncTask({ BackgroundAsyncTask({
when (mediumType) { when (mediumType) {
imageType -> listImages(albumId!!, total!!, skip, take) imageType -> listImages(albumId!!, newest!!, total!!, skip, take)
videoType -> listVideos(albumId!!, total!!, skip, take) videoType -> listVideos(albumId!!, newest!!, total!!, skip, take)
else -> null else -> null
} }
}, { v -> }, { v ->
@ -278,7 +279,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
return listOf() return listOf()
} }
private fun listImages(albumId: String, total: Int, skip: Int?, take: Int?): Map<String, Any> { private fun listImages(albumId: String, newest: Boolean, total: Int, skip: Int?, take: Int?): Map<String, Any> {
val media = mutableListOf<Map<String, Any?>>() val media = mutableListOf<Map<String, Any?>>()
val offset = skip ?: 0 val offset = skip ?: 0
val limit = take ?: (total - offset) val limit = take ?: (total - offset)
@ -304,7 +305,11 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
) )
putInt( putInt(
android.content.ContentResolver.QUERY_ARG_SORT_DIRECTION, 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 // Selection
if (albumId != allAlbumId) { if (albumId != allAlbumId) {
@ -332,13 +337,14 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
} }
return mapOf( return mapOf(
"newest" to newest,
"start" to offset, "start" to offset,
"total" to total, "total" to total,
"items" to media "items" to media
) )
} }
private fun listVideos(albumId: String, total: Int, skip: Int?, take: Int?): Map<String, Any> { private fun listVideos(albumId: String, newest: Boolean, total: Int, skip: Int?, take: Int?): Map<String, Any> {
val media = mutableListOf<Map<String, Any?>>() val media = mutableListOf<Map<String, Any?>>()
val offset = skip ?: 0 val offset = skip ?: 0
val limit = take ?: (total - offset) val limit = take ?: (total - offset)
@ -364,7 +370,11 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
) )
putInt( putInt(
android.content.ContentResolver.QUERY_ARG_SORT_DIRECTION, 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 // Selection
if (albumId != allAlbumId) { if (albumId != allAlbumId) {
@ -392,6 +402,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
} }
return mapOf( return mapOf(
"newest" to newest,
"start" to offset, "start" to offset,
"total" to total, "total" to total,
"items" to media "items" to media

View File

@ -21,9 +21,10 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
let arguments = call.arguments as! Dictionary<String, AnyObject> let arguments = call.arguments as! Dictionary<String, AnyObject>
let albumId = arguments["albumId"] as! String let albumId = arguments["albumId"] as! String
let mediumType = arguments["mediumType"] as! String let mediumType = arguments["mediumType"] as! String
let newest = arguments["newest"] as! Bool
let skip = arguments["skip"] as? NSNumber let skip = arguments["skip"] as? NSNumber
let take = arguments["take"] 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") { else if(call.method == "getMedium") {
let arguments = call.arguments as! Dictionary<String, AnyObject> let arguments = call.arguments as! Dictionary<String, AnyObject>
@ -168,11 +169,11 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
return PHAsset.fetchAssets(in: collection ?? PHAssetCollection.init(), options: options).count 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() let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [ fetchOptions.sortDescriptors = [
NSSortDescriptor(key: "creationDate", ascending: false), NSSortDescriptor(key: "creationDate", ascending: newest ? false : true),
NSSortDescriptor(key: "modificationDate", ascending: false) NSSortDescriptor(key: "modificationDate", ascending: newest ? false : true)
] ]
fetchOptions.predicate = predicateFromMediumType(mediumType: mediumType) fetchOptions.predicate = predicateFromMediumType(mediumType: mediumType)
@ -193,6 +194,7 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
} }
return [ return [
"newest": newest,
"start": start, "start": start,
"total": total, "total": total,
"items": items, "items": items,
@ -271,7 +273,10 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
if (mediumType != nil) { if (mediumType != nil) {
fetchOptions.predicate = self.predicateFromMediumType(mediumType: mediumType!) 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, *) { if #available(iOS 9, *) {
fetchOptions.fetchLimit = 1 fetchOptions.fetchLimit = 1
} }

View File

@ -35,6 +35,7 @@ class PhotoGallery {
/// List all available media in a specific album, support pagination of media /// List all available media in a specific album, support pagination of media
static Future<MediaPage> _listMedia({ static Future<MediaPage> _listMedia({
required Album album, required Album album,
bool newest = true,
required int total, required int total,
int? skip, int? skip,
int? take, int? take,
@ -42,6 +43,7 @@ class PhotoGallery {
final json = await _channel.invokeMethod('listMedia', { final json = await _channel.invokeMethod('listMedia', {
'albumId': album.id, 'albumId': album.id,
'mediumType': mediumTypeToJson(album.mediumType), 'mediumType': mediumTypeToJson(album.mediumType),
'newest': newest,
'total': total, 'total': total,
'skip': skip, 'skip': skip,
'take': take, 'take': take,

View File

@ -30,11 +30,13 @@ class Album {
/// Pagination can be controlled out of [skip] (defaults to `0`) and /// Pagination can be controlled out of [skip] (defaults to `0`) and
/// [take] (defaults to `<total>`). /// [take] (defaults to `<total>`).
Future<MediaPage> listMedia({ Future<MediaPage> listMedia({
bool newest = true,
int? skip, int? skip,
int? take, int? take,
}) { }) {
return PhotoGallery._listMedia( return PhotoGallery._listMedia(
album: this, album: this,
newest: newest,
total: this.count, total: this.count,
skip: skip, skip: skip,
take: take, take: take,

View File

@ -5,6 +5,9 @@ part of photogallery;
class MediaPage { class MediaPage {
final Album album; final Album album;
/// The sort direction is newest or not
final bool newest;
/// The start offset for those media. /// The start offset for those media.
final int start; final int start;
@ -22,7 +25,8 @@ class MediaPage {
/// Creates a range of media from platform channel protocol. /// Creates a range of media from platform channel protocol.
MediaPage.fromJson(this.album, dynamic json) MediaPage.fromJson(this.album, dynamic json)
: start = json['start'], : newest = json['newest'],
start = json['start'],
total = json['total'], total = json['total'],
items = json['items'].map<Medium>((x) => Medium.fromJson(x)).toList(); items = json['items'].map<Medium>((x) => Medium.fromJson(x)).toList();
@ -31,6 +35,7 @@ class MediaPage {
assert(!isLast); assert(!isLast);
return PhotoGallery._listMedia( return PhotoGallery._listMedia(
album: album, album: album,
newest: newest,
total: total, total: total,
skip: end, skip: end,
take: items.length, take: items.length,

View File

@ -29,6 +29,7 @@ void main() {
test('list media', () async { test('list media', () async {
MediumType mediumType = MediumType.image; MediumType mediumType = MediumType.image;
bool newest = true;
int skip = 0; int skip = 0;
int take = 1; int take = 1;
List<Album> albums = await PhotoGallery.listAlbums(mediumType: mediumType); List<Album> albums = await PhotoGallery.listAlbums(mediumType: mediumType);
@ -37,6 +38,7 @@ void main() {
MediaPage expected = Generator.generateMediaPage( MediaPage expected = Generator.generateMediaPage(
album: allAlbum, album: allAlbum,
mediumType: mediumType, mediumType: mediumType,
newest: newest,
total: allAlbum.count, total: allAlbum.count,
skip: skip, skip: skip,
take: take, take: take,

View File

@ -30,6 +30,7 @@ class Generator {
static dynamic generateMediaPageJson({ static dynamic generateMediaPageJson({
required String albumId, required String albumId,
MediumType? mediumType, MediumType? mediumType,
bool newest = true,
int total = 10, int total = 10,
int? skip, int? skip,
int? take, int? take,
@ -46,6 +47,7 @@ class Generator {
} }
return { return {
"newest": newest,
"start": skip, "start": skip,
"total": total, "total": total,
"items": items, "items": items,
@ -71,6 +73,7 @@ class Generator {
static MediaPage generateMediaPage({ static MediaPage generateMediaPage({
required Album album, required Album album,
MediumType? mediumType, MediumType? mediumType,
bool newest = true,
required int total, required int total,
int? skip, int? skip,
int? take, int? take,
@ -78,6 +81,7 @@ class Generator {
dynamic json = generateMediaPageJson( dynamic json = generateMediaPageJson(
albumId: album.id, albumId: album.id,
mediumType: mediumType, mediumType: mediumType,
newest: newest,
total: total, total: total,
skip: skip, skip: skip,
take: take, take: take,

View File

@ -12,12 +12,14 @@ Future<dynamic> mockMethodCallHandler(MethodCall call) async {
} else if (call.method == "listMedia") { } else if (call.method == "listMedia") {
String albumId = call.arguments['albumId']; String albumId = call.arguments['albumId'];
MediumType? mediumType = jsonToMediumType(call.arguments['mediumType']); MediumType? mediumType = jsonToMediumType(call.arguments['mediumType']);
bool newest = call.arguments['newest'];
int? total = call.arguments['total']; int? total = call.arguments['total'];
int? skip = call.arguments['skip']; int? skip = call.arguments['skip'];
int? take = call.arguments['take']; int? take = call.arguments['take'];
dynamic mediaPage = Generator.generateMediaPageJson( dynamic mediaPage = Generator.generateMediaPageJson(
albumId: albumId, albumId: albumId,
mediumType: mediumType, mediumType: mediumType,
newest: newest,
total: total ?? 10, total: total ?? 10,
skip: skip, skip: skip,
take: take, take: take,