Visual_Novel_iOS/crush/Crush/Src/Modules/Me/View/MeRootPageView.swift

358 lines
12 KiB
Swift
Raw Normal View History

2025-10-09 10:29:35 +00:00
//
// 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)
}
}
}