426 lines
13 KiB
Swift
426 lines
13 KiB
Swift
|
|
//
|
|||
|
|
// BuyCreditsSheetView.swift
|
|||
|
|
// Crush
|
|||
|
|
//
|
|||
|
|
// Created by Leon on 2025/7/23.
|
|||
|
|
//
|
|||
|
|
|
|||
|
|
import UIKit
|
|||
|
|
import Combine
|
|||
|
|
/// 额外购买次数
|
|||
|
|
class BuyCreditsSheetView: EGPopBaseView {
|
|||
|
|
var closeButton: EPIconTertiaryButton!
|
|||
|
|
var logo :UIImageView!
|
|||
|
|
var titleLabel:UILabel!
|
|||
|
|
|
|||
|
|
|
|||
|
|
var stackV : UIStackView!
|
|||
|
|
// content 1: numberscontent
|
|||
|
|
var priceLabel: UILabel!
|
|||
|
|
|
|||
|
|
// content 2:
|
|||
|
|
var addButton: InDecreaseButton!
|
|||
|
|
/// 1-999
|
|||
|
|
var inputBox:NumbersInputBox!
|
|||
|
|
var decreaseButton: InDecreaseButton!
|
|||
|
|
|
|||
|
|
// content 3: total Price
|
|||
|
|
var totalPriceLabel: UILabel!
|
|||
|
|
|
|||
|
|
var buyButton:StyleButton!
|
|||
|
|
|
|||
|
|
// Data
|
|||
|
|
|
|||
|
|
var maxNum = 999
|
|||
|
|
var minNum = 1
|
|||
|
|
|
|||
|
|
/// 单价(每次价格)
|
|||
|
|
var pricePer: Int = 7000
|
|||
|
|
@Published var num: Int = 10
|
|||
|
|
private var cancellables = Set<AnyCancellable>()
|
|||
|
|
|
|||
|
|
init() {
|
|||
|
|
super.init(direction: .bottom)
|
|||
|
|
contentView.backgroundColor = .c.csbn
|
|||
|
|
contentLength = 444 + UIWindow.safeAreaBottom
|
|||
|
|
|
|||
|
|
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
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
logo = {
|
|||
|
|
let v = UIImageView()
|
|||
|
|
contentView.addSubview(v)
|
|||
|
|
v.image = UIImage(named: "buy_credits_title_logo")
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.size.equalTo(CGSize(width: 100, height: 100))
|
|||
|
|
make.centerX.equalToSuperview()
|
|||
|
|
make.top.equalToSuperview().offset(24)
|
|||
|
|
}
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
titleLabel = {
|
|||
|
|
let v = UILabel()
|
|||
|
|
contentView.addSubview(v)
|
|||
|
|
v.text = "Buy Credits"
|
|||
|
|
v.font = .t.ttm
|
|||
|
|
v.textColor = .text
|
|||
|
|
v.textAlignment = .center
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.leading.equalToSuperview().offset(24)
|
|||
|
|
make.trailing.equalToSuperview().offset(-24)
|
|||
|
|
make.top.equalTo(logo.snp.bottom).offset(24)
|
|||
|
|
}
|
|||
|
|
v.numberOfLines = 0
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
stackV = {
|
|||
|
|
let v = UIStackView()
|
|||
|
|
v.axis = .vertical
|
|||
|
|
v.spacing = 0
|
|||
|
|
contentView.addSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.leading.equalToSuperview().offset(24)
|
|||
|
|
make.trailing.equalToSuperview().offset(-24)
|
|||
|
|
make.top.equalTo(titleLabel.snp.bottom).offset(24)
|
|||
|
|
}
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
do{
|
|||
|
|
let priceView = {
|
|||
|
|
let v = UIView()
|
|||
|
|
stackV.addArrangedSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.height.equalTo(48)
|
|||
|
|
}
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
let tipLabel = {
|
|||
|
|
let label = UILabel()
|
|||
|
|
label.font = .t.tll
|
|||
|
|
label.textColor = .text
|
|||
|
|
priceView.addSubview(label)
|
|||
|
|
label.snp.makeConstraints { make in
|
|||
|
|
make.leading.equalToSuperview()
|
|||
|
|
make.centerY.equalToSuperview()
|
|||
|
|
}
|
|||
|
|
return label
|
|||
|
|
}()
|
|||
|
|
tipLabel.text = "Price"
|
|||
|
|
|
|||
|
|
priceLabel = {
|
|||
|
|
let v = UILabel()
|
|||
|
|
v.font = .t.tll
|
|||
|
|
v.textColor = .text
|
|||
|
|
priceView.addSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.trailing.equalToSuperview()
|
|||
|
|
make.centerY.equalToSuperview()
|
|||
|
|
}
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
let coinIv = {
|
|||
|
|
let v = UIImageView()
|
|||
|
|
priceView.addSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.trailing.equalTo(priceLabel.snp.leading).offset(-8)
|
|||
|
|
make.centerY.equalToSuperview()
|
|||
|
|
}
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
coinIv.image = UIImage(named: "icon_16_diamond")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setupQuantityView()
|
|||
|
|
|
|||
|
|
do{
|
|||
|
|
let priceView = {
|
|||
|
|
let v = UIView()
|
|||
|
|
stackV.addArrangedSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.height.equalTo(48)
|
|||
|
|
}
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
let tipLabel = {
|
|||
|
|
let label = UILabel()
|
|||
|
|
label.font = .t.tll
|
|||
|
|
label.textColor = .text
|
|||
|
|
priceView.addSubview(label)
|
|||
|
|
label.snp.makeConstraints { make in
|
|||
|
|
make.leading.equalToSuperview()
|
|||
|
|
make.centerY.equalToSuperview()
|
|||
|
|
}
|
|||
|
|
return label
|
|||
|
|
}()
|
|||
|
|
tipLabel.text = "Total Price"
|
|||
|
|
|
|||
|
|
totalPriceLabel = {
|
|||
|
|
let v = UILabel()
|
|||
|
|
v.font = .t.tll
|
|||
|
|
v.textColor = .text
|
|||
|
|
priceView.addSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.trailing.equalToSuperview()
|
|||
|
|
make.centerY.equalToSuperview()
|
|||
|
|
}
|
|||
|
|
v.text = "0"
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
let coinIv = {
|
|||
|
|
let v = UIImageView()
|
|||
|
|
v.image = UIImage(named: "icon_16_diamond")
|
|||
|
|
priceView.addSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.trailing.equalTo(totalPriceLabel.snp.leading).offset(-8)
|
|||
|
|
make.centerY.equalToSuperview()
|
|||
|
|
}
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
coinIv.isHidden = false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
buyButton = {
|
|||
|
|
let v = StyleButton()
|
|||
|
|
v.primary(size: .large)
|
|||
|
|
contentView.addSubview(v)
|
|||
|
|
v.addTarget(self, action: #selector(submitAction), for: .touchUpInside)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.leading.equalToSuperview().offset(24)
|
|||
|
|
make.trailing.equalToSuperview().offset(-24)
|
|||
|
|
//make.top.equalTo(titleLabel.snp.bottom).offset(24)
|
|||
|
|
make.bottom.equalToSuperview().offset(-16-UIWindow.safeAreaBottom*0.5)
|
|||
|
|
}
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
buyButton.setTitle("Confirm", for: .normal)
|
|||
|
|
|
|||
|
|
setupData()
|
|||
|
|
setupEvent()
|
|||
|
|
|
|||
|
|
//#warning("test")
|
|||
|
|
// testData()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private func setupQuantityView(){
|
|||
|
|
let quantityView = {
|
|||
|
|
let v = UIView()
|
|||
|
|
stackV.addArrangedSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.height.equalTo(72)
|
|||
|
|
}
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
let quantityLabel = {
|
|||
|
|
let v = UILabel()
|
|||
|
|
v.font = .t.tll
|
|||
|
|
v.textColor = .text
|
|||
|
|
quantityView.addSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.leading.equalToSuperview()
|
|||
|
|
make.centerY.equalToSuperview()
|
|||
|
|
}
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
quantityLabel.text = "Quantity"
|
|||
|
|
|
|||
|
|
addButton = {
|
|||
|
|
let v = InDecreaseButton()
|
|||
|
|
v.setupIncreaseState()
|
|||
|
|
quantityView.addSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.trailing.equalToSuperview()
|
|||
|
|
make.centerY.equalToSuperview()
|
|||
|
|
}
|
|||
|
|
v.addTarget(self, action: #selector(tapIncreaseButton), for: .touchUpInside)
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
inputBox = {
|
|||
|
|
let v = NumbersInputBox()
|
|||
|
|
quantityView.addSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.trailing.equalTo(addButton.snp.leading).offset(-8)
|
|||
|
|
make.centerY.equalToSuperview()
|
|||
|
|
}
|
|||
|
|
//v.text = "0"
|
|||
|
|
v.placeholder = "0"
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
decreaseButton = {
|
|||
|
|
let v = InDecreaseButton()
|
|||
|
|
v.setupDecreaseState()
|
|||
|
|
quantityView.addSubview(v)
|
|||
|
|
v.snp.makeConstraints { make in
|
|||
|
|
make.trailing.equalTo(inputBox.snp.leading).offset(-8)
|
|||
|
|
make.centerY.equalToSuperview()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
v.addTarget(self, action: #selector(tapDecreaseButton), for: .touchUpInside)
|
|||
|
|
return v
|
|||
|
|
}()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private func setupData(){
|
|||
|
|
|
|||
|
|
// 单价
|
|||
|
|
let price = Coin(cents: 70*100)
|
|||
|
|
let priceLabelText = "\(price.formatted)"
|
|||
|
|
priceLabel.text = priceLabelText
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private func setupEvent(){
|
|||
|
|
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChanged(noti:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
|
|||
|
|
|
|||
|
|
inputBox.textDidChanged = {[weak self] textField in
|
|||
|
|
guard let self = self else{return}
|
|||
|
|
let count = Int(textField.text ?? "1") ?? 0
|
|||
|
|
|
|||
|
|
self.num = count
|
|||
|
|
if count > self.maxNum{
|
|||
|
|
textField.text = "\(self.maxNum)"
|
|||
|
|
self.num = self.maxNum
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
self.buyButton.isEnabled = count > 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
inputBox.textDidEndEditing = {[weak self] textField in
|
|||
|
|
guard let self = self else{return}
|
|||
|
|
let count = Int(textField.text ?? "1") ?? 1
|
|||
|
|
self.num = count
|
|||
|
|
if count < self.minNum{
|
|||
|
|
textField.text = "\(self.minNum)"
|
|||
|
|
self.num = self.minNum
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$num.sink {[weak self] count in
|
|||
|
|
guard let self = self else{return}
|
|||
|
|
|
|||
|
|
self.inputBox.text = "\(count)"
|
|||
|
|
|
|||
|
|
let total = count * self.pricePer
|
|||
|
|
let totalCoin = Coin(cents: total)
|
|||
|
|
totalPriceLabel.text = totalCoin.formatted
|
|||
|
|
|
|||
|
|
self.decreaseButton.isEnabled = count > minNum
|
|||
|
|
self.addButton.isEnabled = count < maxNum
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
}.store(in: &cancellables)
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private func testData(){
|
|||
|
|
// let price = Coin(cents: 70*100)
|
|||
|
|
// let priceLabelText = "\(price.formatted) USD"
|
|||
|
|
// priceLabel.text = priceLabelText
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@available(*, unavailable)
|
|||
|
|
required init?(coder: NSCoder) {
|
|||
|
|
fatalError("init(coder:) has not been implemented")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
override func show() {
|
|||
|
|
super.show()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// MARK: - Action
|
|||
|
|
|
|||
|
|
@objc func submitAction(){
|
|||
|
|
|
|||
|
|
// let alert = Alert(title: "Buy Credits", text: "Are you sure you want to buy credits?")
|
|||
|
|
// let action1 = AlertAction(title: "Cancel", actionStyle: .cancel)
|
|||
|
|
// let action2 = AlertAction(title: "Buy", actionStyle: .destructive)
|
|||
|
|
// alert.addAction(action1)
|
|||
|
|
// alert.addAction(action2)
|
|||
|
|
// alert.show()
|
|||
|
|
|
|||
|
|
doPurchase()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@objc private func tapDecreaseButton(){
|
|||
|
|
num -= 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@objc private func tapIncreaseButton(){
|
|||
|
|
num += 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// MARK: - Functions
|
|||
|
|
|
|||
|
|
private func doPurchase(){
|
|||
|
|
// #warning("test")
|
|||
|
|
// dismiss()
|
|||
|
|
// let buyCoinSheet = CoinsRechargeSheet()
|
|||
|
|
// buyCoinSheet.show()
|
|||
|
|
// return
|
|||
|
|
|
|||
|
|
let count = num
|
|||
|
|
// 创作次数+X
|
|||
|
|
Hud.showIndicator()
|
|||
|
|
UserProvider.request(.buyUserCreateCount(count: num), modelType: EmptyModel.self) {[weak self] result in
|
|||
|
|
Hud.hideIndicator()
|
|||
|
|
switch result {
|
|||
|
|
case .success:
|
|||
|
|
Hud.toast(str: "创作次数+\(count)") {[weak self] complete in
|
|||
|
|
self?.dismiss()
|
|||
|
|
}
|
|||
|
|
NotificationCenter.post(name: .buyCreditsOnce)
|
|||
|
|
case .failure(let failure):
|
|||
|
|
switch failure {
|
|||
|
|
case let .serviceError(code, _):
|
|||
|
|
if code == .insufficentCoin{
|
|||
|
|
self?.dismiss()
|
|||
|
|
// 遇到此错误吗会会统一弹出sheet去充值
|
|||
|
|
// let buyCoinSheet = CoinsRechargeSheet()
|
|||
|
|
// buyCoinSheet.show()
|
|||
|
|
}
|
|||
|
|
default:
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// MARK: - Helper
|
|||
|
|
@objc func keyboardWillChanged(noti: Notification) {
|
|||
|
|
guard let userInfo = noti.userInfo else { return }
|
|||
|
|
//let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! TimeInterval
|
|||
|
|
let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
|
|||
|
|
|
|||
|
|
if endFrame.origin.y >= UIScreen.main.bounds.height {
|
|||
|
|
bottomKeyboardHeight = 0
|
|||
|
|
refreshLPositon()
|
|||
|
|
}else{
|
|||
|
|
bottomKeyboardHeight = endFrame.height
|
|||
|
|
refreshLPositon()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|