Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Threema/ThreemaFramework/Business/   (Social Medium ©)  Datei vom 26.9.2026 mit Größe 14 kB image not shown  

Quelle  AlbumManager.swift   Sprache: JAVA

 

import CocoaLumberjackSwift
import FileUtility
import Photos
import UIKit

public final class AlbumManager: NSObject {
    
    public struct SaveMediaItem {
        let url: URL
        let type: PHAssetResourceType
        let filename: String
    }
    
    static let albumName = "Threema Media"
    
    public static let shared = AlbumManager()
    
    override private init() {
        super.init()
    }
    
    // MARK: - Public Functions
    
    /// Tries to save media to the Photos app on device. Requests for access if not yet granted.
    /// - Parameter item: SaveMediaItem created from ThumbnailDisplayMessage to be saved
    public func save(_ item: SaveMediaItem, showNotifications: Bool = true, autosave: Bool = false) {
        
        defer {
            FileUtility.shared.deleteIfExists(at: item.url)
        }
        
        // Check access, requests if not yet granted
        let accessType = PhotosRightsHelper.checkAccessAllowed(rightsHelper: PhotosRightsHelper())
        
        guard accessType != .none else {
            DDLogNotice("[AlbumManager] Insufficient permissions to save media to photos.")
            
            if showNotifications {
                NotificationPresenterWrapper.shared.present(type: .saveToPhotosError)
            }
            if autosave {
                NotificationPresenterWrapper.shared.present(type: .autosaveMediaError)
            }
            
            return
        }
        
        // If we can load the Threema Album we save the media there, else we just save to photos
        if let threemaMediaCollection = threemaMediaCollection() {
            DDLogNotice("[AlbumManager] Saving to Threema Media album.")
            saveToAlbum(
                item,
                collection: threemaMediaCollection,
                showNotifications: showNotifications,
                autosave: autosave
            )
        }
        else {
            DDLogNotice("[AlbumManager] Threema Media album could not be fetched/created. Saving to default photos.")
            saveToPhotos(item, showNotifications: showNotifications, autosave: autosave)
        }
    }
    
    // MARK: - Private Functions
    
    /// Save to Threema Media album
    private func saveToAlbum(
        _ item: SaveMediaItem,
        collection: PHAssetCollection,
        showNotifications: Bool,
        autosave: Bool = false
    ) {
        do {
            try PHPhotoLibrary.shared().performChangesAndWait {
                // Create asset creation request with options
                let assetCreationRequest = self.phAssetCreationRequest(for: item)
                
                // Create collection change request
                let assetCollectionChangeRequest = PHAssetCollectionChangeRequest(for: collection)
                
                guard let assetCollectionChangeRequest,
                      let placeholderAsset = assetCreationRequest.placeholderForCreatedAsset else {
                    return
                }
                
                // Save
                assetCollectionChangeRequest.addAssets([placeholderAsset] as NSFastEnumeration)
            }
            
            if showNotifications {
                NotificationPresenterWrapper.shared.present(type: .saveToPhotosSuccess)
            }
            
            DDLogNotice("[AlbumManager] Media saved to Threema Media album.")
        }
        catch {
            if showNotifications {
                NotificationPresenterWrapper.shared.present(type: .saveToPhotosError)
            }
            if autosave {
                NotificationPresenterWrapper.shared.present(type: .autosaveMediaError)
            }
            
            DDLogError(
                "[AlbumManager] Could not save media to Threema Media album. Error: \(error.localizedDescription)"
            )
        }
    }
    
    /// Save to general photos
    private func saveToPhotos(_ item: SaveMediaItem, showNotifications: Bool, autosave: Bool = false) {
        do {
            try PHPhotoLibrary.shared().performChangesAndWait {
                self.phAssetCreationRequest(for: item)
            }
            
            if showNotifications {
                NotificationPresenterWrapper.shared.present(type: .saveToPhotosSuccess)
            }
            
            DDLogNotice("[AlbumManager] Media saved to general photos.")
        }
        catch {
            if showNotifications {
                NotificationPresenterWrapper.shared.present(type: .saveToPhotosError)
            }
            if autosave {
                NotificationPresenterWrapper.shared.present(type: .autosaveMediaError)
            }
            
            DDLogError(
                "[AlbumManager] Could not save media to general photos. Error: \(error.localizedDescription)"
            )
        }
    }
    
