1.1.6,新增广告中介
This commit is contained in:
parent
cf0a5032f7
commit
ecb612fce1
@ -17,6 +17,10 @@
|
||||
CB0968752C2121410045E55B /* GADTSmallTemplateView.m in Sources */ = {isa = PBXBuildFile; fileRef = CB09686C2C2121410045E55B /* GADTSmallTemplateView.m */; };
|
||||
CB0968762C2121410045E55B /* GADTSmallTemplateView.xib in Resources */ = {isa = PBXBuildFile; fileRef = CB09686D2C2121410045E55B /* GADTSmallTemplateView.xib */; };
|
||||
CB0968772C2121410045E55B /* GADTTemplateView.m in Sources */ = {isa = PBXBuildFile; fileRef = CB09686F2C2121410045E55B /* GADTTemplateView.m */; };
|
||||
CB0B368B2C65AE3A004036E2 /* Lottie in Frameworks */ = {isa = PBXBuildFile; productRef = CB0B368A2C65AE3A004036E2 /* Lottie */; };
|
||||
CB0B368D2C65AEEF004036E2 /* Wave_Animation.json in Resources */ = {isa = PBXBuildFile; fileRef = CB0B368C2C65AEEF004036E2 /* Wave_Animation.json */; };
|
||||
CB0B368F2C65B026004036E2 /* MP_WaveAnimationMaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0B368E2C65B026004036E2 /* MP_WaveAnimationMaskView.swift */; };
|
||||
CB0B36912C65EBFC004036E2 /* MPPositive_BaseShowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0B36902C65EBFC004036E2 /* MPPositive_BaseShowView.swift */; };
|
||||
CB15B89B2C353B2400756E89 /* MP_GuideViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB15B8992C353B2400756E89 /* MP_GuideViewController.swift */; };
|
||||
CB15B89C2C353B2400756E89 /* MP_GuideViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CB15B89A2C353B2400756E89 /* MP_GuideViewController.xib */; };
|
||||
CB1E3B662C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */; };
|
||||
@ -274,6 +278,9 @@
|
||||
CB09686E2C2121410045E55B /* GADTTemplateView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GADTTemplateView.h; sourceTree = "<group>"; };
|
||||
CB09686F2C2121410045E55B /* GADTTemplateView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GADTTemplateView.m; sourceTree = "<group>"; };
|
||||
CB09687E2C2126DD0045E55B /* Swift-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Swift-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
CB0B368C2C65AEEF004036E2 /* Wave_Animation.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Wave_Animation.json; sourceTree = "<group>"; };
|
||||
CB0B368E2C65B026004036E2 /* MP_WaveAnimationMaskView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_WaveAnimationMaskView.swift; sourceTree = "<group>"; };
|
||||
CB0B36902C65EBFC004036E2 /* MPPositive_BaseShowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_BaseShowView.swift; sourceTree = "<group>"; };
|
||||
CB15B8992C353B2400756E89 /* MP_GuideViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_GuideViewController.swift; sourceTree = "<group>"; };
|
||||
CB15B89A2C353B2400756E89 /* MP_GuideViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MP_GuideViewController.xib; sourceTree = "<group>"; };
|
||||
CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CustomPlayListModel.swift; sourceTree = "<group>"; };
|
||||
@ -521,6 +528,7 @@
|
||||
CBAFCBAD2C0A10DA0054500E /* FirebaseCrashlytics in Frameworks */,
|
||||
CBD4570D2C2EC38400CE766D /* AppTrackingTransparency.framework in Frameworks */,
|
||||
CBAFCBAB2C0A10DA0054500E /* FirebaseAnalytics in Frameworks */,
|
||||
CB0B368B2C65AE3A004036E2 /* Lottie in Frameworks */,
|
||||
CB6EEB8E2C5DFE6100AEC414 /* StoreKit.framework in Frameworks */,
|
||||
CBAFCBAF2C0A10DA0054500E /* FirebaseRemoteConfig in Frameworks */,
|
||||
CB7FC5462C2AA01F00292A43 /* FacebookCore in Frameworks */,
|
||||
@ -582,6 +590,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CBAFC9F72C0A10500054500E /* MP_Lunch_ProgressView.swift */,
|
||||
CB0B368E2C65B026004036E2 /* MP_WaveAnimationMaskView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@ -680,6 +689,7 @@
|
||||
CBAFCA122C0A10500054500E /* Sounds of appliances */,
|
||||
CBAFCA1C2C0A10500054500E /* Sounds of nature */,
|
||||
CBAFCA1D2C0A10500054500E /* Resource.plist */,
|
||||
CB0B368C2C65AEEF004036E2 /* Wave_Animation.json */,
|
||||
);
|
||||
path = "Resource(资源)";
|
||||
sourceTree = "<group>";
|
||||
@ -903,6 +913,7 @@
|
||||
CBAFCA782C0A10500054500E /* MPPositive_BottomShowView.swift */,
|
||||
CBAFCA7C2C0A10500054500E /* MPPositive_MoreOperationDownLoadTableViewCell.swift */,
|
||||
CB0033F52C295E3100B18FD3 /* MPPositive_MoreOperationShowTableViewCell.swift */,
|
||||
CB0B36902C65EBFC004036E2 /* MPPositive_BaseShowView.swift */,
|
||||
);
|
||||
path = Base;
|
||||
sourceTree = "<group>";
|
||||
@ -1098,13 +1109,6 @@
|
||||
path = ViewControllers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CBAFCACA2C0A10500054500E /* Add(新增资源) */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
path = "Add(新增资源)";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CBAFCAD12C0A10500054500E /* Base(基类-导航栏-标签栏) */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1149,10 +1153,9 @@
|
||||
CBAFCAE22C0A10500054500E /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CBAFCACA2C0A10500054500E /* Add(新增资源) */,
|
||||
CBAFCAD12C0A10500054500E /* Base(基类-导航栏-标签栏) */,
|
||||
CBAFCAD62C0A10500054500E /* Center(个人资源) */,
|
||||
CBAFCAE12C0A10500054500E /* Home(音乐资源列表-播放器) */,
|
||||
CBAFCAD62C0A10500054500E /* Center(个人资源) */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@ -1238,6 +1241,7 @@
|
||||
CB7FC5412C2AA01F00292A43 /* FacebookAEM */,
|
||||
CB7FC5432C2AA01F00292A43 /* FacebookBasics */,
|
||||
CB7FC5452C2AA01F00292A43 /* FacebookCore */,
|
||||
CB0B368A2C65AE3A004036E2 /* Lottie */,
|
||||
);
|
||||
productName = relax.offline.mp3.music;
|
||||
productReference = CBC2D6E82BFDF3D700E17703 /* relax.offline.mp3.music.app */;
|
||||
@ -1270,6 +1274,7 @@
|
||||
packageReferences = (
|
||||
CBAFCBA92C0A10DA0054500E /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
|
||||
CB7FC5402C2AA01F00292A43 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */,
|
||||
CB0B36892C65AE3A004036E2 /* XCRemoteSwiftPackageReference "lottie-spm" */,
|
||||
);
|
||||
productRefGroup = CBC2D6E92BFDF3D700E17703 /* Products */;
|
||||
projectDirPath = "";
|
||||
@ -1331,6 +1336,7 @@
|
||||
CB15B89C2C353B2400756E89 /* MP_GuideViewController.xib in Resources */,
|
||||
CBAFCB002C0A10500054500E /* Chirping of Birds.mp3 in Resources */,
|
||||
CBAFCBA72C0A10500054500E /* MPSideA_Home_SecondListCollectionViewCell.xib in Resources */,
|
||||
CB0B368D2C65AEEF004036E2 /* Wave_Animation.json in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1464,6 +1470,7 @@
|
||||
CB2CAAD82C5A1AC500EF691D /* MP_IAPViewController.swift in Sources */,
|
||||
CBC1FB7E2C509BB400AC0633 /* MPPositive_LibraryListViewModel.swift in Sources */,
|
||||
CBAFCB992C0A10500054500E /* MPSideA_CustomTabBarView.swift in Sources */,
|
||||
CB0B368F2C65B026004036E2 /* MP_WaveAnimationMaskView.swift in Sources */,
|
||||
CBAFCB342C0A10500054500E /* MPPositive_DownloadViewModel.swift in Sources */,
|
||||
CBAFCB1E2C0A10500054500E /* MPPositive_JsonRecommend.swift in Sources */,
|
||||
CB7FC5482C2AC25C00292A43 /* MPPositive_CenterListSearchView.swift in Sources */,
|
||||
@ -1472,6 +1479,7 @@
|
||||
CBAFCB402C0A10500054500E /* MPPositive_SearchResultsLoadViewModel.swift in Sources */,
|
||||
CBAFCB132C0A10500054500E /* MP_WebWork.swift in Sources */,
|
||||
CBAFCB3A2C0A10500054500E /* MPPositive_SearchSuggestionItemListModel.swift in Sources */,
|
||||
CB0B36912C65EBFC004036E2 /* MPPositive_BaseShowView.swift in Sources */,
|
||||
CBAFCB122C0A10500054500E /* MP_PlayerSlider.swift in Sources */,
|
||||
CBAFCB082C0A10500054500E /* MP_AnalyticsManager.swift in Sources */,
|
||||
CBAFCB1C2C0A10500054500E /* MPPositive_JsonNext.swift in Sources */,
|
||||
@ -1873,6 +1881,14 @@
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
CB0B36892C65AE3A004036E2 /* XCRemoteSwiftPackageReference "lottie-spm" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/airbnb/lottie-spm.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 4.5.0;
|
||||
};
|
||||
};
|
||||
CB7FC5402C2AA01F00292A43 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/facebook/facebook-ios-sdk";
|
||||
@ -1892,6 +1908,11 @@
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
CB0B368A2C65AE3A004036E2 /* Lottie */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = CB0B36892C65AE3A004036E2 /* XCRemoteSwiftPackageReference "lottie-spm" */;
|
||||
productName = Lottie;
|
||||
};
|
||||
CB7FC5412C2AA01F00292A43 /* FacebookAEM */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = CB7FC5402C2AA01F00292A43 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"originHash" : "356668427da72005d8cb60963e877385296f1863605fc5a20d1f75f2cec3b22c",
|
||||
"originHash" : "faf6001fdda5daa8e1887ad5537209b76d1294d394c19dacdef18322dc72fcd3",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "abseil-cpp-binary",
|
||||
@ -100,6 +100,15 @@
|
||||
"version" : "1.22.5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "lottie-spm",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/airbnb/lottie-spm.git",
|
||||
"state" : {
|
||||
"revision" : "b842598f1295f3ffa1475b1580672d1fe5b83580",
|
||||
"version" : "4.5.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "nanopb",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
||||
Binary file not shown.
@ -222,7 +222,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
}
|
||||
//MARK: - 当应用被用户关闭时
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
MP_AnalyticsManager.shared.ad_session_total_valueAction()
|
||||
print("应用关闭了")
|
||||
//检索应用是否播放歌曲
|
||||
guard let load = MP_PlayerManager.shared.loadPlayer, let videoId = load.currentVideoId, let songs = load.songVideos else {return}
|
||||
|
||||
@ -344,15 +344,23 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
||||
if ad === MP_AdMobManager.shared.appOpenAd || ad === MP_AdMobManager.shared.appInterstitialAd {
|
||||
if let openAd = MP_AdMobManager.shared.appOpenAd {
|
||||
print("当前展示的广告是开屏广告,广告ID--\(openAd.adUnitID)")
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(openAd.responseInfo) {
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
}
|
||||
}else {
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: .init())
|
||||
}
|
||||
}else if let openAd = MP_AdMobManager.shared.appInterstitialAd {
|
||||
print("当前展示的广告是开屏广告,广告ID--\(openAd.adUnitID)")
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(openAd.responseInfo) {
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
}
|
||||
}else {
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: .init())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
//
|
||||
// MP_WaveAnimationMaskView.swift
|
||||
// relax.offline.mp3.music
|
||||
//
|
||||
// Created by Mr.Zhou on 2024/8/9.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Lottie
|
||||
class MP_WaveAnimationMaskView: UIView {
|
||||
///动画View
|
||||
private lazy var lotView:LottieAnimationView = {
|
||||
//获取动画View
|
||||
let json = Bundle.main.path(forResource: "Wave_Animation", ofType: "json")
|
||||
let animationView:LottieAnimationView = .init(filePath: json ?? "")
|
||||
//无限循环
|
||||
animationView.loopMode = .loop
|
||||
//填充
|
||||
animationView.contentMode = .scaleAspectFill
|
||||
animationView.backgroundColor = .clear
|
||||
return animationView
|
||||
}()
|
||||
init(frame: CGRect, cornerRadius:CGFloat) {
|
||||
super.init(frame: frame)
|
||||
backgroundColor = .init(hex: "#000000", alpha: 0.6)
|
||||
layer.masksToBounds = true
|
||||
layer.cornerRadius = cornerRadius
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
}
|
||||
//配置
|
||||
func configure() {
|
||||
addSubview(lotView)
|
||||
lotView.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
make.width.height.equalToSuperview().multipliedBy(0.35)
|
||||
}
|
||||
}
|
||||
//启动动画
|
||||
func startAnimation() {
|
||||
lotView.play()
|
||||
}
|
||||
//暂停动画
|
||||
func stopAnimation() {
|
||||
lotView.stop()
|
||||
}
|
||||
}
|
||||
@ -49,7 +49,7 @@ extension Range where Bound == String.Index {
|
||||
///扩展UILabel
|
||||
extension UILabel {
|
||||
///设置文本渐变色
|
||||
func setGradientTextColor(_ colors:[CGColor]) {
|
||||
func setGradientTextColor(_ colors:[CGColor], alignmentMode:CATextLayerAlignmentMode = .center) {
|
||||
self.layoutIfNeeded()
|
||||
//设置一个渐变层
|
||||
let gradientLayer = CAGradientLayer()
|
||||
@ -63,7 +63,7 @@ extension UILabel {
|
||||
textLayer.string = self.attributedText
|
||||
textLayer.isWrapped = true
|
||||
textLayer.truncationMode = .end
|
||||
textLayer.alignmentMode = .center
|
||||
textLayer.alignmentMode = alignmentMode
|
||||
textLayer.contentsScale = UIScreen.main.scale
|
||||
gradientLayer.mask = textLayer
|
||||
//添加层级
|
||||
|
||||
@ -79,6 +79,8 @@ let serviceUrl:URL = .init(string: "https://musiclax.mystrikingly.com/terms")!
|
||||
let gradientTextColors:[CGColor] = [UIColor(red: 0, green: 0.863, blue: 1, alpha: 1).cgColor,
|
||||
UIColor(red: 0, green: 1, blue: 0.561, alpha: 1).cgColor,
|
||||
UIColor(red: 0.776, green: 1, blue: 0.639, alpha: 1).cgColor]
|
||||
///常用文本颜色-绿色
|
||||
let greenTextColor:UIColor = .init(hex: "#80F988", alpha: 1.0)
|
||||
|
||||
//MARK: - 全局变量与方法
|
||||
//存储默认配置值
|
||||
@ -160,7 +162,8 @@ func coreDefaultValues() {
|
||||
if UserDefaults.standard.object(forKey: "LoadINSERTID") == nil {
|
||||
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/4335559460", ad: "AdMob", type: .Insert),
|
||||
.init(level: 2, identifier: "ca-app-pub-1371732277241593/2398278378", ad: "AdMob", type: .Insert),
|
||||
.init(level: 1, identifier: "ca-app-pub-1371732277241593/3107763383", ad: "AdMob", type: .Insert)]) {
|
||||
.init(level: 1, identifier: "ca-app-pub-1371732277241593/7827517266", ad: "AdMob", type: .Insert),
|
||||
.init(level: 0, identifier: "ca-app-pub-1371732277241593/3107763383", ad: "AdMob", type: .Insert)]) {
|
||||
//存入默认开屏热启动广告ID
|
||||
UserDefaults.standard.set(array, forKey: "LoadINSERTID")
|
||||
}
|
||||
@ -190,7 +193,10 @@ func coreDefaultValues() {
|
||||
UserDefaults.standard.removeObject(forKey: "GlobalINSERTID")
|
||||
}
|
||||
if UserDefaults.standard.object(forKey: "GlobalINSERTID") == nil {
|
||||
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/9449223728", ad: "AdMob", type: .Insert)]) {
|
||||
if let array = coreAdModelforJson([.init(level: 3, identifier: "ca-app-pub-1371732277241593/2696862512", ad: "AdMob", type: .Insert),
|
||||
.init(level: 2, identifier: "ca-app-pub-1371732277241593/2477370661", ad: "AdMob", type: .Insert),
|
||||
.init(level: 1, identifier: "ca-app-pub-1371732277241593/3391529916", ad: "AdMob", type: .Insert),
|
||||
.init(level: 0, identifier: "ca-app-pub-1371732277241593/9449223728", ad: "AdMob", type: .Insert)]) {
|
||||
//存入默认开屏热启动广告ID
|
||||
UserDefaults.standard.set(array, forKey: "GlobalINSERTID")
|
||||
}
|
||||
|
||||
@ -0,0 +1 @@
|
||||
{"v":"4.8.0","meta":{"g":"LottieFiles AE ","a":"","k":"","d":"","tc":""},"fr":25,"ip":0,"op":24,"w":1080,"h":1080,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[890,540,0],"ix":2},"a":{"a":0,"k":[-55.281,30.914,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":6,"s":[300,418]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":14,"s":[300,1018]},{"t":23,"s":[300,418]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":364,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false,"_render":true},{"ty":"fl","c":{"a":0,"k":[0.051,0.8745,0.1176,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[-55.281,30.914],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":750,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[540,540,0],"ix":2},"a":{"a":0,"k":[-55.281,30.914,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":0,"s":[300,1018]},{"i":{"x":[0.833,0.833],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":13,"s":[300,300]},{"t":24,"s":[300,1018]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":364,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false,"_render":true},{"ty":"fl","c":{"a":0,"k":[0.051,0.8745,0.1176,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[-55.281,30.914],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":750,"st":0,"bm":0,"completed":true},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[190,540,0],"ix":2},"a":{"a":0,"k":[-55.281,30.914,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":0,"s":[300,300]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":11,"s":[300,1018]},{"t":22,"s":[300,300]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":364,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false,"_render":true},{"ty":"fl","c":{"a":0,"k":[0.051,0.8745,0.1176,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false,"_render":true},{"ty":"tr","p":{"a":0,"k":[-55.281,30.914],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform","_render":true}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"_render":true}],"ip":0,"op":750,"st":0,"bm":0,"completed":true}],"markers":[],"__complete":true}
|
||||
@ -8,8 +8,8 @@
|
||||
import UIKit
|
||||
import AVFoundation
|
||||
import GoogleMobileAds
|
||||
import AppLovinSDK
|
||||
import AppLovinAdapter
|
||||
import AppLovinSDK
|
||||
import LiftoffMonetizeAdapter
|
||||
import VungleAdsSDK
|
||||
import PangleAdapter
|
||||
@ -70,6 +70,7 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
}
|
||||
private override init() {
|
||||
super.init()
|
||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(netWorkReachableAction(_:)), notificationName: .net_switch_reachable)
|
||||
GADMobileAds.sharedInstance().audioVideoManager.delegate = self
|
||||
GADMobileAds.sharedInstance().audioVideoManager.audioSessionIsApplicationManaged = false
|
||||
reloadAdMobIDs()
|
||||
@ -311,7 +312,16 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
}
|
||||
}
|
||||
}
|
||||
//网络可用时触发
|
||||
@objc private func netWorkReachableAction(_ sender:Notification) {
|
||||
DispatchQueue.main.async {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
loadMoreAdMobs()
|
||||
}
|
||||
}
|
||||
deinit{
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
displaySearchTimer?.invalidate()
|
||||
displaySearchTimer = nil
|
||||
displayLibraryTimer?.invalidate()
|
||||
@ -414,6 +424,16 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
print("热启动广告组已经全部加载失败,停止继续加载")
|
||||
MP_AnalyticsManager.shared.hot_ads_loadFailureAction("No Ads Fill")
|
||||
completion(false)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||||
[weak self] in
|
||||
self?.loadOpenAd(.HOST, completion: { status in
|
||||
if status {
|
||||
print("重新加载热启动广告成功")
|
||||
}else {
|
||||
print("重新加载热启动广告失败")
|
||||
}
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
item = OpenHOSTID[level]
|
||||
@ -490,6 +510,16 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
self.showOpenAdIfAvailable(type, completion: completion)
|
||||
}
|
||||
}
|
||||
if type == .HOST {
|
||||
//同步展示全屏广告
|
||||
showGlobalInterstitialAdIfAvailable { ad in
|
||||
if let ad = ad {
|
||||
if let block = completion {
|
||||
block(ad, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
if type == .ICE {
|
||||
@ -542,6 +572,7 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
}
|
||||
}
|
||||
}else {
|
||||
print("开屏广告展示失败")
|
||||
if type == .ICE {
|
||||
MP_AnalyticsManager.shared.cold_ads_showFailureAction("Ad loading failed")
|
||||
}else {
|
||||
@ -674,9 +705,15 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
guard level < (SearchINSERTID.count) else {
|
||||
print("搜索插页广告组已经全部加载失败,停止继续加载")
|
||||
MP_AnalyticsManager.shared.search_ads_loadFailureAction("No Ads Fill")
|
||||
//开始加载全局插页
|
||||
loadGlobalInterstitialAd { status in
|
||||
completion(status)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
|
||||
[weak self] in
|
||||
self?.loadSearchInterstitialAd { status in
|
||||
if status {
|
||||
print("重新加载搜索插页广告")
|
||||
}else {
|
||||
print("加载搜索插页广告失败")
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -728,6 +765,8 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
self.showSearchInterstitialAdIfAvailable(completion: completion)
|
||||
}
|
||||
}
|
||||
//展示全屏广告
|
||||
showGlobalInterstitialAdIfAvailable(completion: nil)
|
||||
return
|
||||
}
|
||||
MP_AnalyticsManager.shared.search_ads_chanceAction()
|
||||
@ -741,16 +780,6 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
interstitialSwitch = true
|
||||
ad.present(fromRootViewController: nil)
|
||||
}
|
||||
}else if let ad = globalInterstitialAd {
|
||||
//加载全局插页广告
|
||||
//传递加载完成事件
|
||||
if let block = completion {
|
||||
block(ad)
|
||||
}else {
|
||||
isShowingGlobalInterstitialAd = true
|
||||
interstitialSwitch = true
|
||||
ad.present(fromRootViewController: nil)
|
||||
}
|
||||
}else {
|
||||
MP_AnalyticsManager.shared.search_ads_showFailureAction("Ad loading failed")
|
||||
}
|
||||
@ -796,9 +825,15 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
guard level < (PlayerINSERTID.count) else {
|
||||
print("播放插页广告组已经全部加载失败,停止继续加载")
|
||||
MP_AnalyticsManager.shared.play_ads_loadFailureAction("No Ads Fill")
|
||||
//开始加载全局插页
|
||||
loadGlobalInterstitialAd { status in
|
||||
completion(status)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
|
||||
[weak self] in
|
||||
self?.loadPlayInterstitialAd { status in
|
||||
if status {
|
||||
print("重新加载播放插页广告")
|
||||
}else {
|
||||
print("加载播放插页广告失败")
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -826,17 +861,26 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
}
|
||||
}
|
||||
///播放插页广告展示
|
||||
func showPlayInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
||||
func showPlayInterstitialAdIfAvailable(completion:((GADInterstitialAd?) -> Void)?) {
|
||||
guard openAdStatus else {
|
||||
completion?(nil)
|
||||
return
|
||||
}
|
||||
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||||
completion?(nil)
|
||||
return
|
||||
}
|
||||
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
||||
guard !interstitialSwitch, !isShowingPlayInterstitialAd else { return }
|
||||
guard !interstitialSwitch, !isShowingPlayInterstitialAd else {
|
||||
completion?(nil)
|
||||
return
|
||||
}
|
||||
//检索是否存在插页间隔时间
|
||||
if let date = interstitialDate {
|
||||
if isShowInterstitialADAvailable(date) == false {
|
||||
//未超过插页间隔时长
|
||||
print("距上一次展示插页广告时长未超过要求,此次插页广告展示滞后")
|
||||
completion?(nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -844,8 +888,10 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
if !isPlayInterstitialAdAvailable() {
|
||||
loadPlayInterstitialAd{ [weak self] success in
|
||||
guard let self = self else { return }
|
||||
if success {
|
||||
if success {
|
||||
self.showPlayInterstitialAdIfAvailable(completion: completion)
|
||||
}else {
|
||||
completion?(nil)
|
||||
}
|
||||
}
|
||||
return
|
||||
@ -861,18 +907,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
interstitialSwitch = true
|
||||
ad.present(fromRootViewController: nil)
|
||||
}
|
||||
}else if let ad = globalInterstitialAd {
|
||||
//加载全局插页广告
|
||||
//传递加载完成事件
|
||||
if let block = completion {
|
||||
block(ad)
|
||||
}else {
|
||||
isShowingGlobalInterstitialAd = true
|
||||
interstitialSwitch = true
|
||||
ad.present(fromRootViewController: nil)
|
||||
}
|
||||
}else {
|
||||
MP_AnalyticsManager.shared.play_ads_showFailureAction("Ad loading failed")
|
||||
completion?(nil)
|
||||
}
|
||||
}
|
||||
//查询是否有播放插页广告
|
||||
@ -916,9 +953,15 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
guard level < (SwitchINSERTID.count) else {
|
||||
print("切歌插页广告组已经全部加载失败,停止继续加载")
|
||||
MP_AnalyticsManager.shared.cut_ads_loadFailureAction("No Ads Fill")
|
||||
//开始加载全局插页
|
||||
loadGlobalInterstitialAd { status in
|
||||
completion(status)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
|
||||
[weak self] in
|
||||
self?.loadSwitchInterstitialAd { status in
|
||||
if status {
|
||||
print("重新加载切歌插页广告")
|
||||
}else {
|
||||
print("加载切歌插页广告失败")
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -968,6 +1011,8 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
self.showSwitchInterstitialAdIfAvailable(completion: completion)
|
||||
}
|
||||
}
|
||||
//展示全屏广告
|
||||
showGlobalInterstitialAdIfAvailable(completion: nil)
|
||||
return
|
||||
}
|
||||
MP_AnalyticsManager.shared.cut_ads_chanceAction()
|
||||
@ -981,16 +1026,6 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
interstitialSwitch = true
|
||||
ad.present(fromRootViewController: nil)
|
||||
}
|
||||
}else if let ad = globalInterstitialAd {
|
||||
//加载全局插页广告
|
||||
//传递加载完成事件
|
||||
if let block = completion {
|
||||
block(ad)
|
||||
}else {
|
||||
isShowingGlobalInterstitialAd = true
|
||||
interstitialSwitch = true
|
||||
ad.present(fromRootViewController: nil)
|
||||
}
|
||||
}else {
|
||||
MP_AnalyticsManager.shared.cut_ads_showFailureAction("Ad loading failed")
|
||||
}
|
||||
@ -1035,9 +1070,15 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
guard level < (LoadINSERTID.count) else {
|
||||
print("下载插页广告组已经全部加载失败,停止继续加载")
|
||||
MP_AnalyticsManager.shared.dl_ads_loadFailureAction("No Ads Fill")
|
||||
//开始加载全局插页
|
||||
loadGlobalInterstitialAd { status in
|
||||
completion(status)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
|
||||
[weak self] in
|
||||
self?.loadLoadInterstitialAd { status in
|
||||
if status {
|
||||
print("重新加载下载插页广告")
|
||||
}else {
|
||||
print("加载下载插页广告失败")
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -1087,6 +1128,8 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
self.showLoadInterstitialAdIfAvailable(completion: completion)
|
||||
}
|
||||
}
|
||||
//展示全屏广告
|
||||
showGlobalInterstitialAdIfAvailable(completion: nil)
|
||||
return
|
||||
}
|
||||
MP_AnalyticsManager.shared.dl_ads_chanceAction()
|
||||
@ -1100,16 +1143,6 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
interstitialSwitch = true
|
||||
ad.present(fromRootViewController: nil)
|
||||
}
|
||||
}else if let ad = globalInterstitialAd {
|
||||
//加载全局插页广告
|
||||
//传递加载完成事件
|
||||
if let block = completion {
|
||||
block(ad)
|
||||
}else {
|
||||
isShowingGlobalInterstitialAd = true
|
||||
interstitialSwitch = true
|
||||
ad.present(fromRootViewController: nil)
|
||||
}
|
||||
}else {
|
||||
MP_AnalyticsManager.shared.dl_ads_showFailureAction("Ad loading failed")
|
||||
}
|
||||
@ -1133,25 +1166,25 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
private var loadLibraryInterstitialAdTime:Date?
|
||||
///曲库广告处理闭包
|
||||
var completeLibraryInterstitialAdBlock:(() -> Void)?
|
||||
///搜索原生广告加载器
|
||||
///曲库原生广告加载器
|
||||
var libraryAdLoader:GADAdLoader?
|
||||
///搜索原生广告
|
||||
///曲库原生广告
|
||||
var libraryNativeAds:[GADNativeAd]?
|
||||
///搜索原生广告视图一
|
||||
///曲库原生广告视图一
|
||||
var libraryNativeAdFirstView:GADNativeAdView?
|
||||
///原生广告视图二
|
||||
var libraryNativeAdSecondView:GADNativeAdView?
|
||||
///搜索原生存储时长
|
||||
///曲库原生存储时长
|
||||
var refreshLibraryTimes:TimeInterval = 3600
|
||||
///搜索原生显示刷新计时器
|
||||
///曲库原生显示刷新计时器
|
||||
var displayLibraryTimer:Timer?
|
||||
///搜索原生加载时间
|
||||
///曲库原生加载时间
|
||||
var expirationLibraryDate:Date?
|
||||
///搜索控制器
|
||||
///曲库控制器
|
||||
var libraryViewController:UIViewController?
|
||||
///搜索原生回调闭包
|
||||
///曲库原生回调闭包
|
||||
var onLibraryNativeAdBlock:(() -> Void)?
|
||||
///配置搜索原生广告加载器
|
||||
///配置曲库原生广告加载器
|
||||
func configureLibraryNativeAd(rootController vc:UIViewController) {
|
||||
guard openAdStatus else {
|
||||
return
|
||||
@ -1160,7 +1193,7 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
libraryViewController = vc
|
||||
}
|
||||
}
|
||||
///搜索原生广告加载
|
||||
///曲库原生广告加载
|
||||
func loadLibraryNativeAd() {
|
||||
guard openAdStatus else {return}
|
||||
guard let vc = libraryViewController, libraryNativeAds == nil else {return}
|
||||
@ -1181,7 +1214,7 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
libraryNativeAds = []
|
||||
}
|
||||
}
|
||||
///将加载的搜索原生广告添加到页面中
|
||||
///将加载的曲库原生广告添加到页面中
|
||||
func layoutLibraryNativeAd(in containerView: UIView, index:Int) {
|
||||
guard openAdStatus else {return}
|
||||
containerView.subviews.forEach { item in
|
||||
@ -1254,7 +1287,7 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
self?.loadLibraryNativeAd()
|
||||
}
|
||||
}
|
||||
///搜索原生存储时长
|
||||
///曲库原生存储时长
|
||||
private func refreshLibraryDate(_ date:Date?) -> Bool {
|
||||
guard let date = date else {return false}
|
||||
return Date().timeIntervalSince(date) < refreshLibraryTimes
|
||||
@ -1281,9 +1314,15 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
guard level < (LibraryINSERTID.count) else {
|
||||
print("曲库插页广告组已经全部加载失败,停止继续加载")
|
||||
MP_AnalyticsManager.shared.listclk_ads_loadFailureAction("No Ads Fill")
|
||||
//开始加载全局插页
|
||||
loadGlobalInterstitialAd { status in
|
||||
completion(status)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
|
||||
[weak self] in
|
||||
self?.loadLoadInterstitialAd { status in
|
||||
if status {
|
||||
print("重新加载曲库插页广告")
|
||||
}else {
|
||||
print("加载曲库插页广告失败")
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -1333,6 +1372,8 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
self.showLibraryInterstitialAdIfAvailable(completion: completion)
|
||||
}
|
||||
}
|
||||
//展示全屏广告
|
||||
showGlobalInterstitialAdIfAvailable(completion: nil)
|
||||
return
|
||||
}
|
||||
MP_AnalyticsManager.shared.listclk_ads_chanceAction()
|
||||
@ -1347,17 +1388,6 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
interstitialSwitch = true
|
||||
ad.present(fromRootViewController: nil)
|
||||
}
|
||||
}else if let ad = globalInterstitialAd {
|
||||
//加载全局插页广告
|
||||
|
||||
//传递加载完成事件
|
||||
if let block = completion {
|
||||
block(ad)
|
||||
}else {
|
||||
isShowingGlobalInterstitialAd = true
|
||||
interstitialSwitch = true
|
||||
ad.present(fromRootViewController: nil)
|
||||
}
|
||||
}else {
|
||||
MP_AnalyticsManager.shared.listclk_ads_showFailureAction("Ad loading failed")
|
||||
}
|
||||
@ -1420,7 +1450,7 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
}
|
||||
}
|
||||
///全局插页广告展示
|
||||
func showGlobalInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) {
|
||||
func showGlobalInterstitialAdIfAvailable(completion:((GADInterstitialAd?) -> Void)?) {
|
||||
guard openAdStatus else {
|
||||
return
|
||||
}
|
||||
@ -1440,6 +1470,8 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
guard let self = self else { return }
|
||||
if success {
|
||||
self.showGlobalInterstitialAdIfAvailable(completion: completion)
|
||||
}else {
|
||||
completion?(nil)
|
||||
}
|
||||
}
|
||||
return
|
||||
@ -1488,63 +1520,109 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
|
||||
if OpenICEID.contains(where: {($0.identifier == (appOpenAd?.adUnitID ?? "") || $0.identifier == (appInterstitialAd?.adUnitID ?? ""))}) {
|
||||
//冷启动,检索是插页还是开屏
|
||||
if let openAd = appOpenAd {
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(openAd.responseInfo) {
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
}
|
||||
}else {
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: .init())
|
||||
}
|
||||
}else if let openAd = appInterstitialAd {
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(openAd.responseInfo) {
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
}
|
||||
}else {
|
||||
MP_AnalyticsManager.shared.cold_ads_showSuccessAction(openAd.responseInfo, adValue: .init())
|
||||
}
|
||||
}
|
||||
}else if OpenHOSTID.contains(where: {($0.identifier == (appOpenAd?.adUnitID ?? "") || $0.identifier == (appInterstitialAd?.adUnitID ?? ""))}) {
|
||||
//热启动,检索是插页还是开屏
|
||||
if let openAd = appOpenAd {
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.hot_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(openAd.responseInfo) {
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.hot_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
}
|
||||
}else {
|
||||
MP_AnalyticsManager.shared.hot_ads_showSuccessAction(openAd.responseInfo, adValue: .init())
|
||||
}
|
||||
}else if let openAd = appInterstitialAd {
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.hot_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(openAd.responseInfo) {
|
||||
//上传广告收益
|
||||
openAd.paidEventHandler = { adValue in
|
||||
MP_AnalyticsManager.shared.hot_ads_showSuccessAction(openAd.responseInfo, adValue: adValue)
|
||||
}
|
||||
}else {
|
||||
MP_AnalyticsManager.shared.hot_ads_showSuccessAction(openAd.responseInfo, adValue: .init())
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if ad === searchInterstitialAd {//搜索插页广告
|
||||
print("当前展示的广告是搜索插页广告,广告ID--\(searchInterstitialAd?.adUnitID ?? "")")
|
||||
searchInterstitialAd?.paidEventHandler = { adValue in
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(searchInterstitialAd?.responseInfo) {
|
||||
searchInterstitialAd?.paidEventHandler = { adValue in
|
||||
if let response = self.searchInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.search_ads_showSuccessAction(response, adValue: adValue)
|
||||
}
|
||||
}
|
||||
}else {
|
||||
if let response = self.searchInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.search_ads_showSuccessAction(response, adValue: adValue)
|
||||
MP_AnalyticsManager.shared.search_ads_showSuccessAction(response, adValue: .init())
|
||||
}
|
||||
}
|
||||
}else if ad === playInterstitialAd {//播放插页广告
|
||||
print("当前展示的广告是播放插页广告,广告ID--\(playInterstitialAd?.adUnitID ?? "")")
|
||||
playInterstitialAd?.paidEventHandler = { adValue in
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(playInterstitialAd?.responseInfo) {
|
||||
playInterstitialAd?.paidEventHandler = { adValue in
|
||||
if let response = self.playInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.play_ads_showSuccessAction(response, adValue: adValue)
|
||||
}
|
||||
}
|
||||
}else {
|
||||
if let response = self.playInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.play_ads_showSuccessAction(response, adValue: adValue)
|
||||
MP_AnalyticsManager.shared.play_ads_showSuccessAction(response, adValue: .init())
|
||||
}
|
||||
}
|
||||
}else if ad === switchInterstitialAd {//切歌插页广告
|
||||
print("当前展示的广告是切歌插页广告,广告ID--\(switchInterstitialAd?.adUnitID ?? "")")
|
||||
switchInterstitialAd?.paidEventHandler = { adValue in
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(switchInterstitialAd?.responseInfo) {
|
||||
switchInterstitialAd?.paidEventHandler = { adValue in
|
||||
if let response = self.switchInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.cut_ads_showSuccessAction(response, adValue: adValue)
|
||||
}
|
||||
}
|
||||
}else {
|
||||
if let response = self.switchInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.cut_ads_showSuccessAction(response, adValue: adValue)
|
||||
MP_AnalyticsManager.shared.cut_ads_showSuccessAction(response, adValue: .init())
|
||||
}
|
||||
}
|
||||
}else if ad === loadInterstitialAd {//下载插页广告
|
||||
print("当前展示的广告是下载插页广告,广告ID--\(loadInterstitialAd?.adUnitID ?? "")")
|
||||
loadInterstitialAd?.paidEventHandler = { adValue in
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(switchInterstitialAd?.responseInfo) {
|
||||
loadInterstitialAd?.paidEventHandler = { adValue in
|
||||
if let response = self.loadInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.dl_ads_showSuccessAction(response, adValue: adValue)
|
||||
}
|
||||
}
|
||||
}else {
|
||||
if let response = self.loadInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.dl_ads_showSuccessAction(response, adValue: adValue)
|
||||
MP_AnalyticsManager.shared.dl_ads_showSuccessAction(response, adValue: .init())
|
||||
}
|
||||
}
|
||||
}else if ad === libraryInterstitialAd {//曲库插页广告
|
||||
print("当前展示的广告是曲库插页广告,广告ID--\(libraryInterstitialAd?.adUnitID ?? "")")
|
||||
libraryInterstitialAd?.paidEventHandler = { adValue in
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(switchInterstitialAd?.responseInfo) {
|
||||
libraryInterstitialAd?.paidEventHandler = { adValue in
|
||||
if let response = self.libraryInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.listclk_ads_showSuccessAction(response, adValue: adValue)
|
||||
}
|
||||
}
|
||||
}else {
|
||||
if let response = self.libraryInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.listclk_ads_showSuccessAction(response, adValue: adValue)
|
||||
MP_AnalyticsManager.shared.listclk_ads_showSuccessAction(response, adValue: .init())
|
||||
}
|
||||
}
|
||||
}else if ad === globalInterstitialAd {//全局插页广告
|
||||
|
||||
@ -54,6 +54,8 @@ class MP_AnalyticsManager: NSObject {
|
||||
private let player_b_success_action = "player_b_success_action"
|
||||
//播放失败
|
||||
private let player_b_failure_error = "player_b_failure_error"
|
||||
//资源获取失败
|
||||
private let player_resource_failure = "player_resource_failure"
|
||||
//点击收藏
|
||||
private let player_b_love_click = "player_b_love_click"
|
||||
//取消收藏
|
||||
@ -64,6 +66,7 @@ class MP_AnalyticsManager: NSObject {
|
||||
private let player_b_downloadsuccess_action = "player_b_downloadsuccess_action"
|
||||
//资源下载失败
|
||||
private let player_b_downloadfailure_error = "player_b_downloadfailure_error"
|
||||
|
||||
//B面搜索曝光
|
||||
private let search_pv = "search_pv"
|
||||
//如何进入搜索结果页
|
||||
@ -138,7 +141,7 @@ class MP_AnalyticsManager: NSObject {
|
||||
if array.isEmpty == false, let data = coreAdModelforJson(array) {
|
||||
UserDefaults.standard.removeObject(forKey: key)
|
||||
//重新更新内容
|
||||
print("Reload--\(key)")
|
||||
print("\(key)---IDs:\(array.count)")
|
||||
UserDefaults.standard.set(data, forKey: key)
|
||||
}
|
||||
}
|
||||
@ -339,6 +342,11 @@ class MP_AnalyticsManager: NSObject {
|
||||
"error":error
|
||||
])
|
||||
}
|
||||
///资源获取失败
|
||||
func player_resource_failureAction(_ code:String) {
|
||||
Analytics.logEvent(player_resource_failure, parameters: ["area_code":code])
|
||||
}
|
||||
|
||||
///点击收藏
|
||||
/// - Parameters:
|
||||
/// - videoid: 音乐id
|
||||
@ -540,20 +548,13 @@ class MP_AnalyticsManager: NSObject {
|
||||
"CS_CURRENCY":adValue.currencyCode,
|
||||
"CS_VALUE":priceString,
|
||||
"CS_STATUS":isOLD ? "Old":"New"]
|
||||
//同时执行当前活跃会话的总价格和总次数更新
|
||||
if var totalPrices = UserDefaults.standard.array(forKey: "Session_TotalPrices") as? [Double] {
|
||||
print("更新了当前活跃会话的广告总次数和总价值")
|
||||
totalPrices.append(price)
|
||||
UserDefaults.standard.set(totalPrices, forKey: "Session_TotalPrices")
|
||||
}else {
|
||||
print("更新了当前活跃会话的广告总次数和总价值")
|
||||
//没有这个数据
|
||||
var array:[Double] = []
|
||||
array.append(price)
|
||||
UserDefaults.standard.set(array, forKey: "Session_TotalPrices")
|
||||
}
|
||||
return parameters
|
||||
}
|
||||
///检索广告来源
|
||||
func infoFromAdMobSource(_ responseInfo:GADResponseInfo?) -> Bool {
|
||||
guard let responseInfo = responseInfo else {return false}
|
||||
return (responseInfo.loadedAdNetworkResponseInfo?.adSourceInstanceName ?? "").contains("AdMob")
|
||||
}
|
||||
|
||||
//价格转化(全部转化为美元)
|
||||
private func valueToUSD(_ adValue:GADAdValue) -> Double {
|
||||
@ -765,28 +766,6 @@ class MP_AnalyticsManager: NSObject {
|
||||
print("列表原生成功展示信息--\(parameters)")
|
||||
Analytics.logEvent(list_ads_show, parameters: parameters)
|
||||
}
|
||||
///对总价值的价格上报事件
|
||||
func ad_session_total_valueAction() {
|
||||
//取出当前活跃次数总价值以及对应数据
|
||||
if let totalPrices = UserDefaults.standard.array(forKey: "Session_TotalPrices") as? [Double] {
|
||||
//成功获取了总价值与总次数
|
||||
var totalPrice:Double = 0
|
||||
totalPrices.forEach { item in
|
||||
totalPrice += item
|
||||
}
|
||||
let priceString = String(format: "%.5f", totalPrices)
|
||||
let count = totalPrices.count
|
||||
let currentTime = getCurrentLosAngelesTime()
|
||||
let parameters:[String:Any] = ["session_currentTime":currentTime,
|
||||
"session_totalPrice":priceString,
|
||||
"session_totalNumber":count]
|
||||
print("当前活跃会话总价值--\(parameters)")
|
||||
//发布事件
|
||||
Analytics.logEvent(ad_session_total_value, parameters: parameters)
|
||||
//清理当前活跃会话广告总价值
|
||||
UserDefaults.standard.removeObject(forKey: "Session_TotalPrices")
|
||||
}
|
||||
}
|
||||
//获取太平洋洛杉矶时间
|
||||
func getCurrentLosAngelesTime() -> String {
|
||||
// 获取当前日期和时间
|
||||
|
||||
@ -285,7 +285,6 @@ extension MP_IAPManager: SKProductsRequestDelegate, SKPaymentTransactionObserver
|
||||
|
||||
do {
|
||||
if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
|
||||
print("Receipt validation response: \(jsonResponse)")
|
||||
if let status = jsonResponse["status"] as? Int {
|
||||
if status == 0 {
|
||||
completion(true)
|
||||
@ -339,8 +338,6 @@ extension MP_IAPManager: SKProductsRequestDelegate, SKPaymentTransactionObserver
|
||||
}
|
||||
do {
|
||||
if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
|
||||
print("Sandbox receipt validation response: \(jsonResponse)")
|
||||
|
||||
if let status = jsonResponse["status"] as? Int, status == 0 {
|
||||
completion(true)
|
||||
} else {
|
||||
|
||||
@ -2092,6 +2092,9 @@ extension MP_NetWorkManager {
|
||||
parsingAndroidPlayerStreamingData(streamingData){ videos,itags,mimeType in
|
||||
completion((videos,itags,mimeType),infos)
|
||||
}
|
||||
}else {
|
||||
MP_HUD.error("Failed to obtain resource, please try again later", delay: 1.0, completion: nil)
|
||||
MP_AnalyticsManager.shared.player_resource_failureAction(locaton ?? "HK")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -143,7 +143,7 @@ class MP_PlayerManager:NSObject{
|
||||
}
|
||||
}
|
||||
//是否因为广告原因延迟了播放(当广告加载时,延迟播放器状态切换)
|
||||
var isAdLate:Bool?{
|
||||
var isAdLate:Bool? = false{
|
||||
didSet{
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()) {
|
||||
[weak self] in
|
||||
@ -370,6 +370,8 @@ class MP_PlayerManager:NSObject{
|
||||
}else {
|
||||
player.play()
|
||||
}
|
||||
}else {
|
||||
|
||||
}
|
||||
//暂停计时器,并获取延时值
|
||||
suspendTimer()
|
||||
|
||||
@ -37,6 +37,7 @@ class MPPositive_BaseViewController: MP_BaseViewController, UIGestureRecognizerD
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(errorAction(_ :)), notificationName: .netWork_error_deal)
|
||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(switchCurrentVideoAction(_ :)), notificationName: .positive_player_reload)
|
||||
}
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
@ -161,5 +162,21 @@ class MPPositive_BaseViewController: MP_BaseViewController, UIGestureRecognizerD
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
///当用户切换了歌曲后
|
||||
@objc private func switchCurrentVideoAction(_ notification:Notification) {
|
||||
DispatchQueue.main.async {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
//检索当前View内部是否存在tableView
|
||||
view.subviews.forEach { item in
|
||||
if item is UITableView {
|
||||
let tableView = item as? UITableView
|
||||
tableView?.reloadData()
|
||||
}else if item is UICollectionView {
|
||||
let collectionView = item as? UICollectionView
|
||||
collectionView?.reloadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ class MPPositive_TabBarController: UITabBarController, UIViewControllerTransitio
|
||||
}
|
||||
//是否Push
|
||||
private var isPush:Bool = false
|
||||
var pushPlayerBlock:(() -> Void)?
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.setValue(customTabBar, forKey: "tabBar")
|
||||
@ -94,28 +95,38 @@ extension MPPositive_TabBarController {
|
||||
@objc private func pupPlayerAction() {
|
||||
MP_AdMobManager.shared.showPlayInterstitialAdIfAvailable { [weak self] ad in
|
||||
guard let self = self else {return}
|
||||
//判断音乐播放器是否已经播放
|
||||
MP_AdMobManager.shared.isShowingPlayInterstitialAd = true
|
||||
//播放器还未播放,可以弹出广告
|
||||
MP_AdMobManager.shared.setInterstitialSwitch(true)
|
||||
ad.fullScreenContentDelegate = self
|
||||
ad.present(fromRootViewController: self)
|
||||
if let ad = ad {
|
||||
//判断音乐播放器是否已经播放
|
||||
MP_AdMobManager.shared.isShowingPlayInterstitialAd = true
|
||||
//播放器还未播放,可以弹出广告
|
||||
MP_AdMobManager.shared.setInterstitialSwitch(true)
|
||||
ad.fullScreenContentDelegate = self
|
||||
ad.present(fromRootViewController: self)
|
||||
}else {
|
||||
if let block = self.pushPlayerBlock {
|
||||
block()
|
||||
}
|
||||
}
|
||||
}
|
||||
//执行加载播放器页面
|
||||
DispatchQueue.main.async {
|
||||
//赋予block任务块
|
||||
self.pushPlayerBlock = {
|
||||
[weak self] in
|
||||
let playerVC = MPPositive_PlayerViewController()
|
||||
playerVC.modalPresentationStyle = .fullScreen
|
||||
playerVC.recommendBlock = {
|
||||
let recommendVC = MPPositive_RecommendViewController(MP_PlayerManager.shared.loadPlayer?.currentVideo?.song.relatedID ?? "")
|
||||
self?.viewControllers![self?.selectedIndex ?? 0].children[0].navigationController?.pushViewController(recommendVC, animated: false)
|
||||
//执行加载播放器页面
|
||||
DispatchQueue.main.async {
|
||||
[weak self] in
|
||||
let playerVC = MPPositive_PlayerViewController()
|
||||
playerVC.modalPresentationStyle = .fullScreen
|
||||
playerVC.recommendBlock = {
|
||||
let recommendVC = MPPositive_RecommendViewController(MP_PlayerManager.shared.loadPlayer?.currentVideo?.song.relatedID ?? "")
|
||||
self?.viewControllers![self?.selectedIndex ?? 0].children[0].navigationController?.pushViewController(recommendVC, animated: false)
|
||||
}
|
||||
playerVC.searchBlock = { (text) in
|
||||
MP_AnalyticsManager.shared.search_from_actionAction("player page")
|
||||
let resultVC = MPPositive_SearchResultShowViewController(text, isShowAd: false)
|
||||
self?.viewControllers![self?.selectedIndex ?? 0].children[0].navigationController?.pushViewController(resultVC, animated: false)
|
||||
}
|
||||
self?.present(playerVC, animated: true)
|
||||
}
|
||||
playerVC.searchBlock = { (text) in
|
||||
MP_AnalyticsManager.shared.search_from_actionAction("player page")
|
||||
let resultVC = MPPositive_SearchResultShowViewController(text, isShowAd: false)
|
||||
self?.viewControllers![self?.selectedIndex ?? 0].children[0].navigationController?.pushViewController(resultVC, animated: false)
|
||||
}
|
||||
self?.present(playerVC, animated: true)
|
||||
}
|
||||
}
|
||||
//切换底部音乐模块状态
|
||||
@ -167,9 +178,15 @@ extension MPPositive_TabBarController {
|
||||
// UIApplication.shared.isStatusBarHidden = true
|
||||
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
||||
print("当前展示的广告是播放插页广告,广告ID--\(MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? "")")
|
||||
MP_AdMobManager.shared.playInterstitialAd?.paidEventHandler = { adValue in
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(MP_AdMobManager.shared.playInterstitialAd?.responseInfo) {
|
||||
MP_AdMobManager.shared.playInterstitialAd?.paidEventHandler = { adValue in
|
||||
if let response = MP_AdMobManager.shared.playInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.play_ads_showSuccessAction(response, adValue: adValue)
|
||||
}
|
||||
}
|
||||
}else {
|
||||
if let response = MP_AdMobManager.shared.playInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.play_ads_showSuccessAction(response, adValue: adValue)
|
||||
MP_AnalyticsManager.shared.play_ads_showSuccessAction(response, adValue: .init())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,16 +202,8 @@ extension MPPositive_TabBarController {
|
||||
if MP_AdMobManager.shared.completePlayInterstitialAdBlock != nil {
|
||||
MP_AdMobManager.shared.completePlayInterstitialAdBlock!()
|
||||
}
|
||||
//执行加载播放器页面
|
||||
DispatchQueue.main.async {
|
||||
[weak self] in
|
||||
let playerVC = MPPositive_PlayerViewController()
|
||||
playerVC.modalPresentationStyle = .fullScreen
|
||||
playerVC.recommendBlock = {
|
||||
let recommendVC = MPPositive_RecommendViewController(MP_PlayerManager.shared.loadPlayer.currentVideo.song.relatedID)
|
||||
self?.viewControllers![self?.selectedIndex ?? 0].children[0].navigationController?.pushViewController(recommendVC, animated: false)
|
||||
}
|
||||
self?.present(playerVC, animated: true)
|
||||
if let block = self.pushPlayerBlock {
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -102,6 +102,10 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
|
||||
MP_HUD.loading()
|
||||
}
|
||||
MP_AdMobManager.shared.configureLibraryNativeAd(rootController: self)
|
||||
MP_AdMobManager.shared.loadLibraryNativeAd()
|
||||
//加载搜索原生广告
|
||||
MP_AdMobManager.shared.configureSreachNativeAd(rootController: self)
|
||||
MP_AdMobManager.shared.loadSearchNativeAd()
|
||||
errorBlock = {
|
||||
[weak self] in
|
||||
guard let self = self else {
|
||||
@ -454,102 +458,96 @@ extension MPPositive_HomeViewController: UITableViewDataSource, UITableViewDeleg
|
||||
}
|
||||
|
||||
func numberOfSections(in tableView: UITableView) -> Int {
|
||||
if MPPositive_BrowseLoadViewModel.shared.libraryList.libraryViewModels.isEmpty {
|
||||
return 1
|
||||
}else {
|
||||
return 2
|
||||
}
|
||||
return 1
|
||||
}
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if MPPositive_BrowseLoadViewModel.shared.libraryList.libraryViewModels.isEmpty {
|
||||
return MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count
|
||||
}else {
|
||||
switch section {
|
||||
case 0:
|
||||
return 1
|
||||
default:
|
||||
return MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count
|
||||
}
|
||||
}
|
||||
return MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count + 1
|
||||
}
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
switch indexPath.section {
|
||||
case 0:
|
||||
switch indexPath.row {
|
||||
case 1:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeLibraryListstableViewCellID, for: indexPath) as! MPPositive_HomeLibraryListstableViewCell
|
||||
cell.libraryViewModels = MPPositive_BrowseLoadViewModel.shared.libraryList.libraryViewModels
|
||||
return cell
|
||||
default:
|
||||
if let first = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.row].items.first, first.browseItem.itemType == .single, (first.browseItem.pageType == "MUSIC_VIDEO_TYPE_ATV" || first.browseItem.pageType == "MUSIC_VIDEO_TYPE_UGC") {
|
||||
//是单曲
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeSinglesTableViewCellID, for: indexPath) as! MPPositive_HomeSinglesTableViewCell
|
||||
cell.browseViewModel = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.row]
|
||||
return cell
|
||||
}else {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeShowTableViewCellID, for: indexPath) as! MPPositive_HomeShowTableViewCell
|
||||
cell.browseViewModel = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.row]
|
||||
if let first = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.row].items.first, first.browseItem.itemType == .single, first.browseItem.pageType == "MUSIC_VIDEO_TYPE_OMV" {
|
||||
cell.showType = .Fifth
|
||||
let row:Int = indexPath.row == 0 ? 0:(indexPath.row-1)
|
||||
if row < MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count {
|
||||
if let first = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[row].items.first, first.browseItem.itemType == .single, (first.browseItem.pageType == "MUSIC_VIDEO_TYPE_ATV" || first.browseItem.pageType == "MUSIC_VIDEO_TYPE_UGC") {
|
||||
//是单曲
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeSinglesTableViewCellID, for: indexPath) as! MPPositive_HomeSinglesTableViewCell
|
||||
cell.browseViewModel = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[row]
|
||||
return cell
|
||||
}else {
|
||||
//判断是列表还是艺术家
|
||||
if MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.row].items.first?.browseItem.pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
||||
cell.showType = .Fourth
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeShowTableViewCellID, for: indexPath) as! MPPositive_HomeShowTableViewCell
|
||||
cell.browseViewModel = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[row]
|
||||
if let first = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[row].items.first, first.browseItem.itemType == .single, first.browseItem.pageType == "MUSIC_VIDEO_TYPE_OMV" {
|
||||
cell.showType = .Fifth
|
||||
}else {
|
||||
cell.showType = .Third
|
||||
}
|
||||
}
|
||||
cell.requestNextBlock = {
|
||||
[weak self] (item) in
|
||||
guard let self = self else {return}
|
||||
MP_AnalyticsManager.shared.home_b_module_clickAction(item.browseItem.pageType ?? "")
|
||||
switch item.browseItem.itemType {
|
||||
case .single:
|
||||
//单曲/视频跳转
|
||||
MPPositive_Debouncer.shared.call {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||||
MP_HUD.text("Weak connection.", delay: 2.0, completion: nil)
|
||||
return
|
||||
}
|
||||
MP_AnalyticsManager.shared.song_clickAction("Home")
|
||||
//优先清除数据
|
||||
MP_PlayerManager.shared.loadPlayer = nil
|
||||
//弹出播放器
|
||||
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
|
||||
MP_AnalyticsManager.shared.player_b_impAction()
|
||||
//触发next请求,优先获取列表全部单曲基础数据(不完善)
|
||||
MP_NetWorkManager.shared.requestNextList(item.browseItem.playListId ?? "", videoId: item.browseItem.videoId ?? "", clickTrackingParams: item.browseItem.clickTrackingParams){ [weak self] listSongs in
|
||||
guard let self = self else {return}
|
||||
//回掉的数据并不完善,生成一个playerloadViewModel
|
||||
let lodaViewModel = MPPositive_PlayerLoadViewModel(listSongs, currentVideoId: item.browseItem.videoId ?? "")
|
||||
lodaViewModel.improveData(item.browseItem.videoId ?? "")
|
||||
//更改播放器播放类型
|
||||
MP_PlayerManager.shared.setPlayType(.normal)
|
||||
MP_PlayerManager.shared.loadPlayer = lodaViewModel
|
||||
MP_AnalyticsManager.shared.player_b_listAction()
|
||||
}
|
||||
//判断是列表还是艺术家
|
||||
if MPPositive_BrowseLoadViewModel.shared.browseModuleLists[row].items.first?.browseItem.pageType == "MUSIC_PAGE_TYPE_ARTIST" {
|
||||
cell.showType = .Fourth
|
||||
}else {
|
||||
cell.showType = .Third
|
||||
}
|
||||
case .list:
|
||||
isFirstAppearance = false
|
||||
//列表专辑
|
||||
let listVC = MPPositive_ListShowViewController(item.browseItem.browseId ?? "", params: "", title: item.title ?? "", subtitle: item.subtitle ?? "", clickTrackingParams: item.browseItem.clickTrackingParams ?? "")
|
||||
navigationController?.pushViewController(listVC, animated: true)
|
||||
case .artist:
|
||||
isFirstAppearance = false
|
||||
//前往艺术家页面
|
||||
let artistVC = MPPositive_ArtistShowViewController(item.browseItem.artistId ?? "", clickTrackingParams: item.browseItem.clickTrackingParams ?? "")
|
||||
navigationController?.pushViewController(artistVC, animated: true)
|
||||
default:
|
||||
break
|
||||
}
|
||||
cell.requestNextBlock = {
|
||||
[weak self] (item) in
|
||||
guard let self = self else {return}
|
||||
MP_AnalyticsManager.shared.home_b_module_clickAction(item.browseItem.pageType ?? "")
|
||||
switch item.browseItem.itemType {
|
||||
case .single:
|
||||
//单曲/视频跳转
|
||||
MPPositive_Debouncer.shared.call {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||||
MP_HUD.text("Weak connection.", delay: 2.0, completion: nil)
|
||||
return
|
||||
}
|
||||
MP_AnalyticsManager.shared.song_clickAction("Home")
|
||||
//优先清除数据
|
||||
MP_PlayerManager.shared.loadPlayer = nil
|
||||
//弹出播放器
|
||||
NotificationCenter.notificationKey.post(notificationName: .pup_player_vc)
|
||||
MP_AnalyticsManager.shared.player_b_impAction()
|
||||
//触发next请求,优先获取列表全部单曲基础数据(不完善)
|
||||
MP_NetWorkManager.shared.requestNextList(item.browseItem.playListId ?? "", videoId: item.browseItem.videoId ?? "", clickTrackingParams: item.browseItem.clickTrackingParams){ [weak self] listSongs in
|
||||
guard let self = self else {return}
|
||||
//回掉的数据并不完善,生成一个playerloadViewModel
|
||||
let lodaViewModel = MPPositive_PlayerLoadViewModel(listSongs, currentVideoId: item.browseItem.videoId ?? "")
|
||||
lodaViewModel.improveData(item.browseItem.videoId ?? "")
|
||||
//更改播放器播放类型
|
||||
MP_PlayerManager.shared.setPlayType(.normal)
|
||||
MP_PlayerManager.shared.loadPlayer = lodaViewModel
|
||||
MP_AnalyticsManager.shared.player_b_listAction()
|
||||
}
|
||||
}
|
||||
case .list:
|
||||
isFirstAppearance = false
|
||||
//列表专辑
|
||||
let listVC = MPPositive_ListShowViewController(item.browseItem.browseId ?? "", params: "", title: item.title ?? "", subtitle: item.subtitle ?? "", clickTrackingParams: item.browseItem.clickTrackingParams ?? "")
|
||||
navigationController?.pushViewController(listVC, animated: true)
|
||||
case .artist:
|
||||
isFirstAppearance = false
|
||||
//前往艺术家页面
|
||||
let artistVC = MPPositive_ArtistShowViewController(item.browseItem.artistId ?? "", clickTrackingParams: item.browseItem.clickTrackingParams ?? "")
|
||||
navigationController?.pushViewController(artistVC, animated: true)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
cell.findMoreBlock = {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
isFirstAppearance = false
|
||||
let moreVC = MPPositive_MoreContentViewController(MPPositive_BrowseLoadViewModel.shared.browseModuleLists[row])
|
||||
navigationController?.pushViewController(moreVC, animated: true)
|
||||
}
|
||||
return cell
|
||||
}
|
||||
cell.findMoreBlock = {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
isFirstAppearance = false
|
||||
let moreVC = MPPositive_MoreContentViewController(MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.row])
|
||||
navigationController?.pushViewController(moreVC, animated: true)
|
||||
}
|
||||
}else {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeLibraryListstableViewCellID, for: indexPath) as! MPPositive_HomeLibraryListstableViewCell
|
||||
cell.libraryViewModels = MPPositive_BrowseLoadViewModel.shared.libraryList.libraryViewModels
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,6 +212,7 @@ class MPPositive_SearchResultShowViewController: MPPositive_BaseViewController,
|
||||
searchText = ""
|
||||
suggestionView.suggestions = nil
|
||||
resultsShowView.loadModel = nil
|
||||
historyView.isHidden = false
|
||||
}
|
||||
//取消并返回上一页
|
||||
@objc private func backPopClick(_ sender:UIButton) {
|
||||
@ -235,6 +236,7 @@ extension MPPositive_SearchResultShowViewController:UITextFieldDelegate {
|
||||
if text.isEmpty {
|
||||
self.suggestionList = nil
|
||||
cancelDebounceTimer()
|
||||
historyView.isHidden = false
|
||||
}else {
|
||||
//触发网络请求
|
||||
loadSearchSuggestions(text)
|
||||
|
||||
@ -33,9 +33,6 @@ class MPPositive_SearchViewController: MPPositive_BaseViewController {
|
||||
super.viewDidLoad()
|
||||
setTitle("")
|
||||
configure()
|
||||
//加载搜索原生广告
|
||||
MP_AdMobManager.shared.configureSreachNativeAd(rootController: self)
|
||||
MP_AdMobManager.shared.loadSearchNativeAd()
|
||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(grideReloadAction(_ :)), notificationName: .search_gride_reload)
|
||||
}
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
//
|
||||
// MPPositive_BaseShowView.swift
|
||||
// relax.offline.mp3.music
|
||||
//
|
||||
// Created by Mr.Zhou on 2024/8/9.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class MPPositive_BaseShowView: UIView {
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(switchCurrentVideoAction(_ :)), notificationName: .positive_player_reload)
|
||||
}
|
||||
///当用户切换了歌曲后
|
||||
@objc private func switchCurrentVideoAction(_ notification:Notification) {
|
||||
DispatchQueue.main.async {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
//检索当前View内部是否存在tableView
|
||||
subviews.forEach { item in
|
||||
if item is UITableView {
|
||||
let tableView = item as? UITableView
|
||||
tableView?.reloadData()
|
||||
}else if item is UICollectionView {
|
||||
let collectionView = item as? UICollectionView
|
||||
collectionView?.reloadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
}
|
||||
deinit{
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,7 @@ class MPPositive_ArtistShowSongTableViewCell: UITableViewCell, PKDownloadButtonD
|
||||
imageView.layer.masksToBounds = true
|
||||
return imageView
|
||||
}()
|
||||
private lazy var maskImageView:MP_WaveAnimationMaskView = .init(frame: .init(x: 0, y: 0, width: 24*width, height: 24*width), cornerRadius: 10*width)
|
||||
private lazy var titleLabel:UILabel = createLabel(font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left)
|
||||
private lazy var subtitleLabel:UILabel = createLabel(font: .systemFont(ofSize: 12*width, weight: .regular), textColor: .init(hex: "#FFFFFF", alpha: 0.6), textAlignment: .left)
|
||||
///更多按钮
|
||||
@ -54,6 +55,15 @@ class MPPositive_ArtistShowSongTableViewCell: UITableViewCell, PKDownloadButtonD
|
||||
titleLabel.text = itemView.title
|
||||
subtitleLabel.text = itemView.subtitle
|
||||
setProgress(itemView.browseItem.videoId ?? "")
|
||||
if (itemView?.browseItem.videoId == MP_PlayerManager.shared.loadPlayer?.currentVideo?.song?.videoId) {
|
||||
titleLabel.textColor = greenTextColor
|
||||
maskImageView.isHidden = false
|
||||
maskImageView.startAnimation()
|
||||
}else {
|
||||
titleLabel.textColor = .white
|
||||
maskImageView.isHidden = true
|
||||
maskImageView.stopAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,6 +112,14 @@ class MPPositive_ArtistShowSongTableViewCell: UITableViewCell, PKDownloadButtonD
|
||||
make.bottom.equalToSuperview().offset(-8*width)
|
||||
make.left.equalToSuperview().offset(18*width)
|
||||
}
|
||||
contentView.addSubview(maskImageView)
|
||||
maskImageView.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(iconImageView)
|
||||
make.center.equalTo(iconImageView)
|
||||
}
|
||||
maskImageView.configure()
|
||||
maskImageView.isHidden = true
|
||||
maskImageView.stopAnimation()
|
||||
contentView.addSubview(moreBtn)
|
||||
moreBtn.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(24*width)
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class MPPositive_HomeSingleCollectionViewCell: UICollectionViewCell {
|
||||
import DownloadButton
|
||||
class MPPositive_HomeSingleCollectionViewCell: UICollectionViewCell, PKDownloadButtonDelegate {
|
||||
///封面图片
|
||||
private lazy var coverImageView:UIImageView = {
|
||||
let imageView:UIImageView = .init()
|
||||
@ -16,6 +16,7 @@ class MPPositive_HomeSingleCollectionViewCell: UICollectionViewCell {
|
||||
imageView.layer.cornerRadius = 10*width
|
||||
return imageView
|
||||
}()
|
||||
private lazy var maskImageView:MP_WaveAnimationMaskView = .init(frame: .init(x: 0, y: 0, width: 24*width, height: 24*width), cornerRadius: 10*width)
|
||||
///标题
|
||||
private lazy var titleLabel:UILabel = createLabel(font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left)
|
||||
///副标题
|
||||
@ -27,19 +28,62 @@ class MPPositive_HomeSingleCollectionViewCell: UICollectionViewCell {
|
||||
btn.addTarget(self, action: #selector(moreActionClick(_ :)), for: .touchUpInside)
|
||||
return btn
|
||||
}()
|
||||
///下载按钮
|
||||
private lazy var dowloadBtn:PKDownloadButton = {
|
||||
let btn:PKDownloadButton = .init()
|
||||
//开始下载状态
|
||||
btn.startDownloadButton.cleanDefaultAppearance()
|
||||
btn.startDownloadButton.setBackgroundImage(UIImage(named: "Song_Unload'logo"), for: .normal)
|
||||
//下载结束状态
|
||||
btn.downloadedButton.setBackgroundImage(UIImage(named: "Song_Loaded'logo"), for: .normal)
|
||||
btn.downloadedButton.setAttributedTitle(nil, for: .normal)
|
||||
//停止下载状态
|
||||
btn.stopDownloadButton.stopButton.setImage(UIImage(named: "download"), for: .normal)
|
||||
btn.stopDownloadButton.tintColor = UIColor(hex: "#80F988")
|
||||
btn.stopDownloadButton.stopButtonWidth = 2
|
||||
btn.stopDownloadButton.filledLineWidth = 3*width
|
||||
btn.stopDownloadButton.filledLineStyleOuter = true
|
||||
|
||||
//加载状态设置
|
||||
btn.pendingView.tintColor = UIColor(hex: "#80F988")
|
||||
btn.pendingView.radius = 12*width
|
||||
btn.pendingView.emptyLineRadians = 2*width
|
||||
btn.pendingView.spinTime = 3
|
||||
btn.delegate = self
|
||||
return btn
|
||||
}()
|
||||
var moreBlock:(() -> Void)?
|
||||
//删除
|
||||
var deleteBlock:(() -> Void)?
|
||||
//取消
|
||||
var cancelBlock:(() -> Void)?
|
||||
var itemViewModel:MPPositive_BrowseItemViewModel!{
|
||||
didSet{
|
||||
itemViewModel.setUrltoImage(coverImageView)
|
||||
titleLabel.text = itemViewModel.title
|
||||
subtitleLabel.text = itemViewModel.subtitle
|
||||
itemViewModel?.setUrltoImage(coverImageView)
|
||||
titleLabel.text = itemViewModel?.title
|
||||
subtitleLabel.text = itemViewModel?.subtitle
|
||||
setProgress(itemViewModel?.browseItem.videoId ?? "")
|
||||
if (itemViewModel?.browseItem.videoId == MP_PlayerManager.shared.loadPlayer?.currentVideo?.song?.videoId) {
|
||||
titleLabel.textColor = greenTextColor
|
||||
maskImageView.isHidden = false
|
||||
maskImageView.startAnimation()
|
||||
}else {
|
||||
titleLabel.textColor = .white
|
||||
maskImageView.isHidden = true
|
||||
maskImageView.stopAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
//注册通知
|
||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(downloadProgressAction(_ :)), notificationName: .download_progress_source)
|
||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(downloadEndAction(_ :)), notificationName: .dowload_end_source)
|
||||
confirgue()
|
||||
}
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
}
|
||||
@ -53,17 +97,31 @@ class MPPositive_HomeSingleCollectionViewCell: UICollectionViewCell {
|
||||
make.left.equalToSuperview().offset(18*width)
|
||||
make.centerY.equalToSuperview()
|
||||
}
|
||||
addSubview(maskImageView)
|
||||
maskImageView.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(coverImageView)
|
||||
make.center.equalTo(coverImageView)
|
||||
}
|
||||
maskImageView.configure()
|
||||
maskImageView.isHidden = true
|
||||
maskImageView.stopAnimation()
|
||||
addSubview(moreBtn)
|
||||
moreBtn.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(24*width)
|
||||
make.centerY.equalTo(coverImageView.snp.centerY)
|
||||
make.right.equalToSuperview().offset(-5*width)
|
||||
}
|
||||
addSubview(dowloadBtn)
|
||||
dowloadBtn.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(24*width)
|
||||
make.centerY.equalTo(moreBtn.snp.centerY)
|
||||
make.right.equalTo(moreBtn.snp.left).offset(-8*width)
|
||||
}
|
||||
addSubview(titleLabel)
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.top.equalTo(coverImageView.snp.top).offset(10*width)
|
||||
make.left.equalTo(coverImageView.snp.right).offset(12*width)
|
||||
make.right.equalTo(moreBtn.snp.left).offset(-12*width)
|
||||
make.right.equalTo(dowloadBtn.snp.left).offset(-12*width)
|
||||
}
|
||||
addSubview(subtitleLabel)
|
||||
subtitleLabel.snp.makeConstraints { make in
|
||||
@ -71,6 +129,19 @@ class MPPositive_HomeSingleCollectionViewCell: UICollectionViewCell {
|
||||
make.left.right.equalTo(titleLabel)
|
||||
}
|
||||
}
|
||||
//收到progress加载
|
||||
@objc private func downloadProgressAction(_ sender:Notification) {
|
||||
if let dict = sender.object as? [String:String], let videoId = dict["videoId"], let currentVideoId = itemViewModel?.browseItem.videoId, videoId == currentVideoId {
|
||||
//比较当前videoId
|
||||
setProgress(videoId)
|
||||
}
|
||||
}
|
||||
//收到下载结束
|
||||
@objc private func downloadEndAction(_ sender:Notification) {
|
||||
if let dict = sender.object as? [String:String], let videoId = dict["videoId"], let currentVideoId = itemViewModel?.browseItem.videoId, videoId == currentVideoId {
|
||||
setProgress(videoId)
|
||||
}
|
||||
}
|
||||
//点击更多
|
||||
@objc private func moreActionClick(_ sender:UIButton) {
|
||||
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||||
@ -82,4 +153,122 @@ class MPPositive_HomeSingleCollectionViewCell: UICollectionViewCell {
|
||||
}
|
||||
moreBlock!()
|
||||
}
|
||||
//根据输入videoId检索是否下载
|
||||
func setProgress(_ videoId:String) {
|
||||
guard videoId.isEmpty == false, videoId == itemViewModel?.browseItem.videoId else {
|
||||
DispatchQueue.main.async {
|
||||
//未加入下载队列
|
||||
self.dowloadBtn.state = .startDownload
|
||||
}
|
||||
return
|
||||
}
|
||||
MP_DownloadManager.shared.loadQueue.async {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
//判断是否下载完成
|
||||
MP_DownloadManager.shared.isDownloadedFileDocuments(videoId) { statu in
|
||||
if statu == false {
|
||||
//未下载,判断是否加入了下载队列
|
||||
if MP_DownloadManager.shared.isTasksQueue(for: videoId) {
|
||||
//加入下载队列,确定是否活跃下中
|
||||
if MP_DownloadManager.shared.isActiveTask(for: videoId) {
|
||||
DispatchQueue.main.async {
|
||||
self.dowloadBtn.state = .downloading
|
||||
}
|
||||
//活跃中,获取下载值
|
||||
if let progress = MP_DownloadManager.shared.getProgress(for: videoId) {
|
||||
//下载中
|
||||
DispatchQueue.main.async {
|
||||
self.dowloadBtn.stopDownloadButton.progress = progress
|
||||
}
|
||||
}
|
||||
}else {
|
||||
//处于队列中,还未开始下载
|
||||
DispatchQueue.main.async {
|
||||
//未加入下载队列
|
||||
self.dowloadBtn.state = .pending
|
||||
}
|
||||
}
|
||||
}else {
|
||||
//未加入下载队列
|
||||
DispatchQueue.main.async {
|
||||
//未加入下载队列
|
||||
self.dowloadBtn.state = .startDownload
|
||||
}
|
||||
}
|
||||
}else {
|
||||
DispatchQueue.main.async {
|
||||
//已经完成下载
|
||||
self.dowloadBtn.state = .downloaded
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//下载按钮代理
|
||||
func downloadButtonTapped(_ downloadButton: PKDownloadButton!, currentState state: PKDownloadButtonState) {
|
||||
var video:MPPositive_SongItemModel!
|
||||
//根据当前按钮状态确定进度
|
||||
switch state {
|
||||
case .startDownload://开始状态,点击后进入下载状态
|
||||
//检索当前网络状态
|
||||
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||||
MP_HUD.text("Weak connection.", delay: 2.0, completion: nil)
|
||||
return
|
||||
}
|
||||
//检索当前歌曲是否下载过
|
||||
guard let videoId = itemViewModel.browseItem.videoId else {
|
||||
return
|
||||
}
|
||||
//切换为准备状态
|
||||
downloadButton.state = .pending
|
||||
//通过网络请求获取当前预览项资源(转为Song)
|
||||
MP_NetWorkManager.shared.requestNextList("", videoId: videoId, clickTrackingParams: nil){
|
||||
[weak self] listSongs in
|
||||
guard let self = self, let first = listSongs.first else {
|
||||
//获取资源失败
|
||||
self?.setProgress(videoId)
|
||||
return
|
||||
}
|
||||
let group = DispatchGroup()
|
||||
group.enter()
|
||||
improveDataforLycirsAndRelated(first) {(result) in
|
||||
first.lyricsID = result.0
|
||||
first.relatedID = result.1
|
||||
group.leave()
|
||||
}
|
||||
group.enter()
|
||||
//补全资源路径组和封面路径组
|
||||
improveDataforResouceAndCover(first) {(resourceUrls, coverUrls) in
|
||||
if let resourceUrls = resourceUrls {
|
||||
first.resourceUrls = resourceUrls.0
|
||||
first.itags = resourceUrls.1
|
||||
first.mimeTypes = resourceUrls.2
|
||||
}
|
||||
first.coverUrls = coverUrls
|
||||
group.leave()
|
||||
}
|
||||
group.notify(queue: .main, execute: {
|
||||
[weak self] in
|
||||
guard let self = self else {
|
||||
self?.setProgress(videoId)
|
||||
return
|
||||
}
|
||||
video = first
|
||||
//事件打点
|
||||
MP_AnalyticsManager.shared.player_b_download_clickAction(video.videoId, videoname: video.title ?? "", artistname: video.shortBylineText ?? "")
|
||||
//补全了数据,执行下载
|
||||
MP_DownloadManager.shared.prepareVideoDownloadTask(from: video)
|
||||
})
|
||||
}
|
||||
case .downloaded://已下载
|
||||
if let block = deleteBlock {
|
||||
block()
|
||||
}
|
||||
default:
|
||||
if let block = cancelBlock {
|
||||
block()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ class MPPositive_HomeSinglesTableViewCell: UITableViewCell, UIViewControllerTran
|
||||
collectionView.snp.makeConstraints { make in
|
||||
make.top.equalTo(titleLabel.snp.bottom)
|
||||
make.left.right.equalToSuperview()
|
||||
make.bottom.equalToSuperview().offset(-32*width).priority(999)
|
||||
make.bottom.equalToSuperview().offset(-20*width).priority(999)
|
||||
}
|
||||
}
|
||||
//经过计算设置tableViewCell真实高度
|
||||
@ -98,8 +98,7 @@ extension MPPositive_HomeSinglesTableViewCell:UICollectionViewDataSource, UIColl
|
||||
cell.itemViewModel = browseViewModel.items[indexPath.row]
|
||||
cell.moreBlock = {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
let itemView = self.browseViewModel.items[indexPath.row]
|
||||
guard let self = self, let itemView = self.browseViewModel?.items[indexPath.row] else {return}
|
||||
MPPositive_Debouncer.shared.call {
|
||||
MPPositive_ModalType = .MoreOperations
|
||||
let moreVC = MPPositive_MoreSongOperationsViewController(itemView)
|
||||
@ -113,6 +112,44 @@ extension MPPositive_HomeSinglesTableViewCell:UICollectionViewDataSource, UIColl
|
||||
self.parentController()?.present(moreVC, animated: true)
|
||||
}
|
||||
}
|
||||
cell.deleteBlock = {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
//点击删除下载
|
||||
let alertController = UIAlertController(title: "Delete This Song", message: "Are you sure you want to delete the offline resources of this song?", preferredStyle: .alert)
|
||||
let cancel = UIAlertAction(title: "Cancel", style: .cancel)
|
||||
alertController.addAction(cancel)
|
||||
let sure = UIAlertAction(title: "Sure", style: .destructive) {(action) in
|
||||
guard let videoId = self.browseViewModel?.items[indexPath.row].browseItem.videoId else {return}
|
||||
//确定删除
|
||||
MP_DownloadManager.shared.deleteFileDocuments(videoId) { videoId in
|
||||
MP_HUD.progress("Loading...", delay: 0.5) {
|
||||
MP_HUD.text("Removed", delay: 1.0, completion: nil)
|
||||
collectionView.reloadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
alertController.addAction(sure)
|
||||
self.parentController()?.present(alertController, animated: true)
|
||||
}
|
||||
cell.cancelBlock = {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
//点击取消下载
|
||||
let alertController = UIAlertController(title: "Cancel Song Download Task", message: "Are you sure you want to cancel the download task of this song?", preferredStyle: .alert)
|
||||
let cancel = UIAlertAction(title: "Cancel", style: .cancel)
|
||||
alertController.addAction(cancel)
|
||||
let sure = UIAlertAction(title: "Sure", style: .destructive) {(action) in
|
||||
guard let videoId = self.browseViewModel?.items[indexPath.row].browseItem.videoId else {return}
|
||||
//确定取消
|
||||
MP_DownloadManager.shared.cancelDownloadTask(videoId) { videoId in
|
||||
MP_HUD.text("Canceled", delay: 1.0, completion: nil)
|
||||
collectionView.reloadData()
|
||||
}
|
||||
}
|
||||
alertController.addAction(sure)
|
||||
self.parentController()?.present(alertController, animated: true)
|
||||
}
|
||||
return cell
|
||||
}
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
|
||||
@ -17,6 +17,7 @@ class MPPositive_MusicItemShowTableViewCell: UITableViewCell, PKDownloadButtonDe
|
||||
imageView.layer.cornerRadius = 10*width
|
||||
return imageView
|
||||
}()
|
||||
private lazy var maskImageView:MP_WaveAnimationMaskView = .init(frame: .init(x: 0, y: 0, width: 24*width, height: 24*width), cornerRadius: 10*width)
|
||||
///标题
|
||||
private lazy var titleLabel:UILabel = createLabel(font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left)
|
||||
///副标题
|
||||
@ -63,6 +64,15 @@ class MPPositive_MusicItemShowTableViewCell: UITableViewCell, PKDownloadButtonDe
|
||||
subtitleLabel.text = itemView.subtitle
|
||||
rankLabel.isHidden = (itemView.coverUrl != nil)
|
||||
setProgress(itemView.browseItem.videoId ?? "")
|
||||
if (itemView?.browseItem.videoId == MP_PlayerManager.shared.loadPlayer?.currentVideo?.song?.videoId) {
|
||||
titleLabel.textColor = greenTextColor
|
||||
maskImageView.isHidden = false
|
||||
maskImageView.startAnimation()
|
||||
}else {
|
||||
titleLabel.textColor = .white
|
||||
maskImageView.isHidden = true
|
||||
maskImageView.stopAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
var rank:Int = 0 {
|
||||
@ -180,6 +190,14 @@ class MPPositive_MusicItemShowTableViewCell: UITableViewCell, PKDownloadButtonDe
|
||||
make.top.equalToSuperview().offset(8*width).priority(999)
|
||||
make.bottom.equalToSuperview().offset(-8*width).priority(999)
|
||||
}
|
||||
contentView.addSubview(maskImageView)
|
||||
maskImageView.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(coverImageView)
|
||||
make.center.equalTo(coverImageView)
|
||||
}
|
||||
maskImageView.configure()
|
||||
maskImageView.isHidden = true
|
||||
maskImageView.stopAnimation()
|
||||
contentView.addSubview(rankLabel)
|
||||
rankLabel.snp.makeConstraints { make in
|
||||
make.center.equalTo(coverImageView)
|
||||
@ -235,8 +253,6 @@ class MPPositive_MusicItemShowTableViewCell: UITableViewCell, PKDownloadButtonDe
|
||||
guard let videoId = itemView.browseItem.videoId else {
|
||||
return
|
||||
}
|
||||
//未下载
|
||||
// MP_AdMobManager.shared.showLoadInterstitialAdIfAvailable(completion: nil)
|
||||
//切换为准备状态
|
||||
downloadButton.state = .pending
|
||||
//通过网络请求获取当前预览项资源(转为Song)
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
import UIKit
|
||||
import MJRefresh
|
||||
class MPPositive_RecommendShowTypeView: UIView, JXSegmentedListContainerViewListDelegate {
|
||||
class MPPositive_RecommendShowTypeView: MPPositive_BaseShowView, JXSegmentedListContainerViewListDelegate {
|
||||
//tableView
|
||||
private lazy var tableView:UITableView = {
|
||||
let tableView = UITableView()
|
||||
|
||||
@ -108,8 +108,12 @@ extension MPPositive_SearchHistoryView: UICollectionViewDataSource, UICollection
|
||||
return cell
|
||||
}
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
if let text = historys[indexPath.row].text, let block = selectedTagBlock {
|
||||
block(text)
|
||||
MPPositive_Debouncer.shared.call {
|
||||
[weak self] in
|
||||
guard let self = self else {return}
|
||||
if let text = historys[indexPath.row].text, let block = selectedTagBlock {
|
||||
block(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
import UIKit
|
||||
///对搜索预览结果展示
|
||||
class MPPositive_SearchResultPreviewShowView: UIView, JXSegmentedListContainerViewListDelegate {
|
||||
class MPPositive_SearchResultPreviewShowView: MPPositive_BaseShowView, JXSegmentedListContainerViewListDelegate {
|
||||
//tableView
|
||||
private lazy var tableView:UITableView = {
|
||||
let tableView = UITableView()
|
||||
|
||||
@ -17,6 +17,7 @@ class MPPositive_SearchResultShowTableViewCell: UITableViewCell, PKDownloadButto
|
||||
imageView.layer.cornerRadius = 10*width
|
||||
return imageView
|
||||
}()
|
||||
private lazy var maskImageView:MP_WaveAnimationMaskView = .init(frame: .init(x: 0, y: 0, width: 24*width, height: 24*width), cornerRadius: 10*width)
|
||||
private lazy var titleLabel:UILabel = createLabel(font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left)
|
||||
private lazy var subtitleLabel:UILabel = createLabel(font: .systemFont(ofSize: 12*width, weight: .regular), textColor: .init(hex: "#FFFFFF", alpha: 0.6), textAlignment: .left)
|
||||
///更多按钮
|
||||
@ -72,6 +73,15 @@ class MPPositive_SearchResultShowTableViewCell: UITableViewCell, PKDownloadButto
|
||||
titleLabel.text = songViewModel.title
|
||||
subtitleLabel.text = songViewModel.subtitle
|
||||
setProgress(songViewModel.collectionSong.videoId ?? "")
|
||||
if (songViewModel?.collectionSong.videoId == MP_PlayerManager.shared.loadPlayer?.currentVideo?.song?.videoId) {
|
||||
titleLabel.textColor = greenTextColor
|
||||
maskImageView.isHidden = false
|
||||
maskImageView.startAnimation()
|
||||
}else {
|
||||
titleLabel.textColor = .white
|
||||
maskImageView.isHidden = true
|
||||
maskImageView.stopAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
var loadViewModel:MPPositive_DownloadViewModel!{
|
||||
@ -80,6 +90,15 @@ class MPPositive_SearchResultShowTableViewCell: UITableViewCell, PKDownloadButto
|
||||
titleLabel.text = loadViewModel.title
|
||||
subtitleLabel.text = loadViewModel.subtitle
|
||||
setProgress(loadViewModel.loadItem.videoId ?? "")
|
||||
if (loadViewModel?.loadItem.videoId == MP_PlayerManager.shared.loadPlayer?.currentVideo?.song?.videoId) {
|
||||
titleLabel.textColor = greenTextColor
|
||||
maskImageView.isHidden = false
|
||||
maskImageView.startAnimation()
|
||||
}else {
|
||||
titleLabel.textColor = .white
|
||||
maskImageView.isHidden = true
|
||||
maskImageView.stopAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
var videoModel:MPPositive_CustomVideoModel!{
|
||||
@ -88,6 +107,15 @@ class MPPositive_SearchResultShowTableViewCell: UITableViewCell, PKDownloadButto
|
||||
titleLabel.text = videoModel.title
|
||||
subtitleLabel.text = videoModel.subtitle
|
||||
setProgress(videoModel.videoId ?? "")
|
||||
if (videoModel?.videoId == MP_PlayerManager.shared.loadPlayer?.currentVideo?.song?.videoId) {
|
||||
titleLabel.textColor = greenTextColor
|
||||
maskImageView.isHidden = false
|
||||
maskImageView.startAnimation()
|
||||
}else {
|
||||
titleLabel.textColor = .white
|
||||
maskImageView.isHidden = true
|
||||
maskImageView.stopAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,6 +221,14 @@ class MPPositive_SearchResultShowTableViewCell: UITableViewCell, PKDownloadButto
|
||||
make.bottom.equalToSuperview().offset(-8*width)
|
||||
make.left.equalToSuperview().offset(18*width)
|
||||
}
|
||||
contentView.addSubview(maskImageView)
|
||||
maskImageView.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(iconImageView)
|
||||
make.center.equalTo(iconImageView)
|
||||
}
|
||||
maskImageView.configure()
|
||||
maskImageView.isHidden = true
|
||||
maskImageView.stopAnimation()
|
||||
contentView.addSubview(moreBtn)
|
||||
moreBtn.snp.makeConstraints { make in
|
||||
make.width.height.equalTo(24*width)
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
import UIKit
|
||||
import MJRefresh
|
||||
///对搜索结果进行分类详情展示
|
||||
class MPPositive_SearchResultTypeShowView: UIView, JXSegmentedListContainerViewListDelegate, UIViewControllerTransitioningDelegate {
|
||||
class MPPositive_SearchResultTypeShowView: MPPositive_BaseShowView, JXSegmentedListContainerViewListDelegate, UIViewControllerTransitioningDelegate {
|
||||
//tableView
|
||||
private lazy var tableView:UITableView = {
|
||||
let tableView = UITableView()
|
||||
|
||||
@ -12,6 +12,7 @@ class MPSideA_TabBarController: UITabBarController, GADFullScreenContentDelegate
|
||||
private lazy var customTabBar:MPSideA_CustomTabBar = .init(frame: .init(x: 0, y: 0, width: screen_Width, height: 72*width))
|
||||
//底部音乐展示View(默认隐藏)
|
||||
private lazy var bottomView:MPSideA_BottomShowView = .instanceFromNib()
|
||||
var pushPlayerBlock:(() -> Void)?
|
||||
//底部bottomShowView的展示状态
|
||||
private var isbottomShow:Bool = false{
|
||||
willSet{
|
||||
@ -154,19 +155,28 @@ extension MPSideA_TabBarController: UIViewControllerTransitioningDelegate {
|
||||
print("Go to player")
|
||||
MP_AdMobManager.shared.showPlayInterstitialAdIfAvailable { [weak self] ad in
|
||||
guard let self = self else {return}
|
||||
//判断音乐播放器是否已经播放
|
||||
MP_AdMobManager.shared.isShowingPlayInterstitialAd = true
|
||||
//播放器还未播放,可以弹出广告
|
||||
MP_AdMobManager.shared.setInterstitialSwitch(true)
|
||||
ad.fullScreenContentDelegate = self
|
||||
ad.present(fromRootViewController: self)
|
||||
if let ad = ad {
|
||||
//判断音乐播放器是否已经播放
|
||||
MP_AdMobManager.shared.isShowingPlayInterstitialAd = true
|
||||
//播放器还未播放,可以弹出广告
|
||||
MP_AdMobManager.shared.setInterstitialSwitch(true)
|
||||
ad.fullScreenContentDelegate = self
|
||||
ad.present(fromRootViewController: self)
|
||||
}else {
|
||||
if let block = self.pushPlayerBlock {
|
||||
block()
|
||||
}
|
||||
}
|
||||
}
|
||||
//执行加载播放器页面
|
||||
DispatchQueue.main.async {
|
||||
self.pushPlayerBlock = {
|
||||
[weak self] in
|
||||
//模态弹出
|
||||
let playerVC = MPSideA_PlayerViewController()
|
||||
self?.present(playerVC, animated: true)
|
||||
//执行加载播放器页面
|
||||
DispatchQueue.main.async {
|
||||
[weak self] in
|
||||
//模态弹出
|
||||
let playerVC = MPSideA_PlayerViewController()
|
||||
self?.present(playerVC, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
|
||||
@ -261,9 +271,15 @@ extension MPSideA_TabBarController {
|
||||
func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
|
||||
if ad === MP_AdMobManager.shared.playInterstitialAd {//播放插页广告
|
||||
print("当前展示的广告是播放插页广告,广告ID--\(MP_AdMobManager.shared.playInterstitialAd?.adUnitID ?? "")")
|
||||
MP_AdMobManager.shared.playInterstitialAd?.paidEventHandler = { adValue in
|
||||
if MP_AnalyticsManager.shared.infoFromAdMobSource(MP_AdMobManager.shared.playInterstitialAd?.responseInfo) {
|
||||
MP_AdMobManager.shared.playInterstitialAd?.paidEventHandler = { adValue in
|
||||
if let response = MP_AdMobManager.shared.playInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.play_ads_showSuccessAction(response, adValue: adValue)
|
||||
}
|
||||
}
|
||||
}else {
|
||||
if let response = MP_AdMobManager.shared.playInterstitialAd?.responseInfo {
|
||||
MP_AnalyticsManager.shared.play_ads_showSuccessAction(response, adValue: adValue)
|
||||
MP_AnalyticsManager.shared.play_ads_showSuccessAction(response, adValue: .init())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -279,11 +295,8 @@ extension MPSideA_TabBarController {
|
||||
MP_AdMobManager.shared.completePlayInterstitialAdBlock!()
|
||||
}
|
||||
//执行加载播放器页面
|
||||
DispatchQueue.main.async {
|
||||
[weak self] in
|
||||
//模态弹出
|
||||
let playerVC = MPSideA_PlayerViewController()
|
||||
self?.present(playerVC, animated: true)
|
||||
if let block = self.pushPlayerBlock {
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,11 @@ class MPSideA_CenterTableViewCell: UITableViewCell {
|
||||
@IBOutlet weak var coverImageView: UIImageView!
|
||||
@IBOutlet weak var titleLabel: UILabel!
|
||||
@IBOutlet weak var durationLabel: UILabel!
|
||||
@IBOutlet weak var maskAnimationView: MP_WaveAnimationMaskView!{
|
||||
didSet{
|
||||
maskAnimationView.configure()
|
||||
}
|
||||
}
|
||||
var musicView:MPSideA_MusicViewModel!{
|
||||
didSet{
|
||||
coverImageView.image = musicView.cover
|
||||
@ -21,11 +26,15 @@ class MPSideA_CenterTableViewCell: UITableViewCell {
|
||||
//展示未播放状态
|
||||
titleLabel.textColor = .init(hex: "#FFFFFF")
|
||||
durationLabel.textColor = .init(hex: "#FFFFFF")
|
||||
maskAnimationView.isHidden = true
|
||||
maskAnimationView.stopAnimation()
|
||||
return
|
||||
}
|
||||
//展示播放状态
|
||||
titleLabel.textColor = .init(hex: "#80F988")
|
||||
durationLabel.textColor = .init(hex: "#80F988")
|
||||
maskAnimationView.isHidden = false
|
||||
maskAnimationView.startAnimation()
|
||||
}
|
||||
}
|
||||
var moreBlock:((UIButton) -> Void)?
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="KGk-i7-Jjw" customClass="MPSideA_CenterTableViewCell" customModule="MusicPlayer" customModuleProvider="target">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="KGk-i7-Jjw" customClass="MPSideA_CenterTableViewCell" customModule="relax_offline_mp3_music" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="71"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
@ -81,8 +81,18 @@
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</imageView>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Fhk-Be-l2C" customClass="MP_WaveAnimationMaskView" customModule="relax_offline_mp3_music" customModuleProvider="target">
|
||||
<rect key="frame" x="16" y="8.6666666666666643" width="54" height="54"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
|
||||
<real key="value" value="4"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Fhk-Be-l2C" firstAttribute="height" secondItem="KQ5-gn-XK6" secondAttribute="height" id="0Ea-Xy-CDE"/>
|
||||
<constraint firstItem="f9L-Km-S9Y" firstAttribute="bottom" secondItem="KQ5-gn-XK6" secondAttribute="bottom" constant="-7" id="2R8-t5-DkQ">
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||
@ -106,6 +116,9 @@
|
||||
</constraint>
|
||||
<constraint firstItem="KQ5-gn-XK6" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="WEt-Nd-ihp"/>
|
||||
<constraint firstItem="pQd-Fs-d6k" firstAttribute="width" relation="lessThanOrEqual" secondItem="H2p-sc-9uM" secondAttribute="width" multiplier="0.575" id="Y7g-4m-BWf"/>
|
||||
<constraint firstItem="Fhk-Be-l2C" firstAttribute="centerY" secondItem="KQ5-gn-XK6" secondAttribute="centerY" id="Z0P-pA-7p4"/>
|
||||
<constraint firstItem="Fhk-Be-l2C" firstAttribute="centerX" secondItem="KQ5-gn-XK6" secondAttribute="centerX" id="asM-Ne-rZT"/>
|
||||
<constraint firstItem="Fhk-Be-l2C" firstAttribute="width" secondItem="KQ5-gn-XK6" secondAttribute="width" id="avH-v6-tB2"/>
|
||||
<constraint firstItem="KQ5-gn-XK6" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="16" id="dom-zk-hNH">
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||
@ -124,6 +137,7 @@
|
||||
<connections>
|
||||
<outlet property="coverImageView" destination="KQ5-gn-XK6" id="whi-Cd-FEs"/>
|
||||
<outlet property="durationLabel" destination="f9L-Km-S9Y" id="fed-Ql-TqO"/>
|
||||
<outlet property="maskAnimationView" destination="Fhk-Be-l2C" id="P1N-sr-lZB"/>
|
||||
<outlet property="titleLabel" destination="pQd-Fs-d6k" id="9Mt-WP-wWR"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="131" y="-12"/>
|
||||
|
||||
@ -12,6 +12,11 @@ class MPSideA_Home_FirstListCollectionViewCell: UICollectionViewCell {
|
||||
@IBOutlet weak var stateBtn: UIButton!
|
||||
@IBOutlet weak var titleLabel: UILabel!
|
||||
@IBOutlet weak var subtitleLabel: UILabel!
|
||||
@IBOutlet weak var maskAnimationView: MP_WaveAnimationMaskView!{
|
||||
didSet{
|
||||
maskAnimationView.configure()
|
||||
}
|
||||
}
|
||||
var musicView:MPSideA_MusicViewModel!{
|
||||
didSet{
|
||||
coverImageView.image = musicView.cover
|
||||
@ -23,12 +28,16 @@ class MPSideA_Home_FirstListCollectionViewCell: UICollectionViewCell {
|
||||
titleLabel.textColor = .init(hex: "#FFFFFF")
|
||||
subtitleLabel.textColor = .init(hex: "#FFFFFF")
|
||||
stateBtn.isSelected = false
|
||||
maskAnimationView.isHidden = true
|
||||
maskAnimationView.stopAnimation()
|
||||
return
|
||||
}
|
||||
//展示播放状态
|
||||
titleLabel.textColor = .init(hex: "#80F988")
|
||||
subtitleLabel.textColor = .init(hex: "#80F988")
|
||||
stateBtn.isSelected = true
|
||||
maskAnimationView.isHidden = false
|
||||
maskAnimationView.startAnimation()
|
||||
}
|
||||
}
|
||||
override func awakeFromNib() {
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="MPSideA_Home_FirstListCollectionViewCell" customModule="MusicPlayer" customModuleProvider="target">
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="MPSideA_Home_FirstListCollectionViewCell" customModule="relax_offline_mp3_music" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="166" height="140"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
@ -20,6 +20,10 @@
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Home First'placeholder" translatesAutoresizingMaskIntoConstraints="NO" id="IxK-KI-sPo">
|
||||
<rect key="frame" x="0.0" y="0.0" width="166" height="140"/>
|
||||
</imageView>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ejm-CB-ugh" customClass="MP_WaveAnimationMaskView" customModule="relax_offline_mp3_music" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="166" height="140"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wKm-JE-O2C">
|
||||
<rect key="frame" x="0.0" y="90" width="166" height="50"/>
|
||||
<subviews>
|
||||
@ -86,10 +90,14 @@
|
||||
<viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="Ejm-CB-ugh" secondAttribute="bottom" id="2Ea-Cd-XKI"/>
|
||||
<constraint firstItem="wKm-JE-O2C" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="2Tw-xc-dHw"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Ejm-CB-ugh" secondAttribute="trailing" id="APA-CI-l8U"/>
|
||||
<constraint firstItem="IxK-KI-sPo" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="DQx-j8-rw9"/>
|
||||
<constraint firstItem="3mZ-cR-XZ2" firstAttribute="width" relation="lessThanOrEqual" secondItem="gTV-IL-0wX" secondAttribute="width" multiplier="0.65" id="H1W-jt-7AD"/>
|
||||
<constraint firstItem="Ejm-CB-ugh" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="JOi-bU-vpr"/>
|
||||
<constraint firstAttribute="bottom" secondItem="wKm-JE-O2C" secondAttribute="bottom" id="NLe-1e-6gE"/>
|
||||
<constraint firstItem="Ejm-CB-ugh" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="O1I-c8-bsO"/>
|
||||
<constraint firstAttribute="trailing" secondItem="wKm-JE-O2C" secondAttribute="trailing" id="SCT-Of-PdD"/>
|
||||
<constraint firstAttribute="trailing" secondItem="IxK-KI-sPo" secondAttribute="trailing" id="UBr-kj-ydd"/>
|
||||
<constraint firstItem="IxK-KI-sPo" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="ag6-ex-A0t"/>
|
||||
@ -102,6 +110,7 @@
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="coverImageView" destination="IxK-KI-sPo" id="Mo3-bF-ky3"/>
|
||||
<outlet property="maskAnimationView" destination="Ejm-CB-ugh" id="ioR-c6-gOU"/>
|
||||
<outlet property="stateBtn" destination="8Ew-eq-4bL" id="RW8-Vd-cAb"/>
|
||||
<outlet property="subtitleLabel" destination="bEk-CN-UZ5" id="tU3-zv-9BO"/>
|
||||
<outlet property="titleLabel" destination="3mZ-cR-XZ2" id="5Za-3E-g0M"/>
|
||||
|
||||
@ -11,7 +11,11 @@ class MPSideA_Home_FourthListCollectionViewCell: UICollectionViewCell {
|
||||
@IBOutlet weak var coverImageView: UIImageView!
|
||||
@IBOutlet weak var titleLabel: UILabel!
|
||||
@IBOutlet weak var subtitleLabel: UILabel!
|
||||
@IBOutlet weak var shieldView: UIView!
|
||||
@IBOutlet weak var maskAnimationView: MP_WaveAnimationMaskView!{
|
||||
didSet{
|
||||
maskAnimationView.configure()
|
||||
}
|
||||
}
|
||||
@IBOutlet weak var stateBtn: UIButton!
|
||||
var musicView:MPSideA_MusicViewModel!{
|
||||
didSet{
|
||||
@ -24,14 +28,16 @@ class MPSideA_Home_FourthListCollectionViewCell: UICollectionViewCell {
|
||||
titleLabel.textColor = .init(hex: "#FFFFFF")
|
||||
subtitleLabel.textColor = .init(hex: "#FFFFFF")
|
||||
stateBtn.isSelected = false
|
||||
shieldView.isHidden = true
|
||||
maskAnimationView.isHidden = true
|
||||
maskAnimationView.stopAnimation()
|
||||
return
|
||||
}
|
||||
//展示播放状态
|
||||
titleLabel.textColor = .init(hex: "#80F988")
|
||||
subtitleLabel.textColor = .init(hex: "#80F988")
|
||||
stateBtn.isSelected = true
|
||||
shieldView.isHidden = false
|
||||
maskAnimationView.isHidden = false
|
||||
maskAnimationView.startAnimation()
|
||||
}
|
||||
}
|
||||
override func awakeFromNib() {
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="MPSideA_Home_FourthListCollectionViewCell" customModule="MusicPlayer" customModuleProvider="target">
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="MPSideA_Home_FourthListCollectionViewCell" customModule="relax_offline_mp3_music" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="340" height="54"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
@ -37,30 +37,9 @@
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</imageView>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="60V-3q-xjG">
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="60V-3q-xjG" customClass="MP_WaveAnimationMaskView" customModule="relax_offline_mp3_music" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="54" height="54"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Home Fourth'play" translatesAutoresizingMaskIntoConstraints="NO" id="aOI-1H-A0f">
|
||||
<rect key="frame" x="20" y="18.666666666666668" width="14" height="17.000000000000004"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="17" id="Nub-tX-eND">
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</constraint>
|
||||
<constraint firstAttribute="width" constant="14" id="RTp-Cb-qJl">
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</constraint>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.78000000000000003" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="aOI-1H-A0f" firstAttribute="centerY" secondItem="60V-3q-xjG" secondAttribute="centerY" id="Iry-Jt-YVR"/>
|
||||
<constraint firstItem="aOI-1H-A0f" firstAttribute="centerX" secondItem="60V-3q-xjG" secondAttribute="centerX" id="Yif-ra-MVB"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
|
||||
<real key="value" value="10"/>
|
||||
@ -139,18 +118,17 @@
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="coverImageView" destination="F8Y-Ib-X9N" id="wLl-Ms-S6x"/>
|
||||
<outlet property="shieldView" destination="60V-3q-xjG" id="4xZ-F8-A3R"/>
|
||||
<outlet property="maskAnimationView" destination="60V-3q-xjG" id="i1x-wk-L8p"/>
|
||||
<outlet property="stateBtn" destination="WO3-U6-jrd" id="tF6-T9-0eR"/>
|
||||
<outlet property="subtitleLabel" destination="YME-v2-8NJ" id="w4z-Sj-hiA"/>
|
||||
<outlet property="titleLabel" destination="cu0-Xi-QRO" id="Bra-kW-ZuR"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="130.53435114503816" y="-12.67605633802817"/>
|
||||
<point key="canvasLocation" x="129.7709923664122" y="-12.67605633802817"/>
|
||||
</collectionViewCell>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="Home Fourth'pause" width="20" height="20"/>
|
||||
<image name="Home Fourth'placeholder" width="54" height="54"/>
|
||||
<image name="Home Fourth'play" width="14" height="16"/>
|
||||
<image name="Home Fourth'play 1" width="20" height="20"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
@ -11,7 +11,11 @@ class MPSideA_Home_SecondListCollectionViewCell: UICollectionViewCell {
|
||||
@IBOutlet weak var coverImageView: UIImageView!
|
||||
@IBOutlet weak var titleLabel: UILabel!
|
||||
@IBOutlet weak var subtitleLabel: UILabel!
|
||||
@IBOutlet weak var shieldView: UIView!
|
||||
@IBOutlet weak var maskAnimationView: MP_WaveAnimationMaskView!{
|
||||
didSet{
|
||||
maskAnimationView.configure()
|
||||
}
|
||||
}
|
||||
var musicView:MPSideA_MusicViewModel!{
|
||||
didSet{
|
||||
coverImageView.image = musicView.cover
|
||||
@ -22,13 +26,15 @@ class MPSideA_Home_SecondListCollectionViewCell: UICollectionViewCell {
|
||||
//展示未播放状态
|
||||
titleLabel.textColor = .init(hex: "#FFFFFF")
|
||||
subtitleLabel.textColor = .init(hex: "#FFFFFF")
|
||||
shieldView.isHidden = true
|
||||
maskAnimationView.isHidden = true
|
||||
maskAnimationView.stopAnimation()
|
||||
return
|
||||
}
|
||||
//展示播放状态
|
||||
titleLabel.textColor = .init(hex: "#80F988")
|
||||
subtitleLabel.textColor = .init(hex: "#80F988")
|
||||
shieldView.isHidden = false
|
||||
maskAnimationView.isHidden = false
|
||||
maskAnimationView.startAnimation()
|
||||
}
|
||||
}
|
||||
override func awakeFromNib() {
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="1r0-2H-0D5" customClass="MPSideA_Home_SecondListCollectionViewCell" customModule="MusicPlayer" customModuleProvider="target">
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="1r0-2H-0D5" customClass="MPSideA_Home_SecondListCollectionViewCell" customModule="relax_offline_mp3_music" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="108" height="118"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
@ -25,30 +25,9 @@
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</imageView>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Tyv-4Y-wyb">
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Tyv-4Y-wyb" customClass="MP_WaveAnimationMaskView" customModule="relax_offline_mp3_music" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="108" height="118"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Home Second'play" translatesAutoresizingMaskIntoConstraints="NO" id="SiV-f4-RHR">
|
||||
<rect key="frame" x="47" y="50.666666666666664" width="14" height="16.999999999999993"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="14" id="Ozz-kM-mcw">
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</constraint>
|
||||
<constraint firstAttribute="height" constant="17" id="ZPx-cH-pvj">
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</constraint>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.78000000000000003" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="SiV-f4-RHR" firstAttribute="centerX" secondItem="Tyv-4Y-wyb" secondAttribute="centerX" id="Hab-Rm-WEv"/>
|
||||
<constraint firstItem="SiV-f4-RHR" firstAttribute="centerY" secondItem="Tyv-4Y-wyb" secondAttribute="centerY" id="juS-g0-gka"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
|
||||
<real key="value" value="18"/>
|
||||
@ -105,7 +84,7 @@
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="coverImageView" destination="k8M-sZ-yqy" id="UA4-JB-BYG"/>
|
||||
<outlet property="shieldView" destination="Tyv-4Y-wyb" id="dEG-dE-o9A"/>
|
||||
<outlet property="maskAnimationView" destination="Tyv-4Y-wyb" id="bbb-AW-A55"/>
|
||||
<outlet property="subtitleLabel" destination="6bw-Sd-6Cr" id="Ri8-B4-qe0"/>
|
||||
<outlet property="titleLabel" destination="NZo-PD-Okw" id="fH3-ZI-hIb"/>
|
||||
</connections>
|
||||
@ -114,6 +93,5 @@
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="Home Second'placeholder" width="108" height="118"/>
|
||||
<image name="Home Second'play" width="14" height="17"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user