This commit is contained in:
fmodf 2024-07-13 16:23:03 +02:00
parent d2b536509a
commit ae7a13e92b
3 changed files with 82 additions and 25 deletions

View file

@ -4,12 +4,21 @@ import UIKit
final class FileMiddleware {
static let shared = FileMiddleware()
private var downloadingMessageIDs = ThreadSafeSet<String>()
func middleware(state _: AppState, action: AppAction) -> AnyPublisher<AppAction, Never> {
switch action {
case .conversationAction(.messagesUpdated(let messages)):
return Future { promise in
return Future { [weak self] promise in
guard let wSelf = self else {
promise(.success(.empty))
return
}
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(id: message.id, attachmentRemotePath: message.attachmentRemotePath!)))
@ -34,14 +43,19 @@ final class FileMiddleware {
}.eraseToAnyPublisher()
case .fileAction(.attachmentFileDownloaded(let id, let localUrl)):
return Just(.fileAction(.createAttachmentThumbnail(id: id, localUrl: localUrl)))
.eraseToAnyPublisher()
return Future { [weak self] promise in
self?.downloadingMessageIDs.remove(id)
promise(.success(.fileAction(.createAttachmentThumbnail(id: id, localUrl: localUrl))))
}
.eraseToAnyPublisher()
case .fileAction(.createAttachmentThumbnail(let id, let localUrl)):
return Future { promise in
return Future { [weak self] promise in
if let thumbnailUrl = FileProcessing.shared.createThumbnail(id: id, localUrl: localUrl) {
self?.downloadingMessageIDs.remove(id)
promise(.success(.fileAction(.attachmentThumbnailCreated(id: id, thumbnailUrl: thumbnailUrl))))
} else {
self?.downloadingMessageIDs.remove(id)
promise(.success(.empty))
}
}

View file

@ -0,0 +1,26 @@
import Foundation
class ThreadSafeSet<T: Hashable> {
private var set: Set<T> = []
private let accessQueue = DispatchQueue(label: "com.example.ThreadSafeSet")
func insert(_ newElement: T) {
_ = accessQueue.sync {
set.insert(newElement)
}
}
func remove(_ element: T) {
_ = accessQueue.sync {
set.remove(element)
}
}
var elements: Set<T> {
accessQueue.sync { set }
}
func contains(_ element: T) -> Bool {
accessQueue.sync { set.contains(element) }
}
}

View file

@ -70,29 +70,33 @@ private struct AttachmentView: View {
let message: Message
var body: some View {
switch message.attachmentType {
case .image:
if let thumbnail = thumbnail() {
thumbnail
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: Const.attachmentPreviewSize, height: Const.attachmentPreviewSize)
} else {
if message.attachmentDownloadFailed {
failed
} else {
switch message.attachmentType {
case .image:
if let thumbnail = thumbnail() {
thumbnail
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: Const.attachmentPreviewSize, height: Const.attachmentPreviewSize)
} else {
placeholder
}
case .movie:
if let file = message.attachmentLocalPath {
VideoPlayerView(url: file)
.frame(width: Const.attachmentPreviewSize, height: Const.attachmentPreviewSize)
.cornerRadius(Const.attachmentPreviewSize / 10)
.overlay(RoundedRectangle(cornerRadius: Const.attachmentPreviewSize / 10).stroke(Color.Material.Shape.separator, lineWidth: 1))
} else {
placeholder
}
default:
placeholder
}
case .movie:
if let file = message.attachmentLocalPath {
VideoPlayerView(url: file)
.frame(width: Const.attachmentPreviewSize, height: Const.attachmentPreviewSize)
.cornerRadius(Const.attachmentPreviewSize / 10)
.overlay(RoundedRectangle(cornerRadius: Const.attachmentPreviewSize / 10).stroke(Color.Material.Shape.separator, lineWidth: 1))
} else {
placeholder
}
default:
placeholder
}
}
@ -113,6 +117,19 @@ private struct AttachmentView: View {
}
}
@ViewBuilder private var failed: some View {
Rectangle()
.foregroundColor(.Material.Background.dark)
.frame(width: Const.attachmentPreviewSize, height: Const.attachmentPreviewSize)
.overlay {
ZStack {
Image(systemName: "exclamationmark.triangle")
.font(.body1)
.foregroundColor(.Rainbow.red500)
}
}
}
private func progressImageName(_ type: MessageAttachmentType) -> String {
switch type {
case .image: