ConferenceListCell.swift 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. //
  2. // ConferenceOptionCell.swift
  3. // TUIRoomKit
  4. //
  5. // Created by CY zhao on 2024/6/6.
  6. //
  7. import Foundation
  8. import UIKit
  9. import Factory
  10. class ConferenceListCell: UITableViewCell {
  11. @Injected(\.conferenceStore) private var store
  12. @Injected(\.conferenceMainViewStore) private var viewStore
  13. static let reusedIdentifier = "ConferenceListCell"
  14. private var conferenceInfo: ConferenceInfo?
  15. let roomNameLabel: UILabel = {
  16. let label = UILabel(frame: .zero)
  17. label.font = UIFont(name: "PingFangSC-Medium", size: 16)
  18. label.textColor = UIColor.tui_color(withHex: "4F586B")
  19. return label
  20. }()
  21. let interactiveIcon: UIImageView = {
  22. let image = UIImage(named: "room_right_black_arrow", in: tuiRoomKitBundle(), compatibleWith: nil)
  23. let imageView = UIImageView(image: image)
  24. return imageView
  25. }()
  26. let detailLabel: UILabel = {
  27. let label = UILabel(frame: .zero)
  28. return label
  29. }()
  30. let enterButton: UIButton = {
  31. let button = UIButton(type: .custom)
  32. button.setTitle(.enterText, for: .normal)
  33. button.setTitleColor(UIColor.tui_color(withHex: "#4E5461"), for: .normal)
  34. button.titleLabel?.font = UIFont(name: "PingFangSC-Medium", size: 14)
  35. button.backgroundColor = UIColor.tui_color(withHex: "F0F3FA")
  36. button.sizeToFit()
  37. button.layer.cornerRadius = button.frame.height / 2
  38. return button
  39. }()
  40. override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  41. super.init(style: style, reuseIdentifier: reuseIdentifier)
  42. selectionStyle = .none
  43. backgroundColor = .clear
  44. }
  45. required init?(coder: NSCoder) {
  46. fatalError("init(coder:) has not been implemented")
  47. }
  48. private var isViewReady = false
  49. override func didMoveToWindow() {
  50. super.didMoveToWindow()
  51. guard !isViewReady else {
  52. return
  53. }
  54. isViewReady = true
  55. constructViewHierarchy()
  56. activateConstraints()
  57. bindInteraction()
  58. }
  59. private func constructViewHierarchy() {
  60. contentView.addSubview(roomNameLabel)
  61. contentView.addSubview(interactiveIcon)
  62. contentView.addSubview(detailLabel)
  63. contentView.addSubview(enterButton)
  64. }
  65. private func activateConstraints() {
  66. enterButton.snp.makeConstraints { make in
  67. make.trailing.equalToSuperview()
  68. make.width.greaterThanOrEqualTo(68)
  69. make.top.equalToSuperview().offset(8)
  70. }
  71. interactiveIcon.snp.makeConstraints { make in
  72. make.trailing.lessThanOrEqualTo(enterButton.snp.leading).offset(-5)
  73. make.width.height.equalTo(16)
  74. make.centerY.equalTo(roomNameLabel)
  75. }
  76. roomNameLabel.snp.makeConstraints { make in
  77. make.trailing.equalTo(interactiveIcon.snp.leading)
  78. make.leading.equalToSuperview()
  79. make.top.equalToSuperview()
  80. }
  81. detailLabel.snp.makeConstraints { make in
  82. make.leading.equalToSuperview()
  83. make.top.equalTo(roomNameLabel.snp.bottom).offset(6)
  84. make.trailing.lessThanOrEqualTo(enterButton.snp.leading).offset(-20)
  85. }
  86. }
  87. private func bindInteraction() {
  88. enterButton.addTarget(self, action: #selector(enterAction(sender:)), for: .touchUpInside)
  89. }
  90. @objc func enterAction(sender: UIButton) {
  91. guard let info = conferenceInfo else {
  92. return
  93. }
  94. if !info.basicInfo.roomId.isEmpty {
  95. store.dispatch(action: RoomActions.joinConference(payload: info.basicInfo.roomId))
  96. store.dispatch(action: ScheduleViewActions.popDetailView())
  97. viewStore.updateInternalCreation(isInternalCreation: true)
  98. }
  99. }
  100. func updateCell(with info: ConferenceInfo) {
  101. conferenceInfo = info
  102. roomNameLabel.text = info.basicInfo.name
  103. detailLabel.attributedText = getAttributedText(from: info)
  104. }
  105. private func getAttributedText(from info: ConferenceInfo) -> NSMutableAttributedString {
  106. let normalAttributes: [NSAttributedString.Key: Any] =
  107. [.font: UIFont.systemFont(ofSize: 14), .foregroundColor: UIColor.tui_color(withHex: "4F586B")]
  108. let duration = getDuration(from: info)
  109. var result = NSMutableAttributedString(string: duration, attributes: normalAttributes)
  110. addDelimiter(to: &result)
  111. let roomId = addSpaces(to: info.basicInfo.roomId)
  112. let roomIdAtrributeString = NSMutableAttributedString(string: roomId, attributes: normalAttributes)
  113. result.append(roomIdAtrributeString)
  114. guard info.status == .running else { return result }
  115. addDelimiter(to: &result)
  116. let status = getStatusString(from: info)
  117. let statusAttributes: [NSAttributedString.Key: Any] =
  118. [.font:UIFont.systemFont(ofSize: 14), .foregroundColor: UIColor.tui_color(withHex: "1C66E5")]
  119. let statusAtrributeString = NSMutableAttributedString(string: status, attributes: statusAttributes)
  120. result.append(statusAtrributeString)
  121. return result
  122. }
  123. private func addDelimiter(to attributeString: inout NSMutableAttributedString) {
  124. let delimiterAtrributeString = NSMutableAttributedString(string:" | ",
  125. attributes: [
  126. .font: UIFont.systemFont(ofSize: 11),
  127. .foregroundColor: UIColor.tui_color(withHex: "969EB4"),
  128. .baselineOffset: 2
  129. ])
  130. attributeString.append(delimiterAtrributeString)
  131. }
  132. private func addSpaces(to string: String) -> String {
  133. var result = ""
  134. for (index, char) in string.enumerated() {
  135. if index > 0 && index % 3 == 0 {
  136. result += " "
  137. }
  138. result += String(char)
  139. }
  140. return result
  141. }
  142. private func getDuration(from info: ConferenceInfo) -> String {
  143. let dateFormatter = DateFormatter()
  144. dateFormatter.locale = Locale(identifier: "en_US_POSIX")
  145. dateFormatter.timeZone = .current
  146. dateFormatter.dateFormat = "HH:mm"
  147. let startDate = Date(timeIntervalSince1970: TimeInterval(info.scheduleStartTime))
  148. let endDate = Date(timeIntervalSince1970: TimeInterval(info.scheduleEndTime))
  149. let startString = dateFormatter.string(from: startDate)
  150. let endString = dateFormatter.string(from: endDate)
  151. return startString + " - " + endString
  152. }
  153. private func getStatusString(from info: ConferenceInfo) -> String {
  154. if info.status == .running {
  155. return .inProgressText
  156. }
  157. return ""
  158. }
  159. }
  160. private extension String {
  161. static var enterText: String {
  162. localized("Enter")
  163. }
  164. static var inProgressText: String {
  165. localized("Ongoing")
  166. }
  167. }