bug修复,空白页面开发

This commit is contained in:
zeng 2025-05-08 13:39:30 +08:00
parent 5814d4f434
commit 2bbfb16139
53 changed files with 421 additions and 110 deletions

View File

@ -7,6 +7,8 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
1BE7892B2DCB0E530001A8F1 /* FacebookCore in Frameworks */ = {isa = PBXBuildFile; productRef = 1BE7892A2DCB0E530001A8F1 /* FacebookCore */; };
1BE7892D2DCB0E530001A8F1 /* FacebookLogin in Frameworks */ = {isa = PBXBuildFile; productRef = 1BE7892C2DCB0E530001A8F1 /* FacebookLogin */; };
1BF22FD12DC2169B0082429A /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 1BF22FD02DC2169B0082429A /* FirebaseAnalytics */; }; 1BF22FD12DC2169B0082429A /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 1BF22FD02DC2169B0082429A /* FirebaseAnalytics */; };
1BF22FD32DC2169B0082429A /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 1BF22FD22DC2169B0082429A /* FirebaseCore */; }; 1BF22FD32DC2169B0082429A /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 1BF22FD22DC2169B0082429A /* FirebaseCore */; };
1BF22FD52DC2169B0082429A /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 1BF22FD42DC2169B0082429A /* FirebaseMessaging */; }; 1BF22FD52DC2169B0082429A /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 1BF22FD42DC2169B0082429A /* FirebaseMessaging */; };
@ -49,6 +51,8 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
1BF22FD52DC2169B0082429A /* FirebaseMessaging in Frameworks */, 1BF22FD52DC2169B0082429A /* FirebaseMessaging in Frameworks */,
1BE7892B2DCB0E530001A8F1 /* FacebookCore in Frameworks */,
1BE7892D2DCB0E530001A8F1 /* FacebookLogin in Frameworks */,
91D08C5AEAE459A3B8EA48C6 /* Pods_MoviaBox.framework in Frameworks */, 91D08C5AEAE459A3B8EA48C6 /* Pods_MoviaBox.framework in Frameworks */,
1BF22FD32DC2169B0082429A /* FirebaseCore in Frameworks */, 1BF22FD32DC2169B0082429A /* FirebaseCore in Frameworks */,
1BF22FD12DC2169B0082429A /* FirebaseAnalytics in Frameworks */, 1BF22FD12DC2169B0082429A /* FirebaseAnalytics in Frameworks */,
@ -146,6 +150,7 @@
minimizedProjectReferenceProxies = 1; minimizedProjectReferenceProxies = 1;
packageReferences = ( packageReferences = (
1BF22FCF2DC2169B0082429A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, 1BF22FCF2DC2169B0082429A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
1BE789292DCB0E530001A8F1 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */,
); );
preferredProjectObjectVersion = 77; preferredProjectObjectVersion = 77;
productRefGroup = 1DBC405A2DA4EDFC0093FCB0 /* Products */; productRefGroup = 1DBC405A2DA4EDFC0093FCB0 /* Products */;
@ -455,6 +460,14 @@
/* End XCConfigurationList section */ /* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */ /* Begin XCRemoteSwiftPackageReference section */
1BE789292DCB0E530001A8F1 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/facebook/facebook-ios-sdk";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 14.1.0;
};
};
1BF22FCF2DC2169B0082429A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { 1BF22FCF2DC2169B0082429A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
@ -466,6 +479,16 @@
/* End XCRemoteSwiftPackageReference section */ /* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */ /* Begin XCSwiftPackageProductDependency section */
1BE7892A2DCB0E530001A8F1 /* FacebookCore */ = {
isa = XCSwiftPackageProductDependency;
package = 1BE789292DCB0E530001A8F1 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */;
productName = FacebookCore;
};
1BE7892C2DCB0E530001A8F1 /* FacebookLogin */ = {
isa = XCSwiftPackageProductDependency;
package = 1BE789292DCB0E530001A8F1 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */;
productName = FacebookLogin;
};
1BF22FD02DC2169B0082429A /* FirebaseAnalytics */ = { 1BF22FD02DC2169B0082429A /* FirebaseAnalytics */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = 1BF22FCF2DC2169B0082429A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; package = 1BF22FCF2DC2169B0082429A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;

View File

@ -1,5 +1,5 @@
{ {
"originHash" : "c63c63846d9c539229e96de38d6af51417e28c0ee9a0bc48bd0f0f19d923c329", "originHash" : "c47d0d305ed42c8e2ce41760feb2ed27468bf8a4c789d72416aad5bed8e64bd2",
"pins" : [ "pins" : [
{ {
"identity" : "abseil-cpp-binary", "identity" : "abseil-cpp-binary",
@ -19,6 +19,15 @@
"version" : "11.2.0" "version" : "11.2.0"
} }
}, },
{
"identity" : "facebook-ios-sdk",
"kind" : "remoteSourceControl",
"location" : "https://github.com/facebook/facebook-ios-sdk",
"state" : {
"revision" : "c19607d535864533523d1f437c84035e5fb101cf",
"version" : "14.1.0"
}
},
{ {
"identity" : "firebase-ios-sdk", "identity" : "firebase-ios-sdk",
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",

View File

@ -34,11 +34,25 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
} }
///APP ///APP
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.badge, .alert]) completionHandler([.badge, .banner])
} }
///app ///app
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if #available(iOS 16.0, *) {
UNUserNotificationCenter.current().setBadgeCount(0)
} else {
UIApplication.shared.applicationIconBadgeNumber = 0
}
let userInfo = response.notification.request.content.userInfo
if let shortPlayId = userInfo["short_play_id"] as? String {
let vc = SPPlayerDetailViewController()
vc.shortPlayId = shortPlayId
SPAPPTool.topViewController()?.navigationController?.pushViewController(vc, animated: true)
}
completionHandler() completionHandler()
} }

View File

@ -0,0 +1,31 @@
//
// AppDelegate+Thirdparty.swift
// MoviaBox
//
// Created by on 2025/5/7.
//
import UIKit
import AdjustSdk
#if canImport(FacebookCore)
import FacebookCore
#endif
extension AppDelegate {
func registThirdparty(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
//Facebook
#if canImport(FacebookCore)
ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
#endif
registAdjust()
}
private func registAdjust() {
let config = ADJConfig(appToken: "mtogye6pmha8", environment: ADJEnvironmentProduction)
Adjust.initSdk(config)
}
}

