推送弹窗,VIP弹窗
@ -146,6 +146,8 @@
|
||||
BF5E75D32DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C12DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift */; };
|
||||
BF5E75D52DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75D42DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift */; };
|
||||
BF5E75DB2DE5B8B700DE9DFE /* VPMarqueeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75DA2DE5B8B700DE9DFE /* VPMarqueeView.swift */; };
|
||||
BFCCE10D2DF951F600EDE165 /* SceneDelegate+APNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFCCE10C2DF951ED00EDE165 /* SceneDelegate+APNS.swift */; };
|
||||
BFCCE1122DF9638B00EDE165 /* VPVipAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFCCE1112DF9638B00EDE165 /* VPVipAlertView.swift */; };
|
||||
BFF5AFA42DE6F15E0044227A /* VPMeVipCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFA32DE6F15E0044227A /* VPMeVipCell.swift */; };
|
||||
BFF5AFA62DE700420044227A /* VPMeVipPrivilegeItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFA52DE700420044227A /* VPMeVipPrivilegeItemView.swift */; };
|
||||
BFF5AFA82DE704DC0044227A /* VPMeCoinCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFA72DE704DC0044227A /* VPMeCoinCell.swift */; };
|
||||
@ -372,6 +374,8 @@
|
||||
BF5E75C92DE5692D00DE9DFE /* UIViewController+JXTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+JXTransition.swift"; sourceTree = "<group>"; };
|
||||
BF5E75D42DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeCagetoryRecommandContentCell.swift; sourceTree = "<group>"; };
|
||||
BF5E75DA2DE5B8B700DE9DFE /* VPMarqueeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMarqueeView.swift; sourceTree = "<group>"; };
|
||||
BFCCE10C2DF951ED00EDE165 /* SceneDelegate+APNS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SceneDelegate+APNS.swift"; sourceTree = "<group>"; };
|
||||
BFCCE1112DF9638B00EDE165 /* VPVipAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPVipAlertView.swift; sourceTree = "<group>"; };
|
||||
BFF5AFA32DE6F15E0044227A /* VPMeVipCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMeVipCell.swift; sourceTree = "<group>"; };
|
||||
BFF5AFA52DE700420044227A /* VPMeVipPrivilegeItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMeVipPrivilegeItemView.swift; sourceTree = "<group>"; };
|
||||
BFF5AFA72DE704DC0044227A /* VPMeCoinCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMeCoinCell.swift; sourceTree = "<group>"; };
|
||||
@ -502,6 +506,7 @@
|
||||
BF0FA7312DDEBD6400C9E5F2 /* AppDelegate+Config.swift */,
|
||||
BFF5B2472DF051D90044227A /* AppDelegate+Thirdparty.swift */,
|
||||
BFF5B2492DF0524D0044227A /* AppDelegate+Open.swift */,
|
||||
BFCCE10C2DF951ED00EDE165 /* SceneDelegate+APNS.swift */,
|
||||
);
|
||||
path = AppDelegate;
|
||||
sourceTree = "<group>";
|
||||
@ -1036,6 +1041,7 @@
|
||||
BFF5B22F2DEFEF0C0044227A /* VPDeleteAccountNormalView.swift */,
|
||||
BFF5B2312DEFF1220044227A /* VPDeleteAccountDetailView.swift */,
|
||||
BFF5B2332DEFF2030044227A /* VPDeleteAccountTipView.swift */,
|
||||
BFCCE1112DF9638B00EDE165 /* VPVipAlertView.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
@ -1435,6 +1441,7 @@
|
||||
BFF5AFDE2DEEBF370044227A /* VPPlayerRechargeView.swift in Sources */,
|
||||
BFF5AFAA2DE7070A0044227A /* VPMeCoinItemView.swift in Sources */,
|
||||
BF0FA7692DE0502900C9E5F2 /* VPEpisodeCell.swift in Sources */,
|
||||
BFCCE10D2DF951F600EDE165 /* SceneDelegate+APNS.swift in Sources */,
|
||||
BFF5B2372DF013410044227A /* VPAlertWindowManager.swift in Sources */,
|
||||
BF5E75BE2DE54B2800DE9DFE /* VPAboutUsHeaderView.swift in Sources */,
|
||||
BFF5AFB22DE7FC130044227A /* CGMutablePath+VPAdd.swift in Sources */,
|
||||
@ -1531,6 +1538,7 @@
|
||||
BF5E75B32DE465EC00DE9DFE /* Dictionary+SPAdd.swift in Sources */,
|
||||
BF0FA7162DDC78FF00C9E5F2 /* ZKCycleScrollViewFlowLayout.swift in Sources */,
|
||||
BFF5B2612DF16B430044227A /* JXIAPManager.swift in Sources */,
|
||||
BFCCE1122DF9638B00EDE165 /* VPVipAlertView.swift in Sources */,
|
||||
BF0FA7172DDC78FF00C9E5F2 /* ZKCycleScrollView.swift in Sources */,
|
||||
BFF5B4AF2DF6B6630044227A /* VPMutualCollectionView.swift in Sources */,
|
||||
BF0FA7612DDFFE7100C9E5F2 /* VPVideoDetailModel.swift in Sources */,
|
||||
|
@ -31,17 +31,23 @@ extension SceneDelegate {
|
||||
}
|
||||
|
||||
extension SceneDelegate {
|
||||
|
||||
///是否有正在打开的消息
|
||||
static var hasOpenMessage = false
|
||||
///是否需要重试
|
||||
static var isNeedRetry = false
|
||||
|
||||
private static var webpageURL: URL?
|
||||
|
||||
func vp_handleOpenAppMessage(webpageURL: URL?) {
|
||||
guard VPNetworkReachabilityManager.manager.isReachable == true else {
|
||||
guard VPNetworkReachabilityManager.manager.isReachable == true, SceneDelegate.haveBeenShownAPNS else {
|
||||
if let webpageURL = webpageURL {
|
||||
SceneDelegate.webpageURL = webpageURL
|
||||
}
|
||||
Self.isNeedRetry = true
|
||||
return
|
||||
}
|
||||
Self.isNeedRetry = false
|
||||
SceneDelegate.webpageURL = nil
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
self._handleOpenAppMessage(webpageURL: webpageURL)
|
||||
@ -98,7 +104,7 @@ extension SceneDelegate {
|
||||
///重试
|
||||
func vp_retryHandleOpenAppMessage() {
|
||||
guard Self.isNeedRetry else { return }
|
||||
vp_handleOpenAppMessage(webpageURL: nil)
|
||||
vp_handleOpenAppMessage(webpageURL: SceneDelegate.webpageURL)
|
||||
}
|
||||
|
||||
}
|
||||
|
67
Veloria/AppDelegate/SceneDelegate+APNS.swift
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// SceneDelegate+APNS.swift
|
||||
// Veloria
|
||||
//
|
||||
// Created by 湖南秦九 on 2025/6/11.
|
||||
//
|
||||
|
||||
|
||||
extension SceneDelegate {
|
||||
///是否展示过通知提示
|
||||
static var haveBeenShownAPNS = false
|
||||
|
||||
func requestAPNS() {
|
||||
|
||||
|
||||
let center = UNUserNotificationCenter.current()
|
||||
center.delegate = self
|
||||
|
||||
center.requestAuthorization(options: [.badge, .sound, .alert]) { grant, error in
|
||||
if !grant {
|
||||
if let date = UserDefaults.standard.object(forKey: kVPApnsAlertDefaultsKey) as? Date {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
#if DEBUG
|
||||
self.showApnsAlert()
|
||||
#else
|
||||
if !date.vp_isToday {
|
||||
self.showApnsAlert()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
UserDefaults.standard.set(Date(), forKey: kVPApnsAlertDefaultsKey)
|
||||
} else {
|
||||
|
||||
SceneDelegate.haveBeenShownAPNS = true
|
||||
self.vp_retryHandleOpenAppMessage()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
UIApplication.shared.registerForRemoteNotifications()
|
||||
|
||||
}
|
||||
|
||||
private func showApnsAlert() {
|
||||
let alert = VPAlertView(title: "kAPNSAlertTitle".localized, subtitle: "kAPNSAlertText".localized, icon: UIImage(named: "alert_icon_03"), normalButtonText: nil, highlightButtonText: "Allow".localized)
|
||||
alert.show()
|
||||
|
||||
alert.clickHighlightButton = { [weak self] in
|
||||
guard let _ = self else { return }
|
||||
VPAppTool.openApnsSetting()
|
||||
SceneDelegate.haveBeenShownAPNS = true
|
||||
}
|
||||
|
||||
alert.clickCloseButton = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
SceneDelegate.haveBeenShownAPNS = true
|
||||
self.vp_retryHandleOpenAppMessage()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//MARK: -------------- UNUserNotificationCenterDelegate --------------
|
||||
extension SceneDelegate: UNUserNotificationCenterDelegate {
|
||||
|
||||
}
|
@ -17,16 +17,24 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
guard let windowScene = (scene as? UIWindowScene) else { return }
|
||||
VPAppTool.windowScene = windowScene
|
||||
|
||||
timer = Timer.scheduledTimer(timeInterval: 60 * 10, target: YYWeakProxy(target: self), selector: #selector(handleOnLine), userInfo: nil, repeats: true)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: VPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
|
||||
|
||||
self.requestAPNS()
|
||||
|
||||
|
||||
if let webpageURL = connectionOptions.userActivities.first?.webpageURL {
|
||||
self.vp_handleOpenAppMessage(webpageURL: webpageURL)
|
||||
}
|
||||
|
||||
window = UIWindow(windowScene: windowScene)
|
||||
window?.rootViewController = VPTabBarController()
|
||||
window?.makeKeyAndVisible()
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
|
@ -18,3 +18,9 @@ let kVPLoginUserInfoDefaultsKey = "kSPLoginUserInfoDefaultsKey"
|
||||
|
||||
///待恢复数据
|
||||
let kVPWaitRestoreIAPDefaultsKey = "kVPWaitRestoreIAPDefaultsKey"
|
||||
|
||||
///推送提示
|
||||
let kVPApnsAlertDefaultsKey = "kVPApnsAlertDefaultsKey"
|
||||
|
||||
///vip弹窗时间
|
||||
let kVPVipAlertDateDefaultsKey = "kVPVipAlertDateDefaultsKey"
|
||||
|
@ -21,4 +21,11 @@ extension Date {
|
||||
return formatter.string(from: self)
|
||||
}
|
||||
|
||||
///是否是今天
|
||||
var vp_isToday: Bool {
|
||||
get {
|
||||
return Calendar.current.isDateInToday(self)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -234,4 +234,16 @@ extension UIColor {
|
||||
return UIColor(rgb: 0x024E3D, alpha: alpha)
|
||||
}
|
||||
|
||||
static func color005D48(alpha: CGFloat = 1) -> UIColor {
|
||||
return UIColor(rgb: 0x005D48, alpha: alpha)
|
||||
}
|
||||
|
||||
static func colorC5C5C5(alpha: CGFloat = 1) -> UIColor {
|
||||
return UIColor(rgb: 0xC5C5C5, alpha: alpha)
|
||||
}
|
||||
|
||||
static func colorDAFDFF(alpha: CGFloat = 1) -> UIColor {
|
||||
return UIColor(rgb: 0xDAFDFF, alpha: alpha)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,21 +20,6 @@ class VPWalletAPI {
|
||||
param.method = .get
|
||||
|
||||
VPNetwork.request(parameters: param) { (response: VPNetworkResponse<VPPayTemplateModel>) in
|
||||
/*
|
||||
if let data = response.data {
|
||||
var vipList: [VPPayTemplateItem] = []
|
||||
data.list_sub_vip?.forEach({
|
||||
if $0.vip_type_key == .quarter {
|
||||
vipList.append($0)
|
||||
}
|
||||
})
|
||||
data.list_sub_vip = vipList
|
||||
completer?(data)
|
||||
|
||||
} else {
|
||||
completer?(nil)
|
||||
}
|
||||
*/
|
||||
completer?(response.data)
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ class VPMeViewController: VPViewController {
|
||||
|
||||
|
||||
|
||||
private weak var vipAlertView: VPVipAlertView?
|
||||
|
||||
private lazy var tableView: VPTableView = {
|
||||
let tableView = VPTableView(frame: .zero, style: .insetGrouped)
|
||||
tableView.delegate = self
|
||||
@ -63,6 +65,8 @@ class VPMeViewController: VPViewController {
|
||||
requestUserInfo()
|
||||
}
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
showVipAlert()
|
||||
}
|
||||
|
||||
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||
@ -86,6 +90,22 @@ extension VPMeViewController {
|
||||
self.tableView.reloadData()
|
||||
}
|
||||
|
||||
private func showVipAlert() {
|
||||
guard VPLoginManager.manager.userInfo?.is_vip != true else { return }
|
||||
guard VPVipAlertView.isAllowShowAlert else { return }
|
||||
|
||||
VPWalletAPI.requestPayTemplate { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
guard self.isDidAppear else { return }
|
||||
guard self.vipAlertView == nil else { return }
|
||||
guard let item = model?.list_sub_vip?.first else { return }
|
||||
|
||||
let alert = VPVipAlertView().show()
|
||||
alert.model = item
|
||||
self.vipAlertView = alert
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension VPMeViewController {
|
||||
|
292
Veloria/Class/Me/View/VPVipAlertView.swift
Normal file
@ -0,0 +1,292 @@
|
||||
//
|
||||
// VPVipAlertView.swift
|
||||
// Veloria
|
||||
//
|
||||
// Created by 湖南秦九 on 2025/6/11.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class VPVipAlertView: VPBaseAlertView {
|
||||
|
||||
///上一次弹窗时间
|
||||
static var lastAlertDate: Date? = UserDefaults.standard.object(forKey: kVPVipAlertDateDefaultsKey) as? Date {
|
||||
didSet {
|
||||
UserDefaults.standard.set(lastAlertDate, forKey: kVPVipAlertDateDefaultsKey)
|
||||
UserDefaults.standard.synchronize()
|
||||
}
|
||||
}
|
||||
///是否允许展示提示框
|
||||
static var isAllowShowAlert: Bool {
|
||||
#if DEBUG
|
||||
return true
|
||||
#else
|
||||
guard let lastAlertDate = lastAlertDate else { return true }
|
||||
let nowDate = Date()
|
||||
|
||||
let interval = nowDate.timeIntervalSince1970 - lastAlertDate.timeIntervalSince1970
|
||||
|
||||
//一个小时弹出一次
|
||||
if interval > 60 * 60 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
var model: VPPayTemplateItem? {
|
||||
didSet {
|
||||
unitLabel.text = model?.currency
|
||||
moneyLabel.text = model?.price
|
||||
durationLabel.text = "/\(model?.vip_type_key?.getText() ?? "")"
|
||||
|
||||
if let coin = model?.send_coins, coin > 0 {
|
||||
extraBgView.isHidden = false
|
||||
|
||||
let text = String(format: "Extra %@".localized, "\(coin)")
|
||||
extraLabel.text = "+" + text
|
||||
} else {
|
||||
extraBgView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgView: UIView = {
|
||||
let view = UIImageView(image: UIImage(named: "vpi_alert_bg_image"))
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var bgIconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "alert_icon_04"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var closeButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.setImage(UIImage(named: "close_icon_02"), for: .normal)
|
||||
button.addTarget(self, action: #selector(handleCloseButton), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var unlockButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.setBackgroundImage(UIImage(named: "vip_unlock_button"), for: .normal)
|
||||
button.setTitle("kUnlockButtonText".localized, for: .normal)
|
||||
button.setTitleColor(.color005D48(), for: .normal)
|
||||
button.titleLabel?.font = .fontMedium(ofSize: 14)
|
||||
button.addTarget(self, action: #selector(hadnleUnlockButton), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .fontBold(ofSize: 16)
|
||||
label.textColor = .colorFFFFFF()
|
||||
label.text = "kVipAlertTitle".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var textLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .fontMedium(ofSize: 14)
|
||||
label.textColor = .colorC5C5C5()
|
||||
label.text = "kVipAlertText".localized
|
||||
label.numberOfLines = 0
|
||||
label.textAlignment = .center
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var vipBgView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "vip_alert_bg_week"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var hotView: UIView = {
|
||||
let view = UIButton(type: .custom)
|
||||
view.isUserInteractionEnabled = false
|
||||
view.setBackgroundImage(UIImage(named: "hot_bg_icon_01"), for: .normal)
|
||||
view.setTitle("HOT", for: .normal)
|
||||
view.setTitleColor(.colorFFFFFF(), for: .normal)
|
||||
view.titleLabel?.font = .fontRegular(ofSize: 11)
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var unitLabel: VPGradientLabel = {
|
||||
let label = VPGradientLabel()
|
||||
label.font = .fontRegular(ofSize: 14)
|
||||
label.gradientLayer.colors = [UIColor.color64A3A7().cgColor, UIColor.color416767().cgColor]
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var moneyLabel: VPGradientLabel = {
|
||||
let label = VPGradientLabel()
|
||||
label.font = .fontAaHouDiHei(ofSize: 22)
|
||||
label.gradientLayer.colors = [UIColor.color64A3A7().cgColor, UIColor.color416767().cgColor]
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var durationLabel: VPGradientLabel = {
|
||||
let label = VPGradientLabel()
|
||||
label.font = .fontRegular(ofSize: 12)
|
||||
label.gradientLayer.colors = [UIColor.color64A3A7().cgColor, UIColor.color416767().cgColor]
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var extraBgView: UIView = {
|
||||
let view = VPGradientView()
|
||||
view.colors = [UIColor.colorDAFDFF().cgColor, UIColor.colorDAFDFF(alpha: 0).cgColor]
|
||||
view.locations = [0, 1]
|
||||
view.startPoint = .init(x: 0, y: 0.5)
|
||||
view.endPoint = .init(x: 1, y: 0.5)
|
||||
view.layer.cornerRadius = 4
|
||||
view.layer.masksToBounds = true
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var extraLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .fontRegular(ofSize: 10)
|
||||
label.textColor = .color416767()
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var extraIconView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coin_icon_08"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
vp_setupUI()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func show(in view: UIView? = nil) -> Self {
|
||||
VPVipAlertView.lastAlertDate = Date()
|
||||
return super.show(in: VPAppTool.keyWindow)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension VPVipAlertView {
|
||||
@objc private func handleCloseButton() {
|
||||
self.dismiss()
|
||||
}
|
||||
|
||||
@objc private func hadnleUnlockButton() {
|
||||
guard let model = model else { return }
|
||||
|
||||
VPIAPManager.manager.start(model: model) { [weak self] finish in
|
||||
if finish {
|
||||
self?.dismiss()
|
||||
VPLoginManager.manager.updateUserInfo(completer: nil)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
extension VPVipAlertView {
|
||||
|
||||
private func vp_setupUI() {
|
||||
contentView.addSubview(bgView)
|
||||
contentView.addSubview(bgIconImageView)
|
||||
contentView.addSubview(unlockButton)
|
||||
contentView.addSubview(closeButton)
|
||||
bgView.addSubview(titleLabel)
|
||||
bgView.addSubview(textLabel)
|
||||
bgView.addSubview(vipBgView)
|
||||
vipBgView.addSubview(hotView)
|
||||
vipBgView.addSubview(unitLabel)
|
||||
vipBgView.addSubview(moneyLabel)
|
||||
vipBgView.addSubview(durationLabel)
|
||||
vipBgView.addSubview(extraBgView)
|
||||
extraBgView.addSubview(extraLabel)
|
||||
extraBgView.addSubview(extraIconView)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.top.left.right.equalToSuperview()
|
||||
make.width.equalTo(274)
|
||||
make.height.equalTo(330)
|
||||
}
|
||||
|
||||
bgIconImageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(-136)
|
||||
}
|
||||
|
||||
unlockButton.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(bgView.snp.bottom).offset(8)
|
||||
}
|
||||
|
||||
closeButton.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(unlockButton.snp.bottom).offset(20)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(159)
|
||||
}
|
||||
|
||||
textLabel.snp.makeConstraints { make in
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(8)
|
||||
make.centerX.equalToSuperview()
|
||||
make.right.lessThanOrEqualToSuperview().offset(-20)
|
||||
}
|
||||
|
||||
vipBgView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.bottom.equalToSuperview().offset(-22)
|
||||
}
|
||||
|
||||
hotView.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview()
|
||||
make.right.equalToSuperview()
|
||||
}
|
||||
|
||||
unitLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.top.equalToSuperview().offset(16)
|
||||
}
|
||||
|
||||
moneyLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(unitLabel.snp.right)
|
||||
make.bottom.equalTo(unitLabel).offset(4)
|
||||
}
|
||||
|
||||
durationLabel.snp.makeConstraints { make in
|
||||
make.bottom.equalTo(moneyLabel).offset(-5)
|
||||
make.left.equalTo(moneyLabel.snp.right)
|
||||
}
|
||||
|
||||
extraBgView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.bottom.equalToSuperview().offset(-9)
|
||||
make.height.equalTo(21)
|
||||
// make.width.equalTo(86)
|
||||
}
|
||||
|
||||
extraLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(11)
|
||||
make.centerY.equalToSuperview()
|
||||
}
|
||||
|
||||
extraIconView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalTo(extraLabel.snp.right).offset(3)
|
||||
make.right.equalToSuperview().offset(-7)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -11,6 +11,7 @@ class VPAlertView: VPBaseAlertView {
|
||||
|
||||
var clickNormalButton: (() -> Void)?
|
||||
var clickHighlightButton: (() -> Void)?
|
||||
var clickCloseButton: (() -> Void)?
|
||||
|
||||
|
||||
private lazy var bgView: UIImageView = {
|
||||
@ -92,7 +93,7 @@ class VPAlertView: VPBaseAlertView {
|
||||
private lazy var closeButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.setImage(UIImage(named: "close_icon_02"), for: .normal)
|
||||
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
||||
button.addTarget(self, action: #selector(handleCloseButton), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
@ -126,6 +127,11 @@ class VPAlertView: VPBaseAlertView {
|
||||
|
||||
extension VPAlertView {
|
||||
|
||||
@objc private func handleCloseButton() {
|
||||
self.clickCloseButton?()
|
||||
self.dismiss()
|
||||
}
|
||||
|
||||
@objc private func handleHighlightButton() {
|
||||
self.clickHighlightButton?()
|
||||
self.dismiss()
|
||||
|
@ -11,7 +11,7 @@ class VPAlertWindowManager {
|
||||
|
||||
static let manager = VPAlertWindowManager()
|
||||
|
||||
private var window: UIWindow?
|
||||
private(set) var window: UIWindow?
|
||||
|
||||
private var count = 0
|
||||
|
||||
@ -31,11 +31,24 @@ class VPAlertWindowManager {
|
||||
func dismissWindow() {
|
||||
// count -= 1
|
||||
guard let window = self.window else { return }
|
||||
if window.subviews.count <= 0 {
|
||||
|
||||
var isHidden = true
|
||||
|
||||
window.subviews.forEach {
|
||||
if $0.isKind(of: VPBaseAlertView.self) {
|
||||
isHidden = false
|
||||
}
|
||||
}
|
||||
if isHidden {
|
||||
window.isHidden = true
|
||||
self.window = nil
|
||||
}
|
||||
|
||||
// if window.subviews.count <= 0 {
|
||||
// window.isHidden = true
|
||||
// self.window = nil
|
||||
// }
|
||||
|
||||
// if count == 0 {
|
||||
// window?.isHidden = true
|
||||
// window = nil
|
||||
|
@ -35,7 +35,7 @@ class VPIAPManager {
|
||||
|
||||
|
||||
///开始内购
|
||||
func start(model: VPPayTemplateItem, shortPlayId: String? = nil, videoId: String? = nil, handler: CompletionHandler? = nil) {
|
||||
func start(model: VPPayTemplateItem, shortPlayId: String? = nil, videoId: String? = nil, hudShowView: UIView? = nil, handler: CompletionHandler? = nil) {
|
||||
|
||||
if let _ = self.waitRestoreModel {
|
||||
VPToast.show(text: "kIapErrorToast01".localized)
|
||||
@ -53,7 +53,7 @@ class VPIAPManager {
|
||||
|
||||
let productId = VPIAPManager.IAPPrefix + (model.ios_template_id ?? "")
|
||||
|
||||
VPHUD.show()
|
||||
VPHUD.show(containerView: hudShowView)
|
||||
|
||||
VPWalletAPI.requestCreateOrder(payId: payId, shortPlayId: shortPlayId ?? "0", videoId: videoId ?? "0") { orderModel in
|
||||
guard let orderModel = orderModel else {
|
||||
|
22
Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "顶部装饰@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "顶部装饰@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/顶部装饰@2x.png
vendored
Normal file
After Width: | Height: | Size: 266 KiB |
BIN
Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/顶部装饰@3x.png
vendored
Normal file
After Width: | Height: | Size: 545 KiB |
22
Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "金币1 2@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "金币1 2@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/金币1 2@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/金币1 2@3x.png
vendored
Normal file
After Width: | Height: | Size: 3.2 KiB |
22
Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Rectangle 29@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Rectangle 29@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Rectangle 29@2x.png
vendored
Normal file
After Width: | Height: | Size: 509 B |
BIN
Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Rectangle 29@3x.png
vendored
Normal file
After Width: | Height: | Size: 695 B |
22
Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "按钮@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "按钮@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/按钮@2x.png
vendored
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/按钮@3x.png
vendored
Normal file
After Width: | Height: | Size: 56 KiB |
22
Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "会员卡片bg@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "会员卡片bg@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/会员卡片bg@2x.png
vendored
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/会员卡片bg@3x.png
vendored
Normal file
After Width: | Height: | Size: 124 KiB |
44
Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "弹窗bg@2x.png",
|
||||
"idiom" : "universal",
|
||||
"resizing" : {
|
||||
"cap-insets" : {
|
||||
"bottom" : 100,
|
||||
"top" : 387
|
||||
},
|
||||
"center" : {
|
||||
"height" : 1,
|
||||
"mode" : "tile"
|
||||
},
|
||||
"mode" : "3-part-vertical"
|
||||
},
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "弹窗bg@3x.png",
|
||||
"idiom" : "universal",
|
||||
"resizing" : {
|
||||
"cap-insets" : {
|
||||
"bottom" : 138,
|
||||
"top" : 550
|
||||
},
|
||||
"center" : {
|
||||
"height" : 1,
|
||||
"mode" : "tile"
|
||||
},
|
||||
"mode" : "3-part-vertical"
|
||||
},
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/弹窗bg@2x.png
vendored
Normal file
After Width: | Height: | Size: 104 KiB |
BIN
Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/弹窗bg@3x.png
vendored
Normal file
After Width: | Height: | Size: 165 KiB |
@ -90,6 +90,7 @@
|
||||
"More" = "More";
|
||||
"Confirm" = "Confirm";
|
||||
"Order Record" = "Order Record";
|
||||
"Allow" = "Allow";
|
||||
|
||||
|
||||
"kBonusCoinCount" = "+%@ Bonus";
|
||||
@ -141,10 +142,16 @@
|
||||
//请选择需要删除的短剧
|
||||
"kToastText1" = "Please select the short plays that need to be deleted";
|
||||
|
||||
"kUnlockButtonText" = "Unlock VIP Benefits";
|
||||
|
||||
"kDeleteAccountAlertTitle" = "Confirm Account Deletion";
|
||||
"kDeleteAccountAlertText" = "This action cannot be undone.";
|
||||
"kUnFavoritesAlertTitle" = "UnFavorites";
|
||||
"kUnFavoritesAlertText" = "You may not find this collection after you uncollect it";
|
||||
"kAPNSAlertTitle" = "Turn on Notifications?";
|
||||
"kAPNSAlertText" = "Get alerts for new episodes and exclusive offers.";
|
||||
"kVipAlertTitle" = "Unlock VIP Privileges!";
|
||||
"kVipAlertText" = "Enjoy ad-free streaming, early access, and exclusive content!";
|
||||
"kLogoutAlertTitle" = "Ready to Leave?";
|
||||
"kLogoutAlertText" = "when you sign out, your watch history will not be synced to your account.";
|
||||
|
||||
|