This commit is contained in:
zeng 2026-03-21 15:39:33 +08:00
parent 4fb32eb227
commit 6a817fabfe
21 changed files with 668 additions and 86 deletions

View File

@ -186,6 +186,8 @@
F3F389372F6E35EA001B0E15 /* XSCoinsPackConfirmView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F389362F6E35EA001B0E15 /* XSCoinsPackConfirmView.swift */; };
F3F389392F6E4268001B0E15 /* XSCoinsPackConfirmItem1View.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F389382F6E4268001B0E15 /* XSCoinsPackConfirmItem1View.swift */; };
F3F3893B2F6E47E6001B0E15 /* XSCoinsPackConfirmItem2View.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F3893A2F6E47E6001B0E15 /* XSCoinsPackConfirmItem2View.swift */; };
F3F3893D2F6E6FA4001B0E15 /* XSCoinsPackClaimListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F3893C2F6E6FA4001B0E15 /* XSCoinsPackClaimListView.swift */; };
F3F3893F2F6E7141001B0E15 /* XSCoinsPackClaimListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F3893E2F6E7141001B0E15 /* XSCoinsPackClaimListCell.swift */; };
F3F683ED2F56C380008AF250 /* XSHomeHistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F683EC2F56C380008AF250 /* XSHomeHistoryView.swift */; };
/* End PBXBuildFile section */
@ -373,6 +375,8 @@
F3F389362F6E35EA001B0E15 /* XSCoinsPackConfirmView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XSCoinsPackConfirmView.swift; sourceTree = "<group>"; };
F3F389382F6E4268001B0E15 /* XSCoinsPackConfirmItem1View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XSCoinsPackConfirmItem1View.swift; sourceTree = "<group>"; };
F3F3893A2F6E47E6001B0E15 /* XSCoinsPackConfirmItem2View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XSCoinsPackConfirmItem2View.swift; sourceTree = "<group>"; };
F3F3893C2F6E6FA4001B0E15 /* XSCoinsPackClaimListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XSCoinsPackClaimListView.swift; sourceTree = "<group>"; };
F3F3893E2F6E7141001B0E15 /* XSCoinsPackClaimListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XSCoinsPackClaimListCell.swift; sourceTree = "<group>"; };
F3F683EC2F56C380008AF250 /* XSHomeHistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XSHomeHistoryView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -924,6 +928,8 @@
F3F389362F6E35EA001B0E15 /* XSCoinsPackConfirmView.swift */,
F3F389382F6E4268001B0E15 /* XSCoinsPackConfirmItem1View.swift */,
F3F3893A2F6E47E6001B0E15 /* XSCoinsPackConfirmItem2View.swift */,
F3F3893C2F6E6FA4001B0E15 /* XSCoinsPackClaimListView.swift */,
F3F3893E2F6E7141001B0E15 /* XSCoinsPackClaimListCell.swift */,
);
path = View;
sourceTree = "<group>";
@ -1136,6 +1142,7 @@
F3F388D52F67DDBC001B0E15 /* XSMineWalletView.swift in Sources */,
F3F389272F6A9597001B0E15 /* XSBaseAlert.swift in Sources */,
F3F388D92F67F9E1001B0E15 /* XSMineVipView.swift in Sources */,
F3F3893D2F6E6FA4001B0E15 /* XSCoinsPackClaimListView.swift in Sources */,
F347D2D42F04BF3D00786648 /* XSHomeNewTitleView.swift in Sources */,
F304E6122F67D74A00E9B0A6 /* XSVideoUnlockResult.swift in Sources */,
F3F388FE2F6931D1001B0E15 /* XSConsumptionRecordsViewController.swift in Sources */,
@ -1200,6 +1207,7 @@
F3F388E12F680090001B0E15 /* XSScrollView.swift in Sources */,
F35547E92F3DDBDD006F28CD /* XSWebView.swift in Sources */,
F3F389042F6939C7001B0E15 /* XSOrderRecordsViewController.swift in Sources */,
F3F3893F2F6E7141001B0E15 /* XSCoinsPackClaimListCell.swift in Sources */,
F347D31A2F0A545000786648 /* XSDiscoverViewController.swift in Sources */,
F355483D2F52BC81006F28CD /* XSSettingAPI.swift in Sources */,
F3B312A42F30AC9B0093B180 /* XSSearchData.swift in Sources */,

