Visual_Novel_iOS/crush/Crush/Src/Modules/Wallet/Sheet/CoinsRechargeSheet.swift

273 lines
9.3 KiB
Swift
Raw Normal View History

2025-10-09 10:29:35 +00:00
//
// CoinsRechargeSheet.swift
// Crush
//
// Created by Leon on 2025/9/16.
//
import UIKit
import Combine
class CoinsRechargeSheet: EGPopBaseView {
var titleLabel: UILabel!
var descLabel: CLLabel!
var closeButton: EPIconTertiaryButton!
var bottomView: UIView!
var balanceLabel: CLIconLabel!
var rechargeButton: StyleButton!
var layout = UICollectionViewFlowLayout()
var cv: UICollectionView!
// MARK: -
private var cancellables = Set<AnyCancellable>()
@Published private var datas = [IAPProducts]()
@Published private var selectIndex = 0
@Published private var selectProduct: IAPProducts?
private let viewModel = CoinsRechargeViewModel()
init() {
super.init(direction: .bottom)
contentView.backgroundColor = .c.csbn
contentLength = 549 + UIWindow.safeAreaBottom
setupViews()
setupDatas()
setupEvents()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupViews() {
contentView.backgroundColor = .c.csbn
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
}()
descLabel = {
let v = CLLabel()
v.font = .t.tbs
v.numberOfLines = 2
contentView.addSubview(v)
v.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(CGFloat.lrs)
make.trailing.equalToSuperview().offset(-CGFloat.lrs)
// make.top.equalTo(titleLabel.snp.bottom).offset(24)
// make.top.equalToSuperview().offset(80)
make.centerY.equalTo(contentView.snp.top).offset(80 + 10)
}
return v
}()
bottomView = {
let v = UIView()
contentView.addSubview(v)
v.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview()
make.bottom.equalToSuperview().offset(-UIWindow.safeAreaBottom)
make.height.equalTo(80)
}
return v
}()
balanceLabel = {
let v = CLIconLabel()
v.spacing = 8
v.iconSize = CGSize(width: 24, height: 24)
v.iconImageView.image = UIImage.icon32Diamond
v.contentLabel.textColor = .text
v.contentLabel.font = .t.tndm
v.contentLabel.text = "0"
bottomView.addSubview(v)
v.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(24)
make.centerY.equalToSuperview()
}
return v
}()
rechargeButton = {
let v = StyleButton()
v.primary(size: .large)
v.addTarget(self, action: #selector(rechargeButtonAction), for: .touchUpInside)
bottomView.addSubview(v)
v.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.trailing.equalToSuperview().offset(-24)
//make.leading.equalToSuperview().offset(<#T##amount: any ConstraintOffsetTarget##any ConstraintOffsetTarget#>)
make.leading.greaterThanOrEqualTo(balanceLabel.snp.trailing).offset(16)
}
return v
}()
do {
let width = floor((UIScreen.width - 24 * 2 - 16) * 0.5)
let height = 96.0
layout.scrollDirection = .vertical
layout.itemSize = CGSize(width: width, height: height)
layout.minimumLineSpacing = 16
layout.minimumInteritemSpacing = 16
layout.sectionInset = UIEdgeInsets(top: 0, left: 24, bottom: 0, right: 24)
cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = .clear
cv.showsHorizontalScrollIndicator = false
cv.delegate = self
cv.dataSource = self
cv.contentInsetAdjustmentBehavior = .never
cv.register(CoinsRechargeGridCell.self, forCellWithReuseIdentifier: "CoinsRechargeGridCell")
contentView.addSubview(cv)
cv.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview()
make.top.equalToSuperview().offset(136)
//make.bottom.equalToSuperview()
make.bottom.equalTo(bottomView.snp.top)
}
}
titleLabel.text = "Crush Coin insufficient"
descLabel.text = "The Crush coin is insufficient and cannot continue, please recharge"
rechargeButton.setTitle("Recharge", for: .normal)
}
// MARK: -
private func setupEvents() {
//
$selectIndex.sink { [weak self] index in
guard let self = self else { return }
if index < self.datas.count {
self.selectProduct = self.datas[index]
}
}.store(in: &cancellables)
$datas.sink {[weak self] products in
self?.selectIndex = self?.selectIndex ?? 0
}.store(in: &cancellables)
//
WalletCore.shared.$balance.sink { [weak self] wallet in
self?.balanceLabel.contentLabel.text = wallet.displayBalance()
// DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) {
// self?.dismiss()
// }
}.store(in: &cancellables)
NotificationCenter.default.addObserver(self, selector: #selector(notifyChargeDone), name: AppNotificationName.chargeDonePushTradeId.notificationName, object: nil)
}
@objc private func notifyChargeDone(){
dismiss()
}
// MARK: -
private func setupDatas() {
loadBalance()
loadCoinsTiers()
}
private func loadBalance() {
WalletCore.shared.refreshWallet()
}
private func loadCoinsTiers() {
CLPurchase.shared.loadCoinTiersProducts { [weak self] response in
self?.handleValidProductsInEpalServer(products: response?.productList)
}
}
// MARK: -
private func handleValidProductsInEpalServer(products: [IAPProducts]?) {
guard let items = products else {
return
}
datas = items
cv.reloadData()
//
Hud.showIndicator()
IAPCore.shared.requestProducts(items) { [weak self] iapIds in
Hud.hideIndicator()
var validProducts: [IAPProducts] = []
for id in iapIds {
for per in items {
if id == per.productId {
validProducts.append(per)
continue
}
}
}
self?.datas = validProducts
self?.cv.reloadData()
}
}
// MARK: -
@objc private func rechargeButtonAction() {
guard let selectedProduct = selectProduct else {
Hud.toast(str: "Please select a recharge option")
return
}
//
viewModel.purchase(product: selectedProduct) { [weak self] success, tradeNo in
if success, let tradeId = tradeNo {
selectedProduct.tradeId = tradeId
IAPCore.shared.addPayProductId(productId: selectedProduct.productId ?? "", tradeId: tradeId)
} else {
Hud.toast(str: "Purchase failed, please try again")
}
}
}
}
extension CoinsRechargeSheet: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return datas.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CoinsRechargeGridCell", for: indexPath) as! CoinsRechargeGridCell
let data = datas[indexPath.item]
cell.block.backgroundColor = .c.csnn
cell.config(data)
cell.setupSelected(selected: indexPath.item == selectIndex)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectIndex = indexPath.item
collectionView.reloadData()
}
}