首页更多页面,W2A统计功能,Bug处理
This commit is contained in:
parent
eaa1d76bbe
commit
a30c319c05
@ -217,6 +217,8 @@
|
||||
BFF5B26E2DF297680044227A /* VPOpenAppModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B26D2DF297680044227A /* VPOpenAppModel.swift */; };
|
||||
BFF5B2752DF2C3750044227A /* VPDetailRecommandView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2742DF2C3750044227A /* VPDetailRecommandView.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 */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -439,6 +441,8 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -676,6 +680,7 @@
|
||||
1B056E562DDACC6B007EE38D /* VPHomePageViewController.swift */,
|
||||
BF0FA7382DDECF8900C9E5F2 /* VPHomeListViewController.swift */,
|
||||
BF0FA7742DE071B500C9E5F2 /* VPSearchViewController.swift */,
|
||||
BFF5B2782DF679720044227A /* VPMoreVideoViewController.swift */,
|
||||
);
|
||||
path = Controller;
|
||||
sourceTree = "<group>";
|
||||
@ -909,6 +914,7 @@
|
||||
BFF5AFE12DEED2960044227A /* VPPlayerCoinBuyView.swift */,
|
||||
BFF5B2742DF2C3750044227A /* VPDetailRecommandView.swift */,
|
||||
BFF5B2762DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift */,
|
||||
BFF5B4AE2DF6B6630044227A /* VPMutualCollectionView.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
@ -1433,6 +1439,7 @@
|
||||
BFF5AFD42DE9A5FB0044227A /* VPVIPRecordCell.swift in Sources */,
|
||||
BFF5AFD62DE9A8D70044227A /* VPWalletHeaderView.swift in Sources */,
|
||||
BF0FA6EE2DDC5F8700C9E5F2 /* JXUUID.m in Sources */,
|
||||
BFF5B2792DF679720044227A /* VPMoreVideoViewController.swift in Sources */,
|
||||
BF5E75B12DE4656600DE9DFE /* VPCampaignWebViewController.swift in Sources */,
|
||||
BF5E75BC2DE546AD00DE9DFE /* VPAboutUsCell.swift in Sources */,
|
||||
BFF5AFD02DE9A0370044227A /* VPCoinRecordCell.swift in Sources */,
|
||||
@ -1522,6 +1529,7 @@
|
||||
BF0FA7162DDC78FF00C9E5F2 /* ZKCycleScrollViewFlowLayout.swift in Sources */,
|
||||
BFF5B2612DF16B430044227A /* JXIAPManager.swift in Sources */,
|
||||
BF0FA7172DDC78FF00C9E5F2 /* ZKCycleScrollView.swift in Sources */,
|
||||
BFF5B4AF2DF6B6630044227A /* VPMutualCollectionView.swift in Sources */,
|
||||
BF0FA7612DDFFE7100C9E5F2 /* VPVideoDetailModel.swift in Sources */,
|
||||
BFF5AFD22DE9A58A0044227A /* VPVIPRecordViewController.swift in Sources */,
|
||||
BFF5AFDA2DEE90350044227A /* VPVideoLockView.swift in Sources */,
|
||||
|
@ -16,7 +16,7 @@ extension SceneDelegate {
|
||||
}
|
||||
|
||||
//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 {
|
||||
vp_handleOpenAppMessage(webpageURL: url)
|
||||
@ -33,13 +33,17 @@ extension SceneDelegate {
|
||||
extension SceneDelegate {
|
||||
|
||||
static var hasOpenMessage = false
|
||||
///是否需要重试
|
||||
static var isNeedRetry = false
|
||||
|
||||
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() + 1) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
self._handleOpenAppMessage(webpageURL: webpageURL)
|
||||
}
|
||||
|
||||
@ -50,7 +54,7 @@ extension SceneDelegate {
|
||||
|
||||
Self.hasOpenMessage = true
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||||
Self.hasOpenMessage = false
|
||||
}
|
||||
|
||||
@ -58,7 +62,8 @@ extension SceneDelegate {
|
||||
var statUrlStr: String? = webpageURL?.absoluteString
|
||||
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
|
||||
let tempArr = pasteStr.components(separatedBy: "?")
|
||||
let query = tempArr.last
|
||||
@ -70,6 +75,10 @@ extension SceneDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if let urlStr = statUrlStr {//上报结果
|
||||
VPStatAPI.requestStatW2a(data: urlStr)
|
||||
}
|
||||
@ -86,4 +95,10 @@ extension SceneDelegate {
|
||||
|
||||
}
|
||||
|
||||
///重试
|
||||
func vp_retryHandleOpenAppMessage() {
|
||||
guard Self.isNeedRetry else { return }
|
||||
vp_handleOpenAppMessage(webpageURL: nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,25 +30,55 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
VPStatAPI.requestEnterApp()
|
||||
vp_handleOpenAppMessage(webpageURL: nil)
|
||||
// vpLog(message: "++++++++++++++sceneDidBecomeActive")
|
||||
enterForeground()
|
||||
}
|
||||
|
||||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
VPStatAPI.requestLeaveApp()
|
||||
// vpLog(message: "++++++++++++++sceneWillResignActive")
|
||||
enterBackground()
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
|
||||
// vpLog(message: "++++++++++++++sceneWillEnterForeground")
|
||||
// enterForeground()
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
self.vp_handleOpenAppMessage(webpageURL: nil)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -59,8 +89,11 @@ extension SceneDelegate {
|
||||
|
||||
|
||||
@objc private func reachabilityDidChangeNotification() {
|
||||
vp_handleOpenAppMessage(webpageURL: nil)
|
||||
vp_retryHandleOpenAppMessage()
|
||||
|
||||
if VPNetworkReachabilityManager.manager.isReachable == true {
|
||||
handleOnLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,4 +15,10 @@ extension Date {
|
||||
return dateComponents.day ?? 0
|
||||
}
|
||||
|
||||
func formatString(dateFormat: String) -> String {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = dateFormat
|
||||
return formatter.string(from: self)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 []
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -80,8 +80,15 @@ class VPNetwork: NSObject {
|
||||
}
|
||||
completion?(res)
|
||||
} else {
|
||||
if code == 402, parameters.isToast {
|
||||
VPToast.show(text: "kNetworkToast02".localized)
|
||||
}
|
||||
///重新获取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" {
|
||||
@ -137,7 +144,7 @@ class VPNetwork: NSObject {
|
||||
var res = VPNetworkResponse<T>()
|
||||
res.code = -1
|
||||
if parameters.isToast {
|
||||
VPToast.show(text: "network_toast_01".localized)
|
||||
VPToast.show(text: "kNetworkToast01".localized)
|
||||
}
|
||||
completion?(res)
|
||||
break
|
||||
|
@ -34,7 +34,11 @@ extension VPWebViewController {
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
case VPWebMessageOpenFeedbackDetail:
|
||||
guard let body = body as? [String : Any] else { return }
|
||||
guard let id = body["id"] as? Int else { return }
|
||||
|
||||
let vc = VPCampaignWebViewController()
|
||||
vc.id = "\(id)"
|
||||
vc.bgImageView.isHidden = true
|
||||
vc.urlStr = kVPFeedBackDetailWebUrl
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
|
@ -22,7 +22,8 @@ class VPExploreViewController: VPVideoPlayerViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
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.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 {
|
||||
|
||||
private func requestDataArr(page: Int) {
|
||||
private func requestDataArr(page: Int, completer: (() -> Void)? = nil) {
|
||||
|
||||
VPVideoAPI.requestRecommandsVideo(page: page) { [weak self] listModel in
|
||||
guard let self = self else { return }
|
||||
if let listModel = listModel, let list = listModel.list {
|
||||
if page == 1 {
|
||||
self.setDataArr(dataArr: list) { [weak self] in
|
||||
self?.play()
|
||||
self?.scrollToItem(indexPath: IndexPath(row: 0, section: 0), animated: false)
|
||||
// self?.play()
|
||||
}
|
||||
} else {
|
||||
self.addDataArr(dataArr: list)
|
||||
}
|
||||
self.pagination = listModel.pagination
|
||||
}
|
||||
completer?()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class VPHomePageViewController: VPViewController {
|
||||
param.wViewController = { [weak self] index in
|
||||
let categoryModel = self?.viewModel.categoryList[index]
|
||||
let vc = VPHomeListViewController()
|
||||
vc.categoryId = categoryModel?.category_id
|
||||
vc.categoryId = categoryModel?.id
|
||||
return vc
|
||||
}
|
||||
|
||||
@ -128,6 +128,7 @@ class VPHomePageViewController: VPViewController {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: VPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
|
||||
|
||||
requestHomeData()
|
||||
requestCategories()
|
||||
setupPageView()
|
||||
vp_setupUI()
|
||||
|
||||
@ -147,6 +148,7 @@ class VPHomePageViewController: VPViewController {
|
||||
self.pageView.downSc?.vp_endHeaderRefreshing()
|
||||
}
|
||||
self.requestHomeData()
|
||||
self.requestCategories()
|
||||
|
||||
}
|
||||
|
||||
@ -187,6 +189,7 @@ extension VPHomePageViewController {
|
||||
if self.viewModel.oldModuleList == nil {
|
||||
requestHomeData()
|
||||
}
|
||||
requestCategories()
|
||||
}
|
||||
|
||||
}
|
||||
@ -247,18 +250,25 @@ extension VPHomePageViewController {
|
||||
guard let self = self else { return }
|
||||
if let list = 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.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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
118
Veloria/Class/Home/Controller/VPMoreVideoViewController.swift
Normal file
118
Veloria/Class/Home/Controller/VPMoreVideoViewController.swift
Normal 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)
|
||||
}
|
||||
}
|
@ -10,6 +10,6 @@ import SmartCodable
|
||||
|
||||
class VPCategoryModel: VPModel, SmartCodable {
|
||||
|
||||
var category_name: String?
|
||||
var category_id: String?
|
||||
var name: String?
|
||||
var id: String?
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class VPHomeModuleItem: VPModel, SmartCodable {
|
||||
///分类推荐
|
||||
case cagetory_recommand = "home_cagetory_recommand"
|
||||
case week_ranking = "week_ranking"
|
||||
case category_navigation = "category_navigation"
|
||||
// case category_navigation = "category_navigation"
|
||||
///跑马灯
|
||||
case marquee = "marquee"
|
||||
}
|
||||
@ -33,11 +33,11 @@ class VPHomeModuleItem: VPModel, SmartCodable {
|
||||
|
||||
func didFinishMapping() {
|
||||
if let data = data as? [[String : Any]] {
|
||||
if module_key == .category_navigation {
|
||||
self.categoryList = [VPCategoryModel].deserialize(from: data)
|
||||
} else {
|
||||
self.list = [VPShortModel].deserialize(from: data)
|
||||
}
|
||||
// if module_key == .category_navigation {
|
||||
// self.categoryList = [VPCategoryModel].deserialize(from: data)
|
||||
// } else {
|
||||
// }
|
||||
self.list = [VPShortModel].deserialize(from: data)
|
||||
} else if let data = data as? [String : Any] {
|
||||
var dataList: [[String : Any]]?
|
||||
if let list = data["list"] as? [[String : Any]] {
|
||||
|
@ -38,6 +38,18 @@ class VPHomeRankingContentCell: VPHomeItemContentCell {
|
||||
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 = {
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
layout.scrollDirection = .horizontal
|
||||
@ -67,6 +79,13 @@ class VPHomeRankingContentCell: VPHomeItemContentCell {
|
||||
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 {
|
||||
@ -75,6 +94,7 @@ extension VPHomeRankingContentCell {
|
||||
containerView.addSubview(iconImageView)
|
||||
containerView.addSubview(titleLabel)
|
||||
containerView.addSubview(collectionView)
|
||||
containerView.addSubview(moreButton)
|
||||
|
||||
iconImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(15)
|
||||
@ -92,6 +112,10 @@ extension VPHomeRankingContentCell {
|
||||
make.height.equalTo(collectionViewLayout.itemSize.height * 3 + collectionViewLayout.minimumInteritemSpacing * 2)
|
||||
}
|
||||
|
||||
moreButton.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(titleLabel)
|
||||
make.right.equalToSuperview().offset(-13)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,6 +32,18 @@ class VPHomeRecommandContentCell: VPHomeItemContentCell {
|
||||
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 = {
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
layout.scrollDirection = .horizontal
|
||||
@ -60,6 +72,13 @@ class VPHomeRecommandContentCell: VPHomeItemContentCell {
|
||||
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 {
|
||||
@ -67,6 +86,7 @@ extension VPHomeRecommandContentCell {
|
||||
private func vp_setupUI() {
|
||||
containerView.addSubview(titleLabel)
|
||||
containerView.addSubview(collectionView)
|
||||
containerView.addSubview(moreButton)
|
||||
|
||||
if Self.moduleKey == .v3_recommand {
|
||||
|
||||
@ -97,6 +117,11 @@ extension VPHomeRecommandContentCell {
|
||||
make.top.equalToSuperview().offset(32)
|
||||
make.height.equalTo(collectionViewLayout.itemSize.height)
|
||||
}
|
||||
|
||||
moreButton.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(titleLabel)
|
||||
make.right.equalToSuperview().offset(-13)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,18 +9,28 @@ import UIKit
|
||||
|
||||
class VPSearchResultCell: VPCollectionViewCell {
|
||||
|
||||
var searchText: String? {
|
||||
didSet {
|
||||
|
||||
}
|
||||
}
|
||||
var searchText: String?
|
||||
|
||||
var model: VPShortModel? {
|
||||
didSet {
|
||||
coverImageView.vp_setImage(url: model?.image_url)
|
||||
videoNameLabel.text = model?.name
|
||||
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
|
||||
if watchCount > 1000 {
|
||||
let numStr = NSNumber(floatLiteral: CGFloat(watchCount) / 1000).toString(maximumFractionDigits: 1)
|
||||
|
@ -12,8 +12,13 @@ class VPSearchResultView: UIView {
|
||||
var viewModel: VPSearchViewModel?
|
||||
|
||||
private lazy var dataArr: [VPShortModel] = []
|
||||
///当前数据对应的词
|
||||
private lazy var currentDataText = ""
|
||||
|
||||
private(set) lazy var searchText: String = ""
|
||||
|
||||
|
||||
|
||||
//MARK: UI属性
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
@ -26,7 +31,7 @@ class VPSearchResultView: UIView {
|
||||
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: UIScreen.tabbarSafeBottomMargin + 10, right: 15)
|
||||
layout.sectionInset = .init(top: 0, left: 15, bottom: 0, right: 15)
|
||||
layout.minimumLineSpacing = 10
|
||||
return layout
|
||||
}()
|
||||
@ -35,6 +40,7 @@ class VPSearchResultView: UIView {
|
||||
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")
|
||||
collectionView.vp_addNormalEmpty(image: UIImage(named: "empty_image_02"))
|
||||
collectionView.keyboardDismissMode = .onDrag
|
||||
@ -80,7 +86,7 @@ extension VPSearchResultView {
|
||||
extension VPSearchResultView: UICollectionViewDataSource, UICollectionViewDelegate {
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! VPSearchResultCell
|
||||
cell.searchText = self.searchText
|
||||
cell.searchText = self.currentDataText
|
||||
cell.model = dataArr[indexPath.row]
|
||||
return cell
|
||||
}
|
||||
@ -109,6 +115,7 @@ extension VPSearchResultView {
|
||||
|
||||
if let list = list {
|
||||
self.dataArr = list
|
||||
self.currentDataText = text
|
||||
self.collectionView.reloadData()
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,25 @@ class VPHomeViewModel: VPModel {
|
||||
private(set) lazy var categoryList: [VPCategoryModel] = []
|
||||
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] = []
|
||||
|
||||
@ -39,23 +58,25 @@ class VPHomeViewModel: VPModel {
|
||||
if key == .banner {
|
||||
newModuleList.insert($0, at: 0)
|
||||
|
||||
} else if key == .category_navigation { //分类数据
|
||||
}
|
||||
/* else if key == .category_navigation { //分类数据
|
||||
if needUpdateCategory {
|
||||
categoryList.removeAll()
|
||||
categoryTitleList.removeAll()
|
||||
|
||||
let allCategory = VPCategoryModel()
|
||||
allCategory.category_name = "All".localized
|
||||
allCategory.category_id = "0"
|
||||
allCategory.name = "All".localized
|
||||
allCategory.id = "0"
|
||||
categoryList.append(allCategory)
|
||||
categoryList += ($0.categoryList ?? [])
|
||||
|
||||
categoryList.forEach { model in
|
||||
categoryTitleList.append(model.category_name ?? "")
|
||||
categoryTitleList.append(model.name ?? "")
|
||||
}
|
||||
}
|
||||
|
||||
} else if key == .marquee { //跑马灯数据
|
||||
}*/
|
||||
else if key == .marquee { //跑马灯数据
|
||||
marqueeArr = $0.list ?? []
|
||||
} else {
|
||||
newModuleList.append($0)
|
||||
|
@ -115,6 +115,8 @@ extension VPMeViewController: UITableViewDelegate, UITableViewDataSource {
|
||||
cell.userInfo = VPLoginManager.manager.userInfo
|
||||
} else if let cell = cell as? VPMeCoinCell {
|
||||
cell.userInfo = VPLoginManager.manager.userInfo
|
||||
} else if let cell = cell as? VPMeVipCell {
|
||||
cell.userInfo = VPLoginManager.manager.userInfo
|
||||
}
|
||||
|
||||
return cell
|
||||
|
@ -9,6 +9,20 @@ import UIKit
|
||||
|
||||
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 = {
|
||||
let view = VPGradientView()
|
||||
view.colors = [UIColor.color06DEAD(alpha: 0.32).cgColor, UIColor.colorFFFFFF(alpha: 0.05).cgColor]
|
||||
@ -36,7 +50,6 @@ class VPMeVipCell: VPTableViewCell {
|
||||
let label = UILabel()
|
||||
label.font = .fontBold(ofSize: 15)
|
||||
label.textColor = .colorFFFFFF()
|
||||
label.text = "Join VIP".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
@ -44,7 +57,6 @@ class VPMeVipCell: VPTableViewCell {
|
||||
let label = UILabel()
|
||||
label.font = .fontRegular(ofSize: 12)
|
||||
label.textColor = .colorFFFFFF()
|
||||
label.text = "kVipTipText1".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
|
@ -59,9 +59,12 @@ class VPCollectListViewController: VPViewController {
|
||||
///全选状态发生变化
|
||||
var didChangeAllSelected: (() -> Void)?
|
||||
|
||||
///取消编辑
|
||||
var cancelEditBlock: (() -> Void)?
|
||||
|
||||
private lazy var deleteGroup = DispatchGroup()
|
||||
|
||||
private lazy var dataArr: [VPShortModel] = []
|
||||
private(set) lazy var dataArr: [VPShortModel] = []
|
||||
private var page: Int = 1
|
||||
|
||||
///更新节点,当节点大于1时,下次进入页面会更新列表
|
||||
@ -287,6 +290,7 @@ extension VPCollectListViewController {
|
||||
self.deleteGroup.notify(queue: .main) { [weak self] in
|
||||
VPHUD.dismiss()
|
||||
guard let self = self else { return }
|
||||
self.cancelEditBlock?()
|
||||
self.requestDataArr(page: 1, completer: nil)
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,11 @@ class VPMyListViewController: VPViewController {
|
||||
///0普通状态 1编辑状态
|
||||
private var editState: EditState = .normal {
|
||||
didSet {
|
||||
if collectVC.dataArr.count <= 0, editState != .normal {
|
||||
editState = .normal
|
||||
return
|
||||
}
|
||||
|
||||
if editState == .normal {
|
||||
pageView.upSc.mainView.isHidden = false
|
||||
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] = {
|
||||
let vc2 = VPWatchHistoryViewController()
|
||||
|
@ -65,8 +65,8 @@ class VPVideoPlayerViewController: VPViewController {
|
||||
return layout
|
||||
}()
|
||||
|
||||
private(set) lazy var collectionView: VPCollectionView = {
|
||||
let collectionView = VPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
|
||||
private(set) lazy var collectionView: VPMutualCollectionView = {
|
||||
let collectionView = VPMutualCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
|
||||
collectionView.delegate = self
|
||||
collectionView.dataSource = self
|
||||
collectionView.isPagingEnabled = true
|
||||
@ -74,7 +74,6 @@ class VPVideoPlayerViewController: VPViewController {
|
||||
collectionView.showsHorizontalScrollIndicator = false
|
||||
collectionView.bounces = false
|
||||
collectionView.scrollsToTop = false
|
||||
// PlayerCellClass.registerCell(collectionView: collectionView)
|
||||
collectionView.register(PlayerCellClass.self, forCellWithReuseIdentifier: "cell")
|
||||
return collectionView
|
||||
}()
|
||||
|
188
Veloria/Class/Player/View/VPMutualCollectionView.swift
Normal file
188
Veloria/Class/Player/View/VPMutualCollectionView.swift
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -63,12 +63,15 @@ class VPLoginManager: NSObject {
|
||||
|
||||
///退出登录
|
||||
func logout(completer: ((_ isFinish: Bool) -> Void)?) {
|
||||
VPStatAPI.requestLeaveApp()
|
||||
VPUserAPI.requestLogout { [weak self] token in
|
||||
guard let self = self else { return }
|
||||
if let token = token {
|
||||
self.setLoginToken(token: token)
|
||||
self.userInfo?.is_tourist = true
|
||||
self.updateUserInfo(completer: nil)
|
||||
VPStatAPI.requestStatOnLine()
|
||||
VPStatAPI.requestEnterApp()
|
||||
completer?(true)
|
||||
NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil)
|
||||
NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil)
|
||||
@ -80,12 +83,15 @@ class VPLoginManager: NSObject {
|
||||
|
||||
///删除账号
|
||||
func deleteAccount(completer: ((_ isFinish: Bool) -> Void)?) {
|
||||
VPStatAPI.requestLeaveApp()
|
||||
VPUserAPI.requestDelete { [weak self] isFinish in
|
||||
guard let self = self else { return }
|
||||
if isFinish {
|
||||
self.setLoginToken(token: nil)
|
||||
self.userInfo?.is_tourist = true
|
||||
self.updateUserInfo(completer: nil)
|
||||
VPStatAPI.requestStatOnLine()
|
||||
VPStatAPI.requestEnterApp()
|
||||
completer?(true)
|
||||
NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil)
|
||||
NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil)
|
||||
@ -120,7 +126,7 @@ extension VPLoginManager {
|
||||
completer?(false)
|
||||
return
|
||||
}
|
||||
|
||||
VPStatAPI.requestLeaveApp()
|
||||
VPUserAPI.requestThirdLogin(model: thirdSignModel) { [weak self] token in
|
||||
guard let self = self else { return }
|
||||
guard let token = token else {
|
||||
@ -130,6 +136,8 @@ extension VPLoginManager {
|
||||
self.setLoginToken(token: token)
|
||||
self.userInfo?.is_tourist = false
|
||||
self.updateUserInfo(completer: nil)
|
||||
VPStatAPI.requestStatOnLine()
|
||||
VPStatAPI.requestEnterApp()
|
||||
completer?(true)
|
||||
NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil)
|
||||
NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil)
|
||||
|
22
Veloria/Source/Assets.xcassets/icon/arrow_right_icon_03.imageset/Contents.json
vendored
Normal file
22
Veloria/Source/Assets.xcassets/icon/arrow_right_icon_03.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
Veloria/Source/Assets.xcassets/icon/arrow_right_icon_03.imageset/Frame@2x.png
vendored
Normal file
BIN
Veloria/Source/Assets.xcassets/icon/arrow_right_icon_03.imageset/Frame@2x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 248 B |
BIN
Veloria/Source/Assets.xcassets/icon/arrow_right_icon_03.imageset/Frame@3x.png
vendored
Normal file
BIN
Veloria/Source/Assets.xcassets/icon/arrow_right_icon_03.imageset/Frame@3x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 334 B |
22
Veloria/Source/Assets.xcassets/icon/title_icon_01.imageset/Contents.json
vendored
Normal file
22
Veloria/Source/Assets.xcassets/icon/title_icon_01.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
Veloria/Source/Assets.xcassets/icon/title_icon_01.imageset/Frame@2x.png
vendored
Normal file
BIN
Veloria/Source/Assets.xcassets/icon/title_icon_01.imageset/Frame@2x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
Veloria/Source/Assets.xcassets/icon/title_icon_01.imageset/Frame@3x.png
vendored
Normal file
BIN
Veloria/Source/Assets.xcassets/icon/title_icon_01.imageset/Frame@3x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
22
Veloria/Source/Assets.xcassets/icon/title_icon_02.imageset/Contents.json
vendored
Normal file
22
Veloria/Source/Assets.xcassets/icon/title_icon_02.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
Veloria/Source/Assets.xcassets/icon/title_icon_02.imageset/Frame@2x.png
vendored
Normal file
BIN
Veloria/Source/Assets.xcassets/icon/title_icon_02.imageset/Frame@2x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
Veloria/Source/Assets.xcassets/icon/title_icon_02.imageset/Frame@3x.png
vendored
Normal file
BIN
Veloria/Source/Assets.xcassets/icon/title_icon_02.imageset/Frame@3x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
@ -37,6 +37,7 @@
|
||||
"Feedback Details" = "Feedback Details";
|
||||
"Rewards" = "Rewards";
|
||||
"Join VIP" = "Join VIP";
|
||||
"VIP Active" = "VIP Active";
|
||||
"Conins" = "Conins";
|
||||
"Donate" = "Donate";
|
||||
"Wallet" = "Wallet";
|
||||
@ -87,13 +88,16 @@
|
||||
"Success" = "Success";
|
||||
"Restore" = "Restore";
|
||||
"Watch Now" = "Watch Now";
|
||||
"More" = "More";
|
||||
|
||||
|
||||
"kDetailRecommandTitle" = "Picked Just for You";
|
||||
"kHomeTitleText" = "10,000+ addictive shorts await!";
|
||||
"kSearchPlaceholderText1" = "Search dramas";
|
||||
"kSearchPlaceholderText2" = "#Recersal of fate";
|
||||
"kHomeMenuTitle" = "Select Categories";
|
||||
"kVipTipText1" = "unlock 1000+ exclusive dramas";
|
||||
"kVipTipText1" = "unlock exclusive dramas";
|
||||
"kVipTipText2" = "vip expires: %@";
|
||||
"kVipPrivilegeText1" = "Ad-Free\nStreaming";
|
||||
"kVipPrivilegeText2" = "Exclusive\nEpisodes";
|
||||
"kVipPrivilegeText3" = "Daily free\ncoins";
|
||||
@ -104,6 +108,7 @@
|
||||
"kVideoLockTipText" = "Please unlock the previous episode";
|
||||
//无网提示
|
||||
"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";
|
||||
//解锁失败
|
||||
|
@ -8,7 +8,8 @@
|
||||
</array>
|
||||
<key>com.apple.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>webcredentials:example.com</string>
|
||||
<string>applinks:qjwl168.com</string>
|
||||
<string>applinks:veloriaapp.go.link</string>
|
||||
</array>
|
||||
<key>keychain-access-groups</key>
|
||||
<array/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user