diff --git a/Examples/xx-messenger/Sources/ChatFeature/ChatFeature.swift b/Examples/xx-messenger/Sources/ChatFeature/ChatFeature.swift index f2b7cdb111f146799726c55cb36ab5db8520ce49..9e06c687da0ac5b02cffb06b21754514681f3ee2 100644 --- a/Examples/xx-messenger/Sources/ChatFeature/ChatFeature.swift +++ b/Examples/xx-messenger/Sources/ChatFeature/ChatFeature.swift @@ -115,31 +115,50 @@ public let chatReducer = Reducer<ChatState, ChatAction, ChatEnvironment> let myContactId = try env.messenger.e2e.tryGet().getContact().getId() state.myContactId = myContactId let queryChat: XXModels.Message.Query.Chat + let receivedFileTransfersQuery: XXModels.FileTransfer.Query + let sentFileTransfersQuery: XXModels.FileTransfer.Query switch state.id { case .contact(let contactId): queryChat = .direct(myContactId, contactId) + receivedFileTransfersQuery = .init( + contactId: contactId, + isIncoming: true + ) + sentFileTransfersQuery = .init( + contactId: myContactId, + isIncoming: false + ) } - let query = XXModels.Message.Query(chat: queryChat) - return try env.db().fetchMessagesPublisher(query) - .assertNoFailure() - .map { messages in - messages.compactMap { message in - guard let id = message.id else { return nil } - return ChatState.Message( - id: id, - date: message.date, - senderId: message.senderId, - text: message.text, - status: message.status - ) - } + let messagesQuery = XXModels.Message.Query(chat: queryChat) + return Publishers.CombineLatest3( + try env.db().fetchMessagesPublisher(messagesQuery), + try env.db().fetchFileTransfersPublisher(receivedFileTransfersQuery), + try env.db().fetchFileTransfersPublisher(sentFileTransfersQuery) + ) + .map { messages, receivedFileTransfers, sentFileTransfers in + (messages, receivedFileTransfers + sentFileTransfers) + } + .assertNoFailure() + .map { messages, fileTransfers in + messages.compactMap { message in + guard let id = message.id else { return nil } + return ChatState.Message( + id: id, + date: message.date, + senderId: message.senderId, + text: message.text, + status: message.status, + fileTransfer: fileTransfers.first { $0.id == message.fileTransferId } + ) } - .map { IdentifiedArrayOf<ChatState.Message>(uniqueElements: $0) } - .map(ChatAction.didFetchMessages) - .subscribe(on: env.bgQueue) - .receive(on: env.mainQueue) - .eraseToEffect() - .cancellable(id: FetchEffectId.self, cancelInFlight: true) + } + .removeDuplicates() + .map { IdentifiedArrayOf<ChatState.Message>(uniqueElements: $0) } + .map(ChatAction.didFetchMessages) + .subscribe(on: env.bgQueue) + .receive(on: env.mainQueue) + .eraseToEffect() + .cancellable(id: FetchEffectId.self, cancelInFlight: true) } catch { state.failure = error.localizedDescription return .none diff --git a/Examples/xx-messenger/Tests/ChatFeatureTests/ChatFeatureTests.swift b/Examples/xx-messenger/Tests/ChatFeatureTests/ChatFeatureTests.swift index 7f0633021b525d1e26517db1ffc87ed073fae3d6..492d26d383857455b33dfa882851439c6c695973 100644 --- a/Examples/xx-messenger/Tests/ChatFeatureTests/ChatFeatureTests.swift +++ b/Examples/xx-messenger/Tests/ChatFeatureTests/ChatFeatureTests.swift @@ -21,6 +21,8 @@ final class ChatFeatureTests: XCTestCase { var didFetchMessagesWithQuery: [XXModels.Message.Query] = [] let messagesPublisher = PassthroughSubject<[XXModels.Message], Error>() + var didFetchFileTransfersWithQuery: [XXModels.FileTransfer.Query] = [] + let fileTransfersPublisher = PassthroughSubject<[XXModels.FileTransfer], Error>() store.environment.mainQueue = .immediate store.environment.bgQueue = .immediate @@ -39,6 +41,10 @@ final class ChatFeatureTests: XCTestCase { didFetchMessagesWithQuery.append(query) return messagesPublisher.eraseToAnyPublisher() } + db.fetchFileTransfersPublisher.run = { query in + didFetchFileTransfersWithQuery.append(query) + return fileTransfersPublisher.eraseToAnyPublisher() + } return db } @@ -49,7 +55,25 @@ final class ChatFeatureTests: XCTestCase { XCTAssertNoDifference(didFetchMessagesWithQuery, [ .init(chat: .direct(myContactId, contactId)) ]) + XCTAssertNoDifference(didFetchFileTransfersWithQuery, [ + .init(contactId: contactId, isIncoming: true), + .init(contactId: myContactId, isIncoming: false), + ]) + let receivedFileTransfer = FileTransfer( + id: "file-transfer-1-id".data(using: .utf8)!, + contactId: contactId, + name: "file-transfer-1-name", + type: "file-transfer-1-type", + isIncoming: true + ) + let sentFileTransfer = FileTransfer( + id: "file-transfer-2-id".data(using: .utf8)!, + contactId: myContactId, + name: "file-transfer-2-name", + type: "file-transfer-2-type", + isIncoming: false + ) messagesPublisher.send([ .init( id: nil, @@ -69,7 +93,8 @@ final class ChatFeatureTests: XCTestCase { date: Date(timeIntervalSince1970: 1), status: .received, isUnread: false, - text: "Message 1" + text: "Message 1", + fileTransferId: receivedFileTransfer.id ), .init( id: 2, @@ -79,9 +104,14 @@ final class ChatFeatureTests: XCTestCase { date: Date(timeIntervalSince1970: 2), status: .sent, isUnread: false, - text: "Message 2" + text: "Message 2", + fileTransferId: sentFileTransfer.id ), ]) + fileTransfersPublisher.send([ + receivedFileTransfer, + sentFileTransfer, + ]) let expectedMessages = IdentifiedArrayOf<ChatState.Message>(uniqueElements: [ .init( @@ -89,14 +119,16 @@ final class ChatFeatureTests: XCTestCase { date: Date(timeIntervalSince1970: 1), senderId: contactId, text: "Message 1", - status: .received + status: .received, + fileTransfer: receivedFileTransfer ), .init( id: 2, date: Date(timeIntervalSince1970: 2), senderId: myContactId, text: "Message 2", - status: .sent + status: .sent, + fileTransfer: sentFileTransfer ), ]) @@ -105,6 +137,7 @@ final class ChatFeatureTests: XCTestCase { } messagesPublisher.send(completion: .finished) + fileTransfersPublisher.send(completion: .finished) } func testStartFailure() {