    @discardableResult
    private func phAssetCreationRequest(for item: SaveMediaItem) -> PHAssetCreationRequest {
        // Create asset creation request with options
        let assetCreationRequest = PHAssetCreationRequest.forAsset()
        
        let options = PHAssetResourceCreationOptions()

        options.originalFilename = item.filename
        options.shouldMoveFile = true
        
        assetCreationRequest.addResource(with: item.type, fileURL: item.url, options: options)
        return assetCreationRequest
    }
    
    // MARK: - Collection
    
    /// Retrieve, or create the Threema Media collection, returns nil if we do not have permissions
    private func threemaMediaCollection() -> PHAssetCollection? {
        // We first try to fetch the album, if not found we create it
        
        // Fetch
        if let collection = loadExistingThreemaMediaCollection() {
            return collection
        }
        
        // Not found, create
        if let collection = createThreemaMediaCollection() {
            return collection
        }
        
        // We do not have full photos access permission
        return nil
    }
    
    private func loadExistingThreemaMediaCollection() -> PHAssetCollection? {
        let fetchOptions = PHFetchOptions()
        fetchOptions.predicate = NSPredicate(format: "title = %@", AlbumManager.albumName)
        let collection = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
        
        // If there is our Album, we return it
        if let foundAlbum = collection.firstObject {
            return foundAlbum
        }
        
        DDLogNotice("[AlbumManager] Threema Media album not found.")
        return nil
    }
    
