import AVFoundation import Combine import Foundation import Photos import UIKit final class SharingMiddleware { static let shared = SharingMiddleware() func middleware(state: AppState, action: AppAction) -> AnyPublisher { switch action { // MARK: - Camera and Gallery Access case .sharingAction(.checkCameraAccess): return Future { promise in let status = AVCaptureDevice.authorizationStatus(for: .video) switch status { case .authorized: promise(.success(.sharingAction(.setCameraAccess(true)))) case .notDetermined: AVCaptureDevice.requestAccess(for: .video) { granted in promise(.success(.sharingAction(.setCameraAccess(granted)))) } case .denied, .restricted: promise(.success(.sharingAction(.setCameraAccess(false)))) @unknown default: promise(.success(.sharingAction(.setCameraAccess(false)))) } } .eraseToAnyPublisher() case .sharingAction(.checkGalleryAccess): return Future { promise in let status = PHPhotoLibrary.authorizationStatus() switch status { case .authorized, .limited: promise(.success(.sharingAction(.setGalleryAccess(true)))) case .notDetermined: PHPhotoLibrary.requestAuthorization { status in promise(.success(.sharingAction(.setGalleryAccess(status == .authorized)))) } case .denied, .restricted: promise(.success(.sharingAction(.setGalleryAccess(false)))) @unknown default: promise(.success(.sharingAction(.setGalleryAccess(false)))) } } .eraseToAnyPublisher() case .fileAction(.itemsFromGalleryFetched(let items)): return Just(.sharingAction(.galleryItemsUpdated(items: items))) .eraseToAnyPublisher() // MARK: - Sharing case .sharingAction(.shareMedia(let ids)): return Future { promise in let items = state.sharingState.galleryItems.filter { ids.contains($0.id) } promise(.success(.fileAction(.copyGalleryItemsForUploading(items: items)))) } .eraseToAnyPublisher() case .fileAction(.itemsCopiedForUploading(let newMessageIds, let localNames)): if let chat = state.conversationsState.currentChat { return Just(.conversationAction(.sendMediaMessages( from: chat.account, to: chat.participant, messagesIds: newMessageIds, localFilesNames: localNames ))) .eraseToAnyPublisher() } else { return Empty().eraseToAnyPublisher() } case .sharingAction(.cameraCaptured(let media, let type)): return Future { promise in if let (id, localName) = FileProcessing.shared.copyCameraCapturedForUploading(media: media, type: type) { promise(.success(.fileAction(.itemsCopiedForUploading(newMessageIds: [id], localNames: [localName]))) ) } else { promise(.success(.empty)) } } .eraseToAnyPublisher() case .sharingAction(.shareLocation(let lat, let lon)): if let chat = state.conversationsState.currentChat { let msg = "geo:\(lat),\(lon)" return Just(.conversationAction(.sendMessage(from: chat.account, to: chat.participant, body: msg))) .eraseToAnyPublisher() } else { return Empty().eraseToAnyPublisher() } case .sharingAction(.shareDocuments(let data)): print("Sharing documents: \(data.count)") return Empty().eraseToAnyPublisher() case .sharingAction(.shareContact(let jid)): if let chat = state.conversationsState.currentChat { let msg = "contact:\(jid)" return Just(.conversationAction(.sendMessage(from: chat.account, to: chat.participant, body: msg))) .eraseToAnyPublisher() } else { return Empty().eraseToAnyPublisher() } default: return Empty().eraseToAnyPublisher() } } }