| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- //
- // FloatChatDisplayView.swift
- // TUIRoomKit
- //
- // Created by CY zhao on 2024/5/9.
- // Copyright © 2024 Tencent. All rights reserved.
- //
- import UIKit
- #if USE_OPENCOMBINE
- import OpenCombine
- import OpenCombineDispatch
- #else
- import Combine
- #endif
- import Factory
- protocol FloatChatDisplayViewDelegate: AnyObject {
- func getTheLatestUserName(userId: String) -> String
- }
- class FloatChatDisplayView: UIView {
- @Injected(\.floatChatService) private var store: FloatChatStoreProvider
- private lazy var messagePublisher = self.store.select(FloatChatSelectors.getLatestMessage)
- private var messages: [FloatChatMessageView] = []
- var cancellableSet = Set<AnyCancellable>()
- private let messageSpacing: CGFloat = 8
- weak var delegate: FloatChatDisplayViewDelegate?
-
- private lazy var blurLayer: CALayer = {
- let layer = CAGradientLayer()
- layer.colors = [
- UIColor.black.withAlphaComponent(0).cgColor,
- UIColor.black.withAlphaComponent(1).cgColor
- ]
- layer.locations = [0, 0.2]
- layer.startPoint = CGPoint(x: 0.5, y: 0)
- layer.endPoint = CGPoint(x: 0.5, y: 1)
- return layer
- }()
-
- override func layoutSubviews() {
- super.layoutSubviews()
- blurLayer.frame = self.bounds
- }
-
- private var isViewReady = false
- override func didMoveToWindow() {
- super.didMoveToWindow()
- guard !isViewReady else { return }
- constructViewHierarchy()
- bindInteraction()
- reportViewShow()
- isViewReady = true
- }
- private func constructViewHierarchy() {
- self.layer.mask = blurLayer
- }
-
- func bindInteraction() {
- messagePublisher
- .filter{ !($0.content.isEmpty && $0.type == .text) }
- .receive(on: DispatchQueue.mainQueue)
- .sink { [weak self] floatMessage in
- guard let self = self else { return }
- self.addMessage(floatMessage)
- }
- .store(in: &cancellableSet)
- }
-
- private func reportViewShow() {
- store.dispatch(action: FloatChatActions.reportData(payload: .metricsBarragePanelShow))
- }
-
- private func addMessage(_ message: FloatChatMessage) {
- var message = message
- if let userName = delegate?.getTheLatestUserName(userId: message.user.userId), !userName.isEmpty {
- message.user.userName = userName
- }
- let messageView = FloatChatMessageView(floatMessage: message)
- if currentMessageHeight() + messageView.height + messageSpacing > bounds.height {
- removeOldestMessage()
- }
- addSubview(messageView)
- messageView.snp.makeConstraints { make in
- make.leading.equalToSuperview()
- make.width.lessThanOrEqualToSuperview()
- make.height.lessThanOrEqualToSuperview()
- if let lastMessage = messages.last {
- make.top.equalTo(lastMessage.snp.bottom).offset(messageSpacing).priority(.high)
- }
- make.bottom.lessThanOrEqualToSuperview()
- }
- messages.append(messageView)
-
- DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
- self.removeMessageWithAnimation(message: messageView)
- }
- }
-
- private func currentMessageHeight() -> CGFloat {
- return messages.reduce(0) { $0 + $1.height + messageSpacing}
- }
-
- private func removeOldestMessage() {
- guard let oldest = messages.first else { return }
- removeMessage(message: oldest)
- }
-
- private func removeMessageWithAnimation(message: FloatChatMessageView) {
- UIView.animate(withDuration: 0.3) {
- message.alpha = 0
- } completion: { _ in
- self.removeMessage(message: message)
- }
- }
-
- private func removeMessage(message: FloatChatMessageView) {
- if let index = messages.firstIndex(of: message) {
- message.removeFromSuperview()
- messages.remove(at: index)
- }
- }
- }
- extension FloatChatDisplayView {
- override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
- return nil
- }
- }
|