View File

@ -152,4 +152,24 @@ struct XSStoreAPI {
let response: XSNetwork.Response<XSCoinsPackModel> = await XSNetwork.request(parameters: param)
return response.data
}
static func requestReceiveCoinsPackCoins(id: String?) async -> Bool {
var param = XSNetwork.Parameters(path: "/receiveDayCoin")
param.method = .post
param.isLoding = true
param.isToast = true
if let id = id {
param.parameters = [
"id" : id
]
}
let response: XSNetwork.Response<String> = await XSNetwork.request(parameters: param)
if response.isSuccess {
return true
} else {
return false
}
}
}

View File

@ -75,7 +75,9 @@ class XSMineHeaderView: UITableViewHeaderFooterView {
stackView.addArrangedSubview(walletView)
stackView.addArrangedSubview(coinsPackView)
stackView.addArrangedSubview(vipView)
if userInfo?.is_vip == true {
stackView.addArrangedSubview(vipView)
}
if !historyDataArr.isEmpty {
stackView.addArrangedSubview(historyView)

View File

@ -14,7 +14,7 @@ class XSCoinsPackViewController: XSViewController {
private var model: XSCoinsPackModel? {
didSet {
self.headerView.model = model
// claimView.dataArr = model?.receive_list ?? []
claimView.dataArr = model?.receive_list ?? []
}
}
@ -57,6 +57,9 @@ class XSCoinsPackViewController: XSViewController {
private lazy var headerView: XSCoinsPackHeaderView = {
let view = XSCoinsPackHeaderView()
view.clickClaimButton = { [weak self] in
self?.requestReceiveCoins(nil)
}
return view
}()
@ -75,6 +78,15 @@ class XSCoinsPackViewController: XSViewController {
return view
}()
private lazy var claimView: XSCoinsPackClaimListView = {
let view = XSCoinsPackClaimListView()
view.clickClaimButton = { [weak self] id in
guard let self = self else { return }
self.requestReceiveCoins(id)
}
return view
}()
private lazy var tipView: UIView = {
let view = UIView()
view.addSubview(tipTitleLabel)
@ -149,11 +161,11 @@ class XSCoinsPackViewController: XSViewController {
private func reloadData() {
stackView.xs_removeAllArrangedSubview()
// if self.claimView.dataArr.count > 0 {
// stackView.addArrangedSubview(self.claimView)
// } else if self.buyView.dataArr.count > 0 {
if self.claimView.dataArr.count > 0 {
stackView.addArrangedSubview(self.claimView)
} else if self.buyView.dataArr.count > 0 {
stackView.addArrangedSubview(self.buyView)
// }
}
stackView.addArrangedSubview(tipView)
}
@ -231,15 +243,16 @@ extension XSCoinsPackViewController {
}
}
// private func requestReceiveCoins(_ id: String?) {
// FAStoreAPI.requestReceiveCoinsPackCoins(id: id) { [weak self] finish in
// guard let self = self else { return }
// self.requestCoinsPackData()
// if finish {
private func requestReceiveCoins(_ id: String?) {
Task {
let result = await XSStoreAPI.requestReceiveCoinsPackCoins(id: id)
self.requestCoinsPackData()
// if result {
// self.showVideoRecommand()
// }
// }
// }
}
}
}

View File

@ -6,6 +6,7 @@
//
import UIKit
import SnapKit
class XSStoreViewController: XSViewController {
@ -41,16 +42,59 @@ class XSStoreViewController: XSViewController {
return view
}()
private lazy var tipView: UIView = {
let view = UIView()
view.addSubview(tipTitleLabel)
view.addSubview(tipTextLabel)
tipTitleLabel.snp.makeConstraints { make in
make.top.equalToSuperview()
make.left.equalToSuperview().offset(16)
}
tipTextLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(16)
make.right.lessThanOrEqualToSuperview().offset(-16)
make.top.equalTo(tipTitleLabel.snp.bottom).offset(4)
make.bottom.equalToSuperview()
}
return view
}()
private lazy var tipTitleLabel: UILabel = {
let label = UILabel()
label.font = .font(ofSize: 12, weight: .bold)
label.textColor = .white.withAlphaComponent(0.5)
label.text = "Tips".localized
return label
}()
private lazy var tipTextLabel: UILabel = {
let att = NSMutableAttributedString(string: "store_tips".localized)
att.yy_lineSpacing = 3
let label = UILabel()
label.font = .font(ofSize: 12, weight: .regular)
label.textColor = .white.withAlphaComponent(0.5)
label.attributedText = att
label.numberOfLines = 0
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Store".localized
let barButtonItem = UIBarButtonItem(title: "Restore".localized, style: .plain, target: self, action: #selector(handleRestore))
barButtonItem.tintColor = .white
self.navigationItem.rightBarButtonItem = barButtonItem
xs_setupUI()
reloadData()
requestPayData()
restore(isLoding: false)
}
@ -76,7 +120,7 @@ class XSStoreViewController: XSViewController {
self.addVipView()
self.addCoinsView()
}
// self.stackView.addArrangedSubview(tipView)
self.stackView.addArrangedSubview(tipView)
}
private func addCoinsView() {
@ -103,6 +147,12 @@ class XSStoreViewController: XSViewController {
private func buyFinish() {
self.requestPayData()
}
@objc private func handleRestore() {
restore(isLoding: true)
}
}
@ -142,4 +192,15 @@ extension XSStoreViewController {
}
}
private func restore(isLoding: Bool) {
XSIapManager.manager.restore(isLoding: isLoding) { [weak self] isFinish, buyType in
if isFinish {
Task {
await XSLoginManager.manager.updateUserInfo()
}
self?.buyFinish()
}
}
}
}

View File

@ -22,7 +22,7 @@ class XSCoinsPackBuyView: UIView {
let label = UILabel()
label.font = .font(ofSize: 14, weight: .bold).withBoldItalic()
label.textColor = .FFDAA_4
label.text = "Rewards Overview".localized
label.text = "Weekly Refill".localized
return label
}()

View File

@ -0,0 +1,246 @@
//
// XSCoinsPackClaimListCell.swift
// XSeri
//
// Created by 鸿 on 2026/3/21.
//
import UIKit
import SnapKit
class XSCoinsPackClaimListCell: UICollectionViewCell {
var clickClaimButton: ((_ id: String?) -> Void)?
var model: XSCoinsPackReceiveModel? {
didSet {
coinsView1.coins = model?.week_max_total
coinsView2.coins = model?.week_remaining_total
claimButton.isEnabled = (model?.receive_coins ?? 0) > 0
claimButton.setNeedsUpdateConfiguration()
let titleAtt = NSMutableAttributedString(string: "\(model?.title ?? "")")
titleAtt.yy_color = .black
titleAtt.yy_font = .font(ofSize: 14, weight: .bold)
let day = "Day"
let dayAtt = NSMutableAttributedString(string: " (\(day) \(model?.day_text ?? ""))")
dayAtt.yy_color = ._946_A_37
dayAtt.yy_font = .font(ofSize: 14, weight: .regular)
titleAtt.append(dayAtt)
titleLabel.attributedText = titleAtt
}
}
private lazy var bgView: UIImageView = {
let view = UIImageView(image: UIImage(named: "coins_pack_bg_image_02"))
view.layer.cornerRadius = 12
view.layer.masksToBounds = true
return view
}()
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 0
return label
}()
private lazy var lineView1 = UIImageView(image: UIImage(named: "line_image_03"))
private lazy var lineView2 = UIImageView(image: UIImage(named: "line_image_04"))
private lazy var coinsView1: CoinsView = {
let view = CoinsView()
view.title = "Total Reward".localized
return view
}()
private lazy var coinsView2: CoinsView = {
let view = CoinsView()
view.title = "Remaining".localized
return view
}()
private lazy var claimButton: UIButton = {
var config = UIButton.Configuration.plain()
config.titleAlignment = .center
config.background.backgroundColor = .white
config.background.cornerRadius = 24
let button = UIButton(configuration: config, primaryAction: UIAction(handler: { [weak self] _ in
guard let self = self else { return }
self.clickClaimButton?(self.model?.id)
}))
button.isEnabled = false
button.configurationUpdateHandler = { [weak self] button in
guard let self = self else { return }
var config = button.configuration
if button.isEnabled {
config?.background.backgroundColor = .white
let coinImage = UIImage(named: "coins_icon_05")!
let coinText = NSTextAttachment(image: coinImage)
coinText.bounds = .init(x: 0, y: -2.5, width: coinImage.size.width, height: coinImage.size.height)
let coinAtt = AttributedString(NSAttributedString(attachment: coinText))
let countAtt = AttributedString(" \(self.model?.receive_coins ?? 0)", attributes: AttributeContainer([
.font : UIFont.font(ofSize: 12, weight: .bold),
.foregroundColor : UIColor._946_A_37
]))
config?.attributedTitle = AttributedString("Claim".localized, attributes: AttributeContainer([
.font : UIFont.font(ofSize: 14, weight: .bold),
.foregroundColor : UIColor.black
]))
config?.attributedSubtitle = coinAtt + countAtt
} else {
config?.background.backgroundColor = ._616161
config?.attributedTitle = AttributedString("Claimed".localized, attributes: AttributeContainer([
.font : UIFont.font(ofSize: 14, weight: .bold),
.foregroundColor : UIColor.white.withAlphaComponent(0.5)
]))
config?.attributedSubtitle = nil
}
button.configuration = config
}
return button
}()
override init(frame: CGRect) {
super.init(frame: frame)
xs_setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension XSCoinsPackClaimListCell {
private func xs_setupUI() {
contentView.addSubview(bgView)
bgView.addSubview(titleLabel)
bgView.addSubview(lineView1)
bgView.addSubview(lineView2)
bgView.addSubview(coinsView1)
bgView.addSubview(coinsView2)
bgView.addSubview(claimButton)
bgView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(12)
make.centerY.equalTo(self.bgView.snp.top).offset(25)
make.right.lessThanOrEqualToSuperview().offset(-12)
}
lineView1.snp.makeConstraints { make in
make.left.equalToSuperview().offset(12)
make.centerX.equalToSuperview()
make.top.equalToSuperview().offset(48)
}
coinsView1.snp.makeConstraints { make in
make.left.equalToSuperview().offset(12)
make.bottom.equalToSuperview().offset(-17)
}
lineView2.snp.makeConstraints { make in
make.centerY.equalTo(coinsView1)
make.left.equalTo(coinsView1.snp.right).offset(12)
}
coinsView2.snp.makeConstraints { make in
make.centerY.equalTo(coinsView1)
make.left.equalTo(lineView2.snp.right).offset(12)
}
claimButton.snp.makeConstraints { make in
make.right.equalToSuperview().offset(-12)
make.centerY.equalTo(coinsView1)
make.height.equalTo(48)
make.width.equalTo(120)
}
}
}
extension XSCoinsPackClaimListCell {
class CoinsView: UIView {
var title: String? {
didSet {
titleLabel.text = title
}
}
var coins: Int? {
didSet {
coinsLabel.text = "\(coins ?? 0)"
}
}
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = .font(ofSize: 12, weight: .bold)
label.textColor = .black
return label
}()
private lazy var iconImageView = UIImageView(image: UIImage(named: "coins_icon_05"))
private lazy var coinsLabel: UILabel = {
let label = UILabel()
label.font = .font(ofSize: 14, weight: .bold)
label.textColor = ._946_A_37
label.text = "0"
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(titleLabel)
addSubview(iconImageView)
addSubview(coinsLabel)
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview()
make.top.equalToSuperview()
make.right.lessThanOrEqualToSuperview()
}
iconImageView.snp.makeConstraints { make in
make.left.equalToSuperview()
make.bottom.equalToSuperview()
make.top.equalTo(titleLabel.snp.bottom).offset(8)
}
coinsLabel.snp.makeConstraints { make in
make.centerY.equalTo(iconImageView)
make.left.equalTo(iconImageView.snp.right).offset(4)
make.right.lessThanOrEqualToSuperview()
}
}
@MainActor required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
}

View File

@ -0,0 +1,116 @@
//
// XSCoinsPackClaimListView.swift
// XSeri
//
// Created by 鸿 on 2026/3/21.
//
import UIKit
import SnapKit
class XSCoinsPackClaimListView: UIView {
var clickClaimButton: ((_ id: String?) -> Void)?
var dataArr: [XSCoinsPackReceiveModel] = [] {
didSet {
collectionView.reloadData()
}
}
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = .font(ofSize: 14, weight: .bold).withBoldItalic()
label.textColor = .FFDAA_4
label.text = "Active Refills".localized
return label
}()
private lazy var titleLineView: UIView = {
let view = UIImageView(image: UIImage(named: "coins_pack_line_image"))
return view
}()
private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout()
layout.itemSize = .init(width: XSScreen.width - 32, height: 122)
layout.minimumLineSpacing = 12
return layout
}()
private lazy var collectionView: XSCollectionView = {
let collectionView = XSCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.addObserver(self, forKeyPath: "contentSize", context: nil)
collectionView.register(XSCoinsPackClaimListCell.self, forCellWithReuseIdentifier: "cell")
return collectionView
}()
deinit {
collectionView.removeObserver(self, forKeyPath: "contentSize")
}
override init(frame: CGRect) {
super.init(frame: frame)
xs_setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "contentSize" {
let height = self.collectionView.contentSize.height + 1
collectionView.snp.updateConstraints { make in
make.height.equalTo(height)
}
}
}
}
extension XSCoinsPackClaimListView {
private func xs_setupUI() {
addSubview(titleLabel)
addSubview(titleLineView)
addSubview(collectionView)
titleLabel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalToSuperview()
}
titleLineView.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(28)
make.top.equalTo(titleLabel.snp.bottom).offset(6)
}
collectionView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.top.equalTo(titleLabel.snp.bottom).offset(16)
make.height.equalTo(1)
make.bottom.equalToSuperview()
}
}
}
//MARK: UICollectionViewDelegate UICollectionViewDataSource
extension XSCoinsPackClaimListView: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! XSCoinsPackClaimListCell
cell.model = self.dataArr[indexPath.row]
cell.clickClaimButton = { [weak self] id in
self?.clickClaimButton?(id)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dataArr.count
}
}

