Files
Stow/ios/Stow/Sources/Services/ScreenshotLibraryService.swift
T

72 lines
2.6 KiB
Swift

import Photos
import UIKit
struct ScreenshotCandidate: Identifiable {
let id: String
let asset: PHAsset
let capturedAt: Date
}
@MainActor
enum ScreenshotLibraryService {
static func requestAccess() async -> PHAuthorizationStatus {
let current = PHPhotoLibrary.authorizationStatus(for: .readWrite)
guard current == .notDetermined else { return current }
return await withCheckedContinuation { continuation in
PHPhotoLibrary.requestAuthorization(for: .readWrite) { result in
continuation.resume(returning: result)
}
}
}
static func recentScreenshots(limit: Int = 30) -> [ScreenshotCandidate] {
let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let assets = PHAsset.fetchAssets(with: .image, options: options)
var screenshots: [ScreenshotCandidate] = []
for index in 0..<assets.count {
let asset = assets.object(at: index)
guard asset.mediaSubtypes.contains(.photoScreenshot) else { continue }
screenshots.append(ScreenshotCandidate(
id: asset.localIdentifier,
asset: asset,
capturedAt: asset.creationDate ?? .now
))
if screenshots.count >= limit { break }
}
return screenshots
}
static func thumbnail(for asset: PHAsset) async -> UIImage? {
await withCheckedContinuation { continuation in
let options = PHImageRequestOptions()
options.deliveryMode = .highQualityFormat
options.resizeMode = .fast
options.isNetworkAccessAllowed = false
PHImageManager.default().requestImage(
for: asset,
targetSize: CGSize(width: 300, height: 300),
contentMode: .aspectFill,
options: options
) { image, _ in
continuation.resume(returning: image)
}
}
}
static func imageData(for asset: PHAsset) async throws -> Data {
try await withCheckedThrowingContinuation { continuation in
let options = PHImageRequestOptions()
options.deliveryMode = .highQualityFormat
options.isNetworkAccessAllowed = true
PHImageManager.default().requestImageDataAndOrientation(for: asset, options: options) { data, _, _, _ in
if let data {
continuation.resume(returning: data)
} else {
continuation.resume(throwing: ImportError.invalidImage)
}
}
}
}
}