bug修复,空白页面开发
@ -7,6 +7,8 @@
|
||||
objects = {
|
||||
|
||||
/* 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 */; };
|
||||
1BF22FD32DC2169B0082429A /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 1BF22FD22DC2169B0082429A /* FirebaseCore */; };
|
||||
1BF22FD52DC2169B0082429A /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 1BF22FD42DC2169B0082429A /* FirebaseMessaging */; };
|
||||
@ -49,6 +51,8 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1BF22FD52DC2169B0082429A /* FirebaseMessaging in Frameworks */,
|
||||
1BE7892B2DCB0E530001A8F1 /* FacebookCore in Frameworks */,
|
||||
1BE7892D2DCB0E530001A8F1 /* FacebookLogin in Frameworks */,
|
||||
91D08C5AEAE459A3B8EA48C6 /* Pods_MoviaBox.framework in Frameworks */,
|
||||
1BF22FD32DC2169B0082429A /* FirebaseCore in Frameworks */,
|
||||
1BF22FD12DC2169B0082429A /* FirebaseAnalytics in Frameworks */,
|
||||
@ -146,6 +150,7 @@
|
||||
minimizedProjectReferenceProxies = 1;
|
||||
packageReferences = (
|
||||
1BF22FCF2DC2169B0082429A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
|
||||
1BE789292DCB0E530001A8F1 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */,
|
||||
);
|
||||
preferredProjectObjectVersion = 77;
|
||||
productRefGroup = 1DBC405A2DA4EDFC0093FCB0 /* Products */;
|
||||
@ -455,6 +460,14 @@
|
||||
/* End XCConfigurationList 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" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
|
||||
@ -466,6 +479,16 @@
|
||||
/* End XCRemoteSwiftPackageReference 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 */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 1BF22FCF2DC2169B0082429A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"originHash" : "c63c63846d9c539229e96de38d6af51417e28c0ee9a0bc48bd0f0f19d923c329",
|
||||
"originHash" : "c47d0d305ed42c8e2ce41760feb2ed27468bf8a4c789d72416aad5bed8e64bd2",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "abseil-cpp-binary",
|
||||
@ -19,6 +19,15 @@
|
||||
"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",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
@ -34,11 +34,25 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
|
||||
}
|
||||
///APP处于前台是接收通知消息
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||
completionHandler([.badge, .alert])
|
||||
completionHandler([.badge, .banner])
|
||||
}
|
||||
|
||||
///点击通知消息进入app
|
||||
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()
|
||||
}
|
||||
|
||||
|
31
MoviaBox/AppDelegate/AppDelegate+Thirdparty.swift
Normal 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)
|
||||
}
|
||||
|
||||
}
|
@ -6,9 +6,6 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
#if canImport(FacebookCore)
|
||||
import FacebookCore
|
||||
#endif
|
||||
|
||||
@main
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
@ -16,10 +13,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
///Facebook
|
||||
#if canImport(FacebookCore)
|
||||
ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
#endif
|
||||
|
||||
|
||||
self.registThirdparty(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
|
||||
self.appConfig()
|
||||
///注册消息通知
|
||||
@ -31,7 +27,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: SPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
|
||||
|
||||
|
||||
|
||||
let _ = JXIAPManager.manager
|
||||
|
||||
// SPLoginManager.manager.requestVisitorLogin(completer: nil)
|
||||
SPLoginManager.manager.updateUserInfo(completer: nil)
|
||||
|
@ -37,8 +37,9 @@ class SPHomeAPI: NSObject {
|
||||
|
||||
///首页模块接口
|
||||
static func requestHomeModuleData(completer: ((_ model: SPHomeModuleModel?) -> Void)?) {
|
||||
let param = SPNetworkParameters(path: "/homeBannerAndNineSquare")
|
||||
// param.method = .get
|
||||
var param = SPNetworkParameters(path: "/homeModuleData")
|
||||
// let param = SPNetworkParameters(path: "/homeBannerAndNineSquare")
|
||||
param.method = .get
|
||||
|
||||
SPNetwork.request(parameters: param) { (response: SPNetworkResponse<SPHomeModuleModel>) in
|
||||
completer?(response.data)
|
||||
|
@ -15,9 +15,9 @@ class SPVideoAPI: NSObject {
|
||||
"short_play_id" : shortPlayId
|
||||
]
|
||||
|
||||
if let videoId = videoId {
|
||||
parameters["video_id"] = videoId
|
||||
}
|
||||
// if let videoId = videoId {
|
||||
// }
|
||||
parameters["video_id"] = "0"
|
||||
if let activityId = activityId {
|
||||
parameters["activity_id"] = activityId
|
||||
}
|
||||
|
@ -17,16 +17,16 @@ import UIKit
|
||||
|
||||
#if DEBUG
|
||||
let SPBaseURL = "https://api-thimratv.thimratv.com"
|
||||
let SPURLPathPrefix = "/0a2c5b02"
|
||||
let SPURLPathPrefix = "/93f03506"
|
||||
|
||||
let SPWebBaseURL = "https://www.thimratv.com"
|
||||
let SPCampaignWebURL = "https://campaign.thimratv.com"
|
||||
let SPCampaignWebURL = "https://campaign.moviatv.com"
|
||||
#else
|
||||
let SPBaseURL = "https://api-thimratv.thimratv.com"
|
||||
let SPURLPathPrefix = "/0a2c5b02"
|
||||
let SPURLPathPrefix = "/93f03506"
|
||||
|
||||
let SPWebBaseURL = "https://www.thimratv.com"
|
||||
let SPCampaignWebURL = "https://campaign.thimratv.com"
|
||||
let SPCampaignWebURL = "https://campaign.moviatv.com"
|
||||
#endif
|
||||
|
||||
|
||||
@ -42,6 +42,8 @@ let SPInformationSharingWebUrl = SPWebBaseURL + "/information_sharing"
|
||||
let SPPersoInforDisclosureWebUrl = SPWebBaseURL + "/persoInfor_disclosure"
|
||||
///全国青少年互联网文明公约
|
||||
let SPCivizatioConventionWebUrl = SPWebBaseURL + "/civizatio_convention"
|
||||
///会员服务协议
|
||||
let SPMemberShipAgreement = SPWebBaseURL + "/member_ship_agreement"
|
||||
|
||||
///反馈首页
|
||||
let SPFeedBackHomeWebUrl = SPCampaignWebURL + "/pages/leave/index"
|
||||
|
@ -97,6 +97,9 @@ extension SPExplorePlayerControlView {
|
||||
self.viewController?.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
override func handleEpisodeButton() {
|
||||
self.handleAllEpisodeButton()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,8 @@ class SPHomeHeaderView: UICollectionReusableView {
|
||||
view.itemSize = .init(width: 234, height: Self.bannerHeight())
|
||||
view.itemAlpha = true
|
||||
view.itemZoomScale = 0.9
|
||||
view.itemSpacing = 10
|
||||
view.rotationAngle = 10
|
||||
view.itemSpacing = 30
|
||||
view.rotationAngle = 12
|
||||
view.delegate = self
|
||||
view.dataSource = self
|
||||
view.hidesPageControl = true
|
||||
|
@ -11,13 +11,15 @@ class SPLoginViewController: SPViewController {
|
||||
|
||||
private lazy var logoImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "login_logo_icon_01"))
|
||||
imageView.layer.cornerRadius = 10
|
||||
imageView.layer.masksToBounds = true
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var nameImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "login_logo_icon_02"))
|
||||
return imageView
|
||||
}()
|
||||
// private lazy var nameImageView: UIImageView = {
|
||||
// let imageView = UIImageView(image: UIImage(named: "login_logo_icon_02"))
|
||||
// return imageView
|
||||
// }()
|
||||
|
||||
private lazy var stackView: UIStackView = {
|
||||
let stackView = UIStackView(arrangedSubviews: [faceBookButton, appleButton])
|
||||
@ -136,7 +138,7 @@ extension SPLoginViewController {
|
||||
|
||||
private func _setupUI() {
|
||||
view.addSubview(logoImageView)
|
||||
view.addSubview(nameImageView)
|
||||
// view.addSubview(nameImageView)
|
||||
view.addSubview(stackView)
|
||||
view.addSubview(agreementLabel)
|
||||
// view.addSubview(faceBookButton)
|
||||
@ -146,15 +148,15 @@ extension SPLoginViewController {
|
||||
make.top.equalToSuperview().offset(kSPStatusbarHeight + kSPMainW(120))
|
||||
}
|
||||
|
||||
nameImageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(logoImageView.snp.bottom).offset(24)
|
||||
}
|
||||
// nameImageView.snp.makeConstraints { make in
|
||||
// make.centerX.equalToSuperview()
|
||||
// make.top.equalTo(logoImageView.snp.bottom).offset(24)
|
||||
// }
|
||||
|
||||
stackView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(37)
|
||||
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
|
||||
|
@ -10,7 +10,7 @@ import UIKit
|
||||
class SPMineHeaderView: UIView {
|
||||
|
||||
var contentHeight: CGFloat {
|
||||
var height: CGFloat = kSPStatusbarHeight + 108
|
||||
var height: CGFloat = kSPStatusbarHeight + 100
|
||||
|
||||
var stackHeight = 0.0
|
||||
stackHeight += memberView.intrinsicContentSize.height
|
||||
@ -219,7 +219,7 @@ extension SPMineHeaderView {
|
||||
|
||||
stackView.snp.makeConstraints { make in
|
||||
make.left.right.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(kSPStatusbarHeight + 108)
|
||||
make.top.equalToSuperview().offset(kSPStatusbarHeight + 100)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,14 +149,10 @@ extension SPCollectListViewController: UICollectionViewDelegate, UICollectionVie
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
let count = self.dataArr.count
|
||||
if count == 0 {
|
||||
let parameters = SPEmptyParameters(image: UIImage(named: "empty_image_01"))
|
||||
let emptyState = SPEmptyState.normail(parameters: parameters)
|
||||
self.collectionView.emptyState.format = emptyState.format
|
||||
self.collectionView.emptyState.show(emptyState)
|
||||
self.collectionView.addNormalEmpty()
|
||||
} else {
|
||||
self.collectionView.emptyState.hide()
|
||||
self.collectionView.hiddenEmpty()
|
||||
}
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
|
@ -143,13 +143,11 @@ extension SPPlayHistoryViewController: UICollectionViewDelegate, UICollectionVie
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
let count = self.dataArr.count
|
||||
|
||||
if count == 0 {
|
||||
let parameters = SPEmptyParameters(image: UIImage(named: "empty_image_01"))
|
||||
let emptyState = SPEmptyState.normail(parameters: parameters)
|
||||
self.collectionView.emptyState.format = emptyState.format
|
||||
self.collectionView.emptyState.show(emptyState)
|
||||
self.collectionView.addNormalEmpty()
|
||||
} else {
|
||||
self.collectionView.emptyState.hide()
|
||||
self.collectionView.hiddenEmpty()
|
||||
}
|
||||
|
||||
return count
|
||||
|
@ -18,7 +18,7 @@ class SPPlayerDetailViewController: SPPlayerListViewController {
|
||||
}
|
||||
|
||||
|
||||
var videoId: String?
|
||||
var videoId: String? = "0"
|
||||
var shortPlayId: String?
|
||||
var activityId: String?
|
||||
var playHistoryModel: SPShortModel?
|
||||
@ -56,8 +56,14 @@ class SPPlayerDetailViewController: SPPlayerListViewController {
|
||||
return view
|
||||
}()
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(buyVipFinishNotification), name: SPIAPManager.buyVipFinishNotification, object: nil)
|
||||
|
||||
self.autoNextEpisode = true
|
||||
self.dataSource = self
|
||||
self.delegate = self
|
||||
@ -67,6 +73,8 @@ class SPPlayerDetailViewController: SPPlayerListViewController {
|
||||
_addAction()
|
||||
|
||||
_setupUI()
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -82,7 +90,7 @@ class SPPlayerDetailViewController: SPPlayerListViewController {
|
||||
if videoInfo.is_lock == true {
|
||||
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
|
||||
|
||||
@ -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
|
||||
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 {
|
||||
var row: Int?
|
||||
self.detailModel?.episodeList?.enumerated().forEach({
|
||||
@ -267,6 +304,7 @@ extension SPPlayerDetailViewController {
|
||||
} else {
|
||||
self.play()
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class SPPlayBuyView: HWPanModalContentView {
|
||||
let label = UILabel()
|
||||
label.font = .fontMedium(ofSize: 16)
|
||||
label.textColor = .colorFFFFFF()
|
||||
label.text = "Stroe".localized
|
||||
label.text = "Store".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
@ -122,6 +122,10 @@ extension SPPlayBuyView {
|
||||
guard let self = self else { return }
|
||||
self.rechargeView.userInfo = SPLoginManager.manager.userInfo
|
||||
}
|
||||
|
||||
self.dismiss(animated: true) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func handleRestoreButton() {
|
||||
@ -186,7 +190,7 @@ extension SPPlayBuyView {
|
||||
SPWalletAPI.requestPayTemplate { [weak self] templateModel in
|
||||
guard let self = self else { return }
|
||||
self.rechargeView.dataArr = templateModel?.list_coins
|
||||
self.memberView.dataArr = templateModel?.list_sub_vip
|
||||
self.memberView.setDataArr(dataArr: templateModel?.list_sub_vip)
|
||||
|
||||
self.stackView.removeAllArrangedSubview()
|
||||
|
||||
|
@ -94,7 +94,7 @@ class SPPlayerControlView: UIView {
|
||||
|
||||
///右边功能区
|
||||
private(set) lazy var rightFeatureView: UIStackView = {
|
||||
let view = UIStackView(arrangedSubviews: [collectButton])
|
||||
let view = UIStackView(arrangedSubviews: [collectButton, episodeButton])
|
||||
view.axis = .vertical
|
||||
view.spacing = 25
|
||||
return view
|
||||
@ -107,6 +107,12 @@ class SPPlayerControlView: UIView {
|
||||
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 {
|
||||
viewModel?.removeObserver(self, forKeyPath: "isPlaying")
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
@ -204,6 +210,8 @@ extension SPPlayerControlView {
|
||||
|
||||
extension SPPlayerControlView {
|
||||
|
||||
@objc func handleEpisodeButton() {}
|
||||
|
||||
@objc private func hadlePlayAndOrPaused() {
|
||||
self.viewModel?.handlePauseOrPlay?()
|
||||
|
||||
|
@ -97,12 +97,6 @@ class SPPlayerDetailControlView: SPPlayerControlView {
|
||||
private var timer: Timer?
|
||||
|
||||
//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 = {
|
||||
let label = UILabel()
|
||||
label.font = .fontRegular(ofSize: 12)
|
||||
@ -244,7 +238,6 @@ class SPPlayerDetailControlView: SPPlayerControlView {
|
||||
extension SPPlayerDetailControlView {
|
||||
|
||||
private func _setupUI() {
|
||||
self.rightFeatureView.addArrangedSubview(episodeButton)
|
||||
|
||||
toolView.addSubview(progressTimeLabel)
|
||||
addSubview(retreatButton)
|
||||
@ -276,7 +269,7 @@ extension SPPlayerDetailControlView {
|
||||
}
|
||||
|
||||
extension SPPlayerDetailControlView {
|
||||
@objc private func handleEpisodeButton() {
|
||||
@objc override func handleEpisodeButton() {
|
||||
self.viewModel?.handleEpisode?()
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,15 @@ class SPRewardsViewController: SPCampaignWebViewController {
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -75,7 +75,13 @@ extension SPCoinOrderRecordViewController: UITableViewDelegate, UITableViewDataS
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -81,7 +81,13 @@ extension SPConsumptionRecordsViewController: UITableViewDelegate, UITableViewDa
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,13 @@ extension SPRewardCoinsViewController: UITableViewDelegate, UITableViewDataSourc
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,47 @@ class SPStoreViewController: SPViewController {
|
||||
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() {
|
||||
super.viewDidLoad()
|
||||
self.title = "Store".localized
|
||||
@ -105,6 +146,7 @@ extension SPStoreViewController {
|
||||
scrollView.addSubview(stackView)
|
||||
scrollView.addSubview(tipTitleLabel)
|
||||
scrollView.addSubview(tipTextLabel)
|
||||
scrollView.addSubview(agreementLabel)
|
||||
|
||||
scrollView.snp.makeConstraints { make in
|
||||
make.left.right.bottom.equalToSuperview()
|
||||
@ -126,6 +168,12 @@ extension SPStoreViewController {
|
||||
make.left.equalTo(tipTitleLabel)
|
||||
make.right.lessThanOrEqualTo(stackView).offset(-24)
|
||||
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))
|
||||
}
|
||||
}
|
||||
@ -139,7 +187,7 @@ extension SPStoreViewController {
|
||||
SPWalletAPI.requestPayTemplate { [weak self] templateModel in
|
||||
guard let self = self else { return }
|
||||
self.rechargeView.dataArr = templateModel?.list_coins
|
||||
self.memberView.dataArr = templateModel?.list_sub_vip
|
||||
self.memberView.setDataArr(dataArr: templateModel?.list_sub_vip)
|
||||
|
||||
self.stackView.removeAllArrangedSubview()
|
||||
|
||||
|
@ -74,7 +74,13 @@ extension SPVIPOrderRecordViewController: UITableViewDelegate, UITableViewDataSo
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class SPCoinRechargeView: UIView {
|
||||
|
||||
var userInfo: SPUserInfo? {
|
||||
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()
|
||||
label.font = .fontRegular(ofSize: 14)
|
||||
label.textColor = .colorFFFFFF(alpha: 0.7)
|
||||
label.text = "Coins Balance:"
|
||||
label.text = "Coins Balance:".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
|
@ -19,13 +19,7 @@ class SPMemberRechargeView: UIView {
|
||||
///会员购买成功
|
||||
var buyFinishHandle: (() -> Void)?
|
||||
|
||||
var dataArr: [SPPayTemplateItem]? {
|
||||
didSet {
|
||||
self.invalidateIntrinsicContentSize()
|
||||
|
||||
self.collectionView.reloadData()
|
||||
}
|
||||
}
|
||||
private var dataArr: [SPPayTemplateItem]?
|
||||
|
||||
var shortPlayId: String?
|
||||
var videoId: String?
|
||||
@ -67,6 +61,19 @@ class SPMemberRechargeView: UIView {
|
||||
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 {
|
||||
|
@ -33,7 +33,7 @@ extension SPEmptyState: CustomState {
|
||||
|
||||
var title: String? {
|
||||
switch self {
|
||||
case .normail(let parameters):
|
||||
case .normail(_):
|
||||
return nil
|
||||
|
||||
}
|
||||
@ -53,7 +53,8 @@ extension SPEmptyState {
|
||||
var format = EmptyStateFormat()
|
||||
format.backgroundColor = .clear
|
||||
format.imageSize = self.image?.size ?? .zero
|
||||
// format.verticalMargin = -10
|
||||
format.animation = nil
|
||||
format.verticalMargin = -50
|
||||
//
|
||||
// format.buttonWidth = 107
|
||||
// format.buttonTopMargin = 10
|
||||
|
23
MoviaBox/Libs/Empty/UIScrollView+Empty.swift
Normal 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()
|
||||
}
|
||||
}
|
@ -132,7 +132,7 @@ class SPPlayer: NSObject {
|
||||
|
||||
///准备播放
|
||||
func prepare() {
|
||||
// self.player.prepareToPlay()
|
||||
self.player.prepareToPlay()
|
||||
}
|
||||
|
||||
func stop() {
|
||||
@ -254,6 +254,7 @@ extension SPPlayer {
|
||||
self.replay()
|
||||
} else {
|
||||
self.isPlaying = false
|
||||
self.prepare()
|
||||
self.delegate?.sp_playCompletion?(self)
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ class SPIAPManager: NSObject {
|
||||
///开始内购
|
||||
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)
|
||||
handler?(false)
|
||||
return
|
||||
@ -46,6 +46,11 @@ class SPIAPManager: NSObject {
|
||||
}
|
||||
self.completionHandler = handler
|
||||
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 ?? "")
|
||||
|
||||
@ -86,26 +91,35 @@ class SPIAPManager: NSObject {
|
||||
SPHUD.show()
|
||||
}
|
||||
SPWalletAPI.requestVerifyOrder(orderCode: orderCode, payId: payId, productId: productId, purchaseToken: receipt) { model in
|
||||
if model?.status == "success" {
|
||||
if isLoding {
|
||||
SPHUD.dismiss()
|
||||
}
|
||||
|
||||
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 {
|
||||
SPToast.show(text: "success".localized)
|
||||
}
|
||||
completer?(true)
|
||||
if buyType == .vip {
|
||||
NotificationCenter.default.post(name: SPIAPManager.buyVipFinishNotification, object: nil)
|
||||
}
|
||||
} else {
|
||||
// SPToast.show(text: "failure".localized)
|
||||
completer?(false)
|
||||
}
|
||||
|
||||
if isLoding {
|
||||
SPHUD.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//MARK: -------------- JXIAPManagerDelegate --------------
|
||||
@ -131,11 +145,23 @@ extension SPIAPManager: JXIAPManagerDelegate {
|
||||
self.orderCode = nil
|
||||
self.payId = nil
|
||||
|
||||
if model?.status == "success" {
|
||||
guard let model = model else {
|
||||
self.completionHandler?(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
|
||||
|
||||
SPToast.show(text: "success".localized)
|
||||
self.completionHandler?(true)
|
||||
if buyType == .vip {
|
||||
NotificationCenter.default.post(name: SPIAPManager.buyVipFinishNotification, object: nil)
|
||||
}
|
||||
} else {
|
||||
self.completionHandler?(false)
|
||||
}
|
||||
@ -158,3 +184,9 @@ extension SPIAPManager: JXIAPManagerDelegate {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SPIAPManager {
|
||||
///成功购买会员
|
||||
@objc static let buyVipFinishNotification = NSNotification.Name(rawValue: "SPIAPManager.buyVipFinishNotification")
|
||||
|
||||
}
|
||||
|
@ -13,5 +13,6 @@ class SPIAPVerifyModel: SPModel, SmartCodable {
|
||||
var status: String?
|
||||
var money: String?
|
||||
var is_backhaul: String?
|
||||
var code: String?
|
||||
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ class SPWaitRestoreModel: SPModel, NSSecureCoding {
|
||||
var payId: String?
|
||||
var productId: String?
|
||||
var receipt: String?
|
||||
var buyType: SPWalletAPI.BuyType?
|
||||
|
||||
|
||||
required init() { }
|
||||
@ -31,6 +32,7 @@ class SPWaitRestoreModel: SPModel, NSSecureCoding {
|
||||
coder.encode(payId, forKey: "payId")
|
||||
coder.encode(productId, forKey: "productId")
|
||||
coder.encode(receipt, forKey: "receipt")
|
||||
coder.encode(buyType?.rawValue, forKey: "buyType")
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@ -39,6 +41,9 @@ class SPWaitRestoreModel: SPModel, NSSecureCoding {
|
||||
payId = coder.decodeObject(of: NSString.self, forKey: "payId") as? String
|
||||
productId = coder.decodeObject(of: NSString.self, forKey: "productId") 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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,11 @@
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</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>
|
||||
<array/>
|
||||
</dict>
|
||||
|
@ -5,12 +5,12 @@
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Episodes@2x.png",
|
||||
"filename" : "Group 79@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Episodes@3x.png",
|
||||
"filename" : "Group 79@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.3 KiB |
BIN
MoviaBox/Source/Assets.xcassets/icon/episode_icon_02.imageset/Group 79@2x.png
vendored
Normal file
After Width: | Height: | Size: 619 B |
BIN
MoviaBox/Source/Assets.xcassets/icon/episode_icon_02.imageset/Group 79@3x.png
vendored
Normal file
After Width: | Height: | Size: 912 B |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 46 KiB |
@ -5,12 +5,11 @@
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "APP图标 2@2x.png",
|
||||
"filename" : "LOGO(MoviaBox).jpg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "APP图标 2@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
|
BIN
MoviaBox/Source/Assets.xcassets/icon/login_logo_icon_01.imageset/LOGO(MoviaBox).jpg
vendored
Normal file
After Width: | Height: | Size: 4.9 KiB |
@ -5,12 +5,12 @@
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "空空如也@2x.png",
|
||||
"filename" : "image 39@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "空空如也@3x.png",
|
||||
"filename" : "image 39@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
|
BIN
MoviaBox/Source/Assets.xcassets/image/empty_image_01.imageset/image 39@2x.png
vendored
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
MoviaBox/Source/Assets.xcassets/image/empty_image_01.imageset/image 39@3x.png
vendored
Normal file
After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 31 KiB |
@ -14,6 +14,14 @@
|
||||
<string>fb1228062532660582</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>MoviaTV</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict/>
|
||||
</array>
|
||||
<key>FacebookAppID</key>
|
||||
@ -48,6 +56,11 @@
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
|
@ -17,3 +17,4 @@
|
||||
#import "WMPageController.h"
|
||||
#import <SVProgressHUD/SVProgressHUD.h>
|
||||
#import <TZImagePickerController/TZImagePickerController.h>
|
||||
#import <Adjust.h>
|
||||
|
@ -19,13 +19,15 @@
|
||||
"Trending Now" = "Trending Now";
|
||||
"Editor's Hotlist" = "Editor's Hotlist";
|
||||
"Shorts for You" = "Shorts for You";
|
||||
"Episodes" = "Episodes";
|
||||
"Series" = "Series";
|
||||
"Save" = "Save";
|
||||
"Added" = "Added";
|
||||
"FeedBack" = "FeedBack";
|
||||
"Settings" = "Settings";
|
||||
"Language" = "Language";
|
||||
"Privacy Policy" = "Privacy Policy";
|
||||
"Terms of Service" = "Terms of Service";
|
||||
"Renewal Agreement" = "Renewal Agreement";
|
||||
"User Agreement" = "User Agreement";
|
||||
"About Us" = "About Us";
|
||||
"My list" = "My list";
|
||||
@ -67,7 +69,6 @@
|
||||
"Consumption records" = "Consumption records";
|
||||
"Purchase records" = "Purchase records";
|
||||
"Reward Coins" = "Reward Coins";
|
||||
"Stroe" = "Stroe";
|
||||
"Coins Balance:" = "Coins Balance:";
|
||||
"Membership" = "Membership";
|
||||
"%@ Bonus" = "%@ Bonus";
|
||||
@ -106,6 +107,6 @@
|
||||
"kLoginAgreementText" = "By continuing, you agree to the User Agreement and Privacy Policy";
|
||||
"kBuyMemberTipText" = "Auto renew · Cancel anytime";
|
||||
"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";
|
||||
|
||||
|
@ -46,7 +46,7 @@ class JXIAPManager: NSObject {
|
||||
private var payment: SKPayment?
|
||||
|
||||
private var product: SKProduct?
|
||||
private var productId: String = ""
|
||||
private var productId: String?
|
||||
private var orderId: String?
|
||||
private var applicationUsername: String? {
|
||||
get {
|
||||
@ -112,7 +112,10 @@ extension JXIAPManager: SKProductsRequestDelegate {
|
||||
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
|
||||
guard let product = response.products.first else {
|
||||
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
|
||||
}
|
||||
@ -128,7 +131,7 @@ extension JXIAPManager: SKPaymentTransactionObserver {
|
||||
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
|
||||
|
||||
for transaction in transactions {
|
||||
|
||||
spLog(message: "transactionState = \(transaction.transactionState)")
|
||||
switch transaction.transactionState {
|
||||
case .purchased:
|
||||
DispatchQueue.main.async {
|
||||
@ -169,14 +172,21 @@ extension JXIAPManager: SKPaymentTransactionObserver {
|
||||
extension JXIAPManager {
|
||||
private func completeTransaction(transaction: SKPaymentTransaction) {
|
||||
//自动续费
|
||||
if let _ = transaction.original, transaction.payment.applicationUsername == nil {
|
||||
return
|
||||
}
|
||||
// if let _ = transaction.original, transaction.payment.applicationUsername == nil {
|
||||
// return
|
||||
// }
|
||||
//重新开通自动续费
|
||||
if let _ = transaction.original, transaction.payment.applicationUsername != nil {
|
||||
self.delegate?.jx_iapPayFailed?(productId: productId, code: .unknown)
|
||||
return
|
||||
}
|
||||
// if let _ = transaction.original, transaction.payment.applicationUsername != nil {
|
||||
// self.delegate?.jx_iapPayFailed?(productId: productId, code: .unknown)
|
||||
// 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 }
|
||||
let receiptData = NSData(contentsOf: receiptURL)
|
||||
@ -184,15 +194,20 @@ extension JXIAPManager {
|
||||
guard let transactionIdentifier = transaction.transactionIdentifier else { return }
|
||||
|
||||
self.delegate?.jx_iapPaySuccess?(productId: productId, receipt: encodeStr, transactionIdentifier: transactionIdentifier)
|
||||
|
||||
}
|
||||
|
||||
private func failedTransaction(transaction: SKPaymentTransaction) {
|
||||
let error = transaction.error as? SKError
|
||||
guard let productId = self.productId else { return }
|
||||
self.productId = nil
|
||||
|
||||
switch error?.code {
|
||||
case SKError.paymentCancelled:
|
||||
self.delegate?.jx_iapPayFailed?(productId: productId, code: .cancelled)
|
||||
default:
|
||||
self.delegate?.jx_iapPayFailed?(productId: productId, code: .unknown)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
4
Podfile
@ -31,7 +31,7 @@ target 'MoviaBox' do
|
||||
pod 'WMZPageController' #分页控制器
|
||||
pod 'SVProgressHUD' #HUD
|
||||
pod 'TZImagePickerController' #相册
|
||||
# pod 'FBSDKCoreKit' # Facebook 基础
|
||||
# pod 'FBSDKLoginKit' # Facebook 登录
|
||||
pod 'Adjust' # Adjust
|
||||
|
||||
|
||||
end
|
||||
|
12
Podfile.lock
@ -1,4 +1,9 @@
|
||||
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)
|
||||
- CocoaAsyncSocket (7.6.5)
|
||||
- EmptyStateKit (1.1.0)
|
||||
@ -32,6 +37,7 @@ PODS:
|
||||
- ZFPlayer/Core (4.1.4)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Adjust
|
||||
- EmptyStateKit
|
||||
- HWPanModal
|
||||
- Kingfisher
|
||||
@ -50,6 +56,8 @@ DEPENDENCIES:
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/CocoaPods/Specs.git:
|
||||
- Adjust
|
||||
- AdjustSignature
|
||||
- Kingfisher
|
||||
- ZFPlayer
|
||||
trunk:
|
||||
@ -70,6 +78,8 @@ SPEC REPOS:
|
||||
- YYKit
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Adjust: 3389abb14f761aa0d1966d52814864df9606535e
|
||||
AdjustSignature: 23b9e5d4adcadffc303bb6b410fde617dd88504f
|
||||
Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
|
||||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
||||
EmptyStateKit: dc41e9ce5c6089f67a49d063bce73ade9f2ba73f
|
||||
@ -88,6 +98,6 @@ SPEC CHECKSUMS:
|
||||
YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7
|
||||
ZFPlayer: 5cf39e8d9f0c2394a014b0db4767b5b5a6bffe13
|
||||
|
||||
PODFILE CHECKSUM: 38415be06361089ed99017f8e3cdad9bd57ec94a
|
||||
PODFILE CHECKSUM: 2a79f81260b8df4d6be58f4acb217732b1cd49ab
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|