Visual_Novel_iOS/crush/Crush/Src/Components/UI/Sheet/ChatModePickInsufficientCoi...

304 lines
10 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// ChatModePickInsufficientCoinSheet.swift
// Crush
//
// Created by Leon on 2025/9/23.
//
import UIKit
import Combine
///
class ChatModePickInsufficientCoinSheet: EGPopBaseView {
var closeButton: EPIconTertiaryButton!
var titleLabel: UILabel!
var subTitleLabel: LineSpaceLabel!
//
var scrollView: UIScrollView!
//
var modelCardViews: [ChatModelCardView] = []
var bottomView: UIView!
var balance: CLIconLabel!
var operateButton: StyleButton! // Recharge
//
private var chatModels: [AIChatModel] = []
private var currentSelectedModelCode: String?
var cardHeight = 168.0
//
var selectionCallback: ChatModelSelectionCallback?
private var cancellables = Set<AnyCancellable>()
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init(currentSelectedModelCode: String? = nil) {
self.currentSelectedModelCode = currentSelectedModelCode
super.init(direction: .bottom)
contentView.backgroundColor = .c.csbn
//
contentLength = 200 + UIWindow.safeAreaBottom
setupViews()
setupDatas()
setupEvent()
}
private func setupViews() {
closeButton = {
let v = EPIconTertiaryButton(radius: .round, iconSize: .small, iconCode: .delete)
v.addTarget(self, action: #selector(bgButtonPressed), for: .touchUpInside)
contentView.addSubview(v)
v.snp.makeConstraints { make in
make.top.equalToSuperview().offset(20)
make.size.equalTo(v.bgImageSize())
make.trailing.equalToSuperview().offset(-16)
}
return v
}()
titleLabel = {
let v = UILabel()
v.font = .t.ttm
v.textColor = .text
v.textAlignment = .center
contentView.addSubview(v)
v.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(24)
make.trailing.equalToSuperview().offset(-24)
make.top.equalToSuperview().offset(32)
}
return v
}()
subTitleLabel = {
let v = LineSpaceLabel()
let typo = CLSystemToken.typography(token: .tbs)
v.config(typo)
v.textColor = .c.ctpn
contentView.addSubview(v)
v.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(24)
make.leading.equalToSuperview().offset(CGFloat.lrs)
make.trailing.equalToSuperview().offset(-CGFloat.lrs)
}
return v
}()
scrollView = {
let v = UIScrollView()
v.showsVerticalScrollIndicator = false
v.showsHorizontalScrollIndicator = false
contentView.addSubview(v)
v.snp.makeConstraints { make in
make.leading.equalToSuperview()
make.trailing.equalToSuperview()
make.top.equalTo(subTitleLabel.snp.bottom).offset(16) // 24
make.height.equalTo(cardHeight) //
}
return v
}()
bottomView = {
let v = UIView()
contentView.addSubview(v)
v.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-UIWindow.safeAreaBottom)
make.leading.trailing.equalToSuperview()
make.height.equalTo(80)
}
return v
}()
balance = {
let v = CLIconLabel()
v.iconSize = CGSize(width: 16, height: 16)
v.iconImageView.image = .icon16Diamond
v.contentLabel.textColor = .white
v.contentLabel.font = .t.tlm
bottomView.addSubview(v)
v.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.leading.equalToSuperview().offset(24)
}
return v
}()
operateButton = {
let v = StyleButton()
v.primary(size: .large)
v.addTarget(self, action: #selector(operateButtonTapped), for: .touchUpInside)
bottomView.addSubview(v)
v.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.trailing.equalToSuperview().offset(-24)
make.leading.greaterThanOrEqualTo(balance.snp.trailing).offset(48)
}
return v
}()
titleLabel.text = "Dialog Model"
subTitleLabel.text = "The Crush coin is insufficient and cannot continue to send messages. The charging standard of the current model"
operateButton.setTitle("Recharge", for: .normal)
}
private func setupDatas(){
// let group = DispatchGroup()
//
// group.enter()
loadChatModels {
// group.leave()
}
// group.enter()
// loadChatSetting {
// group.leave()
// }
//
// group.notify(queue: .main) {[weak self] in
// self?.setupModelCards()
// }
}
private func setupEvent(){
WalletCore.shared.$balance.sink {[weak self] balance in
if let priceLabel = self?.balance {
priceLabel.contentLabel.text = balance.displayBalance()
}
}.store(in: &cancellables)
}
private func loadChatModels(completion:(()->Void)? = nil) {
guard let models = AppDictManager.shared.chatModels, models.count > 0 else {
//
AppDictManager.shared.loadChatModelDict { [weak self] success in
if success {
self?.loadChatModels()
}
}
return
}
chatModels = models
setupModelCards()
completion?()
}
private func setupModelCards() {
//
modelCardViews.forEach { $0.removeFromSuperview() }
modelCardViews.removeAll()
//
for (index, model) in chatModels.enumerated() {
let cardView = ChatModelCardView()
cardView.configure(with: model, isSelected: model.code == currentSelectedModelCode)
cardView.tag = index
cardView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(modelCardTapped(_:))))
scrollView.addSubview(cardView)
modelCardViews.append(cardView)
cardView.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview()
make.width.equalTo(scrollView.snp.width)
make.height.equalTo(cardHeight) //
if index == 0 {
make.top.equalToSuperview()
} else {
make.top.equalTo(modelCardViews[index - 1].snp.bottom).offset(12)
}
if index == chatModels.count - 1 {
make.bottom.equalToSuperview()
}
}
}
// contentLength
updateContentLength()
//
// DispatchQueue.main.async { [weak self] in
// self?.scrollToSelectedModel()
// }
}
private func updateContentLength() {
let subTitleHeight = subTitleLabel.sizeThatFits(CGSize(width: UIScreen.width - CGFloat.lrs*2, height: CGFLOAT_MAX)).height
//dlog(" \(subTitleHeight)")
// + +
let baseHeight: CGFloat = 80 + subTitleHeight + 80 + 16// titleLabel top + spacing + stayTunedLabel + bottom margin
// 200 + 12
let cardHeight: CGFloat = cardHeight
let cardSpacing: CGFloat = 12
let totalCardHeight = CGFloat(chatModels.count) * cardHeight + CGFloat(max(0, chatModels.count - 1)) * cardSpacing
// 2
let maxVisibleHeight = min(totalCardHeight, cardHeight * 2 + cardSpacing)
// scrollView
scrollView.snp.updateConstraints { make in
make.height.equalTo(maxVisibleHeight)
}
// contentLength
contentLength = baseHeight + maxVisibleHeight + UIWindow.safeAreaBottom
//
layoutIfNeeded()
}
// MARK: - Function
private func scrollToSelectedModel() {
guard let selectedCode = currentSelectedModelCode,
let selectedIndex = chatModels.firstIndex(where: { $0.code == selectedCode }),
selectedIndex < chatModels.count else { return }
// scrollViewframe
guard scrollView.frame.height > 0 else {
// frame
DispatchQueue.main.async { [weak self] in
self?.scrollToSelectedModel()
}
return
}
let offsetY = CGFloat(selectedIndex) * (cardHeight + 12) // +
scrollView.setContentOffset(CGPoint(x: 0, y: offsetY), animated: false)
}
// MARK: - Action
@objc private func modelCardTapped(_ gesture: UITapGestureRecognizer) {
guard let cardView = gesture.view as? ChatModelCardView,
let index = modelCardViews.firstIndex(of: cardView),
index < chatModels.count else { return }
let selectedModel = chatModels[index]
modelCardViews.forEach { $0.setSelected(false) }
cardView.setSelected(true)
//
selectionCallback?(selectedModel)
IMAIViewModel.shared.updateChatModel(code: selectedModel.code, completion: nil)
//
dismiss()
}
@objc private func operateButtonTapped(){
dismiss()
AppRouter.goWalletCenter()
}
}