View File

@ -6,9 +6,6 @@
// //
import UIKit import UIKit
#if canImport(FacebookCore)
import FacebookCore
#endif
@main @main
class AppDelegate: UIResponder, UIApplicationDelegate { class AppDelegate: UIResponder, UIApplicationDelegate {
@ -16,10 +13,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
///Facebook
#if canImport(FacebookCore)
ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions) self.registThirdparty(application, didFinishLaunchingWithOptions: launchOptions)
#endif
self.appConfig() self.appConfig()
/// ///
@ -31,7 +27,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
let _ = JXIAPManager.manager
// SPLoginManager.manager.requestVisitorLogin(completer: nil) // SPLoginManager.manager.requestVisitorLogin(completer: nil)
SPLoginManager.manager.updateUserInfo(completer: nil) SPLoginManager.manager.updateUserInfo(completer: nil)

View File

@ -37,8 +37,9 @@ class SPHomeAPI: NSObject {
/// ///
static func requestHomeModuleData(completer: ((_ model: SPHomeModuleModel?) -> Void)?) { static func requestHomeModuleData(completer: ((_ model: SPHomeModuleModel?) -> Void)?) {
let param = SPNetworkParameters(path: "/homeBannerAndNineSquare") var param = SPNetworkParameters(path: "/homeModuleData")
// param.method = .get // let param = SPNetworkParameters(path: "/homeBannerAndNineSquare")
param.method = .get
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPHomeModuleModel>) in SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPHomeModuleModel>) in
completer?(response.data) completer?(response.data)

View File

@ -15,9 +15,9 @@ class SPVideoAPI: NSObject {
"short_play_id" : shortPlayId "short_play_id" : shortPlayId
] ]
if let videoId = videoId { // if let videoId = videoId {
parameters["video_id"] = videoId // }
} parameters["video_id"] = "0"
if let activityId = activityId { if let activityId = activityId {
parameters["activity_id"] = activityId parameters["activity_id"] = activityId
} }

View File

@ -17,16 +17,16 @@ import UIKit
#if DEBUG #if DEBUG
let SPBaseURL = "https://api-thimratv.thimratv.com" let SPBaseURL = "https://api-thimratv.thimratv.com"
let SPURLPathPrefix = "/0a2c5b02" let SPURLPathPrefix = "/93f03506"
let SPWebBaseURL = "https://www.thimratv.com" let SPWebBaseURL = "https://www.thimratv.com"
let SPCampaignWebURL = "https://campaign.thimratv.com" let SPCampaignWebURL = "https://campaign.moviatv.com"
#else #else
let SPBaseURL = "https://api-thimratv.thimratv.com" let SPBaseURL = "https://api-thimratv.thimratv.com"
let SPURLPathPrefix = "/0a2c5b02" let SPURLPathPrefix = "/93f03506"
let SPWebBaseURL = "https://www.thimratv.com" let SPWebBaseURL = "https://www.thimratv.com"
let SPCampaignWebURL = "https://campaign.thimratv.com" let SPCampaignWebURL = "https://campaign.moviatv.com"
#endif #endif
@ -42,6 +42,8 @@ let SPInformationSharingWebUrl = SPWebBaseURL + "/information_sharing"
let SPPersoInforDisclosureWebUrl = SPWebBaseURL + "/persoInfor_disclosure" let SPPersoInforDisclosureWebUrl = SPWebBaseURL + "/persoInfor_disclosure"
/// ///
let SPCivizatioConventionWebUrl = SPWebBaseURL + "/civizatio_convention" let SPCivizatioConventionWebUrl = SPWebBaseURL + "/civizatio_convention"
///
let SPMemberShipAgreement = SPWebBaseURL + "/member_ship_agreement"
/// ///
let SPFeedBackHomeWebUrl = SPCampaignWebURL + "/pages/leave/index" let SPFeedBackHomeWebUrl = SPCampaignWebURL + "/pages/leave/index"

View File

@ -97,6 +97,9 @@ extension SPExplorePlayerControlView {
self.viewController?.navigationController?.pushViewController(vc, animated: true) self.viewController?.navigationController?.pushViewController(vc, animated: true)
} }
override func handleEpisodeButton() {
self.handleAllEpisodeButton()
}
} }

View File

