Zum Inhalt

apple/PhysarumApp/Sources/Capture/CaptureSaver.swift

#if !os(tvOS)
import Foundation
import Photos

/// Distinguishes a Photos-permission denial (recoverable via Settings) from a
/// write failure (transient).
enum CaptureSaveError: Error, Equatable {
    case permissionDenied
    case writeFailed
}

enum CaptureSaver {
    /// Save a still/clip file URL to the Photos library (add-only). Requests
    /// permission on first use.
    static func saveToPhotos(_ url: URL, isVideo: Bool) async -> Result<Void, CaptureSaveError> {
        let status = await PHPhotoLibrary.requestAuthorization(for: .addOnly)
        guard status == .authorized || status == .limited else { return .failure(.permissionDenied) }
        let ok = await withCheckedContinuation { cont in
            PHPhotoLibrary.shared().performChanges {
                let req = PHAssetCreationRequest.forAsset()
                let opts = PHAssetResourceCreationOptions()
                opts.originalFilename = url.lastPathComponent
                req.addResource(with: isVideo ? .video : .photo, fileURL: url, options: opts)
            } completionHandler: { ok, _ in cont.resume(returning: ok) }
        }
        return ok ? .success(()) : .failure(.writeFailed)
    }

    /// Save a Live Photo (paired HEIC still + MOV) to the Photos library.
    static func saveLivePhoto(still: URL, video: URL) async -> Result<Void, CaptureSaveError> {
        let status = await PHPhotoLibrary.requestAuthorization(for: .addOnly)
        guard status == .authorized || status == .limited else { return .failure(.permissionDenied) }
        let ok = await withCheckedContinuation { cont in
            PHPhotoLibrary.shared().performChanges {
                let req = PHAssetCreationRequest.forAsset()
                req.addResource(with: .photo, fileURL: still, options: nil)
                req.addResource(with: .pairedVideo, fileURL: video, options: nil)
            } completionHandler: { ok, _ in cont.resume(returning: ok) }
        }
        return ok ? .success(()) : .failure(.writeFailed)
    }
}
#endif