Files
featherVoice/TUIKit/TUIRoomKit/Source/View/Page/Widget/TopNavigationBar/TopView.swift

298 lines
9.6 KiB
Swift
Raw Normal View History

2025-08-08 10:49:36 +08:00
//
// TopView.swift
// TUIRoomKit
//
// Created by janejntang on 2022/12/30.
// Copyright © 2022 Tencent. All rights reserved.
//
import Foundation
class TopView: UIView {
// MARK: - store property
let viewModel: TopViewModel
private var viewArray: [TopItemView] = []
let backgroundImageView: UIImageView = {
let image = UIImage(named: "room_top_background",in: tuiRoomKitBundle(), compatibleWith: nil)
let imageView = UIImageView(image: image)
return imageView
}()
let contentView: UIView = {
let view = UIView()
return view
}()
let stackView: UIStackView = {
let view = UIStackView()
view.axis = .horizontal
view.alignment = .center
view.spacing = 2.scale375()
return view
}()
let meetingTitleView: UIView = {
let view = UIView()
return view
}()
let meetingNameLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor(0xD5E0F2)
label.font = UIFont(name: "PingFangSC-Medium", size: 16)
label.textAlignment = isRTL ? .right : .left
label.lineBreakMode = .byTruncatingTail
return label
}()
let dropDownButton: UIButton = {
let button = UIButton(type: .custom)
let normalIcon = UIImage(named: "room_drop_down", in: tuiRoomKitBundle(), compatibleWith: nil)
button.setImage(normalIcon, for: .normal)
button.isEnabled = true
return button
}()
let timeLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor(0xD1D9EC)
label.textAlignment = .center
label.adjustsFontSizeToFitWidth = true
label.font = UIFont(name: "PingFangSC-Medium", size: 12)
return label
}()
let exitView: UIView = {
let view = UIView()
return view
}()
let exitImage: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "room_exit", in: tuiRoomKitBundle(), compatibleWith: nil)?.checkOverturn()
return imageView
}()
let exitLabel: UILabel = {
let label = UILabel()
label.text = .exitText
label.textColor = UIColor(0xED414D)
label.textAlignment = .right
label.adjustsFontSizeToFitWidth = true
label.font = UIFont(name: "PingFangSC-Medium", size: 14)
return label
}()
var menuButtons: [UIView] = []
// MARK: - initialized function
init(viewModel: TopViewModel) {
self.viewModel = viewModel
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - view layout
private var isViewReady: Bool = false
override func didMoveToWindow() {
super.didMoveToWindow()
guard !isViewReady else { return }
backgroundColor = UIColor(0x0F1014)
constructViewHierarchy()
activateConstraints()
bindInteraction()
isViewReady = true
}
func constructViewHierarchy() {
addSubview(backgroundImageView)
addSubview(contentView)
contentView.addSubview(meetingTitleView)
contentView.addSubview(stackView)
contentView.addSubview(exitView)
meetingTitleView.addSubview(meetingNameLabel)
meetingTitleView.addSubview(dropDownButton)
meetingTitleView.addSubview(timeLabel)
exitView.addSubview(exitImage)
exitView.addSubview(exitLabel)
for item in viewModel.viewItems {
let view = TopItemView(itemData: item)
menuButtons.append(view)
stackView.addArrangedSubview(view)
viewArray.append(view)
let size = item.size ?? CGSize(width: 35.scale375(), height: 40.scale375Height())
view.snp.makeConstraints { make in
make.height.equalTo(size.height)
make.width.equalTo(size.width)
}
}
}
func activateConstraints() {
updateRootViewOrientation(isLandscape: isLandscape)
backgroundImageView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
meetingTitleView.snp.makeConstraints { make in
make.width.lessThanOrEqualTo(180.scale375())
make.height.equalTo(44.scale375Height())
make.center.equalToSuperview()
}
stackView.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(16.scale375())
make.top.bottom.equalToSuperview()
}
meetingNameLabel.snp.makeConstraints { make in
make.top.equalToSuperview()
make.height.equalTo(24.scale375())
make.width.lessThanOrEqualTo(128.scale375())
make.leading.equalToSuperview()
}
timeLabel.snp.makeConstraints { make in
make.top.equalTo(meetingNameLabel.snp.bottom).offset(5)
make.centerX.equalToSuperview()
make.height.equalTo(20)
}
exitView.snp.makeConstraints { make in
make.top.bottom.equalToSuperview()
make.trailing.equalToSuperview().offset(-16.scale375())
make.width.equalTo(51.scale375())
}
exitImage.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.left.equalToSuperview()
make.width.equalTo(20.scale375())
make.height.equalTo(20.scale375())
}
exitLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.right.equalToSuperview()
make.width.equalTo(28.scale375())
make.height.equalTo(20.scale375())
}
}
func bindInteraction() {
let dropTap = UITapGestureRecognizer(target: self, action: #selector(dropDownAction(sender:)))
let exitTap = UITapGestureRecognizer(target: self, action: #selector(exitAction(sender:)))
meetingNameLabel.text = viewModel.engineManager.store.roomInfo.name
meetingTitleView.addGestureRecognizer(dropTap)
exitView.addGestureRecognizer(exitTap)
viewModel.viewResponder = self
}
func updateRootViewOrientation(isLandscape: Bool) {
contentView.snp.remakeConstraints { make in
if isLandscape {
make.top.equalToSuperview()
} else {
make.top.equalToSuperview().offset(44.scale375Height())
}
make.leading.trailing.bottom.equalToSuperview()
}
meetingTitleView.snp.remakeConstraints { make in
if isLandscape {
make.width.lessThanOrEqualTo(300.scale375())
make.height.equalTo(24.scale375Height())
} else {
make.width.lessThanOrEqualTo(180.scale375())
make.height.equalTo(44.scale375Height())
}
make.center.equalToSuperview()
}
dropDownButton.snp.remakeConstraints { make in
make.leading.equalTo(meetingNameLabel.snp.trailing).offset(2.scale375())
make.centerY.equalTo(meetingNameLabel)
make.width.height.equalTo(16.scale375())
if !isLandscape {
make.trailing.equalToSuperview()
}
}
timeLabel.snp.remakeConstraints { make in
if isLandscape {
make.centerY.equalTo(dropDownButton)
make.leading.equalTo(dropDownButton.snp.trailing).offset(15)
make.trailing.equalToSuperview()
} else {
make.top.equalTo(meetingNameLabel.snp.bottom).offset(5)
make.centerX.equalToSuperview()
}
}
}
@objc func dropDownAction(sender: UIView) {
viewModel.dropDownAction(sender: sender)
}
@objc func exitAction(sender: UIView) {
viewModel.exitAction(sender: sender)
}
deinit {
debugPrint("deinit \(self)")
}
}
enum AlertAction {
case dismissRoomAction
case transferMasterAction
case leaveRoomAction
case cancelAction
}
extension TopView: TopViewModelResponder {
func updateMeetingNameLabel(_ text: String) {
meetingNameLabel.text = text
}
func updateStackView(item: ButtonItemData) {
guard let view = viewArray.first(where: { $0.itemData.buttonType == item.buttonType }) else { return }
view.setupViewState(item: item)
}
func updateTimerLabel(text: String) {
self.timeLabel.text = text
}
#if RTCube_APPSTORE
func showReportView() {
let selector = NSSelectorFromString("showReportAlertWithRoomId:ownerId:")
if responds(to: selector) {
let roomInfo = viewModel.store.roomInfo
perform(selector, with: roomInfo.roomId, with: roomInfo.ownerId)
}
}
#endif
}
private extension String {
static var leaveRoomTitle: String {
localized("Are you sure you want to leave the conference?")
}
static var destroyRoomTitle: String {
localized("Are you sure you want to end the conference?")
}
static var dismissMeetingTitle: String {
localized("If you don't want to end the conference")
}
static var appointNewHostText: String {
localized("Please appoint a new host before leaving the conference")
}
static var leaveMeetingText: String {
localized("Leave conference")
}
static var dismissMeetingText: String {
localized("End conference")
}
static var cancelText: String {
localized("Cancel")
}
static var exitText: String {
localized("Exit")
}
}