sendbird-uikit-ios/Sources/View/Channel/MessageCell/SBUUserMessageCell.swift

227 lines
8.0 KiB
Swift

//
// SBUUserMessageCell.swift
// SendbirdUIKit
//
// Created by Harry Kim on 2020/02/20.
// Copyright © 2020 Sendbird, Inc. All rights reserved.
//
import UIKit
import SendbirdChatSDK
@IBDesignable
open class SBUUserMessageCell: SBUContentBaseMessageCell, SBUUserMessageTextViewDelegate {
// MARK: - Public property
public lazy var messageTextView: UIView = SBUUserMessageTextView()
public var userMessage: UserMessage? {
self.message as? UserMessage
}
// + ------------ +
// | reactionView |
// + ------------ +
/// A ``SBUSelectableStackView`` that contains `reactionView`.
public private(set) var additionContainerView: SBUSelectableStackView = {
let view = SBUSelectableStackView()
return view
}()
/// A ``SBUMessageWebView`` which represents a preview of the web link
public var webView: SBUMessageWebView = {
let webView = SBUMessageWebView()
return webView
}()
// MARK: - View Lifecycle
open override func setupViews() {
super.setupViews()
(self.messageTextView as? SBUUserMessageTextView)?.delegate = self
// + --------------- +
// | messageTextView |
// + --------------- +
// | reactionView |
// + --------------- +
self.mainContainerView.setStack([
self.messageTextView,
self.additionContainerView.setStack([
self.reactionView
])
])
}
open override func setupLayouts() {
super.setupLayouts()
}
open override func setupActions() {
super.setupActions()
if let messageTextView = self.messageTextView as? SBUUserMessageTextView {
messageTextView.longPressHandler = { [weak self] _ in
guard let self = self else { return }
self.onLongPressContentView(sender: nil)
}
}
self.messageTextView.addGestureRecognizer(self.contentLongPressRecognizer)
self.messageTextView.addGestureRecognizer(self.contentTapRecognizer)
self.webView.addGestureRecognizer(UITapGestureRecognizer(
target: self,
action: #selector(self.onTapWebview(sender:))
))
}
open override func setupStyles() {
super.setupStyles()
let isWebviewVisible = !self.webView.isHidden
self.additionContainerView.leftBackgroundColor = isWebviewVisible
? self.theme.contentBackgroundColor
: self.theme.leftBackgroundColor
self.additionContainerView.leftPressedBackgroundColor = isWebviewVisible
? self.theme.pressedContentBackgroundColor
: self.theme.leftPressedBackgroundColor
self.additionContainerView.rightBackgroundColor = isWebviewVisible
? self.theme.contentBackgroundColor
: self.theme.rightBackgroundColor
self.additionContainerView.rightPressedBackgroundColor = isWebviewVisible
? self.theme.pressedContentBackgroundColor
: self.theme.rightPressedBackgroundColor
self.additionContainerView.setupStyles()
self.webView.setupStyles()
self.additionContainerView.layer.cornerRadius = 8
}
// MARK: - Common
open override func configure(with configuration: SBUBaseMessageCellParams) {
guard let configuration = configuration as? SBUUserMessageCellParams else { return }
guard let message = configuration.userMessage else { return }
// Set using reaction
self.useReaction = configuration.useReaction
self.useQuotedMessage = configuration.useQuotedMessage
self.useThreadInfo = configuration.useThreadInfo
// Configure Content base message cell
super.configure(with: configuration)
// Set up message position of additionContainerView(reactionView)
self.additionContainerView.position = self.position
self.additionContainerView.isSelected = false
// Set up SBUUserMessageTextView
if let messageTextView = messageTextView as? SBUUserMessageTextView, configuration.withTextView {
messageTextView.configure(
model: SBUUserMessageTextViewModel(
message: message,
position: configuration.messagePosition
)
)
}
// Set up WebView with OG meta data
if let ogMetaData = configuration.message.ogMetaData {
self.additionContainerView.insertArrangedSubview(self.webView, at: 0)
self.webView.isHidden = false
let model = SBUMessageWebViewModel(metaData: ogMetaData)
self.webView.configure(model: model)
} else {
self.additionContainerView.removeArrangedSubview(self.webView)
self.webView.isHidden = true
}
}
@available(*, deprecated, renamed: "configure(with:)") // 2.2.0
open func configure(_ message: UserMessage,
hideDateView: Bool,
groupPosition: MessageGroupPosition,
receiptState: SBUMessageReceiptState?,
useReaction: Bool) {
let configuration = SBUUserMessageCellParams(
message: message,
hideDateView: hideDateView,
useMessagePosition: true,
groupPosition: groupPosition,
receiptState: receiptState ?? .none,
useReaction: false,
withTextView: true
)
self.configure(with: configuration)
}
@available(*, deprecated, renamed: "configure(with:)") // 2.2.0
open func configure(_ message: BaseMessage,
hideDateView: Bool,
receiptState: SBUMessageReceiptState?,
groupPosition: MessageGroupPosition,
withTextView: Bool) {
guard let userMessage = message as? UserMessage else {
SBULog.error("The message is not a type of UserMessage")
return
}
let configuration = SBUUserMessageCellParams(
message: userMessage,
hideDateView: hideDateView,
useMessagePosition: true,
groupPosition: groupPosition,
receiptState: receiptState ?? .none,
useReaction: self.useReaction,
withTextView: withTextView
)
self.configure(with: configuration)
}
/// Adds highlight attribute to the message
open override func configure(highlightInfo: SBUHighlightMessageInfo?) {
// Only apply highlight for the given message, that's not edited (updatedAt didn't change)
guard let message = self.message,
message.messageId == highlightInfo?.messageId,
message.updatedAt == highlightInfo?.updatedAt else { return }
guard let messageTextView = messageTextView as? SBUUserMessageTextView else { return }
messageTextView.configure(
model: SBUUserMessageTextViewModel(
message: message,
position: position,
highlightKeyword: highlightInfo?.keyword
)
)
}
// MARK: - Action
public override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
self.additionContainerView.isSelected = selected
}
@objc
open func onTapWebview(sender: UITapGestureRecognizer) {
guard
let ogMetaData = self.userMessage?.ogMetaData,
let urlString = ogMetaData.url,
let url = URL(string: urlString),
UIApplication.shared.canOpenURL(url) else {
return
}
url.open()
}
// MARK: - Mention
/// As a default, it calls `groupChannelModule(_:didTapMentionUser:)` in ``SBUGroupChannelModuleListDelegate``.
open func userMessageTextView(_ textView: SBUUserMessageTextView, didTapMention user: SBUUser) {
self.mentionTapHandler?(user)
}
}