LNMineUserInfoView.swift 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. //
  2. // LNMineUserInfoView.swift
  3. // Lanu
  4. //
  5. // Created by OneeChan on 2025/12/19.
  6. //
  7. import Foundation
  8. import UIKit
  9. import SnapKit
  10. class LNMineUserInfoView: UIView {
  11. private let avatar = UIImageView()
  12. private let nameLabel = UILabel()
  13. private let idLabel = UILabel()
  14. private let fansCountLabel = UILabel()
  15. private let followCountLabel = UILabel()
  16. private let visitorCountLabel = UILabel()
  17. override init(frame: CGRect) {
  18. super.init(frame: frame)
  19. setupViews()
  20. LNEventDeliver.addObserver(self)
  21. onUserInfoChanged(userInfo: myUserInfo)
  22. onMyRelationInfoChanged()
  23. }
  24. required init?(coder: NSCoder) {
  25. fatalError("init(coder:) has not been implemented")
  26. }
  27. }
  28. extension LNMineUserInfoView: LNProfileManagerNotify, LNRelationManagerNotify {
  29. func onUserInfoChanged(userInfo: LNUserProfileVO) {
  30. guard userInfo.userNo.isMyUid else { return }
  31. avatar.showAvatar(userInfo.avatar)
  32. nameLabel.text = userInfo.nickname
  33. idLabel.text = userInfo.userNo
  34. }
  35. func onMyRelationInfoChanged() {
  36. fansCountLabel.text = "\(myRelationInfo.fansCount)"
  37. followCountLabel.text = "\(myRelationInfo.followCount)"
  38. visitorCountLabel.text = "\(myRelationInfo.visitCount)"
  39. }
  40. }
  41. extension LNMineUserInfoView {
  42. private func setupViews() {
  43. let container = UIView()
  44. container.backgroundColor = .fill
  45. container.layer.cornerRadius = 12
  46. addSubview(container)
  47. container.snp.makeConstraints { make in
  48. make.horizontalEdges.equalToSuperview()
  49. make.bottom.equalToSuperview()
  50. make.top.equalToSuperview().offset(16)
  51. }
  52. let home = UIImageView()
  53. home.image = .icMineHome
  54. home.onTap { [weak self] in
  55. guard let self else { return }
  56. pushToProfile(uid: myUid)
  57. }
  58. container.addSubview(home)
  59. home.snp.makeConstraints { make in
  60. make.top.trailing.equalToSuperview()
  61. make.size.equalTo(home.image?.size ?? .zero)
  62. }
  63. let avatar = buildAvatar()
  64. addSubview(avatar)
  65. avatar.snp.makeConstraints { make in
  66. make.leading.equalToSuperview().offset(16)
  67. make.top.equalToSuperview()
  68. }
  69. let userInfo = buildUserInfo()
  70. container.addSubview(userInfo)
  71. userInfo.snp.makeConstraints { make in
  72. make.leading.equalTo(avatar.snp.trailing).offset(10)
  73. make.bottom.equalTo(avatar)
  74. make.trailing.equalTo(home.snp.leading).offset(6)
  75. }
  76. let relation = buildRelation()
  77. container.addSubview(relation)
  78. relation.snp.makeConstraints { make in
  79. make.horizontalEdges.equalToSuperview().inset(16)
  80. make.bottom.equalToSuperview().offset(-16)
  81. make.top.equalTo(userInfo.snp.bottom).offset(16)
  82. }
  83. }
  84. private func buildAvatar() -> UIView {
  85. avatar.layer.cornerRadius = 35
  86. avatar.layer.borderWidth = 2
  87. avatar.layer.borderColor = UIColor.fill.cgColor
  88. avatar.backgroundColor = .fill
  89. avatar.clipsToBounds = true
  90. avatar.contentMode = .scaleAspectFill
  91. avatar.onTap { [weak self] in
  92. guard let self else { return }
  93. pushToProfile(uid: myUid)
  94. }
  95. avatar.snp.makeConstraints { make in
  96. make.width.height.equalTo(70)
  97. }
  98. return avatar
  99. }
  100. private func buildRelation() -> UIView {
  101. let stackView = UIStackView()
  102. stackView.axis = .horizontal
  103. stackView.spacing = 16
  104. stackView.distribution = .fillEqually
  105. let followView = buildUserCountView(title: .init(key: "A00213"), countLabel: followCountLabel)
  106. followView.onTap { [weak self] in
  107. guard let self else { return }
  108. pushToRelationList(uid: myUid, tabType: .follow)
  109. }
  110. stackView.addArrangedSubview(followView)
  111. let line1 = buildLine()
  112. stackView.addSubview(line1)
  113. line1.snp.makeConstraints { make in
  114. make.centerY.equalToSuperview()
  115. make.centerX.equalTo(followView.snp.trailing)
  116. }
  117. let fansView = buildUserCountView(title: .init(key: "A00214"), countLabel: fansCountLabel)
  118. fansView.onTap { [weak self] in
  119. guard let self else { return }
  120. pushToRelationList(uid: myUid, tabType: .fans)
  121. }
  122. stackView.addArrangedSubview(fansView)
  123. let line2 = buildLine()
  124. stackView.addSubview(line2)
  125. line2.snp.makeConstraints { make in
  126. make.centerY.equalToSuperview()
  127. make.centerX.equalTo(fansView.snp.trailing)
  128. }
  129. let visitorView = buildUserCountView(title: .init(key: "B00109"), countLabel: visitorCountLabel)
  130. visitorView.onTap { [weak self] in
  131. guard let self else { return }
  132. pushToVisitors()
  133. }
  134. stackView.addArrangedSubview(visitorView)
  135. return stackView
  136. }
  137. private func buildUserCountView(title: String, countLabel: UILabel) -> UIView {
  138. let container = UIView()
  139. countLabel.font = .heading_h2
  140. countLabel.textColor = .text_5
  141. container.addSubview(countLabel)
  142. countLabel.snp.makeConstraints { make in
  143. make.centerX.equalToSuperview()
  144. make.leading.greaterThanOrEqualToSuperview()
  145. make.top.equalToSuperview()
  146. }
  147. let textLabel = UILabel()
  148. textLabel.text = title
  149. textLabel.font = .body_s
  150. textLabel.textColor = .text_3
  151. textLabel.textAlignment = .center
  152. container.addSubview(textLabel)
  153. textLabel.snp.makeConstraints { make in
  154. make.horizontalEdges.equalToSuperview()
  155. make.bottom.equalToSuperview()
  156. make.top.equalTo(countLabel.snp.bottom).offset(2)
  157. }
  158. return container
  159. }
  160. private func buildLine() -> UIView {
  161. let line = UIView()
  162. line.backgroundColor = .init(hex: "#D9D9D9")
  163. line.snp.makeConstraints { make in
  164. make.width.equalTo(1)
  165. make.height.equalTo(22)
  166. }
  167. return line
  168. }
  169. private func buildUserInfo() -> UIView {
  170. let container = UIView()
  171. nameLabel.font = .heading_h1_5
  172. nameLabel.textColor = .text_5
  173. container.addSubview(nameLabel)
  174. nameLabel.snp.makeConstraints { make in
  175. make.horizontalEdges.equalToSuperview()
  176. make.top.equalToSuperview()
  177. }
  178. let ID = UILabel()
  179. ID.text = .init(key: "ID")
  180. ID.font = .heading_h5
  181. ID.textColor = .text_3
  182. container.addSubview(ID)
  183. ID.snp.makeConstraints { make in
  184. make.leading.bottom.equalToSuperview()
  185. make.top.equalTo(nameLabel.snp.bottom).offset(2)
  186. }
  187. idLabel.font = .body_xs
  188. idLabel.textColor = .text_4
  189. container.addSubview(idLabel)
  190. idLabel.snp.makeConstraints { make in
  191. make.leading.equalTo(ID.snp.trailing).offset(4)
  192. make.centerY.equalTo(ID)
  193. }
  194. let copyButton = UIButton()
  195. copyButton.setImage(.icCopyLeft, for: .normal)
  196. copyButton.addAction(UIAction(handler: { _ in
  197. let pasteboard = UIPasteboard.general
  198. pasteboard.string = myUid
  199. showToast(.init(key: "A00047"))
  200. }), for: .touchUpInside)
  201. container.addSubview(copyButton)
  202. copyButton.snp.makeConstraints { make in
  203. make.leading.equalTo(idLabel.snp.trailing).offset(4)
  204. make.centerY.equalTo(ID)
  205. make.trailing.lessThanOrEqualToSuperview()
  206. }
  207. return container
  208. }
  209. }
  210. #if DEBUG
  211. import SwiftUI
  212. struct LNMineUserInfoViewPreview: UIViewRepresentable {
  213. func makeUIView(context: Context) -> some UIView {
  214. let container = UIView()
  215. container.backgroundColor = .lightGray
  216. let view = LNMineUserInfoView()
  217. container.addSubview(view)
  218. view.snp.makeConstraints { make in
  219. make.leading.trailing.centerY.equalToSuperview()
  220. }
  221. return container
  222. }
  223. func updateUIView(_ uiView: UIViewType, context: Context) { }
  224. }
  225. #Preview(body: {
  226. LNMineUserInfoViewPreview()
  227. })
  228. #endif