diff --git a/Rocket.Chat.xcodeproj/project.pbxproj b/Rocket.Chat.xcodeproj/project.pbxproj index 0d1060abff..78a64ba302 100644 --- a/Rocket.Chat.xcodeproj/project.pbxproj +++ b/Rocket.Chat.xcodeproj/project.pbxproj @@ -103,6 +103,8 @@ 335F4F03207A31D3005E14AF /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335F4F02207A31D3005E14AF /* NotificationManager.swift */; }; 3397604920EA72EE0054758A /* RuntimeAttributesThemeableViewSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3397604820EA72EE0054758A /* RuntimeAttributesThemeableViewSpec.swift */; }; 339B692B2050449700F97392 /* KeyboardFrameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 339B6929205042D300F97392 /* KeyboardFrameView.swift */; }; + 33A1BB0520FE312900AFA7D4 /* ChatMessageVideoView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 412A95D51FD94ED000954AA6 /* ChatMessageVideoView.xib */; }; + 33A1BB0720FF75D600AFA7D4 /* BaseSubscriptionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33A1BB0620FF75D600AFA7D4 /* BaseSubscriptionCell.swift */; }; 33A5C9BE206A561400FE1C8F /* emojiNames.json in Resources */ = {isa = PBXBuildFile; fileRef = 33A5C9BD206A561400FE1C8F /* emojiNames.json */; }; 33A5C9CA206A565800FE1C8F /* symbols.json in Resources */ = {isa = PBXBuildFile; fileRef = 33A5C9C1206A565800FE1C8F /* symbols.json */; }; 33A5C9CB206A565800FE1C8F /* travel.json in Resources */ = {isa = PBXBuildFile; fileRef = 33A5C9C2206A565800FE1C8F /* travel.json */; }; @@ -177,7 +179,6 @@ 412731D51DE0A55C00FC45A0 /* ChatPreviewModeView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 412731D41DE0A55C00FC45A0 /* ChatPreviewModeView.xib */; }; 412731D71DE0A89B00FC45A0 /* ChatPreviewModeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 412731D61DE0A89B00FC45A0 /* ChatPreviewModeView.swift */; }; 412A95D61FD94ED000954AA6 /* ChatMessageVideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 412A95D41FD94ED000954AA6 /* ChatMessageVideoView.swift */; }; - 412A95D71FD94ED000954AA6 /* ChatMessageVideoView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 412A95D51FD94ED000954AA6 /* ChatMessageVideoView.xib */; }; 412BCC851E55C6A300F7F4EE /* ChatMessageTextView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 412BCC841E55C6A300F7F4EE /* ChatMessageTextView.xib */; }; 412BCC871E55C6B800F7F4EE /* ChatMessageTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 412BCC861E55C6B800F7F4EE /* ChatMessageTextView.swift */; }; 412BCC8B1E55D4AA00F7F4EE /* UIColorCSSColorsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 412BCC8A1E55D4AA00F7F4EE /* UIColorCSSColorsExtension.swift */; }; @@ -736,7 +737,6 @@ B5893BF61F6C4B1D00365768 /* UserReviewManagerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5893BF51F6C4B1D00365768 /* UserReviewManagerSpec.swift */; }; D10E9C1A1F643457007F1796 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D10E9C191F643457007F1796 /* Channel.swift */; }; D10E9C1E1F643474007F1796 /* ChannelModelMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = D10E9C1D1F643474007F1796 /* ChannelModelMapping.swift */; }; - D10E9C201F6434A7007F1796 /* NSRangeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D10E9C1F1F6434A7007F1796 /* NSRangeExtensions.swift */; }; D10E9C221F643616007F1796 /* MentionModelMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = D10E9C211F643616007F1796 /* MentionModelMapping.swift */; }; D12D34031F69C76400AED992 /* SubscriptionExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D12D34021F69C76400AED992 /* SubscriptionExtensions.swift */; }; D1411A2A1F6777F300D6EDF7 /* ChannelSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1411A291F6777F300D6EDF7 /* ChannelSpec.swift */; }; @@ -903,6 +903,7 @@ 335F4F02207A31D3005E14AF /* NotificationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; 3397604820EA72EE0054758A /* RuntimeAttributesThemeableViewSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeAttributesThemeableViewSpec.swift; sourceTree = ""; }; 339B6929205042D300F97392 /* KeyboardFrameView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardFrameView.swift; sourceTree = ""; }; + 33A1BB0620FF75D600AFA7D4 /* BaseSubscriptionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseSubscriptionCell.swift; sourceTree = ""; }; 33A5C9BD206A561400FE1C8F /* emojiNames.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = emojiNames.json; sourceTree = ""; }; 33A5C9C1206A565800FE1C8F /* symbols.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = symbols.json; sourceTree = ""; }; 33A5C9C2206A565800FE1C8F /* travel.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = travel.json; sourceTree = ""; }; @@ -1539,7 +1540,6 @@ BCF38696E8EC385488688390 /* Pods-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rocket.Chat.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Rocket.Chat/Pods-Rocket.Chat.debug.xcconfig"; sourceTree = ""; }; D10E9C191F643457007F1796 /* Channel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Channel.swift; sourceTree = ""; }; D10E9C1D1F643474007F1796 /* ChannelModelMapping.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelModelMapping.swift; sourceTree = ""; }; - D10E9C1F1F6434A7007F1796 /* NSRangeExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSRangeExtensions.swift; sourceTree = ""; }; D10E9C211F643616007F1796 /* MentionModelMapping.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MentionModelMapping.swift; sourceTree = ""; }; D12D34021F69C76400AED992 /* SubscriptionExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubscriptionExtensions.swift; sourceTree = ""; }; D1411A291F6777F300D6EDF7 /* ChannelSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelSpec.swift; sourceTree = ""; }; @@ -2235,7 +2235,6 @@ 41E991D31D343A9F00BDDCA8 /* DateExtension.swift */, 77CCB6BD1F8D0597004BBF67 /* DictionaryExtensions.swift */, 41FC9E07209B3A6300FED485 /* NSAttributedStringExtensions.swift */, - D10E9C1F1F6434A7007F1796 /* NSRangeExtensions.swift */, 80A2A2AA2073BD0800857DAF /* RealmCurrent.swift */, 8076FDA8204853DE00114F28 /* RealmExecute.swift */, 8076FDA32048533000114F28 /* String+Random.swift */, @@ -2304,6 +2303,7 @@ 4147CE7C1F5EAAB300C322C3 /* ServerCell.swift */, 41FBF4EA20BD8C650080D00D /* ServerCell.xib */, 4192054B1D52F4FC004EEC5F /* SubscriptionCell.swift */, + 33A1BB0620FF75D600AFA7D4 /* BaseSubscriptionCell.swift */, 41778EB820ED4C2C007F72F9 /* SubscriptionCellCondensed.swift */, 41DE687C20C6D57F00AA5EC8 /* SubscriptionSortingCell.swift */, 41DE688020C6EBE600AA5EC8 /* SubscriptionSortingCell.xib */, @@ -3677,7 +3677,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 0940; ORGANIZATIONNAME = Rocket.Chat; TargetAttributes = { 41DF76DE1D2C50710028DBF8 = { @@ -3761,10 +3761,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 412A95D71FD94ED000954AA6 /* ChatMessageVideoView.xib in Resources */, + 33A1BB0520FE312900AFA7D4 /* ChatMessageVideoView.xib in Resources */, 14F8A25D202E64B200175FDC /* BnW-29@3x.png in Resources */, 411D40CD20D28150001A1035 /* ChannelInfoBasicCell.xib in Resources */, - 412A95D71FD94ED000954AA6 /* ChatMessageVideoView.xib in Resources */, 33A5C9CC206A565800FE1C8F /* regional.json in Resources */, 412EF3C62050507C001689A3 /* ReusableViewText.xib in Resources */, 14F8A224202E5CBF00175FDC /* Black-60@3x.png in Resources */, @@ -4255,7 +4254,6 @@ 4153E80520504BE700FBC26B /* ReusableViewText.swift in Sources */, 419ECCA61F3CA58A005F224B /* ChatControllerDocuments.swift in Sources */, 14BAFADE20308EE50054A2E6 /* DrawingBrushWidthViewController.swift in Sources */, - D10E9C201F6434A7007F1796 /* NSRangeExtensions.swift in Sources */, 807FB53D2044B49800E21429 /* Emojione+Transform.swift in Sources */, 7798B4191F852D670074B2F4 /* CustomField.swift in Sources */, 4156250820BEDCD100D20576 /* ServersListViewModel.swift in Sources */, @@ -4528,6 +4526,7 @@ 413FB6C11FE17D7D00F010AA /* UIViewExtentions.swift in Sources */, 8076FDB0204856AF00114F28 /* AuthCanBlockMessage.swift in Sources */, 8076FDA9204853DE00114F28 /* RealmExecute.swift in Sources */, + 33A1BB0720FF75D600AFA7D4 /* BaseSubscriptionCell.swift in Sources */, 806EFA5E209BF1AC00D0D650 /* SubscriptionReadRequest.swift in Sources */, 9960C8302063F0C8004A034C /* WebBrowserTableViewController.swift in Sources */, 140A95E4202F536D003FD564 /* DrawingViewController.swift in Sources */, diff --git a/Rocket.Chat.xcodeproj/xcshareddata/xcschemes/Rocket.Chat.xcscheme b/Rocket.Chat.xcodeproj/xcshareddata/xcschemes/Rocket.Chat.xcscheme index ad2691ec16..bc4478708f 100644 --- a/Rocket.Chat.xcodeproj/xcshareddata/xcschemes/Rocket.Chat.xcscheme +++ b/Rocket.Chat.xcodeproj/xcshareddata/xcschemes/Rocket.Chat.xcscheme @@ -1,6 +1,6 @@ (_ request: R, options: APIRequestOptionSet = [], sessionDelegate: URLSessionTaskDelegate? = nil, completion: ((_ result: APIResponse) -> Void)?) -> URLSessionTask? { diff --git a/Rocket.Chat/API/Clients/MessagesClient.swift b/Rocket.Chat/API/Clients/MessagesClient.swift index f1d338fa20..7467260be7 100644 --- a/Rocket.Chat/API/Clients/MessagesClient.swift +++ b/Rocket.Chat/API/Clients/MessagesClient.swift @@ -12,6 +12,7 @@ import SwiftyJSON struct MessagesClient: APIClient { let api: AnyAPIFetcher + // swiftlint:disable function_body_length func sendMessage(_ message: Message, subscription: Subscription, realm: Realm? = Realm.current) { guard let id = message.identifier else { return } let subscriptionIdentifier = subscription.rid @@ -28,7 +29,12 @@ struct MessagesClient: APIClient { } func updateMessage(json: JSON) { + if message.isInvalidated { + return + } + let server = AuthManager.selectedServerHost() + AnalyticsManager.log(event: .messageSent(subscriptionType: subscription.type.rawValue, server: server)) try? realm?.write { @@ -44,6 +50,10 @@ struct MessagesClient: APIClient { func setMessageOffline() { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + if message.isInvalidated { + return + } + try? realm?.write { message.temporary = false message.failed = true @@ -70,7 +80,9 @@ struct MessagesClient: APIClient { switch error { case .version: SubscriptionManager.sendTextMessage(message, completion: { response in - updateMessage(json: response.result["result"]) + DispatchQueue.main.async { + updateMessage(json: response.result["result"]) + } }) default: setMessageOffline() @@ -80,6 +92,8 @@ struct MessagesClient: APIClient { } } + // swiftlint:enable function_body_length + func sendMessage(text: String, subscription: Subscription, id: String = String.random(18), user: User? = AuthManager.currentUser(), realm: Realm? = Realm.current) { let message = Message() message.internalType = "" @@ -178,6 +192,7 @@ struct MessagesClient: APIClient { return true } + // swiftlint:disable function_body_length @discardableResult func reactMessage(_ message: Message, emoji: String, user: User? = AuthManager.currentUser(), realm: Realm? = Realm.current) -> Bool { guard let id = message.identifier, let username = user?.username else { @@ -233,11 +248,13 @@ struct MessagesClient: APIClient { case .version: // version fallback MessageManager.react(message, emoji: emoji, completion: { _ in - AnalyticsManager.log( - event: .reaction( - subscriptionType: message.subscription?.type.rawValue ?? "" + DispatchQueue.main.async { + AnalyticsManager.log( + event: .reaction( + subscriptionType: message.subscription?.type.rawValue ?? "" + ) ) - ) + } }) default: Alert.defaultError.present() @@ -247,4 +264,6 @@ struct MessagesClient: APIClient { return true } + + // swiftlint:enable function_body_length } diff --git a/Rocket.Chat/API/Clients/SpotlightClient.swift b/Rocket.Chat/API/Clients/SpotlightClient.swift index 885a627e9d..2e800b583a 100644 --- a/Rocket.Chat/API/Clients/SpotlightClient.swift +++ b/Rocket.Chat/API/Clients/SpotlightClient.swift @@ -69,7 +69,7 @@ struct SpotlightClient: APIClient { }, completion: { completion(resource.raw, false) }) - case .error(let _): + case .error: completion(nil, true) } } diff --git a/Rocket.Chat/API/Requests/General/PublicSettingsRequest.swift b/Rocket.Chat/API/Requests/General/PublicSettingsRequest.swift index 9b63bddd4b..e8b3df03a9 100644 --- a/Rocket.Chat/API/Requests/General/PublicSettingsRequest.swift +++ b/Rocket.Chat/API/Requests/General/PublicSettingsRequest.swift @@ -38,6 +38,7 @@ final class PublicSettingsRequest: APIRequest { "CAS_enabled", "CAS_login_url", "API_Gitlab_URL", + "API_Wordpress_URL", "Accounts_ShowFormLogin", "Accounts_RegistrationForm", "Accounts_PasswordReset", @@ -50,6 +51,7 @@ final class PublicSettingsRequest: APIRequest { "Accounts_AllowUsernameChange", "Accounts_AllowEmailChange", "Accounts_AllowPasswordChange", + "Accounts_OAuth_Wordpress_server_type", "FileUpload_Storage_Type", "Message_HideType_uj", "Message_HideType_ul", diff --git a/Rocket.Chat/API/Requests/General/SpotlightRequest.swift b/Rocket.Chat/API/Requests/General/SpotlightRequest.swift index 00a9ed04be..d384052ac5 100644 --- a/Rocket.Chat/API/Requests/General/SpotlightRequest.swift +++ b/Rocket.Chat/API/Requests/General/SpotlightRequest.swift @@ -18,7 +18,11 @@ final class SpotlightRequest: APIRequest { let query: String? init(query: String) { - self.query = "query=\(query)" + if let encodedQuery = query.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) { + self.query = "query=\(encodedQuery)" + } else { + self.query = "" + } } } diff --git a/Rocket.Chat/Controllers/Auth/AuthTableViewController.swift b/Rocket.Chat/Controllers/Auth/AuthTableViewController.swift index 6eab5bda65..112c78ee4b 100644 --- a/Rocket.Chat/Controllers/Auth/AuthTableViewController.swift +++ b/Rocket.Chat/Controllers/Auth/AuthTableViewController.swift @@ -124,12 +124,14 @@ class AuthTableViewController: BaseTableViewController { override func viewDidLoad() { super.viewDidLoad() + title = serverURL.host guard let settings = serverPublicSettings else { return } if !settings.isUsernameEmailAuthenticationEnabled { - emailAuthRow.registerButton.isHidden = true + emailAuthRow.isHidden = true + authSeparatorRow.isHidden = true } else { emailAuthRow.registerButton.isHidden = settings.registrationForm != .isPublic } @@ -190,7 +192,7 @@ class AuthTableViewController: BaseTableViewController { return } - let loginService = loginServices[button.tag] + let loginService = LoginService(value: loginServices[button.tag]) if loginService.service == "gitlab", let url = serverPublicSettings?.gitlabUrl { loginServices[button.tag].serverUrl = url try? realm.write { @@ -198,6 +200,25 @@ class AuthTableViewController: BaseTableViewController { } } + if loginService.service == "wordpress" { + if let url = serverPublicSettings?.wordpressUrl, !url.isEmpty { + loginService.serverUrl = url + + /* + NOTE: If should be this, but API is broken + serverPublicSettings?.oauthWordpressServerType == "custom" + */ + + loginService.mapWordPressCustom() + } else { // oauthWordPressServerType == wordpress-com + loginService.mapWordPress() + } // missing implementation for wp-oauth-server + + try? realm.write { + realm.add(loginService, update: true) + } + } + switch loginService.type { case .cas: presentCASViewController(for: loginService) @@ -328,7 +349,11 @@ extension AuthTableViewController { return LoginServiceTableViewCell.rowHeight case kEmailAuthSection: - return loginServices.count > 0 ? EmailAuthTableViewCell.rowHeightBelowSeparator : EmailAuthTableViewCell.rowHeight + if loginServices.count > 0 { + return emailAuthRow.isHidden ? .leastNonzeroMagnitude : EmailAuthTableViewCell.rowHeightBelowSeparator + } + + return EmailAuthTableViewCell.rowHeight default: return 0 } diff --git a/Rocket.Chat/Controllers/Auth/ConnectServerViewController.swift b/Rocket.Chat/Controllers/Auth/ConnectServerViewController.swift index 7adfe245ff..0440829cf9 100644 --- a/Rocket.Chat/Controllers/Auth/ConnectServerViewController.swift +++ b/Rocket.Chat/Controllers/Auth/ConnectServerViewController.swift @@ -23,10 +23,20 @@ final class ConnectServerViewController: BaseViewController { var shouldAutoConnect = false var url: URL? { guard var urlText = textFieldServerURL.text else { return URL(string: defaultURL, scheme: "https") } + if urlText.isEmpty { urlText = defaultURL } - return URL(string: urlText, scheme: "https") + + // Remove all the whitespaces from the string + urlText = urlText.removingWhitespaces() + + // Add .rocket.chat in the end if it's only one string + if !urlText.contains(".") { + urlText += ".rocket.chat" + } + + return URL(string: urlText, scheme: "https") } var serverPublicSettings: AuthSettings? diff --git a/Rocket.Chat/Controllers/Base/BaseViewController.swift b/Rocket.Chat/Controllers/Base/BaseViewController.swift index 257bb2a7d8..bdba384da5 100644 --- a/Rocket.Chat/Controllers/Base/BaseViewController.swift +++ b/Rocket.Chat/Controllers/Base/BaseViewController.swift @@ -61,6 +61,8 @@ class BaseViewController: UIViewController, PopPushDelegate, NavigationBarTransp target: nil, action: nil ) + + popoverPresentationController?.backgroundColor = view.theme?.focusedBackground } override func viewWillAppear(_ animated: Bool) { diff --git a/Rocket.Chat/Controllers/Chat/ChatControllerMessageActions.swift b/Rocket.Chat/Controllers/Chat/ChatControllerMessageActions.swift index 1fefcf1950..b8db1a2bcb 100644 --- a/Rocket.Chat/Controllers/Chat/ChatControllerMessageActions.swift +++ b/Rocket.Chat/Controllers/Chat/ChatControllerMessageActions.swift @@ -39,6 +39,7 @@ extension ChatViewController { present(alert, animated: true, completion: nil) } + // swiftlint:disable function_body_length func actionsForMessage(_ message: Message, view: UIView) -> [UIAlertAction] { guard let messageUser = message.user, @@ -124,6 +125,8 @@ extension ChatViewController { return actions } + // swiftlint:enable function_body_length + func actionsForFailedMessage(_ message: Message) -> [UIAlertAction] { let resend = UIAlertAction(title: localized("chat.message.actions.resend"), style: .default, handler: { _ in diff --git a/Rocket.Chat/Controllers/Chat/ChatViewController.swift b/Rocket.Chat/Controllers/Chat/ChatViewController.swift index 75eaeefb19..537dc124eb 100644 --- a/Rocket.Chat/Controllers/Chat/ChatViewController.swift +++ b/Rocket.Chat/Controllers/Chat/ChatViewController.swift @@ -857,46 +857,22 @@ final class ChatViewController: SLKTextViewController { isAppendingMessages = true - var tempMessages: [Message] = [] - for message in messages { - tempMessages.append(Message(value: message)) - } - - DispatchQueue.global(qos: .background).async { - var objs: [ChatData] = [] - var newMessages: [Message] = [] - - // Do not add duplicated messages - for message in tempMessages { - var insert = true - - for obj in self.dataController.data where message.identifier == obj.message?.identifier { - insert = false - } + let tempMessages = messages.map { Message(value: $0) } - if insert { - newMessages.append(message) - } - } - - // Normalize data into ChatData object - for message in newMessages { - guard let createdAt = message.createdAt else { continue } - var obj = ChatData(type: .message, timestamp: createdAt) - obj.message = message - objs.append(obj) - } + DispatchQueue.global(qos: .background).async { [weak self] in + guard let strongSelf = self else { return } + let chatData = strongSelf.insertMessages(messages: tempMessages) // No new data? Don't update it then - if objs.count == 0 { - if self.dataController.dismissUnreadSeparator { + if chatData.count == 0 { + if strongSelf.dataController.dismissUnreadSeparator { DispatchQueue.main.async { - self.syncCollectionView() + strongSelf.syncCollectionView() } } DispatchQueue.main.async { - self.isAppendingMessages = false + strongSelf.isAppendingMessages = false completion?() } @@ -905,17 +881,45 @@ final class ChatViewController: SLKTextViewController { DispatchQueue.main.async { collectionView.performBatchUpdates({ - let (indexPaths, removedIndexPaths) = self.dataController.insert(objs) + let (indexPaths, removedIndexPaths) = strongSelf.dataController.insert(chatData) collectionView.insertItems(at: indexPaths) collectionView.deleteItems(at: removedIndexPaths) }, completion: { _ in - self.isAppendingMessages = false + strongSelf.isAppendingMessages = false completion?() }) } } } + private func insertMessages(messages: [Message]) -> [ChatData] { + var objs: [ChatData] = [] + var newMessages: [Message] = [] + + // Do not add duplicated messages + for message in messages { + var insert = true + + for obj in self.dataController.data where message.identifier == obj.message?.identifier { + insert = false + } + + if insert { + newMessages.append(message) + } + } + + // Normalize data into ChatData object + for message in newMessages { + guard let createdAt = message.createdAt else { continue } + var obj = ChatData(type: .message, timestamp: createdAt) + obj.message = message + objs.append(obj) + } + + return objs + } + private func showChatPreviewModeView() { chatPreviewModeView?.removeFromSuperview() @@ -1152,27 +1156,8 @@ extension ChatViewController: UICollectionViewDelegateFlowLayout { return CGSize(width: fullWidth, height: value) } - if obj.type == .header { - let isDirectMessage = subscription.type == .directMessage - let directMessageHeaderSize = CGSize(width: fullWidth, height: ChatDirectMessageHeaderCell.minimumHeight) - let channelHeaderSize = CGSize(width: fullWidth, height: ChatChannelHeaderCell.minimumHeight) - return isDirectMessage ? directMessageHeaderSize : channelHeaderSize - } - - if obj.type == .loader { - return CGSize(width: fullWidth, height: ChatLoaderCell.minimumHeight) - } - - if obj.type == .daySeparator { - return CGSize(width: fullWidth, height: ChatMessageDaySeparator.minimumHeight) - } - - if obj.type == .unreadSeparator { - if dataController.dismissUnreadSeparator { - return CGSize(width: fullWidth, height: 0) - } - - return CGSize(width: fullWidth, height: ChatMessageUnreadSeparator.minimumHeight) + if let value = sizeForChatObject(obj, subscription: subscription, fullWidth: fullWidth) { + return value } if let message = obj.message { @@ -1188,6 +1173,33 @@ extension ChatViewController: UICollectionViewDelegateFlowLayout { return CGSize(width: fullWidth, height: 40) } + + func sizeForChatObject(_ obj: ChatData, subscription: Subscription, fullWidth: CGFloat) -> CGSize? { + if obj.type == .header { + let isDirectMessage = subscription.type == .directMessage + let directMessageHeaderSize = CGSize(width: fullWidth, height: ChatDirectMessageHeaderCell.minimumHeight) + let channelHeaderSize = CGSize(width: fullWidth, height: ChatChannelHeaderCell.minimumHeight) + return isDirectMessage ? directMessageHeaderSize : channelHeaderSize + } + + if obj.type == .loader { + return CGSize(width: fullWidth, height: ChatLoaderCell.minimumHeight) + } + + if obj.type == .daySeparator { + return CGSize(width: fullWidth, height: ChatMessageDaySeparator.minimumHeight) + } + + if obj.type == .unreadSeparator { + if dataController.dismissUnreadSeparator { + return CGSize(width: fullWidth, height: 0) + } + + return CGSize(width: fullWidth, height: ChatMessageUnreadSeparator.minimumHeight) + } + + return nil + } } // MARK: UIScrollViewDelegate diff --git a/Rocket.Chat/Controllers/Notification/NotificationViewController.xib b/Rocket.Chat/Controllers/Notification/NotificationViewController.xib index b8db38fec0..1cbc360928 100644 --- a/Rocket.Chat/Controllers/Notification/NotificationViewController.xib +++ b/Rocket.Chat/Controllers/Notification/NotificationViewController.xib @@ -87,7 +87,7 @@ - + diff --git a/Rocket.Chat/Controllers/Subscriptions/SubscriptionsList/SubscriptionsViewController.swift b/Rocket.Chat/Controllers/Subscriptions/SubscriptionsList/SubscriptionsViewController.swift index adac0266a7..1e77bfe4f9 100644 --- a/Rocket.Chat/Controllers/Subscriptions/SubscriptionsList/SubscriptionsViewController.swift +++ b/Rocket.Chat/Controllers/Subscriptions/SubscriptionsList/SubscriptionsViewController.swift @@ -77,17 +77,15 @@ final class SubscriptionsViewController: BaseViewController { tableView.performBatchUpdates({ tableView.deleteRows(at: changes.deletions, with: .automatic) tableView.insertRows(at: changes.insertions, with: .automatic) + tableView.reloadRows(at: changes.modifications, with: .none) }, completion: nil) } else { tableView.beginUpdates() tableView.deleteRows(at: changes.deletions, with: .automatic) tableView.insertRows(at: changes.insertions, with: .automatic) + tableView.reloadRows(at: changes.modifications, with: .none) tableView.endUpdates() } - - UIView.performWithoutAnimation { - tableView.reloadRows(at: changes.modifications, with: .automatic) - } } } @@ -122,6 +120,13 @@ final class SubscriptionsViewController: BaseViewController { titleView?.state = SocketManager.sharedInstance.state } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + if !(searchBar?.text?.isEmpty ?? true) { + searchBar?.perform(#selector(becomeFirstResponder), with: nil, afterDelay: 0.1) + } + } + override func viewDidDisappear(_ animated: Bool) { SocketManager.removeConnectionHandler(token: socketHandlerToken) } diff --git a/Rocket.Chat/Controllers/Subscriptions/SubscriptionsList/SubscriptionsViewModel.swift b/Rocket.Chat/Controllers/Subscriptions/SubscriptionsList/SubscriptionsViewModel.swift index 0dd2e40dcd..4b274f020a 100644 --- a/Rocket.Chat/Controllers/Subscriptions/SubscriptionsList/SubscriptionsViewModel.swift +++ b/Rocket.Chat/Controllers/Subscriptions/SubscriptionsList/SubscriptionsViewModel.swift @@ -77,28 +77,37 @@ class SubscriptionsViewModel { API.current()?.client(SpotlightClient.self).search(query: query) { _, _ in } case .notSearching: + var queryItems = queryBase + + func filtered(using predicateFormat: String) -> Results { + let predicate = NSPredicate(format: predicateFormat) + let filteredResult = queryItems.filter(predicate) + queryItems = queryItems.filter(predicate.negation) + return filteredResult + } + if SubscriptionsSortingManager.selectedGroupingOptions.contains(.unread) { - let queryData = queryBase.filter("alert == true") + let queryData = filtered(using: "alert == true") assorter.registerSection(name: localized("subscriptions.unreads"), objects: queryData) } if SubscriptionsSortingManager.selectedGroupingOptions.contains(.favorites) { - let queryData = queryBase.filter("favorite == true") + let queryData = filtered(using: "favorite == true") assorter.registerSection(name: localized("subscriptions.favorites"), objects: queryData) } if SubscriptionsSortingManager.selectedGroupingOptions.contains(.type) { - let queryDataChannels = queryBase.filter("privateType == 'c'") + let queryDataChannels = filtered(using: "privateType == 'c'") assorter.registerSection(name: localized("subscriptions.channels"), objects: queryDataChannels) - let queryDataGroups = queryBase.filter("privateType == 'p'") + let queryDataGroups = filtered(using: "privateType == 'p'") assorter.registerSection(name: localized("subscriptions.groups"), objects: queryDataGroups) - let queryDataDirectMessages = queryBase.filter("privateType == 'd'") + let queryDataDirectMessages = filtered(using: "privateType == 'd'") assorter.registerSection(name: localized("subscriptions.direct_messages"), objects: queryDataDirectMessages) } else { let title = assorter.numberOfSections > 0 ? localized("subscriptions.conversations") : "" - assorter.registerSection(name: title, objects: queryBase) + assorter.registerSection(name: title, objects: queryItems) } } } @@ -139,3 +148,9 @@ extension SubscriptionsViewModel { } } + +private extension NSPredicate { + var negation: NSPredicate { + return NSCompoundPredicate(notPredicateWithSubpredicate: self) + } +} diff --git a/Rocket.Chat/Controllers/User/UserDetail/UserDetail.storyboard b/Rocket.Chat/Controllers/User/UserDetail/UserDetail.storyboard index 7535470d6d..2bbc22b91e 100644 --- a/Rocket.Chat/Controllers/User/UserDetail/UserDetail.storyboard +++ b/Rocket.Chat/Controllers/User/UserDetail/UserDetail.storyboard @@ -1,5 +1,5 @@ - + @@ -18,7 +18,7 @@ - + diff --git a/Rocket.Chat/Controllers/User/UserDetail/UserDetailTableView.swift b/Rocket.Chat/Controllers/User/UserDetail/UserDetailTableView.swift index a94f2a1dd6..5b056ddfbc 100644 --- a/Rocket.Chat/Controllers/User/UserDetail/UserDetailTableView.swift +++ b/Rocket.Chat/Controllers/User/UserDetail/UserDetailTableView.swift @@ -31,6 +31,12 @@ class UserDetailTableView: UITableView { return 220 + topInset + additionalTopInset } + var preferredContentSize: CGSize { + let height = headerViewHeight + contentSize.height + let width = CGFloat(300) + return CGSize(width: width, height: height) + } + lazy var headerView: UIView = { let headerView = tableHeaderView ?? UIView() tableHeaderView = nil diff --git a/Rocket.Chat/Controllers/User/UserDetail/UserDetailViewController.swift b/Rocket.Chat/Controllers/User/UserDetail/UserDetailViewController.swift index 1824c92e72..d57c5d92fc 100644 --- a/Rocket.Chat/Controllers/User/UserDetail/UserDetailViewController.swift +++ b/Rocket.Chat/Controllers/User/UserDetail/UserDetailViewController.swift @@ -16,6 +16,13 @@ class UserDetailViewController: BaseViewController, StoryboardInitializable { return true } + override var preferredContentSize: CGSize { + set { } + get { + return tableView.preferredContentSize + } + } + @IBOutlet weak var backgroundImageView: FLAnimatedImageView! @IBOutlet weak var avatarImageView: FLAnimatedImageView! @IBOutlet weak var nameLabel: UILabel! @@ -64,8 +71,13 @@ class UserDetailViewController: BaseViewController, StoryboardInitializable { } override func viewDidLoad() { - super.viewDidLoad() updateForModel() + super.viewDidLoad() + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + view.applyTheme() } @IBAction func messageDidPress(_ sender: UIButton) { diff --git a/Rocket.Chat/Controllers/WebViewEmbedded/WebViewControllerEmbedded.xib b/Rocket.Chat/Controllers/WebViewEmbedded/WebViewControllerEmbedded.xib index 226148b8d2..ebef237c52 100644 --- a/Rocket.Chat/Controllers/WebViewEmbedded/WebViewControllerEmbedded.xib +++ b/Rocket.Chat/Controllers/WebViewEmbedded/WebViewControllerEmbedded.xib @@ -1,5 +1,5 @@ - + @@ -17,11 +17,11 @@ - + - + @@ -44,12 +44,12 @@ - + - + diff --git a/Rocket.Chat/Extensions/Models/SubscriptionExtensions.swift b/Rocket.Chat/Extensions/Models/SubscriptionExtensions.swift index 9097a6eb6a..7ab76effa3 100644 --- a/Rocket.Chat/Extensions/Models/SubscriptionExtensions.swift +++ b/Rocket.Chat/Extensions/Models/SubscriptionExtensions.swift @@ -108,7 +108,22 @@ extension Results where Element == Subscription { } func filterBy(name: String) -> Results { - return filter("name CONTAINS[cd] %@", name) + let userIdentifiersForDMs: [String] = Realm.current?.objects(User.self).filter(NSCompoundPredicate( + type: .or, + subpredicates: [ + NSPredicate(format: "name CONTAINS[cd] %@", name), + NSPredicate(format: "username CONTAINS[cd] %@", name) + ] + )).compactMap({ $0.identifier }) ?? [] + + return filter(NSCompoundPredicate( + type: .or, + subpredicates: [ + NSPredicate(format: "name CONTAINS[cd] %@", name), + NSPredicate(format: "fname CONTAINS[cd] %@", name), + NSPredicate(format: "otherUserId IN %@", userIdentifiersForDMs) + ] + )) } } diff --git a/Rocket.Chat/Extensions/NSAttributedStringExtensions.swift b/Rocket.Chat/Extensions/NSAttributedStringExtensions.swift index 57f6d4ba14..382db566fe 100644 --- a/Rocket.Chat/Extensions/NSAttributedStringExtensions.swift +++ b/Rocket.Chat/Extensions/NSAttributedStringExtensions.swift @@ -97,9 +97,20 @@ extension NSMutableAttributedString { func highlightMentions(_ mentions: [Mention], currentUsername: String?) { var handledHighlights: [String] = [] + let shouldUseRealName = AuthSettingsManager.shared.settings?.useUserRealName ?? false + + if shouldUseRealName { + mentions.forEach { mention in + let realName = mention.realName ?? "" + let username = mention.username ?? "" + + if shouldUseRealName { + mutableString.setString(string.replacingOccurrences(of: username, with: realName)) + } + } + } mentions.forEach { mention in - let shouldUseRealName = AuthSettingsManager.shared.settings?.useUserRealName ?? false let realName = mention.realName ?? "" let username = mention.username ?? "" @@ -111,20 +122,12 @@ extension NSMutableAttributedString { if username == currentUsername { background = .primaryAction font = .white - - if shouldUseRealName { - mutableString.setString(string.replacingFirstOccurrence(of: username, with: realName)) - } } else if username == "all" || username == "here" { background = .attention font = .white } else { background = .clear font = .link - - if shouldUseRealName && !realName.isEmpty { - mutableString.setString(string.replacingFirstOccurrence(of: username, with: realName)) - } } let ranges = string.ranges(of: "@\(shouldUseRealName ? realName : username)") diff --git a/Rocket.Chat/Extensions/NSRangeExtensions.swift b/Rocket.Chat/Extensions/NSRangeExtensions.swift deleted file mode 100644 index 08539c9a5b..0000000000 --- a/Rocket.Chat/Extensions/NSRangeExtensions.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// NSRangeExtensions.swift -// Rocket.Chat -// -// Created by Matheus Cardoso on 9/8/17. -// Copyright © 2017 Rocket.Chat. All rights reserved. -// - -import Foundation - -public extension NSRange { - private init(string: String, lowerBound: String.Index, upperBound: String.Index) { - let utf16 = string.utf16 - - guard - let lowerBound = lowerBound.samePosition(in: utf16), - let upperBound = upperBound.samePosition(in: utf16) - else { - self.init() - return - } - - let location = utf16.distance(from: utf16.startIndex, to: lowerBound) - let length = utf16.distance(from: lowerBound, to: upperBound) - self.init(location: location, length: length) - } - - public init(_ range: Range, in string: String) { - self.init(string: string, lowerBound: range.lowerBound, upperBound: range.upperBound) - } -} diff --git a/Rocket.Chat/Extensions/UIButton/UIButtonCenterImage.swift b/Rocket.Chat/Extensions/UIButton/UIButtonCenterImage.swift index bfbfc9e0a2..c0afc6d6ec 100644 --- a/Rocket.Chat/Extensions/UIButton/UIButtonCenterImage.swift +++ b/Rocket.Chat/Extensions/UIButton/UIButtonCenterImage.swift @@ -11,8 +11,7 @@ import UIKit extension UIButton { func centerImageHorizontally() { guard - let imageViewWidth = imageView?.frame.width, - let textWidth = titleLabel?.frame.width + let imageViewWidth = imageView?.frame.width else { return } diff --git a/Rocket.Chat/External/RCEmojiKit/Views/EmojiPicker/EmojiPicker.swift b/Rocket.Chat/External/RCEmojiKit/Views/EmojiPicker/EmojiPicker.swift index c9fd1958f6..8f8d26e629 100644 --- a/Rocket.Chat/External/RCEmojiKit/Views/EmojiPicker/EmojiPicker.swift +++ b/Rocket.Chat/External/RCEmojiKit/Views/EmojiPicker/EmojiPicker.swift @@ -197,6 +197,11 @@ final class EmojiPicker: UIView, RCEmojiKitLocalizable { setupCategoriesView() setupCollectionView() } + + override func layoutSubviews() { + super.layoutSubviews() + applyTheme() + } } extension EmojiPicker: UICollectionViewDataSource { @@ -346,28 +351,6 @@ private class EmojiPickerSectionHeaderView: UICollectionReusableView { // MARK: Themeable extension EmojiPicker { - override var theme: Theme? { - guard let theme = super.theme else { return nil } - guard isPopover else { return theme } - let popoverTheme = Theme( - backgroundColor: theme.focusedBackground, - focusedBackground: theme.focusedBackground, - auxiliaryBackground: theme.auxiliaryBackground, - bannerBackground: theme.bannerBackground, - titleText: theme.titleText, - bodyText: theme.bodyText, - controlText: theme.controlText, - auxiliaryText: theme.auxiliaryText, - tintColor: theme.tintColor, - auxiliaryTintColor: theme.auxiliaryTintColor, - hyperlink: theme.hyperlink, - mutedAccent: theme.mutedAccent, - strongAccent: theme.strongAccent, - appearence: theme.appearence - ) - return popoverTheme - } - override func applyTheme() { super.applyTheme() skinToneButton.backgroundColor = currentSkinTone.color diff --git a/Rocket.Chat/External/RCEmojiKit/Views/Reaction/ReactorListView.swift b/Rocket.Chat/External/RCEmojiKit/Views/Reaction/ReactorListView.swift index 182352aabe..15a44c9620 100644 --- a/Rocket.Chat/External/RCEmojiKit/Views/Reaction/ReactorListView.swift +++ b/Rocket.Chat/External/RCEmojiKit/Views/Reaction/ReactorListView.swift @@ -47,7 +47,6 @@ final class ReactorListView: UIView { @IBOutlet weak var reactorTableView: UITableView! { didSet { - reactorTableView.bounces = false reactorTableView.tableFooterView = UIView() reactorTableView.dataSource = self @@ -82,6 +81,11 @@ final class ReactorListView: UIView { super.init(coder: aDecoder) commonInit() } + + override func layoutSubviews() { + super.layoutSubviews() + applyTheme() + } } // MARK: Initialization @@ -140,8 +144,8 @@ extension ReactorListView: UITableViewDelegate { view.addSubview(stackView) + view.setThemeColor("backgroundColor: bannerBackground") view.applyTheme() - view.backgroundColor = view.theme?.auxiliaryBackground return view } @@ -156,27 +160,3 @@ extension ReactorListView: UITableViewDelegate { selectedReactor(model.reactionViewModels[indexPath.section].reactors[indexPath.row], rect) } } - -extension ReactorListView { - override var theme: Theme? { - guard let theme = super.theme else { return nil } - guard isPopover else { return theme } - let popoverTheme = Theme( - backgroundColor: theme.focusedBackground, - focusedBackground: theme.focusedBackground, - auxiliaryBackground: theme.auxiliaryBackground, - bannerBackground: theme.backgroundColor, - titleText: theme.titleText, - bodyText: theme.bodyText, - controlText: theme.controlText, - auxiliaryText: theme.auxiliaryText, - tintColor: theme.tintColor, - auxiliaryTintColor: theme.auxiliaryTintColor, - hyperlink: theme.hyperlink, - mutedAccent: theme.mutedAccent, - strongAccent: theme.strongAccent, - appearence: theme.appearence - ) - return popoverTheme - } -} diff --git a/Rocket.Chat/External/RCEmojiKit/Views/Reaction/ReactorListView.xib b/Rocket.Chat/External/RCEmojiKit/Views/Reaction/ReactorListView.xib index d2f87a7f72..b0b69ce86b 100644 --- a/Rocket.Chat/External/RCEmojiKit/Views/Reaction/ReactorListView.xib +++ b/Rocket.Chat/External/RCEmojiKit/Views/Reaction/ReactorListView.xib @@ -1,11 +1,11 @@ - + - + diff --git a/Rocket.Chat/Managers/DatabaseManager.swift b/Rocket.Chat/Managers/DatabaseManager.swift index a489208783..26ce9a4a9b 100644 --- a/Rocket.Chat/Managers/DatabaseManager.swift +++ b/Rocket.Chat/Managers/DatabaseManager.swift @@ -115,12 +115,14 @@ struct DatabaseManager { let servers = self.servers ?? [] var validServers: [[String: String]] = [] - for server in servers { + for (index, server) in servers.enumerated() { guard server[ServerPersistKeys.token] != nil, server[ServerPersistKeys.userId] != nil, server[ServerPersistKeys.databaseName] != nil, - server[ServerPersistKeys.serverURL] != nil + server[ServerPersistKeys.serverURL] != nil, + let realmConfiguration = databaseConfiguration(index: index), + (try? Realm(configuration: realmConfiguration)) != nil else { continue } diff --git a/Rocket.Chat/Managers/Model/SubscriptionManager/SubscriptionManagerMessages.swift b/Rocket.Chat/Managers/Model/SubscriptionManager/SubscriptionManagerMessages.swift index b5d1871938..8965ae0175 100644 --- a/Rocket.Chat/Managers/Model/SubscriptionManager/SubscriptionManagerMessages.swift +++ b/Rocket.Chat/Managers/Model/SubscriptionManager/SubscriptionManagerMessages.swift @@ -44,7 +44,7 @@ extension SubscriptionManager { "msg": "method", "method": "toggleFavorite", "params": [subscription.rid, !subscription.favorite] - ] as [String: Any] + ] as [String: Any] SocketManager.send(request, completion: completion) } diff --git a/Rocket.Chat/Models/AuthSettings.swift b/Rocket.Chat/Models/AuthSettings.swift index 267eb039dc..a4ccd93cea 100644 --- a/Rocket.Chat/Models/AuthSettings.swift +++ b/Rocket.Chat/Models/AuthSettings.swift @@ -52,6 +52,7 @@ final class AuthSettings: Object { @objc dynamic var casLoginUrl: String? @objc dynamic var gitlabUrl: String? + @objc dynamic var wordpressUrl: String? @objc dynamic var firstChannelAfterLogin: String? @@ -67,6 +68,7 @@ final class AuthSettings: Object { @objc dynamic var isAllowedToEditUsername = false @objc dynamic var isAllowedToEditEmail = false @objc dynamic var isAllowedToEditPassword = false + @objc dynamic var oauthWordpressServerType = "" // Registration @objc dynamic var rawRegistrationForm: String? diff --git a/Rocket.Chat/Models/LoginService.swift b/Rocket.Chat/Models/LoginService.swift index 2c83a560d3..7e404acd81 100644 --- a/Rocket.Chat/Models/LoginService.swift +++ b/Rocket.Chat/Models/LoginService.swift @@ -141,54 +141,3 @@ extension LoginService { return object } } - -// MARK: Standard Login Services extensions - -extension LoginService { - static var google: LoginService { - let service = LoginService() - service.mapGoogle() - return service - } - - static var facebook: LoginService { - let service = LoginService() - service.mapFacebook() - return service - } - - static var github: LoginService { - let service = LoginService() - service.mapGitHub() - return service - } - - static func gitlab(url: String? = nil) -> LoginService { - let service = LoginService() - service.mapGitLab() - - if let url = url { - service.serverUrl = url - } - - return service - } - - static var linkedin: LoginService { - let service = LoginService() - service.mapLinkedIn() - return service - } - - static var wordpress: LoginService { - let service = LoginService() - service.mapWordPress() - return service - } - - static var cas: LoginService { - let service = LoginService() - service.mapCAS() - return service - } -} diff --git a/Rocket.Chat/Models/Mapping/AuthSettingsModelMapping.swift b/Rocket.Chat/Models/Mapping/AuthSettingsModelMapping.swift index 10ef421433..8ddee3d823 100644 --- a/Rocket.Chat/Models/Mapping/AuthSettingsModelMapping.swift +++ b/Rocket.Chat/Models/Mapping/AuthSettingsModelMapping.swift @@ -43,6 +43,7 @@ extension AuthSettings: ModelMappeable { self.isCASEnabled = objectForKey(object: values, key: "CAS_enabled")?.bool ?? false self.casLoginUrl = objectForKey(object: values, key: "CAS_login_url")?.string self.gitlabUrl = objectForKey(object: values, key: "API_Gitlab_URL")?.string + self.wordpressUrl = objectForKey(object: values, key: "API_Wordpress_URL")?.string self.isUsernameEmailAuthenticationEnabled = objectForKey(object: values, key: "Accounts_ShowFormLogin")?.bool ?? true self.rawRegistrationForm = objectForKey(object: values, key: "Accounts_RegistrationForm")?.string @@ -62,6 +63,7 @@ extension AuthSettings: ModelMappeable { self.isAllowedToEditUsername = objectForKey(object: values, key: "Accounts_AllowUsernameChange")?.bool ?? false self.isAllowedToEditEmail = objectForKey(object: values, key: "Accounts_AllowEmailChange")?.bool ?? false self.isAllowedToEditPassword = objectForKey(object: values, key: "Accounts_AllowPasswordChange")?.bool ?? false + self.oauthWordpressServerType = objectForKey(object: values, key: "Accounts_OAuth_Wordpress_server_type")?.string ?? "" // Upload self.uploadStorageType = objectForKey(object: values, key: "FileUpload_Storage_Type")?.string diff --git a/Rocket.Chat/Models/Mapping/LoginServiceModelMapping.swift b/Rocket.Chat/Models/Mapping/LoginServiceModelMapping.swift index 36e6ec29a7..1da49620f9 100644 --- a/Rocket.Chat/Models/Mapping/LoginServiceModelMapping.swift +++ b/Rocket.Chat/Models/Mapping/LoginServiceModelMapping.swift @@ -11,6 +11,7 @@ import SwiftyJSON import RealmSwift extension LoginService: ModelMappeable { + // swiftlint:disable cyclomatic_complexity func map(_ values: JSON, realm: Realm?) { if identifier == nil { identifier = values["_id"].string ?? values["id"].string @@ -19,10 +20,10 @@ extension LoginService: ModelMappeable { service = values["name"].string ?? values["service"].string clientId = values["appId"].string ?? values["clientId"].string custom = values["custom"].boolValue - serverUrl = values["serverURL"].stringValue - tokenPath = values["tokenPath"].stringValue - authorizePath = values["authorizePath"].stringValue - scope = values["scope"].stringValue + serverUrl = values["serverURL"].string + tokenPath = values["tokenPath"].string + authorizePath = values["authorizePath"].string + scope = values["scope"].string buttonLabelText = values["buttonLabelText"].stringValue buttonLabelColor = values["buttonLabelColor"].stringValue tokenSentVia = values["tokenSentVia"].stringValue @@ -45,7 +46,8 @@ extension LoginService: ModelMappeable { case .gitlab: mapGitLab() case .github: mapGitHub() case .linkedin: mapLinkedIn() - case .wordpress: mapWordPress() + case .wordpress: + break // not mapped here since it needs a public setting for type case .saml: break case .cas: break case .custom: break @@ -53,6 +55,8 @@ extension LoginService: ModelMappeable { } } + // swiftlint:enable cyclomatic_complexity + func mapGoogle() { service = "google" scope = "email profile" @@ -124,7 +128,7 @@ extension LoginService: ModelMappeable { func mapWordPress() { service = "wordpress" - scope = "auth" + scope = scope ?? "auth" serverUrl = "https://public-api.wordpress.com" tokenPath = "/oauth2/token" @@ -136,6 +140,20 @@ extension LoginService: ModelMappeable { callbackPath = "wordpress?close" } + func mapWordPressCustom() { + service = "wordpress" + scope = scope ?? "openid" + + serverUrl = serverUrl ?? "https://public-api.wordpress.com" + tokenPath = tokenPath ?? "/oauth/token" + authorizePath = authorizePath ?? "/oauth/authorize" + buttonLabelText = "wordpress" + buttonLabelColor = "#ffffff" + buttonColor = "#1e8cbe" + + callbackPath = "wordpress?close" + } + func mapCAS() { service = "cas" diff --git a/Rocket.Chat/Models/Mapping/SubscriptionModelMapping.swift b/Rocket.Chat/Models/Mapping/SubscriptionModelMapping.swift index 2d9967590f..6bd82618ac 100644 --- a/Rocket.Chat/Models/Mapping/SubscriptionModelMapping.swift +++ b/Rocket.Chat/Models/Mapping/SubscriptionModelMapping.swift @@ -10,6 +10,7 @@ import Foundation import SwiftyJSON import RealmSwift +// swiftlint:disable cyclomatic_complexity extension Subscription: ModelMappeable { func map(_ values: JSON, realm: Realm?) { if self.identifier == nil { diff --git a/Rocket.Chat/Models/Subscription/SubscriptionUtils.swift b/Rocket.Chat/Models/Subscription/SubscriptionUtils.swift index f607790359..3c0b7eed55 100644 --- a/Rocket.Chat/Models/Subscription/SubscriptionUtils.swift +++ b/Rocket.Chat/Models/Subscription/SubscriptionUtils.swift @@ -30,54 +30,64 @@ extension Subscription { } func fetchRoomIdentifier(_ completion: @escaping MessageCompletionObject ) { + switch type { + case .channel: fetchChannelIdentifier(completion) + case .directMessage: fetchDirectMessageIdentifier(completion) + default: break + } + } + + private func fetchChannelIdentifier(_ completion: @escaping MessageCompletionObject ) { + guard let identifier = self.identifier else { return } + + SubscriptionManager.getRoom(byName: name, completion: { (response) in + guard !response.isError() else { return } + guard let rid = response.result["result"]["_id"].string else { return } + + let result = response.result["result"] + Realm.execute({ realm in + if let obj = Subscription.find(withIdentifier: identifier) { + obj.rid = rid + obj.update(result, realm: realm) + realm.add(obj, update: true) + } + }, completion: { + if let subscription = Subscription.find(rid: rid) { + completion(subscription) + } + }) + }) + } + + private func fetchDirectMessageIdentifier(_ completion: @escaping MessageCompletionObject ) { guard let identifier = self.identifier else { return } - if type == .channel { - SubscriptionManager.getRoom(byName: name, completion: { (response) in - guard !response.isError() else { return } - guard let rid = response.result["result"]["_id"].string else { return } + SubscriptionManager.createDirectMessage(name, completion: { (response) in + guard !response.isError() else { return } + guard let rid = response.result["result"]["rid"].string else { return } - let result = response.result["result"] - Realm.execute({ realm in + Realm.execute({ realm in + // We need to check for the existence of one Subscription + // here because another real time response may have + // already included this object into the database + // before this block is executed. + if let existingObject = Subscription.find(rid: rid, realm: realm) { + if let obj = Subscription.find(withIdentifier: identifier) { + realm.add(existingObject, update: true) + realm.delete(obj) + } + } else { if let obj = Subscription.find(withIdentifier: identifier) { obj.rid = rid - obj.update(result, realm: realm) realm.add(obj, update: true) } - }, completion: { - if let subscription = Subscription.find(rid: rid) { - completion(subscription) - } - }) - }) - } else if type == .directMessage { - SubscriptionManager.createDirectMessage(name, completion: { (response) in - guard !response.isError() else { return } - guard let rid = response.result["result"]["rid"].string else { return } - - Realm.execute({ realm in - // We need to check for the existence of one Subscription - // here because another real time response may have - // already included this object into the database - // before this block is executed. - if let existingObject = Subscription.find(rid: rid, realm: realm) { - if let obj = Subscription.find(withIdentifier: identifier) { - realm.add(existingObject, update: true) - realm.delete(obj) - } - } else { - if let obj = Subscription.find(withIdentifier: identifier) { - obj.rid = rid - realm.add(obj, update: true) - } - } - }, completion: { - if let subscription = Subscription.find(rid: rid) { - completion(subscription) - } - }) + } + }, completion: { + if let subscription = Subscription.find(rid: rid) { + completion(subscription) + } }) - } + }) } func fetchMessages(_ limit: Int = 20, lastMessageDate: Date? = nil) -> [Message] { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State black.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State black.imageset/Contents.json index 7ca382ff0e..8507827073 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State black.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State black.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "Message Empty Black Theme.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "Message Empty Black Theme.pdf" } ], "info" : { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State dark.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State dark.imageset/Contents.json index ea1d1c898d..d414a4c130 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State dark.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State dark.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "Message Empty Dark Theme.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "Message Empty Dark Theme.pdf" } ], "info" : { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State light.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State light.imageset/Contents.json index e015e7fff7..d1ff3f57bb 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State light.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Chat/Empty State light.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "Message Empty.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "Message Empty.pdf" } ], "info" : { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/AttachFiles.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/AttachFiles.imageset/Contents.json index 0d10a1e1ca..024463edd0 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/AttachFiles.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/AttachFiles.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "files.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "files.pdf" } ], "info" : { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/ChooseFromLibrary.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/ChooseFromLibrary.imageset/Contents.json index c5e052cbef..82f8612944 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/ChooseFromLibrary.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/ChooseFromLibrary.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "library.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "library.pdf" } ], "info" : { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/DrawSomething.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/DrawSomething.imageset/Contents.json index b34ddc7842..9d76f04135 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/DrawSomething.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/DrawSomething.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "drawSomething.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "drawSomething.pdf" } ], "info" : { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/RecordVideo.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/RecordVideo.imageset/Contents.json index 1e75780f26..273ecab6ce 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/RecordVideo.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/RecordVideo.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "recordVideo.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "recordVideo.pdf" } ], "info" : { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/TakeAPhoto.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/TakeAPhoto.imageset/Contents.json index bd8b423572..3a643b1728 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/TakeAPhoto.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Composer/Attach/TakeAPhoto.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "takeAPhoto.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "takeAPhoto.pdf" } ], "info" : { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Cancel.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Cancel.imageset/Contents.json index 40a2b6de3e..cae55750df 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Cancel.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Cancel.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "cancel.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "cancel.pdf" } ], "info" : { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Error.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Error.imageset/Contents.json index 66c6dba5dd..f1b191c700 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Error.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Error.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "error.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "error.pdf" } ], "info" : { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_File.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_File.imageset/Contents.json index f428eb4afb..d6b387f287 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_File.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_File.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "filesGrey.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "filesGrey.pdf" } ], "info" : { diff --git a/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Image.imageset/Contents.json b/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Image.imageset/Contents.json index c18290bf32..5582c254f2 100644 --- a/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Image.imageset/Contents.json +++ b/Rocket.Chat/Resources/Assets.xcassets/Message/Upload/Message_Upload_Image.imageset/Contents.json @@ -2,16 +2,7 @@ "images" : [ { "idiom" : "universal", - "filename" : "libraryGrey.pdf", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename" : "libraryGrey.pdf" } ], "info" : { diff --git a/Rocket.Chat/Storyboards/Auth.storyboard b/Rocket.Chat/Storyboards/Auth.storyboard index 65ea2eeb9a..ead40acae4 100644 --- a/Rocket.Chat/Storyboards/Auth.storyboard +++ b/Rocket.Chat/Storyboards/Auth.storyboard @@ -1,5 +1,5 @@ - + @@ -263,7 +263,7 @@ - + @@ -296,7 +296,7 @@ - + @@ -329,7 +329,7 @@ - + @@ -362,7 +362,7 @@ - + @@ -505,7 +505,7 @@ - + @@ -551,7 +551,7 @@ - + @@ -1174,7 +1174,7 @@ to mention you in messages - + diff --git a/Rocket.Chat/Storyboards/Chat.storyboard b/Rocket.Chat/Storyboards/Chat.storyboard index d495fc42d3..b858fae284 100644 --- a/Rocket.Chat/Storyboards/Chat.storyboard +++ b/Rocket.Chat/Storyboards/Chat.storyboard @@ -42,7 +42,7 @@ - + diff --git a/Rocket.Chat/Storyboards/Subscriptions.storyboard b/Rocket.Chat/Storyboards/Subscriptions.storyboard index 099c840855..0702a32ee7 100644 --- a/Rocket.Chat/Storyboards/Subscriptions.storyboard +++ b/Rocket.Chat/Storyboards/Subscriptions.storyboard @@ -133,7 +133,7 @@