| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- //
- // SelectedMembersViewController.swift
- // TUIRoomKit
- //
- // Created by CY zhao on 2024/6/24.
- //
- import Foundation
- import RTCRoomEngine
- protocol SelectedMemberCellProtocol: AnyObject {
- func didDeleteButtonClicked(in memberCell: SelectedMemberCell)
- }
- class SelectedMembersViewController: UIViewController {
- private(set) var showDeleteButton: Bool = true
- var selectedMember: [UserInfo] = []
- var didDeselectMember: ((UserInfo) -> Void)?
- private let arrowViewHeight: CGFloat = 35.0
-
- init(showDeleteButton: Bool = true, selectedMembers: [UserInfo] = []) {
- self.showDeleteButton = showDeleteButton
- self.selectedMember = selectedMembers
- super.init(nibName: nil, bundle: nil)
- modalPresentationStyle = .custom
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- private let tableView: UITableView = {
- let tableView = UITableView(frame: .zero, style: .plain)
- tableView.backgroundColor = .clear
- tableView.register(SelectedMemberCell.self, forCellReuseIdentifier: SelectedMemberCell.reuseIdentifier)
- if #available(iOS 15.0, *) {
- tableView.sectionHeaderTopPadding = 0
- }
- return tableView
- }()
-
- private let dropArrowView : UIView = {
- let view = UIView()
- view.backgroundColor = .white
- return view
- }()
-
- private let dropArrowImageView: UIImageView = {
- let view = UIImageView()
- view.image = UIImage(named: "room_drop_arrow", in:tuiRoomKitBundle(), compatibleWith: nil)
- return view
- }()
-
- let contentView: UIView = {
- let view = UIView(frame: .zero)
- view.backgroundColor = .white
- view.layer.cornerRadius = 8
- view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
- view.clipsToBounds = true
- return view
- }()
-
- override func viewDidLoad() {
- super.viewDidLoad()
- view.backgroundColor = UIColor.tui_color(withHex: "0F1014", alpha: 0.6)
- constructViewHierarchy()
- activateConstraints()
- bindInteraction()
- }
-
- private func constructViewHierarchy() {
- view.addSubview(contentView)
- dropArrowView.addSubview(dropArrowImageView)
- contentView.addSubview(dropArrowView)
- contentView.addSubview(tableView)
- }
-
- private func activateConstraints() {
- contentView.snp.makeConstraints { make in
- make.height.equalTo(610)
- make.leading.bottom.trailing.equalToSuperview()
- }
- 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.bottom.trailing.equalToSuperview()
- }
- }
-
- private func bindInteraction() {
- tableView.delegate = self
- tableView.dataSource = self
- let dropArrowTap = UITapGestureRecognizer(target: self, action: #selector(dropDownPopUpViewAction(sender:)))
- dropArrowView.addGestureRecognizer(dropArrowTap)
- dropArrowView.isUserInteractionEnabled = true
- }
-
- @objc func dropDownPopUpViewAction(sender: UIView) {
- self.dismiss(animated: true)
- }
- }
- extension SelectedMembersViewController: SelectedMemberCellProtocol{
- func didDeleteButtonClicked(in memberCell: SelectedMemberCell) {
- guard let indexPath = self.tableView.indexPath(for: memberCell) else {
- return
- }
- let member = selectedMember[indexPath.row]
- self.didDeselectMember?(member)
- selectedMember.remove(at: indexPath.row)
- self.tableView.deleteRows(at: [indexPath], with: .none)
-
- guard let headerView = tableView.headerView(forSection: 0) as? SelectedMemberHeaderView else {
- return
- }
- headerView.updateLabel(with: selectedMember.count)
- }
- }
- extension SelectedMembersViewController: UITableViewDelegate {
- func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
- return 52
- }
-
- func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
- let headerView = SelectedMemberHeaderView(reuseIdentifier: "CustomHeaderView")
- headerView.updateLabel(with: selectedMember.count)
- return headerView
- }
-
- func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
- return 38
- }
- }
- extension SelectedMembersViewController: UITableViewDataSource {
- func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- return selectedMember.count
- }
-
- func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- guard let cell = tableView.dequeueReusableCell(withIdentifier: SelectedMemberCell.reuseIdentifier, for: indexPath)
- as? SelectedMemberCell else {
- return UITableViewCell()
- }
- let member = selectedMember[indexPath.row]
- cell.updateView(with: member)
- cell.delegate = self
- if showDeleteButton {
- cell.showDeleteButton()
- } else {
- cell.hideDeleteButton()
- }
- return cell
- }
- }
- class SelectedMemberCell: UITableViewCell {
- static let reuseIdentifier = "SelectedMemberCell"
- weak var delegate: SelectedMemberCellProtocol?
- private let avatarImageView: UIImageView = {
- let imgView = UIImageView()
- imgView.layer.cornerRadius = 2
- imgView.layer.masksToBounds = true
- return imgView
- }()
-
- private let nameLabel: UILabel = {
- let label = UILabel()
- label.textColor = UIColor.tui_color(withHex: "22262E")
- label.textAlignment = isRTL ? .right : .left
- label.font = UIFont(name: "PingFangSC-Regular", size: 14)
- label.numberOfLines = 1
- return label
- }()
-
- let deleteButton: UIButton = {
- let button = LargerHitAreaButton()
- let image = UIImage(named: "room_delete", in: tuiRoomKitBundle(), compatibleWith: nil)
- button.setImage(image, for: .normal)
- return button
- }()
-
- private var isViewReady = false
- override func didMoveToWindow() {
- super.didMoveToWindow()
- guard !isViewReady else {
- return
- }
- isViewReady = true
- selectionStyle = .none
- constructViewHierarchy()
- activateConstraints()
- bindInteraction()
- contentView.backgroundColor = .clear
- }
-
- private func constructViewHierarchy() {
- contentView.addSubview(avatarImageView)
- contentView.addSubview(nameLabel)
- contentView.addSubview(deleteButton)
- }
-
- private func activateConstraints() {
- avatarImageView.snp.makeConstraints { make in
- make.width.height.equalTo(32)
- make.leading.equalToSuperview().offset(20)
- make.centerY.equalToSuperview()
- }
- nameLabel.snp.makeConstraints { make in
- make.leading.equalTo(self.avatarImageView.snp.trailing).offset(5)
- make.centerY.equalToSuperview()
- }
- deleteButton.snp.makeConstraints { make in
- make.trailing.equalToSuperview().offset(-20)
- make.centerY.equalToSuperview()
- make.width.height.equalTo(16)
- }
- }
-
- func updateView(with info: UserInfo) {
- let placeholder = UIImage(named: "room_default_avatar_rect", in: tuiRoomKitBundle(), compatibleWith: nil)
- if let url = URL(string: info.avatarUrl) {
- avatarImageView.sd_setImage(with: url, placeholderImage: placeholder)
- } else {
- avatarImageView.image = placeholder
- }
-
- if !info.userName.isEmpty {
- nameLabel.text = info.userName
- } else {
- nameLabel.text = info.userId
- }
- }
-
- func hideDeleteButton() {
- self.deleteButton.isHidden = true
- }
-
- func showDeleteButton() {
- self.deleteButton.isHidden = false
- }
-
- private func bindInteraction() {
- deleteButton.addTarget(self, action: #selector(deleteButtonTapped(sender:)), for: .touchUpInside)
- }
-
- @objc func deleteButtonTapped(sender: UIButton) {
- self.delegate?.didDeleteButtonClicked(in: self)
- }
- }
- class SelectedMemberHeaderView: UITableViewHeaderFooterView {
- override init(reuseIdentifier: String?) {
- super.init(reuseIdentifier: reuseIdentifier)
- backgroundView = UIView()
- backgroundView?.backgroundColor = .white
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- private let label: UILabel = {
- let label = UILabel()
- label.textColor = UIColor.tui_color(withHex: "4F586B")
- label.font = UIFont(name: "PingFangSC-Medium", size: 18)
- label.text = .selectedText
- label.sizeToFit()
- return label
- }()
-
- private var isViewReady = false
- override func didMoveToWindow() {
- super.didMoveToWindow()
- guard !isViewReady else {
- return
- }
- isViewReady = true
- constructViewHierarchy()
- activateConstraints()
- }
-
- private func constructViewHierarchy() {
- addSubview(label)
- }
-
- private func activateConstraints() {
- label.snp.makeConstraints { make in
- make.leading.equalToSuperview().offset(20)
- make.top.equalToSuperview()
- }
- }
-
- func updateLabel(with count: Int) {
- let text = .selectedText + " (" + "\(count)" + ")"
- self.label.text = text
- }
- }
- class LargerHitAreaButton: UIButton {
- var hitAreaEdgeInsets = UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10)
- override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
- let largerFrame = bounds.inset(by: hitAreaEdgeInsets)
- return largerFrame.contains(point)
- }
- }
- private extension String {
- static var selectedText: String {
- localized("Selected")
- }
- }
|