adjust,详情推荐
This commit is contained in:
parent
46d142cf37
commit
a947b20be4
3
Podfile
3
Podfile
@ -30,6 +30,7 @@ target 'Veloria' do
|
||||
pod 'ZFPlayer/AVPlayer' #播放器
|
||||
pod 'EmptyDataSet-Swift' #空数据页面
|
||||
pod 'ZLPhotoBrowser' #相册
|
||||
|
||||
pod 'Adjust' # Adjust
|
||||
pod 'FSPagerView' #banner
|
||||
|
||||
end
|
||||
|
16
Podfile.lock
16
Podfile.lock
@ -1,7 +1,13 @@
|
||||
PODS:
|
||||
- Adjust (5.4.0):
|
||||
- Adjust/Adjust (= 5.4.0)
|
||||
- Adjust/Adjust (5.4.0):
|
||||
- AdjustSignature (= 3.35.2)
|
||||
- AdjustSignature (3.35.2)
|
||||
- Alamofire (5.10.2)
|
||||
- CocoaAsyncSocket (7.6.5)
|
||||
- EmptyDataSet-Swift (5.0.0)
|
||||
- FSPagerView (0.8.3)
|
||||
- HWPanModal (0.9.9)
|
||||
- Kingfisher (8.3.2)
|
||||
- KTVHTTPCache (3.0.2):
|
||||
@ -31,7 +37,9 @@ PODS:
|
||||
- ZLPhotoBrowser/Core (4.6.0.1)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Adjust
|
||||
- EmptyDataSet-Swift
|
||||
- FSPagerView
|
||||
- HWPanModal
|
||||
- Kingfisher
|
||||
- KTVHTTPCache
|
||||
@ -48,9 +56,12 @@ DEPENDENCIES:
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- Adjust
|
||||
- AdjustSignature
|
||||
- Alamofire
|
||||
- CocoaAsyncSocket
|
||||
- EmptyDataSet-Swift
|
||||
- FSPagerView
|
||||
- HWPanModal
|
||||
- Kingfisher
|
||||
- KTVHTTPCache
|
||||
@ -66,9 +77,12 @@ SPEC REPOS:
|
||||
- ZLPhotoBrowser
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Adjust: a5f881d0cbfe9a6df979b076dc7116fe19ece797
|
||||
AdjustSignature: 23b9e5d4adcadffc303bb6b410fde617dd88504f
|
||||
Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
|
||||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
||||
EmptyDataSet-Swift: eb382c0c87a2d9c678077385a595cec52da38171
|
||||
FSPagerView: 670405b2f18e2a87fa37f20b00de783e562c25a8
|
||||
HWPanModal: b57a6717d3cdcd666bff44f9dd2a5be9f4d6f5d2
|
||||
Kingfisher: 0621d0ac0c78fecb19f6dc5303bde2b52abaf2f5
|
||||
KTVHTTPCache: 5711692cdf9a5ecfe829b1e16577deb3ffe3dc86
|
||||
@ -83,6 +97,6 @@ SPEC CHECKSUMS:
|
||||
ZFPlayer: 5cf39e8d9f0c2394a014b0db4767b5b5a6bffe13
|
||||
ZLPhotoBrowser: 20f32e6429448cc1c008795a1b55472d5772939c
|
||||
|
||||
PODFILE CHECKSUM: 4ec05325e0f82746c022a9c8ea6b1af5d1e5092f
|
||||
PODFILE CHECKSUM: a53439eb21a3498b8f423fddbdb2bfb48f960ebf
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
@ -213,6 +213,10 @@
|
||||
BFF5B2662DF16CF60044227A /* VPWaitRestoreModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2652DF16CF60044227A /* VPWaitRestoreModel.swift */; };
|
||||
BFF5B2682DF16EA30044227A /* VPIAPOrderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2672DF16EA30044227A /* VPIAPOrderModel.swift */; };
|
||||
BFF5B26A2DF170DD0044227A /* VPIAPVerifyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2692DF170DD0044227A /* VPIAPVerifyModel.swift */; };
|
||||
BFF5B26C2DF28FD50044227A /* VPStatAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B26B2DF28FD50044227A /* VPStatAPI.swift */; };
|
||||
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 */; };
|
||||
F939C04AD4003BA127F15C28 /* Pods_Veloria.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F57E87E765BF8D72A43DCA /* Pods_Veloria.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -431,6 +435,10 @@
|
||||
BFF5B2652DF16CF60044227A /* VPWaitRestoreModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPWaitRestoreModel.swift; sourceTree = "<group>"; };
|
||||
BFF5B2672DF16EA30044227A /* VPIAPOrderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPIAPOrderModel.swift; sourceTree = "<group>"; };
|
||||
BFF5B2692DF170DD0044227A /* VPIAPVerifyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPIAPVerifyModel.swift; sourceTree = "<group>"; };
|
||||
BFF5B26B2DF28FD50044227A /* VPStatAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPStatAPI.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>"; };
|
||||
BFF5B2762DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPDetailRecommandBannerCell.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 */
|
||||
|
||||
@ -584,6 +592,7 @@
|
||||
children = (
|
||||
1B056E402DDAC30A007EE38D /* VPModel.swift */,
|
||||
BF0FA70F2DDC6CA200C9E5F2 /* VPListModel.swift */,
|
||||
BFF5B26D2DF297680044227A /* VPOpenAppModel.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
@ -764,6 +773,7 @@
|
||||
BF0FA73C2DDED2D000C9E5F2 /* VPVideoAPI.swift */,
|
||||
BF0FA7C22DE45DE300C9E5F2 /* VPUserAPI.swift */,
|
||||
BFF5B2402DF045BF0044227A /* VPRewardsAPI.swift */,
|
||||
BFF5B26B2DF28FD50044227A /* VPStatAPI.swift */,
|
||||
);
|
||||
path = API;
|
||||
sourceTree = "<group>";
|
||||
@ -897,6 +907,8 @@
|
||||
BFF5AFDD2DEEBF370044227A /* VPPlayerRechargeView.swift */,
|
||||
BFF5AFDF2DEEC5AA0044227A /* VPPlayerVipBuyView.swift */,
|
||||
BFF5AFE12DEED2960044227A /* VPPlayerCoinBuyView.swift */,
|
||||
BFF5B2742DF2C3750044227A /* VPDetailRecommandView.swift */,
|
||||
BFF5B2762DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
@ -1335,6 +1347,7 @@
|
||||
BF5E75B62DE46DB600DE9DFE /* UIScrollView+Empty.swift in Sources */,
|
||||
1B056E572DDACC6B007EE38D /* VPHomePageViewController.swift in Sources */,
|
||||
BF0FA7BC2DE4563300C9E5F2 /* VPMeUserInfoCell.swift in Sources */,
|
||||
BFF5B2772DF2CA4B0044227A /* VPDetailRecommandBannerCell.swift in Sources */,
|
||||
BF0FA7B82DE44FCC00C9E5F2 /* VPWebViewController.swift in Sources */,
|
||||
BF0FA72A2DDC922F00C9E5F2 /* VPHomeRecommandCell.swift in Sources */,
|
||||
BF0FA7322DDEBD6400C9E5F2 /* AppDelegate+Config.swift in Sources */,
|
||||
@ -1382,6 +1395,7 @@
|
||||
BF0FA7592DDF1C2800C9E5F2 /* VPPlayerProgressView.swift in Sources */,
|
||||
BFF5AFE02DEEC5AB0044227A /* VPPlayerVipBuyView.swift in Sources */,
|
||||
BFF5AFCA2DE97B7A0044227A /* VPWalletViewController.swift in Sources */,
|
||||
BFF5B26C2DF28FD50044227A /* VPStatAPI.swift in Sources */,
|
||||
BF0FA71B2DDC7FF200C9E5F2 /* VPImageView.swift in Sources */,
|
||||
BF0FA7522DDF134700C9E5F2 /* VPVideoPlayerControlView.swift in Sources */,
|
||||
BF0FA7852DE1561D00C9E5F2 /* VPSearchRecommendedCell.swift in Sources */,
|
||||
@ -1398,6 +1412,7 @@
|
||||
BF5E75CD2DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift in Sources */,
|
||||
BF5E75CE2DE5692D00DE9DFE /* JXPushAnimatedTransition.swift in Sources */,
|
||||
BF5E75CF2DE5692D00DE9DFE /* UIViewController+JXTransition.swift in Sources */,
|
||||
BFF5B26E2DF297680044227A /* VPOpenAppModel.swift in Sources */,
|
||||
BFF5B23F2DF0443B0044227A /* VPWebScriptModel.swift in Sources */,
|
||||
BFF5B23B2DF018900044227A /* VPAlertView.swift in Sources */,
|
||||
BF5E75D02DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift in Sources */,
|
||||
@ -1493,6 +1508,7 @@
|
||||
BFF5AFCC2DE98C7F0044227A /* VPOrderRecordsViewController.swift in Sources */,
|
||||
1B056E412DDAC30A007EE38D /* VPModel.swift in Sources */,
|
||||
BF0FA70A2DDC69C800C9E5F2 /* VPTableViewCell.swift in Sources */,
|
||||
BFF5B2752DF2C3750044227A /* VPDetailRecommandView.swift in Sources */,
|
||||
BF0FA7A12DE1AA5100C9E5F2 /* VPTableView.swift in Sources */,
|
||||
1B056E442DDAC355007EE38D /* UIDevice+VPAdd.swift in Sources */,
|
||||
BF0FA7632DE006E700C9E5F2 /* VPDetailPlayerCell.swift in Sources */,
|
||||
|
@ -16,14 +16,74 @@ extension SceneDelegate {
|
||||
}
|
||||
|
||||
//facebook
|
||||
ApplicationDelegate.shared.application(UIApplication.shared, open: url, sourceApplication: nil, annotation: [UIApplication.OpenURLOptionsKey.annotation])
|
||||
|
||||
var result = ApplicationDelegate.shared.application(UIApplication.shared, open: url, sourceApplication: nil, annotation: [UIApplication.OpenURLOptionsKey.annotation])
|
||||
|
||||
if !result {
|
||||
vp_handleOpenAppMessage(webpageURL: url)
|
||||
}
|
||||
}
|
||||
|
||||
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
|
||||
guard let webpageURL = userActivity.webpageURL else { return }
|
||||
|
||||
vp_handleOpenAppMessage(webpageURL: webpageURL)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SceneDelegate {
|
||||
|
||||
static var hasOpenMessage = false
|
||||
|
||||
func vp_handleOpenAppMessage(webpageURL: URL?) {
|
||||
guard VPNetworkReachabilityManager.manager.isReachable == true else { return }
|
||||
|
||||
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
self._handleOpenAppMessage(webpageURL: webpageURL)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private func _handleOpenAppMessage(webpageURL: URL?) {
|
||||
if Self.hasOpenMessage { return }
|
||||
|
||||
Self.hasOpenMessage = true
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
||||
Self.hasOpenMessage = false
|
||||
}
|
||||
|
||||
//统计用URL
|
||||
var statUrlStr: String? = webpageURL?.absoluteString
|
||||
var data: [String : Any]? = webpageURL?.query?.vp_urlQuryToDictionary()
|
||||
|
||||
if let pasteStr = UIPasteboard.general.string {
|
||||
UIPasteboard.general.string = nil
|
||||
let tempArr = pasteStr.components(separatedBy: "?")
|
||||
let query = tempArr.last
|
||||
|
||||
let tempData = query?.vp_urlQuryToDictionary()
|
||||
if tempData?["short_play_id"] != nil {
|
||||
data = tempData
|
||||
statUrlStr = pasteStr
|
||||
}
|
||||
}
|
||||
|
||||
if let urlStr = statUrlStr {//上报结果
|
||||
VPStatAPI.requestStatW2a(data: urlStr)
|
||||
}
|
||||
|
||||
|
||||
guard let data = data else { return }
|
||||
guard let model = VPOpenAppModel.deserialize(from: data) else { return }
|
||||
guard let shortPlayId = model.short_play_id, shortPlayId.count > 0 else { return }
|
||||
|
||||
|
||||
let vc = VPDetailPlayerViewController()
|
||||
vc.shortPlayId = shortPlayId
|
||||
VPAppTool.topViewController?.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
import UIKit
|
||||
import FacebookCore
|
||||
import AdjustSdk
|
||||
|
||||
extension AppDelegate {
|
||||
|
||||
@ -14,7 +15,11 @@ extension AppDelegate {
|
||||
//facebook
|
||||
ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
|
||||
///设置刷新控件的语言
|
||||
//设置刷新控件的语言
|
||||
MJRefreshConfig.default.languageCode = VPLocalizedManager.shared.mjLocalizedKey
|
||||
|
||||
//Adjust
|
||||
let config = ADJConfig(appToken: "jmtc740fki68", environment: ADJEnvironmentProduction)
|
||||
Adjust.initSdk(config)
|
||||
}
|
||||
}
|
||||
|
@ -10,46 +10,57 @@ import UIKit
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
|
||||
|
||||
private var timer: Timer?
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
guard let windowScene = (scene as? UIWindowScene) else { return }
|
||||
VPAppTool.windowScene = windowScene
|
||||
timer = Timer.scheduledTimer(timeInterval: 60 * 10, target: YYWeakProxy(target: self), selector: #selector(handleOnLine), userInfo: nil, repeats: true)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: VPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil)
|
||||
|
||||
|
||||
window = UIWindow(windowScene: windowScene)
|
||||
window?.rootViewController = VPTabBarController()
|
||||
window?.makeKeyAndVisible()
|
||||
|
||||
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
// Called as the scene is being released by the system.
|
||||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
// Called when the scene has moved from an inactive state to an active state.
|
||||
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
|
||||
VPStatAPI.requestEnterApp()
|
||||
vp_handleOpenAppMessage(webpageURL: nil)
|
||||
}
|
||||
|
||||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
// Called when the scene will move from an active state to an inactive state.
|
||||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||
VPStatAPI.requestLeaveApp()
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the background to the foreground.
|
||||
// Use this method to undo the changes made on entering the background.
|
||||
|
||||
}
|
||||
|
||||
func sceneDidEnterBackground(_ scene: UIScene) {
|
||||
// Called as the scene transitions from the foreground to the background.
|
||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||
// to restore the scene back to its current state.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension SceneDelegate {
|
||||
@objc private func handleOnLine() {
|
||||
VPStatAPI.requestStatOnLine()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@objc private func reachabilityDidChangeNotification() {
|
||||
vp_handleOpenAppMessage(webpageURL: nil)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,3 +31,23 @@ extension String {
|
||||
return string.size(for: font, size: size, mode: .byWordWrapping)
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
///将url中的参数转换成字典
|
||||
func vp_urlQuryToDictionary() -> [String : Any] {
|
||||
let array = self.components(separatedBy: "&")
|
||||
var tempDic: [String : Any] = [:]
|
||||
|
||||
array.forEach {
|
||||
if let strRange = $0.range(of: "=") {
|
||||
var key: String = String($0.prefix(upTo: strRange.upperBound))
|
||||
key.removeLast()
|
||||
var value: String = String($0.suffix(from: strRange.upperBound))
|
||||
value = value.removingPercentEncoding ?? value
|
||||
tempDic[key] = value
|
||||
}
|
||||
}
|
||||
return tempDic
|
||||
}
|
||||
}
|
||||
|
||||
|
25
Veloria/Base/Model/VPOpenAppModel.swift
Normal file
25
Veloria/Base/Model/VPOpenAppModel.swift
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// VPOpenAppModel.swift
|
||||
// Veloria
|
||||
//
|
||||
// Created by 湖南秦九 on 2025/6/6.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
class VPOpenAppModel: VPModel, SmartCodable {
|
||||
|
||||
enum PathType: String, SmartCaseDefaultable {
|
||||
case videoDetail = "detail"
|
||||
///反馈列表
|
||||
case feedback = "feedback"
|
||||
///活动
|
||||
case promotion = "promotion"
|
||||
}
|
||||
|
||||
var id: String?
|
||||
var message_id: String?
|
||||
var short_play_id: String?
|
||||
var path: PathType?
|
||||
}
|
52
Veloria/Base/Networking/API/VPStatAPI.swift
Normal file
52
Veloria/Base/Networking/API/VPStatAPI.swift
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// VPStatAPI.swift
|
||||
// Veloria
|
||||
//
|
||||
// Created by 湖南秦九 on 2025/6/6.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class VPStatAPI: NSObject {
|
||||
|
||||
///进入APP
|
||||
static func requestEnterApp() {
|
||||
|
||||
var param = VPNetworkParameters(path: "/customer/enterTheApp")
|
||||
param.isToast = false
|
||||
param.isLoding = false
|
||||
|
||||
VPNetwork.request(parameters: param) { (_: VPNetworkResponse<String>) in }
|
||||
}
|
||||
|
||||
///离开APP
|
||||
static func requestLeaveApp() {
|
||||
var param = VPNetworkParameters(path: "/customer/leaveApp")
|
||||
param.isToast = false
|
||||
param.isLoding = false
|
||||
|
||||
VPNetwork.request(parameters: param) { (_: VPNetworkResponse<String>) in }
|
||||
}
|
||||
|
||||
static func requestStatOnLine() {
|
||||
var param = VPNetworkParameters(path: "/customer/onLine")
|
||||
param.isToast = false
|
||||
param.isLoding = false
|
||||
|
||||
VPNetwork.request(parameters: param) { (_: VPNetworkResponse<String>) in }
|
||||
}
|
||||
|
||||
///统计w2a点击
|
||||
static func requestStatW2a(data: String) {
|
||||
var param = VPNetworkParameters(path: "/w2aSelfAttribution")
|
||||
param.isToast = false
|
||||
param.isLoding = false
|
||||
param.parameters = [
|
||||
"data" : data
|
||||
]
|
||||
|
||||
VPNetwork.request(parameters: param) { (response: VPNetworkResponse<String>) in
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -139,6 +139,17 @@ class VPVideoAPI: NSObject {
|
||||
completer?(response.data)
|
||||
}
|
||||
}
|
||||
|
||||
///视频推荐
|
||||
static func requestDetailsRecommand(completer: ((_ list: [VPShortModel]?) -> Void)?) {
|
||||
|
||||
var param = VPNetworkParameters(path: "/getDetailsRecommand")
|
||||
param.method = .get
|
||||
|
||||
VPNetwork.request(parameters: param) { (response: VPNetworkResponse<VPListModel<VPShortModel>>) in
|
||||
completer?(response.data?.list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension VPVideoAPI {
|
||||
|
@ -202,7 +202,7 @@ extension VPMeViewController {
|
||||
]
|
||||
|
||||
var cellArr: [VPMeItem] = []
|
||||
cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_05"), title: "Language".localized, type: .language, cellKey: .normal))
|
||||
// cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_05"), title: "Language".localized, type: .language, cellKey: .normal))
|
||||
cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_01"), title: "Privacy Policy".localized, type: .privacyPolicy, cellKey: .normal))
|
||||
cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_02"), title: "User Agreement".localized, type: .userAgreement, cellKey: .normal))
|
||||
cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_04"), title: "Help Center".localized, type: .feedback, cellKey: .normal))
|
||||
|
@ -22,11 +22,14 @@ class VPDetailPlayerViewController: VPVideoPlayerViewController {
|
||||
|
||||
private var detailModel: VPVideoDetailModel?
|
||||
|
||||
///推荐列表
|
||||
private lazy var recommandList: [VPShortModel] = []
|
||||
|
||||
//MARK: UI属性
|
||||
private lazy var backButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.setImage(UIImage(named: "arrow_left_icon_01"), for: .normal)
|
||||
button.addTarget(self, action: #selector(handleBack), for: .touchUpInside)
|
||||
button.addTarget(self, action: #selector(handleBackButton), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
@ -49,8 +52,10 @@ class VPDetailPlayerViewController: VPVideoPlayerViewController {
|
||||
self.delegate = self
|
||||
self.dataSource = self
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(buyVipFinishNotification), name: VPIAPManager.buyVipFinishNotification, object: nil)
|
||||
self.jx_popDelegate = self
|
||||
|
||||
requestDetailData()
|
||||
requestRecommandDataArr()
|
||||
|
||||
vp_setupUI()
|
||||
vp_addAction()
|
||||
@ -78,6 +83,28 @@ class VPDetailPlayerViewController: VPVideoPlayerViewController {
|
||||
super.play()
|
||||
VPVideoAPI.requestCreatePlayHistory(videoId: videoInfo.short_play_video_id, shortPlayId: videoInfo.short_play_id)
|
||||
}
|
||||
|
||||
@objc func handleBackButton() {
|
||||
guard recommandList.count > 0 else {
|
||||
self.handleBack()
|
||||
return
|
||||
}
|
||||
|
||||
self.pause()
|
||||
|
||||
let view = VPDetailRecommandView()
|
||||
view.dataArr = recommandList
|
||||
view.clickCloseButton = { [weak self] in
|
||||
self?.handleBack()
|
||||
}
|
||||
view.clickLookButton = { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
self.shortPlayId = model.short_play_id
|
||||
self.activityId = nil
|
||||
self.requestDetailData()
|
||||
}
|
||||
view.present(in: nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -221,13 +248,22 @@ extension VPDetailPlayerViewController: VPPlayerListViewControllerDelegate {
|
||||
}
|
||||
|
||||
|
||||
//MARK: -------------- JXViewControllerPopDelegate --------------
|
||||
extension VPDetailPlayerViewController: JXViewControllerPopDelegate {
|
||||
func viewControllerPopShouldScrollBegan() -> Bool {
|
||||
self.handleBackButton()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension VPDetailPlayerViewController {
|
||||
|
||||
private func requestDetailData() {
|
||||
guard let shortPlayId = shortPlayId else { return }
|
||||
|
||||
VPHUD.show(containerView: self.view)
|
||||
VPVideoAPI.requestVideoDetail(shortPlayId: shortPlayId, activityId: activityId) { [weak self] model in
|
||||
VPHUD.dismiss()
|
||||
guard let self = self else { return }
|
||||
guard let model = model else { return }
|
||||
self.detailModel = model
|
||||
@ -255,4 +291,14 @@ extension VPDetailPlayerViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private func requestRecommandDataArr() {
|
||||
|
||||
VPVideoAPI.requestDetailsRecommand { [weak self] list in
|
||||
guard let self = self else { return }
|
||||
if let list = list {
|
||||
self.recommandList = list
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
45
Veloria/Class/Player/View/VPDetailRecommandBannerCell.swift
Normal file
45
Veloria/Class/Player/View/VPDetailRecommandBannerCell.swift
Normal file
@ -0,0 +1,45 @@
|
||||
//
|
||||
// VPDetailRecommandBannerCell.swift
|
||||
// Veloria
|
||||
//
|
||||
// Created by 湖南秦九 on 2025/6/6.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import FSPagerView
|
||||
|
||||
class VPDetailRecommandBannerCell: FSPagerViewCell {
|
||||
|
||||
var model: VPShortModel? {
|
||||
didSet {
|
||||
coverImageView.vp_setImage(url: model?.image_url)
|
||||
}
|
||||
}
|
||||
|
||||
// private lazy var player: VPPlayer = {
|
||||
//
|
||||
// }()
|
||||
|
||||
|
||||
private lazy var coverImageView: VPImageView = {
|
||||
let imageView = VPImageView()
|
||||
imageView.layer.cornerRadius = 14
|
||||
imageView.layer.masksToBounds = true
|
||||
return imageView
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
contentView.addSubview(coverImageView)
|
||||
|
||||
coverImageView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
287
Veloria/Class/Player/View/VPDetailRecommandView.swift
Normal file
287
Veloria/Class/Player/View/VPDetailRecommandView.swift
Normal file
@ -0,0 +1,287 @@
|
||||
//
|
||||
// VPDetailRecommandView.swift
|
||||
// Veloria
|
||||
//
|
||||
// Created by 湖南秦九 on 2025/6/6.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import FSPagerView
|
||||
|
||||
class VPDetailRecommandView: HWPanModalContentView {
|
||||
|
||||
|
||||
var dataArr: [VPShortModel] = [] {
|
||||
didSet {
|
||||
|
||||
CATransaction.setCompletionBlock { [weak self] in
|
||||
self?.setVideoTitle()
|
||||
}
|
||||
|
||||
CATransaction.begin()
|
||||
bannerView.reloadData()
|
||||
CATransaction.commit()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var clickCloseButton: (() -> Void)?
|
||||
var clickLookButton: ((_ model: VPShortModel) -> Void)?
|
||||
|
||||
|
||||
|
||||
//MARK: UI属性
|
||||
private lazy var bgView: UIView = {
|
||||
let view = VPGradientView()
|
||||
view.locations = [0, 0.5, 1]
|
||||
view.colors = [UIColor.color045241().cgColor, UIColor.color000000().cgColor, UIColor.color000000().cgColor]
|
||||
view.startPoint = .init(x: 0, y: 0)
|
||||
view.endPoint = .init(x: 1, y: 1)
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var closeButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.setImage(UIImage(named: "close_icon_01"), for: .normal)
|
||||
button.addTarget(self, action: #selector(handleCloseButton), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .fontMedium(ofSize: 16)
|
||||
label.textColor = .colorFFFFFF()
|
||||
label.text = "kDetailRecommandTitle".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var bannerView: FSPagerView = {
|
||||
let view = FSPagerView()
|
||||
view.transformer = FSPagerViewTransformer(type: .overlap)
|
||||
view.transformer?.minimumScale = 0.8
|
||||
view.decelerationDistance = FSPagerView.automaticDistance
|
||||
view.itemSize = .init(width: 194, height: 258)
|
||||
view.isInfinite = true
|
||||
view.delegate = self
|
||||
view.dataSource = self
|
||||
view.register(VPDetailRecommandBannerCell.self, forCellWithReuseIdentifier: "cell")
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var videoTitleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .fontRegular(ofSize: 14)
|
||||
label.textColor = .colorFFFFFF()
|
||||
label.textAlignment = .center
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var videoCategoryView: UIButton = {
|
||||
var config = UIButton.Configuration.plain()
|
||||
config.contentInsets = .init(top: 0, leading: 5, bottom: 0, trailing: 5)
|
||||
|
||||
let view = UIButton(configuration: config)
|
||||
view.isUserInteractionEnabled = false
|
||||
view.backgroundColor = .colorFFFFFF(alpha: 0.1)
|
||||
view.layer.cornerRadius = 3
|
||||
view.layer.masksToBounds = true
|
||||
view.configurationUpdateHandler = { [weak self] button in
|
||||
guard let self = self else { return }
|
||||
if self.dataArr.count <= self.bannerView.currentIndex { return }
|
||||
|
||||
let model = self.dataArr[self.bannerView.currentIndex]
|
||||
let category = model.category?.last ?? ""
|
||||
|
||||
let string = AttributedString.createAttributedString(string: category, color: .colorAFAFAF(), font: .fontRegular(ofSize: 10))
|
||||
|
||||
button.configuration?.attributedTitle = string
|
||||
}
|
||||
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var lookButton: UIButton = {
|
||||
let button = VPGradientButton(type: .custom)
|
||||
button.locations = [0, 1]
|
||||
button.colors = [UIColor.color05CEA0(alpha: 0.3).cgColor, UIColor.color7C174F(alpha: 0.3).cgColor]
|
||||
button.startPoint = .init(x: 0, y: 0.3)
|
||||
button.endPoint = .init(x: 1, y: 0.8)
|
||||
button.bt_setGradientBorder()
|
||||
button.setTitle("Watch Now".localized, for: .normal)
|
||||
button.setTitleColor(.colorFFFFFF(), for: .normal)
|
||||
button.titleLabel?.font = .fontMedium(ofSize: 14)
|
||||
button.layer.cornerRadius = 24
|
||||
button.layer.masksToBounds = true
|
||||
button.addTarget(self, action: #selector(handleLookButton), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
|
||||
vp_setupUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
}
|
||||
|
||||
|
||||
//MARK: HWPanModalPresentable
|
||||
override func longFormHeight() -> PanModalHeight {
|
||||
return PanModalHeightMake(.content, 473 + UIScreen.tabbarSafeBottomMargin)
|
||||
}
|
||||
|
||||
override func showDragIndicator() -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
override func backgroundConfig() -> HWBackgroundConfig {
|
||||
let config = HWBackgroundConfig()
|
||||
config.backgroundAlpha = 0.6
|
||||
return config
|
||||
}
|
||||
|
||||
override func cornerRadius() -> CGFloat {
|
||||
return 24
|
||||
}
|
||||
|
||||
override func allowsTapBackgroundToDismiss() -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
override func allowsDragToDismiss() -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
override func minVerticalVelocityToTriggerDismiss() -> CGFloat {
|
||||
return 0
|
||||
}
|
||||
|
||||
override func allowsPullDownWhenShortState() -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension VPDetailRecommandView {
|
||||
|
||||
private func setVideoTitle() {
|
||||
let index = self.bannerView.currentIndex
|
||||
let cell = self.bannerView.cellForItem(at: index)
|
||||
vpLog(message: cell)
|
||||
|
||||
let model = self.dataArr[index]
|
||||
videoTitleLabel.text = model.name
|
||||
|
||||
if let category = model.category?.last, !category.isEmpty {
|
||||
videoCategoryView.isHidden = false
|
||||
videoCategoryView.setNeedsUpdateConfiguration()
|
||||
} else {
|
||||
videoCategoryView.isHidden = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@objc private func handleCloseButton() {
|
||||
self.clickCloseButton?()
|
||||
|
||||
self.dismiss(animated: true) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func handleLookButton() {
|
||||
let index = self.bannerView.currentIndex
|
||||
self.clickLookButton?(dataArr[index])
|
||||
|
||||
self.dismiss(animated: true) { }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension VPDetailRecommandView {
|
||||
|
||||
private func vp_setupUI() {
|
||||
addSubview(bgView)
|
||||
addSubview(titleLabel)
|
||||
addSubview(closeButton)
|
||||
addSubview(bannerView)
|
||||
addSubview(videoTitleLabel)
|
||||
addSubview(videoCategoryView)
|
||||
addSubview(lookButton)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(39)
|
||||
}
|
||||
|
||||
closeButton.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview().offset(-5)
|
||||
make.top.equalToSuperview().offset(5)
|
||||
make.width.height.equalTo(40)
|
||||
}
|
||||
|
||||
bannerView.snp.makeConstraints { make in
|
||||
make.left.right.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(77)
|
||||
make.height.equalTo(260)
|
||||
}
|
||||
|
||||
videoTitleLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(bannerView.snp.bottom).offset(9)
|
||||
make.width.equalTo(200)
|
||||
}
|
||||
|
||||
videoCategoryView.snp.makeConstraints { make in
|
||||
// make.left.equalTo(videoTitleLabel)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(bannerView.snp.bottom).offset(38)
|
||||
make.height.equalTo(16)
|
||||
}
|
||||
|
||||
lookButton.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.width.equalTo(240)
|
||||
make.height.equalTo(48)
|
||||
make.top.equalTo(bannerView.snp.bottom).offset(74)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//MARK: -------------- FSPagerViewDelegate FSPagerViewDataSource --------------
|
||||
extension VPDetailRecommandView: FSPagerViewDelegate, FSPagerViewDataSource {
|
||||
|
||||
func numberOfItems(in pagerView: FSPagerView) -> Int {
|
||||
return dataArr.count
|
||||
}
|
||||
|
||||
func pagerView(_ pagerView: FSPagerView, cellForItemAt index: Int) -> FSPagerViewCell {
|
||||
let cell = pagerView.dequeueReusableCell(withReuseIdentifier: "cell", at: index) as! VPDetailRecommandBannerCell
|
||||
cell.model = self.dataArr[index]
|
||||
return cell
|
||||
}
|
||||
|
||||
func pagerViewDidEndDecelerating(_ pagerView: FSPagerView) {
|
||||
setVideoTitle()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -14,6 +14,14 @@
|
||||
<string>fb642299232204955</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>VeloriaTV</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>FacebookAppID</key>
|
||||
<string>642299232204955</string>
|
||||
|
@ -86,7 +86,9 @@
|
||||
"Expired" = "Expired";
|
||||
"Success" = "Success";
|
||||
"Restore" = "Restore";
|
||||
"Watch Now" = "Watch Now";
|
||||
|
||||
"kDetailRecommandTitle" = "Picked Just for You";
|
||||
"kHomeTitleText" = "10,000+ addictive shorts await!";
|
||||
"kSearchPlaceholderText1" = "Search dramas";
|
||||
"kSearchPlaceholderText2" = "#Recersal of fate";
|
||||
|
@ -6,6 +6,10 @@
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</array>
|
||||
<key>com.apple.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>webcredentials:example.com</string>
|
||||
</array>
|
||||
<key>keychain-access-groups</key>
|
||||
<array/>
|
||||
</dict>
|
||||
|
@ -14,4 +14,6 @@ D-U-N-S :616751820
|
||||
|
||||
沙盒账号
|
||||
veloria@test.com
|
||||
Test@168
|
||||
Test@168
|
||||
veloria1@test.com
|
||||
Discover2024
|
Loading…
x
Reference in New Issue
Block a user