    private func createThreemaMediaCollection() -> PHAssetCollection? {
        do {
            try PHPhotoLibrary.shared().performChangesAndWait {
                PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: AlbumManager.albumName)
            }
            
            DDLogNotice("[AlbumManager] Threema Media album created.")
            return loadExistingThreemaMediaCollection()
        }
        catch {
            // Normally we do not have full photos permissions if this happens
            DDLogError(
                "[AlbumManager] Could not create Threema Media album in photos. Error: \(error.localizedDescription)"
            )
            return nil
        }
    }
    
    // MARK: - Deprecated

    let successMessage = "[AlbumManager] Successfully saved image to Camera Roll."
    let permissionNotGrantedMessage = "[AlbumManager] Permission to save images not granted"
    let writeErrorMessage = "[AlbumManager] Error writing to image library:"
    let generalError = "[AlbumManager] Could not create error message"
    
    private func checkAuthorizationWithHandler(completion: @escaping ((_ authorizationState: PhotosRights) -> Void)) {
        let accessAllowed = PhotosRightsHelper.checkAccessAllowed(rightsHelper: PhotosRightsHelper())
        completion(accessAllowed)
    }
    
    private func fetchAssetCollectionForAlbum() -> PHAssetCollection? {
        let fetchOptions = PHFetchOptions()
        fetchOptions.predicate = NSPredicate(format: "title = %@", AlbumManager.albumName)
        let collection = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
        
        if let _: AnyObject = collection.firstObject {
            return collection.firstObject
        }
        return nil
    }
    
    @available(*, deprecated, renamed: "saveMediaItem(_:)")
    @objc private func savedImage(_ im: UIImage, error: Error?, context: UnsafeMutableRawPointer?) {
        if error != nil {
            guard let err = error else {
                DDLogError(generalError)
                return
            }
            DDLogError(writeErrorMessage + "\(err.localizedDescription)")
        }
        else {
            DDLogNotice(successMessage)
        }
    }
    
    @available(*, deprecated, renamed: "saveMediaItem(_:)")
    public func save(image: UIImage) {
        func saveIt(_ validAssets: PHAssetCollection) {
            PHPhotoLibrary.shared().performChanges({
                let assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
                if let assetPlaceHolder = assetChangeRequest.placeholderForCreatedAsset {
                    if let albumChangeRequest = PHAssetCollectionChangeRequest(for: validAssets) {
                        let enumeration: NSArray = [assetPlaceHolder]
                        albumChangeRequest.addAssets(enumeration)
                    }
                }
            }, completionHandler: { success, error in
                if success {
                    DDLogNotice(self.successMessage)
                }
                else {
                    guard let err = error else {
                        DDLogError(self.generalError)
                        return
                    }
                    DDLogError(self.writeErrorMessage + "\(err.localizedDescription)")
                }
            })
        }
        checkAuthorizationWithHandler { authorizationState in
            if authorizationState == .full {
                if let validAssets = self.fetchAssetCollectionForAlbum() { // Album already exists
                    saveIt(validAssets)
                }
                else {
                    PHPhotoLibrary.shared().performChanges({
                        PHAssetCollectionChangeRequest
                            .creationRequestForAssetCollection(
                                withTitle: AlbumManager
                                    .albumName
                            ) // create an asset collection with the album name
                    }) { success, error in
                        if success, let validAssets = self.fetchAssetCollectionForAlbum() {
                            saveIt(validAssets)
                        }
                        else {
                            DDLogError(self.writeErrorMessage + " \(error!.localizedDescription)")
                        }
                    }
                }
            }
            else if authorizationState == .write || authorizationState == .potentialWrite {
                UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.savedImage), nil)
            }
            else {
                DDLogNotice(self.permissionNotGrantedMessage)
            }
        }
    }
    
    @available(*, deprecated, renamed: "saveMediaItem(_:)")
    private func saveMovieFromURL(movieURL: URL) {
        PHPhotoLibrary.shared().performChanges({
            PHAssetCreationRequest.creationRequestForAssetFromVideo(atFileURL: movieURL)
        }) { success, error in
            if success {
                DDLogInfo(self.successMessage)
            }
            else {
                guard let err = error else {
                    DDLogError(self.generalError)
                    return
                }
                DDLogError(self.writeErrorMessage + "\(err.localizedDescription)")
            }
        }
    }
    
    @available(*, deprecated, renamed: "saveMediaItem(_:)")
    public func saveMovieToLibrary(movieURL: URL, completionHandler: @escaping ((_ success: Bool) -> Void)) {
        func saveIt(_ validAssets: PHAssetCollection) {
            PHPhotoLibrary.shared().performChanges({
                
                if let assetChangeRequest = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: movieURL) {
                    guard let assetPlaceHolder = assetChangeRequest.placeholderForCreatedAsset else {
                        DDLogError("Could not create placeholder")
                        return
                    }
                    if let albumChangeRequest = PHAssetCollectionChangeRequest(for: validAssets) {
                        let enumeration: NSArray = [assetPlaceHolder]
                        albumChangeRequest.addAssets(enumeration)
                    }
                }
                
            }, completionHandler: { success, error in
                if success {
                    completionHandler(true)
                    DDLogNotice("Successfully saved video to Camera Roll.")
                }
                else {
                    completionHandler(false)
                    DDLogError("Error writing to movie library: \(error!.localizedDescription)")
                }
            })
        }
        checkAuthorizationWithHandler { authorizationState in
            if authorizationState == .full {
                if let validAssets = self.fetchAssetCollectionForAlbum() { // Album already exists
                    saveIt(validAssets)
                }
                else {
                    PHPhotoLibrary.shared().performChanges({
                        PHAssetCollectionChangeRequest
                            .creationRequestForAssetCollection(
                                withTitle: AlbumManager
                                    .albumName
                            ) // create an asset collection with the album name
                    }) { success, error in
                        if success, let validAssets = self.fetchAssetCollectionForAlbum() {
                            saveIt(validAssets)
                        }
                        else {
                            guard let err = error else {
                                DDLogError(self.generalError)
                                return
                            }
                            DDLogError(self.writeErrorMessage + "\(err.localizedDescription)")
                        }
                    }
                }
            }
            else if authorizationState == .write || authorizationState == .potentialWrite {
                self.saveMovieFromURL(movieURL: movieURL)
            }
            else {
                DDLogNotice(self.permissionNotGrantedMessage)
            }
        }
    }
}

Messung
CHZG
1001009999

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.