View File

@ -9,29 +9,71 @@ import UIKit
import SnapKit
import HWPanModal
private final class XSCoinsPackConfirmButtonBackgroundView: XSView {
private let borderWidth: CGFloat = 1
private lazy var fillView: XSView = {
let view = XSView()
view.xs_colors = [UIColor.F_5_BD_7_E.cgColor, UIColor.FFEABC.cgColor, UIColor.FFCF_99.cgColor]
view.xs_startPoint = .init(x: 0, y: 0.5)
view.xs_endPoint = .init(x: 1, y: 0.5)
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
xs_colors = [
UIColor.E_43_B_7_F.withAlphaComponent(0.3).cgColor,
UIColor.B_4054_B.withAlphaComponent(0.3).cgColor
]
xs_startPoint = .init(x: 0, y: 0.5)
xs_endPoint = .init(x: 1, y: 0.5)
addSubview(fillView)
fillView.snp.makeConstraints { make in
make.edges.equalToSuperview().inset(borderWidth)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = bounds.height / 2
layer.masksToBounds = true
fillView.layer.cornerRadius = max(0, (bounds.height - borderWidth * 2) / 2)
fillView.layer.masksToBounds = true
}
}
class XSCoinsPackConfirmView: XSPanModalContentView {
var buyFinishHandle: (() -> Void)?
var shortPlayId: String?
var videoId: String?
var item: XSPayItem? {
didSet {
item2View.list = item?.ext_info?.sub_coins_txt_list
var price = item?.price ?? ""
if let discount_price = item?.discount_price {
price = discount_price
}
priceLabel.text = "\(item?.currency ?? "")\(price)/\(item?.getTimeString() ?? "")"
}
}
private let bgBorderImage = UIImage(named: "gradient_color_image_03")?.xs_flippedVertically()
private lazy var bgView: UIImageView = {
let view = UIImageView(image: UIImage(named: "coins_pack_bg_03"))
view.isUserInteractionEnabled = true
@ -42,7 +84,7 @@ class XSCoinsPackConfirmView: XSPanModalContentView {
view.addObserver(self, forKeyPath: "bounds", context: nil)
return view
}()
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = .font(ofSize: 24, weight: .bold)
@ -50,29 +92,29 @@ class XSCoinsPackConfirmView: XSPanModalContentView {
label.text = "What You Get".localized
return label
}()
private lazy var closeButton: UIButton = {
let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
guard let self = self else { return }
self.dismiss(animated: true) {
}
}))
button.setImage(UIImage(named: "close_icon_03"), for: .normal)
return button
}()
private lazy var scrollView: XSScrollView = {
let scrollView = XSScrollView()
scrollView.addObserver(self, forKeyPath: "contentSize", context: nil)
return scrollView
}()
private lazy var contentTitleView: UIView = {
let view = UIImageView(image: UIImage(named: "coins_pack_confirm_title_bg"))
return view
}()
private lazy var contentTitleLabel: UILabel = {
let label = UILabel()
label.font = .font(ofSize: 14, weight: .bold).withBoldItalic()
@ -80,7 +122,7 @@ class XSCoinsPackConfirmView: XSPanModalContentView {
label.text = "Bonus You Get".localized
return label
}()
private lazy var contentView: UIView = {
let view = UIView()
view.layer.cornerRadius = 18
@ -88,32 +130,26 @@ class XSCoinsPackConfirmView: XSPanModalContentView {
view.backgroundColor = .F_08_FFF.withAlphaComponent(0.1)
return view
}()
private lazy var item1View: XSCoinsPackConfirmItem1View = {
let view = XSCoinsPackConfirmItem1View()
return view
}()
private lazy var item2View: XSCoinsPackConfirmItem2View = {
let view = XSCoinsPackConfirmItem2View()
return view
}()
private lazy var priceLabel: UILabel = {
let label = UILabel()
label.font = .font(ofSize: 18, weight: .bold)
label.textColor = .FFE_17_D
return label
}()
private lazy var continueBgView: UIView = {
let view = XSView()
view.xs_colors = [UIColor.F_5_BD_7_E.cgColor, UIColor.FFEABC.cgColor, UIColor.FFCF_99.cgColor]
view.xs_startPoint = .init(x: 0, y: 0.5)
view.xs_endPoint = .init(x: 1, y: 0.5)
return view
}()
private lazy var continueBgView = XSCoinsPackConfirmButtonBackgroundView()
private lazy var continueButton: UIButton = {
var configuration = UIButton.Configuration.plain()
configuration.background.customView = continueBgView
@ -124,49 +160,57 @@ class XSCoinsPackConfirmView: XSPanModalContentView {
]))
let button = UIButton(configuration: configuration, primaryAction: UIAction(handler: { [weak self] _ in
guard let self = self else { return }
guard let item = self.item else { return }
XSIapManager.manager.start(model: item, shortPlayId: self.shortPlayId, videoId: videoId) { [weak self] finish in
guard let self = self else { return }
guard finish else { return }
self.buyFinishHandle?()
self.dismiss(animated: true) { }
}
}))
return button
}()
deinit {
self.bgView.removeObserver(self, forKeyPath: "bounds")
self.scrollView.removeObserver(self, forKeyPath: "contentSize")
}
override init(frame: CGRect) {
super.init(frame: frame)
// self.contentHeight = 300
xs_setupUI()
}
@MainActor required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "bounds" {
guard let borderImage = bgBorderImage?.xs_resized(to: bgView.bounds.size) else { return }
bgView.layer.borderColor = UIColor(patternImage: borderImage).cgColor
} else if keyPath == "contentSize" {
self.setNeedsLayoutUpdate()
let height = self.scrollView.contentSize.height
scrollView.snp.updateConstraints { make in
make.height.equalTo(height + 1)
}
}
}
override func allowsTapBackgroundToDismiss() -> Bool {
return false
}
override func cornerRadius() -> CGFloat {
return 0
}
override func longFormHeight() -> PanModalHeight {
let height = 78 + scrollView.contentSize.height + 92 + 10
return PanModalHeightMake(.content, height + XSScreen.safeBottom)
@ -174,7 +218,7 @@ class XSCoinsPackConfirmView: XSPanModalContentView {
}
extension XSCoinsPackConfirmView {
private func xs_setupUI() {
addSubview(bgView)
addSubview(titleLabel)
@ -187,61 +231,61 @@ extension XSCoinsPackConfirmView {
contentView.addSubview(item2View)
addSubview(priceLabel)
addSubview(continueButton)
bgView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
titleLabel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalToSuperview().offset(30)
}
closeButton.snp.makeConstraints { make in
make.right.equalToSuperview().offset(-16)
make.top.equalToSuperview().offset(24)
}
scrollView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalToSuperview().offset(78)
make.height.equalTo(1)
}
contentView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(16)
make.centerX.equalToSuperview()
make.top.equalToSuperview().offset(7)
make.bottom.equalToSuperview()
}
contentTitleView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalToSuperview()
}
contentTitleLabel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.left.equalToSuperview().offset(28)
make.top.equalToSuperview().offset(9)
}
item1View.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalToSuperview().offset(46)
}
item2View.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(item1View.snp.bottom).offset(24)
make.bottom.equalToSuperview().offset(-40)
}
priceLabel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.centerY.equalTo(scrollView.snp.bottom).offset(22)
}
continueButton.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(16)
make.bottom.equalToSuperview().offset(-(10 + XSScreen.safeBottom))

