LNIMChatUserMenuView.swift 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. //
  2. // LNIMChatUserMenuView.swift
  3. // Lanu
  4. //
  5. // Created by OneeChan on 2025/12/10.
  6. //
  7. import Foundation
  8. import UIKit
  9. import SnapKit
  10. import Combine
  11. class LNIMChatUserMenuView: LNPopupView {
  12. private let muteSwitch = UISwitch()
  13. private let blackLabel = UILabel()
  14. var viewModel: LNIMChatViewModel? {
  15. didSet {
  16. viewModel?.$messageOpt.sink { [weak self] opt in
  17. guard let self else { return }
  18. muteSwitch.isOn = opt == .RECEIVE_NOT_NOTIFY_MESSAGE
  19. }.store(in: &cancellables)
  20. blackLabel.text = viewModel?.userId.isInMyBlackList != true ? .init(key: "A00044") : .init(key: "A00045")
  21. }
  22. }
  23. override init(frame: CGRect) {
  24. super.init(frame: frame)
  25. setupViews()
  26. }
  27. required init?(coder: NSCoder) {
  28. fatalError("init(coder:) has not been implemented")
  29. }
  30. }
  31. extension LNIMChatUserMenuView {
  32. private func setupViews() {
  33. let stackView = UIStackView()
  34. stackView.axis = .vertical
  35. stackView.spacing = 0
  36. container.addSubview(stackView)
  37. stackView.snp.makeConstraints { make in
  38. make.horizontalEdges.equalToSuperview()
  39. make.top.equalToSuperview().offset(10)
  40. make.bottom.equalToSuperview().offset(commonBottomInset)
  41. }
  42. let menus = [
  43. buildMute(),
  44. buildLine(),
  45. buildRemark(),
  46. buildLine(),
  47. buildBlack(),
  48. buildLine(),
  49. buildReport()]
  50. menus.forEach {
  51. stackView.addArrangedSubview($0)
  52. }
  53. }
  54. private func buildMute() -> UIView {
  55. let scaleX: CGFloat = 40.0 / 51.0
  56. let scaleY: CGFloat = 24.5 / 31.0
  57. muteSwitch.onTintColor = .primary_5
  58. muteSwitch.transform = CGAffineTransform(scaleX: scaleX, y: scaleY)
  59. muteSwitch.addAction(UIAction(handler: { [weak self] _ in
  60. guard let self else { return }
  61. viewModel?.updateMessageOpt(opt: muteSwitch.isOn ? .RECEIVE_NOT_NOTIFY_MESSAGE : .RECEIVE_MESSAGE)
  62. }), for: .valueChanged)
  63. return buildMenuItem(icon: .icImChatMenuMute, title: .init(key: "A00085"), contentView: muteSwitch)
  64. }
  65. private func buildRemark() -> UIView {
  66. let menu = buildMenuItem(icon: .icImChatMenuRemark, title: .init(key: "A00086"), contentView: nil)
  67. menu.onTap { [weak self] in
  68. guard let self else { return }
  69. let panel = LNIMChatUserRemarkPanel()
  70. panel.update(viewModel?.remark ?? "")
  71. panel.handler = { [weak self] remark in
  72. guard let self else { return }
  73. dismiss()
  74. viewModel?.updateRemark(remark)
  75. }
  76. panel.popup()
  77. }
  78. return menu
  79. }
  80. private func buildBlack() -> UIView {
  81. blackLabel.font = .body_m
  82. blackLabel.textColor = .text_5
  83. let menu = buildMenuItem(icon: .icImChatMenuBlack, titleView: blackLabel, contentView: nil)
  84. menu.onTap { [weak self] in
  85. guard let self else { return }
  86. guard let uid = viewModel?.userId else { return }
  87. dismiss()
  88. if viewModel?.userId.isInMyBlackList != true {
  89. LNCommonAlertView.showBlackAlert(uid: uid)
  90. } else {
  91. LNRelationManager.shared.blackListUser(uid: uid, black: false, handler: nil)
  92. }
  93. }
  94. return menu
  95. }
  96. private func buildReport() -> UIView {
  97. let menu = buildMenuItem(icon: .icImChatMenuRemark, title: .init(key: "A00043"), contentView: nil)
  98. menu.onTap { [weak self] in
  99. guard let self else { return }
  100. guard let uid = viewModel?.userId else { return }
  101. dismiss()
  102. pushToReport(uid: uid)
  103. }
  104. return menu
  105. }
  106. private func buildMenuItem(icon: UIImage, title: String, contentView: UIView?) -> UIView {
  107. let titleLabel = UILabel()
  108. titleLabel.text = title
  109. titleLabel.font = .body_m
  110. titleLabel.textColor = .text_5
  111. return buildMenuItem(icon: icon, titleView: titleLabel, contentView: contentView)
  112. }
  113. private func buildMenuItem(icon: UIImage, titleView: UIView, contentView: UIView?) -> UIView {
  114. let container = UIView()
  115. container.snp.makeConstraints { make in
  116. make.height.equalTo(52)
  117. }
  118. let ic = UIImageView()
  119. ic.image = icon
  120. container.addSubview(ic)
  121. ic.snp.makeConstraints { make in
  122. make.leading.equalToSuperview().offset(16)
  123. make.centerY.equalToSuperview()
  124. }
  125. container.addSubview(titleView)
  126. titleView.snp.makeConstraints { make in
  127. make.centerY.equalToSuperview()
  128. make.leading.equalTo(ic.snp.trailing).offset(10)
  129. }
  130. if let contentView {
  131. container.addSubview(contentView)
  132. contentView.snp.makeConstraints { make in
  133. make.centerY.equalToSuperview()
  134. make.trailing.equalToSuperview().offset(-16)
  135. }
  136. } else {
  137. let arrow = UIImageView()
  138. arrow.image = .init(systemName: "chevron.forward")
  139. arrow.tintColor = .text_4
  140. container.addSubview(arrow)
  141. arrow.snp.makeConstraints { make in
  142. make.centerY.equalToSuperview()
  143. make.trailing.equalToSuperview().offset(-16)
  144. }
  145. }
  146. return container
  147. }
  148. private func buildLine() -> UIView {
  149. let container = UIView()
  150. let line = UIView()
  151. line.backgroundColor = .fill_2
  152. container.addSubview(line)
  153. line.snp.makeConstraints { make in
  154. make.verticalEdges.equalToSuperview()
  155. make.height.equalTo(1)
  156. make.horizontalEdges.equalToSuperview().inset(16)
  157. }
  158. return container
  159. }
  160. }