首页更多页面,W2A统计功能,Bug处理

This commit is contained in:
zjx 2025-06-09 18:27:24 +08:00
parent eaa1d76bbe
commit a30c319c05
36 changed files with 687 additions and 56 deletions

View File

@ -217,6 +217,8 @@
BFF5B26E2DF297680044227A /* VPOpenAppModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B26D2DF297680044227A /* VPOpenAppModel.swift */; }; BFF5B26E2DF297680044227A /* VPOpenAppModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B26D2DF297680044227A /* VPOpenAppModel.swift */; };
BFF5B2752DF2C3750044227A /* VPDetailRecommandView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2742DF2C3750044227A /* VPDetailRecommandView.swift */; }; BFF5B2752DF2C3750044227A /* VPDetailRecommandView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2742DF2C3750044227A /* VPDetailRecommandView.swift */; };
BFF5B2772DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2762DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift */; }; BFF5B2772DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2762DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift */; };
BFF5B2792DF679720044227A /* VPMoreVideoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2782DF679720044227A /* VPMoreVideoViewController.swift */; };
BFF5B4AF2DF6B6630044227A /* VPMutualCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B4AE2DF6B6630044227A /* VPMutualCollectionView.swift */; };
F939C04AD4003BA127F15C28 /* Pods_Veloria.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F57E87E765BF8D72A43DCA /* Pods_Veloria.framework */; }; F939C04AD4003BA127F15C28 /* Pods_Veloria.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F57E87E765BF8D72A43DCA /* Pods_Veloria.framework */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@ -439,6 +441,8 @@
BFF5B26D2DF297680044227A /* VPOpenAppModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPOpenAppModel.swift; sourceTree = "<group>"; }; BFF5B26D2DF297680044227A /* VPOpenAppModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPOpenAppModel.swift; sourceTree = "<group>"; };
BFF5B2742DF2C3750044227A /* VPDetailRecommandView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPDetailRecommandView.swift; sourceTree = "<group>"; }; BFF5B2742DF2C3750044227A /* VPDetailRecommandView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPDetailRecommandView.swift; sourceTree = "<group>"; };
BFF5B2762DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPDetailRecommandBannerCell.swift; sourceTree = "<group>"; }; BFF5B2762DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPDetailRecommandBannerCell.swift; sourceTree = "<group>"; };
BFF5B2782DF679720044227A /* VPMoreVideoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMoreVideoViewController.swift; sourceTree = "<group>"; };
BFF5B4AE2DF6B6630044227A /* VPMutualCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMutualCollectionView.swift; sourceTree = "<group>"; };
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 = "<group>"; }; 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 = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -676,6 +680,7 @@
1B056E562DDACC6B007EE38D /* VPHomePageViewController.swift */, 1B056E562DDACC6B007EE38D /* VPHomePageViewController.swift */,
BF0FA7382DDECF8900C9E5F2 /* VPHomeListViewController.swift */, BF0FA7382DDECF8900C9E5F2 /* VPHomeListViewController.swift */,
BF0FA7742DE071B500C9E5F2 /* VPSearchViewController.swift */, BF0FA7742DE071B500C9E5F2 /* VPSearchViewController.swift */,
BFF5B2782DF679720044227A /* VPMoreVideoViewController.swift */,
); );
path = Controller; path = Controller;
sourceTree = "<group>"; sourceTree = "<group>";
@ -909,6 +914,7 @@
BFF5AFE12DEED2960044227A /* VPPlayerCoinBuyView.swift */, BFF5AFE12DEED2960044227A /* VPPlayerCoinBuyView.swift */,
BFF5B2742DF2C3750044227A /* VPDetailRecommandView.swift */, BFF5B2742DF2C3750044227A /* VPDetailRecommandView.swift */,
BFF5B2762DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift */, BFF5B2762DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift */,
BFF5B4AE2DF6B6630044227A /* VPMutualCollectionView.swift */,
); );
path = View; path = View;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1433,6 +1439,7 @@
BFF5AFD42DE9A5FB0044227A /* VPVIPRecordCell.swift in Sources */, BFF5AFD42DE9A5FB0044227A /* VPVIPRecordCell.swift in Sources */,
BFF5AFD62DE9A8D70044227A /* VPWalletHeaderView.swift in Sources */, BFF5AFD62DE9A8D70044227A /* VPWalletHeaderView.swift in Sources */,
BF0FA6EE2DDC5F8700C9E5F2 /* JXUUID.m in Sources */, BF0FA6EE2DDC5F8700C9E5F2 /* JXUUID.m in Sources */,
BFF5B2792DF679720044227A /* VPMoreVideoViewController.swift in Sources */,
BF5E75B12DE4656600DE9DFE /* VPCampaignWebViewController.swift in Sources */, BF5E75B12DE4656600DE9DFE /* VPCampaignWebViewController.swift in Sources */,
BF5E75BC2DE546AD00DE9DFE /* VPAboutUsCell.swift in Sources */, BF5E75BC2DE546AD00DE9DFE /* VPAboutUsCell.swift in Sources */,
BFF5AFD02DE9A0370044227A /* VPCoinRecordCell.swift in Sources */, BFF5AFD02DE9A0370044227A /* VPCoinRecordCell.swift in Sources */,
@ -1522,6 +1529,7 @@
BF0FA7162DDC78FF00C9E5F2 /* ZKCycleScrollViewFlowLayout.swift in Sources */, BF0FA7162DDC78FF00C9E5F2 /* ZKCycleScrollViewFlowLayout.swift in Sources */,
BFF5B2612DF16B430044227A /* JXIAPManager.swift in Sources */, BFF5B2612DF16B430044227A /* JXIAPManager.swift in Sources */,
BF0FA7172DDC78FF00C9E5F2 /* ZKCycleScrollView.swift in Sources */, BF0FA7172DDC78FF00C9E5F2 /* ZKCycleScrollView.swift in Sources */,
BFF5B4AF2DF6B6630044227A /* VPMutualCollectionView.swift in Sources */,
BF0FA7612DDFFE7100C9E5F2 /* VPVideoDetailModel.swift in Sources */, BF0FA7612DDFFE7100C9E5F2 /* VPVideoDetailModel.swift in Sources */,
BFF5AFD22DE9A58A0044227A /* VPVIPRecordViewController.swift in Sources */, BFF5AFD22DE9A58A0044227A /* VPVIPRecordViewController.swift in Sources */,
BFF5AFDA2DEE90350044227A /* VPVideoLockView.swift in Sources */, BFF5AFDA2DEE90350044227A /* VPVideoLockView.swift in Sources */,