@ -64,8 +64,8 @@ class SPHomeHeaderView: UICollectionReusableView {
view.itemSize = .init(width: 234, height: Self.bannerHeight()) view.itemSize = .init(width: 234, height: Self.bannerHeight())
view.itemAlpha = true view.itemAlpha = true
view.itemZoomScale = 0.9 view.itemZoomScale = 0.9
view.itemSpacing = 10 view.itemSpacing = 30
view.rotationAngle = 10 view.rotationAngle = 12
view.delegate = self view.delegate = self
view.dataSource = self view.dataSource = self
view.hidesPageControl = true view.hidesPageControl = true

View File

@ -11,13 +11,15 @@ class SPLoginViewController: SPViewController {
private lazy var logoImageView: UIImageView = { private lazy var logoImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "login_logo_icon_01")) let imageView = UIImageView(image: UIImage(named: "login_logo_icon_01"))
imageView.layer.cornerRadius = 10
imageView.layer.masksToBounds = true
return imageView return imageView
}() }()
private lazy var nameImageView: UIImageView = { // private lazy var nameImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "login_logo_icon_02")) // let imageView = UIImageView(image: UIImage(named: "login_logo_icon_02"))
return imageView // return imageView
}() // }()
private lazy var stackView: UIStackView = { private lazy var stackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [faceBookButton, appleButton]) let stackView = UIStackView(arrangedSubviews: [faceBookButton, appleButton])
@ -136,7 +138,7 @@ extension SPLoginViewController {
private func _setupUI() { private func _setupUI() {
view.addSubview(logoImageView) view.addSubview(logoImageView)
view.addSubview(nameImageView) // view.addSubview(nameImageView)
view.addSubview(stackView) view.addSubview(stackView)
view.addSubview(agreementLabel) view.addSubview(agreementLabel)
// view.addSubview(faceBookButton) // view.addSubview(faceBookButton)
@ -146,15 +148,15 @@ extension SPLoginViewController {
make.top.equalToSuperview().offset(kSPStatusbarHeight + kSPMainW(120)) make.top.equalToSuperview().offset(kSPStatusbarHeight + kSPMainW(120))
} }
nameImageView.snp.makeConstraints { make in // nameImageView.snp.makeConstraints { make in
make.centerX.equalToSuperview() // make.centerX.equalToSuperview()
make.top.equalTo(logoImageView.snp.bottom).offset(24) // make.top.equalTo(logoImageView.snp.bottom).offset(24)
} // }
stackView.snp.makeConstraints { make in stackView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(37) make.left.equalToSuperview().offset(37)
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.top.equalTo(nameImageView.snp.bottom).offset(40) make.top.equalTo(logoImageView.snp.bottom).offset(40)
} }
let size = agreementLabel.textLayout?.textBoundingSize ?? .zero let size = agreementLabel.textLayout?.textBoundingSize ?? .zero

View File

@ -10,7 +10,7 @@ import UIKit
class SPMineHeaderView: UIView { class SPMineHeaderView: UIView {
var contentHeight: CGFloat { var contentHeight: CGFloat {
var height: CGFloat = kSPStatusbarHeight + 108 var height: CGFloat = kSPStatusbarHeight + 100
var stackHeight = 0.0 var stackHeight = 0.0
stackHeight += memberView.intrinsicContentSize.height stackHeight += memberView.intrinsicContentSize.height
@ -219,7 +219,7 @@ extension SPMineHeaderView {
stackView.snp.makeConstraints { make in stackView.snp.makeConstraints { make in
make.left.right.equalToSuperview() make.left.right.equalToSuperview()
make.top.equalToSuperview().offset(kSPStatusbarHeight + 108) make.top.equalToSuperview().offset(kSPStatusbarHeight + 100)
} }
} }

View File

@ -149,14 +149,10 @@ extension SPCollectListViewController: UICollectionViewDelegate, UICollectionVie
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let count = self.dataArr.count let count = self.dataArr.count
if count == 0 { if count == 0 {
let parameters = SPEmptyParameters(image: UIImage(named: "empty_image_01")) self.collectionView.addNormalEmpty()
let emptyState = SPEmptyState.normail(parameters: parameters)
self.collectionView.emptyState.format = emptyState.format
self.collectionView.emptyState.show(emptyState)
} else { } else {
self.collectionView.emptyState.hide() self.collectionView.hiddenEmpty()
} }
return count return count
} }

View File

@ -143,13 +143,11 @@ extension SPPlayHistoryViewController: UICollectionViewDelegate, UICollectionVie
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let count = self.dataArr.count let count = self.dataArr.count
if count == 0 { if count == 0 {
let parameters = SPEmptyParameters(image: UIImage(named: "empty_image_01")) self.collectionView.addNormalEmpty()
let emptyState = SPEmptyState.normail(parameters: parameters)
self.collectionView.emptyState.format = emptyState.format
self.collectionView.emptyState.show(emptyState)
} else { } else {
self.collectionView.emptyState.hide() self.collectionView.hiddenEmpty()
} }
return count return count

View File

@ -18,7 +18,7 @@ class SPPlayerDetailViewController: SPPlayerListViewController {
} }
var videoId: String? var videoId: String? = "0"
var shortPlayId: String? var shortPlayId: String?
var activityId: String? var activityId: String?
var playHistoryModel: SPShortModel? var playHistoryModel: SPShortModel?
@ -56,8 +56,14 @@ class SPPlayerDetailViewController: SPPlayerListViewController {
return view return view
}() }()
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(buyVipFinishNotification), name: SPIAPManager.buyVipFinishNotification, object: nil)
self.autoNextEpisode = true self.autoNextEpisode = true
self.dataSource = self self.dataSource = self
self.delegate = self self.delegate = self
@ -67,6 +73,8 @@ class SPPlayerDetailViewController: SPPlayerListViewController {
_addAction() _addAction()
_setupUI() _setupUI()
} }
@ -82,7 +90,7 @@ class SPPlayerDetailViewController: SPPlayerListViewController {
if videoInfo.is_lock == true { if videoInfo.is_lock == true {
self.pause() self.pause()
// //
let myCoin = SPLoginManager.manager.userInfo?.coin_left_total ?? 0 let myCoin = (SPLoginManager.manager.userInfo?.coin_left_total ?? 0) + (SPLoginManager.manager.userInfo?.send_coin_left_total ?? 0)
// //
let videoCoin = videoInfo.coins ?? 0 let videoCoin = videoInfo.coins ?? 0
@ -197,7 +205,18 @@ extension SPPlayerDetailViewController {
} }
}
@objc private func buyVipFinishNotification() {
guard SPLoginManager.manager.userInfo?.is_vip == true else { return }
self.detailModel?.episodeList?.forEach({
$0.is_lock = false
})
self.reloadData { [weak self] in
self?.play()
}
} }
} }
@ -253,6 +272,24 @@ extension SPPlayerDetailViewController {
self.reloadData { [weak self] in self.reloadData { [weak self] in
guard let self = self else { return } guard let self = self else { return }
if let videoInfo = self.detailModel?.video_info {
var row: Int?
self.detailModel?.episodeList?.enumerated().forEach({
if $1.id == videoInfo.id {
row = $0
}
})
if let row = row {
self.scrollToItem(indexPath: IndexPath(row: row, section: 0), animated: false)
} else {
self.play()
}
} else {
self.play()
}
/*
if let playHistoryModel = self.playHistoryModel { if let playHistoryModel = self.playHistoryModel {
var row: Int? var row: Int?
self.detailModel?.episodeList?.enumerated().forEach({ self.detailModel?.episodeList?.enumerated().forEach({
@ -267,6 +304,7 @@ extension SPPlayerDetailViewController {
} else { } else {
self.play() self.play()
} }
*/
} }
} }

View File

