diff --git a/Veloria.xcodeproj/project.pbxproj b/Veloria.xcodeproj/project.pbxproj index 5aa82d2..aadeadd 100644 --- a/Veloria.xcodeproj/project.pbxproj +++ b/Veloria.xcodeproj/project.pbxproj @@ -171,6 +171,13 @@ BFF5AFD42DE9A5FB0044227A /* VPVIPRecordCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFD32DE9A5FB0044227A /* VPVIPRecordCell.swift */; }; BFF5AFD62DE9A8D70044227A /* VPWalletHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFD52DE9A8D70044227A /* VPWalletHeaderView.swift */; }; BFF5AFD82DE9B8010044227A /* VPWalletHeaderItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFD72DE9B8010044227A /* VPWalletHeaderItemView.swift */; }; + BFF5AFDA2DEE90350044227A /* VPVideoLockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFD92DEE90350044227A /* VPVideoLockView.swift */; }; + BFF5AFDC2DEEA09F0044227A /* VPVideoUnlockModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFDB2DEEA09F0044227A /* VPVideoUnlockModel.swift */; }; + BFF5AFDE2DEEBF370044227A /* VPPlayerRechargeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFDD2DEEBF370044227A /* VPPlayerRechargeView.swift */; }; + BFF5AFE02DEEC5AB0044227A /* VPPlayerVipBuyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFDF2DEEC5AA0044227A /* VPPlayerVipBuyView.swift */; }; + BFF5AFE22DEED2960044227A /* VPPlayerCoinBuyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFE12DEED2960044227A /* VPPlayerCoinBuyView.swift */; }; + BFF5AFE62DEEDB7F0044227A /* VPRewardsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFE52DEEDB7F0044227A /* VPRewardsViewController.swift */; }; + BFF5B21C2DEEDE130044227A /* VPWebViewController+Script.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B21B2DEEDE130044227A /* VPWebViewController+Script.swift */; }; F939C04AD4003BA127F15C28 /* Pods_Veloria.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F57E87E765BF8D72A43DCA /* Pods_Veloria.framework */; }; /* End PBXBuildFile section */ @@ -348,6 +355,13 @@ BFF5AFD32DE9A5FB0044227A /* VPVIPRecordCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPVIPRecordCell.swift; sourceTree = ""; }; BFF5AFD52DE9A8D70044227A /* VPWalletHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPWalletHeaderView.swift; sourceTree = ""; }; BFF5AFD72DE9B8010044227A /* VPWalletHeaderItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPWalletHeaderItemView.swift; sourceTree = ""; }; + BFF5AFD92DEE90350044227A /* VPVideoLockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPVideoLockView.swift; sourceTree = ""; }; + BFF5AFDB2DEEA09F0044227A /* VPVideoUnlockModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPVideoUnlockModel.swift; sourceTree = ""; }; + BFF5AFDD2DEEBF370044227A /* VPPlayerRechargeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPPlayerRechargeView.swift; sourceTree = ""; }; + BFF5AFDF2DEEC5AA0044227A /* VPPlayerVipBuyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPPlayerVipBuyView.swift; sourceTree = ""; }; + BFF5AFE12DEED2960044227A /* VPPlayerCoinBuyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPPlayerCoinBuyView.swift; sourceTree = ""; }; + BFF5AFE52DEEDB7F0044227A /* VPRewardsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPRewardsViewController.swift; sourceTree = ""; }; + BFF5B21B2DEEDE130044227A /* VPWebViewController+Script.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VPWebViewController+Script.swift"; sourceTree = ""; }; E0BDA3570E00C90877E45AA0 /* Pods-VideoPlayer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VideoPlayer.debug.xcconfig"; path = "Target Support Files/Pods-VideoPlayer/Pods-VideoPlayer.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -435,6 +449,7 @@ 1B056E362DDAC1E8007EE38D /* Class */ = { isa = PBXGroup; children = ( + BFF5AFE32DEED86B0044227A /* Rewards */, BFF5AFBB2DE837710044227A /* Wallet */, BF0FA7A62DE4437F00C9E5F2 /* Me */, BF0FA7952DE1948A00C9E5F2 /* MyList */, @@ -698,6 +713,7 @@ BF0FA7012DDC667C00C9E5F2 /* VPVideoInfoModel.swift */, BF0FA7602DDFFE7100C9E5F2 /* VPVideoDetailModel.swift */, BF0FA7702DE062EB00C9E5F2 /* VPVideoRateModel.swift */, + BFF5AFDB2DEEA09F0044227A /* VPVideoUnlockModel.swift */, ); path = Model; sourceTree = ""; @@ -794,6 +810,10 @@ BF0FA76A2DE0533400C9E5F2 /* VPEpisodeMenuView.swift */, BF0FA76E2DE062A700C9E5F2 /* VPRateSelectedView.swift */, BF0FA7722DE0671200C9E5F2 /* VPRateSelectedCell.swift */, + BFF5AFD92DEE90350044227A /* VPVideoLockView.swift */, + BFF5AFDD2DEEBF370044227A /* VPPlayerRechargeView.swift */, + BFF5AFDF2DEEC5AA0044227A /* VPPlayerVipBuyView.swift */, + BFF5AFE12DEED2960044227A /* VPPlayerCoinBuyView.swift */, ); path = View; sourceTree = ""; @@ -890,7 +910,6 @@ children = ( BF0FA7AE2DE443E000C9E5F2 /* VPMeViewController.swift */, BF5E75AE2DE4632200DE9DFE /* VPAboutUsViewController.swift */, - BF5E75B02DE4656600DE9DFE /* VPCampaignWebViewController.swift */, ); path = Controller; sourceTree = ""; @@ -924,6 +943,8 @@ children = ( BF0FA7B52DE44E8000C9E5F2 /* VPWebView.swift */, BF0FA7B72DE44FCC00C9E5F2 /* VPWebViewController.swift */, + BF5E75B02DE4656600DE9DFE /* VPCampaignWebViewController.swift */, + BFF5B21B2DEEDE130044227A /* VPWebViewController+Script.swift */, ); path = WebView; sourceTree = ""; @@ -1015,6 +1036,22 @@ path = Model; sourceTree = ""; }; + BFF5AFE32DEED86B0044227A /* Rewards */ = { + isa = PBXGroup; + children = ( + BFF5AFE42DEED8800044227A /* Controller */, + ); + path = Rewards; + sourceTree = ""; + }; + BFF5AFE42DEED8800044227A /* Controller */ = { + isa = PBXGroup; + children = ( + BFF5AFE52DEEDB7F0044227A /* VPRewardsViewController.swift */, + ); + path = Controller; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -1180,6 +1217,7 @@ BF0FA73B2DDED1C700C9E5F2 /* VPHomeListCell.swift in Sources */, BF0FA79F2DE1A29A00C9E5F2 /* VPCollectListCell.swift in Sources */, BF0FA7592DDF1C2800C9E5F2 /* VPPlayerProgressView.swift in Sources */, + BFF5AFE02DEEC5AB0044227A /* VPPlayerVipBuyView.swift in Sources */, BFF5AFCA2DE97B7A0044227A /* VPWalletViewController.swift in Sources */, BF0FA71B2DDC7FF200C9E5F2 /* VPImageView.swift in Sources */, BF0FA7522DDF134700C9E5F2 /* VPVideoPlayerControlView.swift in Sources */, @@ -1190,6 +1228,7 @@ BFF5AFA42DE6F15E0044227A /* VPMeVipCell.swift in Sources */, BFF5AFB02DE7F9A80044227A /* VPVipViewController.swift in Sources */, BF0FA75D2DDF208400C9E5F2 /* VPExplorePlayerControlView.swift in Sources */, + BFF5B21C2DEEDE130044227A /* VPWebViewController+Script.swift in Sources */, BF5E75CB2DE5692D00DE9DFE /* UINavigationController+JXTransition.swift in Sources */, BF5E75CC2DE5692D00DE9DFE /* JXTransitionDefine.swift in Sources */, BF5E75CD2DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift in Sources */, @@ -1201,6 +1240,7 @@ BF5E75D22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift in Sources */, BF5E75D32DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift in Sources */, 1B056E462DDAC370007EE38D /* UIScreen+VPAdd.swift in Sources */, + BFF5AFDE2DEEBF370044227A /* VPPlayerRechargeView.swift in Sources */, BFF5AFAA2DE7070A0044227A /* VPMeCoinItemView.swift in Sources */, BF0FA7692DE0502900C9E5F2 /* VPEpisodeCell.swift in Sources */, BF5E75BE2DE54B2800DE9DFE /* VPAboutUsHeaderView.swift in Sources */, @@ -1223,6 +1263,7 @@ BFF5AFCE2DE99C730044227A /* VPCoinRecordViewController.swift in Sources */, BF0FA7732DE0671200C9E5F2 /* VPRateSelectedCell.swift in Sources */, 1B056E4D2DDAC7C1007EE38D /* VPTabBarController.swift in Sources */, + BFF5AFDC2DEEA09F0044227A /* VPVideoUnlockModel.swift in Sources */, BF5E75C02DE5566200DE9DFE /* VPHomePageControlView.swift in Sources */, BFF5AFC22DE837FC0044227A /* VPPayTemplateItem.swift in Sources */, BF0FA6DA2DDC5CB600C9E5F2 /* VPLoginManager.swift in Sources */, @@ -1239,6 +1280,7 @@ 1B056E3F2DDAC2DB007EE38D /* VPCryptorService.swift in Sources */, BF0FA7202DDC83AE00C9E5F2 /* JXButton.swift in Sources */, BF0FA7912DE16CBF00C9E5F2 /* VPSearchHistoryView.swift in Sources */, + BFF5AFE22DEED2960044227A /* VPPlayerCoinBuyView.swift in Sources */, BF0FA7992DE1951A00C9E5F2 /* VPMyListViewController.swift in Sources */, BF0FA7452DDF027900C9E5F2 /* VPPlayer.swift in Sources */, BFF5AFC62DE863C00044227A /* VPGradientButton.swift in Sources */, @@ -1280,6 +1322,7 @@ BF0FA7172DDC78FF00C9E5F2 /* ZKCycleScrollView.swift in Sources */, BF0FA7612DDFFE7100C9E5F2 /* VPVideoDetailModel.swift in Sources */, BFF5AFD22DE9A58A0044227A /* VPVIPRecordViewController.swift in Sources */, + BFF5AFDA2DEE90350044227A /* VPVideoLockView.swift in Sources */, BF5E75B82DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift in Sources */, BF0FA6D52DDC5B5D00C9E5F2 /* VPApi.swift in Sources */, BF0FA7C12DE45D5D00C9E5F2 /* VPUserInfo.swift in Sources */, @@ -1289,6 +1332,7 @@ BFF5AFC02DE837D60044227A /* VPPayTemplateModel.swift in Sources */, BF0FA7B62DE44E8000C9E5F2 /* VPWebView.swift in Sources */, 1B056E492DDAC3DF007EE38D /* VPAppTool.swift in Sources */, + BFF5AFE62DEEDB7F0044227A /* VPRewardsViewController.swift in Sources */, BF0FA74E2DDF067E00C9E5F2 /* VPVideoPlayViewModel.swift in Sources */, BF0FA75B2DDF206000C9E5F2 /* VPExplorePlayerCell.swift in Sources */, BF0FA7412DDEFBC700C9E5F2 /* UIScrollView+VPRefresh.swift in Sources */, diff --git a/Veloria/Base/Controller/VPTabBarController.swift b/Veloria/Base/Controller/VPTabBarController.swift index 8dce1ae..ab9876d 100644 --- a/Veloria/Base/Controller/VPTabBarController.swift +++ b/Veloria/Base/Controller/VPTabBarController.swift @@ -154,4 +154,22 @@ extension VPTabBarController { viewController?.showHistoryPage() } } + + func openCollectPage() { + + var index: Int? + var viewController: VPMyListViewController? + self.viewControllers?.enumerated().forEach({ + guard let nav = $1 as? UINavigationController else { return } + if let vc = nav.viewControllers.first as? VPMyListViewController { + index = $0 + viewController = vc + } + + }) + if let index = index { + self.selectedIndex = index + viewController?.showCollectPage() + } + } } diff --git a/Veloria/Base/Extension/UIDevice+VPAdd.swift b/Veloria/Base/Extension/UIDevice+VPAdd.swift index 13c77fe..70bea15 100644 --- a/Veloria/Base/Extension/UIDevice+VPAdd.swift +++ b/Veloria/Base/Extension/UIDevice+VPAdd.swift @@ -11,7 +11,7 @@ import UIKit extension UIDevice { //http://theiphonewiki.com/wiki/Models - static func sp_machineModelName() -> String { + static func vp_machineModelName() -> String { guard let machineModel = UIDevice.current.machineModel else { return "" } let map = [ "iPhone1,1" : "iPhone", diff --git a/Veloria/Base/Networking/API/VPWalletAPI.swift b/Veloria/Base/Networking/API/VPWalletAPI.swift index bf5d436..aaeba1f 100644 --- a/Veloria/Base/Networking/API/VPWalletAPI.swift +++ b/Veloria/Base/Networking/API/VPWalletAPI.swift @@ -23,4 +23,19 @@ class VPWalletAPI { completer?(response.data) } } + + ///金币解锁视频 + static func requestCoinUnlockVideo(shortPlayId: String, videoId: String, completer: ((_ model: VPVideoUnlockModel?) -> Void)?) { + + var param = VPNetworkParameters(path: "/buy_video") + param.isLoding = true + param.parameters = [ + "short_play_id" : shortPlayId, + "video_id" : videoId, + ] + + VPNetwork.request(parameters: param) { (response: VPNetworkResponse) in + completer?(response.data) + } + } } diff --git a/Veloria/Base/Networking/Base/VPApi.swift b/Veloria/Base/Networking/Base/VPApi.swift index 90310fe..2514c4d 100644 --- a/Veloria/Base/Networking/Base/VPApi.swift +++ b/Veloria/Base/Networking/Base/VPApi.swift @@ -89,7 +89,7 @@ extension VPApi: TargetType { "app-name" : "", "system-type" : "ios", "idfa" : JXUUID.idfa(), - "model" : UIDevice.sp_machineModelName(), + "model" : UIDevice.vp_machineModelName(), // "security" : "false", ] //登录信息 diff --git a/Veloria/Class/Me/Controller/VPCampaignWebViewController.swift b/Veloria/Base/WebView/VPCampaignWebViewController.swift similarity index 93% rename from Veloria/Class/Me/Controller/VPCampaignWebViewController.swift rename to Veloria/Base/WebView/VPCampaignWebViewController.swift index e89f07d..4991735 100644 --- a/Veloria/Class/Me/Controller/VPCampaignWebViewController.swift +++ b/Veloria/Base/WebView/VPCampaignWebViewController.swift @@ -11,8 +11,9 @@ class VPCampaignWebViewController: VPWebViewController { var id: String? - ///重试次数 private var receiveDataCount = 0 + + var theme: String? = "theme_1" override func viewDidLoad() { super.viewDidLoad() @@ -60,8 +61,12 @@ extension VPCampaignWebViewController { "time_zone" : String.timeZone(), "lang" : VPLocalizedManager.shared.currentLocalizedKey, "type" : "ios", - "theme" : "theme_1", ] + + if let theme = theme { + dic["theme"] = theme + } + if let id = id { dic["id"] = id } diff --git a/Veloria/Base/WebView/VPWebView.swift b/Veloria/Base/WebView/VPWebView.swift index 601f225..8c4f029 100644 --- a/Veloria/Base/WebView/VPWebView.swift +++ b/Veloria/Base/WebView/VPWebView.swift @@ -33,16 +33,15 @@ class VPWebView: WKWebView { weak var delegate: VPWebViewDelegate? -// private(set) var scriptMessageHandlerArray: [SPWebViewMessageName] = [ -// WebMessageAPP, -// WebMessageOpenFeedbackList, -// WebMessageOpenFeedbackDetail, -// WebMessageOpenPhotoPicker, -// ] + private(set) var scriptMessageHandlerArray: [VPWebViewMessageName] = [ + VPWebMessageAPP, + VPWebMessageOpenFeedbackList, + VPWebMessageOpenFeedbackDetail, + VPWebMessageOpenPhotoPicker, + ] deinit { - self.removeObserver(self, forKeyPath: "estimatedProgress") self.removeObserver(self, forKeyPath: "title") @@ -50,7 +49,7 @@ class VPWebView: WKWebView { override init(frame: CGRect, configuration: WKWebViewConfiguration) { super.init(frame: frame, configuration: configuration) -// addScriptMessageHandler() + addScriptMessageHandler() _setupInit() } required init?(coder: NSCoder) { @@ -78,20 +77,20 @@ class VPWebView: WKWebView { func load(urlStr: String) { guard let url = URL(string: urlStr) else { return } - var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30) + let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30) self.load(request) } -// func removeScriptMessageHandler() { -// self.scriptMessageHandlerArray.forEach{ -// configuration.userContentController.removeScriptMessageHandler(forName: $0) -// } -// } -// func addScriptMessageHandler() { -// self.scriptMessageHandlerArray.forEach{ -// configuration.userContentController.add(YYWeakProxy(target: self) as! WKScriptMessageHandler, name: $0) -// } -// } + func removeScriptMessageHandler() { + self.scriptMessageHandlerArray.forEach{ + configuration.userContentController.removeScriptMessageHandler(forName: $0) + } + } + func addScriptMessageHandler() { + self.scriptMessageHandlerArray.forEach{ + configuration.userContentController.add(YYWeakProxy(target: self) as! WKScriptMessageHandler, name: $0) + } + } } diff --git a/Veloria/Base/WebView/VPWebViewController+Script.swift b/Veloria/Base/WebView/VPWebViewController+Script.swift new file mode 100644 index 0000000..3c977e2 --- /dev/null +++ b/Veloria/Base/WebView/VPWebViewController+Script.swift @@ -0,0 +1,32 @@ +// +// VPWebViewController+Script.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/3. +// + +import UIKit +import WebKit + +typealias VPWebViewMessageName = String + +///APP交互 +let VPWebMessageAPP: VPWebViewMessageName = "js2app" +///打开反馈列表 +let VPWebMessageOpenFeedbackList: VPWebViewMessageName = "openFeedbackList" +///打开反馈详情 +let VPWebMessageOpenFeedbackDetail: VPWebViewMessageName = "openFeedbackDetail" +///打开相册 +let VPWebMessageOpenPhotoPicker: VPWebViewMessageName = "openPhotoPicker" + +extension VPWebViewController { + + func vp_webViewUserContentController(didReceive message: WKScriptMessage) { + let name = message.name + let body = message.body + + + + } + +} diff --git a/Veloria/Base/WebView/VPWebViewController.swift b/Veloria/Base/WebView/VPWebViewController.swift index 7486b19..c805ff1 100644 --- a/Veloria/Base/WebView/VPWebViewController.swift +++ b/Veloria/Base/WebView/VPWebViewController.swift @@ -98,6 +98,6 @@ extension VPWebViewController: VPWebViewDelegate { } func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { -// _webViewUserContentController(didReceive: message) + vp_webViewUserContentController(didReceive: message) } } diff --git a/Veloria/Class/Me/View/VPMeToolCell.swift b/Veloria/Class/Me/View/VPMeToolCell.swift index 6409b5b..c0b706f 100644 --- a/Veloria/Class/Me/View/VPMeToolCell.swift +++ b/Veloria/Class/Me/View/VPMeToolCell.swift @@ -32,11 +32,13 @@ class VPMeToolCell: VPTableViewCell { private lazy var rewardsButton: UIButton = { let button = self.createButton(icon: UIImage(named: "rewards_icon_01"), title: "Rewards".localized) + button.addTarget(self, action: #selector(handleRewardsButton), for: .touchUpInside) return button }() private lazy var favoritesButton: UIButton = { let button = self.createButton(icon: UIImage(named: "favorites_icon_01"), title: "Favorites".localized) + button.addTarget(self, action: #selector(handleFavoritesButton), for: .touchUpInside) return button }() @@ -76,6 +78,16 @@ extension VPMeToolCell { self.viewController?.navigationController?.pushViewController(vc, animated: true) } + @objc private func handleRewardsButton() { + let vc = VPRewardsViewController() + self.viewController?.navigationController?.pushViewController(vc, animated: true) + } + + @objc private func handleFavoritesButton() { + let tabbarVC = VPAppTool.rootViewController as? VPTabBarController + tabbarVC?.openCollectPage() + } + } extension VPMeToolCell { diff --git a/Veloria/Class/MyList/Controller/VPMyListViewController.swift b/Veloria/Class/MyList/Controller/VPMyListViewController.swift index 777f3da..29a2c4f 100644 --- a/Veloria/Class/MyList/Controller/VPMyListViewController.swift +++ b/Veloria/Class/MyList/Controller/VPMyListViewController.swift @@ -138,6 +138,12 @@ class VPMyListViewController: VPViewController { self?.pageView.selectMenu(with: 1) } } + + func showCollectPage() { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in + self?.pageView.selectMenu(with: 0) + } + } } diff --git a/Veloria/Class/Player/Controller/VPDetailPlayerViewController.swift b/Veloria/Class/Player/Controller/VPDetailPlayerViewController.swift index 3231174..0ae7473 100644 --- a/Veloria/Class/Player/Controller/VPDetailPlayerViewController.swift +++ b/Veloria/Class/Player/Controller/VPDetailPlayerViewController.swift @@ -59,8 +59,15 @@ class VPDetailPlayerViewController: VPVideoPlayerViewController { override func play() { guard let videoInfo = self.viewModel.currentPlayer?.videoInfo else { return } - super.play() + if videoInfo.is_lock == true { + self.pause() + + self.onRecharge() + + return + } + super.play() VPVideoAPI.requestCreatePlayHistory(videoId: videoInfo.short_play_video_id, shortPlayId: videoInfo.short_play_id) } @@ -92,6 +99,9 @@ extension VPDetailPlayerViewController { self?.onEpisode() } + self.viewModel.handleUnlock = { [weak self] in + self?.unlockVideo() + } } } @@ -109,6 +119,50 @@ extension VPDetailPlayerViewController { self.episodeView = view } + private func unlockVideo() { + guard let videoInfo = self.viewModel.currentPlayer?.videoInfo else { return } + + guard let sId = videoInfo.short_play_id, let vId = videoInfo.short_play_video_id else { return } + + VPWalletAPI.requestCoinUnlockVideo(shortPlayId: sId, videoId: vId) { [weak self] model in + guard let self = self else { return } + guard let model = model else { return } + + switch model.status { + case .jump: + VPToast.show(text: "kLockPreviousEpisodeText".localized) + + case .noPlay: + VPToast.show(text: "kLockFailText".localized) + + case .notEnough: + self.onRecharge() + break + + case .success: + videoInfo.is_lock = false + self.reloadData { [weak self] in + guard let self = self else { return } + self.play() + } + + VPLoginManager.manager.updateUserInfo(completer: nil) + + default: break + + } + + } + } + + ///打开充值页面 + private func onRecharge() { + let view = VPPlayerRechargeView() + view.present(in: nil) + + + } + } //MARK: -------------- VPPlayerListViewControllerDataSource -------------- diff --git a/Veloria/Class/Player/Model/VPVideoUnlockModel.swift b/Veloria/Class/Player/Model/VPVideoUnlockModel.swift new file mode 100644 index 0000000..df5bce6 --- /dev/null +++ b/Veloria/Class/Player/Model/VPVideoUnlockModel.swift @@ -0,0 +1,25 @@ +// +// VPVideoUnlockModel.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/3. +// + +import UIKit +import SmartCodable + +class VPVideoUnlockModel: VPModel, SmartCodable { + + enum ResponseStatus: String, SmartCaseDefaultable { + ///前面还有没购买的剧 + case jump = "jump" + ///没找到视频 + case noPlay = "no_play" + ///金币不足跳充值 + case notEnough = "not_enough" + ///购买成功 + case success = "success" + } + + var status: ResponseStatus? +} diff --git a/Veloria/Class/Player/View/VPDetailPlayerControlView.swift b/Veloria/Class/Player/View/VPDetailPlayerControlView.swift index cfe0d7b..87b32ef 100644 --- a/Veloria/Class/Player/View/VPDetailPlayerControlView.swift +++ b/Veloria/Class/Player/View/VPDetailPlayerControlView.swift @@ -21,6 +21,8 @@ class VPDetailPlayerControlView: VPVideoPlayerControlView { override var videoInfo: VPVideoInfoModel? { didSet { epView.setTitle(String(format: "EP.%@".localized, "\(videoInfo?.episode ?? "0")"), for: .normal) + lockView.isHidden = !(videoInfo?.is_lock ?? false) + lockView.videoInfo = videoInfo } } @@ -113,6 +115,15 @@ class VPDetailPlayerControlView: VPVideoPlayerControlView { return view }() + private lazy var lockView: VPVideoLockView = { + let view = VPVideoLockView() + view.clickUnlockButton = { [weak self] in + guard let self = self else { return } + self.viewModel?.handleUnlock?() + } + return view + }() + deinit { self.viewModel?.removeObserver(self, forKeyPath: "rateModel") } @@ -172,6 +183,7 @@ extension VPDetailPlayerControlView { epBgView.addSubview(allEpView) addSubview(rateButton) addSubview(timeLabel) + addSubview(lockView) self.sendSubviewToBack(self.bottomView) @@ -216,6 +228,10 @@ extension VPDetailPlayerControlView { make.left.equalToSuperview().offset(15) make.bottom.equalTo(epBgView.snp.top).offset(-16) } + + lockView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } } } diff --git a/Veloria/Class/Player/View/VPEpisodeCell.swift b/Veloria/Class/Player/View/VPEpisodeCell.swift index ba2545f..f6bdbf7 100644 --- a/Veloria/Class/Player/View/VPEpisodeCell.swift +++ b/Veloria/Class/Player/View/VPEpisodeCell.swift @@ -13,22 +13,25 @@ class VPEpisodeCell: VPCollectionViewCell { var videoInfoModel: VPVideoInfoModel? { didSet { numLabel.text = videoInfoModel?.episode + + lockBgView.isHidden = !(videoInfoModel?.is_lock ?? false) + numLabel.textColor = videoInfoModel?.is_lock == true ? .colorFFFFFF(alpha: 0.5) : .colorFFFFFF() } } var vp_isSelected: Bool = false { didSet { if vp_isSelected { - contentView.vp_setGradientBorder() + borderView.isHidden = false contentView.backgroundColor = .color05CEA0(alpha: 0.1) } else { - contentView.vp_removeGradientBorder() + borderView.isHidden = true contentView.backgroundColor = .colorFFFFFF(alpha: 0.1) } } } - private lazy var bgView: UIView = { + private lazy var borderView: UIView = { let view = UIView() view.vp_setGradientBorder() view.layer.cornerRadius = 6 @@ -36,8 +39,6 @@ class VPEpisodeCell: VPCollectionViewCell { return view }() - - private lazy var numLabel: UILabel = { let label = UILabel() label.font = .fontRegular(ofSize: 14) @@ -45,6 +46,16 @@ class VPEpisodeCell: VPCollectionViewCell { return label }() + private lazy var lockBgView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "lock_bg_icon_01")) + return imageView + }() + + private lazy var lockImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "lock_icon_01")) + return imageView + }() + override init(frame: CGRect) { super.init(frame: frame) @@ -63,16 +74,26 @@ extension VPEpisodeCell { contentView.layer.cornerRadius = 6 contentView.layer.masksToBounds = true -// contentView.addSubview(bgView) contentView.addSubview(numLabel) + contentView.addSubview(lockBgView) + lockBgView.addSubview(lockImageView) + contentView.addSubview(borderView) -// bgView.snp.makeConstraints { make in -// make.edges.equalToSuperview() -// } + borderView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } numLabel.snp.makeConstraints { make in make.center.equalToSuperview() } + + lockBgView.snp.makeConstraints { make in + make.top.right.equalToSuperview() + } + + lockImageView.snp.makeConstraints { make in + make.center.equalToSuperview() + } } } diff --git a/Veloria/Class/Player/View/VPPlayerCoinBuyView.swift b/Veloria/Class/Player/View/VPPlayerCoinBuyView.swift new file mode 100644 index 0000000..4f0ca84 --- /dev/null +++ b/Veloria/Class/Player/View/VPPlayerCoinBuyView.swift @@ -0,0 +1,105 @@ +// +// VPPlayerCoinBuyView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/3. +// + +import UIKit + +class VPPlayerCoinBuyView: UIView { + + var dataArr: [VPPayTemplateItem] = [] { + didSet { + self.collectionView.reloadData() + + } + } + + private lazy var selectedIndex = 0 + + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { + + let layout = UICollectionViewFlowLayout() + layout.minimumLineSpacing = 10 + layout.minimumInteritemSpacing = 10 + layout.itemSize = .init(width: 106, height: 108) + layout.sectionInset = .init(top: 0, left: 15, bottom: 0, right: 15) + layout.scrollDirection = .horizontal + return layout + }() + + private lazy var collectionView: VPCollectionView = { + let collectionView = VPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) + collectionView.delegate = self + collectionView.dataSource = self +// collectionView.isScrollEnabled = false + collectionView.showsHorizontalScrollIndicator = false + collectionView.register(VPCoinsBuyCell.self, forCellWithReuseIdentifier: "cell") + return collectionView + }() + + private lazy var tipLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 0 + label.textColor = .colorFFFFFF(alpha: 0.5) + label.font = .fontRegular(ofSize: 12) + label.text = "kStoreTips".localized + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + vp_setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension VPPlayerCoinBuyView { + + private func vp_setupUI() { + addSubview(collectionView) + addSubview(tipLabel) + + collectionView.snp.makeConstraints { make in + make.left.right.top.equalToSuperview() + make.height.equalTo(collectionViewLayout.itemSize.height) +// make.bottom.equalToSuperview() + } + + tipLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(15) + make.right.lessThanOrEqualToSuperview().offset(-15) + make.top.equalTo(collectionView.snp.bottom).offset(12) + make.bottom.equalToSuperview() + } + + } + +} + +//MARK: -------------- UICollectionViewDelegate UICollectionViewDataSource -------------- +extension VPPlayerCoinBuyView: UICollectionViewDelegate, UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! VPCoinsBuyCell + cell.item = self.dataArr[indexPath.row] + cell.vp_isSelected = indexPath.row == selectedIndex + return cell + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return self.dataArr.count + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + self.selectedIndex = indexPath.row + collectionView.reloadData() + } + +} diff --git a/Veloria/Class/Player/View/VPPlayerRechargeView.swift b/Veloria/Class/Player/View/VPPlayerRechargeView.swift new file mode 100644 index 0000000..dbeebfb --- /dev/null +++ b/Veloria/Class/Player/View/VPPlayerRechargeView.swift @@ -0,0 +1,195 @@ +// +// VPPlayerRechargeView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/3. +// + +import UIKit + +class VPPlayerRechargeView: HWPanModalContentView { + + //MARK: UI属性 + private lazy var bgView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "bg_image_01")) + return imageView + }() + + private lazy var closeButton: UIButton = { + let button = UIButton(type: .custom) + button.setImage(UIImage(named: "close_icon_01"), for: .normal) + button.addTarget(self, action: #selector(handleCloseButton), for: .touchUpInside) + return button + }() + + private lazy var coinLabel: UILabel = { + let label = UILabel() + label.font = .fontRegular(ofSize: 13) + return label + }() + + private lazy var coinIconImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "coin_icon_07")) + return imageView + }() + + private lazy var scrollView: VPScrollView = { + let scrollView = VPScrollView() + return scrollView + }() + + private lazy var vipView: VPPlayerVipBuyView = { + let view = VPPlayerVipBuyView() + return view + }() + + private lazy var coinView: VPPlayerCoinBuyView = { + let view = VPPlayerCoinBuyView() + return view + }() + + override init(frame: CGRect) { + super.init(frame: frame) + vp_setupUI() + + updateCoin() + + requestRechargeData() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + + @objc private func handleCloseButton() { + self.dismiss(animated: true) { + + } + } + + //MARK: HWPanModalPresentable + override func panScrollable() -> UIScrollView? { + return scrollView + } + + override func longFormHeight() -> PanModalHeight { + return PanModalHeightMake(.content, UIScreen.height * (2 / 3)) + } + + override func showDragIndicator() -> Bool { + return false + } + + override func backgroundConfig() -> HWBackgroundConfig { + let config = HWBackgroundConfig() + config.backgroundAlpha = 0.6 + return config + } + + override func allowsDragToDismiss() -> Bool { + return false + } + + override func allowsTapBackgroundToDismiss() -> Bool { + return false + } + + override func allowsPullDownWhenShortState() -> Bool { + return false + } + + override func minVerticalVelocityToTriggerDismiss() -> CGFloat { + return 0 + } + + override func showsScrollableVerticalScrollIndicator() -> Bool { + return false + } + +} + +extension VPPlayerRechargeView { + + private func updateCoin() { + let coinCountStr = "\(VPLoginManager.manager.userInfo?.totalCoin ?? 0)" + let text = String(format: "Coins: %@".localized, coinCountStr) + let coinRange = text.ocString().range(of: coinCountStr) + + let string = NSMutableAttributedString(string: text) + string.color = .colorFFFFFF() + string.setColor(.color05CEA0(), range: coinRange) + + coinLabel.attributedText = string + } +} + +extension VPPlayerRechargeView { + + private func vp_setupUI() { + addSubview(bgView) + addSubview(closeButton) + addSubview(coinLabel) + addSubview(coinIconImageView) + addSubview(scrollView) + scrollView.addSubview(vipView) + scrollView.addSubview(coinView) + + bgView.snp.makeConstraints { make in + make.left.right.top.equalToSuperview() + } + + closeButton.snp.makeConstraints { make in + make.right.equalToSuperview().offset(-5) + make.top.equalToSuperview().offset(5) + make.width.equalTo(40) + make.height.equalTo(40) + } + + coinLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(15) + make.centerY.equalTo(coinIconImageView) + } + + coinIconImageView.snp.makeConstraints { make in + make.left.equalTo(coinLabel.snp.right).offset(3) + make.top.equalToSuperview().offset(40) + } + + scrollView.snp.makeConstraints { make in + make.left.right.equalToSuperview() + make.top.equalToSuperview().offset(56) + make.bottom.equalToSuperview() + } + + vipView.snp.makeConstraints { make in + make.left.equalToSuperview() + make.centerX.equalToSuperview() + make.top.equalToSuperview() + } + + coinView.snp.makeConstraints { make in + make.left.equalToSuperview() + make.centerX.equalToSuperview() + make.top.equalTo(vipView.snp.bottom).offset(20) + make.bottom.equalToSuperview().offset(-(UIScreen.tabbarSafeBottomMargin + 10)) + } + } + +} + +extension VPPlayerRechargeView { + + private func requestRechargeData() { + + VPWalletAPI.requestPayTemplate { [weak self] model in + guard let self = self else { return } + if let model = model { + self.vipView.dataArr = model.list_sub_vip ?? [] + self.coinView.dataArr = model.list_coins ?? [] + } + } + + } + +} diff --git a/Veloria/Class/Player/View/VPPlayerVipBuyView.swift b/Veloria/Class/Player/View/VPPlayerVipBuyView.swift new file mode 100644 index 0000000..af87225 --- /dev/null +++ b/Veloria/Class/Player/View/VPPlayerVipBuyView.swift @@ -0,0 +1,144 @@ +// +// VPPlayerVipBuyView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/3. +// + +import UIKit + +class VPPlayerVipBuyView: UIView { + + var dataArr: [VPPayTemplateItem] = [] { + didSet { + self.collectionView.reloadData() + } + } + + private lazy var currentIndex: Int = 0 + + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { + let layout = UICollectionViewFlowLayout() + layout.scrollDirection = .horizontal + layout.minimumLineSpacing = 10 + layout.sectionInset = .init(top: 0, left: 15, bottom: 0, right: 15) + layout.itemSize = .init(width: 332, height: 138) + return layout + }() + + private lazy var collectionView: VPCollectionView = { + let collectionView = VPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) + collectionView.delegate = self + collectionView.dataSource = self + collectionView.showsHorizontalScrollIndicator = false + collectionView.register(VPVipBuyCell.self, forCellWithReuseIdentifier: "cell") + return collectionView + }() + + private lazy var tipBgView: UIView = { + let view = VPGradientView() + view.colors = [UIColor.color05CEA0(alpha: 0.2).cgColor, UIColor.color05CEA0(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 = 8 + view.layer.masksToBounds = true + return view + }() + + private lazy var tipLabel: UILabel = { + + + let hText1 = "1 week".localized + let text1 = "· " + String(format: "kVipPrivilegeText4".localized, hText1) + + let hText2 = "8 days".localized + let text2 = "· " + String(format: "kVipPrivilegeText5".localized, hText2) + + let text3 = "· " + String(format: "kVipPrivilegeText6".localized) + + let text = text1 + "\n" + text2 + "\n" + text3 + + let hRange1 = text.ocString().range(of: hText1) + let hRange2 = text.ocString().range(of: hText2) + + let string = NSMutableAttributedString(string: text) + string.lineSpacing = 5 + string.color = .colorFFFFFF(alpha: 0.8) + string.setColor(.color05CEA0(), range: hRange1) + string.setColor(.color05CEA0(), range: hRange2) + + + + + let label = UILabel() + label.font = .fontRegular(ofSize: 12) + label.attributedText = string + label.numberOfLines = 0 + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + vp_setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension VPPlayerVipBuyView { + + private func vp_setupUI() { + addSubview(collectionView) + addSubview(tipBgView) + tipBgView.addSubview(tipLabel) + + collectionView.snp.makeConstraints { make in + make.left.right.equalToSuperview() + make.top.equalToSuperview() + make.height.equalTo(collectionViewLayout.itemSize.height) + } + + tipBgView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(15) + make.right.equalToSuperview().offset(-15) + make.top.equalTo(collectionView.snp.bottom).offset(10) + make.bottom.equalToSuperview() + } + + tipLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(14) + make.right.lessThanOrEqualToSuperview().offset(-14) + make.top.equalToSuperview().offset(10) + make.centerY.equalToSuperview() + } + } + +} + +//MARK: -------------- UICollectionViewDelegate UICollectionViewDataSource -------------- +extension VPPlayerVipBuyView: UICollectionViewDelegate, UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! VPVipBuyCell + cell.item = dataArr[indexPath.row] + cell.vp_isSelected = indexPath.row == currentIndex + return cell + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return dataArr.count + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + if currentIndex != indexPath.row { + currentIndex = indexPath.row + self.collectionView.reloadData() + } + + } +} diff --git a/Veloria/Class/Player/View/VPVideoLockView.swift b/Veloria/Class/Player/View/VPVideoLockView.swift new file mode 100644 index 0000000..2048b05 --- /dev/null +++ b/Veloria/Class/Player/View/VPVideoLockView.swift @@ -0,0 +1,92 @@ +// +// VPVideoLockView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/3. +// + +import UIKit + +class VPVideoLockView: UIView { + + var videoInfo: VPVideoInfoModel? { + didSet { + unlockButton.setNeedsUpdateConfiguration() + } + } + + var clickUnlockButton: (() -> Void)? + + private lazy var unlockButton: UIButton = { + var config = UIButton.Configuration.plain() + config.imagePlacement = .leading + config.imagePadding = 10 + config.image = UIImage(named: "lock_icon_02") + + let button = VPGradientButton(configuration: config) + button.bt_setGradientBorder() + button.colors = [UIColor.color05CEA0(alpha: 0.3).cgColor, UIColor.color7C174F(alpha: 0.3).cgColor] + button.locations = [0, 1] + button.startPoint = .init(x: 0, y: 0.3) + button.endPoint = .init(x: 1, y: 0.8) + button.layer.cornerRadius = 24 + button.layer.masksToBounds = true + button.configurationUpdateHandler = { [weak self] button in + guard let self = self else { return } + let title = String(format: "Unlocking costs %@ coins".localized, "\(videoInfo?.coins ?? 0)") + let string = AttributedString.createAttributedString(string: title, color: .colorFFFFFF(), font: .fontRegular(ofSize: 14)) + button.configuration?.attributedTitle = string + } + button.addTarget(self, action: #selector(handleUnlockButton), for: .touchUpInside) + return button + }() + + private lazy var coinCountLabel: UILabel = { + let userInfo = VPLoginManager.manager.userInfo + + let label = UILabel() + label.font = .fontRegular(ofSize: 12) + label.textColor = .colorB5B5B5() + label.text = String(format: "Balance: %@ Coins | %@ Bonus".localized, "\(userInfo?.coin_left_total ?? 0)", "\(userInfo?.send_coin_left_total ?? 0)") + return label + }() + + + override init(frame: CGRect) { + super.init(frame: frame) + + backgroundColor = .color000000(alpha: 0.8) + + vp_setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func handleUnlockButton() { + self.clickUnlockButton?() + } + +} + +extension VPVideoLockView { + + private func vp_setupUI() { + addSubview(unlockButton) + addSubview(coinCountLabel) + + unlockButton.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.left.equalToSuperview().offset(40) + make.centerY.equalToSuperview() + make.height.equalTo(48) + } + + coinCountLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(unlockButton.snp.bottom).offset(10) + } + } + +} diff --git a/Veloria/Class/Player/ViewModel/VPVideoPlayViewModel.swift b/Veloria/Class/Player/ViewModel/VPVideoPlayViewModel.swift index 517550b..b25f972 100644 --- a/Veloria/Class/Player/ViewModel/VPVideoPlayViewModel.swift +++ b/Veloria/Class/Player/ViewModel/VPVideoPlayViewModel.swift @@ -17,9 +17,6 @@ class VPVideoPlayViewModel: NSObject { oldValue?.isCurrent = false oldValue?.pause() -// self.currentPlayer?.playerFinishHadle = { [weak self] in -// self?.handlePlayFinish?() -// } self.currentPlayer?.isCurrent = true self.currentPlayer?.rate = rateModel.rate.getRate() } @@ -45,4 +42,6 @@ class VPVideoPlayViewModel: NSObject { var handlePlayTimeDidChange: ((_ time: Int) -> Void)? ///选集 var handleEpisode: (() -> Void)? + + var handleUnlock: (() -> Void)? } diff --git a/Veloria/Class/Rewards/Controller/VPRewardsViewController.swift b/Veloria/Class/Rewards/Controller/VPRewardsViewController.swift new file mode 100644 index 0000000..a2dbbf9 --- /dev/null +++ b/Veloria/Class/Rewards/Controller/VPRewardsViewController.swift @@ -0,0 +1,20 @@ +// +// VPRewardsViewController.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/3. +// + +import UIKit + +class VPRewardsViewController: VPCampaignWebViewController { + + override func viewDidLoad() { + self.urlStr = kVPRewardsWebUrl + super.viewDidLoad() + + self.theme = nil + + } + +} diff --git a/Veloria/Class/Wallet/Controller/VPCoinsViewController.swift b/Veloria/Class/Wallet/Controller/VPCoinsViewController.swift index 690c866..4eb5084 100644 --- a/Veloria/Class/Wallet/Controller/VPCoinsViewController.swift +++ b/Veloria/Class/Wallet/Controller/VPCoinsViewController.swift @@ -174,7 +174,6 @@ extension VPCoinsViewController: UICollectionViewDelegate, UICollectionViewDataS } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - vpLog(message: indexPath.row) self.selectedIndex = indexPath.row collectionView.reloadData() } diff --git a/Veloria/Class/Wallet/View/VPWalletHeaderView.swift b/Veloria/Class/Wallet/View/VPWalletHeaderView.swift index 5afbbdc..bf89b1c 100644 --- a/Veloria/Class/Wallet/View/VPWalletHeaderView.swift +++ b/Veloria/Class/Wallet/View/VPWalletHeaderView.swift @@ -16,7 +16,6 @@ class VPWalletHeaderView: UIView { coinCountLabel.text = "\(userInfo?.totalCoin ?? 0)" rechargeCoinView.count = userInfo?.coin_left_total ?? 0 sendCoinView.count = userInfo?.send_coin_left_total ?? 0 -// coinCountLabel.text = "1234567890" } } diff --git a/Veloria/Source/Assets.xcassets/icon/coin_icon_07.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/coin_icon_07.imageset/Contents.json new file mode 100644 index 0000000..c18e822 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/coin_icon_07.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_07.imageset/金币1 2@2x.png b/Veloria/Source/Assets.xcassets/icon/coin_icon_07.imageset/金币1 2@2x.png new file mode 100644 index 0000000..e3472ed Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/coin_icon_07.imageset/金币1 2@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/coin_icon_07.imageset/金币1 2@3x.png b/Veloria/Source/Assets.xcassets/icon/coin_icon_07.imageset/金币1 2@3x.png new file mode 100644 index 0000000..32a143d Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/coin_icon_07.imageset/金币1 2@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/lock_bg_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/lock_bg_icon_01.imageset/Contents.json new file mode 100644 index 0000000..d0ef545 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/lock_bg_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Rectangle 26@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Rectangle 26@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/lock_bg_icon_01.imageset/Rectangle 26@2x.png b/Veloria/Source/Assets.xcassets/icon/lock_bg_icon_01.imageset/Rectangle 26@2x.png new file mode 100644 index 0000000..6076ed8 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/lock_bg_icon_01.imageset/Rectangle 26@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/lock_bg_icon_01.imageset/Rectangle 26@3x.png b/Veloria/Source/Assets.xcassets/icon/lock_bg_icon_01.imageset/Rectangle 26@3x.png new file mode 100644 index 0000000..adfbf06 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/lock_bg_icon_01.imageset/Rectangle 26@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/lock_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/lock_icon_01.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/lock_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/lock_icon_01.imageset/Frame@2x.png b/Veloria/Source/Assets.xcassets/icon/lock_icon_01.imageset/Frame@2x.png new file mode 100644 index 0000000..cb1e208 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/lock_icon_01.imageset/Frame@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/lock_icon_01.imageset/Frame@3x.png b/Veloria/Source/Assets.xcassets/icon/lock_icon_01.imageset/Frame@3x.png new file mode 100644 index 0000000..cf91850 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/lock_icon_01.imageset/Frame@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/lock_icon_02.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/lock_icon_02.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/lock_icon_02.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/lock_icon_02.imageset/Frame@2x.png b/Veloria/Source/Assets.xcassets/icon/lock_icon_02.imageset/Frame@2x.png new file mode 100644 index 0000000..532465f Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/lock_icon_02.imageset/Frame@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/lock_icon_02.imageset/Frame@3x.png b/Veloria/Source/Assets.xcassets/icon/lock_icon_02.imageset/Frame@3x.png new file mode 100644 index 0000000..822f003 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/lock_icon_02.imageset/Frame@3x.png differ diff --git a/Veloria/Source/en.lproj/Localizable.strings b/Veloria/Source/en.lproj/Localizable.strings index b81ed32..90bc69f 100644 --- a/Veloria/Source/en.lproj/Localizable.strings +++ b/Veloria/Source/en.lproj/Localizable.strings @@ -39,7 +39,6 @@ "Donate" = "Donate"; "Wallet" = "Wallet"; "Store" = "Store"; -"Rewards" = "Rewards"; "Favorites" = "Favorites"; "Language" = "Language"; "VIP" = "VIP"; @@ -63,6 +62,8 @@ "VIP Record" = "VIP Record"; "Total Coins" = "Total Coins"; "Recharge" = "Recharge"; +"Unlocking costs %@ coins" = "Unlocking costs %@ coins"; +"Balance: %@ Coins | %@ Bonus" = "Balance: %@ Coins | %@ Bonus"; "kHomeTitleText" = "10,000+ addictive shorts await!"; @@ -78,6 +79,10 @@ "kVipPrivilegeText6" = "Auto renew, cancel anytime"; //无网提示 "kNetworkToast01" = "The service is abnormal. Check the network."; +//解锁上一集提示 +"kLockPreviousEpisodeText" = "The prequel to this series is not unlocked. Please unlock the prequel before unlocking this series"; +//解锁失败 +"kLockFailText" = "Purchase failed, please try again later!"; "kStoreTips" = "1. Coins are virtual items and cannot be refunded. Use it for this product.