54 lines
1.9 KiB
Swift
54 lines
1.9 KiB
Swift
|
import Photos
|
||
|
import SwiftUI
|
||
|
|
||
|
enum GalleryMediaType {
|
||
|
case video
|
||
|
case photo
|
||
|
}
|
||
|
|
||
|
struct GalleryItem: Identifiable {
|
||
|
let id: String
|
||
|
let type: GalleryMediaType
|
||
|
var thumbnail: Image?
|
||
|
var duration: String?
|
||
|
}
|
||
|
|
||
|
extension GalleryItem {
|
||
|
static func fetchAll() async -> [GalleryItem] {
|
||
|
await Task {
|
||
|
let fetchOptions = PHFetchOptions()
|
||
|
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
|
||
|
let assets = PHAsset.fetchAssets(with: fetchOptions)
|
||
|
var tmpGalleryItems: [GalleryItem] = []
|
||
|
assets.enumerateObjects { asset, _, _ in
|
||
|
if asset.mediaType == .image {
|
||
|
let item = GalleryItem(id: asset.localIdentifier, type: .photo, thumbnail: nil, duration: nil)
|
||
|
tmpGalleryItems.append(item)
|
||
|
}
|
||
|
if asset.mediaType == .video {
|
||
|
let item = GalleryItem(id: asset.localIdentifier, type: .video, thumbnail: nil, duration: asset.duration.minAndSec)
|
||
|
tmpGalleryItems.append(item)
|
||
|
}
|
||
|
}
|
||
|
return tmpGalleryItems
|
||
|
}.value
|
||
|
}
|
||
|
|
||
|
mutating func fetchThumbnail() async throws {
|
||
|
guard let asset = PHAsset.fetchAssets(withLocalIdentifiers: [id], options: nil).firstObject else { return }
|
||
|
let size = CGSize(width: Const.galleryGridSize, height: Const.galleryGridSize)
|
||
|
|
||
|
switch type {
|
||
|
case .photo:
|
||
|
let originalImage = try await PHImageManager.default().getPhoto(for: asset)
|
||
|
let cropped = try await originalImage.scaleAndCropImage(size)
|
||
|
thumbnail = Image(uiImage: cropped)
|
||
|
|
||
|
case .video:
|
||
|
let avAsset = try await PHImageManager.default().getVideo(for: asset)
|
||
|
let cropped = try await avAsset.generateVideoThumbnail(size)
|
||
|
thumbnail = Image(uiImage: cropped)
|
||
|
}
|
||
|
}
|
||
|
}
|