session-ios/Session/Conversations/Message Cells/TypingIndicatorCell.swift

95 lines
3.0 KiB
Swift

// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import SessionUIKit
import SessionMessagingKit
// Assumptions
// We'll never encounter an outgoing typing indicator.
// Typing indicators are only sent in contact threads.
final class TypingIndicatorCell: MessageCell {
// MARK: - UI
private lazy var bubbleView: UIView = {
let result: UIView = UIView()
result.layer.cornerRadius = VisibleMessageCell.smallCornerRadius
result.backgroundColor = Colors.receivedMessageBackground
return result
}()
private let bubbleViewMaskLayer: CAShapeLayer = CAShapeLayer()
private lazy var typingIndicatorView: TypingIndicatorView = TypingIndicatorView()
// MARK: - Lifecycle
override func setUpViewHierarchy() {
super.setUpViewHierarchy()
// Bubble view
addSubview(bubbleView)
bubbleView.pin(.left, to: .left, of: self, withInset: VisibleMessageCell.contactThreadHSpacing)
bubbleView.pin(.top, to: .top, of: self, withInset: 1)
// Typing indicator view
bubbleView.addSubview(typingIndicatorView)
typingIndicatorView.pin(to: bubbleView, withInset: 12)
}
// MARK: - Updating
override func update(with cellViewModel: MessageViewModel, mediaCache: NSCache<NSString, AnyObject>, playbackInfo: ConversationViewModel.PlaybackInfo?, lastSearchText: String?) {
guard cellViewModel.cellType == .typingIndicator else { return }
self.viewModel = cellViewModel
// Bubble view
updateBubbleViewCorners()
// Typing indicator view
typingIndicatorView.startAnimation()
}
override func dynamicUpdate(with cellViewModel: MessageViewModel, playbackInfo: ConversationViewModel.PlaybackInfo?) {
}
override func layoutSubviews() {
super.layoutSubviews()
updateBubbleViewCorners()
}
private func updateBubbleViewCorners() {
let maskPath = UIBezierPath(
roundedRect: bubbleView.bounds,
byRoundingCorners: getCornersToRound(),
cornerRadii: CGSize(
width: VisibleMessageCell.largeCornerRadius,
height: VisibleMessageCell.largeCornerRadius)
)
bubbleViewMaskLayer.path = maskPath.cgPath
bubbleView.layer.mask = bubbleViewMaskLayer
}
override func prepareForReuse() {
super.prepareForReuse()
typingIndicatorView.stopAnimation()
}
// MARK: - Convenience
private func getCornersToRound() -> UIRectCorner {
guard viewModel?.isOnlyMessageInCluster == false else { return .allCorners }
switch viewModel?.positionInCluster {
case .top: return [ .topLeft, .topRight, .bottomRight ]
case .middle: return [ .topRight, .bottomRight ]
case .bottom: return [ .topRight, .bottomRight, .bottomLeft ]
case .none: return .allCorners
}
}
}