View File

@ -16,7 +16,7 @@ extension SceneDelegate {
} }
//facebook //facebook
var result = ApplicationDelegate.shared.application(UIApplication.shared, open: url, sourceApplication: nil, annotation: [UIApplication.OpenURLOptionsKey.annotation]) let result = ApplicationDelegate.shared.application(UIApplication.shared, open: url, sourceApplication: nil, annotation: [UIApplication.OpenURLOptionsKey.annotation])
if !result { if !result {
vp_handleOpenAppMessage(webpageURL: url) vp_handleOpenAppMessage(webpageURL: url)
@ -33,13 +33,17 @@ extension SceneDelegate {
extension SceneDelegate { extension SceneDelegate {
static var hasOpenMessage = false static var hasOpenMessage = false
///
static var isNeedRetry = false
func vp_handleOpenAppMessage(webpageURL: URL?) { func vp_handleOpenAppMessage(webpageURL: URL?) {
guard VPNetworkReachabilityManager.manager.isReachable == true else { return } guard VPNetworkReachabilityManager.manager.isReachable == true else {
Self.isNeedRetry = true
return
}
Self.isNeedRetry = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self._handleOpenAppMessage(webpageURL: webpageURL) self._handleOpenAppMessage(webpageURL: webpageURL)
} }
@ -50,7 +54,7 @@ extension SceneDelegate {
Self.hasOpenMessage = true Self.hasOpenMessage = true
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
Self.hasOpenMessage = false Self.hasOpenMessage = false
} }
@ -58,7 +62,8 @@ extension SceneDelegate {
var statUrlStr: String? = webpageURL?.absoluteString var statUrlStr: String? = webpageURL?.absoluteString
var data: [String : Any]? = webpageURL?.query?.vp_urlQuryToDictionary() var data: [String : Any]? = webpageURL?.query?.vp_urlQuryToDictionary()
if let pasteStr = UIPasteboard.general.string {
if let pasteStr = UIPasteboard.general.string, pasteStr.contains("veloriaapp") {
UIPasteboard.general.string = nil UIPasteboard.general.string = nil
let tempArr = pasteStr.components(separatedBy: "?") let tempArr = pasteStr.components(separatedBy: "?")
let query = tempArr.last let query = tempArr.last
@ -70,6 +75,10 @@ extension SceneDelegate {
} }
} }
if let urlStr = statUrlStr {// if let urlStr = statUrlStr {//
VPStatAPI.requestStatW2a(data: urlStr) VPStatAPI.requestStatW2a(data: urlStr)
} }
@ -86,4 +95,10 @@ extension SceneDelegate {
} }
///
func vp_retryHandleOpenAppMessage() {
guard Self.isNeedRetry else { return }
vp_handleOpenAppMessage(webpageURL: nil)
}
} }

View File

@ -30,25 +30,55 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
} }
func sceneDidDisconnect(_ scene: UIScene) { func sceneDidDisconnect(_ scene: UIScene) {
} }
func sceneDidBecomeActive(_ scene: UIScene) { func sceneDidBecomeActive(_ scene: UIScene) {
VPStatAPI.requestEnterApp() // vpLog(message: "++++++++++++++sceneDidBecomeActive")
vp_handleOpenAppMessage(webpageURL: nil) enterForeground()
} }
func sceneWillResignActive(_ scene: UIScene) { func sceneWillResignActive(_ scene: UIScene) {
VPStatAPI.requestLeaveApp() // vpLog(message: "++++++++++++++sceneWillResignActive")
enterBackground()
} }
func sceneWillEnterForeground(_ scene: UIScene) { func sceneWillEnterForeground(_ scene: UIScene) {
// vpLog(message: "++++++++++++++sceneWillEnterForeground")
// enterForeground()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.vp_handleOpenAppMessage(webpageURL: nil)
}
} }
func sceneDidEnterBackground(_ scene: UIScene) { func sceneDidEnterBackground(_ scene: UIScene) {
// vpLog(message: "++++++++++++++sceneDidEnterBackground")
// enterBackground()
} }
// private var isEnterForeground = false
private func enterForeground() {
// if !isEnterForeground {
// vpLog(message: "++++++++++++++enterForeground")
// }
// isEnterForeground = true
handleOnLine()
VPStatAPI.requestEnterApp()
}
private func enterBackground() {
// if isEnterForeground {
// }
// vpLog(message: "++++++++++++++enterBackground")
// isEnterForeground = false
VPStatAPI.requestLeaveApp()
}
} }
extension SceneDelegate { extension SceneDelegate {
@ -59,8 +89,11 @@ extension SceneDelegate {
@objc private func reachabilityDidChangeNotification() { @objc private func reachabilityDidChangeNotification() {
vp_handleOpenAppMessage(webpageURL: nil) vp_retryHandleOpenAppMessage()
if VPNetworkReachabilityManager.manager.isReachable == true {
handleOnLine()
}
} }
} }

View File

@ -15,4 +15,10 @@ extension Date {
return dateComponents.day ?? 0 return dateComponents.day ?? 0
} }
func formatString(dateFormat: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = dateFormat
return formatter.string(from: self)
}
} }

View File

@ -51,3 +51,24 @@ extension String {
} }
} }
extension String {
func vp_range(of searchString: String) -> [NSRange] {
do {
let newSearch = searchString.lowercased()
let newText = self.lowercased()
let regex = try NSRegularExpression(pattern: newSearch)
let matches = regex.matches(in: newText, range: NSRange(self.startIndex..., in: newText))
let ranges = matches.map { $0.range }
return ranges
} catch {
return []
}
}
}

