diff --git a/Rocket.Chat.xcodeproj/project.pbxproj b/Rocket.Chat.xcodeproj/project.pbxproj index dbb86a552c..6a847ff906 100644 --- a/Rocket.Chat.xcodeproj/project.pbxproj +++ b/Rocket.Chat.xcodeproj/project.pbxproj @@ -190,6 +190,9 @@ 77C2612E1F97453600724A1F /* TextFieldSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77C2612B1F97453600724A1F /* TextFieldSpec.swift */; }; 77CCB6BE1F8D0597004BBF67 /* DictionaryExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77CCB6BD1F8D0597004BBF67 /* DictionaryExtensions.swift */; }; 7DE1B07114BBD1D46E9CC71B /* Pods_Rocket_Chat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F5191CD6C53AEA006C82524 /* Pods_Rocket_Chat.framework */; }; + 80054CF11FD9505A00F5ECF9 /* SendMessageRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80054CF01FD9505A00F5ECF9 /* SendMessageRequest.swift */; }; + 80054CF31FD951B100F5ECF9 /* MessagesClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80054CF21FD951B100F5ECF9 /* MessagesClient.swift */; }; + 80054CF51FD96AFE00F5ECF9 /* MessagesClientSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80054CF41FD96AFE00F5ECF9 /* MessagesClientSpec.swift */; }; 800E22841F8500A200DA84F1 /* MessagesListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 800E22831F8500A200DA84F1 /* MessagesListViewController.swift */; }; 800E22861F8507E400DA84F1 /* SubscriptionMessagesRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 800E22851F8507E400DA84F1 /* SubscriptionMessagesRequest.swift */; }; 800FCD3E1F72893E00D9A692 /* MembersListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 800FCD3D1F72893E00D9A692 /* MembersListViewController.swift */; }; @@ -512,6 +515,9 @@ 77C2612A1F97453600724A1F /* SelectFieldSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectFieldSpec.swift; sourceTree = ""; }; 77C2612B1F97453600724A1F /* TextFieldSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldSpec.swift; sourceTree = ""; }; 77CCB6BD1F8D0597004BBF67 /* DictionaryExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryExtensions.swift; sourceTree = ""; }; + 80054CF01FD9505A00F5ECF9 /* SendMessageRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendMessageRequest.swift; sourceTree = ""; }; + 80054CF21FD951B100F5ECF9 /* MessagesClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesClient.swift; sourceTree = ""; }; + 80054CF41FD96AFE00F5ECF9 /* MessagesClientSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesClientSpec.swift; sourceTree = ""; }; 800E22831F8500A200DA84F1 /* MessagesListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MessagesListViewController.swift; path = Controllers/Chat/MessagesListViewController.swift; sourceTree = ""; }; 800E22851F8507E400DA84F1 /* SubscriptionMessagesRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionMessagesRequest.swift; sourceTree = ""; }; 800FCD3D1F72893E00D9A692 /* MembersListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MembersListViewController.swift; path = Controllers/Chat/MembersListViewController.swift; sourceTree = ""; }; @@ -1307,6 +1313,7 @@ 8013F86E1FD6B59D00EE1A4E /* Clients */ = { isa = PBXGroup; children = ( + 80054CF21FD951B100F5ECF9 /* MessagesClient.swift */, 8013F8701FD6B5B000EE1A4E /* CommandsClient.swift */, 8013F86F1FD6B5B000EE1A4E /* InfoClient.swift */, ); @@ -1332,6 +1339,7 @@ 8013F87E1FD6B66900EE1A4E /* Clients */ = { isa = PBXGroup; children = ( + 80054CF41FD96AFE00F5ECF9 /* MessagesClientSpec.swift */, 8013F87F1FD6B6C600EE1A4E /* CommandsClientSpec.swift */, 8013F8801FD6B6C600EE1A4E /* InfoClientSpec.swift */, ); @@ -1407,6 +1415,7 @@ isa = PBXGroup; children = ( 806C59A11FBB0BD600C32D0A /* PostMessageRequest.swift */, + 80054CF01FD9505A00F5ECF9 /* SendMessageRequest.swift */, ); path = Message; sourceTree = ""; @@ -2107,6 +2116,7 @@ 80113DF81F98330C0048F2C2 /* OAuthViewController.swift in Sources */, 41BD37E11E290F2900CBC4C2 /* UserModelMapping.swift in Sources */, 412BCC871E55C6B800F7F4EE /* ChatMessageTextView.swift in Sources */, + 80054CF31FD951B100F5ECF9 /* MessagesClient.swift in Sources */, 8013F86D1FD6B59A00EE1A4E /* APIClient.swift in Sources */, 414D99161EA0E7CB0020F7E9 /* SignupViewController.swift in Sources */, 800FCD4F1F728EC800D9A692 /* ChannelInfoUserCell.swift in Sources */, @@ -2189,6 +2199,7 @@ D32E28251DFD86C300D6019C /* LauncherProtocol.swift in Sources */, 41DF76E31D2C50710028DBF8 /* AppDelegate.swift in Sources */, D18675EC1F716A0D00406FB4 /* LoginRequest.swift in Sources */, + 80054CF11FD9505A00F5ECF9 /* SendMessageRequest.swift in Sources */, 4174CB131D2D99960086DAC8 /* BaseViewController.swift in Sources */, 897083D31F8CF08100233561 /* CheckTableViewCell.swift in Sources */, 597ECBA21E3708A50041C5C5 /* DataExtension.swift in Sources */, @@ -2257,6 +2268,7 @@ 418C74451FA3820F00499577 /* CompoundPickerViewDelegateSpec.swift in Sources */, 8013F8821FD6B6C600EE1A4E /* InfoClientSpec.swift in Sources */, 77C261251F97445300724A1F /* AuthSettingsSpec.swift in Sources */, + 80054CF51FD96AFE00F5ECF9 /* MessagesClientSpec.swift in Sources */, 411498E51FC7B8D500D66542 /* AttachmentSpec.swift in Sources */, 8013F87C1FD6B64500EE1A4E /* MockAPI.swift in Sources */, 41DC7A221D386B4700896FC0 /* StringExtensionSpec.swift in Sources */, diff --git a/Rocket.Chat/API/Clients/MessagesClient.swift b/Rocket.Chat/API/Clients/MessagesClient.swift new file mode 100644 index 0000000000..b4a3714a3f --- /dev/null +++ b/Rocket.Chat/API/Clients/MessagesClient.swift @@ -0,0 +1,56 @@ +// +// MessagesClient.swift +// Rocket.Chat +// +// Created by Matheus Cardoso on 12/7/17. +// Copyright © 2017 Rocket.Chat. All rights reserved. +// + +import RealmSwift +import SwiftyJSON + +struct MessagesClient: APIClient { + let api: AnyAPIFetcher + + func sendMessage(text: String, subscription: Subscription, id: String = String.random(18), user: User? = AuthManager.currentUser(), realm: Realm? = Realm.shared) { + let message = Message() + message.internalType = "" + message.createdAt = Date.serverDate + message.text = text + message.subscription = subscription + message.user = user + message.identifier = id + message.temporary = true + + try? realm?.write { + realm?.add(message) + } + + func updateMessage(json: JSON) { + DispatchQueue.main.async { + try? realm?.write { + message.temporary = false + message.map(json, realm: realm) + realm?.add(message, update: true) + } + + MessageTextCacheManager.shared.update(for: message, completion: nil) + } + } + + api.fetch(SendMessageRequest(id: id, roomId: subscription.rid, text: text), succeeded: { result in + guard let message = result.raw?["message"] else { return } + updateMessage(json: message) + }, errored: { error in + switch error { + case .version: + // TODO: Remove SendMessage Fallback + old methods after Rocket.Chat 1.0 + SubscriptionManager.sendTextMessage(message, completion: { response in + updateMessage(json: response.result["result"]) + }) + default: + break + } + }) + } +} diff --git a/Rocket.Chat/API/Requests/Message/SendMessageRequest.swift b/Rocket.Chat/API/Requests/Message/SendMessageRequest.swift new file mode 100644 index 0000000000..91ec3f95a0 --- /dev/null +++ b/Rocket.Chat/API/Requests/Message/SendMessageRequest.swift @@ -0,0 +1,43 @@ +// +// SendMessageRequest.swift +// Rocket.Chat +// +// Created by Matheus Cardoso on 12/7/17. +// Copyright © 2017 Rocket.Chat. All rights reserved. +// + +import SwiftyJSON + +typealias SendMessageResult = APIResult + +class SendMessageRequest: APIRequest { + let method = "POST" + let path = "/api/v1/chat.sendMessage" + let requiredVersion = Version(0, 60, 0) + + let id: String + let roomId: String + let text: String + + init(id: String, roomId: String, text: String) { + self.id = id + self.roomId = roomId + self.text = text + } + + func body() -> Data? { + let body = JSON([ + "message": [ + "_id": id, + "rid": roomId, + "msg": text + ] + ]) + + return body.rawString()?.data(using: .utf8) + } +} + +extension APIResult where T == SendMessageRequest { + +} diff --git a/Rocket.Chat/Controllers/Chat/ChatViewController.swift b/Rocket.Chat/Controllers/Chat/ChatViewController.swift index 4c3be89c2d..2a8d7cd5ce 100644 --- a/Rocket.Chat/Controllers/Chat/ChatViewController.swift +++ b/Rocket.Chat/Controllers/Chat/ChatViewController.swift @@ -384,33 +384,8 @@ final class ChatViewController: SLKTextViewController, Alerter { return } - var message: Message? - Realm.executeOnMainThread({ (realm) in - message = Message() - message?.internalType = "" - message?.createdAt = Date.serverDate - message?.text = text - message?.subscription = subscription - message?.identifier = String.random(18) - message?.temporary = true - message?.user = AuthManager.currentUser() - - if let message = message { - realm.add(message) - } - }) - - if let message = message { - SubscriptionManager.sendTextMessage(message) { response in - Realm.executeOnMainThread({ (realm) in - message.temporary = false - message.map(response.result["result"], realm: realm) - realm.add(message, update: true) - - MessageTextCacheManager.shared.update(for: message, completion: nil) - }) - } - } + guard let client = API.current()?.client(MessagesClient.self) else { return } + client.sendMessage(text: text, subscription: subscription) } fileprivate func updateCellForMessage(identifier: String) { diff --git a/Rocket.ChatTests/API/Clients/MessagesClientSpec.swift b/Rocket.ChatTests/API/Clients/MessagesClientSpec.swift new file mode 100644 index 0000000000..80b60edaa4 --- /dev/null +++ b/Rocket.ChatTests/API/Clients/MessagesClientSpec.swift @@ -0,0 +1,55 @@ +// +// MessagesClientSpec.swift +// Rocket.ChatTests +// +// Created by Matheus Cardoso on 12/7/17. +// Copyright © 2017 Rocket.Chat. All rights reserved. +// + +import XCTest +import SwiftyJSON + +@testable import Rocket_Chat + +class MessagesClientSpec: XCTestCase, RealmTestCase { + func testSendMessage() { + let api = MockAPI() + let realm = testRealm() + let client = MessagesClient(api: api) + + api.nextResult = JSON([ + "success": true, + "message": [ + "mentions": [], + "_id": "a43SYFpMdjEAdM0mrH", + "_updatedAt": "2017-12-07T12:30:38.384Z", + "channels": [], + "rid": "GENERAL", + "u": [ + "name": "Matheus Cardoso", + "username": "matheus.cardoso", + "_id": "ERoZg2xpgcDnXbCJu" + ], + "ts": "2017-12-07T12:30:38.382Z", + "msg": "Test" + ] + ]) + + let user = User.testInstance() + let subscription = Subscription.testInstance() + + client.sendMessage(text: "test", subscription: subscription, id: "a43SYFpMdjEAdM0mrH", user: user, realm: realm) + + let messages = realm.objects(Message.self) + XCTAssertEqual(messages.count, 1) + XCTAssertEqual(realm.objects(Message.self).first?.temporary, true) + + let expectation = XCTestExpectation(description: "message updated in realm") + DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: { + if realm.objects(Message.self).first?.temporary == false { + expectation.fulfill() + } + }) + wait(for: [expectation], timeout: 1.1) + } +}