Rename BaseBubbleCell folder to BaseRoomCell.

This commit is contained in:
SBiOSoftWhare
2022-02-16 09:56:13 +01:00
parent 0ea89fd835
commit e02f6a3b59
9 changed files with 0 additions and 0 deletions
@@ -0,0 +1,337 @@
/*
Copyright 2020 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import UIKit
@objc protocol BaseBubbleCellType: Themable {
var bubbleCellContentView: BubbleCellContentView? { get }
}
/// `BaseBubbleCell` allows a bubble cell that inherits from this class to embed and manage the default room message outer views and add an inner content view.
@objcMembers
class BaseBubbleCell: MXKRoomBubbleTableViewCell, BaseBubbleCellType {
// MARK: - Constants
// MARK: - Properties
private var areViewsSetup: Bool = false
// MARK: Public
weak var bubbleCellContentView: BubbleCellContentView?
private(set) var theme: Theme?
// Overrides
override var bubbleInfoContainer: UIView! {
get {
guard let infoContainer = self.bubbleCellContentView?.bubbleInfoContainer else {
fatalError("[BaseBubbleCell] bubbleInfoContainer should not be used before set")
}
return infoContainer
}
set {
super.bubbleInfoContainer = newValue
}
}
override var bubbleOverlayContainer: UIView! {
get {
guard let overlayContainer = self.bubbleCellContentView?.bubbleOverlayContainer else {
fatalError("[BaseBubbleCell] bubbleOverlayContainer should not be used before set")
}
return overlayContainer
}
set {
super.bubbleInfoContainer = newValue
}
}
override var bubbleInfoContainerTopConstraint: NSLayoutConstraint! {
get {
guard let infoContainerTopConstraint = self.bubbleCellContentView?.bubbleInfoContainerTopConstraint else {
fatalError("[BaseBubbleCell] bubbleInfoContainerTopConstraint should not be used before set")
}
return infoContainerTopConstraint
}
set {
super.bubbleInfoContainerTopConstraint = newValue
}
}
override var pictureView: MXKImageView! {
get {
guard let bubbleCellContentView = self.bubbleCellContentView,
bubbleCellContentView.showSenderAvatar else {
return nil
}
guard let pictureView = self.bubbleCellContentView?.avatarImageView else {
fatalError("[BaseBubbleCell] pictureView should not be used before set")
}
return pictureView
}
set {
super.pictureView = newValue
}
}
override var userNameLabel: UILabel! {
get {
guard let bubbleCellContentView = self.bubbleCellContentView, bubbleCellContentView.showSenderName else {
return nil
}
guard let userNameLabel = bubbleCellContentView.userNameLabel else {
fatalError("[BaseBubbleCell] userNameLabel should not be used before set")
}
return userNameLabel
}
set {
super.userNameLabel = newValue
}
}
override var userNameTapGestureMaskView: UIView! {
get {
guard let bubbleCellContentView = self.bubbleCellContentView,
bubbleCellContentView.showSenderName else {
return nil
}
guard let userNameTapGestureMaskView = self.bubbleCellContentView?.userNameTouchMaskView else {
fatalError("[BaseBubbleCell] userNameTapGestureMaskView should not be used before set")
}
return userNameTapGestureMaskView
}
set {
super.userNameTapGestureMaskView = newValue
}
}
// MARK: - Setup
required override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
private func commonInit() {
self.selectionStyle = .none
self.setupContentView()
self.update(theme: ThemeService.shared().theme)
}
// MARK: - Public
func removeDecorationViews() {
if let bubbleCellReadReceiptsDisplayable = self as? BubbleCellReadReceiptsDisplayable {
bubbleCellReadReceiptsDisplayable.removeReadReceiptsView()
}
if let bubbleCellReactionsDisplayable = self as? BubbleCellReactionsDisplayable {
bubbleCellReactionsDisplayable.removeReactionsView()
}
if let bubbleCellThreadSummaryDisplayable = self as? BubbleCellThreadSummaryDisplayable {
bubbleCellThreadSummaryDisplayable.removeThreadSummaryView()
}
if let timestampDisplayable = self as? TimestampDisplayable {
timestampDisplayable.removeTimestampView()
}
if let urlPreviewDisplayable = self as? RoomCellURLPreviewDisplayable {
urlPreviewDisplayable.removeURLPreviewView()
}
}
// MARK: - Overrides
override var isTextViewNeedsPositioningVerticalSpace: Bool {
return false
}
override func setupViews() {
super.setupViews()
let showEncryptionStatus = bubbleCellContentView?.showEncryptionStatus ?? false
if showEncryptionStatus {
self.setupEncryptionStatusViewTapGestureRecognizer()
}
}
override class func defaultReuseIdentifier() -> String! {
return String(describing: self)
}
override func prepareForReuse() {
super.prepareForReuse()
self.removeDecorationViews()
}
override func render(_ cellData: MXKCellData!) {
// In `MXKRoomBubbleTableViewCell` setupViews() is called in awakeFromNib() that is not called here, so call it only on first render() call
self.setupViewsIfNeeded()
super.render(cellData)
guard let bubbleCellContentView = self.bubbleCellContentView else {
return
}
if let bubbleData = self.bubbleData,
let paginationDate = bubbleData.date,
bubbleCellContentView.showPaginationTitle {
bubbleCellContentView.paginationLabel.text = bubbleData.eventFormatter.dateString(from: paginationDate, withTime: false)?.uppercased()
}
if bubbleCellContentView.showEncryptionStatus {
self.updateEncryptionStatusViewImage()
}
self.updateUserNameColor()
}
override func customizeRendering() {
super.customizeRendering()
self.updateUserNameColor()
}
// MARK: - Themable
func update(theme: Theme) {
self.theme = theme
self.bubbleCellContentView?.update(theme: theme)
}
// MARK: - Private
private func setupViewsIfNeeded() {
guard self.areViewsSetup == false else {
return
}
self.setupViews()
self.areViewsSetup = true
}
private func setupContentView() {
guard self.bubbleCellContentView == nil else {
return
}
let bubbleCellContentView = BubbleCellContentView.instantiate()
self.contentView.vc_addSubViewMatchingParent(bubbleCellContentView)
self.bubbleCellContentView = bubbleCellContentView
}
// MARK: - RoomCellURLPreviewDisplayable
// Cannot use default implementation with ObjC protocol, if self conforms to BubbleCellReadReceiptsDisplayable method below will be used
func addURLPreviewView(_ urlPreviewView: UIView) {
self.bubbleCellContentView?.addURLPreviewView(urlPreviewView)
// tmpSubviews is used for touch detection in MXKRoomBubbleTableViewCell
self.addTemporarySubview(urlPreviewView)
}
func removeURLPreviewView() {
self.bubbleCellContentView?.removeURLPreviewView()
}
// MARK: - BubbleCellReadReceiptsDisplayable
// Cannot use default implementation with ObjC protocol, if self conforms to BubbleCellReadReceiptsDisplayable method below will be used
func addReadReceiptsView(_ readReceiptsView: UIView) {
self.bubbleCellContentView?.addReadReceiptsView(readReceiptsView)
// tmpSubviews is used for touch detection in MXKRoomBubbleTableViewCell
self.addTemporarySubview(readReceiptsView)
}
func removeReadReceiptsView() {
self.bubbleCellContentView?.removeReadReceiptsView()
}
// MARK: - BubbleCellReactionsDisplayable
// Cannot use default implementation with ObjC protocol, if self conforms to BubbleCellReactionsDisplayable method below will be used
func addReactionsView(_ reactionsView: UIView) {
self.bubbleCellContentView?.addReactionsView(reactionsView)
// tmpSubviews is used for touch detection in MXKRoomBubbleTableViewCell
self.addTemporarySubview(reactionsView)
}
func removeReactionsView() {
self.bubbleCellContentView?.removeReactionsView()
}
// MARK: - BubbleCellThreadSummaryDisplayable
func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView) {
self.bubbleCellContentView?.addThreadSummaryView(threadSummaryView)
// tmpSubviews is used for touch detection in MXKRoomBubbleTableViewCell
self.addTemporarySubview(threadSummaryView)
}
func removeThreadSummaryView() {
self.bubbleCellContentView?.removeThreadSummaryView()
}
// Encryption status
private func updateEncryptionStatusViewImage() {
guard let component = self.bubbleData.getFirstBubbleComponentWithDisplay() else {
return
}
self.bubbleCellContentView?.encryptionImageView.image = RoomEncryptedDataBubbleCell.encryptionIcon(for: component)
}
private func setupEncryptionStatusViewTapGestureRecognizer() {
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleEncryptionStatusContainerViewTap(_:)))
tapGestureRecognizer.delegate = self
self.bubbleCellContentView?.encryptionImageView.isUserInteractionEnabled = true
}
@objc private func handleEncryptionStatusContainerViewTap(_ gestureRecognizer: UITapGestureRecognizer) {
guard let delegate = self.delegate else {
return
}
guard let component = self.bubbleData.getFirstBubbleComponentWithDisplay() else {
return
}
let userInfo: [AnyHashable: Any]?
if let tappedEvent = component.event {
userInfo = [kMXKRoomBubbleCellEventKey: tappedEvent]
} else {
userInfo = nil
}
delegate.cell(self, didRecognizeAction: kRoomEncryptedDataBubbleCellTapOnEncryptionIcon, userInfo: userInfo)
}
}
@@ -0,0 +1,306 @@
/*
Copyright 2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import UIKit
import Reusable
/// `BubbleCellContentView` is a container view that display the default room message outer views and enables to manage them. Like pagination title, sender info, read receipts, reactions, encryption status.
@objcMembers
final class BubbleCellContentView: UIView, NibLoadable {
// MARK: - Properties
// MARK: Outlets
@IBOutlet weak var paginationTitleContainerView: UIView!
@IBOutlet weak var paginationLabel: UILabel!
@IBOutlet weak var paginationSeparatorView: UIView!
@IBOutlet weak var userNameContainerView: UIView!
@IBOutlet weak var userNameLabel: UILabel!
@IBOutlet weak var userNameTouchMaskView: UIView!
@IBOutlet weak var avatarContainerView: UIView!
@IBOutlet weak var avatarImageView: MXKImageView!
@IBOutlet weak var innerContentView: UIView!
@IBOutlet weak var innerContentViewLeadingConstraint: NSLayoutConstraint!
@IBOutlet weak var innerContentViewTrailingConstraint: NSLayoutConstraint!
@IBOutlet weak var innerContentViewBottomContraint: NSLayoutConstraint!
@IBOutlet weak var encryptionStatusContainerView: UIView!
@IBOutlet weak var encryptionImageView: UIImageView!
@IBOutlet weak var bubbleInfoContainer: UIView!
@IBOutlet weak var bubbleInfoContainerTopConstraint: NSLayoutConstraint!
@IBOutlet weak var urlPreviewContainerView: UIView!
@IBOutlet weak var urlPreviewContentView: UIView!
@IBOutlet weak var urlPreviewContentViewLeadingConstraint: NSLayoutConstraint!
@IBOutlet weak var urlPreviewContentViewTrailingConstraint: NSLayoutConstraint!
@IBOutlet weak var readReceiptsContainerView: UIView!
@IBOutlet weak var readReceiptsContentView: UIView!
@IBOutlet weak var reactionsContainerView: UIView!
@IBOutlet weak var reactionsContentView: UIView!
@IBOutlet weak var reactionsContentViewLeadingConstraint: NSLayoutConstraint!
@IBOutlet weak var reactionsContentViewTrailingConstraint: NSLayoutConstraint!
@IBOutlet weak var threadSummaryContainerView: UIView!
@IBOutlet weak var threadSummaryContentView: UIView!
@IBOutlet weak var threadSummaryContentViewLeadingConstraint: NSLayoutConstraint!
@IBOutlet weak var threadSummaryContentViewTrailingConstraint: NSLayoutConstraint!
@IBOutlet weak var threadSummaryContentViewBottomConstraint: NSLayoutConstraint!
@IBOutlet weak var bubbleOverlayContainer: UIView!
// MARK: Private
private var showURLPreview: Bool {
get {
return !self.urlPreviewContainerView.isHidden
}
set {
self.urlPreviewContainerView.isHidden = !newValue
}
}
private var showReadReceipts: Bool {
get {
return !self.readReceiptsContainerView.isHidden
}
set {
self.readReceiptsContainerView.isHidden = !newValue
}
}
private var showReactions: Bool {
get {
return !self.reactionsContainerView.isHidden
}
set {
self.reactionsContainerView.isHidden = !newValue
}
}
private var showThreadSummary: Bool {
get {
return !self.threadSummaryContainerView.isHidden
} set {
self.threadSummaryContainerView.isHidden = !newValue
}
}
// MARK: Public
var showPaginationTitle: Bool {
get {
return !self.paginationTitleContainerView.isHidden
}
set {
self.paginationTitleContainerView.isHidden = !newValue
}
}
var showSenderInfo: Bool {
get {
return self.showSenderAvatar && self.showSenderName
}
set {
self.showSenderAvatar = newValue
self.showSenderName = newValue
}
}
var showSenderAvatar: Bool {
get {
return !self.avatarContainerView.isHidden
}
set {
self.avatarContainerView.isHidden = !newValue
}
}
var showSenderName: Bool {
get {
return !self.userNameContainerView.isHidden
}
set {
self.userNameContainerView.isHidden = !newValue
}
}
var showEncryptionStatus: Bool {
get {
return !self.encryptionStatusContainerView.isHidden
}
set {
self.encryptionStatusContainerView.isHidden = !newValue
}
}
var decorationViewsAlignment: RoomCellDecorationAlignment = .left
// MARK: - Setup
class func instantiate() -> BubbleCellContentView {
return BubbleCellContentView.loadFromNib()
}
// MARK: - Public
func update(theme: Theme) {
self.backgroundColor = theme.backgroundColor
self.paginationLabel.textColor = theme.tintColor
self.paginationSeparatorView.backgroundColor = theme.tintColor
}
}
// MARK: - BubbleCellReadReceiptsDisplayable
extension BubbleCellContentView: BubbleCellReadReceiptsDisplayable {
func addReadReceiptsView(_ readReceiptsView: UIView) {
self.readReceiptsContentView.vc_removeAllSubviews()
self.readReceiptsContentView.vc_addSubViewMatchingParent(readReceiptsView)
self.showReadReceipts = true
}
func removeReadReceiptsView() {
self.showReadReceipts = false
self.readReceiptsContentView.vc_removeAllSubviews()
}
}
// MARK: - BubbleCellReactionsDisplayable
extension BubbleCellContentView: BubbleCellReactionsDisplayable {
func addReactionsView(_ reactionsView: UIView) {
self.reactionsContentView.vc_removeAllSubviews()
// Update reactions alignment according to current decoration alignment
if let bubbleReactionsView = reactionsView as? BubbleReactionsView {
let reactionsAlignment: BubbleReactionsViewAlignment
switch self.decorationViewsAlignment {
case .left:
reactionsAlignment = .left
case .right:
reactionsAlignment = .right
}
bubbleReactionsView.alignment = reactionsAlignment
}
self.reactionsContentView.vc_addSubViewMatchingParent(reactionsView)
self.showReactions = true
}
func removeReactionsView() {
self.showReactions = false
self.reactionsContentView.vc_removeAllSubviews()
}
}
// MARK: - BubbleCellThreadSummaryDisplayable
extension BubbleCellContentView: BubbleCellThreadSummaryDisplayable {
func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView) {
guard let containerView = self.threadSummaryContentView else {
return
}
containerView.vc_removeAllSubviews()
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.addSubview(threadSummaryView)
let leadingConstraint: NSLayoutConstraint
let trailingConstraint: NSLayoutConstraint
if self.decorationViewsAlignment == .right {
leadingConstraint = threadSummaryView.leadingAnchor.constraint(greaterThanOrEqualTo: containerView.leadingAnchor)
trailingConstraint = threadSummaryView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor)
} else {
leadingConstraint = threadSummaryView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor)
trailingConstraint = threadSummaryView.trailingAnchor.constraint(lessThanOrEqualTo: containerView.trailingAnchor)
}
NSLayoutConstraint.activate([
leadingConstraint,
threadSummaryView.topAnchor.constraint(equalTo: containerView.topAnchor),
threadSummaryView.heightAnchor.constraint(equalToConstant: RoomBubbleCellLayout.threadSummaryViewHeight),
threadSummaryView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
trailingConstraint
])
self.showThreadSummary = true
}
func removeThreadSummaryView() {
self.showThreadSummary = false
self.threadSummaryContentView.vc_removeAllSubviews()
}
}
// MARK: - RoomCellURLPreviewDisplayable
extension BubbleCellContentView: RoomCellURLPreviewDisplayable {
func addURLPreviewView(_ urlPreviewView: UIView) {
guard let containerView = self.urlPreviewContentView else {
return
}
containerView.vc_removeAllSubviews()
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.addSubview(urlPreviewView)
if let urlPreviewView = urlPreviewView as? URLPreviewView {
urlPreviewView.availableWidth = containerView.frame.width
}
let leadingConstraint: NSLayoutConstraint
let trailingConstraint: NSLayoutConstraint
if self.decorationViewsAlignment == .right {
leadingConstraint = urlPreviewView.leadingAnchor.constraint(greaterThanOrEqualTo: containerView.leadingAnchor)
trailingConstraint = urlPreviewView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor)
} else {
leadingConstraint = urlPreviewView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor)
trailingConstraint = urlPreviewView.trailingAnchor.constraint(lessThanOrEqualTo: containerView.trailingAnchor)
}
NSLayoutConstraint.activate([
leadingConstraint,
urlPreviewView.topAnchor.constraint(equalTo: containerView.topAnchor),
urlPreviewView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
trailingConstraint
])
self.showURLPreview = true
}
func removeURLPreviewView() {
self.showURLPreview = false
self.urlPreviewContentView.vc_removeAllSubviews()
}
}
@@ -0,0 +1,317 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="zG5-YA-Ijy" customClass="BubbleCellContentView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="595" height="97"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XQw-Mj-NZY">
<rect key="frame" x="0.0" y="0.0" width="595" height="97"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="5GX-gn-bK1">
<rect key="frame" x="0.0" y="0.0" width="595" height="97"/>
<subviews>
<view hidden="YES" contentMode="scaleToFill" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="u1e-Q2-PhY">
<rect key="frame" x="0.0" y="0.0" width="595" height="44"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ro1-vP-6Ha" userLabel="Pagination Title View">
<rect key="frame" x="56" y="10" width="529" height="24"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="r7y-FK-GWS" userLabel="Pagination Label">
<rect key="frame" x="0.0" y="0.0" width="519" height="18"/>
<constraints>
<constraint firstAttribute="height" constant="18" id="uCj-An-Yc2"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<color key="textColor" red="0.66666666669999997" green="0.66666666669999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ytv-tA-NmI" userLabel="Pagination Separator View">
<rect key="frame" x="0.0" y="23" width="529" height="1"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<accessibility key="accessibilityConfiguration" identifier="PaginationTitleView"/>
<constraints>
<constraint firstAttribute="height" constant="24" id="5bk-I2-Cw6"/>
<constraint firstAttribute="bottom" secondItem="ytv-tA-NmI" secondAttribute="bottom" id="5oD-hl-YNI"/>
<constraint firstAttribute="trailing" secondItem="ytv-tA-NmI" secondAttribute="trailing" id="Cfu-Jn-urV"/>
<constraint firstItem="r7y-FK-GWS" firstAttribute="leading" secondItem="Ro1-vP-6Ha" secondAttribute="leading" id="Fpo-9J-9Ci"/>
<constraint firstItem="r7y-FK-GWS" firstAttribute="top" secondItem="Ro1-vP-6Ha" secondAttribute="top" id="Rpc-oi-muy"/>
<constraint firstItem="ytv-tA-NmI" firstAttribute="top" secondItem="r7y-FK-GWS" secondAttribute="bottom" constant="5" id="lam-eF-rEV"/>
<constraint firstItem="ytv-tA-NmI" firstAttribute="leading" secondItem="Ro1-vP-6Ha" secondAttribute="leading" id="oBH-4x-jgt"/>
<constraint firstAttribute="trailing" secondItem="r7y-FK-GWS" secondAttribute="trailing" constant="10" id="r4y-XW-aAD"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="Ro1-vP-6Ha" firstAttribute="top" secondItem="u1e-Q2-PhY" secondAttribute="top" constant="10" id="5kZ-rt-pvq"/>
<constraint firstAttribute="trailing" secondItem="Ro1-vP-6Ha" secondAttribute="trailing" constant="10" id="8P7-ZL-7pg"/>
<constraint firstItem="Ro1-vP-6Ha" firstAttribute="leading" secondItem="u1e-Q2-PhY" secondAttribute="leading" constant="56" id="A4v-WV-EGn"/>
<constraint firstAttribute="bottom" secondItem="Ro1-vP-6Ha" secondAttribute="bottom" constant="10" id="UcW-P4-rQv"/>
</constraints>
</view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1cK-e6-Mg5">
<rect key="frame" x="0.0" y="0.0" width="595" height="0.0"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="yXz-Za-4yR" customClass="MXKImageView">
<rect key="frame" x="13" y="10" width="30" height="30"/>
<color key="backgroundColor" red="0.66666666669999997" green="0.66666666669999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="PictureView"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="FbD-UB-dqc"/>
<constraint firstAttribute="width" constant="30" id="y7F-jl-kEF"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="yXz-Za-4yR" firstAttribute="leading" secondItem="1cK-e6-Mg5" secondAttribute="leading" constant="13" id="UjU-eY-ARJ"/>
<constraint firstItem="yXz-Za-4yR" firstAttribute="top" secondItem="1cK-e6-Mg5" secondAttribute="top" constant="10" id="jlf-dg-fp0"/>
</constraints>
</view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="w0C-6a-f5M">
<rect key="frame" x="0.0" y="0.0" width="595" height="31"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ohU-Sc-mgb">
<rect key="frame" x="46" y="4" width="534" height="30"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="User name:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="8" translatesAutoresizingMaskIntoConstraints="NO" id="meG-P8-61b">
<rect key="frame" x="56" y="10" width="524" height="18"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="UserNameLabel"/>
<constraints>
<constraint firstAttribute="height" constant="18" placeholder="YES" id="Jma-ST-usg"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<color key="textColor" red="0.33333333329999998" green="0.33333333329999998" blue="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="meG-P8-61b" secondAttribute="bottom" constant="3" id="HDT-eS-UWo"/>
<constraint firstItem="ohU-Sc-mgb" firstAttribute="trailing" secondItem="meG-P8-61b" secondAttribute="trailing" id="Lbz-vD-hax"/>
<constraint firstItem="ohU-Sc-mgb" firstAttribute="bottom" secondItem="meG-P8-61b" secondAttribute="bottom" constant="6" id="U50-ZB-dRG"/>
<constraint firstItem="meG-P8-61b" firstAttribute="top" secondItem="w0C-6a-f5M" secondAttribute="top" constant="10" id="baE-tR-0Ck"/>
<constraint firstItem="ohU-Sc-mgb" firstAttribute="leading" secondItem="meG-P8-61b" secondAttribute="leading" constant="-10" id="ktD-JC-hfG"/>
<constraint firstItem="ohU-Sc-mgb" firstAttribute="top" secondItem="meG-P8-61b" secondAttribute="top" constant="-6" id="s5V-Fj-iNL"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vcq-cR-uBc">
<rect key="frame" x="0.0" y="0.0" width="595" height="97"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4d4-XQ-ido">
<rect key="frame" x="0.0" y="0.0" width="0.0" height="97"/>
<subviews>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uHE-o7-sCe">
<rect key="frame" x="0.0" y="16" width="16" height="97"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="encryption_warning" translatesAutoresizingMaskIntoConstraints="NO" id="Ujc-3c-e5B">
<rect key="frame" x="0.0" y="3" width="16" height="16"/>
<constraints>
<constraint firstAttribute="height" constant="16" id="8ck-Jh-jur"/>
<constraint firstAttribute="width" constant="16" id="bGQ-Ha-arJ"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="Ujc-3c-e5B" firstAttribute="top" secondItem="uHE-o7-sCe" secondAttribute="top" constant="3" id="d8G-zC-zPx"/>
<constraint firstAttribute="width" constant="16" id="uSI-O4-RCY"/>
<constraint firstItem="Ujc-3c-e5B" firstAttribute="centerX" secondItem="uHE-o7-sCe" secondAttribute="centerX" id="z4k-EX-K17"/>
</constraints>
</view>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7Y6-Py-paB">
<rect key="frame" x="0.0" y="16" width="50" height="97"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="BubbleInfoContainer"/>
<constraints>
<constraint firstAttribute="width" constant="50" id="LtA-zk-OCc"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="uHE-o7-sCe" firstAttribute="height" secondItem="4d4-XQ-ido" secondAttribute="height" id="DhB-EC-rCE"/>
<constraint firstItem="7Y6-Py-paB" firstAttribute="top" secondItem="4d4-XQ-ido" secondAttribute="top" constant="16" id="Wx9-0o-vzm"/>
</constraints>
</stackView>
<view clipsSubviews="YES" contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="oeI-eO-mFK">
<rect key="frame" x="56" y="3" width="524" height="78"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="oeI-eO-mFK" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="vcq-cR-uBc" secondAttribute="leading" constant="56" id="0Fr-0L-9tU"/>
<constraint firstAttribute="bottom" secondItem="oeI-eO-mFK" secondAttribute="bottom" constant="16" id="8M5-uW-82s"/>
<constraint firstItem="oeI-eO-mFK" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="4d4-XQ-ido" secondAttribute="trailing" constant="6" id="9By-U1-wTY"/>
<constraint firstAttribute="trailing" secondItem="oeI-eO-mFK" secondAttribute="trailing" constant="15" id="Pbe-4d-q6Y"/>
<constraint firstAttribute="bottom" secondItem="4d4-XQ-ido" secondAttribute="bottom" id="Tkw-p1-CYF"/>
<constraint firstItem="4d4-XQ-ido" firstAttribute="leading" secondItem="vcq-cR-uBc" secondAttribute="leading" id="cbh-iX-gKz"/>
<constraint firstItem="4d4-XQ-ido" firstAttribute="top" secondItem="vcq-cR-uBc" secondAttribute="top" id="hOM-gq-1au"/>
<constraint firstAttribute="height" priority="250" id="lRu-Kd-3JZ"/>
<constraint firstItem="oeI-eO-mFK" firstAttribute="top" secondItem="vcq-cR-uBc" secondAttribute="top" constant="3" id="uZZ-I6-Xtq"/>
<constraint firstItem="oeI-eO-mFK" firstAttribute="leading" secondItem="vcq-cR-uBc" secondAttribute="leading" priority="750" id="vsh-pW-S46"/>
</constraints>
</view>
<view hidden="YES" clipsSubviews="YES" contentMode="scaleAspectFit" verticalHuggingPriority="254" translatesAutoresizingMaskIntoConstraints="NO" id="57V-Sl-EmD">
<rect key="frame" x="0.0" y="0.0" width="595" height="0.0"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="vpX-Nl-AEt">
<rect key="frame" x="56" y="0.0" width="524" height="0.0"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" priority="250" placeholder="YES" id="0Sv-R6-k3e"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="vpX-Nl-AEt" secondAttribute="trailing" constant="15" id="ZmA-Ns-chh"/>
<constraint firstAttribute="bottom" secondItem="vpX-Nl-AEt" secondAttribute="bottom" id="blD-s1-b1N"/>
<constraint firstItem="vpX-Nl-AEt" firstAttribute="top" secondItem="57V-Sl-EmD" secondAttribute="top" id="sFV-XK-lE4"/>
</constraints>
</view>
<view hidden="YES" clipsSubviews="YES" contentMode="scaleAspectFit" verticalHuggingPriority="252" translatesAutoresizingMaskIntoConstraints="NO" id="Dj1-m6-1Jw">
<rect key="frame" x="0.0" y="0.0" width="595" height="0.0"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="SNw-aM-ILI">
<rect key="frame" x="56" y="0.0" width="524" height="0.0"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" priority="250" placeholder="YES" id="kBO-PM-cjY"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="SNw-aM-ILI" firstAttribute="top" secondItem="Dj1-m6-1Jw" secondAttribute="top" id="1PE-go-s7Z"/>
<constraint firstAttribute="bottom" secondItem="SNw-aM-ILI" secondAttribute="bottom" id="SBT-1C-CPb"/>
<constraint firstAttribute="trailing" secondItem="SNw-aM-ILI" secondAttribute="trailing" constant="15" id="ynR-d4-6cf"/>
</constraints>
</view>
<view hidden="YES" contentMode="scaleToFill" verticalHuggingPriority="253" translatesAutoresizingMaskIntoConstraints="NO" id="4zo-V8-CNe">
<rect key="frame" x="0.0" y="0.0" width="595" height="16"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rQt-NH-Cb0">
<rect key="frame" x="439" y="0.0" width="150" height="16"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="16" id="WZx-xk-gav"/>
<constraint firstAttribute="width" constant="150" id="fsY-DK-hUg"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="rQt-NH-Cb0" secondAttribute="bottom" id="6yV-vn-doj"/>
<constraint firstItem="rQt-NH-Cb0" firstAttribute="top" secondItem="4zo-V8-CNe" secondAttribute="top" id="DNc-jy-Urh"/>
<constraint firstAttribute="trailing" secondItem="rQt-NH-Cb0" secondAttribute="trailing" constant="6" id="lq2-AY-Lus"/>
</constraints>
</view>
<view hidden="YES" clipsSubviews="YES" contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="2eB-kB-m20">
<rect key="frame" x="0.0" y="0.0" width="595" height="0.0"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="snf-Ea-To0">
<rect key="frame" x="56" y="0.0" width="524" height="0.0"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" priority="250" placeholder="YES" id="ymW-ys-P0T"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="snf-Ea-To0" secondAttribute="bottom" id="4tt-w0-4JE"/>
<constraint firstItem="snf-Ea-To0" firstAttribute="top" secondItem="2eB-kB-m20" secondAttribute="top" id="Im9-Z0-ieI"/>
<constraint firstAttribute="trailing" secondItem="snf-Ea-To0" secondAttribute="trailing" constant="15" id="Qwm-Of-Zgc"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="Dj1-m6-1Jw" firstAttribute="width" secondItem="5GX-gn-bK1" secondAttribute="width" id="0Px-jL-CMJ"/>
<constraint firstItem="1cK-e6-Mg5" firstAttribute="width" secondItem="5GX-gn-bK1" secondAttribute="width" id="2De-xT-k5e"/>
<constraint firstItem="meG-P8-61b" firstAttribute="trailing" secondItem="oeI-eO-mFK" secondAttribute="trailing" id="2Dy-o0-r33"/>
<constraint firstItem="snf-Ea-To0" firstAttribute="leading" secondItem="oeI-eO-mFK" secondAttribute="leading" id="2lm-T3-dEu"/>
<constraint firstItem="w0C-6a-f5M" firstAttribute="width" secondItem="5GX-gn-bK1" secondAttribute="width" id="5nl-Le-VDi"/>
<constraint firstItem="u1e-Q2-PhY" firstAttribute="width" secondItem="5GX-gn-bK1" secondAttribute="width" id="KrJ-dm-TaV"/>
<constraint firstItem="57V-Sl-EmD" firstAttribute="width" secondItem="5GX-gn-bK1" secondAttribute="width" id="a2p-Bn-M5e"/>
<constraint firstItem="4zo-V8-CNe" firstAttribute="width" secondItem="5GX-gn-bK1" secondAttribute="width" id="bdq-sQ-NQy"/>
<constraint firstItem="vpX-Nl-AEt" firstAttribute="leading" secondItem="oeI-eO-mFK" secondAttribute="leading" id="lTt-Qx-fuQ"/>
<constraint firstItem="meG-P8-61b" firstAttribute="leading" secondItem="oeI-eO-mFK" secondAttribute="leading" id="lq1-xP-tea"/>
<constraint firstItem="SNw-aM-ILI" firstAttribute="leading" secondItem="oeI-eO-mFK" secondAttribute="leading" id="x1n-oT-dez"/>
</constraints>
</stackView>
</subviews>
<color key="backgroundColor" red="0.95294117649999999" green="0.97254901959999995" blue="0.99215686270000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="5GX-gn-bK1" firstAttribute="leading" secondItem="zG5-YA-Ijy" secondAttribute="leading" id="36u-ut-l3G"/>
<constraint firstItem="5GX-gn-bK1" firstAttribute="top" secondItem="zG5-YA-Ijy" secondAttribute="top" id="As1-dI-9ba"/>
<constraint firstItem="XQw-Mj-NZY" firstAttribute="top" secondItem="zG5-YA-Ijy" secondAttribute="top" id="BuL-ri-8kT"/>
<constraint firstAttribute="bottom" secondItem="5GX-gn-bK1" secondAttribute="bottom" id="cNV-Or-YPg"/>
<constraint firstAttribute="trailing" secondItem="5GX-gn-bK1" secondAttribute="trailing" id="deR-Cu-Brh"/>
<constraint firstAttribute="trailing" secondItem="XQw-Mj-NZY" secondAttribute="trailing" id="eJl-Fg-neU"/>
<constraint firstAttribute="bottom" secondItem="XQw-Mj-NZY" secondAttribute="bottom" id="kPs-G8-HdC"/>
<constraint firstItem="XQw-Mj-NZY" firstAttribute="leading" secondItem="zG5-YA-Ijy" secondAttribute="leading" id="w8M-8g-ZQD"/>
</constraints>
<nil key="simulatedTopBarMetrics"/>
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="avatarContainerView" destination="1cK-e6-Mg5" id="8j5-Km-Jfj"/>
<outlet property="avatarImageView" destination="yXz-Za-4yR" id="f56-93-gxa"/>
<outlet property="bubbleInfoContainer" destination="7Y6-Py-paB" id="uLv-MM-HIL"/>
<outlet property="bubbleInfoContainerTopConstraint" destination="Wx9-0o-vzm" id="nLG-nC-lwV"/>
<outlet property="bubbleOverlayContainer" destination="XQw-Mj-NZY" id="6d1-EN-LPY"/>
<outlet property="encryptionImageView" destination="Ujc-3c-e5B" id="7zc-Y7-1jT"/>
<outlet property="encryptionStatusContainerView" destination="uHE-o7-sCe" id="Dl7-QS-WKl"/>
<outlet property="innerContentView" destination="oeI-eO-mFK" id="ap1-He-C6g"/>
<outlet property="innerContentViewBottomContraint" destination="8M5-uW-82s" id="Vn0-6C-LSW"/>
<outlet property="innerContentViewLeadingConstraint" destination="0Fr-0L-9tU" id="ByY-oe-d8Y"/>
<outlet property="innerContentViewTrailingConstraint" destination="Pbe-4d-q6Y" id="24b-AS-hX4"/>
<outlet property="paginationLabel" destination="r7y-FK-GWS" id="R9V-ix-mDu"/>
<outlet property="paginationSeparatorView" destination="ytv-tA-NmI" id="sgk-n1-KQi"/>
<outlet property="paginationTitleContainerView" destination="u1e-Q2-PhY" id="Osl-dF-fpA"/>
<outlet property="reactionsContainerView" destination="Dj1-m6-1Jw" id="p5e-n1-Wca"/>
<outlet property="reactionsContentView" destination="SNw-aM-ILI" id="wMe-f0-qhq"/>
<outlet property="reactionsContentViewLeadingConstraint" destination="x1n-oT-dez" id="LUh-3Q-SVr"/>
<outlet property="reactionsContentViewTrailingConstraint" destination="ynR-d4-6cf" id="Sy0-o9-vAC"/>
<outlet property="readReceiptsContainerView" destination="4zo-V8-CNe" id="7ek-u4-CX8"/>
<outlet property="readReceiptsContentView" destination="rQt-NH-Cb0" id="tqw-je-kp9"/>
<outlet property="threadSummaryContainerView" destination="2eB-kB-m20" id="0Y4-4E-I9K"/>
<outlet property="threadSummaryContentView" destination="snf-Ea-To0" id="6Oo-Gj-e4Z"/>
<outlet property="threadSummaryContentViewBottomConstraint" destination="4tt-w0-4JE" id="6db-Jz-jys"/>
<outlet property="threadSummaryContentViewLeadingConstraint" destination="2lm-T3-dEu" id="jR6-sh-Nul"/>
<outlet property="threadSummaryContentViewTrailingConstraint" destination="Qwm-Of-Zgc" id="dfE-aR-MQQ"/>
<outlet property="urlPreviewContainerView" destination="57V-Sl-EmD" id="9c6-ai-BY8"/>
<outlet property="urlPreviewContentView" destination="vpX-Nl-AEt" id="P8S-Fg-VFQ"/>
<outlet property="urlPreviewContentViewLeadingConstraint" destination="lTt-Qx-fuQ" id="5Fc-zl-b1j"/>
<outlet property="urlPreviewContentViewTrailingConstraint" destination="ZmA-Ns-chh" id="EXg-Rr-cuJ"/>
<outlet property="userNameContainerView" destination="w0C-6a-f5M" id="fZE-vY-0nR"/>
<outlet property="userNameLabel" destination="meG-P8-61b" id="ETK-ag-WYR"/>
<outlet property="userNameTouchMaskView" destination="ohU-Sc-mgb" id="FwW-aL-kc5"/>
</connections>
<point key="canvasLocation" x="-1092" y="-1332"/>
</view>
</objects>
<resources>
<image name="encryption_warning" width="12" height="12"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
@@ -0,0 +1,23 @@
/*
Copyright 2020 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import Foundation
/// `BubbleCellReactionsDisplayable` is a protocol indicating that a cell support displaying reactions.
@objc protocol BubbleCellReactionsDisplayable {
func addReactionsView(_ reactionsView: UIView)
func removeReactionsView()
}
@@ -0,0 +1,23 @@
/*
Copyright 2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import Foundation
/// `BubbleCellReadReceiptsDisplayable` is a protocol indicating that a cell support displaying read receipts.
@objc protocol BubbleCellReadReceiptsDisplayable {
func addReadReceiptsView(_ readReceiptsView: UIView)
func removeReadReceiptsView()
}
@@ -0,0 +1,23 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
/// `BubbleCellThreadSummaryDisplayable` is a protocol indicating that a cell support displaying a thread summary.
@objc protocol BubbleCellThreadSummaryDisplayable {
func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView)
func removeThreadSummaryView()
}
@@ -0,0 +1,23 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
/// BubbleCellContentView decoration view items alignment
enum RoomCellDecorationAlignment {
case left
case right
}
@@ -0,0 +1,23 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
/// `RoomCellURLPreviewDisplayable` is a protocol indicating that a cell support displaying a URL preview.
@objc protocol RoomCellURLPreviewDisplayable {
func addURLPreviewView(_ urlPreviewView: UIView)
func removeURLPreviewView()
}
@@ -0,0 +1,23 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import UIKit
/// `TimestampDisplayable` is a protocol indicating that a view supports displaying a timestamp.
@objc protocol TimestampDisplayable {
func addTimestampView(_ timestampView: UIView)
func removeTimestampView()
}