From 8fdc96fb277c1ae12c0bc372647c3b7801794eb8 Mon Sep 17 00:00:00 2001 From: Samar Sunkaria Date: Tue, 10 Jul 2018 01:21:41 +0530 Subject: [PATCH 01/48] Refactoring SpotlightClient and fixed a few warnings --- Rocket.Chat/API/Clients/SpotlightClient.swift | 79 +++++++++++-------- .../RuntimeAttributesThemeableView.swift | 2 +- Rocket.Chat/Theme/ThemeableViews.swift | 6 +- .../API/Clients/SpotlightClientSpec.swift | 2 +- Rocket.ChatTests/Models/Auth/AuthSpec.swift | 1 + .../Models/SubscriptionSpec.swift | 1 + 6 files changed, 55 insertions(+), 36 deletions(-) diff --git a/Rocket.Chat/API/Clients/SpotlightClient.swift b/Rocket.Chat/API/Clients/SpotlightClient.swift index 7d5cb43193..394160c74f 100644 --- a/Rocket.Chat/API/Clients/SpotlightClient.swift +++ b/Rocket.Chat/API/Clients/SpotlightClient.swift @@ -7,6 +7,7 @@ // import RealmSwift +import SwiftyJSON struct SpotlightClient: APIClient { let api: AnyAPIFetcher @@ -27,39 +28,11 @@ struct SpotlightClient: APIClient { var identifiers = [String]() realm?.execute({ (realm) in - resource.rooms.forEach { object in - let subscription = Subscription.getOrCreate(realm: realm, values: object, updates: { (object) in - object?.rid = object?.identifier ?? "" - }) + let roomSubscriptions = SpotlightClient.parse(rooms: resource.rooms, realm: realm) + let userSubscriptions = SpotlightClient.parse(users: resource.users, realm: realm) - if let identifier = subscription.identifier { - identifiers.append(identifier) - } - - subscriptions.append(subscription) - } - - resource.users.forEach { object in - let user = User.getOrCreate(realm: realm, values: object, updates: nil) - - guard let username = user.username else { - return - } - - let subscription = Subscription.find(name: username, subscriptionType: [.directMessage]) ?? Subscription() - if subscription.realm == nil { - subscription.identifier = subscription.identifier ?? user.identifier ?? "" - subscription.otherUserId = user.identifier - subscription.type = .directMessage - subscription.name = user.username ?? "" - subscription.fname = user.name ?? "" - subscriptions.append(subscription) - } - - if let identifier = subscription.identifier { - identifiers.append(identifier) - } - } + subscriptions = roomSubscriptions.subscriptions + userSubscriptions.subscriptions + identifiers = roomSubscriptions.identifiers + userSubscriptions.identifiers realm.add(subscriptions, update: true) }, completion: { @@ -85,4 +58,46 @@ struct SpotlightClient: APIClient { } } } + + private struct Subscriptions { + var subscriptions: [Subscription] + var identifiers: [String] + } + + private static func parse(rooms: [JSON], realm: Realm) -> Subscriptions { + return rooms.reduce(Subscriptions(subscriptions: [], identifiers: [])) { (result, object) -> Subscriptions in + let subscription = Subscription.getOrCreate(realm: realm, values: object, updates: { (object) in + object?.rid = object?.identifier ?? "" + }) + + return Subscriptions( + subscriptions: result.subscriptions + [subscription], + identifiers: result.identifiers + [subscription.identifier].compactMap { $0 } + ) + } + } + + private static func parse(users: [JSON], realm: Realm) -> Subscriptions { + return users.reduce(Subscriptions(subscriptions: [], identifiers: [])) { (result, object) -> Subscriptions in + let user = User.getOrCreate(realm: realm, values: object, updates: nil) + + guard let username = user.username else { + return result + } + + let subscription = Subscription.find(name: username, subscriptionType: [.directMessage]) ?? Subscription() + if subscription.realm == nil { + subscription.identifier = subscription.identifier ?? user.identifier ?? "" + subscription.otherUserId = user.identifier + subscription.type = .directMessage + subscription.name = user.username ?? "" + subscription.fname = user.name ?? "" + } + + return Subscriptions( + subscriptions: result.subscriptions + [subscription].compactMap { $0.realm == nil ? $0 : nil }, + identifiers: result.identifiers + [subscription.identifier].compactMap { $0 } + ) + } + } } diff --git a/Rocket.Chat/Theme/RuntimeAttributesThemeableView.swift b/Rocket.Chat/Theme/RuntimeAttributesThemeableView.swift index 94ef18017f..c868ba7317 100644 --- a/Rocket.Chat/Theme/RuntimeAttributesThemeableView.swift +++ b/Rocket.Chat/Theme/RuntimeAttributesThemeableView.swift @@ -54,7 +54,7 @@ extension UIView { This can be read as `view.backgroundColor = UIColor(hex: "#FFFFFF")` - **TIP:** The color can be represented in various forms of hex, eg. `aaa`, `ababab`, `#ffffff`, `#AAAAAAFF`, etc. Some common color names are also supported, such as `red`, `green`, `blue`, etc. This behavior is adopted from the UIColor extension declared in the `UIColorCSSColorsExtension.swift` file. + **TIP:** The color can be represented in various forms of hex, (eg. `aaa`, `#ffffff`, `#AAAAAAFF`) and some common color names are also supported (such as `red`, `green`, `blue`). This behavior is adopted from the UIColor extension declared in the `UIColorCSSColorsExtension.swift` file. */ @objc func setThemeColorOverride(_ overrideString: String) { diff --git a/Rocket.Chat/Theme/ThemeableViews.swift b/Rocket.Chat/Theme/ThemeableViews.swift index 794349c625..a3268cdfcf 100644 --- a/Rocket.Chat/Theme/ThemeableViews.swift +++ b/Rocket.Chat/Theme/ThemeableViews.swift @@ -18,12 +18,14 @@ extension UIView: Themeable { The default implementation calls the `applyTheme` method on all of its subviews, and sets the background color of the views. - Override this method to adapt the components of the view to the theme currently applied. `super.applyTheme` should be called somewhere in the implementation to sutomatically call `applyTheme` on all of the subviews, to set the `backgroundColor` and set the attributes defined in User Defined Runtime Attributes. + Override this method to adapt the components of the view to the theme currently applied. + + `super.applyTheme` should be called somewhere in the implementation to automatically call `applyTheme` on all of the subviews, set the `backgroundColor` according to the theme and the `UIColor` attributes defined in Runtime Attributes. This method should only be called directly if the view or any of its subviews require theming after the first initialization. - Important: - It is recommended that this method be only overridden, if it is not possible to use User Defined Runtime Attributes to achieve the desired result. For more information, please see [Setting theme properties using User Defined Runtime Attributes](https://github.com/RocketChat/Rocket.Chat.iOS/pull/1850). + It is recommended that this method be only overridden, if it's not possible to use User Defined Runtime Attributes to achieve the desired result. For more information, please see [Setting theme properties using Runtime Attributes](https://github.com/RocketChat/Rocket.Chat.iOS/pull/1850). On first initializaiton, it is recommended that the view controller for the view be added as an observer to the ThemeManager using the `ThemeManager.addObserver(_:)` method. If a view controller does not exist, the view should be added as an observer instead. diff --git a/Rocket.ChatTests/API/Clients/SpotlightClientSpec.swift b/Rocket.ChatTests/API/Clients/SpotlightClientSpec.swift index c13786cdf6..27f04df6ea 100644 --- a/Rocket.ChatTests/API/Clients/SpotlightClientSpec.swift +++ b/Rocket.ChatTests/API/Clients/SpotlightClientSpec.swift @@ -73,6 +73,6 @@ class SpotlightClientSpec: XCTestCase, RealmTestCase { } }) - wait(for: [expectation], timeout: 2) + wait(for: [expectation], timeout: 10) } } diff --git a/Rocket.ChatTests/Models/Auth/AuthSpec.swift b/Rocket.ChatTests/Models/Auth/AuthSpec.swift index 5853919382..0aee749b0a 100644 --- a/Rocket.ChatTests/Models/Auth/AuthSpec.swift +++ b/Rocket.ChatTests/Models/Auth/AuthSpec.swift @@ -25,6 +25,7 @@ extension Auth { } } +// swiftlint:disable type_body_length file_length class AuthSpec: XCTestCase, RealmTestCase { // MARK: Setup diff --git a/Rocket.ChatTests/Models/SubscriptionSpec.swift b/Rocket.ChatTests/Models/SubscriptionSpec.swift index d5819cb690..56419337b6 100644 --- a/Rocket.ChatTests/Models/SubscriptionSpec.swift +++ b/Rocket.ChatTests/Models/SubscriptionSpec.swift @@ -25,6 +25,7 @@ extension Subscription { } } +// swiftlint:disable type_body_length file_length class SubscriptionSpec: XCTestCase { override func setUp() { From 414720a1a0333b6aaf1fa91ebaf52fd465403ff7 Mon Sep 17 00:00:00 2001 From: Samar Sunkaria Date: Mon, 16 Jul 2018 18:10:18 +0530 Subject: [PATCH 02/48] Refactoring ChatMessageCell and reducing warnings --- Rocket.Chat/API/Clients/SpotlightClient.swift | 88 +++++++-------- .../User/UserDetail/UserDetail.storyboard | 4 +- .../UIButton/UIButtonCenterImage.swift | 3 +- Rocket.Chat/Storyboards/Chat.storyboard | 2 +- .../Views/Cells/Chat/ChatMessageCell.swift | 106 ++++++++++-------- .../Views/Cells/Chat/Info/MemberCell.swift | 2 +- .../Chat/ChatBannerView/ChatBannerView.xib | 2 +- .../Sections/SubscriptionSectionView.xib | 2 +- .../Views/Subscriptions/ServersListView.xib | 6 +- .../API/Clients/SpotlightClientSpec.swift | 1 + 10 files changed, 110 insertions(+), 106 deletions(-) diff --git a/Rocket.Chat/API/Clients/SpotlightClient.swift b/Rocket.Chat/API/Clients/SpotlightClient.swift index 8f0cc4c92e..2e800b583a 100644 --- a/Rocket.Chat/API/Clients/SpotlightClient.swift +++ b/Rocket.Chat/API/Clients/SpotlightClient.swift @@ -7,7 +7,6 @@ // import RealmSwift -import SwiftyJSON struct SpotlightClient: APIClient { let api: AnyAPIFetcher @@ -25,61 +24,54 @@ struct SpotlightClient: APIClient { } realm?.execute({ (realm) in - let roomSubscriptions = SpotlightClient.parse(rooms: resource.rooms, realm: realm) - let userSubscriptions = SpotlightClient.parse(users: resource.users, realm: realm) + var subscriptions: [Subscription] = [] - subscriptions = roomSubscriptions.subscriptions + userSubscriptions.subscriptions - identifiers = roomSubscriptions.identifiers + userSubscriptions.identifiers + resource.rooms.forEach { object in + if let roomIdentifier = object["_id"].string { + if let subscription = Subscription.find(rid: roomIdentifier, realm: realm) { + subscription.map(object, realm: realm) + subscription.mapRoom(object, realm: realm) + subscriptions.append(subscription) + } else { + let subscription = Subscription() + subscription.identifier = String.random() + subscription.rid = roomIdentifier + subscription.name = object["name"].string ?? "" - realm.add(subscriptions, update: true) - }, completion: { - completion(resource.raw, false) - }) - case .error(let _): - completion(nil, true) - } - } - } + if let typeRaw = object["t"].string, let type = SubscriptionType(rawValue: typeRaw) { + subscription.type = type + } - private struct Subscriptions { - var subscriptions: [Subscription] - var identifiers: [String] - } + subscriptions.append(subscription) + } + } + } - private static func parse(rooms: [JSON], realm: Realm) -> Subscriptions { - return rooms.reduce(Subscriptions(subscriptions: [], identifiers: [])) { (result, object) -> Subscriptions in - let subscription = Subscription.getOrCreate(realm: realm, values: object, updates: { (object) in - object?.rid = object?.identifier ?? "" - }) + resource.users.forEach { object in + let user = User.getOrCreate(realm: realm, values: object, updates: nil) - return Subscriptions( - subscriptions: result.subscriptions + [subscription], - identifiers: result.identifiers + [subscription.identifier].compactMap { $0 } - ) - } - } - - private static func parse(users: [JSON], realm: Realm) -> Subscriptions { - return users.reduce(Subscriptions(subscriptions: [], identifiers: [])) { (result, object) -> Subscriptions in - let user = User.getOrCreate(realm: realm, values: object, updates: nil) + guard let username = user.username else { + return + } - guard let username = user.username else { - return result - } + let subscription = Subscription.find(name: username, subscriptionType: [.directMessage]) ?? Subscription() + if subscription.realm == nil { + subscription.identifier = subscription.identifier ?? user.identifier ?? "" + subscription.otherUserId = user.identifier + subscription.type = .directMessage + subscription.name = user.username ?? "" + subscription.fname = user.name ?? "" + subscriptions.append(subscription) + } + } - let subscription = Subscription.find(name: username, subscriptionType: [.directMessage]) ?? Subscription() - if subscription.realm == nil { - subscription.identifier = subscription.identifier ?? user.identifier ?? "" - subscription.otherUserId = user.identifier - subscription.type = .directMessage - subscription.name = user.username ?? "" - subscription.fname = user.name ?? "" + realm.add(subscriptions, update: true) + }, completion: { + completion(resource.raw, false) + }) + case .error: + completion(nil, true) } - - return Subscriptions( - subscriptions: result.subscriptions + [subscription].compactMap { $0.realm == nil ? $0 : nil }, - identifiers: result.identifiers + [subscription.identifier].compactMap { $0 } - ) } } } 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/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/Storyboards/Chat.storyboard b/Rocket.Chat/Storyboards/Chat.storyboard index d495fc42d3..d0bb6c2fa6 100644 --- a/Rocket.Chat/Storyboards/Chat.storyboard +++ b/Rocket.Chat/Storyboards/Chat.storyboard @@ -42,7 +42,7 @@ - + diff --git a/Rocket.Chat/Views/Cells/Chat/ChatMessageCell.swift b/Rocket.Chat/Views/Cells/Chat/ChatMessageCell.swift index 5177197285..11e3139262 100644 --- a/Rocket.Chat/Views/Cells/Chat/ChatMessageCell.swift +++ b/Rocket.Chat/Views/Cells/Chat/ChatMessageCell.swift @@ -219,7 +219,6 @@ final class ChatMessageCell: UICollectionViewCell { return addedHeight } - //swiftlint:disable cyclomatic_complexity func insertAttachments() { var mediaViewHeight = CGFloat(0) mediaViewHeight += insertURLs() @@ -228,52 +227,11 @@ final class ChatMessageCell: UICollectionViewCell { let type = attachment.type switch type { - case .textAttachment: - guard let view = ChatMessageTextView.instantiateFromNib() else { break } - view.viewModel = ChatMessageTextViewModel(withAttachment: attachment) - view.delegate = delegate - view.translatesAutoresizingMaskIntoConstraints = false - - mediaViews.addArrangedSubview(view) - mediaViewHeight += ChatMessageTextView.heightFor(collapsed: attachment.collapsed, withText: attachment.text, isFile: attachment.isFile) - - if !attachment.collapsed { - attachment.fields.forEach { - guard let view = ChatMessageTextView.instantiateFromNib() else { return } - view.viewModel = ChatMessageAttachmentFieldViewModel(withAttachment: attachment, andAttachmentField: $0) - mediaViews.addArrangedSubview(view) - mediaViewHeight += ChatMessageTextView.heightFor(collapsed: false, withText: $0.value) - } - } - - case .image: - guard let view = ChatMessageImageView.instantiateFromNib() else { break } - view.attachment = attachment - view.delegate = delegate - view.translatesAutoresizingMaskIntoConstraints = false - - mediaViews.addArrangedSubview(view) - mediaViewHeight += ChatMessageImageView.heightFor(withText: attachment.descriptionText) - - case .video: - guard let view = ChatMessageVideoView.instantiateFromNib() else { break } - view.attachment = attachment - view.delegate = delegate - view.translatesAutoresizingMaskIntoConstraints = false - - mediaViews.addArrangedSubview(view) - mediaViewHeight += ChatMessageVideoView.heightFor(withText: attachment.descriptionText) - - case .audio: - guard let view = ChatMessageAudioView.instantiateFromNib() else { break } - view.attachment = attachment - view.translatesAutoresizingMaskIntoConstraints = false - - mediaViews.addArrangedSubview(view) - mediaViewHeight += ChatMessageAudioView.heightFor(withText: attachment.descriptionText) - - default: - return + case .textAttachment: mediaViewHeight += insertTextAttachment(attachment) + case .image: mediaViewHeight += insertImageAttachment(attachment) + case .video: mediaViewHeight += insertVideoAttachment(attachment) + case .audio: mediaViewHeight += insertAudioAttachment(attachment) + default: return } } @@ -441,6 +399,60 @@ extension ChatMessageCell { } } +// MARK: Insert attachments + +extension ChatMessageCell { + private func insertTextAttachment(_ attachment: Attachment) -> CGFloat { + guard let view = ChatMessageTextView.instantiateFromNib() else { return 0 } + view.viewModel = ChatMessageTextViewModel(withAttachment: attachment) + view.delegate = delegate + view.translatesAutoresizingMaskIntoConstraints = false + + mediaViews.addArrangedSubview(view) + var attachmentHeight = ChatMessageTextView.heightFor(collapsed: attachment.collapsed, withText: attachment.text, isFile: attachment.isFile) + + if !attachment.collapsed { + attachment.fields.forEach { + guard let view = ChatMessageTextView.instantiateFromNib() else { return } + view.viewModel = ChatMessageAttachmentFieldViewModel(withAttachment: attachment, andAttachmentField: $0) + mediaViews.addArrangedSubview(view) + attachmentHeight += ChatMessageTextView.heightFor(collapsed: false, withText: $0.value) + } + } + + return attachmentHeight + } + + private func insertImageAttachment(_ attachment: Attachment) -> CGFloat { + guard let view = ChatMessageImageView.instantiateFromNib() else { return 0 } + view.attachment = attachment + view.delegate = delegate + view.translatesAutoresizingMaskIntoConstraints = false + + mediaViews.addArrangedSubview(view) + return ChatMessageImageView.heightFor(withText: attachment.descriptionText) + } + + private func insertVideoAttachment(_ attachment: Attachment) -> CGFloat { + guard let view = ChatMessageVideoView.instantiateFromNib() else { return 0 } + view.attachment = attachment + view.delegate = delegate + view.translatesAutoresizingMaskIntoConstraints = false + + mediaViews.addArrangedSubview(view) + return ChatMessageVideoView.heightFor(withText: attachment.descriptionText) + } + + private func insertAudioAttachment(_ attachment: Attachment) -> CGFloat { + guard let view = ChatMessageAudioView.instantiateFromNib() else { return 0 } + view.attachment = attachment + view.translatesAutoresizingMaskIntoConstraints = false + + mediaViews.addArrangedSubview(view) + return ChatMessageAudioView.heightFor(withText: attachment.descriptionText) + } +} + // MARK: Themeable extension ChatMessageCell { diff --git a/Rocket.Chat/Views/Cells/Chat/Info/MemberCell.swift b/Rocket.Chat/Views/Cells/Chat/Info/MemberCell.swift index 69ffe63104..6fcc9a5214 100644 --- a/Rocket.Chat/Views/Cells/Chat/Info/MemberCell.swift +++ b/Rocket.Chat/Views/Cells/Chat/Info/MemberCell.swift @@ -12,7 +12,7 @@ struct MemberCellData { let member: User var nameText: String { - let utcText = member.utcOffset != nil ? "(UTC \(member.utcOffset ?? 0))" : "" + let utcText = "(UTC \(member.utcOffset))" return "\(member.displayName()) \(utcText)" } diff --git a/Rocket.Chat/Views/Chat/ChatBannerView/ChatBannerView.xib b/Rocket.Chat/Views/Chat/ChatBannerView/ChatBannerView.xib index 8002efc452..b4476c682b 100644 --- a/Rocket.Chat/Views/Chat/ChatBannerView/ChatBannerView.xib +++ b/Rocket.Chat/Views/Chat/ChatBannerView/ChatBannerView.xib @@ -45,7 +45,7 @@ -