@ -40,7 +40,7 @@ class SPPlayBuyView: HWPanModalContentView {
let label = UILabel() let label = UILabel()
label.font = .fontMedium(ofSize: 16) label.font = .fontMedium(ofSize: 16)
label.textColor = .colorFFFFFF() label.textColor = .colorFFFFFF()
label.text = "Stroe".localized label.text = "Store".localized
return label return label
}() }()
@ -122,6 +122,10 @@ extension SPPlayBuyView {
guard let self = self else { return } guard let self = self else { return }
self.rechargeView.userInfo = SPLoginManager.manager.userInfo self.rechargeView.userInfo = SPLoginManager.manager.userInfo
} }
self.dismiss(animated: true) {
}
} }
@objc private func handleRestoreButton() { @objc private func handleRestoreButton() {
@ -186,7 +190,7 @@ extension SPPlayBuyView {
SPWalletAPI.requestPayTemplate { [weak self] templateModel in SPWalletAPI.requestPayTemplate { [weak self] templateModel in
guard let self = self else { return } guard let self = self else { return }
self.rechargeView.dataArr = templateModel?.list_coins self.rechargeView.dataArr = templateModel?.list_coins
self.memberView.dataArr = templateModel?.list_sub_vip self.memberView.setDataArr(dataArr: templateModel?.list_sub_vip)
self.stackView.removeAllArrangedSubview() self.stackView.removeAllArrangedSubview()

View File

@ -94,7 +94,7 @@ class SPPlayerControlView: UIView {
/// ///
private(set) lazy var rightFeatureView: UIStackView = { private(set) lazy var rightFeatureView: UIStackView = {
let view = UIStackView(arrangedSubviews: [collectButton]) let view = UIStackView(arrangedSubviews: [collectButton, episodeButton])
view.axis = .vertical view.axis = .vertical
view.spacing = 25 view.spacing = 25
return view return view
@ -107,6 +107,12 @@ class SPPlayerControlView: UIView {
return button return button
}() }()
private lazy var episodeButton: UIButton = {
let button = createFeatureButton(title: "Series".localized, image: UIImage(named: "episode_icon_02"))
button.addTarget(self, action: #selector(handleEpisodeButton), for: .touchUpInside)
return button
}()
deinit { deinit {
viewModel?.removeObserver(self, forKeyPath: "isPlaying") viewModel?.removeObserver(self, forKeyPath: "isPlaying")
NotificationCenter.default.removeObserver(self) NotificationCenter.default.removeObserver(self)
@ -204,6 +210,8 @@ extension SPPlayerControlView {
extension SPPlayerControlView { extension SPPlayerControlView {
@objc func handleEpisodeButton() {}
@objc private func hadlePlayAndOrPaused() { @objc private func hadlePlayAndOrPaused() {
self.viewModel?.handlePauseOrPlay?() self.viewModel?.handlePauseOrPlay?()

View File

@ -97,12 +97,6 @@ class SPPlayerDetailControlView: SPPlayerControlView {
private var timer: Timer? private var timer: Timer?
//MARK: UI //MARK: UI
private lazy var episodeButton: UIButton = {
let button = createFeatureButton(title: "Episodes".localized, image: UIImage(named: "episode_icon_02"))
button.addTarget(self, action: #selector(handleEpisodeButton), for: .touchUpInside)
return button
}()
private lazy var progressTimeLabel: UILabel = { private lazy var progressTimeLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.font = .fontRegular(ofSize: 12) label.font = .fontRegular(ofSize: 12)
@ -244,7 +238,6 @@ class SPPlayerDetailControlView: SPPlayerControlView {
extension SPPlayerDetailControlView { extension SPPlayerDetailControlView {
private func _setupUI() { private func _setupUI() {
self.rightFeatureView.addArrangedSubview(episodeButton)
toolView.addSubview(progressTimeLabel) toolView.addSubview(progressTimeLabel)
addSubview(retreatButton) addSubview(retreatButton)
@ -276,7 +269,7 @@ extension SPPlayerDetailControlView {
} }
extension SPPlayerDetailControlView { extension SPPlayerDetailControlView {
@objc private func handleEpisodeButton() { @objc override func handleEpisodeButton() {
self.viewModel?.handleEpisode?() self.viewModel?.handleEpisode?()
} }

View File

@ -16,8 +16,15 @@ class SPRewardsViewController: SPCampaignWebViewController {
NotificationCenter.default.addObserver(self, selector: #selector(loginStateDidChangeNotification), name: SPLoginManager.loginStateDidChangeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(loginStateDidChangeNotification), name: SPLoginManager.loginStateDidChangeNotification, object: nil)
self.webView.scrollView.sp_addRefreshHeader { [weak self] in
self?.handleHeaderRefresh(nil)
}
} }
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
self.reload()
self.webView.scrollView.sp_endHeaderRefreshing()
}

View File

@ -75,7 +75,13 @@ extension SPCoinOrderRecordViewController: UITableViewDelegate, UITableViewDataS
} }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataArr.count let count = self.dataArr.count
if count == 0 {
self.tableView.addNormalEmpty()
} else {
self.tableView.hiddenEmpty()
}
return count
} }
} }

View File

@ -81,7 +81,13 @@ extension SPConsumptionRecordsViewController: UITableViewDelegate, UITableViewDa
} }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataArr.count let count = self.dataArr.count
if count == 0 {
self.tableView.addNormalEmpty()
} else {
self.tableView.hiddenEmpty()
}
return count
} }
} }

View File

@ -83,7 +83,13 @@ extension SPRewardCoinsViewController: UITableViewDelegate, UITableViewDataSourc
} }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataArr.count let count = self.dataArr.count
if count == 0 {
self.tableView.addNormalEmpty()
} else {
self.tableView.hiddenEmpty()
}
return count
} }
} }

View File

@ -54,6 +54,47 @@ class SPStoreViewController: SPViewController {
return label return label
}() }()
private lazy var agreementLabel: YYLabel = {
let text1 = "Terms of Service".localized
let text2 = "Privacy Policy".localized
let text3 = "Renewal Agreement".localized
let text = "\(text1) | \(text2)\n\(text3)"
let range1 = text.ocString().range(of: text1)
let range2 = text.ocString().range(of: text2)
let range3 = text.ocString().range(of: text3)
let string = NSMutableAttributedString(string: text)
string.color = tipTextLabel.textColor
string.font = tipTextLabel.font
string.setTextHighlight(range1, color: nil, backgroundColor: nil) { [weak self] _, _, _, _ in
guard let self = self else { return }
let vc = SPWebViewController()
vc.urlStr = SPUserAgreementWebUrl
self.navigationController?.pushViewController(vc, animated: true)
}
string.setTextHighlight(range2, color: nil, backgroundColor: nil) { [weak self] _, _, _, _ in
guard let self = self else { return }
let vc = SPWebViewController()
vc.urlStr = SPPrivacyPolicyWebUrl
self.navigationController?.pushViewController(vc, animated: true)
}
string.setTextHighlight(range3, color: nil, backgroundColor: nil) { [weak self] _, _, _, _ in
guard let self = self else { return }
let vc = SPWebViewController()
vc.urlStr = SPMemberShipAgreement
self.navigationController?.pushViewController(vc, animated: true)
}
let label = YYLabel()
label.numberOfLines = 0
label.attributedText = string
return label
}()
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
self.title = "Store".localized self.title = "Store".localized
@ -105,6 +146,7 @@ extension SPStoreViewController {
scrollView.addSubview(stackView) scrollView.addSubview(stackView)
scrollView.addSubview(tipTitleLabel) scrollView.addSubview(tipTitleLabel)
scrollView.addSubview(tipTextLabel) scrollView.addSubview(tipTextLabel)
scrollView.addSubview(agreementLabel)
scrollView.snp.makeConstraints { make in scrollView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview() make.left.right.bottom.equalToSuperview()
@ -126,6 +168,12 @@ extension SPStoreViewController {
make.left.equalTo(tipTitleLabel) make.left.equalTo(tipTitleLabel)
make.right.lessThanOrEqualTo(stackView).offset(-24) make.right.lessThanOrEqualTo(stackView).offset(-24)
make.top.equalTo(tipTitleLabel.snp.bottom).offset(4) make.top.equalTo(tipTitleLabel.snp.bottom).offset(4)
// make.bottom.equalTo(-(kSPTabbarSafeBottomMargin + 10))
}
agreementLabel.snp.makeConstraints { make in
make.top.equalTo(tipTextLabel.snp.bottom).offset(20)
make.left.equalTo(tipTextLabel)
make.bottom.equalTo(-(kSPTabbarSafeBottomMargin + 10)) make.bottom.equalTo(-(kSPTabbarSafeBottomMargin + 10))
} }
} }
@ -139,7 +187,7 @@ extension SPStoreViewController {
SPWalletAPI.requestPayTemplate { [weak self] templateModel in SPWalletAPI.requestPayTemplate { [weak self] templateModel in
guard let self = self else { return } guard let self = self else { return }
self.rechargeView.dataArr = templateModel?.list_coins self.rechargeView.dataArr = templateModel?.list_coins
self.memberView.dataArr = templateModel?.list_sub_vip self.memberView.setDataArr(dataArr: templateModel?.list_sub_vip)
self.stackView.removeAllArrangedSubview() self.stackView.removeAllArrangedSubview()

View File

@ -74,7 +74,13 @@ extension SPVIPOrderRecordViewController: UITableViewDelegate, UITableViewDataSo
} }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataArr.count let count = self.dataArr.count
if count == 0 {
self.tableView.addNormalEmpty()
} else {
self.tableView.hiddenEmpty()
}
return count
} }
} }

