Files
midi_ios/TUIKit/TUIRoomKit/Source/View/Page/Widget/MediaSettings/QualityInfoPanel.swift
2025-08-14 10:07:49 +08:00

380 lines
12 KiB
Swift

//
// QualityInfoPanel.swift
// TUIRoomKit
//
// Created by CY zhao on 2024/4/19.
// Copyright © 2024 Tencent. All rights reserved.
//
import Foundation
class QualityInfoPanel: UIView {
var viewModel: QualityInfoViewModel = QualityInfoViewModel()
let landscapeHight: CGFloat = min(kScreenWidth, kScreenHeight)
let portraitHight: CGFloat = 411.scale375Height()
private let arrowViewHeight: CGFloat = 35.0
private let cellHeight: CGFloat = 33.0
private let lineViewHorizontalMargin = 16.0
private let headerHeight = 48
private var currentLandscape: Bool = isLandscape
let bgView: UIView = {
let view = UIView(frame: .zero)
view.backgroundColor = .black
view.alpha = 0.6
return view
}()
let contentView: UIView = {
let view = UIView(frame: .zero)
view.backgroundColor = UIColor(0x22262E)
view.layer.cornerRadius = 12
return view
}()
private let dropArrowView : UIView = {
let view = UIView()
return view
}()
private let dropArrowImageView: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "room_drop_arrow", in:tuiRoomKitBundle(), compatibleWith: nil)
return view
}()
lazy var tableView: UITableView = {
let tableView = UITableView(frame: .zero, style: .grouped)
tableView.separatorStyle = .none
tableView.backgroundColor = UIColor(0x22262E)
tableView.delegate = self
tableView.dataSource = self
tableView.register(QualityTableViewCell.self,
forCellReuseIdentifier: "QualityTableViewCell")
tableView.sectionHeaderHeight = headerHeight.scale375()
if #available(iOS 15.0, *) {
tableView.sectionHeaderTopPadding = 0
}
return tableView
}()
var willDismiss: (() -> Void)?
var didDismiss: (() -> Void)?
override init(frame: CGRect = .zero) {
super.init(frame: frame)
contentView.transform = CGAffineTransform(translationX: 0, y: kScreenHeight)
alpha = 0
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private var isViewReady = false
override func didMoveToWindow() {
super.didMoveToWindow()
guard !isViewReady else {
return
}
isViewReady = true
self.viewModel.viewResponder = self
constructViewHierarchy()
activateConstraints()
bindInteraction()
}
func show(rootView: UIView) {
rootView.addSubview(self)
self.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
UIView.animate(withDuration: 0.3) { [weak self] in
guard let self = self else { return }
self.alpha = 1
self.contentView.transform = .identity
}
}
func dismiss() {
if let action = willDismiss {
action()
}
UIView.animate(withDuration: 0.3) { [weak self] in
guard let self = self else { return }
self.alpha = 0
self.contentView.transform = CGAffineTransform(translationX: 0, y: kScreenHeight)
} completion: { [weak self] _ in
guard let self = self else { return }
if let action = self.didDismiss {
action()
}
self.removeFromSuperview()
}
}
override func layoutSubviews() {
super.layoutSubviews()
guard currentLandscape != isLandscape else { return }
setupViewOrientation(isLandscape: isLandscape)
currentLandscape = isLandscape
}
func constructViewHierarchy() {
addSubview(bgView)
addSubview(contentView)
dropArrowView.addSubview(dropArrowImageView)
contentView.addSubview(dropArrowView)
contentView.addSubview(tableView)
}
func activateConstraints() {
bgView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
setupViewOrientation(isLandscape: isLandscape)
dropArrowView.snp.makeConstraints { make in
make.top.leading.trailing.equalToSuperview()
make.height.equalTo(arrowViewHeight)
}
dropArrowImageView.snp.makeConstraints { make in
make.centerX.centerY.equalToSuperview()
make.width.equalTo(24.scale375())
make.height.equalTo(3.scale375())
}
tableView.snp.makeConstraints { make in
make.top.equalTo(dropArrowView.snp.bottom)
make.leading.trailing.bottom.equalToSuperview()
}
}
func bindInteraction() {
let dropArrowTap = UITapGestureRecognizer(target: self, action: #selector(dropDownPopUpViewAction(sender:)))
dropArrowView.addGestureRecognizer(dropArrowTap)
dropArrowView.isUserInteractionEnabled = true
}
private func setupViewOrientation(isLandscape: Bool) {
contentView.snp.remakeConstraints { make in
if isLandscape {
make.height.equalTo(landscapeHight)
} else {
make.height.equalTo(portraitHight)
}
make.leading.trailing.bottom.equalToSuperview()
}
}
@objc func dropDownPopUpViewAction(sender: UIView) {
dismiss()
}
deinit {
debugPrint("deinit \(self)")
}
}
extension QualityInfoPanel: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.sections[section].items.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return viewModel.sections.count
}
}
extension QualityInfoPanel: UITableViewDelegate {
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "QualityTableViewCell", for: indexPath)
if let qualityCell = cell as? QualityTableViewCell {
qualityCell.setCellModel(model: self.viewModel.sections[indexPath.section].items[indexPath.row])
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return cellHeight.scale375()
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
let headerLabel = UILabel()
headerLabel.font = UIFont.systemFont(ofSize: 14, weight: .regular)
headerLabel.textColor = UIColor(0x99A2B2)
headerLabel.textAlignment = isRTL ? .right : .left
headerLabel.text = viewModel.sections[safe: section]?.titleText
headerView.addSubview(headerLabel)
headerLabel.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(16)
make.centerY.equalToSuperview()
}
return headerView
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
if section == self.viewModel.sections.count - 1 {
return 0
}
return 0.5
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
if section == self.viewModel.sections.count - 1 {
return nil
}
let footerView = UIView()
let lineView = UIView(frame: CGRect(x: lineViewHorizontalMargin,
y: 0,
width: tableView.frame.size.width - 2 * lineViewHorizontalMargin,
height: 0.5))
lineView.backgroundColor = UIColor(0xB2BBD1)
footerView.addSubview(lineView)
return footerView
}
}
extension QualityInfoPanel: QualityViewResponder {
func reloadData() {
self.tableView.reloadData()
}
}
class QualityTableViewCell: UITableViewCell {
let titleLabel: UILabel = {
let label = UILabel(frame: .zero)
label.font = UIFont(name: "PingFangSC-Regular", size: 16)
label.textColor = UIColor(0xE7ECF6)
label.sizeToFit()
return label
}()
let normalInfoLabel: UILabel = {
let label = UILabel(frame: .zero)
label.font = UIFont(name: "PingFangSC-Regular", size: 16)
label.textColor = UIColor(0xE7ECF6)
label.isHidden = true
label.sizeToFit()
return label
}()
let upInfoLabel: UILabel = {
let label = UILabel(frame: .zero)
label.font = UIFont(name: "PingFangSC-Regular", size: 16)
label.textColor = UIColor(0xE7ECF6)
label.isHidden = true
label.sizeToFit()
return label
}()
let uplinkImageView: UIImageView = {
let norImage = UIImage(named: "room_uplink_arrow", in: tuiRoomKitBundle(), compatibleWith: nil)
let imageView = UIImageView(image: norImage)
imageView.isHidden = true
return imageView
}()
let downInfoLabel: UILabel = {
let label = UILabel(frame: .zero)
label.font = UIFont(name: "PingFangSC-Regular", size: 16)
label.textColor = UIColor(0xE7ECF6)
label.isHidden = true
label.sizeToFit()
return label
}()
let downlinkImageView: UIImageView = {
let norImage = UIImage(named: "room_downlink_arrow", in: tuiRoomKitBundle(), compatibleWith: nil)
let imageView = UIImageView(image: norImage)
imageView.isHidden = true
return imageView
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
private var isViewReady = false
override func didMoveToWindow() {
super.didMoveToWindow()
backgroundColor = .clear
selectionStyle = .none
guard !isViewReady else {
return
}
isViewReady = true
constructViewHierarchy()
activateConstraints()
}
private func constructViewHierarchy() {
contentView.addSubview(titleLabel)
contentView.addSubview(normalInfoLabel)
contentView.addSubview(downInfoLabel)
contentView.addSubview(downlinkImageView)
contentView.addSubview(upInfoLabel)
contentView.addSubview(uplinkImageView)
}
private func activateConstraints() {
titleLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.leading.equalToSuperview().offset(16)
}
normalInfoLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.trailing.equalToSuperview().offset(-16)
}
downlinkImageView.snp.makeConstraints { make in
make.width.height.equalTo(16)
make.centerY.equalToSuperview()
make.trailing.equalToSuperview().offset(-16)
}
downInfoLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.trailing.equalTo(downlinkImageView.snp.leading).offset(-4)
}
uplinkImageView.snp.makeConstraints { make in
make.width.height.equalTo(16)
make.centerY.equalToSuperview()
make.trailing.equalTo(downInfoLabel.snp.leading).offset(-16)
}
upInfoLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.trailing.equalTo(uplinkImageView.snp.leading).offset(-4)
}
}
func setCellModel(model: QualityCellModel) {
self.titleLabel.text = model.titleText
if model.type == .upDown {
showUpDownInfo(isShow: true)
showNormalInfo(isShow: false)
upInfoLabel.text = model.uplinkString
downInfoLabel.text = model.downlinkString
} else {
showUpDownInfo(isShow: false)
showNormalInfo(isShow: true)
normalInfoLabel.text = model.normalString
}
}
private func showUpDownInfo(isShow: Bool) {
upInfoLabel.isHidden = !isShow
uplinkImageView.isHidden = !isShow
downInfoLabel.isHidden = !isShow
downlinkImageView.isHidden = !isShow
}
private func showNormalInfo(isShow: Bool) {
normalInfoLabel.isHidden = !isShow
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}