another.im-ios/old/AppCore/Middlewares/FileMiddleware.swift

142 lines
6.9 KiB
Swift
Raw Normal View History

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()
2024-07-13 14:23:03 +00:00
private var downloadingMessageIDs = ThreadSafeSet<String>()
2024-07-11 13:59:24 +00:00
func middleware(state _: AppState, action: AppAction) -> AnyPublisher<AppAction, Never> {
switch action {
2024-07-14 13:42:51 +00:00
// MARK: - For incomig attachments
2024-07-13 13:38:15 +00:00
case .conversationAction(.messagesUpdated(let messages)):
2024-08-07 12:49:47 +00:00
return Deferred {
Future { [weak self] promise in
guard let wSelf = self else {
promise(.success(.info("FileMiddleware: on checking attachments/shares messages, middleware self is nil")))
return
2024-07-13 14:23:03 +00:00
}
2024-07-14 19:22:46 +00:00
2024-08-07 12:49:47 +00:00
// for incoming messages with attachments
for message in messages where message.attachmentRemotePath != nil && message.attachmentLocalPath == nil {
if wSelf.downloadingMessageIDs.contains(message.id) {
continue
}
wSelf.downloadingMessageIDs.insert(message.id)
DispatchQueue.main.async {
// swiftlint:disable:next force_unwrapping
store.dispatch(.fileAction(.downloadAttachmentFile(messageId: message.id, attachmentRemotePath: message.attachmentRemotePath!)))
}
2024-07-14 19:22:46 +00:00
}
2024-08-07 12:49:47 +00:00
// for outgoing messages with shared attachments
for message in messages where message.attachmentLocalPath != nil && message.attachmentRemotePath == nil && message.pending {
2024-07-16 17:17:19 +00:00
DispatchQueue.main.async {
2024-08-07 12:49:47 +00:00
store.dispatch(.xmppAction(.xmppSharingTryUpload(message)))
2024-07-16 17:17:19 +00:00
}
2024-07-14 19:22:46 +00:00
}
2024-08-07 12:49:47 +00:00
// for outgoing messages with shared attachments which are already uploaded
// but have no thumbnail (only for images)
for message in messages where !message.pending && !message.sentError && message.attachmentType == .image {
if message.attachmentLocalName != nil && message.attachmentRemotePath != nil && message.attachmentThumbnailName == nil {
DispatchQueue.main.async {
// swiftlint:disable:next force_unwrapping
store.dispatch(.fileAction(.createAttachmentThumbnail(messageId: message.id, localName: message.attachmentLocalName!)))
}
}
}
promise(.success(.info("FileMiddleware: attachments/shares messages processed")))
}
}
.eraseToAnyPublisher()
2024-07-12 11:43:14 +00:00
2024-07-13 13:42:47 +00:00
case .fileAction(.downloadAttachmentFile(let id, let attachmentRemotePath)):
2024-08-07 12:49:47 +00:00
return Deferred {
Future { promise in
let localName = "\(id)_\(UUID().uuidString)\(attachmentRemotePath.lastPathComponent)"
let localUrl = FileProcessing.fileFolder.appendingPathComponent(localName)
DownloadManager.shared.enqueueDownload(from: attachmentRemotePath, to: localUrl) { error in
DispatchQueue.main.async {
if let error {
store.dispatch(.fileAction(.downloadingAttachmentFileFailed(messageId: id, reason: error.localizedDescription)))
} else {
store.dispatch(.fileAction(.attachmentFileDownloaded(messageId: id, localName: localName)))
}
2024-07-12 11:43:14 +00:00
}
}
2024-08-07 12:49:47 +00:00
promise(.success(.info("FileMiddleware: started downloading attachment for message \(id)")))
2024-07-13 01:29:46 +00:00
}
2024-08-07 12:49:47 +00:00
}
.eraseToAnyPublisher()
2024-07-12 11:43:14 +00:00
2024-07-14 10:08:51 +00:00
case .fileAction(.attachmentFileDownloaded(let id, let localName)):
2024-08-07 12:49:47 +00:00
return Deferred {
Future { [weak self] promise in
self?.downloadingMessageIDs.remove(id)
promise(.success(.fileAction(.createAttachmentThumbnail(messageId: id, localName: localName))))
}
2024-07-13 14:23:03 +00:00
}
.eraseToAnyPublisher()
2024-07-12 11:43:14 +00:00
2024-07-14 10:08:51 +00:00
case .fileAction(.createAttachmentThumbnail(let id, let localName)):
2024-08-07 12:49:47 +00:00
return Deferred {
Future { [weak self] promise in
if let thumbnailName = FileProcessing.shared.createThumbnail(localName: localName) {
self?.downloadingMessageIDs.remove(id)
promise(.success(.fileAction(.attachmentThumbnailCreated(messageId: id, thumbnailName: thumbnailName))))
} else {
self?.downloadingMessageIDs.remove(id)
promise(.success(.info("FileMiddleware: failed to create thumbnail from \(localName) for message \(id)")))
}
2024-07-11 13:59:24 +00:00
}
}
2024-07-13 01:29:46 +00:00
.eraseToAnyPublisher()
2024-07-11 13:59:24 +00:00
2024-07-14 13:42:51 +00:00
// MARK: - For outgoing sharing
case .fileAction(.fetchItemsFromGallery):
2024-08-07 12:49:47 +00:00
return Deferred {
Future<AppAction, Never> { promise in
let items = FileProcessing.shared.fetchGallery()
promise(.success(.fileAction(.itemsFromGalleryFetched(items: items))))
}
2024-07-14 13:42:51 +00:00
}
.eraseToAnyPublisher()
case .fileAction(.itemsFromGalleryFetched(let items)):
2024-08-07 12:49:47 +00:00
return Deferred {
Future { promise in
let newItems = FileProcessing.shared.fillGalleryItemsThumbnails(items: items)
promise(.success(.sharingAction(.galleryItemsUpdated(items: newItems))))
}
2024-07-14 13:42:51 +00:00
}
.eraseToAnyPublisher()
2024-07-14 16:53:33 +00:00
case .fileAction(.copyGalleryItemsForUploading(let items)):
2024-08-07 12:49:47 +00:00
return Deferred {
Future { promise in
let ids = FileProcessing.shared.copyGalleryItemsForUploading(items: items)
promise(.success(.fileAction(.itemsCopiedForUploading(newMessageIds: ids.map { $0.0 }, localNames: ids.map { $0.1 }))))
}
2024-07-16 11:48:50 +00:00
}
.eraseToAnyPublisher()
case .fileAction(.copyCameraCapturedForUploading(let media, let type)):
2024-08-07 12:49:47 +00:00
return Deferred {
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(.info("FileMiddleware: failed to copy camera captured media for uploading")))
}
2024-07-16 11:48:50 +00:00
}
2024-07-14 16:53:33 +00:00
}
.eraseToAnyPublisher()
2024-07-11 13:59:24 +00:00
default:
return Empty().eraseToAnyPublisher()
}
}
}