diff --git a/Examples/xx-messenger/Sources/AppCore/SendImage/SendImage.swift b/Examples/xx-messenger/Sources/AppCore/SendImage/SendImage.swift index 724e33baf6992636b5c2ec8477be47aa06415fb1..a457dcd49e11c3e06975a7151a6bd8a9dd839412 100644 --- a/Examples/xx-messenger/Sources/AppCore/SendImage/SendImage.swift +++ b/Examples/xx-messenger/Sources/AppCore/SendImage/SendImage.swift @@ -5,6 +5,14 @@ import XXMessengerClient import XXModels public struct SendImage { + public struct ProgressError: Error, Equatable { + public init(message: String) { + self.message = message + } + + public var message: String + } + public typealias OnError = (Error) -> Void public typealias Completion = () -> Void @@ -27,8 +35,79 @@ extension SendImage { now: @escaping () -> Date ) -> SendImage { SendImage { image, recipientId, onError, completion in - // TODO: implement sending image - completion() + func updateProgress(transferId: Data, progress: Float) { + do { + if var transfer = try db().fetchFileTransfers(.init(id: [transferId])).first { + transfer.progress = progress + try db().saveFileTransfer(transfer) + } + } catch { + onError(error) + } + } + + let file = FileSend( + name: "image.jpg", + type: "image", + preview: nil, + contents: image + ) + let params = MessengerSendFile.Params( + file: file, + recipientId: recipientId, + retry: 2, + callbackIntervalMS: 500 + ) + do { + let date = now() + let myContactId = try messenger.e2e.tryGet().getContact().getId() + let transferId = try messenger.sendFile(params) { info in + switch info { + case .progress(let transferId, let transmitted, let total): + updateProgress( + transferId: transferId, + progress: total > 0 ? Float(transmitted) / Float(total) : 0 + ) + + case .finished(let transferId): + updateProgress( + transferId: transferId, + progress: 1 + ) + + case .failed(_, .error(let error)): + onError(error) + + case .failed(_, .progressError(let message)): + onError(ProgressError(message: message)) + + case .failed(_, .close(let error)): + onError(error) + } + } + try db().saveFileTransfer(XXModels.FileTransfer( + id: transferId, + contactId: myContactId, + name: file.name, + type: file.type, + data: image, + progress: 0, + isIncoming: false, + createdAt: date + )) + try db().saveMessage(XXModels.Message( + senderId: myContactId, + recipientId: recipientId, + groupId: nil, + date: date, + status: .sent, + isUnread: false, + text: "", + fileTransferId: transferId + )) + } catch { + onError(error) + } } } } diff --git a/Examples/xx-messenger/Tests/AppCoreTests/SendImage/SendImageTests.swift b/Examples/xx-messenger/Tests/AppCoreTests/SendImage/SendImageTests.swift index 147b63aca5193d58b5966e88edf59e149aa6ff88..d1cb1741abe2ffdbd2f4481800ca8529943cb9df 100644 --- a/Examples/xx-messenger/Tests/AppCoreTests/SendImage/SendImageTests.swift +++ b/Examples/xx-messenger/Tests/AppCoreTests/SendImage/SendImageTests.swift @@ -9,13 +9,46 @@ final class SendImageTests: XCTestCase { func testSend() { let image = "image-data".data(using: .utf8)! let recipientId = "recipient-id".data(using: .utf8)! + let myContactId = "my-contact-id".data(using: .utf8)! + let transferId = "transfer-id".data(using: .utf8)! + let currentDate = Date(timeIntervalSince1970: 123) var actions: [Action] = [] + var sendFileCallback: MessengerSendFile.Callback? - let messenger: Messenger = .unimplemented - let db: DBManagerGetDB = .unimplemented - let now: () -> Date = Date.init - let send: SendImage = .live(messenger: messenger, db: db, now: now) + var messenger: Messenger = .unimplemented + messenger.e2e.get = { + var e2e: E2E = .unimplemented + e2e.getContact.run = { + var contact: XXClient.Contact = .unimplemented(Data()) + contact.getIdFromContact.run = { _ in myContactId } + return contact + } + return e2e + } + messenger.sendFile.run = { params, callback in + actions.append(.didSendFile(params)) + sendFileCallback = callback + return transferId + } + var db: DBManagerGetDB = .unimplemented + db.run = { + var db: Database = .unimplemented + db.saveFileTransfer.run = { model in + actions.append(.didSaveFileTransfer(model)) + return model + } + db.saveMessage.run = { model in + actions.append(.didSaveMessage(model)) + return model + } + db.fetchFileTransfers.run = { query in + actions.append(.didFetchFileTransfers(query)) + return [.stub(withProgress: 0)] + } + return db + } + let send: SendImage = .live(messenger: messenger, db: db, now: { currentDate }) actions = [] send( @@ -30,7 +63,77 @@ final class SendImageTests: XCTestCase { ) XCTAssertNoDifference(actions, [ - .didComplete + .didSendFile(.init( + file: .init( + name: "image.jpg", + type: "image", + preview: nil, + contents: image + ), + recipientId: recipientId, + retry: 2, + callbackIntervalMS: 500 + )), + .didSaveFileTransfer(.init( + id: transferId, + contactId: myContactId, + name: "image.jpg", + type: "image", + data: image, + progress: 0, + isIncoming: false, + createdAt: currentDate + )), + .didSaveMessage(.init( + senderId: myContactId, + recipientId: recipientId, + groupId: nil, + date: currentDate, + status: .sent, + isUnread: false, + text: "", + fileTransferId: transferId + )), + ]) + + actions = [] + let sendError = NSError(domain: "send-error", code: 1) + sendFileCallback?(.failed(id: transferId, .error(sendError))) + + XCTAssertNoDifference(actions, [ + .didFail(sendError), + ]) + + actions = [] + let closeError = NSError(domain: "close-error", code: 2) + sendFileCallback?(.failed(id: transferId, .close(closeError))) + + XCTAssertNoDifference(actions, [ + .didFail(closeError), + ]) + + actions = [] + let progressError = "progress-error" + sendFileCallback?(.failed(id: transferId, .progressError(progressError))) + + XCTAssertNoDifference(actions, [ + .didFail(SendImage.ProgressError(message: progressError) as NSError), + ]) + + actions = [] + sendFileCallback?(.progress(id: transferId, transmitted: 1, total: 2)) + + XCTAssertNoDifference(actions, [ + .didFetchFileTransfers(.init(id: [transferId])), + .didSaveFileTransfer(.stub(withProgress: 0.5)), + ]) + + actions = [] + sendFileCallback?(.finished(id: transferId)) + + XCTAssertNoDifference(actions, [ + .didFetchFileTransfers(.init(id: [transferId])), + .didSaveFileTransfer(.stub(withProgress: 1)), ]) } } @@ -38,4 +141,23 @@ final class SendImageTests: XCTestCase { private enum Action: Equatable { case didFail(NSError) case didComplete + case didSendFile(MessengerSendFile.Params) + case didSaveFileTransfer(XXModels.FileTransfer) + case didSaveMessage(XXModels.Message) + case didFetchFileTransfers(XXModels.FileTransfer.Query) +} + +private extension XXModels.FileTransfer { + static func stub(withProgress progress: Float) -> XXModels.FileTransfer { + XXModels.FileTransfer( + id: Data(), + contactId: Data(), + name: "", + type: "", + data: nil, + progress: progress, + isIncoming: false, + createdAt: Date(timeIntervalSince1970: 0) + ) + } }