// // MeRootPageView.swift // Crush // // Created by Leon on 2025/7/22. // import UIKit class MeRootPageView: UIView { var headerView: MeHeaderView! var layout: UICollectionViewFlowLayout! var cv: UICollectionView! // Layout var headerHeight: CGFloat = 300 // Data var datas:[AIRoleInfo] = [AIRoleInfo]() var tapAvatarAction : (()-> Void)? override init(frame: CGRect) { super.init(frame: frame) setupViews() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupViews() { cv = { // item's height: w:h = 165:260, + 112 let lr = CGFloat.lrs let itemW = (UIScreen.width - lr * 2 - 16) * 0.5 let itemH = itemW * 260 / 165.0 + 112 layout = UICollectionViewFlowLayout() layout.scrollDirection = .vertical layout.minimumLineSpacing = 0 layout.minimumInteritemSpacing = 16 layout.sectionInset = .init(top: 0, left: lr, bottom: 24 + UIWindow.safeAreaBottom, right: lr) layout.itemSize = .init(width: itemW, height: itemH) layout.headerReferenceSize = .init(width: UIScreen.width, height: headerHeight) let view = UICollectionView(frame: .zero, collectionViewLayout: layout) view.backgroundColor = .clear //.c.cbd view.delegate = self view.dataSource = self view.register(MeRootPageRollCell.self, forCellWithReuseIdentifier: "MeRootPageRollCell") view.register(MeHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "MeHeaderView") addSubview(view) view.snp.makeConstraints { make in make.leading.trailing.equalToSuperview() make.top.equalToSuperview().offset(UIWindow.navBarTotalHeight) make.bottom.equalToSuperview() } return view }() } func config(datas:[AIRoleInfo]?){ guard let roles = datas else{ self.datas = [] setupEmpty(empty: true) return } self.datas = roles setupEmpty(empty: roles.count <= 0) cv.reloadData() } private func setupEmpty(empty: Bool){ if(empty){ showStartYEmpty(text: "No Character Yet", startY: 442 + UIWindow.statusBarHeight) }else{ removeEmpty() } } } extension MeRootPageView: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return self.datas.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MeRootPageRollCell", for: indexPath) as! MeRootPageRollCell cell.cellType = .meRoleList let data = datas[indexPath.item] cell.config(data: data) return cell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let data = datas[indexPath.item] AppRouter.goAIRoleHome(aiId: data.aiId) } func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { if kind == UICollectionView.elementKindSectionHeader { headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "MeHeaderView", for: indexPath) as? MeHeaderView headerView.heightChangeBlock = { [weak self] height in self?.headerHeight = height // dlog("height change :\(height)") self?.layout.headerReferenceSize = .init(width: UIScreen.width, height: height) self?.layout.invalidateLayout() } headerView.avatarView.tapAction = {[weak self] in self?.tapAvatarAction?() } return headerView } return UICollectionReusableView() } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { return .init(width: UIScreen.width, height: headerHeight) } } enum RoleGridCellType { case meRoleList case discoverList } class MeRootPageRollCell: UICollectionViewCell { var bgView: UIView! var gradientBorderView: GradientBorderView! var avatarView: UIImageView! var overlayOnIv: GradientView! var likeIconLabel: CLIconLabel! var seeBanIv: UIImageView! // --- var nameLabel: UILabel! var descLabel: UILabel! // Mobile tags var tagsStackH: UIStackView! var cellType: RoleGridCellType = .meRoleList // Datas var datas: [AIRoleInfo]? override init(frame: CGRect) { super.init(frame: frame) setupViews() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupViews() { bgView = { let v = UIView() v.layer.cornerRadius = 16 v.layer.masksToBounds = true v.backgroundColor = .clear // .c.csbn contentView.addSubview(v) v.snp.makeConstraints { make in make.leading.trailing.equalToSuperview() make.height.equalTo(v.snp.width).multipliedBy(260.0 / 165.0) make.top.equalToSuperview().offset(0) } return v }() gradientBorderView = { let gradient = CLSystemToken.gradient(token: .ccvn) let color1 = gradient.firstColor! let color2 = gradient.secondColor! let v = GradientBorderView(colors: [color1, color2], gradientType: .leftToRight) v.gBorderWidth = 1 v.layer.cornerRadius = 16 v.layer.masksToBounds = true v.backgroundColor = .c.csbn bgView.addSubview(v) v.snp.makeConstraints { make in make.edges.equalToSuperview() } return v }() avatarView = { let v = UIImageView() v.contentMode = .scaleAspectFill v.backgroundColor = .random.withAlphaComponent(0.3) v.layer.cornerRadius = 16 v.layer.masksToBounds = true v.clipsToBounds = true bgView.addSubview(v) v.snp.makeConstraints { make in make.edges.equalToSuperview().inset(UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)) } return v }() overlayOnIv = { let colors = [UIColor.black.withAlphaComponent(0), UIColor.black] let v = GradientView(colors: colors, gradientType: .topToBottom) v.layer.cornerRadius = 16 v.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner] v.layer.masksToBounds = true bgView.addSubview(v) v.snp.makeConstraints { make in make.leading.trailing.equalTo(avatarView) make.bottom.equalTo(avatarView) make.height.equalTo(44) } return v }() likeIconLabel = { let v = CLIconLabel() bgView.addSubview(v) v.iconImageView.image = MWIconFont.image(fromIcon: .like, size: .init(width: 12, height: 12), color: .c.ctpn) v.snp.makeConstraints { make in make.height.equalTo(20) make.leading.equalToSuperview().offset(16) make.bottom.equalToSuperview().offset(-8) } return v }() seeBanIv = { let v = UIImageView() bgView.addSubview(v) v.backgroundColor = .c.csedn v.layer.cornerRadius = 4 v.layer.masksToBounds = true v.contentMode = .center v.image = MWIconFont.image(fromIcon: .eyeOff, size: CGSize(width: 12, height: 12), color: .c.ctpn) v.snp.makeConstraints { make in make.size.equalTo(CGSize(width: 24, height: 24)) make.top.equalToSuperview().offset(8) make.trailing.equalToSuperview().offset(-8) } return v }() nameLabel = { let v = UILabel() v.font = .t.tts v.textColor = .c.ctpn v.textAlignment = .left v.numberOfLines = 1 contentView.addSubview(v) v.snp.makeConstraints { make in make.top.equalTo(bgView.snp.bottom).offset(8) make.leading.equalToSuperview() make.trailing.equalToSuperview() } return v }() descLabel = { let v = UILabel() v.font = .t.tbs v.textColor = .c.ctsn v.textAlignment = .left v.numberOfLines = 2 contentView.addSubview(v) v.snp.makeConstraints { make in make.top.equalTo(nameLabel.snp.bottom).offset(4) make.leading.equalToSuperview() make.trailing.equalToSuperview() } return v }() tagsStackH = { let v = UIStackView() v.axis = .horizontal v.spacing = 8 v.alignment = .center contentView.addSubview(v) v.snp.makeConstraints { make in make.top.equalTo(descLabel.snp.bottom).offset(8) make.leading.equalToSuperview() make.trailing.lessThanOrEqualToSuperview() } return v }() // do { // let tag = RoleTag() // tag.title = "Sensibility" // tag.style = .purple // tagsStackH.addArrangedSubview(tag) // } // // do { // let tag = RoleTag() // tag.title = "Romantic" // tag.style = .theme // tagsStackH.addArrangedSubview(tag) // } // #warning("test data") // testData() } private func testData() { nameLabel.text = "测试数据" avatarView.image = UIImage(named: "eg") descLabel.text = "desc desc desc desc desc desc desc desc" likeIconLabel.contentLabel.text = "11.2k" } public func config(data: AIRoleInfo?){ guard let role = data else {return} // 私密 seeBanIv.isHidden = !(data?.permission == 2) nameLabel.text = role.nickname descLabel.text = role.introduction ?? "" avatarView.loadImage(role.homeImageUrl) let countDisplay = String.displayNumber(NSNumber(value: (data?.likedNum ?? 0)), scale: 1) likeIconLabel.contentLabel.text = countDisplay tagsStackH.removeSubviews() if let characterName = role.characterName{ let tag = RoleTag() tag.title = characterName // if cellType == .meRoleList{ // tag.style = .default // }else{ // tag.style = .blurPurple // } tag.style = .default tagsStackH.addArrangedSubview(tag) } if let tagName = role.tagName{ let tag = RoleTag() tag.title = tagName // if cellType == .meRoleList{ // tag.style = .default // }else{ // tag.style = .blurTheme // } tag.style = .default tagsStackH.addArrangedSubview(tag) } } }