2024-07-11 13:59:24 +00:00
|
|
|
import Combine
|
2024-07-12 11:43:14 +00:00
|
|
|
import Foundation
|
|
|
|
import UIKit
|
2024-07-11 13:59:24 +00:00
|
|
|
|
|
|
|
final class FileMiddleware {
|
2024-07-12 11:43:14 +00:00
|
|
|
static let shared = FileMiddleware()
|
|
|
|
private var downloader = DownloadManager()
|
2024-07-11 13:59:24 +00:00
|
|
|
|
|
|
|
func middleware(state _: AppState, action: AppAction) -> AnyPublisher<AppAction, Never> {
|
|
|
|
switch action {
|
2024-07-12 11:43:14 +00:00
|
|
|
case .conversationAction(.attachmentsUpdated(let attachments)):
|
|
|
|
DispatchQueue.global(qos: .background).async {
|
|
|
|
for attachment in attachments where attachment.localPath == nil {
|
|
|
|
if let remotePath = attachment.remotePath {
|
|
|
|
let localUrl = self.fileFolder.appendingPathComponent(attachment.id)
|
|
|
|
self.downloader.download(from: remotePath, to: localUrl) { error in
|
|
|
|
if error == nil {
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
store.dispatch(.fileAction(.attachmentFileDownloaded(id: attachment.id, localUrl: localUrl)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Empty().eraseToAnyPublisher()
|
|
|
|
|
|
|
|
case .fileAction(.attachmentFileDownloaded(let id, let localUrl)):
|
|
|
|
DispatchQueue.global(qos: .background).async {
|
|
|
|
guard let attachment = store.state.conversationsState.currentAttachments.first(where: { $0.id == id }) else { return }
|
|
|
|
switch attachment.type {
|
|
|
|
case .image:
|
|
|
|
if let data = try? Data(contentsOf: localUrl), let image = UIImage(data: data) {
|
|
|
|
image.scaleAndCropImage(toExampleSize: CGSizeMake(Const.attachmentPreviewSize, Const.attachmentPreviewSize)) { img in
|
|
|
|
if let img = img, let data = img.jpegData(compressionQuality: 1.0) {
|
|
|
|
let thumbnailUrl = self.fileFolder.appendingPathComponent("\(id)_thumbnail.jpg")
|
|
|
|
do {
|
|
|
|
try data.write(to: thumbnailUrl)
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
store.dispatch(.fileAction(.attachmentThumbnailCreated(id: id, thumbnailUrl: thumbnailUrl)))
|
|
|
|
}
|
|
|
|
} catch {
|
|
|
|
print("Error writing thumbnail: \(error)")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case .movie:
|
|
|
|
// self.downloadAndMakeThumbnail(for: attachment)
|
|
|
|
break
|
|
|
|
|
|
|
|
default:
|
|
|
|
break
|
2024-07-11 13:59:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Empty().eraseToAnyPublisher()
|
|
|
|
|
|
|
|
default:
|
|
|
|
return Empty().eraseToAnyPublisher()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-07-12 11:43:14 +00:00
|
|
|
|
|
|
|
private extension FileMiddleware {
|
|
|
|
var fileFolder: URL {
|
|
|
|
// swiftlint:disable:next force_unwrapping
|
|
|
|
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
|
|
|
return documentsURL.appendingPathComponent(Const.fileFolder)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private final class DownloadManager {
|
|
|
|
private let urlSession: URLSession
|
|
|
|
|
|
|
|
init() {
|
|
|
|
let configuration = URLSessionConfiguration.default
|
|
|
|
urlSession = URLSession(configuration: configuration)
|
|
|
|
}
|
|
|
|
|
|
|
|
func download(from url: URL, to localUrl: URL, completion: @escaping (Error?) -> Void) {
|
|
|
|
let task = urlSession.downloadTask(with: url) { tempLocalUrl, _, error in
|
|
|
|
if let tempLocalUrl = tempLocalUrl, error == nil {
|
|
|
|
do {
|
|
|
|
try FileManager.default.copyItem(at: tempLocalUrl, to: localUrl)
|
|
|
|
completion(nil)
|
|
|
|
} catch let writeError {
|
|
|
|
completion(writeError)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
completion(error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
task.resume()
|
|
|
|
}
|
|
|
|
}
|