// // MeHeaderView.swift // Crush // // Created by Leon on 2025/7/22. // import UIKit import Combine class MeHeaderView: UICollectionReusableView { var avatarView: AvatarView! // var avatarTopButton: UIButton! // name row: var namesStackH: UIStackView! var nameLabel: UILabel! var sexIcon: UIImageView! // another row: var idStackH: UIStackView! var idLabel: UILabel! var copyIcon: UIImageView! var copyBtn: UIButton! // entrances row: var entrancesBlock: UIView! var entrancesStackH: UIStackView! var entrance1: UIButton! var entrance2: UIButton! var entrance3: UIButton! var sectionTitle: UILabel! var gradientBorderContainer: GradientBorderView! var gradientLabel: ColorLabel! var unlockVipButton:UIButton! var heightChangeBlock: ((CGFloat) -> Void)? private var cancellables = Set() override init(frame: CGRect) { super.init(frame: frame) setupViews() setupData() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupViews() { avatarView = { let view = AvatarView() // view.contentMode = .scaleAspectFill // view.layer.cornerRadius = 40 // view.layer.masksToBounds = true // view.backgroundColor = .c.csbn addSubview(view) view.snp.makeConstraints { make in make.width.height.equalTo(80) make.top.equalToSuperview().offset(0) make.centerX.equalToSuperview() } return view }() // avatarTopButton = { // let v = UIButton() // addSubview(v) // v.snp.makeConstraints { make in // make.edges.equalTo(avatarView) // } // return v // }() namesStackH = { let view = UIStackView() view.axis = .horizontal view.spacing = 8 view.alignment = .center addSubview(view) view.snp.makeConstraints { make in make.top.equalTo(avatarView.snp.bottom).offset(8) make.centerX.equalToSuperview() make.leading.greaterThanOrEqualToSuperview().offset(CGFloat.lrs) make.trailing.lessThanOrEqualToSuperview().offset(-CGFloat.lrs) } return view }() nameLabel = { let view = UILabel() view.font = .t.thm view.textColor = .c.ctpn view.textAlignment = .left view.numberOfLines = 1 view.lineBreakMode = .byTruncatingTail view.setContentHuggingPriority(.required, for: .horizontal) view.setContentCompressionResistancePriority(.required, for: .horizontal) namesStackH.addArrangedSubview(view) return view }() sexIcon = { let view = UIImageView() view.contentMode = .scaleAspectFit view.image = UIImage(named: "sex_male_flag") namesStackH.addArrangedSubview(view) view.snp.makeConstraints { make in make.width.height.equalTo(24) } return view }() idStackH = { let view = UIStackView() view.axis = .horizontal view.spacing = 8 view.alignment = .center addSubview(view) view.snp.makeConstraints { make in make.top.equalTo(namesStackH.snp.bottom).offset(8) make.centerX.equalToSuperview() make.leading.greaterThanOrEqualToSuperview().offset(CGFloat.lrs) make.trailing.lessThanOrEqualToSuperview().offset(-CGFloat.lrs) } return view }() idLabel = { let view = UILabel() view.font = .t.tbs view.textColor = .c.ctsn view.textAlignment = .left view.numberOfLines = 1 view.lineBreakMode = .byTruncatingTail idStackH.addArrangedSubview(view) return view }() copyIcon = { let view = UIImageView() view.contentMode = .scaleAspectFit view.image = MWIconFont.image(fromIcon: .copy, size: .init(width: 12, height: 12), color: .c.ctsn) idStackH.addArrangedSubview(view) return view }() copyBtn = { let view = UIButton() view.setImage(UIImage(named: "copy_icon"), for: .normal) view.addTarget(self, action: #selector(copyBtnAction), for: .touchUpInside) addSubview(view) view.snp.makeConstraints { make in make.height.equalTo(24) make.centerY.equalTo(idStackH) make.leading.equalTo(idStackH) make.trailing.equalTo(idStackH) } return view }() entrancesBlock = { let view = UIView() view.backgroundColor = .c.csbn view.layer.cornerRadius = 16 view.layer.masksToBounds = true addSubview(view) view.snp.makeConstraints { make in make.top.equalTo(idStackH.snp.bottom).offset(24) make.leading.equalToSuperview().offset(CGFloat.lrs) make.trailing.equalToSuperview().offset(-CGFloat.lrs) } return view }() entrancesStackH = { let view = UIStackView() view.axis = .horizontal view.spacing = 8 view.alignment = .center view.distribution = .fillEqually entrancesBlock.addSubview(view) view.snp.makeConstraints { make in make.top.equalToSuperview().offset(16) make.leading.equalToSuperview().offset(16) make.trailing.equalToSuperview().offset(-16) make.bottom.equalToSuperview().offset(-16) make.height.equalTo(68) } return view }() entrance1 = { let view = UIButton() view.titleLabel?.font = UIFont.t.tls view.setImage(UIImage(named: "me_header_membership"), for: .normal) view.setTitle("Membership", for: .normal) view.addTarget(self, action: #selector(entrance1Action), for: .touchUpInside) entrancesStackH.addArrangedSubview(view) return view }() entrance2 = { let view = UIButton() view.titleLabel?.font = UIFont.t.tls view.setImage(UIImage(named: "me_header_diamonds"), for: .normal) view.setTitle("Diamonds", for: .normal) view.addTarget(self, action: #selector(entrance2Action), for: .touchUpInside) entrancesStackH.addArrangedSubview(view) return view }() entrance3 = { let view = UIButton() view.titleLabel?.font = .t.tls view.setImage(UIImage(named: "me_header_creator"), for: .normal) view.setTitle("Creator", for: .normal) view.addTarget(self, action: #selector(entrance3Action), for: .touchUpInside) entrancesStackH.addArrangedSubview(view) return view }() sectionTitle = { let view = UILabel() view.font = .t.ttm view.textColor = .c.ctpn view.textAlignment = .left view.numberOfLines = 1 addSubview(view) view.snp.makeConstraints { make in make.top.equalTo(entrancesBlock.snp.bottom).offset(24) make.leading.equalToSuperview().offset(CGFloat.lrs) make.trailing.equalToSuperview().offset(-CGFloat.lrs) // make.bottom.equalToSuperview().offset(-24) } return view }() gradientBorderContainer = { let gradient = CLSystemToken.gradient(token: .ccvn) let v = GradientBorderView(colors: gradient.colors(), gradientType: .leftToRight) v.gBorderWidth = 1 v.layer.cornerRadius = 16 v.layer.masksToBounds = true v.backgroundColor = .clear addSubview(v) v.snp.makeConstraints { make in make.height.equalTo(32) make.trailing.equalToSuperview().offset(-CGFloat.lrs) make.centerY.equalTo(sectionTitle) } return v }() let vipItemsStackH = { let v = UIStackView() v.spacing = 4 gradientBorderContainer.addSubview(v) v.snp.makeConstraints { make in make.centerY.equalToSuperview() make.leading.equalToSuperview().offset(16) make.trailing.equalToSuperview().offset(-16) } return v }() let tipIcon = { let v = UIImageView() v.image = UIImage(named: "vip_flag_16") vipItemsStackH.addArrangedSubview(v) return v }() tipIcon.isHidden = false gradientLabel = { let v = ColorLabel() v.applyGradient(.vip) v.font = .t.tls // v.textAlignment = .center vipItemsStackH.addArrangedSubview(v) return v }() unlockVipButton = { let v = UIButton() v.addTarget(self, action: #selector(tapUnlockVIP), for: .touchUpInside) gradientBorderContainer.addSubview(v) v.snp.makeConstraints { make in make.edges.equalToSuperview() } return v }() nameLabel.text = "nickname" idLabel.text = "idxxxxx" sectionTitle.text = "Characters 0/3" gradientLabel.text = "Unlock More" } private func setupData(){ UserCore.shared.$user.sink {[weak self] user in self?.nameLabel.text = user?.nickname //self?.avatarView.loadImage(user?.headImage) self?.avatarView.bindImageUrl(imgUrl: user?.headImage) self?.sexIcon.image = user?.sex.icon self?.idLabel.text = "ID: \(user?.idCard ?? "-")" self?.setupRoleCount(valid: user?.createdAiCount ?? 0, total: user?.canCreateAiCount ?? 0) self?.gradientBorderContainer.isHidden = user?.isMember ?? false }.store(in: &cancellables) } public func setupRoleCount(valid:Int, total:Int){ sectionTitle.text = "Characters \(valid)/\(total)" } // MARK: - Action @objc private func copyBtnAction() { // copy idLabel's content to clipboard if let idcard = UserCore.shared.user?.idCard, idcard.count > 0{ UIPasteboard.general.string = idcard Hud.toast(str: "Copy Successfully") } } @objc private func entrance1Action() { AppRouter.goVIPCenter() } @objc private func entrance2Action() { AppRouter.goWalletCenter() } @objc private func entrance3Action() { AppRouter.goCreatorIntroduction() } @objc private func tapUnlockVIP(){ //AppRouter.goVIPCenter() CLPurchase.shared.showVIPSubscribeSheet() } override func layoutSubviews() { super.layoutSubviews() entrance1.setUp(.top, padding: 8) entrance2.setUp(.top, padding: 8) entrance3.setUp(.top, padding: 8) let maxY = sectionTitle.frame.maxY + 24 heightChangeBlock?(maxY) } }