spb/focale Public
Swift 100%
1//2// PhotoLibraryWriter.swift3// Focale4//5// Author: Simon-Pierre Boucher6// Contact: contact@spboucher.ai7//8// Writes captures into the system photo library via PHAssetCreationRequest.9// No parallel library, no private sandbox (CLAUDE.md §4). The user can10// uninstall tomorrow and lose nothing.11//1213import Foundation14import Photos1516actor PhotoLibraryWriter {1718 /// PhotoKit runs change blocks on its own queue; this box carries the19 /// created identifier out of the @Sendable block without giving the20 /// block any actor isolation (a Swift 6 runtime crash otherwise).21 private final class IdentifierBox: @unchecked Sendable {22 var value: String?23 }2425 /// Saves a capture and returns the new asset's localIdentifier —26 /// the key the whole index is built on.27 func save(_ photo: CapturedPhoto) async throws -> String {28 let box = IdentifierBox()29 let change: @Sendable () -> Void = {30 let request = PHAssetCreationRequest.forAsset()31 if let processed = photo.processedData {32 request.addResource(with: .photo, data: processed, options: nil)33 if let raw = photo.rawData {34 let options = PHAssetResourceCreationOptions()35 request.addResource(with: .alternatePhoto, data: raw, options: options)36 }37 } else if let raw = photo.rawData {38 request.addResource(with: .photo, data: raw, options: nil)39 }40 box.value = request.placeholderForCreatedAsset?.localIdentifier41 }42 try await PHPhotoLibrary.shared().performChanges(change)4344 guard let localIdentifier = box.value else { throw CaptureError.captureFailed }45 return localIdentifier46 }47}48