123 lines
3.3 KiB
Swift
123 lines
3.3 KiB
Swift
import Foundation
|
|
import Photos
|
|
import UniformTypeIdentifiers
|
|
import ExpoModulesCore
|
|
|
|
class Asset: SharedObject {
|
|
let id: String
|
|
var phAsset: PHAsset?
|
|
|
|
init(id: String) {
|
|
self.id = id
|
|
}
|
|
|
|
func getHeight() async throws -> Int {
|
|
let phAsset = try await requirePHAsset()
|
|
return phAsset.pixelHeight
|
|
}
|
|
|
|
func getWidth() async throws -> Int {
|
|
let phAsset = try await requirePHAsset()
|
|
return phAsset.pixelWidth
|
|
}
|
|
|
|
func getDuration() async throws -> Double? {
|
|
let phAsset = try await requirePHAsset()
|
|
return phAsset.duration != 0 ? phAsset.duration : nil
|
|
}
|
|
|
|
func getFilename() async throws -> String {
|
|
let phAsset = try await requirePHAsset()
|
|
guard let filename = phAsset.value(forKey: "filename") as? String else {
|
|
throw FailedToGetPropertyException("filename")
|
|
}
|
|
return filename
|
|
}
|
|
|
|
func getCreationTime() async throws -> Int? {
|
|
let phAsset = try await requirePHAsset()
|
|
guard let date = phAsset.creationDate else {
|
|
return nil
|
|
}
|
|
return Int(date.timeIntervalSince1970)
|
|
}
|
|
|
|
func getModificationTime() async throws -> Int? {
|
|
let phAsset = try await requirePHAsset()
|
|
guard let date = phAsset.modificationDate else {
|
|
return nil
|
|
}
|
|
return Int(date.timeIntervalSince1970)
|
|
}
|
|
|
|
func getMediaType() async throws -> MediaTypeNext {
|
|
let phAsset = try await requirePHAsset()
|
|
return MediaTypeNext.from(phAsset.mediaType)
|
|
}
|
|
|
|
func getUri() async throws -> String {
|
|
let phAsset = try await requirePHAsset()
|
|
|
|
switch phAsset.mediaType {
|
|
case PHAssetMediaType.image:
|
|
let contentEditingInput = try await phAsset.requestContentEditingInput()
|
|
guard let url = contentEditingInput.fullSizeImageURL else {
|
|
throw FailedToGetPropertyException("uri")
|
|
}
|
|
return url.absoluteString
|
|
|
|
case PHAssetMediaType.video:
|
|
let options = PHVideoRequestOptions()
|
|
options.version = .original
|
|
guard let avAsset = try await PHImageManager.default()
|
|
.requestAVAsset(forVideo: phAsset, options: options) as? AVURLAsset else {
|
|
throw FailedToGetPropertyException("uri")
|
|
}
|
|
return avAsset.url.absoluteString
|
|
|
|
default:
|
|
throw FailedToGetPropertyException("uri")
|
|
}
|
|
}
|
|
|
|
func delete() async throws {
|
|
let assetToDelete = try await requirePHAsset()
|
|
try await AssetRepository.shared.delete(by: [assetToDelete])
|
|
}
|
|
|
|
private func requirePHAsset() async throws -> PHAsset {
|
|
try await loadPHAsset()
|
|
guard let phAsset else {
|
|
throw AssetNotFoundException(id)
|
|
}
|
|
return phAsset
|
|
}
|
|
|
|
private func loadPHAsset() async throws {
|
|
if phAsset != nil {
|
|
return
|
|
}
|
|
|
|
let options = PHFetchOptions()
|
|
options.includeHiddenAssets = true
|
|
options.includeAllBurstAssets = true
|
|
options.fetchLimit = 1
|
|
|
|
guard let fetchedAsset = PHAsset.fetchAssets(
|
|
withLocalIdentifiers: [self.id],
|
|
options: options
|
|
).firstObject else {
|
|
throw AssetNotFoundException(id)
|
|
}
|
|
self.phAsset = fetchedAsset
|
|
}
|
|
|
|
static func from(filePath: URL) async throws -> Asset {
|
|
guard FileManager.default.fileExists(atPath: filePath.path) else {
|
|
throw FailedToCreateAssetException("File does not exist at path: \(filePath.path)")
|
|
}
|
|
let id = try await AssetRepository.shared.add(from: filePath)
|
|
return Asset(id: id)
|
|
}
|
|
}
|