View File

@ -53,4 +53,14 @@ class VPHomeAPI: NSObject {
} }
} }
static func requestCategories(completer: ((_ list: [VPCategoryModel]?) -> Void)?) {
var param = VPNetworkParameters(path: "/getCategories")
param.method = .get
VPNetwork.request(parameters: param) { (response: VPNetworkResponse<VPListModel<VPCategoryModel>>) in
completer?(response.data?.list)
}
}
} }

View File

@ -80,8 +80,15 @@ class VPNetwork: NSObject {
} }
completion?(res) completion?(res)
} else { } else {
if code == 402, parameters.isToast {
VPToast.show(text: "kNetworkToast02".localized)
}
///token ///token
self.requestToken(completer: nil) self.requestToken { token in
if token != nil {
VPLoginManager.manager.updateUserInfo(completer: nil)
}
}
/// ///
if let tokenOperation = self.tokenOperation, parameters.path != "/customer/register" { if let tokenOperation = self.tokenOperation, parameters.path != "/customer/register" {
@ -137,7 +144,7 @@ class VPNetwork: NSObject {
var res = VPNetworkResponse<T>() var res = VPNetworkResponse<T>()
res.code = -1 res.code = -1
if parameters.isToast { if parameters.isToast {
VPToast.show(text: "network_toast_01".localized) VPToast.show(text: "kNetworkToast01".localized)
} }
completion?(res) completion?(res)
break break

View File

@ -34,7 +34,11 @@ extension VPWebViewController {
self.navigationController?.pushViewController(vc, animated: true) self.navigationController?.pushViewController(vc, animated: true)
case VPWebMessageOpenFeedbackDetail: case VPWebMessageOpenFeedbackDetail:
guard let body = body as? [String : Any] else { return }
guard let id = body["id"] as? Int else { return }
let vc = VPCampaignWebViewController() let vc = VPCampaignWebViewController()
vc.id = "\(id)"
vc.bgImageView.isHidden = true vc.bgImageView.isHidden = true
vc.urlStr = kVPFeedBackDetailWebUrl vc.urlStr = kVPFeedBackDetailWebUrl
self.navigationController?.pushViewController(vc, animated: true) self.navigationController?.pushViewController(vc, animated: true)

View File

@ -22,7 +22,8 @@ class VPExploreViewController: VPVideoPlayerViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(loginStateDidChangeNotification), name: VPLoginManager.loginStateDidChangeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(loginStateDidChangeNotification), name: VPLoginManager.loginStateDidChangeNotification, object: nil)
self.collectionView.vp_onRefrsh = true
self.collectionView.vp_refreshDelegate = self
self.delegate = self self.delegate = self
self.dataSource = self self.dataSource = self
@ -75,22 +76,37 @@ extension VPExploreViewController: VPPlayerListViewControllerDataSource {
} }
//MARK: -------------- VPMutualCollectionViewDelegate --------------
extension VPExploreViewController: VPMutualCollectionViewDelegate {
func vp_loadNewData(collectionView: VPMutualCollectionView) {
collectionView.endRefresh()
requestDataArr(page: 1) { [weak self] in
guard let self = self else { return }
self.collectionView.endRefresh()
}
}
}
extension VPExploreViewController { extension VPExploreViewController {
private func requestDataArr(page: Int) { private func requestDataArr(page: Int, completer: (() -> Void)? = nil) {
VPVideoAPI.requestRecommandsVideo(page: page) { [weak self] listModel in VPVideoAPI.requestRecommandsVideo(page: page) { [weak self] listModel in
guard let self = self else { return } guard let self = self else { return }
if let listModel = listModel, let list = listModel.list { if let listModel = listModel, let list = listModel.list {
if page == 1 { if page == 1 {
self.setDataArr(dataArr: list) { [weak self] in self.setDataArr(dataArr: list) { [weak self] in
self?.play() self?.scrollToItem(indexPath: IndexPath(row: 0, section: 0), animated: false)
// self?.play()
} }
} else { } else {
self.addDataArr(dataArr: list) self.addDataArr(dataArr: list)
} }
self.pagination = listModel.pagination self.pagination = listModel.pagination
} }
completer?()
} }
} }

View File

@ -18,7 +18,7 @@ class VPHomePageViewController: VPViewController {
param.wViewController = { [weak self] index in param.wViewController = { [weak self] index in
let categoryModel = self?.viewModel.categoryList[index] let categoryModel = self?.viewModel.categoryList[index]
let vc = VPHomeListViewController() let vc = VPHomeListViewController()
vc.categoryId = categoryModel?.category_id vc.categoryId = categoryModel?.id
return vc return vc
} }
@ -128,6 +128,7 @@ class VPHomePageViewController: VPViewController {
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: VPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: VPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
requestHomeData() requestHomeData()
requestCategories()
setupPageView() setupPageView()
vp_setupUI() vp_setupUI()
@ -147,6 +148,7 @@ class VPHomePageViewController: VPViewController {
self.pageView.downSc?.vp_endHeaderRefreshing() self.pageView.downSc?.vp_endHeaderRefreshing()
} }
self.requestHomeData() self.requestHomeData()
self.requestCategories()
} }
@ -187,6 +189,7 @@ extension VPHomePageViewController {
if self.viewModel.oldModuleList == nil { if self.viewModel.oldModuleList == nil {
requestHomeData() requestHomeData()
} }
requestCategories()
} }
} }
@ -247,18 +250,25 @@ extension VPHomePageViewController {
guard let self = self else { return } guard let self = self else { return }
if let list = list { if let list = list {
self.viewModel.oldModuleList = list self.viewModel.oldModuleList = list
if self.viewModel.needUpdateCategory {
self.viewModel.needUpdateCategory = false
self.pageParam.wTitleArr = self.viewModel.categoryTitleList
self.pageView.updateMenuData()
self.setupPageView()
}
self.searchButton.marqueeArr = self.viewModel.marqueeArr self.searchButton.marqueeArr = self.viewModel.marqueeArr
self.pageView.downSc?.reloadData() self.pageView.downSc?.reloadData()
} }
} }
}
private func requestCategories() {
if self.viewModel.rawCategoryList.count > 0 { return }
VPHomeAPI.requestCategories { [weak self] list in
guard let self = self else { return }
if let list = list {
self.viewModel.rawCategoryList = list
self.pageParam.wTitleArr = self.viewModel.categoryTitleList
self.pageView.updateMenuData()
self.setupPageView()
}
}
} }
} }

