update "mediumType" to be optional parameter of "listAlbums" to allow fetch both type of media
This commit is contained in:
parent
1db9b6966e
commit
6976ab8d3b
@ -98,7 +98,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
val mediumType = call.argument<String>("mediumType")
|
val mediumType = call.argument<String>("mediumType")
|
||||||
executor.submit {
|
executor.submit {
|
||||||
result.success(
|
result.success(
|
||||||
listAlbums(mediumType!!)
|
listAlbums(mediumType)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,11 +111,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
val take = call.argument<Int>("take")
|
val take = call.argument<Int>("take")
|
||||||
executor.submit {
|
executor.submit {
|
||||||
result.success(
|
result.success(
|
||||||
when (mediumType) {
|
listMedia(mediumType, albumId!!, newest!!, total!!, skip, take)
|
||||||
imageType -> listImages(albumId!!, newest!!, total!!, skip, take)
|
|
||||||
videoType -> listVideos(albumId!!, newest!!, total!!, skip, take)
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,24 +169,24 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun listAlbums(mediumType: String): List<Map<String, Any>> {
|
private fun listAlbums(mediumType: String?): List<Map<String, Any?>> {
|
||||||
return when (mediumType) {
|
return when (mediumType) {
|
||||||
imageType -> {
|
imageType -> {
|
||||||
listImageAlbums()
|
listImageAlbums().values.toList()
|
||||||
}
|
}
|
||||||
videoType -> {
|
videoType -> {
|
||||||
listVideoAlbums()
|
listVideoAlbums().values.toList()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
listOf()
|
listAllAlbums().values.toList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun listImageAlbums(): List<Map<String, Any>> {
|
private fun listImageAlbums(): Map<String, Map<String, Any>> {
|
||||||
this.context.run {
|
this.context.run {
|
||||||
var total = 0
|
var total = 0
|
||||||
val albumHashMap = mutableMapOf<String, MutableMap<String, Any>>()
|
val albumHashMap = hashMapOf<String, HashMap<String, Any>>()
|
||||||
|
|
||||||
val imageProjection = arrayOf(
|
val imageProjection = arrayOf(
|
||||||
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
|
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
|
||||||
@ -214,7 +210,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
val album = albumHashMap[bucketId]
|
val album = albumHashMap[bucketId]
|
||||||
if (album == null) {
|
if (album == null) {
|
||||||
val folderName = cursor.getString(bucketColumn)
|
val folderName = cursor.getString(bucketColumn)
|
||||||
albumHashMap[bucketId] = mutableMapOf(
|
albumHashMap[bucketId] = hashMapOf(
|
||||||
"id" to bucketId,
|
"id" to bucketId,
|
||||||
"mediumType" to imageType,
|
"mediumType" to imageType,
|
||||||
"name" to folderName,
|
"name" to folderName,
|
||||||
@ -228,25 +224,25 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val albumList = mutableListOf<Map<String, Any>>()
|
val albumLinkedMap = linkedMapOf<String, Map<String, Any>>()
|
||||||
albumList.add(
|
albumLinkedMap.put(
|
||||||
mapOf(
|
allAlbumId,
|
||||||
|
hashMapOf(
|
||||||
"id" to allAlbumId,
|
"id" to allAlbumId,
|
||||||
"mediumType" to imageType,
|
"mediumType" to imageType,
|
||||||
"name" to allAlbumName,
|
"name" to allAlbumName,
|
||||||
"count" to total
|
"count" to total
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
albumList.addAll(albumHashMap.values)
|
albumLinkedMap.putAll(albumHashMap)
|
||||||
return albumList
|
return albumLinkedMap
|
||||||
}
|
}
|
||||||
return listOf()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun listVideoAlbums(): List<Map<String, Any>> {
|
private fun listVideoAlbums(): Map<String, Map<String, Any>> {
|
||||||
this.context.run {
|
this.context.run {
|
||||||
var total = 0
|
var total = 0
|
||||||
val albumHashMap = mutableMapOf<String, MutableMap<String, Any>>()
|
val albumHashMap = hashMapOf<String, HashMap<String, Any>>()
|
||||||
|
|
||||||
val videoProjection = arrayOf(
|
val videoProjection = arrayOf(
|
||||||
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
|
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
|
||||||
@ -270,7 +266,7 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
val album = albumHashMap[bucketId]
|
val album = albumHashMap[bucketId]
|
||||||
if (album == null) {
|
if (album == null) {
|
||||||
val folderName = cursor.getString(bucketColumn)
|
val folderName = cursor.getString(bucketColumn)
|
||||||
albumHashMap[bucketId] = mutableMapOf(
|
albumHashMap[bucketId] = hashMapOf(
|
||||||
"id" to bucketId,
|
"id" to bucketId,
|
||||||
"mediumType" to videoType,
|
"mediumType" to videoType,
|
||||||
"name" to folderName,
|
"name" to folderName,
|
||||||
@ -284,16 +280,58 @@ class PhotoGalleryPlugin : FlutterPlugin, MethodCallHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val albumList = mutableListOf<Map<String, Any>>()
|
val albumLinkedMap = linkedMapOf<String, Map<String, Any>>()
|
||||||
albumList.add(mapOf(
|
albumLinkedMap.put(
|
||||||
|
allAlbumId,
|
||||||
|
hashMapOf(
|
||||||
"id" to allAlbumId,
|
"id" to allAlbumId,
|
||||||
"mediumType" to videoType,
|
"mediumType" to videoType,
|
||||||
"name" to allAlbumName,
|
"name" to allAlbumName,
|
||||||
"count" to total))
|
"count" to total
|
||||||
albumList.addAll(albumHashMap.values)
|
)
|
||||||
return albumList
|
)
|
||||||
|
albumLinkedMap.putAll(albumHashMap)
|
||||||
|
return albumLinkedMap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun listAllAlbums(): Map<String, Map<String, Any?>> {
|
||||||
|
val imageMap = this.listImageAlbums()
|
||||||
|
val videoMap = this.listVideoAlbums()
|
||||||
|
val albumMap = (imageMap.keys + videoMap.keys).associateWith {
|
||||||
|
mapOf(
|
||||||
|
"id" to it,
|
||||||
|
"mediumType" to null,
|
||||||
|
"name" to imageMap[it]?.get("name"),
|
||||||
|
"count" to (imageMap[it]?.get("count") ?: 0) as Int + (videoMap[it]?.get("count") ?: 0) as Int,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return albumMap
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun listMedia(mediumType: String?, albumId: String, newest: Boolean, total: Int, skip: Int?, take: Int?): Map<String, Any?> {
|
||||||
|
return when (mediumType) {
|
||||||
|
imageType -> {
|
||||||
|
listImages(albumId, newest, total, skip, take)
|
||||||
|
}
|
||||||
|
videoType -> {
|
||||||
|
listVideos(albumId, newest, total, skip, take)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val images = listImages(albumId, newest, total, skip, take).get("items") as List<Map<String, Any?>>
|
||||||
|
val videos = listVideos(albumId, newest, total, skip, take).get("items") as List<Map<String, Any?>>
|
||||||
|
var items = (images +videos).sortedWith(compareBy<Map<String, Any?>> {it.get("creationDate") as Long}.thenBy { it.get("modifiedDate") as Long })
|
||||||
|
if (newest) {
|
||||||
|
items = items.reversed()
|
||||||
|
}
|
||||||
|
mapOf(
|
||||||
|
"newest" to newest,
|
||||||
|
"start" to (skip ?: 0),
|
||||||
|
"total" to total,
|
||||||
|
"items" to items
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return listOf()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun listImages(albumId: String, newest: Boolean, 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> {
|
||||||
|
@ -29,8 +29,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
|
|
||||||
Future<void> initAsync() async {
|
Future<void> initAsync() async {
|
||||||
if (await _promptPermissionSetting()) {
|
if (await _promptPermissionSetting()) {
|
||||||
List<Album> albums =
|
List<Album> albums = await PhotoGallery.listAlbums();
|
||||||
await PhotoGallery.listAlbums(mediumType: MediumType.image);
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_albums = albums;
|
_albums = albums;
|
||||||
_loading = false;
|
_loading = false;
|
||||||
|
@ -14,14 +14,14 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||||
if(call.method == "listAlbums") {
|
if(call.method == "listAlbums") {
|
||||||
let arguments = call.arguments as! Dictionary<String, AnyObject>
|
let arguments = call.arguments as! Dictionary<String, AnyObject>
|
||||||
let mediumType = arguments["mediumType"] as! String
|
let mediumType = arguments["mediumType"] as? String
|
||||||
let hideIfEmpty = arguments["hideIfEmpty"] as? Bool
|
let hideIfEmpty = arguments["hideIfEmpty"] as? Bool
|
||||||
result(listAlbums(mediumType: mediumType, hideIfEmpty: hideIfEmpty))
|
result(listAlbums(mediumType: mediumType, hideIfEmpty: hideIfEmpty))
|
||||||
}
|
}
|
||||||
else if(call.method == "listMedia") {
|
else if(call.method == "listMedia") {
|
||||||
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 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
|
||||||
@ -90,11 +90,13 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
|
|
||||||
private var assetCollections : [PHAssetCollection] = []
|
private var assetCollections : [PHAssetCollection] = []
|
||||||
|
|
||||||
private func listAlbums(mediumType: String, hideIfEmpty: Bool? = true) -> [NSDictionary] {
|
private func listAlbums(mediumType: String?, hideIfEmpty: Bool? = true) -> [[String: Any?]] {
|
||||||
self.assetCollections = []
|
self.assetCollections = []
|
||||||
let fetchOptions = PHFetchOptions()
|
let fetchOptions = PHFetchOptions()
|
||||||
var total = 0
|
if #available(iOS 9, *) {
|
||||||
var albums = [NSDictionary]()
|
fetchOptions.fetchLimit = 1
|
||||||
|
}
|
||||||
|
var albums = [[String: Any?]]()
|
||||||
var albumIds = Set<String>()
|
var albumIds = Set<String>()
|
||||||
|
|
||||||
func addCollection (collection: PHAssetCollection, hideIfEmpty: Bool) -> Void {
|
func addCollection (collection: PHAssetCollection, hideIfEmpty: Bool) -> Void {
|
||||||
@ -106,14 +108,8 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
guard !albumIds.contains(albumId) else { return }
|
guard !albumIds.contains(albumId) else { return }
|
||||||
albumIds.insert(albumId)
|
albumIds.insert(albumId)
|
||||||
|
|
||||||
let options = PHFetchOptions()
|
let count = countMedia(collection: collection, mediumType: mediumType)
|
||||||
options.predicate = self.predicateFromMediumType(mediumType: mediumType)
|
|
||||||
if #available(iOS 9, *) {
|
|
||||||
fetchOptions.fetchLimit = 1
|
|
||||||
}
|
|
||||||
let count = PHAsset.fetchAssets(in: collection, options: options).count
|
|
||||||
if(count > 0 || !hideIfEmpty) {
|
if(count > 0 || !hideIfEmpty) {
|
||||||
total+=count
|
|
||||||
self.assetCollections.append(collection)
|
self.assetCollections.append(collection)
|
||||||
albums.append([
|
albums.append([
|
||||||
"id": collection.localIdentifier,
|
"id": collection.localIdentifier,
|
||||||
@ -156,15 +152,15 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
"id": "__ALL__",
|
"id": "__ALL__",
|
||||||
"mediumType": mediumType,
|
"mediumType": mediumType,
|
||||||
"name": "All",
|
"name": "All",
|
||||||
"count" : countMedia(collection: nil, mediumTypes: [mediumType]),
|
"count" : countMedia(collection: nil, mediumType: mediumType),
|
||||||
], at: 0)
|
], at: 0)
|
||||||
|
|
||||||
return albums
|
return albums
|
||||||
}
|
}
|
||||||
|
|
||||||
private func countMedia(collection: PHAssetCollection?, mediumTypes: [String]) -> Int {
|
private func countMedia(collection: PHAssetCollection?, mediumType: String?) -> Int {
|
||||||
let options = PHFetchOptions()
|
let options = PHFetchOptions()
|
||||||
options.predicate = self.predicateFromMediumTypes(mediumTypes: mediumTypes)
|
options.predicate = self.predicateFromMediumType(mediumType: mediumType)
|
||||||
if(collection == nil) {
|
if(collection == nil) {
|
||||||
return PHAsset.fetchAssets(with: options).count
|
return PHAsset.fetchAssets(with: options).count
|
||||||
}
|
}
|
||||||
@ -172,13 +168,13 @@ 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, mediumType: String, newest: Bool, skip: NSNumber?, take: NSNumber?) -> NSDictionary {
|
private func listMedia(albumId: String, mediumType: String?, newest: Bool, skip: NSNumber?, take: NSNumber?) -> NSDictionary {
|
||||||
let fetchOptions = PHFetchOptions()
|
let fetchOptions = PHFetchOptions()
|
||||||
|
fetchOptions.predicate = predicateFromMediumType(mediumType: mediumType)
|
||||||
fetchOptions.sortDescriptors = [
|
fetchOptions.sortDescriptors = [
|
||||||
NSSortDescriptor(key: "creationDate", ascending: newest ? false : true),
|
NSSortDescriptor(key: "creationDate", ascending: newest ? false : true),
|
||||||
NSSortDescriptor(key: "modificationDate", ascending: newest ? false : true)
|
NSSortDescriptor(key: "modificationDate", ascending: newest ? false : true)
|
||||||
]
|
]
|
||||||
fetchOptions.predicate = predicateFromMediumType(mediumType: mediumType)
|
|
||||||
|
|
||||||
let collection = self.assetCollections.first(where: { (collection) -> Bool in
|
let collection = self.assetCollections.first(where: { (collection) -> Bool in
|
||||||
collection.localIdentifier == albumId
|
collection.localIdentifier == albumId
|
||||||
@ -277,9 +273,7 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
) {
|
) {
|
||||||
let manager = PHImageManager.default()
|
let manager = PHImageManager.default()
|
||||||
let fetchOptions = PHFetchOptions()
|
let fetchOptions = PHFetchOptions()
|
||||||
if (mediumType != nil) {
|
fetchOptions.predicate = self.predicateFromMediumType(mediumType: mediumType)
|
||||||
fetchOptions.predicate = self.predicateFromMediumType(mediumType: mediumType!)
|
|
||||||
}
|
|
||||||
fetchOptions.sortDescriptors = [
|
fetchOptions.sortDescriptors = [
|
||||||
NSSortDescriptor(key: "creationDate", ascending: false),
|
NSSortDescriptor(key: "creationDate", ascending: false),
|
||||||
NSSortDescriptor(key: "modificationDate", ascending: false)
|
NSSortDescriptor(key: "modificationDate", ascending: false)
|
||||||
@ -509,16 +503,14 @@ public class SwiftPhotoGalleryPlugin: NSObject, FlutterPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func predicateFromMediumTypes(mediumTypes: [String]) -> NSPredicate {
|
private func predicateFromMediumType(mediumType: String?) -> NSPredicate? {
|
||||||
let predicates = mediumTypes.map { (dartValue) -> NSPredicate in
|
guard let type = mediumType else {
|
||||||
return predicateFromMediumType(mediumType: dartValue)
|
return nil
|
||||||
}
|
}
|
||||||
return NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.or, subpredicates: predicates)
|
guard let swiftType = toSwiftMediumType(value: type) else {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
return NSPredicate(format: "mediaType = %d", swiftType.rawValue)
|
||||||
private func predicateFromMediumType(mediumType: String) -> NSPredicate {
|
|
||||||
let swiftType = toSwiftMediumType(value: mediumType)
|
|
||||||
return NSPredicate(format: "mediaType = %d", swiftType!.rawValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func extractFileExtensionFromUTI(uti: String?) -> String {
|
private func extractFileExtensionFromUTI(uti: String?) -> String {
|
||||||
|
@ -22,7 +22,7 @@ class PhotoGallery {
|
|||||||
|
|
||||||
/// List all available gallery albums and counts number of items of [MediumType].
|
/// List all available gallery albums and counts number of items of [MediumType].
|
||||||
static Future<List<Album>> listAlbums({
|
static Future<List<Album>> listAlbums({
|
||||||
required MediumType mediumType,
|
MediumType? mediumType,
|
||||||
bool? hideIfEmpty = true,
|
bool? hideIfEmpty = true,
|
||||||
}) async {
|
}) async {
|
||||||
final json = await _channel.invokeMethod('listAlbums', {
|
final json = await _channel.invokeMethod('listAlbums', {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user