357 lines
12 KiB
Swift
357 lines
12 KiB
Swift
//
|
|
// TransferMasterView.swift
|
|
// TUIRoomKit
|
|
//
|
|
// Created by janejntang on 2023/2/20.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
class TransferMasterView: UIView {
|
|
let viewModel: TransferMasterViewModel
|
|
var attendeeList: [UserEntity]
|
|
var searchArray: [UserEntity] = []
|
|
private var isSearching: Bool = false
|
|
|
|
let topLabel: UILabel = {
|
|
let label = UILabel()
|
|
label.textColor = UIColor(0xD5E0F2)
|
|
label.font = UIFont(name: "PingFangSC-Regular", size: 16)
|
|
label.text = .transferMasterText
|
|
return label
|
|
}()
|
|
|
|
let searchBar: UISearchBar = {
|
|
let searchBar = UISearchBar()
|
|
searchBar.placeholder = .searchMemberText
|
|
searchBar.setBackgroundImage(UIColor(0x1B1E26).trans2Image(), for: .top, barMetrics: .default)
|
|
if #available(iOS 13, *) {
|
|
searchBar.searchTextField.textColor = UIColor(0xB2BBD1)
|
|
searchBar.searchTextField.tintColor = UIColor(0xB2BBD1).withAlphaComponent(0.3)
|
|
searchBar.searchTextField.layer.cornerRadius = 6
|
|
searchBar.searchTextField.font = UIFont.systemFont(ofSize: 14, weight: .medium)
|
|
} else {
|
|
if let textField = searchBar.value(forKey: "searchField") as? UITextField {
|
|
textField.textColor = UIColor(0xB2BBD1)
|
|
textField.tintColor = UIColor(0xB2BBD1).withAlphaComponent(0.3)
|
|
textField.layer.cornerRadius = 6
|
|
textField.font = UIFont.systemFont(ofSize: 14, weight: .medium)
|
|
}
|
|
}
|
|
return searchBar
|
|
}()
|
|
|
|
let searchControl: UIControl = {
|
|
let view = UIControl()
|
|
view.backgroundColor = .clear
|
|
view.isHidden = true
|
|
return view
|
|
}()
|
|
|
|
let appointMasterButton: UIButton = {
|
|
let button = UIButton(type: .custom)
|
|
button.titleLabel?.font = UIFont.systemFont(ofSize: 14)
|
|
button.setTitle(.appointAndLeaveRoomText, for: .normal)
|
|
button.setTitleColor(UIColor(0xFFFFFF), for: .normal)
|
|
button.setBackgroundImage(UIColor(0x006EFF).withAlphaComponent(0.2).trans2Image(), for: .disabled)
|
|
button.setBackgroundImage(UIColor(0x006EFF).trans2Image(), for: .normal)
|
|
button.layer.cornerRadius = 12
|
|
button.clipsToBounds = true
|
|
button.titleLabel?.adjustsFontSizeToFitWidth = true
|
|
button.adjustsImageWhenHighlighted = false
|
|
return button
|
|
}()
|
|
|
|
lazy var transferMasterTableView: UITableView = {
|
|
let tableView = UITableView(frame: .zero, style: .plain)
|
|
tableView.separatorStyle = .none
|
|
tableView.delegate = self
|
|
tableView.dataSource = self
|
|
tableView.backgroundColor = UIColor(0x1B1E26)
|
|
tableView.register(TransferMasterTableCell.self, forCellReuseIdentifier: "RaiseHandCell")
|
|
return tableView
|
|
}()
|
|
|
|
init(viewModel: TransferMasterViewModel) {
|
|
self.viewModel = viewModel
|
|
self.attendeeList = viewModel.attendeeList
|
|
super.init(frame: .zero)
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
private var isViewReady: Bool = false
|
|
override func didMoveToWindow() {
|
|
super.didMoveToWindow()
|
|
backgroundColor = UIColor(0x1B1E26)
|
|
guard !isViewReady else { return }
|
|
constructViewHierarchy()
|
|
activateConstraints()
|
|
bindInteraction()
|
|
isViewReady = true
|
|
}
|
|
|
|
func constructViewHierarchy() {
|
|
addSubview(topLabel)
|
|
addSubview(searchBar)
|
|
addSubview(transferMasterTableView)
|
|
addSubview(appointMasterButton)
|
|
addSubview(searchControl)
|
|
}
|
|
|
|
func activateConstraints() {
|
|
topLabel.snp.makeConstraints { make in
|
|
make.top.equalToSuperview().offset(10.scale375Height())
|
|
make.leading.equalToSuperview().offset(16.scale375())
|
|
make.trailing.equalToSuperview().offset(-16.scale375())
|
|
make.height.equalTo(24.scale375Height())
|
|
}
|
|
searchBar.snp.makeConstraints { make in
|
|
make.leading.equalToSuperview().offset(16.scale375())
|
|
make.trailing.equalToSuperview().offset(-16.scale375())
|
|
make.height.equalTo(34.scale375Height())
|
|
make.top.equalTo(topLabel.snp.bottom).offset(23.scale375Height())
|
|
}
|
|
transferMasterTableView.snp.makeConstraints { make in
|
|
make.leading.equalToSuperview().offset(16.scale375())
|
|
make.trailing.equalToSuperview().offset(-16.scale375())
|
|
make.top.equalTo(searchBar.snp.bottom).offset(10.scale375Height())
|
|
make.bottom.equalToSuperview()
|
|
}
|
|
appointMasterButton.snp.makeConstraints { make in
|
|
make.trailing.equalToSuperview().offset(-20)
|
|
make.bottom.equalToSuperview().offset(-40 - kDeviceSafeBottomHeight)
|
|
make.height.equalTo(50)
|
|
make.leading.equalToSuperview().offset(20)
|
|
}
|
|
searchControl.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview()
|
|
}
|
|
}
|
|
|
|
func bindInteraction() {
|
|
searchBar.delegate = self
|
|
viewModel.viewResponder = self
|
|
appointMasterButton.addTarget(self, action: #selector(appointMasterAction(sender:)), for: .touchUpInside)
|
|
let tap = UITapGestureRecognizer(target: self, action: #selector(hideSearchControl(sender:)))
|
|
searchControl.addGestureRecognizer(tap)
|
|
appointMasterButton.isEnabled = viewModel.userId.count > 0
|
|
}
|
|
|
|
@objc func appointMasterAction(sender: UIButton) {
|
|
viewModel.appointMasterAction(sender: sender)
|
|
}
|
|
|
|
@objc func hideSearchControl(sender: UIView) {
|
|
if #available(iOS 13, *) {
|
|
searchBar.searchTextField.resignFirstResponder()
|
|
} else {
|
|
searchBar.resignFirstResponder()
|
|
}
|
|
searchControl.isHidden = true
|
|
}
|
|
|
|
deinit {
|
|
debugPrint("deinit \(self)")
|
|
}
|
|
}
|
|
|
|
extension TransferMasterView: UISearchBarDelegate {
|
|
func searchBar(_ searchBar:UISearchBar,textDidChange searchText:String){
|
|
let searchContentText = searchText.trimmingCharacters(in: .whitespaces)
|
|
if searchContentText.count == 0 {
|
|
attendeeList = viewModel.attendeeList
|
|
transferMasterTableView.reloadData()
|
|
isSearching = false
|
|
} else {
|
|
searchArray = viewModel.attendeeList.filter({ model -> Bool in
|
|
return model.userName.contains(searchContentText)
|
|
})
|
|
attendeeList = searchArray
|
|
transferMasterTableView.reloadData()
|
|
isSearching = true
|
|
}
|
|
}
|
|
|
|
func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
|
|
searchControl.isHidden = false
|
|
return true
|
|
}
|
|
}
|
|
|
|
extension TransferMasterView: UITableViewDataSource {
|
|
internal func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
return attendeeList.count
|
|
}
|
|
}
|
|
|
|
extension TransferMasterView: UITableViewDelegate {
|
|
internal func tableView(_ tableView: UITableView,
|
|
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
let attendeeModel = attendeeList[indexPath.row]
|
|
let cell = TransferMasterTableCell(attendeeModel: attendeeModel, viewModel: viewModel)
|
|
cell.selectionStyle = .none
|
|
return cell
|
|
}
|
|
|
|
internal func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
|
searchBar.endEditing(true)
|
|
if #available(iOS 13, *) {
|
|
searchBar.searchTextField.resignFirstResponder()
|
|
} else {
|
|
searchBar.resignFirstResponder()
|
|
}
|
|
viewModel.userId = attendeeList[indexPath.row].userId
|
|
appointMasterButton.isEnabled = true
|
|
transferMasterTableView.reloadData()
|
|
}
|
|
internal func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
|
return 60.scale375Height()
|
|
}
|
|
}
|
|
|
|
extension TransferMasterView: TransferMasterViewResponder {
|
|
func makeToast(message: String) {
|
|
makeToast(message)
|
|
}
|
|
|
|
func reloadTransferMasterTableView() {
|
|
guard !isSearching else { return }
|
|
attendeeList = viewModel.attendeeList
|
|
transferMasterTableView.reloadData()
|
|
}
|
|
|
|
func searchControllerChangeActive(isActive: Bool) {
|
|
searchBar.endEditing(!isActive)
|
|
if #available(iOS 13, *) {
|
|
searchBar.searchTextField.resignFirstResponder()
|
|
} else {
|
|
searchBar.resignFirstResponder()
|
|
}
|
|
}
|
|
}
|
|
|
|
class TransferMasterTableCell: UITableViewCell {
|
|
let attendeeModel: UserEntity
|
|
let viewModel: TransferMasterViewModel
|
|
|
|
let avatarImageView: UIImageView = {
|
|
let img = UIImageView()
|
|
img.layer.cornerRadius = 20
|
|
img.layer.masksToBounds = true
|
|
return img
|
|
}()
|
|
|
|
let userLabel: UILabel = {
|
|
let label = UILabel()
|
|
label.textColor = UIColor(0xD5E0F2)
|
|
label.backgroundColor = UIColor.clear
|
|
label.textAlignment = isRTL ? .right : .left
|
|
label.textAlignment = .left
|
|
label.font = UIFont(name: "PingFangSC-Regular", size: 16)
|
|
label.numberOfLines = 1
|
|
return label
|
|
}()
|
|
|
|
let checkMarkButton: UIButton = {
|
|
let button = UIButton(type: .custom)
|
|
button.setImage(UIImage(named: "room_check_mark", in: tuiRoomKitBundle(), compatibleWith: nil), for: .normal)
|
|
button.isHidden = true
|
|
return button
|
|
}()
|
|
|
|
let downLineView : UIView = {
|
|
let view = UIView()
|
|
view.backgroundColor = UIColor(0x2A2D38)
|
|
return view
|
|
}()
|
|
|
|
init(attendeeModel: UserEntity ,viewModel: TransferMasterViewModel) {
|
|
self.attendeeModel = attendeeModel
|
|
self.viewModel = viewModel
|
|
super.init(style: .default, reuseIdentifier: "TransferMasterTableCell")
|
|
}
|
|
|
|
private var isViewReady: Bool = false
|
|
override func didMoveToWindow() {
|
|
super.didMoveToWindow()
|
|
guard !isViewReady else { return }
|
|
constructViewHierarchy()
|
|
activateConstraints()
|
|
bindInteraction()
|
|
isViewReady = true
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func constructViewHierarchy() {
|
|
contentView.addSubview(avatarImageView)
|
|
contentView.addSubview(userLabel)
|
|
contentView.addSubview(checkMarkButton)
|
|
contentView.addSubview(downLineView)
|
|
}
|
|
|
|
func activateConstraints() {
|
|
avatarImageView.snp.makeConstraints { make in
|
|
make.width.height.equalTo(40.scale375Height())
|
|
make.leading.equalToSuperview()
|
|
make.centerY.equalToSuperview()
|
|
}
|
|
checkMarkButton.snp.makeConstraints { make in
|
|
make.width.height.equalTo(22.scale375())
|
|
make.trailing.equalToSuperview()
|
|
make.centerY.equalTo(self.avatarImageView)
|
|
}
|
|
userLabel.snp.makeConstraints { make in
|
|
make.centerY.equalToSuperview()
|
|
make.leading.equalTo(avatarImageView.snp.trailing).offset(10.scale375())
|
|
make.width.equalTo(150.scale375())
|
|
make.height.equalTo(22.scale375Height())
|
|
}
|
|
downLineView.snp.makeConstraints { make in
|
|
make.leading.equalTo(userLabel)
|
|
make.trailing.equalToSuperview()
|
|
make.bottom.equalToSuperview()
|
|
make.height.equalTo(1.scale375Height())
|
|
}
|
|
}
|
|
|
|
func bindInteraction() {
|
|
backgroundColor = UIColor(0x1B1E26)
|
|
setupViewState(item: attendeeModel)
|
|
}
|
|
|
|
func setupViewState(item: UserEntity) {
|
|
let placeholder = UIImage(named: "room_default_user", in: tuiRoomKitBundle(), compatibleWith: nil)
|
|
if let url = URL(string: item.avatarUrl) {
|
|
avatarImageView.sd_setImage(with: url, placeholderImage: placeholder)
|
|
} else {
|
|
avatarImageView.image = placeholder
|
|
}
|
|
userLabel.text = item.userName
|
|
if viewModel.userId == attendeeModel.userId {
|
|
checkMarkButton.isHidden = false
|
|
}
|
|
}
|
|
|
|
deinit {
|
|
debugPrint("deinit \(self)")
|
|
}
|
|
}
|
|
|
|
private extension String {
|
|
static var transferMasterText: String {
|
|
localized("Appoint a new master")
|
|
}
|
|
static var searchMemberText: String {
|
|
localized("Search for participants")
|
|
}
|
|
static var appointAndLeaveRoomText: String {
|
|
localized("Appoint and leave")
|
|
}
|
|
}
|