View File

@ -10,12 +10,13 @@ import SnapKit
class XSCoinsPackHeaderView: UIView {
var clickClaimButton: (() -> Void)?
var model: XSCoinsPackModel? {
didSet {
coinsView1.coins = model?.week_max_total
coinsView2.coins = model?.week_total
let activeRefillsStr = NSMutableAttributedString(string: "Active Refills:".localized + " ")
activeRefillsStr.yy_font = .font(ofSize: 12, weight: .regular)
activeRefillsStr.yy_color = .white.withAlphaComponent(0.5)
@ -79,8 +80,7 @@ class XSCoinsPackHeaderView: UIView {
config.background.cornerRadius = 24
let button = UIButton(configuration: config, primaryAction: UIAction(handler: { [weak self] _ in
// self?.clickClaimButton?()
self?.claimButton.isEnabled = false
self?.clickClaimButton?()
}))
button.isEnabled = false
button.configurationUpdateHandler = { [weak self] button in
@ -98,11 +98,7 @@ class XSCoinsPackHeaderView: UIView {
.foregroundColor : UIColor._763200
]))
// let countAtt = AttributedString(" \(self.model?.receive_coins ?? 0)".localized, attributes: AttributeContainer([
// .font : UIFont.font(ofSize: 14, weight: .bold),
// .foregroundColor : UIColor.FFFFFF
// ]))
let countAtt = AttributedString(" 10".localized, attributes: AttributeContainer([
let countAtt = AttributedString(" \(self.model?.receive_coins ?? 0)", attributes: AttributeContainer([
.font : UIFont.font(ofSize: 14, weight: .bold),
.foregroundColor : UIColor.FF_7700
]))

View File

@ -199,23 +199,25 @@ extension XSStoreCoinsView: UICollectionViewDelegate, UICollectionViewDataSource
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let model = dataArr[indexPath.section][indexPath.row]
let item = dataArr[indexPath.section][indexPath.row]
self.selectedIndexPath = indexPath
collectionView.reloadData()
if model.buy_type == .subCoins {
// let view = FACoinPackConfirmView()
// view.shortPlayId = self.shortPlayId
// view.videoId = self.videoId
// view.model = model
// view.buyFinishHandle = { [weak self] in
// guard let self = self else { return }
// FALogin.manager.requestUserInfo(completer: nil)
// self.buyFinishHandle?()
// }
// view.present(in: nil)
if item.buy_type == .subCoins {
let view = XSCoinsPackConfirmView()
view.shortPlayId = self.shortPlayId
view.videoId = self.videoId
view.item = item
view.buyFinishHandle = { [weak self] in
guard let self = self else { return }
Task {
await XSLoginManager.manager.updateUserInfo()
}
self.buyFinishHandle?()
}
view.present(in: nil)
} else {
XSIapManager.manager.start(model: model, shortPlayId: self.shortPlayId, videoId: self.videoId) { [weak self] finish in
XSIapManager.manager.start(model: item, shortPlayId: self.shortPlayId, videoId: self.videoId) { [weak self] finish in
guard let self = self else { return }
if finish {
Task {

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "金币订阅包-bg@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "金币订阅包-bg@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "虚线@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "虚线@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "line_image_04@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "line_image_04@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

View File

@ -80,11 +80,16 @@
"Claim All" = "Claim All";
"Get a Refill to Claim" = "Get a Refill to Claim";
"Active Refills:" = "Active Refills:";
"Active Refills" = "Active Refills";
"What You Get" = "What You Get";
"Bonus You Get" = "Bonus You Get";
"Weekly Refill Package" = "Weekly Refill Package";
"Daily Bonuses" = "Daily Bonuses";
"Continue" = "Continue";
"Total Reward" = "Total Reward";
"Remaining" = "Remaining";
"Claim" = "Claim";
"Restore" = "Restore";
"me_daily_1" = "Daily reward ready!";
"me_daily_2" = "Claim your rewards now.";
@ -107,3 +112,6 @@
"pay_error_4" = "Purchase Failed";
"pay_error_5" = "There are no recoverable in-app purchases.";
"pay_error_6" = "You have unfinished in-app purchases, please restore them first.";
"Tips" = "Tips";
"store_tips" = "1. Coins are virtual items and cannot be refunded. Use it for this product.<br>2. Both the coins and the reward coins will never expire.<br>3. Coins will be used first when unlocking episodes. If the amount is insufficient, reward coins will automatically be used.<br>4. The purchase has not been credited, click <Restore> torefresh.<br>5. For other questions, contact us via Portfolio > Feedback.";