View File

@ -26,7 +26,7 @@ class SPCoinRechargeView: UIView {
var userInfo: SPUserInfo? { var userInfo: SPUserInfo? {
didSet { didSet {
coinLabel.text = "\(userInfo?.coin_left_total ?? 0)" coinLabel.text = "\((userInfo?.coin_left_total ?? 0) + (userInfo?.send_coin_left_total ?? 0))"
} }
} }
@ -38,7 +38,7 @@ class SPCoinRechargeView: UIView {
let label = UILabel() let label = UILabel()
label.font = .fontRegular(ofSize: 14) label.font = .fontRegular(ofSize: 14)
label.textColor = .colorFFFFFF(alpha: 0.7) label.textColor = .colorFFFFFF(alpha: 0.7)
label.text = "Coins Balance:" label.text = "Coins Balance:".localized
return label return label
}() }()

View File

@ -19,13 +19,7 @@ class SPMemberRechargeView: UIView {
/// ///
var buyFinishHandle: (() -> Void)? var buyFinishHandle: (() -> Void)?
var dataArr: [SPPayTemplateItem]? { private var dataArr: [SPPayTemplateItem]?
didSet {
self.invalidateIntrinsicContentSize()
self.collectionView.reloadData()
}
}
var shortPlayId: String? var shortPlayId: String?
var videoId: String? var videoId: String?
@ -67,6 +61,19 @@ class SPMemberRechargeView: UIView {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
///
func setDataArr(dataArr: [SPPayTemplateItem]?) {
self.dataArr = []
dataArr?.forEach({
if $0.vip_type_key == .quarter {
self.dataArr?.append($0)
}
})
self.collectionView.reloadData()
self.invalidateIntrinsicContentSize()
}
} }
extension SPMemberRechargeView { extension SPMemberRechargeView {

View File

@ -33,7 +33,7 @@ extension SPEmptyState: CustomState {
var title: String? { var title: String? {
switch self { switch self {
case .normail(let parameters): case .normail(_):
return nil return nil
} }
@ -53,8 +53,9 @@ extension SPEmptyState {
var format = EmptyStateFormat() var format = EmptyStateFormat()
format.backgroundColor = .clear format.backgroundColor = .clear
format.imageSize = self.image?.size ?? .zero format.imageSize = self.image?.size ?? .zero
// format.verticalMargin = -10 format.animation = nil
// format.verticalMargin = -50
//
// format.buttonWidth = 107 // format.buttonWidth = 107
// format.buttonTopMargin = 10 // format.buttonTopMargin = 10
// format.buttonColor = .system_fill_primary_100 // format.buttonColor = .system_fill_primary_100

View File

@ -0,0 +1,23 @@
//
// UIScrollView+Empty.swift
// MoviaBox
//
// Created by on 2025/5/8.
//
import UIKit
extension UIScrollView {
func addNormalEmpty() {
let parameters = SPEmptyParameters()
let emptyState = SPEmptyState.normail(parameters: parameters)
self.emptyState.format = emptyState.format
self.emptyState.show(emptyState)
}
func hiddenEmpty() {
self.emptyState.hide()
}
}

View File

@ -132,7 +132,7 @@ class SPPlayer: NSObject {
/// ///
func prepare() { func prepare() {
// self.player.prepareToPlay() self.player.prepareToPlay()
} }
func stop() { func stop() {
@ -254,6 +254,7 @@ extension SPPlayer {
self.replay() self.replay()
} else { } else {
self.isPlaying = false self.isPlaying = false
self.prepare()
self.delegate?.sp_playCompletion?(self) self.delegate?.sp_playCompletion?(self)
} }
} }

View File

@ -34,7 +34,7 @@ class SPIAPManager: NSObject {
/// ///
func startRecharge(model: SPPayTemplateItem, shortPlayId: String? = nil, videoId: String? = nil, handler: CompletionHandler? = nil) { func startRecharge(model: SPPayTemplateItem, shortPlayId: String? = nil, videoId: String? = nil, handler: CompletionHandler? = nil) {
if let waitRestoreModel = self.waitRestoreModel { if let _ = self.waitRestoreModel {
SPToast.show(text: "kToastMessage_02".localized) SPToast.show(text: "kToastMessage_02".localized)
handler?(false) handler?(false)
return return
@ -46,6 +46,11 @@ class SPIAPManager: NSObject {
} }
self.completionHandler = handler self.completionHandler = handler
self.waitRestoreModel = SPWaitRestoreModel() self.waitRestoreModel = SPWaitRestoreModel()
if model.buy_type == .coins {
self.waitRestoreModel?.buyType = .coins
} else if model.buy_type == .subVip {
self.waitRestoreModel?.buyType = .vip
}
let productId = SPIAPManager.IAPPrefix + (model.ios_template_id ?? "") let productId = SPIAPManager.IAPPrefix + (model.ios_template_id ?? "")
@ -86,26 +91,35 @@ class SPIAPManager: NSObject {
SPHUD.show() SPHUD.show()
} }
SPWalletAPI.requestVerifyOrder(orderCode: orderCode, payId: payId, productId: productId, purchaseToken: receipt) { model in SPWalletAPI.requestVerifyOrder(orderCode: orderCode, payId: payId, productId: productId, purchaseToken: receipt) { model in
if model?.status == "success" { if isLoding {
self.waitRestoreModel = nil SPHUD.dismiss()
UserDefaults.jx_setObject(self.waitRestoreModel, forKey: kSPWaitRestoreIAPDefaultsKey) }
guard let model = model else {
completer?(false)
return
}
let buyType = self.waitRestoreModel?.buyType
self.waitRestoreModel = nil
UserDefaults.jx_setObject(self.waitRestoreModel, forKey: kSPWaitRestoreIAPDefaultsKey)
if model.status == "success" {
SPLoginManager.manager.userInfo?.is_vip = true
if isLoding { if isLoding {
SPToast.show(text: "success".localized) SPToast.show(text: "success".localized)
} }
completer?(true) completer?(true)
if buyType == .vip {
NotificationCenter.default.post(name: SPIAPManager.buyVipFinishNotification, object: nil)
}
} else { } else {
// SPToast.show(text: "failure".localized) // SPToast.show(text: "failure".localized)
completer?(false) completer?(false)
} }
if isLoding {
SPHUD.dismiss()
}
} }
} }
} }
//MARK: -------------- JXIAPManagerDelegate -------------- //MARK: -------------- JXIAPManagerDelegate --------------
@ -131,11 +145,23 @@ extension SPIAPManager: JXIAPManagerDelegate {
self.orderCode = nil self.orderCode = nil
self.payId = nil self.payId = nil
if model?.status == "success" { guard let model = model else {
self.waitRestoreModel = nil self.completionHandler?(false)
UserDefaults.jx_setObject(self.waitRestoreModel, forKey: kSPWaitRestoreIAPDefaultsKey) return
}
let buyType = self.waitRestoreModel?.buyType
self.waitRestoreModel = nil
UserDefaults.jx_setObject(self.waitRestoreModel, forKey: kSPWaitRestoreIAPDefaultsKey)
if model.status == "success" {
SPLoginManager.manager.userInfo?.is_vip = true
SPToast.show(text: "success".localized) SPToast.show(text: "success".localized)
self.completionHandler?(true) self.completionHandler?(true)
if buyType == .vip {
NotificationCenter.default.post(name: SPIAPManager.buyVipFinishNotification, object: nil)
}
} else { } else {
self.completionHandler?(false) self.completionHandler?(false)
} }
@ -158,3 +184,9 @@ extension SPIAPManager: JXIAPManagerDelegate {
} }
} }
extension SPIAPManager {
///
@objc static let buyVipFinishNotification = NSNotification.Name(rawValue: "SPIAPManager.buyVipFinishNotification")
}

View File

@ -13,5 +13,6 @@ class SPIAPVerifyModel: SPModel, SmartCodable {
var status: String? var status: String?
var money: String? var money: String?
var is_backhaul: String? var is_backhaul: String?
var code: String?
} }

View File

@ -16,6 +16,7 @@ class SPWaitRestoreModel: SPModel, NSSecureCoding {
var payId: String? var payId: String?
var productId: String? var productId: String?
var receipt: String? var receipt: String?
var buyType: SPWalletAPI.BuyType?
required init() { } required init() { }
@ -31,6 +32,7 @@ class SPWaitRestoreModel: SPModel, NSSecureCoding {
coder.encode(payId, forKey: "payId") coder.encode(payId, forKey: "payId")
coder.encode(productId, forKey: "productId") coder.encode(productId, forKey: "productId")
coder.encode(receipt, forKey: "receipt") coder.encode(receipt, forKey: "receipt")
coder.encode(buyType?.rawValue, forKey: "buyType")
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
@ -39,6 +41,9 @@ class SPWaitRestoreModel: SPModel, NSSecureCoding {
payId = coder.decodeObject(of: NSString.self, forKey: "payId") as? String payId = coder.decodeObject(of: NSString.self, forKey: "payId") as? String
productId = coder.decodeObject(of: NSString.self, forKey: "productId") as? String productId = coder.decodeObject(of: NSString.self, forKey: "productId") as? String
receipt = coder.decodeObject(of: NSString.self, forKey: "receipt") as? String receipt = coder.decodeObject(of: NSString.self, forKey: "receipt") as? String
if let type = coder.decodeObject(of: NSString.self, forKey: "buyType") as? String {
buyType = SPWalletAPI.BuyType(rawValue: type)
}
} }
} }

View File

@ -8,6 +8,11 @@
<array> <array>
<string>Default</string> <string>Default</string>
</array> </array>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:moviaboxapp.go.link</string>
<string>applinks:www.moviatv.com</string>
</array>
<key>keychain-access-groups</key> <key>keychain-access-groups</key>
<array/> <array/>
</dict> </dict>

View File

@ -5,12 +5,12 @@
"scale" : "1x" "scale" : "1x"
}, },
{ {
"filename" : "Episodes@2x.png", "filename" : "Group 79@2x.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"filename" : "Episodes@3x.png", "filename" : "Group 79@3x.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "3x" "scale" : "3x"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

View File

@ -5,12 +5,11 @@
"scale" : "1x" "scale" : "1x"
}, },
{ {
"filename" : "APP图标 2@2x.png", "filename" : "LOGOMoviaBox.jpg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"filename" : "APP图标 2@3x.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "3x" "scale" : "3x"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -5,12 +5,12 @@
"scale" : "1x" "scale" : "1x"
}, },
{ {
"filename" : "空空如也@2x.png", "filename" : "image 39@2x.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"filename" : "空空如也@3x.png", "filename" : "image 39@3x.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "3x" "scale" : "3x"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

View File

@ -14,6 +14,14 @@
<string>fb1228062532660582</string> <string>fb1228062532660582</string>
</array> </array>
</dict> </dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>MoviaTV</string>
</array>
</dict>
<dict/> <dict/>
</array> </array>
<key>FacebookAppID</key> <key>FacebookAppID</key>
@ -48,6 +56,11 @@
</array> </array>
</dict> </dict>
</dict> </dict>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
</dict> </dict>

View File

@ -17,3 +17,4 @@
#import "WMPageController.h" #import "WMPageController.h"
#import <SVProgressHUD/SVProgressHUD.h> #import <SVProgressHUD/SVProgressHUD.h>
#import <TZImagePickerController/TZImagePickerController.h> #import <TZImagePickerController/TZImagePickerController.h>
#import <Adjust.h>

View File

@ -19,13 +19,15 @@
"Trending Now" = "Trending Now"; "Trending Now" = "Trending Now";
"Editor's Hotlist" = "Editor's Hotlist"; "Editor's Hotlist" = "Editor's Hotlist";
"Shorts for You" = "Shorts for You"; "Shorts for You" = "Shorts for You";
"Episodes" = "Episodes"; "Series" = "Series";
"Save" = "Save"; "Save" = "Save";
"Added" = "Added"; "Added" = "Added";
"FeedBack" = "FeedBack"; "FeedBack" = "FeedBack";
"Settings" = "Settings"; "Settings" = "Settings";
"Language" = "Language"; "Language" = "Language";
"Privacy Policy" = "Privacy Policy"; "Privacy Policy" = "Privacy Policy";
"Terms of Service" = "Terms of Service";
"Renewal Agreement" = "Renewal Agreement";
"User Agreement" = "User Agreement"; "User Agreement" = "User Agreement";
"About Us" = "About Us"; "About Us" = "About Us";
"My list" = "My list"; "My list" = "My list";
@ -67,7 +69,6 @@
"Consumption records" = "Consumption records"; "Consumption records" = "Consumption records";
"Purchase records" = "Purchase records"; "Purchase records" = "Purchase records";
"Reward Coins" = "Reward Coins"; "Reward Coins" = "Reward Coins";
"Stroe" = "Stroe";
"Coins Balance:" = "Coins Balance:"; "Coins Balance:" = "Coins Balance:";
"Membership" = "Membership"; "Membership" = "Membership";
"%@ Bonus" = "%@ Bonus"; "%@ Bonus" = "%@ Bonus";
@ -106,6 +107,6 @@
"kLoginAgreementText" = "By continuing, you agree to the User Agreement and Privacy Policy"; "kLoginAgreementText" = "By continuing, you agree to the User Agreement and Privacy Policy";
"kBuyMemberTipText" = "Auto renew · Cancel anytime"; "kBuyMemberTipText" = "Auto renew · Cancel anytime";
"kStoreTipTitle" = "Related terms and conditions:"; "kStoreTipTitle" = "Related terms and conditions:";
"kStoreTipText" = "1. Coins can only be used within this application.2. Payment: The purchase will be charged to your iTunes account. 3. Renewal: Your Apple iTunes account will be charged within 24 hours before the expiration and the subscription period will be extended for another subscription cycle upon successful deduction.4. Cancellation: To cancel the subscription renewal, please turn off the automatic renewal function in the iTunes/Apple ID settings at least 24 hours before the current subscription period expires. If canceled within the last 24 hours before expiration, a subscription fee will still be charged. 5. Payment successful but recharge not taking effect for an extended period? Click here to refresh or send an email to: cs.jiaer.developer@icloud.com. 6. Manage your subscriptions: You can view, change, or cancel your subscriptions. Terms of Service | Privacy Policy Renewal Agreement"; "kStoreTipText" = "1. Coins can only be used within this application.2. Payment: The purchase will be charged to your iTunes account. 3. Renewal: Your Apple iTunes account will be charged within 24 hours before the expiration and the subscription period will be extended for another subscription cycle upon successful deduction.4. Cancellation: To cancel the subscription renewal, please turn off the automatic renewal function in the iTunes/Apple ID settings at least 24 hours before the current subscription period expires. If canceled within the last 24 hours before expiration, a subscription fee will still be charged. 5. Payment successful but recharge not taking effect for an extended period? Click here to refresh or send an email to: cs.jiaer.developer@icloud.com. 6. Manage your subscriptions: You can view, change, or cancel your subscriptions. ";
"kDeleteAccountCheckText" = "I accept the deletion risk and agree to delete my account"; "kDeleteAccountCheckText" = "I accept the deletion risk and agree to delete my account";

View File

@ -46,7 +46,7 @@ class JXIAPManager: NSObject {
private var payment: SKPayment? private var payment: SKPayment?
private var product: SKProduct? private var product: SKProduct?
private var productId: String = "" private var productId: String?
private var orderId: String? private var orderId: String?
private var applicationUsername: String? { private var applicationUsername: String? {
get { get {
@ -112,7 +112,10 @@ extension JXIAPManager: SKProductsRequestDelegate {
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
guard let product = response.products.first else { guard let product = response.products.first else {
DispatchQueue.main.async { DispatchQueue.main.async {
self.delegate?.jx_iapPayFailed?(productId: self.productId, code: .noProduct) if let productId = self.productId {
self.productId = nil
self.delegate?.jx_iapPayFailed?(productId: productId, code: .noProduct)
}
} }
return return
} }
@ -128,7 +131,7 @@ extension JXIAPManager: SKPaymentTransactionObserver {
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions { for transaction in transactions {
spLog(message: "transactionState = \(transaction.transactionState)")
switch transaction.transactionState { switch transaction.transactionState {
case .purchased: case .purchased:
DispatchQueue.main.async { DispatchQueue.main.async {
@ -169,14 +172,21 @@ extension JXIAPManager: SKPaymentTransactionObserver {
extension JXIAPManager { extension JXIAPManager {
private func completeTransaction(transaction: SKPaymentTransaction) { private func completeTransaction(transaction: SKPaymentTransaction) {
// //
if let _ = transaction.original, transaction.payment.applicationUsername == nil { // if let _ = transaction.original, transaction.payment.applicationUsername == nil {
return // return
} // }
// //
if let _ = transaction.original, transaction.payment.applicationUsername != nil { // if let _ = transaction.original, transaction.payment.applicationUsername != nil {
self.delegate?.jx_iapPayFailed?(productId: productId, code: .unknown) // self.delegate?.jx_iapPayFailed?(productId: productId, code: .unknown)
return // return
} // }
spLog(message: "transactionDate = \(String(describing: transaction.transactionDate))")
spLog(message: "nowDate = \(Date())")
spLog(message: "productIdentifier = \(transaction.payment.productIdentifier)")
guard let productId = self.productId, productId == transaction.payment.productIdentifier else { return }
self.productId = nil
guard let receiptURL = Bundle.main.appStoreReceiptURL else { return } guard let receiptURL = Bundle.main.appStoreReceiptURL else { return }
let receiptData = NSData(contentsOf: receiptURL) let receiptData = NSData(contentsOf: receiptURL)
@ -184,15 +194,20 @@ extension JXIAPManager {
guard let transactionIdentifier = transaction.transactionIdentifier else { return } guard let transactionIdentifier = transaction.transactionIdentifier else { return }
self.delegate?.jx_iapPaySuccess?(productId: productId, receipt: encodeStr, transactionIdentifier: transactionIdentifier) self.delegate?.jx_iapPaySuccess?(productId: productId, receipt: encodeStr, transactionIdentifier: transactionIdentifier)
} }
private func failedTransaction(transaction: SKPaymentTransaction) { private func failedTransaction(transaction: SKPaymentTransaction) {
let error = transaction.error as? SKError let error = transaction.error as? SKError
guard let productId = self.productId else { return }
self.productId = nil
switch error?.code { switch error?.code {
case SKError.paymentCancelled: case SKError.paymentCancelled:
self.delegate?.jx_iapPayFailed?(productId: productId, code: .cancelled) self.delegate?.jx_iapPayFailed?(productId: productId, code: .cancelled)
default: default:
self.delegate?.jx_iapPayFailed?(productId: productId, code: .unknown) self.delegate?.jx_iapPayFailed?(productId: productId, code: .unknown)
} }
} }
} }

View File

@ -31,7 +31,7 @@ target 'MoviaBox' do
pod 'WMZPageController' #分页控制器 pod 'WMZPageController' #分页控制器
pod 'SVProgressHUD' #HUD pod 'SVProgressHUD' #HUD
pod 'TZImagePickerController' #相册 pod 'TZImagePickerController' #相册
# pod 'FBSDKCoreKit' # Facebook 基础 pod 'Adjust' # Adjust
# pod 'FBSDKLoginKit' # Facebook 登录
end end

View File

@ -1,4 +1,9 @@
PODS: PODS:
- Adjust (5.3.0):
- Adjust/Adjust (= 5.3.0)
- Adjust/Adjust (5.3.0):
- AdjustSignature (= 3.35.2)
- AdjustSignature (3.35.2)
- Alamofire (5.10.2) - Alamofire (5.10.2)
- CocoaAsyncSocket (7.6.5) - CocoaAsyncSocket (7.6.5)
- EmptyStateKit (1.1.0) - EmptyStateKit (1.1.0)
@ -32,6 +37,7 @@ PODS:
- ZFPlayer/Core (4.1.4) - ZFPlayer/Core (4.1.4)
DEPENDENCIES: DEPENDENCIES:
- Adjust
- EmptyStateKit - EmptyStateKit
- HWPanModal - HWPanModal
- Kingfisher - Kingfisher
@ -50,6 +56,8 @@ DEPENDENCIES:
SPEC REPOS: SPEC REPOS:
https://github.com/CocoaPods/Specs.git: https://github.com/CocoaPods/Specs.git:
- Adjust
- AdjustSignature
- Kingfisher - Kingfisher
- ZFPlayer - ZFPlayer
trunk: trunk:
@ -70,6 +78,8 @@ SPEC REPOS:
- YYKit - YYKit
SPEC CHECKSUMS: SPEC CHECKSUMS:
Adjust: 3389abb14f761aa0d1966d52814864df9606535e
AdjustSignature: 23b9e5d4adcadffc303bb6b410fde617dd88504f
Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496 Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
EmptyStateKit: dc41e9ce5c6089f67a49d063bce73ade9f2ba73f EmptyStateKit: dc41e9ce5c6089f67a49d063bce73ade9f2ba73f
@ -88,6 +98,6 @@ SPEC CHECKSUMS:
YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7 YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7
ZFPlayer: 5cf39e8d9f0c2394a014b0db4767b5b5a6bffe13 ZFPlayer: 5cf39e8d9f0c2394a014b0db4767b5b5a6bffe13
PODFILE CHECKSUM: 38415be06361089ed99017f8e3cdad9bd57ec94a PODFILE CHECKSUM: 2a79f81260b8df4d6be58f4acb217732b1cd49ab
COCOAPODS: 1.16.2 COCOAPODS: 1.16.2