diff --git a/Veloria.xcodeproj/project.pbxproj b/Veloria.xcodeproj/project.pbxproj index a7be765..cb9ef72 100644 --- a/Veloria.xcodeproj/project.pbxproj +++ b/Veloria.xcodeproj/project.pbxproj @@ -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 = ""; }; BF5E75D42DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeCagetoryRecommandContentCell.swift; sourceTree = ""; }; BF5E75DA2DE5B8B700DE9DFE /* VPMarqueeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMarqueeView.swift; sourceTree = ""; }; + BFCCE10C2DF951ED00EDE165 /* SceneDelegate+APNS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SceneDelegate+APNS.swift"; sourceTree = ""; }; + BFCCE1112DF9638B00EDE165 /* VPVipAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPVipAlertView.swift; sourceTree = ""; }; BFF5AFA32DE6F15E0044227A /* VPMeVipCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMeVipCell.swift; sourceTree = ""; }; BFF5AFA52DE700420044227A /* VPMeVipPrivilegeItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMeVipPrivilegeItemView.swift; sourceTree = ""; }; BFF5AFA72DE704DC0044227A /* VPMeCoinCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMeCoinCell.swift; sourceTree = ""; }; @@ -502,6 +506,7 @@ BF0FA7312DDEBD6400C9E5F2 /* AppDelegate+Config.swift */, BFF5B2472DF051D90044227A /* AppDelegate+Thirdparty.swift */, BFF5B2492DF0524D0044227A /* AppDelegate+Open.swift */, + BFCCE10C2DF951ED00EDE165 /* SceneDelegate+APNS.swift */, ); path = AppDelegate; sourceTree = ""; @@ -1036,6 +1041,7 @@ BFF5B22F2DEFEF0C0044227A /* VPDeleteAccountNormalView.swift */, BFF5B2312DEFF1220044227A /* VPDeleteAccountDetailView.swift */, BFF5B2332DEFF2030044227A /* VPDeleteAccountTipView.swift */, + BFCCE1112DF9638B00EDE165 /* VPVipAlertView.swift */, ); path = View; sourceTree = ""; @@ -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 */, diff --git a/Veloria/AppDelegate/AppDelegate+Open.swift b/Veloria/AppDelegate/AppDelegate+Open.swift index c8b670d..457c198 100644 --- a/Veloria/AppDelegate/AppDelegate+Open.swift +++ b/Veloria/AppDelegate/AppDelegate+Open.swift @@ -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) } } diff --git a/Veloria/AppDelegate/SceneDelegate+APNS.swift b/Veloria/AppDelegate/SceneDelegate+APNS.swift new file mode 100644 index 0000000..9e77884 --- /dev/null +++ b/Veloria/AppDelegate/SceneDelegate+APNS.swift @@ -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 { + +} diff --git a/Veloria/AppDelegate/SceneDelegate.swift b/Veloria/AppDelegate/SceneDelegate.swift index f00302f..a206ea9 100644 --- a/Veloria/AppDelegate/SceneDelegate.swift +++ b/Veloria/AppDelegate/SceneDelegate.swift @@ -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) { diff --git a/Veloria/Base/Define/VPUserDefaultsKey.swift b/Veloria/Base/Define/VPUserDefaultsKey.swift index 8525384..3966122 100644 --- a/Veloria/Base/Define/VPUserDefaultsKey.swift +++ b/Veloria/Base/Define/VPUserDefaultsKey.swift @@ -18,3 +18,9 @@ let kVPLoginUserInfoDefaultsKey = "kSPLoginUserInfoDefaultsKey" ///待恢复数据 let kVPWaitRestoreIAPDefaultsKey = "kVPWaitRestoreIAPDefaultsKey" + +///推送提示 +let kVPApnsAlertDefaultsKey = "kVPApnsAlertDefaultsKey" + +///vip弹窗时间 +let kVPVipAlertDateDefaultsKey = "kVPVipAlertDateDefaultsKey" diff --git a/Veloria/Base/Extension/Date+VPAdd.swift b/Veloria/Base/Extension/Date+VPAdd.swift index 72dbd20..cb0a64b 100644 --- a/Veloria/Base/Extension/Date+VPAdd.swift +++ b/Veloria/Base/Extension/Date+VPAdd.swift @@ -21,4 +21,11 @@ extension Date { return formatter.string(from: self) } + ///是否是今天 + var vp_isToday: Bool { + get { + return Calendar.current.isDateInToday(self) + } + } + } diff --git a/Veloria/Base/Extension/UIColor+VPAdd.swift b/Veloria/Base/Extension/UIColor+VPAdd.swift index 55d32c8..ed85572 100644 --- a/Veloria/Base/Extension/UIColor+VPAdd.swift +++ b/Veloria/Base/Extension/UIColor+VPAdd.swift @@ -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) + } + } diff --git a/Veloria/Base/Networking/API/VPWalletAPI.swift b/Veloria/Base/Networking/API/VPWalletAPI.swift index 14dc2a7..6289b7a 100644 --- a/Veloria/Base/Networking/API/VPWalletAPI.swift +++ b/Veloria/Base/Networking/API/VPWalletAPI.swift @@ -20,21 +20,6 @@ class VPWalletAPI { param.method = .get VPNetwork.request(parameters: param) { (response: VPNetworkResponse) 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) } } diff --git a/Veloria/Class/Me/Controller/VPMeViewController.swift b/Veloria/Class/Me/Controller/VPMeViewController.swift index 0e379dd..c74e2f3 100644 --- a/Veloria/Class/Me/Controller/VPMeViewController.swift +++ b/Veloria/Class/Me/Controller/VPMeViewController.swift @@ -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 { diff --git a/Veloria/Class/Me/View/VPVipAlertView.swift b/Veloria/Class/Me/View/VPVipAlertView.swift new file mode 100644 index 0000000..0ee8615 --- /dev/null +++ b/Veloria/Class/Me/View/VPVipAlertView.swift @@ -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) + } + } + + +} diff --git a/Veloria/Libs/Alert/VPAlertView.swift b/Veloria/Libs/Alert/VPAlertView.swift index 4d5e3f4..980fa79 100644 --- a/Veloria/Libs/Alert/VPAlertView.swift +++ b/Veloria/Libs/Alert/VPAlertView.swift @@ -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() diff --git a/Veloria/Libs/Alert/VPAlertWindowManager.swift b/Veloria/Libs/Alert/VPAlertWindowManager.swift index 31ec5e3..7e0d576 100644 --- a/Veloria/Libs/Alert/VPAlertWindowManager.swift +++ b/Veloria/Libs/Alert/VPAlertWindowManager.swift @@ -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 diff --git a/Veloria/Libs/VPIAPManager/VPIAPManager.swift b/Veloria/Libs/VPIAPManager/VPIAPManager.swift index e42352e..8ffb03c 100644 --- a/Veloria/Libs/VPIAPManager/VPIAPManager.swift +++ b/Veloria/Libs/VPIAPManager/VPIAPManager.swift @@ -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 { diff --git a/Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/Contents.json new file mode 100644 index 0000000..c06bdd9 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/Contents.json @@ -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 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/顶部装饰@2x.png b/Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/顶部装饰@2x.png new file mode 100644 index 0000000..508c1df Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/顶部装饰@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/顶部装饰@3x.png b/Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/顶部装饰@3x.png new file mode 100644 index 0000000..63d11a2 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/alert_icon_04.imageset/顶部装饰@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/Contents.json new file mode 100644 index 0000000..c18e822 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/Contents.json @@ -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 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/金币1 2@2x.png b/Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/金币1 2@2x.png new file mode 100644 index 0000000..b864d7b Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/金币1 2@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/金币1 2@3x.png b/Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/金币1 2@3x.png new file mode 100644 index 0000000..d013696 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/coin_icon_08.imageset/金币1 2@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Contents.json new file mode 100644 index 0000000..8d4a42c --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Contents.json @@ -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 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Rectangle 29@2x.png b/Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Rectangle 29@2x.png new file mode 100644 index 0000000..29151f9 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Rectangle 29@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Rectangle 29@3x.png b/Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Rectangle 29@3x.png new file mode 100644 index 0000000..98558c9 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/hot_bg_icon_01.imageset/Rectangle 29@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/Contents.json new file mode 100644 index 0000000..379ba42 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/Contents.json @@ -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 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/按钮@2x.png b/Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/按钮@2x.png new file mode 100644 index 0000000..7683c3f Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/按钮@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/按钮@3x.png b/Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/按钮@3x.png new file mode 100644 index 0000000..c580778 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/vip_unlock_button.imageset/按钮@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/Contents.json b/Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/Contents.json new file mode 100644 index 0000000..9f9964f --- /dev/null +++ b/Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/Contents.json @@ -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 + } +} diff --git a/Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/会员卡片bg@2x.png b/Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/会员卡片bg@2x.png new file mode 100644 index 0000000..e66e508 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/会员卡片bg@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/会员卡片bg@3x.png b/Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/会员卡片bg@3x.png new file mode 100644 index 0000000..ca5a498 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/image/vip_alert_bg_week.imageset/会员卡片bg@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/Contents.json b/Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/Contents.json new file mode 100644 index 0000000..de33ae8 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/Contents.json @@ -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 + } +} diff --git a/Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/弹窗bg@2x.png b/Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/弹窗bg@2x.png new file mode 100644 index 0000000..f625f47 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/弹窗bg@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/弹窗bg@3x.png b/Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/弹窗bg@3x.png new file mode 100644 index 0000000..876d725 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/image/vpi_alert_bg_image.imageset/弹窗bg@3x.png differ diff --git a/Veloria/Source/en.lproj/Localizable.strings b/Veloria/Source/en.lproj/Localizable.strings index 6117338..e8a7a6a 100644 --- a/Veloria/Source/en.lproj/Localizable.strings +++ b/Veloria/Source/en.lproj/Localizable.strings @@ -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.";