import Combine final class ConversationMiddleware { static let shared = ConversationMiddleware() func middleware(state: AppState, action: AppAction) -> AnyPublisher { switch action { case .chatsAction(.chatStarted(let chat)): return Future { promise in let roster = state.rostersState.rosters .first { $0.bareJid == chat.account && $0.contactBareJid == chat.participant } promise(.success(.conversationAction(.makeConversationActive(chat: chat, roster: roster)))) } .eraseToAnyPublisher() case .conversationAction(.makeConversationActive): return Just(AppAction.changeFlow(.conversation)).eraseToAnyPublisher() case .xmppAction(.xmppMessageReceived(let message)): return Future { promise in let currentChat = state.conversationsState.currentChat if message.from == currentChat?.participant, message.to == currentChat?.account, message.contentType != .typing { promise(.success(.conversationAction(.messageForCurrentConversationReceived(message)))) } else { promise(.success(.empty)) } } .eraseToAnyPublisher() case .conversationAction(.messageForCurrentConversationReceived(let message)): return Future { promise in var currentMessages = state.conversationsState.currentMessages currentMessages.append(message) promise(.success(.conversationAction(.messagesUpdated(messages: currentMessages)))) } .eraseToAnyPublisher() default: return Empty().eraseToAnyPublisher() } } }