From 87c125549ae840932f78358fb600fc3baf586234 Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 10:48:06 -0300 Subject: [PATCH 01/13] Add BaseFileMessageCell and implement FileCell and FileMessageCell --- Rocket.Chat.xcodeproj/project.pbxproj | 28 +++++--- .../Chat/ChatSections/MessageSection.swift | 2 +- .../Chat/MessagesViewController.swift | 2 +- .../New Chat/Cells/BaseFileMessageCell.swift | 14 ++++ .../Views/Chat/New Chat/Cells/FileCell.swift | 40 +++++++++++ .../Views/Chat/New Chat/Cells/FileCell.xib | 63 +++++++++++++++++ .../Chat/New Chat/Cells/FileMessageCell.swift | 24 ++++--- .../Chat/New Chat/Cells/FileMessageCell.xib | 67 ++++++++++++++----- .../ChatItems/FileMessageChatItem.swift | 2 +- 9 files changed, 205 insertions(+), 37 deletions(-) create mode 100644 Rocket.Chat/Views/Chat/New Chat/Cells/BaseFileMessageCell.swift create mode 100644 Rocket.Chat/Views/Chat/New Chat/Cells/FileCell.swift create mode 100644 Rocket.Chat/Views/Chat/New Chat/Cells/FileCell.xib diff --git a/Rocket.Chat.xcodeproj/project.pbxproj b/Rocket.Chat.xcodeproj/project.pbxproj index 4f840f8a3f..2c969bec62 100644 --- a/Rocket.Chat.xcodeproj/project.pbxproj +++ b/Rocket.Chat.xcodeproj/project.pbxproj @@ -747,8 +747,8 @@ 9938A08520D3077800714AB4 /* CustomFieldTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9938A08420D3077800714AB4 /* CustomFieldTableViewCell.xib */; }; 9938A08720D3141C00714AB4 /* CustomFieldTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9938A08620D3141C00714AB4 /* CustomFieldTableViewCell.swift */; }; 9938A08920D3164D00714AB4 /* SignupCustomFieldsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9938A08820D3164D00714AB4 /* SignupCustomFieldsTableViewController.swift */; }; - 993B7B3C215F07020067B962 /* FileMessageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 993B7B3B215F07020067B962 /* FileMessageCell.xib */; }; - 993B7B3E215F0A270067B962 /* FileMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 993B7B3D215F0A270067B962 /* FileMessageCell.swift */; }; + 993B7B3C215F07020067B962 /* FileCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 993B7B3B215F07020067B962 /* FileCell.xib */; }; + 993B7B3E215F0A270067B962 /* FileCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 993B7B3D215F0A270067B962 /* FileCell.swift */; }; 993B7B40215F0B730067B962 /* FileMessageChatItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 993B7B3F215F0B730067B962 /* FileMessageChatItem.swift */; }; 993E513A1FB1E18D006403D5 /* DraftMessageManagerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 993E51391FB1E18D006403D5 /* DraftMessageManagerSpec.swift */; }; 994C90B42174B50B00383AFF /* BaseVideoMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 994C90B32174B50B00383AFF /* BaseVideoMessageCell.swift */; }; @@ -796,6 +796,9 @@ 998E649A2161B3E300E7C45A /* AttachmentFieldView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 998E64992161B3E300E7C45A /* AttachmentFieldView.xib */; }; 998E649C2161B4D900E7C45A /* AttachmentFieldView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 998E649B2161B4D900E7C45A /* AttachmentFieldView.swift */; }; 998E649E2161B6DF00E7C45A /* TextAttachmentChatItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 998E649D2161B6DF00E7C45A /* TextAttachmentChatItem.swift */; }; + 9990750F2176202400CAB7C8 /* BaseFileMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9990750E2176202400CAB7C8 /* BaseFileMessageCell.swift */; }; + 999075112176222300CAB7C8 /* FileMessageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 999075102176222300CAB7C8 /* FileMessageCell.xib */; }; + 99907513217622A900CAB7C8 /* FileMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99907512217622A900CAB7C8 /* FileMessageCell.swift */; }; 99923773204B3BD800C2D15F /* UploadAvatarRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99923772204B3BD800C2D15F /* UploadAvatarRequest.swift */; }; 999483EB20644CC4004F61CA /* WebBrowserViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 999483EA20644CC4004F61CA /* WebBrowserViewModel.swift */; }; 999F25B5207EEB0C002E0F68 /* FileModelMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 999F25B4207EEB0C002E0F68 /* FileModelMapping.swift */; }; @@ -1642,8 +1645,8 @@ 9938A08420D3077800714AB4 /* CustomFieldTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CustomFieldTableViewCell.xib; sourceTree = ""; }; 9938A08620D3141C00714AB4 /* CustomFieldTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomFieldTableViewCell.swift; sourceTree = ""; }; 9938A08820D3164D00714AB4 /* SignupCustomFieldsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignupCustomFieldsTableViewController.swift; sourceTree = ""; }; - 993B7B3B215F07020067B962 /* FileMessageCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FileMessageCell.xib; sourceTree = ""; }; - 993B7B3D215F0A270067B962 /* FileMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMessageCell.swift; sourceTree = ""; }; + 993B7B3B215F07020067B962 /* FileCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FileCell.xib; sourceTree = ""; }; + 993B7B3D215F0A270067B962 /* FileCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileCell.swift; sourceTree = ""; }; 993B7B3F215F0B730067B962 /* FileMessageChatItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMessageChatItem.swift; sourceTree = ""; }; 993E51391FB1E18D006403D5 /* DraftMessageManagerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftMessageManagerSpec.swift; sourceTree = ""; }; 994C90B32174B50B00383AFF /* BaseVideoMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseVideoMessageCell.swift; sourceTree = ""; }; @@ -1691,6 +1694,9 @@ 998E64992161B3E300E7C45A /* AttachmentFieldView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AttachmentFieldView.xib; sourceTree = ""; }; 998E649B2161B4D900E7C45A /* AttachmentFieldView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentFieldView.swift; sourceTree = ""; }; 998E649D2161B6DF00E7C45A /* TextAttachmentChatItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextAttachmentChatItem.swift; sourceTree = ""; }; + 9990750E2176202400CAB7C8 /* BaseFileMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseFileMessageCell.swift; sourceTree = ""; }; + 999075102176222300CAB7C8 /* FileMessageCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FileMessageCell.xib; sourceTree = ""; }; + 99907512217622A900CAB7C8 /* FileMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMessageCell.swift; sourceTree = ""; }; 99923772204B3BD800C2D15F /* UploadAvatarRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadAvatarRequest.swift; sourceTree = ""; }; 999483EA20644CC4004F61CA /* WebBrowserViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebBrowserViewModel.swift; sourceTree = ""; }; 999F25B4207EEB0C002E0F68 /* FileModelMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileModelMapping.swift; sourceTree = ""; }; @@ -3740,8 +3746,11 @@ 419EB5B6215E52EA00E591BF /* VideoCell.swift */, 419EB5BE215E6A0C00E591BF /* ReactionsCell.xib */, 419EB5BC215E69FF00E591BF /* ReactionsCell.swift */, - 993B7B3B215F07020067B962 /* FileMessageCell.xib */, - 993B7B3D215F0A270067B962 /* FileMessageCell.swift */, + 9990750E2176202400CAB7C8 /* BaseFileMessageCell.swift */, + 999075102176222300CAB7C8 /* FileMessageCell.xib */, + 99907512217622A900CAB7C8 /* FileMessageCell.swift */, + 993B7B3B215F07020067B962 /* FileCell.xib */, + 993B7B3D215F0A270067B962 /* FileCell.swift */, 998E649521619DF700E7C45A /* TextAttachmentCell.xib */, 998E64972161ADE200E7C45A /* TextAttachmentCell.swift */, 998E64992161B3E300E7C45A /* AttachmentFieldView.xib */, @@ -4187,7 +4196,7 @@ 14F8A244202E5D0600175FDC /* Red-83.5@2x.png in Resources */, 14F8A259202E64B200175FDC /* BnW-40@3x.png in Resources */, 14F8A245202E5D0600175FDC /* Red-76@3x.png in Resources */, - 993B7B3C215F07020067B962 /* FileMessageCell.xib in Resources */, + 993B7B3C215F07020067B962 /* FileCell.xib in Resources */, 80235D261F74672D00A56CA5 /* LoaderTableViewCell.xib in Resources */, 14F8A25A202E64B200175FDC /* BnW-29@2x.png in Resources */, 418C4DC81DC4C08800ABED4C /* SubscriptionSectionView.xib in Resources */, @@ -4259,6 +4268,7 @@ 14F8A284202E659000175FDC /* White-60@2x.png in Resources */, 14F8A286202E659000175FDC /* White-29@2x.png in Resources */, 14F8A282202E659000175FDC /* White-76@3x.png in Resources */, + 999075112176222300CAB7C8 /* FileMessageCell.xib in Resources */, 14F8A223202E5CBF00175FDC /* Black-76@2x.png in Resources */, 4135A64621623F2A00C1741A /* ImageMessageCell.xib in Resources */, 80AC400420EECB03005082E1 /* ChatBannerView.xib in Resources */, @@ -4949,7 +4959,7 @@ 80A2A2AB2073BD0800857DAF /* RealmCurrent.swift in Sources */, 80B2D99320E54AD4002F4149 /* UIViewControllerPushOrPresent.swift in Sources */, 33F67A40212BFC40004EB4A0 /* UnmanagedUser.swift in Sources */, - 993B7B3E215F0A270067B962 /* FileMessageCell.swift in Sources */, + 993B7B3E215F0A270067B962 /* FileCell.swift in Sources */, 8013F8761FD6B5E000EE1A4E /* VersionMiddleware.swift in Sources */, 80235D241F7466FF00A56CA5 /* LoaderTableViewCell.swift in Sources */, 41FBF4E720BC320E0080D00D /* ServersListView.swift in Sources */, @@ -5024,6 +5034,7 @@ 996735D221585CA70049BB63 /* BasicMessageChatItem.swift in Sources */, 800F38ED2019492D0005CB78 /* DeepLink.swift in Sources */, 998E64982161ADE200E7C45A /* TextAttachmentCell.swift in Sources */, + 9990750F2176202400CAB7C8 /* BaseFileMessageCell.swift in Sources */, 419EB5BD215E69FF00E591BF /* ReactionsCell.swift in Sources */, 99BE4D822152D56E001A43E2 /* MessagesViewController.swift in Sources */, 80CC8A1B20ACEA6A009D64DF /* ChatControllerUserActionPresenter.swift in Sources */, @@ -5031,6 +5042,7 @@ 41EE15801E05BF1F00754D45 /* ChatControllerMessageCellProtocol.swift in Sources */, 41865AF21FC8B23400A5E48F /* WebViewControllerEmbedded.swift in Sources */, 414B3B25203E2F2C0078D3D9 /* MainSplitViewController.swift in Sources */, + 99907513217622A900CAB7C8 /* FileMessageCell.swift in Sources */, 414A1FF61D46320F00093E10 /* ResponseMessage.swift in Sources */, 996735CF21582E790049BB63 /* BasicMessageCell.swift in Sources */, 4151B44E1E2CF19A00F8AA1B /* UserModelHandler.swift in Sources */, diff --git a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift index 25003f4643..f9c8da3947 100644 --- a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift +++ b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift @@ -155,7 +155,7 @@ final class MessageSection: ChatSection { cell.delegate = self } else if let cell = cell as? SequentialMessageCell { cell.delegate = self - } else if let cell = cell as? FileMessageCell { + } else if let cell = cell as? FileCell { cell.delegate = self } else if let cell = cell as? ImageMessageCell { cell.delegate = self diff --git a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift index 18480c1c34..4680a187b8 100644 --- a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift +++ b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift @@ -59,7 +59,7 @@ final class MessagesViewController: RocketChatViewController { collectionView.register(VideoCell.nib, forCellWithReuseIdentifier: VideoCell.identifier) collectionView.register(VideoMessageCell.nib, forCellWithReuseIdentifier: VideoMessageCell.identifier) collectionView.register(ReactionsCell.nib, forCellWithReuseIdentifier: ReactionsCell.identifier) - collectionView.register(FileMessageCell.nib, forCellWithReuseIdentifier: FileMessageCell.identifier) + collectionView.register(FileCell.nib, forCellWithReuseIdentifier: FileCell.identifier) collectionView.register(TextAttachmentCell.nib, forCellWithReuseIdentifier: TextAttachmentCell.identifier) collectionView.register(ImageMessageCell.nib, forCellWithReuseIdentifier: ImageMessageCell.identifier) collectionView.register(QuoteCell.nib, forCellWithReuseIdentifier: QuoteCell.identifier) diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/BaseFileMessageCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/BaseFileMessageCell.swift new file mode 100644 index 0000000000..209f968083 --- /dev/null +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/BaseFileMessageCell.swift @@ -0,0 +1,14 @@ +// +// BaseFileMessageCell.swift +// Rocket.Chat +// +// Created by Filipe Alvarenga on 16/10/18. +// Copyright © 2018 Rocket.Chat. All rights reserved. +// + +import UIKit +import RocketChatViewController + +class BaseFileMessageCell: MessageHeaderCell { + weak var delegate: ChatMessageCellProtocol? +} diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/FileCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/FileCell.swift new file mode 100644 index 0000000000..8253818a38 --- /dev/null +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/FileCell.swift @@ -0,0 +1,40 @@ +// +// FileMessageCell.swift +// Rocket.Chat +// +// Created by Filipe Alvarenga on 28/09/18. +// Copyright © 2018 Rocket.Chat. All rights reserved. +// + +import Foundation +import RocketChatViewController + +final class FileCell: BaseFileMessageCell, SizingCell { + static let identifier = String(describing: FileCell.self) + + static let sizingCell: UICollectionViewCell & ChatCell = { + guard let cell = FileCell.instantiateFromNib() else { + return FileCell() + } + + return cell + }() + + @IBOutlet weak var fileButton: UIButton! + + override func configure() { + guard let viewModel = viewModel?.base as? FileMessageChatItem else { + return + } + + fileButton.setTitle(viewModel.attachment.title, for: .normal) + } + + @IBAction func didTapFileButton() { + guard let viewModel = viewModel?.base as? FileMessageChatItem else { + return + } + + delegate?.openFileFromCell(attachment: viewModel.attachment) + } +} diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/FileCell.xib b/Rocket.Chat/Views/Chat/New Chat/Cells/FileCell.xib new file mode 100644 index 0000000000..e627c19526 --- /dev/null +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/FileCell.xib @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.swift index 219d2c0f0c..098000ce70 100644 --- a/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.swift +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.swift @@ -2,14 +2,14 @@ // FileMessageCell.swift // Rocket.Chat // -// Created by Filipe Alvarenga on 28/09/18. +// Created by Filipe Alvarenga on 16/10/18. // Copyright © 2018 Rocket.Chat. All rights reserved. // -import Foundation +import UIKit import RocketChatViewController -final class FileMessageCell: UICollectionViewCell, ChatCell, SizingCell { +class FileMessageCell: BaseFileMessageCell { static let identifier = String(describing: FileMessageCell.self) static let sizingCell: UICollectionViewCell & ChatCell = { @@ -20,18 +20,24 @@ final class FileMessageCell: UICollectionViewCell, ChatCell, SizingCell { return cell }() - @IBOutlet weak var fileButton: UIButton! - - weak var delegate: ChatMessageCellProtocol? + @IBOutlet weak var avatarContainerView: UIView! { + didSet { + avatarContainerView.layer.cornerRadius = 4 + avatarView.frame = avatarContainerView.bounds + avatarContainerView.addSubview(avatarView) + } + } - var adjustedHorizontalInsets: CGFloat = 0 - var viewModel: AnyChatItem? + @IBOutlet weak var username: UILabel! + @IBOutlet weak var date: UILabel! + @IBOutlet weak var fileButton: UIButton! - func configure() { + override func configure() { guard let viewModel = viewModel?.base as? FileMessageChatItem else { return } + configure(with: avatarView, date: date, and: username) fileButton.setTitle(viewModel.attachment.title, for: .normal) } diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.xib b/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.xib index cf6feb0cac..30d2625afe 100644 --- a/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.xib +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.xib @@ -12,24 +12,47 @@ - - + + - + - - - - - + + + + + + + + + + + - - + + - + + + + - + diff --git a/Rocket.Chat/Views/Chat/New Chat/ChatItems/FileMessageChatItem.swift b/Rocket.Chat/Views/Chat/New Chat/ChatItems/FileMessageChatItem.swift index 94537ade21..ae0bf16eb8 100644 --- a/Rocket.Chat/Views/Chat/New Chat/ChatItems/FileMessageChatItem.swift +++ b/Rocket.Chat/Views/Chat/New Chat/ChatItems/FileMessageChatItem.swift @@ -12,7 +12,7 @@ import RocketChatViewController struct FileMessageChatItem: ChatItem, Differentiable { var relatedReuseIdentifier: String { - return FileMessageCell.identifier + return FileCell.identifier } var attachment: UnmanagedAttachment From 5d2e7bb916478b64360036f6b1f8ab4b9fb08fc4 Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 11:15:13 -0300 Subject: [PATCH 02/13] Implement File attachment with message headers --- .../Chat/ChatSections/MessageSection.swift | 23 +++++++++++++++---- .../Chat/MessagesViewController.swift | 1 + .../Chat/New Chat/Cells/FileMessageCell.swift | 2 +- .../ChatItems/FileMessageChatItem.swift | 11 +++++++-- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift index f9c8da3947..61a6cd9133 100644 --- a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift +++ b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift @@ -27,6 +27,7 @@ final class MessageSection: ChatSection { self.controllerContext = controllerContext } + // swiftlint:disable function_body_length func viewModels() -> [AnyChatItem] { guard let object = object.base as? MessageSectionModel, @@ -98,7 +99,7 @@ final class MessageSection: ChatSection { cells.append(TextAttachmentChatItem( attachment: attachment ).wrapped) - case .textAttachment: + case .textAttachment where !attachment.isFile: cells.append(QuoteChatItem( attachment: attachment ).wrapped) @@ -111,9 +112,23 @@ final class MessageSection: ChatSection { ).wrapped) default: if attachment.isFile { - cells.append(FileMessageChatItem( - attachment: attachment - ).wrapped) + if object.message.text.isEmpty && shouldAppendMessageHeader { + cells.append(FileMessageChatItem( + attachment: attachment, + hasText: false, + user: user, + message: object.message + ).wrapped) + + shouldAppendMessageHeader = false + } else { + cells.append(FileMessageChatItem( + attachment: attachment, + hasText: true, + user: nil, + message: nil + ).wrapped) + } } } } diff --git a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift index 4680a187b8..3a2ef0dc7a 100644 --- a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift +++ b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift @@ -60,6 +60,7 @@ final class MessagesViewController: RocketChatViewController { collectionView.register(VideoMessageCell.nib, forCellWithReuseIdentifier: VideoMessageCell.identifier) collectionView.register(ReactionsCell.nib, forCellWithReuseIdentifier: ReactionsCell.identifier) collectionView.register(FileCell.nib, forCellWithReuseIdentifier: FileCell.identifier) + collectionView.register(FileMessageCell.nib, forCellWithReuseIdentifier: FileMessageCell.identifier) collectionView.register(TextAttachmentCell.nib, forCellWithReuseIdentifier: TextAttachmentCell.identifier) collectionView.register(ImageMessageCell.nib, forCellWithReuseIdentifier: ImageMessageCell.identifier) collectionView.register(QuoteCell.nib, forCellWithReuseIdentifier: QuoteCell.identifier) diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.swift index 098000ce70..620a5ac213 100644 --- a/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.swift +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/FileMessageCell.swift @@ -9,7 +9,7 @@ import UIKit import RocketChatViewController -class FileMessageCell: BaseFileMessageCell { +class FileMessageCell: BaseFileMessageCell, SizingCell { static let identifier = String(describing: FileMessageCell.self) static let sizingCell: UICollectionViewCell & ChatCell = { diff --git a/Rocket.Chat/Views/Chat/New Chat/ChatItems/FileMessageChatItem.swift b/Rocket.Chat/Views/Chat/New Chat/ChatItems/FileMessageChatItem.swift index ae0bf16eb8..20345bea7c 100644 --- a/Rocket.Chat/Views/Chat/New Chat/ChatItems/FileMessageChatItem.swift +++ b/Rocket.Chat/Views/Chat/New Chat/ChatItems/FileMessageChatItem.swift @@ -10,12 +10,19 @@ import Foundation import DifferenceKit import RocketChatViewController -struct FileMessageChatItem: ChatItem, Differentiable { +final class FileMessageChatItem: MessageHeaderChatItem, ChatItem, Differentiable { var relatedReuseIdentifier: String { - return FileCell.identifier + return hasText ? FileCell.identifier : FileMessageCell.identifier } var attachment: UnmanagedAttachment + let hasText: Bool + + init(attachment: UnmanagedAttachment, hasText: Bool, user: UnmanagedUser?, message: UnmanagedMessage?) { + self.attachment = attachment + self.hasText = hasText + super.init(user: user, avatar: message?.avatar, emoji: message?.emoji, date: message?.createdAt) + } var differenceIdentifier: String { return attachment.fullFileURL?.absoluteString ?? attachment.titleLink From aab32841a8f14fb8117fe207ecc82f8a6d4174b0 Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 14:10:21 -0300 Subject: [PATCH 03/13] Add fatal error when trying to use a cell that doesn't conforms to SizingCell on MessagesViewController --- Rocket.Chat/Controllers/Chat/MessagesViewController.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift index 3a2ef0dc7a..523a805b7f 100644 --- a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift +++ b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift @@ -119,7 +119,11 @@ extension MessagesViewController { return size } else { guard let sizingCell = UINib(nibName: item.relatedReuseIdentifier, bundle: nil).instantiate() as? SizingCell else { - return .zero + fatalError(""" + Failed to reference sizing cell instance. Please, + check the relatedReuseIdentifier and make sure all + the chat components conform to SizingCell protocol + """) } let horizontalMargins = collectionView.adjustedContentInset.left + collectionView.adjustedContentInset.right From 920377be187f68193daebeaa4fb5c68d80dce18f Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 15:15:00 -0300 Subject: [PATCH 04/13] Start moving shared code to BaseTextAttachmentMessageCell --- Rocket.Chat.xcodeproj/project.pbxproj | 4 + .../Cells/BaseTextAttachmentMessageCell.swift | 102 ++++++++++++++++++ .../New Chat/Cells/TextAttachmentCell.swift | 98 +++-------------- 3 files changed, 119 insertions(+), 85 deletions(-) create mode 100644 Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift diff --git a/Rocket.Chat.xcodeproj/project.pbxproj b/Rocket.Chat.xcodeproj/project.pbxproj index 2c969bec62..37167f901c 100644 --- a/Rocket.Chat.xcodeproj/project.pbxproj +++ b/Rocket.Chat.xcodeproj/project.pbxproj @@ -799,6 +799,7 @@ 9990750F2176202400CAB7C8 /* BaseFileMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9990750E2176202400CAB7C8 /* BaseFileMessageCell.swift */; }; 999075112176222300CAB7C8 /* FileMessageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 999075102176222300CAB7C8 /* FileMessageCell.xib */; }; 99907513217622A900CAB7C8 /* FileMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99907512217622A900CAB7C8 /* FileMessageCell.swift */; }; + 9990751521765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9990751421765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift */; }; 99923773204B3BD800C2D15F /* UploadAvatarRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99923772204B3BD800C2D15F /* UploadAvatarRequest.swift */; }; 999483EB20644CC4004F61CA /* WebBrowserViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 999483EA20644CC4004F61CA /* WebBrowserViewModel.swift */; }; 999F25B5207EEB0C002E0F68 /* FileModelMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 999F25B4207EEB0C002E0F68 /* FileModelMapping.swift */; }; @@ -1697,6 +1698,7 @@ 9990750E2176202400CAB7C8 /* BaseFileMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseFileMessageCell.swift; sourceTree = ""; }; 999075102176222300CAB7C8 /* FileMessageCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FileMessageCell.xib; sourceTree = ""; }; 99907512217622A900CAB7C8 /* FileMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMessageCell.swift; sourceTree = ""; }; + 9990751421765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTextAttachmentMessageCell.swift; sourceTree = ""; }; 99923772204B3BD800C2D15F /* UploadAvatarRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadAvatarRequest.swift; sourceTree = ""; }; 999483EA20644CC4004F61CA /* WebBrowserViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebBrowserViewModel.swift; sourceTree = ""; }; 999F25B4207EEB0C002E0F68 /* FileModelMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileModelMapping.swift; sourceTree = ""; }; @@ -3751,6 +3753,7 @@ 99907512217622A900CAB7C8 /* FileMessageCell.swift */, 993B7B3B215F07020067B962 /* FileCell.xib */, 993B7B3D215F0A270067B962 /* FileCell.swift */, + 9990751421765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift */, 998E649521619DF700E7C45A /* TextAttachmentCell.xib */, 998E64972161ADE200E7C45A /* TextAttachmentCell.swift */, 998E64992161B3E300E7C45A /* AttachmentFieldView.xib */, @@ -4610,6 +4613,7 @@ 41499C8F1F2A116900790EA7 /* ServerManager.swift in Sources */, 995F710E20C7837300B7535F /* AuthSeparatorTableViewCell.swift in Sources */, 41B554C51FBF0C71000510B7 /* UIWindowExtensions.swift in Sources */, + 9990751521765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift in Sources */, 8062E33520A5ECF50044F407 /* APIRequestOption.swift in Sources */, 99B15BCD20FD4589005A528F /* DatabaseManagerAuthSettings.swift in Sources */, 807C7C0620751ED2006B600E /* SpotlightClient.swift in Sources */, diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift new file mode 100644 index 0000000000..df22092850 --- /dev/null +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift @@ -0,0 +1,102 @@ +// +// BaseTextAttachmentMessageCell.swift +// Rocket.Chat +// +// Created by Filipe Alvarenga on 16/10/18. +// Copyright © 2018 Rocket.Chat. All rights reserved. +// + +import UIKit + +class BaseTextAttachmentMessageCell: MessageHeaderCell { + weak var delegate: ChatMessageCellProtocol? + + var subtitleHeightConstraint: NSLayoutConstraint! + var emptySubtitleHeightConstraint: NSLayoutConstraint! + var textContainerLeadingInitialConstant: CGFloat = 0 + var statusViewLeadingInitialConstant: CGFloat = 0 + var statusViewWidthInitialConstant: CGFloat = 0 + var fieldsStackViewLeadingInitialConstant: CGFloat = 0 + var fieldsStackViewTrailingInitialConstant: CGFloat = 0 + var textContainerTrailingInitialConstant: CGFloat = 0 + var fieldsStackTopInitialConstant: CGFloat = 0 + var fieldsStackHeightInitialConstant: CGFloat = 0 + var subtitleHeightInitialConstant: CGFloat = 0 + var subtitleTopInitialConstant: CGFloat = 0 + var fieldLabelWidth: CGFloat { + return + UIScreen.main.bounds.width - + textContainerLeadingInitialConstant - + statusViewLeadingInitialConstant - + statusViewWidthInitialConstant - + fieldsStackViewLeadingInitialConstant - + fieldsStackViewTrailingInitialConstant - + textContainerTrailingInitialConstant - + adjustedHorizontalInsets + } + + func configure(stackView: UIStackView) -> CGFloat { + guard let viewModel = viewModel?.base as? TextAttachmentChatItem else { + return 0 + } + + let maxSize = CGSize(width: fieldLabelWidth, height: .greatestFiniteMagnitude) + var stackViewHeight: CGFloat = 0 + var attachmentFieldViews: [AttachmentFieldView] = [] + + reset(stackView: stackView) + + for attachmentField in viewModel.attachment.fields { + guard let attachmentFieldView = AttachmentFieldView.instantiateFromNib() else { + continue + } + + let attributedValue = NSMutableAttributedString(string: attachmentField.value).transformMarkdown(with: theme) + attachmentFieldView.field.text = attachmentField.title + attachmentFieldView.value.attributedText = attributedValue + + let valueTextHeight = attachmentFieldView.value.sizeThatFits(maxSize).height + let fieldViewHeight = attachmentFieldView.fieldHeightConstraint.constant + + attachmentFieldView.valueTopConstraint.constant + + valueTextHeight + + stackViewHeight += fieldViewHeight + attachmentFieldView.contentSize = CGSize(width: fieldLabelWidth, height: fieldViewHeight) + attachmentFieldView.invalidateIntrinsicContentSize() + attachmentFieldViews.append(attachmentFieldView) + } + + stackViewHeight += stackView.spacing * CGFloat(attachmentFieldViews.count - 1) + + attachmentFieldViews.forEach { view in + stackView.addArrangedSubview(view) + } + + return stackViewHeight + } + + func reset(stackView: UIStackView) { + stackView.arrangedSubviews.forEach { subview in + stackView.removeArrangedSubview(subview) + subview.removeFromSuperview() + } + } + + @objc func didTapTextContainerView() { + guard + let viewModel = viewModel, + let textAttachmentViewModel = viewModel.base as? TextAttachmentChatItem + else { + return + } + + textAttachmentViewModel.toggleAttachmentFields() + delegate?.viewDidCollapseChange(viewModel: viewModel) + } +} + +extension BaseTextAttachmentMessageCell: UIGestureRecognizerDelegate { + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool { + return false + } +} diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentCell.swift index 85a5a94719..5ad1640b3f 100644 --- a/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentCell.swift +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentCell.swift @@ -9,7 +9,7 @@ import UIKit import RocketChatViewController -final class TextAttachmentCell: UICollectionViewCell, ChatCell, SizingCell { +final class TextAttachmentCell: BaseTextAttachmentMessageCell, SizingCell { static let identifier = String(describing: TextAttachmentCell.self) static let sizingCell: UICollectionViewCell & ChatCell = { @@ -36,28 +36,6 @@ final class TextAttachmentCell: UICollectionViewCell, ChatCell, SizingCell { @IBOutlet weak var fieldsStackViewTrailingConstraint: NSLayoutConstraint! @IBOutlet weak var fieldsStackViewHeightConstraint: NSLayoutConstraint! @IBOutlet weak var textContainerTrailingConstraint: NSLayoutConstraint! - var fieldLabelWidth: CGFloat { - return - UIScreen.main.bounds.width - - textContainerLeadingConstraint.constant - - statusViewLeadingConstraint.constant - - statusViewWidthConstraint.constant - - fieldsStackViewLeadingConstraint.constant - - fieldsStackViewTrailingConstraint.constant - - textContainerTrailingConstraint.constant - - adjustedHorizontalInsets - } - - weak var delegate: ChatMessageCellProtocol? - - var adjustedHorizontalInsets: CGFloat = 0 - var viewModel: AnyChatItem? - var subtitleHeightConstraint: NSLayoutConstraint! - var emptySubtitleHeightConstraint: NSLayoutConstraint! - var fieldsStackTopInitialConstant: CGFloat = 0 - var fieldsStackHeightInitialConstant: CGFloat = 0 - var subtitleHeightInitialConstant: CGFloat = 0 - var subtitleTopInitialConstant: CGFloat = 0 override func awakeFromNib() { super.awakeFromNib() @@ -89,13 +67,19 @@ final class TextAttachmentCell: UICollectionViewCell, ChatCell, SizingCell { fieldsStackHeightInitialConstant = fieldsStackViewHeightConstraint.constant subtitleTopInitialConstant = subtitleTopConstraint.constant subtitleHeightInitialConstant = subtitleHeightConstraint.constant + textContainerLeadingInitialConstant = textContainerLeadingConstraint.constant + statusViewLeadingInitialConstant = statusViewLeadingConstraint.constant + statusViewWidthInitialConstant = statusViewWidthConstraint.constant + fieldsStackViewLeadingInitialConstant = fieldsStackViewLeadingConstraint.constant + fieldsStackViewTrailingInitialConstant = fieldsStackViewTrailingConstraint.constant + textContainerTrailingInitialConstant = textContainerTrailingConstraint.constant let gesture = UITapGestureRecognizer(target: self, action: #selector(didTapTextContainerView)) gesture.delegate = self textContainer.addGestureRecognizer(gesture) } - func configure() { + override func configure() { guard let viewModel = viewModel?.base as? TextAttachmentChatItem else { return } @@ -117,7 +101,7 @@ final class TextAttachmentCell: UICollectionViewCell, ChatCell, SizingCell { emptySubtitleHeightConstraint.constant = 0 subtitle.text = "" - resetFieldsStackView() + reset(stackView: fieldsStackView) fieldsStackViewTopConstraint.constant = 0 fieldsStackViewHeightConstraint.constant = 0 } @@ -131,6 +115,7 @@ final class TextAttachmentCell: UICollectionViewCell, ChatCell, SizingCell { subtitleTopConstraint.constant = subtitleTopInitialConstant subtitleHeightConstraint.constant = subtitleHeightInitialConstant subtitle.text = subtitleText + layoutIfNeeded() } else { subtitleHeightConstraint.isActive = false emptySubtitleHeightConstraint.isActive = true @@ -139,73 +124,16 @@ final class TextAttachmentCell: UICollectionViewCell, ChatCell, SizingCell { subtitle.text = "" } - let maxSize = CGSize(width: fieldLabelWidth, height: .greatestFiniteMagnitude) - var stackViewHeight: CGFloat = 0 - var attachmentFieldViews: [AttachmentFieldView] = [] - - resetFieldsStackView() - fieldsStackViewTopConstraint.constant = fieldsStackTopInitialConstant - fieldsStackViewHeightConstraint.constant = fieldsStackHeightInitialConstant - - for attachmentField in viewModel.attachment.fields { - guard let attachmentFieldView = AttachmentFieldView.instantiateFromNib() else { - continue - } - - let attributedValue = NSMutableAttributedString(string: attachmentField.value).transformMarkdown(with: theme) - attachmentFieldView.field.text = attachmentField.title - attachmentFieldView.value.attributedText = attributedValue - - let valueTextHeight = attachmentFieldView.value.sizeThatFits(maxSize).height - let fieldViewHeight = attachmentFieldView.fieldHeightConstraint.constant + - attachmentFieldView.valueTopConstraint.constant + - valueTextHeight - - stackViewHeight += fieldViewHeight - attachmentFieldView.contentSize = CGSize(width: fieldLabelWidth, height: fieldViewHeight) - attachmentFieldView.invalidateIntrinsicContentSize() - attachmentFieldViews.append(attachmentFieldView) - } - - stackViewHeight += fieldsStackView.spacing * CGFloat(attachmentFieldViews.count - 1) - fieldsStackViewHeightConstraint.constant = stackViewHeight + fieldsStackViewHeightConstraint.constant = configure(stackView: fieldsStackView) layoutIfNeeded() - - attachmentFieldViews.forEach { view in - fieldsStackView.addArrangedSubview(view) - } - } - - func resetFieldsStackView() { - fieldsStackView.arrangedSubviews.forEach { subview in - fieldsStackView.removeArrangedSubview(subview) - subview.removeFromSuperview() - } - } - - @objc func didTapTextContainerView() { - guard - let viewModel = viewModel, - let textAttachmentViewModel = viewModel.base as? TextAttachmentChatItem - else { - return - } - - textAttachmentViewModel.toggleAttachmentFields() - delegate?.viewDidCollapseChange(viewModel: viewModel) } override func prepareForReuse() { super.prepareForReuse() - resetFieldsStackView() + reset(stackView: fieldsStackView) + fieldsStackViewTopConstraint.constant = fieldsStackTopInitialConstant fieldsStackViewHeightConstraint.constant = fieldsStackHeightInitialConstant } } - -extension TextAttachmentCell: UIGestureRecognizerDelegate { - func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool { - return false - } -} From d975a2e952bc13a1e1c26d9d9ff565a5d07506e6 Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 15:31:25 -0300 Subject: [PATCH 05/13] Fix subtitle label sizing bug --- .../Views/Chat/New Chat/Cells/TextAttachmentCell.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentCell.swift index 5ad1640b3f..a80548dab6 100644 --- a/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentCell.swift +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentCell.swift @@ -113,9 +113,11 @@ final class TextAttachmentCell: BaseTextAttachmentMessageCell, SizingCell { emptySubtitleHeightConstraint.isActive = false subtitleHeightConstraint.isActive = true subtitleTopConstraint.constant = subtitleTopInitialConstant - subtitleHeightConstraint.constant = subtitleHeightInitialConstant subtitle.text = subtitleText - layoutIfNeeded() + + let maxSize = CGSize(width: fieldLabelWidth, height: .greatestFiniteMagnitude) + let subtitleHeight = subtitle.sizeThatFits(maxSize).height + subtitleHeightConstraint.constant = subtitleHeight } else { subtitleHeightConstraint.isActive = false emptySubtitleHeightConstraint.isActive = true @@ -125,8 +127,6 @@ final class TextAttachmentCell: BaseTextAttachmentMessageCell, SizingCell { } fieldsStackViewHeightConstraint.constant = configure(stackView: fieldsStackView) - - layoutIfNeeded() } override func prepareForReuse() { @@ -135,5 +135,6 @@ final class TextAttachmentCell: BaseTextAttachmentMessageCell, SizingCell { reset(stackView: fieldsStackView) fieldsStackViewTopConstraint.constant = fieldsStackTopInitialConstant fieldsStackViewHeightConstraint.constant = fieldsStackHeightInitialConstant + subtitleTopConstraint.constant = subtitleTopInitialConstant } } From ea459eabff52538a5f4c8404d7fee8a5bcecbf84 Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 15:46:23 -0300 Subject: [PATCH 06/13] Implement TextAttachment with message headers --- Rocket.Chat.xcodeproj/project.pbxproj | 8 + .../Cells/BaseTextAttachmentMessageCell.swift | 4 + .../Cells/TextAttachmentMessageCell.swift | 155 +++++++++++++++++ .../Cells/TextAttachmentMessageCell.xib | 156 ++++++++++++++++++ 4 files changed, 323 insertions(+) create mode 100644 Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentMessageCell.swift create mode 100644 Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentMessageCell.xib diff --git a/Rocket.Chat.xcodeproj/project.pbxproj b/Rocket.Chat.xcodeproj/project.pbxproj index 37167f901c..bf9c0cb6a8 100644 --- a/Rocket.Chat.xcodeproj/project.pbxproj +++ b/Rocket.Chat.xcodeproj/project.pbxproj @@ -800,6 +800,8 @@ 999075112176222300CAB7C8 /* FileMessageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 999075102176222300CAB7C8 /* FileMessageCell.xib */; }; 99907513217622A900CAB7C8 /* FileMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99907512217622A900CAB7C8 /* FileMessageCell.swift */; }; 9990751521765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9990751421765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift */; }; + 99907517217666C000CAB7C8 /* TextAttachmentMessageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 99907516217666C000CAB7C8 /* TextAttachmentMessageCell.xib */; }; + 999075192176673800CAB7C8 /* TextAttachmentMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 999075182176673800CAB7C8 /* TextAttachmentMessageCell.swift */; }; 99923773204B3BD800C2D15F /* UploadAvatarRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99923772204B3BD800C2D15F /* UploadAvatarRequest.swift */; }; 999483EB20644CC4004F61CA /* WebBrowserViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 999483EA20644CC4004F61CA /* WebBrowserViewModel.swift */; }; 999F25B5207EEB0C002E0F68 /* FileModelMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 999F25B4207EEB0C002E0F68 /* FileModelMapping.swift */; }; @@ -1699,6 +1701,8 @@ 999075102176222300CAB7C8 /* FileMessageCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FileMessageCell.xib; sourceTree = ""; }; 99907512217622A900CAB7C8 /* FileMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMessageCell.swift; sourceTree = ""; }; 9990751421765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTextAttachmentMessageCell.swift; sourceTree = ""; }; + 99907516217666C000CAB7C8 /* TextAttachmentMessageCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TextAttachmentMessageCell.xib; sourceTree = ""; }; + 999075182176673800CAB7C8 /* TextAttachmentMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextAttachmentMessageCell.swift; sourceTree = ""; }; 99923772204B3BD800C2D15F /* UploadAvatarRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadAvatarRequest.swift; sourceTree = ""; }; 999483EA20644CC4004F61CA /* WebBrowserViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebBrowserViewModel.swift; sourceTree = ""; }; 999F25B4207EEB0C002E0F68 /* FileModelMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileModelMapping.swift; sourceTree = ""; }; @@ -3754,6 +3758,8 @@ 993B7B3B215F07020067B962 /* FileCell.xib */, 993B7B3D215F0A270067B962 /* FileCell.swift */, 9990751421765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift */, + 99907516217666C000CAB7C8 /* TextAttachmentMessageCell.xib */, + 999075182176673800CAB7C8 /* TextAttachmentMessageCell.swift */, 998E649521619DF700E7C45A /* TextAttachmentCell.xib */, 998E64972161ADE200E7C45A /* TextAttachmentCell.swift */, 998E64992161B3E300E7C45A /* AttachmentFieldView.xib */, @@ -4284,6 +4290,7 @@ 41DE688120C6EBE600AA5EC8 /* SubscriptionSortingCell.xib in Resources */, 41FBF4EB20BD8C650080D00D /* ServerCell.xib in Resources */, 14F8A220202E5CBF00175FDC /* Black-29@3x.png in Resources */, + 99907517217666C000CAB7C8 /* TextAttachmentMessageCell.xib in Resources */, 80AE2544203E61CF00DC2867 /* ChatMessageUnreadSeparator.xib in Resources */, 33A5C9D2206A565800FE1C8F /* nature.json in Resources */, 14F8A26E202E653E00175FDC /* Grey-76@3x.png in Resources */, @@ -4661,6 +4668,7 @@ 4112DC5A1FFFB9B2005995E1 /* ModelMappeable.swift in Sources */, 809B53161FE3D3DC00833DD2 /* MessageReaction.swift in Sources */, D10E9C1A1F643457007F1796 /* Channel.swift in Sources */, + 999075192176673800CAB7C8 /* TextAttachmentMessageCell.swift in Sources */, 0B9AB2C120444ECD00ABEA05 /* LanguageViewController.swift in Sources */, 806728FD200789F4009FE94D /* PreferencesNavigationController.swift in Sources */, 413996171F3B44500075F96E /* UploadHelper.swift in Sources */, diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift index df22092850..2ed7843500 100644 --- a/Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift @@ -13,6 +13,8 @@ class BaseTextAttachmentMessageCell: MessageHeaderCell { var subtitleHeightConstraint: NSLayoutConstraint! var emptySubtitleHeightConstraint: NSLayoutConstraint! + var avatarLeadingInitialConstant: CGFloat = 0 + var avatarWidthInitialConstant: CGFloat = 0 var textContainerLeadingInitialConstant: CGFloat = 0 var statusViewLeadingInitialConstant: CGFloat = 0 var statusViewWidthInitialConstant: CGFloat = 0 @@ -26,6 +28,8 @@ class BaseTextAttachmentMessageCell: MessageHeaderCell { var fieldLabelWidth: CGFloat { return UIScreen.main.bounds.width - + avatarLeadingInitialConstant - + avatarWidthInitialConstant textContainerLeadingInitialConstant - statusViewLeadingInitialConstant - statusViewWidthInitialConstant - diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentMessageCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentMessageCell.swift new file mode 100644 index 0000000000..aad67d8e98 --- /dev/null +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentMessageCell.swift @@ -0,0 +1,155 @@ +// +// TextAttachmentMessageCell.swift +// Rocket.Chat +// +// Created by Filipe Alvarenga on 16/10/18. +// Copyright © 2018 Rocket.Chat. All rights reserved. +// + +import UIKit +import RocketChatViewController + +final class TextAttachmentMessageCell: BaseTextAttachmentMessageCell, SizingCell { + static let identifier = String(describing: TextAttachmentMessageCell.self) + + static let sizingCell: UICollectionViewCell & ChatCell = { + guard let cell = TextAttachmentMessageCell.instantiateFromNib() else { + return TextAttachmentMessageCell() + } + + return cell + }() + + @IBOutlet weak var avatarContainerView: UIView! { + didSet { + avatarContainerView.layer.cornerRadius = 4 + avatarView.frame = avatarContainerView.bounds + avatarContainerView.addSubview(avatarView) + } + } + + @IBOutlet weak var username: UILabel! + @IBOutlet weak var date: UILabel! + @IBOutlet weak var textContainer: UIView! + @IBOutlet weak var title: UILabel! + @IBOutlet weak var subtitle: UILabel! + @IBOutlet weak var statusView: UIView! + @IBOutlet weak var arrow: UIImageView! + @IBOutlet weak var fieldsStackView: UIStackView! + + @IBOutlet weak var avatarLeadingConstraint: NSLayoutConstraint! + @IBOutlet weak var avatarWidthConstraint: NSLayoutConstraint! + @IBOutlet weak var textContainerLeadingConstraint: NSLayoutConstraint! + @IBOutlet weak var statusViewWidthConstraint: NSLayoutConstraint! + @IBOutlet weak var statusViewLeadingConstraint: NSLayoutConstraint! + @IBOutlet weak var subtitleTopConstraint: NSLayoutConstraint! + @IBOutlet weak var fieldsStackViewTopConstraint: NSLayoutConstraint! + @IBOutlet weak var fieldsStackViewLeadingConstraint: NSLayoutConstraint! + @IBOutlet weak var fieldsStackViewTrailingConstraint: NSLayoutConstraint! + @IBOutlet weak var fieldsStackViewHeightConstraint: NSLayoutConstraint! + @IBOutlet weak var textContainerTrailingConstraint: NSLayoutConstraint! + + override func awakeFromNib() { + super.awakeFromNib() + + emptySubtitleHeightConstraint = NSLayoutConstraint( + item: subtitle, + attribute: .height, + relatedBy: .equal, + toItem: nil, + attribute: .notAnAttribute, + multiplier: 0, + constant: 0 + ) + + subtitleHeightConstraint = NSLayoutConstraint( + item: subtitle, + attribute: .height, + relatedBy: .greaterThanOrEqual, + toItem: nil, + attribute: .notAnAttribute, + multiplier: 0, + constant: 16 + ) + + emptySubtitleHeightConstraint.isActive = false + subtitleHeightConstraint.isActive = true + + fieldsStackTopInitialConstant = fieldsStackViewTopConstraint.constant + fieldsStackHeightInitialConstant = fieldsStackViewHeightConstraint.constant + subtitleTopInitialConstant = subtitleTopConstraint.constant + subtitleHeightInitialConstant = subtitleHeightConstraint.constant + avatarLeadingInitialConstant = avatarLeadingConstraint.constant + avatarWidthInitialConstant = avatarWidthConstraint.constant + textContainerLeadingInitialConstant = textContainerLeadingConstraint.constant + statusViewLeadingInitialConstant = statusViewLeadingConstraint.constant + statusViewWidthInitialConstant = statusViewWidthConstraint.constant + fieldsStackViewLeadingInitialConstant = fieldsStackViewLeadingConstraint.constant + fieldsStackViewTrailingInitialConstant = fieldsStackViewTrailingConstraint.constant + textContainerTrailingInitialConstant = textContainerTrailingConstraint.constant + + let gesture = UITapGestureRecognizer(target: self, action: #selector(didTapTextContainerView)) + gesture.delegate = self + textContainer.addGestureRecognizer(gesture) + } + + override func configure() { + guard let viewModel = viewModel?.base as? TextAttachmentChatItem else { + return + } + + title.text = viewModel.attachment.title + configure(with: avatarView, date: date, and: username) + + if viewModel.attachment.collapsed { + configureCollapsedState(with: viewModel) + } else { + configureExpandedState(with: viewModel) + } + } + + func configureCollapsedState(with viewModel: TextAttachmentChatItem) { + arrow.image = #imageLiteral(resourceName: "Attachment Collapsed Light") + subtitleHeightConstraint.isActive = false + emptySubtitleHeightConstraint.isActive = true + subtitleTopConstraint.constant = 0 + emptySubtitleHeightConstraint.constant = 0 + subtitle.text = "" + + reset(stackView: fieldsStackView) + fieldsStackViewTopConstraint.constant = 0 + fieldsStackViewHeightConstraint.constant = 0 + } + + func configureExpandedState(with viewModel: TextAttachmentChatItem) { + arrow.image = #imageLiteral(resourceName: "Attachment Expanded Light") + + if let subtitleText = viewModel.attachment.text { + emptySubtitleHeightConstraint.isActive = false + subtitleHeightConstraint.isActive = true + subtitleTopConstraint.constant = subtitleTopInitialConstant + subtitle.text = subtitleText + + let maxSize = CGSize(width: fieldLabelWidth, height: .greatestFiniteMagnitude) + let subtitleHeight = subtitle.sizeThatFits(maxSize).height + subtitleHeightConstraint.constant = subtitleHeight + } else { + subtitleHeightConstraint.isActive = false + emptySubtitleHeightConstraint.isActive = true + subtitleTopConstraint.constant = 0 + emptySubtitleHeightConstraint.constant = 0 + subtitle.text = "" + } + + fieldsStackViewHeightConstraint.constant = configure(stackView: fieldsStackView) + } + + override func prepareForReuse() { + super.prepareForReuse() + + reset(stackView: fieldsStackView) + fieldsStackViewTopConstraint.constant = fieldsStackTopInitialConstant + fieldsStackViewHeightConstraint.constant = fieldsStackHeightInitialConstant + subtitleTopConstraint.constant = subtitleTopInitialConstant + } +} diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentMessageCell.xib b/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentMessageCell.xib new file mode 100644 index 0000000000..8398453c3a --- /dev/null +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/TextAttachmentMessageCell.xib @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 2b06c0dcfa05b3f879c756169ebc18a2be740efc Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 15:50:13 -0300 Subject: [PATCH 07/13] Refactor TextAttachmentChatItem to support message headers --- .../Chat/ChatSections/MessageSection.swift | 20 ++++++++++++++++--- .../ChatItems/TextAttachmentChatItem.swift | 11 ++++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift index 61a6cd9133..3cc024ad8f 100644 --- a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift +++ b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift @@ -96,9 +96,23 @@ final class MessageSection: ChatSection { ).wrapped) } case .textAttachment where attachment.fields.count > 0: - cells.append(TextAttachmentChatItem( - attachment: attachment - ).wrapped) + if object.message.text.isEmpty && shouldAppendMessageHeader { + cells.append(TextAttachmentChatItem( + attachment: attachment, + hasText: false, + user: user, + message: object.message + ).wrapped) + + shouldAppendMessageHeader = false + } else { + cells.append(TextAttachmentChatItem( + attachment: attachment, + hasText: true, + user: nil, + message: nil + ).wrapped) + } case .textAttachment where !attachment.isFile: cells.append(QuoteChatItem( attachment: attachment diff --git a/Rocket.Chat/Views/Chat/New Chat/ChatItems/TextAttachmentChatItem.swift b/Rocket.Chat/Views/Chat/New Chat/ChatItems/TextAttachmentChatItem.swift index ca665e399c..5f2f7ffad0 100644 --- a/Rocket.Chat/Views/Chat/New Chat/ChatItems/TextAttachmentChatItem.swift +++ b/Rocket.Chat/Views/Chat/New Chat/ChatItems/TextAttachmentChatItem.swift @@ -11,12 +11,19 @@ import DifferenceKit import RocketChatViewController import RealmSwift -struct TextAttachmentChatItem: ChatItem, Differentiable { +final class TextAttachmentChatItem: MessageHeaderChatItem, ChatItem, Differentiable { var relatedReuseIdentifier: String { - return TextAttachmentCell.identifier + return hasText ? TextAttachmentCell.identifier : TextAttachmentMessageCell.identifier } var attachment: UnmanagedAttachment + let hasText: Bool + + init(attachment: UnmanagedAttachment, hasText: Bool, user: UnmanagedUser?, message: UnmanagedMessage?) { + self.attachment = attachment + self.hasText = hasText + super.init(user: user, avatar: message?.avatar, emoji: message?.emoji, date: message?.createdAt) + } var differenceIdentifier: String { return attachment.identifier From c465f1bba5a925a667b304c02bf972164be45634 Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 15:56:11 -0300 Subject: [PATCH 08/13] Add TextAttachmentMessageCell to MessagesViewController --- Rocket.Chat/Controllers/Chat/MessagesViewController.swift | 1 + .../Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift index 523a805b7f..15d8a21cb0 100644 --- a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift +++ b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift @@ -62,6 +62,7 @@ final class MessagesViewController: RocketChatViewController { collectionView.register(FileCell.nib, forCellWithReuseIdentifier: FileCell.identifier) collectionView.register(FileMessageCell.nib, forCellWithReuseIdentifier: FileMessageCell.identifier) collectionView.register(TextAttachmentCell.nib, forCellWithReuseIdentifier: TextAttachmentCell.identifier) + collectionView.register(TextAttachmentMessageCell.nib, forCellWithReuseIdentifier: TextAttachmentMessageCell.identifier) collectionView.register(ImageMessageCell.nib, forCellWithReuseIdentifier: ImageMessageCell.identifier) collectionView.register(QuoteCell.nib, forCellWithReuseIdentifier: QuoteCell.identifier) collectionView.register(MessageURLCell.nib, forCellWithReuseIdentifier: MessageURLCell.identifier) diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift index 2ed7843500..ea941e1728 100644 --- a/Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/BaseTextAttachmentMessageCell.swift @@ -29,7 +29,7 @@ class BaseTextAttachmentMessageCell: MessageHeaderCell { return UIScreen.main.bounds.width - avatarLeadingInitialConstant - - avatarWidthInitialConstant + avatarWidthInitialConstant - textContainerLeadingInitialConstant - statusViewLeadingInitialConstant - statusViewWidthInitialConstant - From 9940273834bc03f9237777375df29be978b3016a Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 16:26:29 -0300 Subject: [PATCH 09/13] Add BaseImageMessageCell and implement image cell with message headers --- Rocket.Chat.xcodeproj/project.pbxproj | 28 ++-- .../Chat/ChatSections/MessageSection.swift | 2 +- .../Chat/MessagesViewController.swift | 2 +- .../New Chat/Cells/BaseImageMessageCell.swift | 30 +++++ .../Views/Chat/New Chat/Cells/ImageCell.swift | 65 +++++++++ .../Views/Chat/New Chat/Cells/ImageCell.xib | 88 +++++++++++++ .../New Chat/Cells/ImageMessageCell.swift | 40 +++--- .../Chat/New Chat/Cells/ImageMessageCell.xib | 124 +++++++++++------- .../ChatItems/ImageMessageChatItem.swift | 2 +- 9 files changed, 303 insertions(+), 78 deletions(-) create mode 100644 Rocket.Chat/Views/Chat/New Chat/Cells/BaseImageMessageCell.swift create mode 100644 Rocket.Chat/Views/Chat/New Chat/Cells/ImageCell.swift create mode 100644 Rocket.Chat/Views/Chat/New Chat/Cells/ImageCell.xib diff --git a/Rocket.Chat.xcodeproj/project.pbxproj b/Rocket.Chat.xcodeproj/project.pbxproj index bf9c0cb6a8..aa96af8763 100644 --- a/Rocket.Chat.xcodeproj/project.pbxproj +++ b/Rocket.Chat.xcodeproj/project.pbxproj @@ -212,8 +212,8 @@ 412F8DD91F599EF100AF7786 /* DatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 412F8DD81F599EF100AF7786 /* DatabaseManager.swift */; }; 4133EDCF1DA2834E005AA783 /* ChatMessageImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4133EDCE1DA2834E005AA783 /* ChatMessageImageView.swift */; }; 4133EDD11DA2835F005AA783 /* ChatMessageImageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4133EDD01DA2835F005AA783 /* ChatMessageImageView.xib */; }; - 4135A64421623F1300C1741A /* ImageMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4135A64321623F1300C1741A /* ImageMessageCell.swift */; }; - 4135A64621623F2A00C1741A /* ImageMessageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4135A64521623F2A00C1741A /* ImageMessageCell.xib */; }; + 4135A64421623F1300C1741A /* ImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4135A64321623F1300C1741A /* ImageCell.swift */; }; + 4135A64621623F2A00C1741A /* ImageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4135A64521623F2A00C1741A /* ImageCell.xib */; }; 4135A64821623F3600C1741A /* ImageMessageChatItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4135A64721623F3600C1741A /* ImageMessageChatItem.swift */; }; 413996171F3B44500075F96E /* UploadHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413996161F3B44500075F96E /* UploadHelper.swift */; }; 413FB6BF1FE17D7D00F010AA /* UIStoryboardExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413FB6BA1FE17D7C00F010AA /* UIStoryboardExtensions.swift */; }; @@ -802,6 +802,9 @@ 9990751521765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9990751421765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift */; }; 99907517217666C000CAB7C8 /* TextAttachmentMessageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 99907516217666C000CAB7C8 /* TextAttachmentMessageCell.xib */; }; 999075192176673800CAB7C8 /* TextAttachmentMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 999075182176673800CAB7C8 /* TextAttachmentMessageCell.swift */; }; + 9990751B21766DF000CAB7C8 /* ImageMessageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9990751A21766DF000CAB7C8 /* ImageMessageCell.xib */; }; + 9990751D21766ECE00CAB7C8 /* BaseImageMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9990751C21766ECE00CAB7C8 /* BaseImageMessageCell.swift */; }; + 9990751F2176714700CAB7C8 /* ImageMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9990751E2176714700CAB7C8 /* ImageMessageCell.swift */; }; 99923773204B3BD800C2D15F /* UploadAvatarRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99923772204B3BD800C2D15F /* UploadAvatarRequest.swift */; }; 999483EB20644CC4004F61CA /* WebBrowserViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 999483EA20644CC4004F61CA /* WebBrowserViewModel.swift */; }; 999F25B5207EEB0C002E0F68 /* FileModelMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 999F25B4207EEB0C002E0F68 /* FileModelMapping.swift */; }; @@ -1113,8 +1116,8 @@ 412F8DD81F599EF100AF7786 /* DatabaseManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = ""; }; 4133EDCE1DA2834E005AA783 /* ChatMessageImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatMessageImageView.swift; sourceTree = ""; }; 4133EDD01DA2835F005AA783 /* ChatMessageImageView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ChatMessageImageView.xib; sourceTree = ""; }; - 4135A64321623F1300C1741A /* ImageMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageMessageCell.swift; sourceTree = ""; }; - 4135A64521623F2A00C1741A /* ImageMessageCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ImageMessageCell.xib; sourceTree = ""; }; + 4135A64321623F1300C1741A /* ImageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCell.swift; sourceTree = ""; }; + 4135A64521623F2A00C1741A /* ImageCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ImageCell.xib; sourceTree = ""; }; 4135A64721623F3600C1741A /* ImageMessageChatItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageMessageChatItem.swift; sourceTree = ""; }; 413996161F3B44500075F96E /* UploadHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UploadHelper.swift; sourceTree = ""; }; 413FB6BA1FE17D7C00F010AA /* UIStoryboardExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIStoryboardExtensions.swift; sourceTree = ""; }; @@ -1703,6 +1706,9 @@ 9990751421765B9600CAB7C8 /* BaseTextAttachmentMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTextAttachmentMessageCell.swift; sourceTree = ""; }; 99907516217666C000CAB7C8 /* TextAttachmentMessageCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TextAttachmentMessageCell.xib; sourceTree = ""; }; 999075182176673800CAB7C8 /* TextAttachmentMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextAttachmentMessageCell.swift; sourceTree = ""; }; + 9990751A21766DF000CAB7C8 /* ImageMessageCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ImageMessageCell.xib; sourceTree = ""; }; + 9990751C21766ECE00CAB7C8 /* BaseImageMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseImageMessageCell.swift; sourceTree = ""; }; + 9990751E2176714700CAB7C8 /* ImageMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageMessageCell.swift; sourceTree = ""; }; 99923772204B3BD800C2D15F /* UploadAvatarRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadAvatarRequest.swift; sourceTree = ""; }; 999483EA20644CC4004F61CA /* WebBrowserViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebBrowserViewModel.swift; sourceTree = ""; }; 999F25B4207EEB0C002E0F68 /* FileModelMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileModelMapping.swift; sourceTree = ""; }; @@ -3764,8 +3770,11 @@ 998E64972161ADE200E7C45A /* TextAttachmentCell.swift */, 998E64992161B3E300E7C45A /* AttachmentFieldView.xib */, 998E649B2161B4D900E7C45A /* AttachmentFieldView.swift */, - 4135A64521623F2A00C1741A /* ImageMessageCell.xib */, - 4135A64321623F1300C1741A /* ImageMessageCell.swift */, + 9990751C21766ECE00CAB7C8 /* BaseImageMessageCell.swift */, + 9990751A21766DF000CAB7C8 /* ImageMessageCell.xib */, + 9990751E2176714700CAB7C8 /* ImageMessageCell.swift */, + 4135A64521623F2A00C1741A /* ImageCell.xib */, + 4135A64321623F1300C1741A /* ImageCell.swift */, 99B4A7AF2164681200C80FF2 /* QuoteCell.xib */, 99B4A7B12164683200C80FF2 /* QuoteCell.swift */, 9914183A2166AF63007D2AA2 /* MessageURLCell.xib */, @@ -4225,6 +4234,7 @@ 41DF76ED1D2C50720028DBF8 /* LaunchScreen.storyboard in Resources */, 140A95E1202F526C003FD564 /* Drawing.storyboard in Resources */, 9914183B2166AF63007D2AA2 /* MessageURLCell.xib in Resources */, + 9990751B21766DF000CAB7C8 /* ImageMessageCell.xib in Resources */, 8041C0442028C828007E21FA /* ReactorListView.xib in Resources */, 8020CCF21FEAB4C3003424F4 /* EmojiPicker.xib in Resources */, 80307E411FD75DC0006AD9EF /* VoiceOver.strings in Resources */, @@ -4279,7 +4289,7 @@ 14F8A282202E659000175FDC /* White-76@3x.png in Resources */, 999075112176222300CAB7C8 /* FileMessageCell.xib in Resources */, 14F8A223202E5CBF00175FDC /* Black-76@2x.png in Resources */, - 4135A64621623F2A00C1741A /* ImageMessageCell.xib in Resources */, + 4135A64621623F2A00C1741A /* ImageCell.xib in Resources */, 80AC400420EECB03005082E1 /* ChatBannerView.xib in Resources */, 14F8A23D202E5D0600175FDC /* Red-29@3x.png in Resources */, 419EB5BF215E6A0C00E591BF /* ReactionsCell.xib in Resources */, @@ -4730,6 +4740,7 @@ 412719461E6B403700461FEE /* RegisterUsernameTableViewController.swift in Sources */, 806C59A21FBB0BD600C32D0A /* PostMessageRequest.swift in Sources */, 1496A87C20FA481B005C2E14 /* SaveNotificationRequest.swift in Sources */, + 9990751F2176714700CAB7C8 /* ImageMessageCell.swift in Sources */, 9938A08720D3141C00714AB4 /* CustomFieldTableViewCell.swift in Sources */, 41BAE3E71D71B26C00C2445A /* URLExtension.swift in Sources */, 991AB00821744E640097AE4C /* BaseAudioMessageCell.swift in Sources */, @@ -4808,6 +4819,7 @@ 80054CF31FD951B100F5ECF9 /* MessagesClient.swift in Sources */, 80CC78CF20DAE334002FBEBC /* SubscriptionsViewModel.swift in Sources */, 33E33ED620E0E59B00EF4560 /* AuthNavigationController.swift in Sources */, + 9990751D21766ECE00CAB7C8 /* BaseImageMessageCell.swift in Sources */, 33F73B302073F24200F03F29 /* NotificationViewController.swift in Sources */, 99DBB8742090360600382DB2 /* MessagesListControllerSearch.swift in Sources */, 414E8A8D20A5DD2200615CE6 /* RoomRolesRequest.swift in Sources */, @@ -4913,7 +4925,7 @@ 8076FDC320485A2200114F28 /* SubscriptionUtils.swift in Sources */, 33D08E2420BD5EDC008D03EF /* ThemeableViewControllers.swift in Sources */, 35BCD301201A57EA00B4BE5A /* Ask.swift in Sources */, - 4135A64421623F1300C1741A /* ImageMessageCell.swift in Sources */, + 4135A64421623F1300C1741A /* ImageCell.swift in Sources */, 33D08E3120BD92A5008D03EF /* ThemePreferenceCell.swift in Sources */, 80CCD3BC216235B1002AFE83 /* MessagesComposerViewModel.swift in Sources */, 992B5AB6209A14B5009C8123 /* AudioFileViewController.swift in Sources */, diff --git a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift index 3cc024ad8f..efc1fed488 100644 --- a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift +++ b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift @@ -186,7 +186,7 @@ final class MessageSection: ChatSection { cell.delegate = self } else if let cell = cell as? FileCell { cell.delegate = self - } else if let cell = cell as? ImageMessageCell { + } else if let cell = cell as? ImageCell { cell.delegate = self } else if let cell = cell as? TextAttachmentCell { cell.delegate = self diff --git a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift index 15d8a21cb0..2da2572fe4 100644 --- a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift +++ b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift @@ -63,7 +63,7 @@ final class MessagesViewController: RocketChatViewController { collectionView.register(FileMessageCell.nib, forCellWithReuseIdentifier: FileMessageCell.identifier) collectionView.register(TextAttachmentCell.nib, forCellWithReuseIdentifier: TextAttachmentCell.identifier) collectionView.register(TextAttachmentMessageCell.nib, forCellWithReuseIdentifier: TextAttachmentMessageCell.identifier) - collectionView.register(ImageMessageCell.nib, forCellWithReuseIdentifier: ImageMessageCell.identifier) + collectionView.register(ImageCell.nib, forCellWithReuseIdentifier: ImageCell.identifier) collectionView.register(QuoteCell.nib, forCellWithReuseIdentifier: QuoteCell.identifier) collectionView.register(MessageURLCell.nib, forCellWithReuseIdentifier: MessageURLCell.identifier) diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/BaseImageMessageCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/BaseImageMessageCell.swift new file mode 100644 index 0000000000..90c93f7ea9 --- /dev/null +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/BaseImageMessageCell.swift @@ -0,0 +1,30 @@ +// +// BaseImageMessageCell.swift +// Rocket.Chat +// +// Created by Filipe Alvarenga on 16/10/18. +// Copyright © 2018 Rocket.Chat. All rights reserved. +// + +import UIKit + +class BaseImageMessageCell: MessageHeaderCell { + weak var delegate: ChatMessageCellProtocol? + + func loadImage(on imageView: UIImageView, startLoadingBlock: () -> Void, stopLoadingBlock: @escaping () -> Void) { + guard let viewModel = viewModel?.base as? ImageMessageChatItem else { + return + } + + if let imageURL = viewModel.imageURL { + startLoadingBlock() + ImageManager.loadImage(with: imageURL, into: imageView) { _, _ in + stopLoadingBlock() + + // TODO: In case of error, show some error placeholder + } + } else { + // TODO: Load some error placeholder + } + } +} diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/ImageCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/ImageCell.swift new file mode 100644 index 0000000000..a90e4d739f --- /dev/null +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/ImageCell.swift @@ -0,0 +1,65 @@ +// +// ImageMessageCell.swift +// Rocket.Chat +// +// Created by Rafael Streit on 01/10/18. +// Copyright © 2018 Rocket.Chat. All rights reserved. +// + +import Foundation +import RocketChatViewController +import FLAnimatedImage + +final class ImageCell: BaseImageMessageCell, SizingCell { + static let identifier = String(describing: ImageCell.self) + + static let sizingCell: UICollectionViewCell & ChatCell = { + guard let cell = ImageCell.instantiateFromNib() else { + return ImageCell() + } + + return cell + }() + + @IBOutlet weak var activityIndicator: UIActivityIndicatorView! + + @IBOutlet weak var imageView: FLAnimatedImageView! { + didSet { + imageView.layer.cornerRadius = 3 + imageView.layer.borderColor = UIColor.lightGray.withAlphaComponent(0.1).cgColor + imageView.layer.borderWidth = 1 + } + } + + @IBOutlet weak var buttonImageHandler: UIButton! + @IBOutlet weak var labelTitle: UILabel! + @IBOutlet weak var labelDescription: UILabel! + + override func configure() { + guard let viewModel = viewModel?.base as? ImageMessageChatItem else { + return + } + + labelTitle.text = viewModel.title + labelDescription.text = viewModel.descriptionText + + loadImage(on: imageView, startLoadingBlock: { [weak self] in + self?.activityIndicator.startAnimating() + }, stopLoadingBlock: { [weak self] in + self?.activityIndicator.stopAnimating() + }) + } + + // MARK: IBAction + + @IBAction func buttonImageHandlerDidPressed(_ sender: Any) { + guard + let viewModel = viewModel?.base as? ImageMessageChatItem, + let imageURL = viewModel.imageURL + else { + return + } + + delegate?.openImageFromCell(url: imageURL, thumbnail: imageView) + } +} diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/ImageCell.xib b/Rocket.Chat/Views/Chat/New Chat/Cells/ImageCell.xib new file mode 100644 index 0000000000..44aced2c0f --- /dev/null +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/ImageCell.xib @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.swift b/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.swift index 27b6b49a44..eb2ff65399 100644 --- a/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.swift +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.swift @@ -2,15 +2,15 @@ // ImageMessageCell.swift // Rocket.Chat // -// Created by Rafael Streit on 01/10/18. +// Created by Filipe Alvarenga on 16/10/18. // Copyright © 2018 Rocket.Chat. All rights reserved. // -import Foundation +import UIKit import RocketChatViewController import FLAnimatedImage -final class ImageMessageCell: UICollectionViewCell, ChatCell, SizingCell { +class ImageMessageCell: BaseImageMessageCell, SizingCell { static let identifier = String(describing: ImageMessageCell.self) static let sizingCell: UICollectionViewCell & ChatCell = { @@ -21,8 +21,17 @@ final class ImageMessageCell: UICollectionViewCell, ChatCell, SizingCell { return cell }() - @IBOutlet weak var activityIndicator: UIActivityIndicatorView! + @IBOutlet weak var avatarContainerView: UIView! { + didSet { + avatarContainerView.layer.cornerRadius = 4 + avatarView.frame = avatarContainerView.bounds + avatarContainerView.addSubview(avatarView) + } + } + @IBOutlet weak var username: UILabel! + @IBOutlet weak var date: UILabel! + @IBOutlet weak var activityIndicator: UIActivityIndicatorView! @IBOutlet weak var imageView: FLAnimatedImageView! { didSet { imageView.layer.cornerRadius = 3 @@ -35,29 +44,20 @@ final class ImageMessageCell: UICollectionViewCell, ChatCell, SizingCell { @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelDescription: UILabel! - weak var delegate: ChatMessageCellProtocol? - - var adjustedHorizontalInsets: CGFloat = 0 - var viewModel: AnyChatItem? - - func configure() { + override func configure() { guard let viewModel = viewModel?.base as? ImageMessageChatItem else { return } + configure(with: avatarView, date: date, and: username) labelTitle.text = viewModel.title labelDescription.text = viewModel.descriptionText - if let imageURL = viewModel.imageURL { - activityIndicator.startAnimating() - ImageManager.loadImage(with: imageURL, into: imageView) { [weak self] _, _ in - self?.activityIndicator.stopAnimating() - - // TODO: In case of error, show some error placeholder - } - } else { - // TODO: Load some error placeholder - } + loadImage(on: imageView, startLoadingBlock: { [weak self] in + self?.activityIndicator.startAnimating() + }, stopLoadingBlock: { [weak self] in + self?.activityIndicator.stopAnimating() + }) } // MARK: IBAction diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.xib b/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.xib index b8dae8dffd..863cef3aa6 100644 --- a/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.xib +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.xib @@ -12,77 +12,107 @@ - - + + - + - - + - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - + + + + + + + + - + diff --git a/Rocket.Chat/Views/Chat/New Chat/ChatItems/ImageMessageChatItem.swift b/Rocket.Chat/Views/Chat/New Chat/ChatItems/ImageMessageChatItem.swift index 9b580f34cd..ee64adc3db 100644 --- a/Rocket.Chat/Views/Chat/New Chat/ChatItems/ImageMessageChatItem.swift +++ b/Rocket.Chat/Views/Chat/New Chat/ChatItems/ImageMessageChatItem.swift @@ -12,7 +12,7 @@ import RocketChatViewController struct ImageMessageChatItem: ChatItem, Differentiable { var relatedReuseIdentifier: String { - return ImageMessageCell.identifier + return ImageCell.identifier } var identifier: String From faf9f33e35141278f081054cf52e5654db4fad95 Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 16:34:28 -0300 Subject: [PATCH 10/13] Refactor ImageMessageCellChatItem --- .../Chat/ChatSections/MessageSection.swift | 29 +++++++++++++++---- .../ChatItems/ImageMessageChatItem.swift | 14 +++++++-- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift index efc1fed488..4fde282afc 100644 --- a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift +++ b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift @@ -118,12 +118,29 @@ final class MessageSection: ChatSection { attachment: attachment ).wrapped) case .image: - cells.append(ImageMessageChatItem( - identifier: attachment.identifier, - title: attachment.title, - descriptionText: attachment.descriptionText, - imageURL: attachment.fullImageURL - ).wrapped) + if object.message.text.isEmpty && shouldAppendMessageHeader { + cells.append(ImageMessageChatItem( + identifier: attachment.identifier, + title: attachment.title, + descriptionText: attachment.descriptionText, + imageURL: attachment.fullImageURL, + hasText: false, + user: user, + message: object.message + ).wrapped) + + shouldAppendMessageHeader = false + } else { + cells.append(ImageMessageChatItem( + identifier: attachment.identifier, + title: attachment.title, + descriptionText: attachment.descriptionText, + imageURL: attachment.fullImageURL, + hasText: true, + user: nil, + message: nil + ).wrapped) + } default: if attachment.isFile { if object.message.text.isEmpty && shouldAppendMessageHeader { diff --git a/Rocket.Chat/Views/Chat/New Chat/ChatItems/ImageMessageChatItem.swift b/Rocket.Chat/Views/Chat/New Chat/ChatItems/ImageMessageChatItem.swift index ee64adc3db..f63670daf3 100644 --- a/Rocket.Chat/Views/Chat/New Chat/ChatItems/ImageMessageChatItem.swift +++ b/Rocket.Chat/Views/Chat/New Chat/ChatItems/ImageMessageChatItem.swift @@ -10,15 +10,25 @@ import Foundation import DifferenceKit import RocketChatViewController -struct ImageMessageChatItem: ChatItem, Differentiable { +final class ImageMessageChatItem: MessageHeaderChatItem, ChatItem, Differentiable { var relatedReuseIdentifier: String { - return ImageCell.identifier + return hasText ? ImageCell.identifier : ImageMessageCell.identifier } var identifier: String var title: String? var descriptionText: String? var imageURL: URL? + let hasText: Bool + + init(identifier: String, title: String?, descriptionText: String?, imageURL: URL?, hasText: Bool, user: UnmanagedUser?, message: UnmanagedMessage?) { + self.identifier = identifier + self.title = title + self.descriptionText = descriptionText + self.imageURL = imageURL + self.hasText = hasText + super.init(user: user, avatar: message?.avatar, emoji: message?.emoji, date: message?.createdAt) + } var differenceIdentifier: String { return identifier From c90d8dcb389db9d53d003584d9d493895102f38d Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 16:34:42 -0300 Subject: [PATCH 11/13] Register ImageMessageCell on MessagesViewController --- Rocket.Chat/Controllers/Chat/MessagesViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift index 2da2572fe4..a3707c9493 100644 --- a/Rocket.Chat/Controllers/Chat/MessagesViewController.swift +++ b/Rocket.Chat/Controllers/Chat/MessagesViewController.swift @@ -64,6 +64,7 @@ final class MessagesViewController: RocketChatViewController { collectionView.register(TextAttachmentCell.nib, forCellWithReuseIdentifier: TextAttachmentCell.identifier) collectionView.register(TextAttachmentMessageCell.nib, forCellWithReuseIdentifier: TextAttachmentMessageCell.identifier) collectionView.register(ImageCell.nib, forCellWithReuseIdentifier: ImageCell.identifier) + collectionView.register(ImageMessageCell.nib, forCellWithReuseIdentifier: ImageMessageCell.identifier) collectionView.register(QuoteCell.nib, forCellWithReuseIdentifier: QuoteCell.identifier) collectionView.register(MessageURLCell.nib, forCellWithReuseIdentifier: MessageURLCell.identifier) From c3d8984497d3e40df4ebfa9b4f2f2b4983d7c64e Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 16:36:20 -0300 Subject: [PATCH 12/13] Add delegate to the cells with message headers --- .../Controllers/Chat/ChatSections/MessageSection.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift index 4fde282afc..a9ee7dc41a 100644 --- a/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift +++ b/Rocket.Chat/Controllers/Chat/ChatSections/MessageSection.swift @@ -203,10 +203,16 @@ final class MessageSection: ChatSection { cell.delegate = self } else if let cell = cell as? FileCell { cell.delegate = self + } else if let cell = cell as? FileMessageCell { + cell.delegate = self + } else if let cell = cell as? ImageMessageCell { + cell.delegate = self } else if let cell = cell as? ImageCell { cell.delegate = self } else if let cell = cell as? TextAttachmentCell { cell.delegate = self + } else if let cell = cell as? TextAttachmentMessageCell { + cell.delegate = self } else if let cell = cell as? QuoteCell { cell.delegate = self } else if let cell = cell as? MessageURLCell { From ee8165679eb8da1398fc67d05e6c595d8ac0d596 Mon Sep 17 00:00:00 2001 From: filipealva Date: Tue, 16 Oct 2018 16:40:48 -0300 Subject: [PATCH 13/13] Connect missing IBOutlet --- Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.xib | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.xib b/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.xib index 863cef3aa6..37bc34cbb2 100644 --- a/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.xib +++ b/Rocket.Chat/Views/Chat/New Chat/Cells/ImageMessageCell.xib @@ -70,6 +70,9 @@