View File

@ -0,0 +1,118 @@
//
// VPMoreVideoViewController.swift
// Veloria
//
// Created by on 2025/6/9.
//
import UIKit
class VPMoreVideoViewController: VPViewController {
var dataArr: [VPShortModel] = [] {
didSet {
self.collectionView.reloadData()
}
}
private lazy var titleLeftImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "title_icon_01"))
return imageView
}()
private lazy var titleRightImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "title_icon_02"))
return imageView
}()
private(set) lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = .boldSystemFont(ofSize: 18)
label.textColor = .colorFFFFFF()
return label
}()
// VPSearchResultCell
private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout()
layout.itemSize = .init(width: UIScreen.width - 30, height: 108)
layout.sectionInset = .init(top: 0, left: 15, bottom: 0, right: 15)
layout.minimumLineSpacing = 10
return layout
}()
private lazy var collectionView: VPCollectionView = {
let collectionView = VPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.contentInset = .init(top: 0, left: 0, bottom: UIScreen.tabbarSafeBottomMargin + 10, right: 0)
collectionView.register(VPSearchResultCell.self, forCellWithReuseIdentifier: "cell")
return collectionView
}()
override func viewDidLoad() {
super.viewDidLoad()
vp_setupUI()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: true)
setNavigationNormalStyle()
}
}
extension VPMoreVideoViewController {
private func vp_setupUI() {
view.addSubview(titleLeftImageView)
view.addSubview(titleRightImageView)
view.addSubview(titleLabel)
view.addSubview(collectionView)
titleLeftImageView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.top.equalToSuperview().offset(UIScreen.navBarHeight + 10)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(titleLeftImageView.snp.right).offset(1)
make.centerY.equalTo(titleLeftImageView)
}
titleRightImageView.snp.makeConstraints { make in
make.centerY.equalTo(titleLeftImageView)
make.left.equalTo(titleLabel.snp.right).offset(1)
}
collectionView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.top.equalToSuperview().offset(UIScreen.navBarHeight + 60)
}
}
}
//MARK: -------------- UICollectionViewDelegate & UICollectionViewDataSource --------------
extension VPMoreVideoViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! VPSearchResultCell
cell.model = dataArr[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.dataArr.count
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let model = dataArr[indexPath.row]
let vc = VPDetailPlayerViewController()
vc.shortPlayId = model.short_play_id
self.navigationController?.pushViewController(vc, animated: true)
}
}

View File

@ -10,6 +10,6 @@ import SmartCodable
class VPCategoryModel: VPModel, SmartCodable { class VPCategoryModel: VPModel, SmartCodable {
var category_name: String? var name: String?
var category_id: String? var id: String?
} }

View File

@ -16,7 +16,7 @@ class VPHomeModuleItem: VPModel, SmartCodable {
/// ///
case cagetory_recommand = "home_cagetory_recommand" case cagetory_recommand = "home_cagetory_recommand"
case week_ranking = "week_ranking" case week_ranking = "week_ranking"
case category_navigation = "category_navigation" // case category_navigation = "category_navigation"
/// ///
case marquee = "marquee" case marquee = "marquee"
} }
@ -33,11 +33,11 @@ class VPHomeModuleItem: VPModel, SmartCodable {
func didFinishMapping() { func didFinishMapping() {
if let data = data as? [[String : Any]] { if let data = data as? [[String : Any]] {
if module_key == .category_navigation { // if module_key == .category_navigation {
self.categoryList = [VPCategoryModel].deserialize(from: data) // self.categoryList = [VPCategoryModel].deserialize(from: data)
} else { // } else {
self.list = [VPShortModel].deserialize(from: data) // }
} self.list = [VPShortModel].deserialize(from: data)
} else if let data = data as? [String : Any] { } else if let data = data as? [String : Any] {
var dataList: [[String : Any]]? var dataList: [[String : Any]]?
if let list = data["list"] as? [[String : Any]] { if let list = data["list"] as? [[String : Any]] {

View File

@ -38,6 +38,18 @@ class VPHomeRankingContentCell: VPHomeItemContentCell {
return label return label
}() }()
private lazy var moreButton: UIButton = {
var config = UIButton.Configuration.plain()
config.imagePadding = 1
config.imagePlacement = .trailing
config.contentInsets = .init(top: 5, leading: 0, bottom: 5, trailing: 0)
config.image = UIImage(named: "arrow_right_icon_03")
config.attributedTitle = AttributedString.createAttributedString(string: "More".localized, color: .colorFFFFFF(alpha: 0.5), font: .fontRegular(ofSize: 12))
let button = UIButton(configuration: config)
button.addTarget(self, action: #selector(handleMoreButton), for: .touchUpInside)
return button
}()
private lazy var collectionViewLayout: UICollectionViewFlowLayout = { private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout() let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal layout.scrollDirection = .horizontal
@ -67,6 +79,13 @@ class VPHomeRankingContentCell: VPHomeItemContentCell {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
@objc private func handleMoreButton() {
let vc = VPMoreVideoViewController()
vc.titleLabel.text = titleLabel.text
vc.dataArr = self.item?.list ?? []
self.viewController?.navigationController?.pushViewController(vc, animated: true)
}
} }
extension VPHomeRankingContentCell { extension VPHomeRankingContentCell {
@ -75,6 +94,7 @@ extension VPHomeRankingContentCell {
containerView.addSubview(iconImageView) containerView.addSubview(iconImageView)
containerView.addSubview(titleLabel) containerView.addSubview(titleLabel)
containerView.addSubview(collectionView) containerView.addSubview(collectionView)
containerView.addSubview(moreButton)
iconImageView.snp.makeConstraints { make in iconImageView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15) make.left.equalToSuperview().offset(15)
@ -92,6 +112,10 @@ extension VPHomeRankingContentCell {
make.height.equalTo(collectionViewLayout.itemSize.height * 3 + collectionViewLayout.minimumInteritemSpacing * 2) make.height.equalTo(collectionViewLayout.itemSize.height * 3 + collectionViewLayout.minimumInteritemSpacing * 2)
} }
moreButton.snp.makeConstraints { make in
make.centerY.equalTo(titleLabel)
make.right.equalToSuperview().offset(-13)
}
} }
} }

View File

@ -32,6 +32,18 @@ class VPHomeRecommandContentCell: VPHomeItemContentCell {
return label return label
}() }()
private lazy var moreButton: UIButton = {
var config = UIButton.Configuration.plain()
config.imagePadding = 1
config.imagePlacement = .trailing
config.contentInsets = .init(top: 5, leading: 0, bottom: 5, trailing: 0)
config.image = UIImage(named: "arrow_right_icon_03")
config.attributedTitle = AttributedString.createAttributedString(string: "More".localized, color: .colorFFFFFF(alpha: 0.5), font: .fontRegular(ofSize: 12))
let button = UIButton(configuration: config)
button.addTarget(self, action: #selector(handleMoreButton), for: .touchUpInside)
return button
}()
private lazy var collectionViewLayout: UICollectionViewFlowLayout = { private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout() let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal layout.scrollDirection = .horizontal
@ -60,6 +72,13 @@ class VPHomeRecommandContentCell: VPHomeItemContentCell {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
@objc private func handleMoreButton() {
let vc = VPMoreVideoViewController()
vc.titleLabel.text = titleLabel.text
vc.dataArr = self.item?.list ?? []
self.viewController?.navigationController?.pushViewController(vc, animated: true)
}
} }
extension VPHomeRecommandContentCell { extension VPHomeRecommandContentCell {
@ -67,6 +86,7 @@ extension VPHomeRecommandContentCell {
private func vp_setupUI() { private func vp_setupUI() {
containerView.addSubview(titleLabel) containerView.addSubview(titleLabel)
containerView.addSubview(collectionView) containerView.addSubview(collectionView)
containerView.addSubview(moreButton)
if Self.moduleKey == .v3_recommand { if Self.moduleKey == .v3_recommand {
@ -97,6 +117,11 @@ extension VPHomeRecommandContentCell {
make.top.equalToSuperview().offset(32) make.top.equalToSuperview().offset(32)
make.height.equalTo(collectionViewLayout.itemSize.height) make.height.equalTo(collectionViewLayout.itemSize.height)
} }
moreButton.snp.makeConstraints { make in
make.centerY.equalTo(titleLabel)
make.right.equalToSuperview().offset(-13)
}
} }
} }

View File

@ -9,18 +9,28 @@ import UIKit
class VPSearchResultCell: VPCollectionViewCell { class VPSearchResultCell: VPCollectionViewCell {
var searchText: String? { var searchText: String?
didSet {
}
}
var model: VPShortModel? { var model: VPShortModel? {
didSet { didSet {
coverImageView.vp_setImage(url: model?.image_url) coverImageView.vp_setImage(url: model?.image_url)
videoNameLabel.text = model?.name
desLabel.text = model?.vp_description desLabel.text = model?.vp_description
let name = model?.name ?? ""
let ranges = name.vp_range(of: searchText ?? "")
let nameString = NSMutableAttributedString(string: name)
ranges.forEach {
nameString.setColor(.colorBE0069(), range: $0)
}
videoNameLabel.attributedText = nameString
// videoNameLabel.text = model?.name
let watchCount = model?.watch_total ?? 0 let watchCount = model?.watch_total ?? 0
if watchCount > 1000 { if watchCount > 1000 {
let numStr = NSNumber(floatLiteral: CGFloat(watchCount) / 1000).toString(maximumFractionDigits: 1) let numStr = NSNumber(floatLiteral: CGFloat(watchCount) / 1000).toString(maximumFractionDigits: 1)

View File

@ -12,8 +12,13 @@ class VPSearchResultView: UIView {
var viewModel: VPSearchViewModel? var viewModel: VPSearchViewModel?
private lazy var dataArr: [VPShortModel] = [] private lazy var dataArr: [VPShortModel] = []
///
private lazy var currentDataText = ""
private(set) lazy var searchText: String = "" private(set) lazy var searchText: String = ""
//MARK: UI //MARK: UI
private lazy var titleLabel: UILabel = { private lazy var titleLabel: UILabel = {
let label = UILabel() let label = UILabel()
@ -26,7 +31,7 @@ class VPSearchResultView: UIView {
private lazy var collectionViewLayout: UICollectionViewFlowLayout = { private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout() let layout = UICollectionViewFlowLayout()
layout.itemSize = .init(width: UIScreen.width - 30, height: 108) layout.itemSize = .init(width: UIScreen.width - 30, height: 108)
layout.sectionInset = .init(top: 0, left: 15, bottom: UIScreen.tabbarSafeBottomMargin + 10, right: 15) layout.sectionInset = .init(top: 0, left: 15, bottom: 0, right: 15)
layout.minimumLineSpacing = 10 layout.minimumLineSpacing = 10
return layout return layout
}() }()
@ -35,6 +40,7 @@ class VPSearchResultView: UIView {
let collectionView = VPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) let collectionView = VPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self collectionView.delegate = self
collectionView.dataSource = self collectionView.dataSource = self
collectionView.contentInset = .init(top: 0, left: 0, bottom: UIScreen.tabbarSafeBottomMargin + 10, right: 0)
collectionView.register(VPSearchResultCell.self, forCellWithReuseIdentifier: "cell") collectionView.register(VPSearchResultCell.self, forCellWithReuseIdentifier: "cell")
collectionView.vp_addNormalEmpty(image: UIImage(named: "empty_image_02")) collectionView.vp_addNormalEmpty(image: UIImage(named: "empty_image_02"))
collectionView.keyboardDismissMode = .onDrag collectionView.keyboardDismissMode = .onDrag
@ -80,7 +86,7 @@ extension VPSearchResultView {
extension VPSearchResultView: UICollectionViewDataSource, UICollectionViewDelegate { extension VPSearchResultView: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! VPSearchResultCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! VPSearchResultCell
cell.searchText = self.searchText cell.searchText = self.currentDataText
cell.model = dataArr[indexPath.row] cell.model = dataArr[indexPath.row]
return cell return cell
} }
@ -109,6 +115,7 @@ extension VPSearchResultView {
if let list = list { if let list = list {
self.dataArr = list self.dataArr = list
self.currentDataText = text
self.collectionView.reloadData() self.collectionView.reloadData()
} }
} }

View File

@ -26,6 +26,25 @@ class VPHomeViewModel: VPModel {
private(set) lazy var categoryList: [VPCategoryModel] = [] private(set) lazy var categoryList: [VPCategoryModel] = []
private(set) lazy var categoryTitleList: [String] = [] private(set) lazy var categoryTitleList: [String] = []
var rawCategoryList: [VPCategoryModel] = [] {
didSet {
let allCategory = VPCategoryModel()
allCategory.name = "All".localized
allCategory.id = "0"
categoryList.removeAll()
categoryTitleList.removeAll()
categoryList.append(allCategory)
categoryList += rawCategoryList
categoryList.forEach { model in
categoryTitleList.append(model.name ?? "")
}
}
}
/// ///
private(set) lazy var marqueeArr: [VPShortModel] = [] private(set) lazy var marqueeArr: [VPShortModel] = []
@ -39,23 +58,25 @@ class VPHomeViewModel: VPModel {
if key == .banner { if key == .banner {
newModuleList.insert($0, at: 0) newModuleList.insert($0, at: 0)
} else if key == .category_navigation { // }
/* else if key == .category_navigation { //
if needUpdateCategory { if needUpdateCategory {
categoryList.removeAll() categoryList.removeAll()
categoryTitleList.removeAll() categoryTitleList.removeAll()
let allCategory = VPCategoryModel() let allCategory = VPCategoryModel()
allCategory.category_name = "All".localized allCategory.name = "All".localized
allCategory.category_id = "0" allCategory.id = "0"
categoryList.append(allCategory) categoryList.append(allCategory)
categoryList += ($0.categoryList ?? []) categoryList += ($0.categoryList ?? [])
categoryList.forEach { model in categoryList.forEach { model in
categoryTitleList.append(model.category_name ?? "") categoryTitleList.append(model.name ?? "")
} }
} }
} else if key == .marquee { // }*/
else if key == .marquee { //
marqueeArr = $0.list ?? [] marqueeArr = $0.list ?? []
} else { } else {
newModuleList.append($0) newModuleList.append($0)

View File

@ -115,6 +115,8 @@ extension VPMeViewController: UITableViewDelegate, UITableViewDataSource {
cell.userInfo = VPLoginManager.manager.userInfo cell.userInfo = VPLoginManager.manager.userInfo
} else if let cell = cell as? VPMeCoinCell { } else if let cell = cell as? VPMeCoinCell {
cell.userInfo = VPLoginManager.manager.userInfo cell.userInfo = VPLoginManager.manager.userInfo
} else if let cell = cell as? VPMeVipCell {
cell.userInfo = VPLoginManager.manager.userInfo
} }
return cell return cell

View File

@ -9,6 +9,20 @@ import UIKit
class VPMeVipCell: VPTableViewCell { class VPMeVipCell: VPTableViewCell {
var userInfo: VPUserInfo? {
didSet {
if userInfo?.is_vip == true {
let date = Date(timeIntervalSince1970: userInfo?.vip_end_time ?? 0)
subtitleLabel.text = String(format: "kVipTipText2".localized, date.formatString(dateFormat: "yyyy-MM-dd"))
titleLabel.text = "VIP Active".localized
} else {
subtitleLabel.text = "kVipTipText1".localized
titleLabel.text = "Join VIP".localized
}
}
}
private lazy var bgView: UIView = { private lazy var bgView: UIView = {
let view = VPGradientView() let view = VPGradientView()
view.colors = [UIColor.color06DEAD(alpha: 0.32).cgColor, UIColor.colorFFFFFF(alpha: 0.05).cgColor] view.colors = [UIColor.color06DEAD(alpha: 0.32).cgColor, UIColor.colorFFFFFF(alpha: 0.05).cgColor]
@ -36,7 +50,6 @@ class VPMeVipCell: VPTableViewCell {
let label = UILabel() let label = UILabel()
label.font = .fontBold(ofSize: 15) label.font = .fontBold(ofSize: 15)
label.textColor = .colorFFFFFF() label.textColor = .colorFFFFFF()
label.text = "Join VIP".localized
return label return label
}() }()
@ -44,7 +57,6 @@ class VPMeVipCell: VPTableViewCell {
let label = UILabel() let label = UILabel()
label.font = .fontRegular(ofSize: 12) label.font = .fontRegular(ofSize: 12)
label.textColor = .colorFFFFFF() label.textColor = .colorFFFFFF()
label.text = "kVipTipText1".localized
return label return label
}() }()

View File

@ -59,9 +59,12 @@ class VPCollectListViewController: VPViewController {
/// ///
var didChangeAllSelected: (() -> Void)? var didChangeAllSelected: (() -> Void)?
///
var cancelEditBlock: (() -> Void)?
private lazy var deleteGroup = DispatchGroup() private lazy var deleteGroup = DispatchGroup()
private lazy var dataArr: [VPShortModel] = [] private(set) lazy var dataArr: [VPShortModel] = []
private var page: Int = 1 private var page: Int = 1
///1 ///1
@ -287,6 +290,7 @@ extension VPCollectListViewController {
self.deleteGroup.notify(queue: .main) { [weak self] in self.deleteGroup.notify(queue: .main) { [weak self] in
VPHUD.dismiss() VPHUD.dismiss()
guard let self = self else { return } guard let self = self else { return }
self.cancelEditBlock?()
self.requestDataArr(page: 1, completer: nil) self.requestDataArr(page: 1, completer: nil)
} }
} }

View File

@ -17,6 +17,11 @@ class VPMyListViewController: VPViewController {
///0 1 ///0 1
private var editState: EditState = .normal { private var editState: EditState = .normal {
didSet { didSet {
if collectVC.dataArr.count <= 0, editState != .normal {
editState = .normal
return
}
if editState == .normal { if editState == .normal {
pageView.upSc.mainView.isHidden = false pageView.upSc.mainView.isHidden = false
pageView.upSc.dataView.isScrollEnabled = true pageView.upSc.dataView.isScrollEnabled = true
@ -30,7 +35,13 @@ class VPMyListViewController: VPViewController {
} }
} }
private lazy var collectVC = VPCollectListViewController() private lazy var collectVC: VPCollectListViewController = {
let vc = VPCollectListViewController()
vc.cancelEditBlock = { [weak self] in
self?.editState = .normal
}
return vc
}()
private lazy var viewControllers: [UIViewController] = { private lazy var viewControllers: [UIViewController] = {
let vc2 = VPWatchHistoryViewController() let vc2 = VPWatchHistoryViewController()

View File

@ -65,8 +65,8 @@ class VPVideoPlayerViewController: VPViewController {
return layout return layout
}() }()
private(set) lazy var collectionView: VPCollectionView = { private(set) lazy var collectionView: VPMutualCollectionView = {
let collectionView = VPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) let collectionView = VPMutualCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self collectionView.delegate = self
collectionView.dataSource = self collectionView.dataSource = self
collectionView.isPagingEnabled = true collectionView.isPagingEnabled = true
@ -74,7 +74,6 @@ class VPVideoPlayerViewController: VPViewController {
collectionView.showsHorizontalScrollIndicator = false collectionView.showsHorizontalScrollIndicator = false
collectionView.bounces = false collectionView.bounces = false
collectionView.scrollsToTop = false collectionView.scrollsToTop = false
// PlayerCellClass.registerCell(collectionView: collectionView)
collectionView.register(PlayerCellClass.self, forCellWithReuseIdentifier: "cell") collectionView.register(PlayerCellClass.self, forCellWithReuseIdentifier: "cell")
return collectionView return collectionView
}() }()

View File

@ -0,0 +1,188 @@
//
// VPMutualCollectionView.swift
// Veloria
//
// Created by on 2025/6/9.
//
import UIKit
@objc protocol VPMutualCollectionViewDelegate: NSObjectProtocol {
@objc optional func vp_loadNewData(collectionView: VPMutualCollectionView)
}
class VPMutualCollectionView: VPCollectionView {
enum RefrshStatus {
///
case normal
///
case pulling
///
case refreshing
}
///
var refreshStatus = RefrshStatus.normal
weak var vp_refreshDelegate: VPMutualCollectionViewDelegate?
///
lazy var refreshPanGesture: UIPanGestureRecognizer = {
let pan = UIPanGestureRecognizer(target: self, action: #selector(handleRefreshPanGesture(sender:)))
pan.delegate = self
return pan
}()
///
lazy var refreshView: UIActivityIndicatorView = {
let view = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
view.isHidden = true
// view.tintColor = .colorFFFFFF()
view.color = .colorFFFFFF()
return view
}()
///
var vp_onRefrsh = false
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: layout)
self.addGestureRecognizer(refreshPanGesture)
addSubview(refreshView)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
refreshView.centerX = self.width / 2
}
@objc func handleRefreshPanGesture(sender: UIPanGestureRecognizer) {
if !vp_onRefrsh {return}
if refreshStatus == .refreshing {return}
switch sender.state {
case .began:
refreshStatus = .normal
refreshView.isHidden = false
refreshView.top = -20
bringSubviewToFront(refreshView)
sender.setTranslation(.zero, in: self)
case .changed:
let point = sender.translation(in: self)
var top = refreshView.top + point.y
if top > UIScreen.tabbarSafeBottomMargin + 70 {
top = UIScreen.tabbarSafeBottomMargin + 70
}
if top >= UIScreen.tabbarSafeBottomMargin + 60 {
refreshStatus = .pulling
} else {
refreshStatus = .normal
}
refreshView.top = top
sender.setTranslation(.zero, in: self)
case .cancelled, .ended, .failed:
if refreshStatus == .pulling {
beginRefresh()
} else {
endRefresh()
}
default:
break
}
}
func beginRefresh() {
self.refreshStatus = .refreshing
self.refreshView.startAnimating()
UIView.animate(withDuration: 0.5) { [weak self] in
self?.refreshView.top = UIScreen.tabbarSafeBottomMargin + 60
} completion: { [weak self] (finish) in
guard let self = self else {return}
self.vp_refreshDelegate?.vp_loadNewData?(collectionView: self)
}
}
func endRefresh() {
self.refreshStatus = .normal
self.refreshView.stopAnimating()
UIView.animate(withDuration: 0.5) { [weak self] in
self?.refreshView.top = -20
} completion: { [weak self] (finish) in
if self?.refreshStatus == .none {
self?.refreshView.isHidden = true
}
}
}
}
extension VPMutualCollectionView {
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
// return panBack(gestureRecognizer: gestureRecognizer)
if gestureRecognizer == self.refreshPanGesture {
if !vp_onRefrsh { return false }
// if self.isScrollEnabled == false { return false }
let point = self.refreshPanGesture.translation(in: self)
let state = gestureRecognizer.state
if state == .began || state == .possible {
///
if point.y > 0 && self.contentOffset.y == 0 {
return true
}
}
return false
} else {
return super.gestureRecognizerShouldBegin(gestureRecognizer)
}
}
func panBack(gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer == self.refreshPanGesture {
if !vp_onRefrsh { return false }
// if self.isScrollEnabled == false { return false }
let point = self.refreshPanGesture.translation(in: self)
let state = gestureRecognizer.state
if state == .began || state == .possible {
///
if point.y > 0 && self.contentOffset.y == 0 {
return true
}
}
return false
} else if (gestureRecognizer == self.panGestureRecognizer) {
let point = self.panGestureRecognizer.translation(in: self)
let state = gestureRecognizer.state
if state == .began || state == .possible {
///
if point.y > 0 && self.contentOffset.y == 0 {
return false
}
}
return true
} else {
return true
}
}
}

View File

@ -63,12 +63,15 @@ class VPLoginManager: NSObject {
///退 ///退
func logout(completer: ((_ isFinish: Bool) -> Void)?) { func logout(completer: ((_ isFinish: Bool) -> Void)?) {
VPStatAPI.requestLeaveApp()
VPUserAPI.requestLogout { [weak self] token in VPUserAPI.requestLogout { [weak self] token in
guard let self = self else { return } guard let self = self else { return }
if let token = token { if let token = token {
self.setLoginToken(token: token) self.setLoginToken(token: token)
self.userInfo?.is_tourist = true self.userInfo?.is_tourist = true
self.updateUserInfo(completer: nil) self.updateUserInfo(completer: nil)
VPStatAPI.requestStatOnLine()
VPStatAPI.requestEnterApp()
completer?(true) completer?(true)
NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil) NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil)
NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil) NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil)
@ -80,12 +83,15 @@ class VPLoginManager: NSObject {
/// ///
func deleteAccount(completer: ((_ isFinish: Bool) -> Void)?) { func deleteAccount(completer: ((_ isFinish: Bool) -> Void)?) {
VPStatAPI.requestLeaveApp()
VPUserAPI.requestDelete { [weak self] isFinish in VPUserAPI.requestDelete { [weak self] isFinish in
guard let self = self else { return } guard let self = self else { return }
if isFinish { if isFinish {
self.setLoginToken(token: nil) self.setLoginToken(token: nil)
self.userInfo?.is_tourist = true self.userInfo?.is_tourist = true
self.updateUserInfo(completer: nil) self.updateUserInfo(completer: nil)
VPStatAPI.requestStatOnLine()
VPStatAPI.requestEnterApp()
completer?(true) completer?(true)
NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil) NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil)
NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil) NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil)
@ -120,7 +126,7 @@ extension VPLoginManager {
completer?(false) completer?(false)
return return
} }
VPStatAPI.requestLeaveApp()
VPUserAPI.requestThirdLogin(model: thirdSignModel) { [weak self] token in VPUserAPI.requestThirdLogin(model: thirdSignModel) { [weak self] token in
guard let self = self else { return } guard let self = self else { return }
guard let token = token else { guard let token = token else {
@ -130,6 +136,8 @@ extension VPLoginManager {
self.setLoginToken(token: token) self.setLoginToken(token: token)
self.userInfo?.is_tourist = false self.userInfo?.is_tourist = false
self.updateUserInfo(completer: nil) self.updateUserInfo(completer: nil)
VPStatAPI.requestStatOnLine()
VPStatAPI.requestEnterApp()
completer?(true) completer?(true)
NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil) NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil)
NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil) NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil)

View File

@ -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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

View File

@ -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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -37,6 +37,7 @@
"Feedback Details" = "Feedback Details"; "Feedback Details" = "Feedback Details";
"Rewards" = "Rewards"; "Rewards" = "Rewards";
"Join VIP" = "Join VIP"; "Join VIP" = "Join VIP";
"VIP Active" = "VIP Active";
"Conins" = "Conins"; "Conins" = "Conins";
"Donate" = "Donate"; "Donate" = "Donate";
"Wallet" = "Wallet"; "Wallet" = "Wallet";
@ -87,13 +88,16 @@
"Success" = "Success"; "Success" = "Success";
"Restore" = "Restore"; "Restore" = "Restore";
"Watch Now" = "Watch Now"; "Watch Now" = "Watch Now";
"More" = "More";
"kDetailRecommandTitle" = "Picked Just for You"; "kDetailRecommandTitle" = "Picked Just for You";
"kHomeTitleText" = "10,000+ addictive shorts await!"; "kHomeTitleText" = "10,000+ addictive shorts await!";
"kSearchPlaceholderText1" = "Search dramas"; "kSearchPlaceholderText1" = "Search dramas";
"kSearchPlaceholderText2" = "#Recersal of fate"; "kSearchPlaceholderText2" = "#Recersal of fate";
"kHomeMenuTitle" = "Select Categories"; "kHomeMenuTitle" = "Select Categories";
"kVipTipText1" = "unlock 1000+ exclusive dramas"; "kVipTipText1" = "unlock exclusive dramas";
"kVipTipText2" = "vip expires: %@";
"kVipPrivilegeText1" = "Ad-Free\nStreaming"; "kVipPrivilegeText1" = "Ad-Free\nStreaming";
"kVipPrivilegeText2" = "Exclusive\nEpisodes"; "kVipPrivilegeText2" = "Exclusive\nEpisodes";
"kVipPrivilegeText3" = "Daily free\ncoins"; "kVipPrivilegeText3" = "Daily free\ncoins";
@ -104,6 +108,7 @@
"kVideoLockTipText" = "Please unlock the previous episode"; "kVideoLockTipText" = "Please unlock the previous episode";
//无网提示 //无网提示
"kNetworkToast01" = "The service is abnormal. Check the network."; "kNetworkToast01" = "The service is abnormal. Check the network.";
"kNetworkToast02" = "Your account is already logged in on another device~";
//解锁上一集提示 //解锁上一集提示
"kLockPreviousEpisodeText" = "The prequel to this series is not unlocked. Please unlock the prequel before unlocking this series"; "kLockPreviousEpisodeText" = "The prequel to this series is not unlocked. Please unlock the prequel before unlocking this series";
//解锁失败 //解锁失败

View File

@ -8,7 +8,8 @@
</array> </array>
<key>com.apple.developer.associated-domains</key> <key>com.apple.developer.associated-domains</key>
<array> <array>
<string>webcredentials:example.com</string> <string>applinks:qjwl168.com</string>
<string>applinks:veloriaapp.go.link</string>
</array> </array>
<key>keychain-access-groups</key> <key>keychain-access-groups</key>
<array/> <array/>