B面1.1.3,视频播放实现

This commit is contained in:
Mr.zhou 2024-07-25 19:44:30 +08:00
parent 6381a24bf9
commit 79ed07e548
73 changed files with 1295 additions and 313 deletions

View File

@ -31,7 +31,6 @@
CBAFCAE82C0A10500054500E /* MP_LunchViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CBAFC9F42C0A10500054500E /* MP_LunchViewController.xib */; };
CBAFCAE92C0A10500054500E /* MP_NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBAFC9F52C0A10500054500E /* MP_NavigationController.swift */; };
CBAFCAEA2C0A10500054500E /* MP_Lunch_ProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBAFC9F72C0A10500054500E /* MP_Lunch_ProgressView.swift */; };
CBAFCAEB2C0A10500054500E /* relax.offline.mp3.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CBAFC9FA2C0A10500054500E /* relax.offline.mp3.xcdatamodeld */; };
CBAFCAEC2C0A10500054500E /* AVPlayerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBAFC9FC2C0A10500054500E /* AVPlayerItem.swift */; };
CBAFCAED2C0A10500054500E /* DateTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBAFC9FD2C0A10500054500E /* DateTime.swift */; };
CBAFCAEE2C0A10500054500E /* HexColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBAFC9FE2C0A10500054500E /* HexColor.swift */; };
@ -225,13 +224,20 @@
CBAFCBAF2C0A10DA0054500E /* FirebaseRemoteConfig in Frameworks */ = {isa = PBXBuildFile; productRef = CBAFCBAE2C0A10DA0054500E /* FirebaseRemoteConfig */; };
CBAFCBB12C0A121F0054500E /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = CBAFCBB02C0A121F0054500E /* GoogleService-Info.plist */; };
CBB6372C2C1C17C300F1DEC9 /* MP_AdMobManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB6372B2C1C17C300F1DEC9 /* MP_AdMobManager.swift */; };
CBB75FDD2C4F7AA60041665D /* UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBB75FDC2C4F7AA60041665D /* UIImageView.swift */; };
CBBAF8CD2C339CF200B3C838 /* MPPositive_JsonCharts.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBBAF8CC2C339CF200B3C838 /* MPPositive_JsonCharts.swift */; };
CBC1FB7A2C50999800AC0633 /* MPPositive_LibraryItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC1FB792C50999800AC0633 /* MPPositive_LibraryItemModel.swift */; };
CBC1FB7C2C509B7300AC0633 /* MPPositive_LibraryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC1FB7B2C509B7300AC0633 /* MPPositive_LibraryViewModel.swift */; };
CBC1FB7E2C509BB400AC0633 /* MPPositive_LibraryListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC1FB7D2C509BB400AC0633 /* MPPositive_LibraryListViewModel.swift */; };
CBC1FB802C50E59C00AC0633 /* MPPositive_HomeLibraryListstableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC1FB7F2C50E59C00AC0633 /* MPPositive_HomeLibraryListstableViewCell.swift */; };
CBC1FB822C50E63900AC0633 /* MPPositive_HomeLibraryListCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC1FB812C50E63900AC0633 /* MPPositive_HomeLibraryListCollectionViewCell.swift */; };
CBC2D6EC2BFDF3D700E17703 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC2D6EB2BFDF3D700E17703 /* AppDelegate.swift */; };
CBC2D6F02BFDF3D700E17703 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC2D6EF2BFDF3D700E17703 /* ViewController.swift */; };
CBC2D6F32BFDF3D700E17703 /* Base in Resources */ = {isa = PBXBuildFile; fileRef = CBC2D6F22BFDF3D700E17703 /* Base */; };
CBC2D6F82BFDF3D800E17703 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CBC2D6F72BFDF3D800E17703 /* Assets.xcassets */; };
CBC2D6FB2BFDF3D800E17703 /* Base in Resources */ = {isa = PBXBuildFile; fileRef = CBC2D6FA2BFDF3D800E17703 /* Base */; };
CBC2D7D42BFDF4B900E17703 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = CBC2D7792BFDF4B900E17703 /* PrivacyInfo.xcprivacy */; };
CBC2EBC72C5203B5000ADA51 /* relax.offline.mp3.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CBC2EBC52C5203B5000ADA51 /* relax.offline.mp3.xcdatamodeld */; };
CBC3F2B22C3E76160075DC74 /* MPPositive_AdModelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC3F2B12C3E76160075DC74 /* MPPositive_AdModelModel.swift */; };
CBC81FBA2C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC81FB92C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift */; };
CBC81FBC2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC81FBB2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift */; };
@ -460,10 +466,15 @@
CBAFCADE2C0A10500054500E /* MPSideA_Home_SecondListCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MPSideA_Home_SecondListCollectionViewCell.swift; sourceTree = "<group>"; };
CBAFCADF2C0A10500054500E /* MPSideA_Home_SecondListCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPSideA_Home_SecondListCollectionViewCell.xib; sourceTree = "<group>"; };
CBAFCAE02C0A10500054500E /* MPSideA_PlayerActionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MPSideA_PlayerActionView.swift; sourceTree = "<group>"; };
CBAFCAE52C0A10500054500E /* MusicPlayer.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MusicPlayer.xcdatamodel; sourceTree = "<group>"; };
CBAFCBB02C0A121F0054500E /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
CBB6372B2C1C17C300F1DEC9 /* MP_AdMobManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_AdMobManager.swift; sourceTree = "<group>"; };
CBB75FDC2C4F7AA60041665D /* UIImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageView.swift; sourceTree = "<group>"; };
CBBAF8CC2C339CF200B3C838 /* MPPositive_JsonCharts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_JsonCharts.swift; sourceTree = "<group>"; };
CBC1FB792C50999800AC0633 /* MPPositive_LibraryItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_LibraryItemModel.swift; sourceTree = "<group>"; };
CBC1FB7B2C509B7300AC0633 /* MPPositive_LibraryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_LibraryViewModel.swift; sourceTree = "<group>"; };
CBC1FB7D2C509BB400AC0633 /* MPPositive_LibraryListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_LibraryListViewModel.swift; sourceTree = "<group>"; };
CBC1FB7F2C50E59C00AC0633 /* MPPositive_HomeLibraryListstableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_HomeLibraryListstableViewCell.swift; sourceTree = "<group>"; };
CBC1FB812C50E63900AC0633 /* MPPositive_HomeLibraryListCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_HomeLibraryListCollectionViewCell.swift; sourceTree = "<group>"; };
CBC2D6E82BFDF3D700E17703 /* relax.offline.mp3.music.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = relax.offline.mp3.music.app; sourceTree = BUILT_PRODUCTS_DIR; };
CBC2D6EB2BFDF3D700E17703 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
CBC2D6EF2BFDF3D700E17703 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
@ -472,6 +483,7 @@
CBC2D6FA2BFDF3D800E17703 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
CBC2D6FC2BFDF3D800E17703 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CBC2D7792BFDF4B900E17703 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
CBC2EBC62C5203B5000ADA51 /* MusicPlayer.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MusicPlayer.xcdatamodel; sourceTree = "<group>"; };
CBC3F2B12C3E76160075DC74 /* MPPositive_AdModelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_AdModelModel.swift; sourceTree = "<group>"; };
CBC81FB92C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_HomeSinglesTableViewCell.swift; sourceTree = "<group>"; };
CBC81FBB2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_HomeSingleCollectionViewCell.swift; sourceTree = "<group>"; };
@ -572,7 +584,7 @@
CBAFC9FB2C0A10500054500E /* DataBase */ = {
isa = PBXGroup;
children = (
CBAFC9FA2C0A10500054500E /* relax.offline.mp3.xcdatamodeld */,
CBC2EBC52C5203B5000ADA51 /* relax.offline.mp3.xcdatamodeld */,
);
path = DataBase;
sourceTree = "<group>";
@ -588,6 +600,7 @@
CBAFCA002C0A10500054500E /* LayoutConstraint.swift */,
CBAFCA012C0A10500054500E /* Notification.swift */,
CBAFCA032C0A10500054500E /* TableView.swift */,
CBB75FDC2C4F7AA60041665D /* UIImageView.swift */,
);
path = "Extension(扩展)";
sourceTree = "<group>";
@ -722,6 +735,7 @@
CBAFCA3D2C0A10500054500E /* MPPositive_ArtistHeaderModel.swift */,
CBC3F2B12C3E76160075DC74 /* MPPositive_AdModelModel.swift */,
CBAFCA3E2C0A10500054500E /* MPPositive_BrowseItemModel.swift */,
CBC1FB792C50999800AC0633 /* MPPositive_LibraryItemModel.swift */,
CBD344DB2C3FCA270095F18F /* MPPositive_GridModel.swift */,
CBAFCA3F2C0A10500054500E /* MPPositive_CollectionArtistModel.swift */,
CBAFCA402C0A10500054500E /* MPPositive_CollectionListModel.swift */,
@ -742,8 +756,10 @@
children = (
CBAFCA482C0A10500054500E /* MPPositive_ArtistContentListViewModel.swift */,
CBAFCA492C0A10500054500E /* MPPositive_ArtistViewModel.swift */,
CBAFCA4A2C0A10500054500E /* MPPositive_BrowseItemViewModel.swift */,
CBC1FB7D2C509BB400AC0633 /* MPPositive_LibraryListViewModel.swift */,
CBC1FB7B2C509B7300AC0633 /* MPPositive_LibraryViewModel.swift */,
CBAFCA4B2C0A10500054500E /* MPPositive_BrowseModuleListViewModel.swift */,
CBAFCA4A2C0A10500054500E /* MPPositive_BrowseItemViewModel.swift */,
CBD344DD2C3FD8230095F18F /* MPPositive_GridViewModel.swift */,
CBAFCA4C2C0A10500054500E /* MPPositive_CollectionArtistViewModel.swift */,
CBAFCA4D2C0A10500054500E /* MPPositive_CollectionListViewModel.swift */,
@ -891,6 +907,8 @@
CBAFCA902C0A10500054500E /* Home */ = {
isa = PBXGroup;
children = (
CBC1FB7F2C50E59C00AC0633 /* MPPositive_HomeLibraryListstableViewCell.swift */,
CBC1FB812C50E63900AC0633 /* MPPositive_HomeLibraryListCollectionViewCell.swift */,
CBC81FB92C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift */,
CBC81FBB2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift */,
CBAFCA8D2C0A10500054500E /* MPPositive_HomeShowTableViewCell.swift */,
@ -1380,6 +1398,7 @@
CBAFCB582C0A10500054500E /* MPPositive_LibraryTableViewCell.swift in Sources */,
CBAFCB222C0A10500054500E /* MPPositive_JsonSearchTypeResults.swift in Sources */,
CBAFCB492C0A10500054500E /* MPPositive_OfflineSongsViewController.swift in Sources */,
CBC1FB822C50E63900AC0633 /* MPPositive_HomeLibraryListCollectionViewCell.swift in Sources */,
CBAFCB782C0A10500054500E /* MPSideA_MusicViewModel.swift in Sources */,
CBAFCB642C0A10500054500E /* MPPositive_HomeListSecondCollectionViewCell.swift in Sources */,
CBAFCB0A2C0A10500054500E /* MP_CacheManager.swift in Sources */,
@ -1393,6 +1412,7 @@
CBAFCB702C0A10500054500E /* MPPositive_SearchResultShowTableViewCell.swift in Sources */,
CBAFCB662C0A10500054500E /* MPPositive_HomeShowTableViewCell.swift in Sources */,
CBAFCB352C0A10500054500E /* MPPositive_ListAlbumListViewModel.swift in Sources */,
CBB75FDD2C4F7AA60041665D /* UIImageView.swift in Sources */,
CBAFCB7C2C0A10500054500E /* MPSideA_NavigationController.swift in Sources */,
CBDBDDF62C40FFC600767F0B /* MPPositive_GrideMoodViewController.swift in Sources */,
CBAFCB932C0A10500054500E /* MPSideA_PlayerViewController.swift in Sources */,
@ -1406,6 +1426,7 @@
CBAFCB5D2C0A10500054500E /* MPPositive_ArtistShowListableViewCell.swift in Sources */,
CBAFCB7D2C0A10500054500E /* MPSideA_PresentationController.swift in Sources */,
CBAFCB2D2C0A10500054500E /* MPPositive_ArtistContentListViewModel.swift in Sources */,
CBC1FB7E2C509BB400AC0633 /* MPPositive_LibraryListViewModel.swift in Sources */,
CBAFCB992C0A10500054500E /* MPSideA_CustomTabBarView.swift in Sources */,
CBAFCB342C0A10500054500E /* MPPositive_DownloadViewModel.swift in Sources */,
CBAFCB1E2C0A10500054500E /* MPPositive_JsonRecommend.swift in Sources */,
@ -1423,9 +1444,11 @@
CBAFCB7B2C0A10500054500E /* MPSideA_BaseViewController.swift in Sources */,
CBAFCB102C0A10500054500E /* MP_NetWorkManager.swift in Sources */,
CBAFCB9D2C0A10500054500E /* MPSideA_SettingTableViewCell.swift in Sources */,
CBC2EBC72C5203B5000ADA51 /* relax.offline.mp3.xcdatamodeld in Sources */,
CBAFCAEC2C0A10500054500E /* AVPlayerItem.swift in Sources */,
CBAFCB7E2C0A10500054500E /* MPSideA_TabBarController.swift in Sources */,
CBAFCB1D2C0A10500054500E /* MPPositive_JsonPlayer.swift in Sources */,
CBC1FB7C2C509B7300AC0633 /* MPPositive_LibraryViewModel.swift in Sources */,
CBAFCB602C0A10500054500E /* MPPositive_ArtistShowTypeView.swift in Sources */,
CBAFCB6F2C0A10500054500E /* MPPositive_SearchResultPreviewShowView.swift in Sources */,
CB0033F42C294DBF00B18FD3 /* MPPositive_CustomPlayListViewController.swift in Sources */,
@ -1473,7 +1496,6 @@
CBAFCB282C0A10500054500E /* MPPositive_DownloadItemModel.swift in Sources */,
CBAFCB152C0A10500054500E /* MPSideA_MediaCenterManager.swift in Sources */,
CBDBDDF22C40C40900767F0B /* MPPositive_GridLoadViewModel.swift in Sources */,
CBAFCAEB2C0A10500054500E /* relax.offline.mp3.xcdatamodeld in Sources */,
CBAFCB192C0A10500054500E /* MPPositive_JsonBrowse.swift in Sources */,
CBAFCB912C0A10500054500E /* MPSideA_HomeViewController.swift in Sources */,
CBAFCAEA2C0A10500054500E /* MP_Lunch_ProgressView.swift in Sources */,
@ -1522,6 +1544,7 @@
CBAFCAED2C0A10500054500E /* DateTime.swift in Sources */,
CBAFCB4F2C0A10500054500E /* MPPositive_PlayerViewController.swift in Sources */,
CBAFCB672C0A10500054500E /* MPPositive_MoreListContentCollectionViewCell.swift in Sources */,
CBC1FB7A2C50999800AC0633 /* MPPositive_LibraryItemModel.swift in Sources */,
CBAFCB422C0A10500054500E /* MPPositive_MoreSongOperationsViewController.swift in Sources */,
CBAFCB532C0A10500054500E /* MPPositive_BottomShowView.swift in Sources */,
CBF3AEDA2C255B1200947AFC /* MPPositive_PlayListsShowTypeView.swift in Sources */,
@ -1535,6 +1558,7 @@
CBAFCB752C0A10500054500E /* MPPositive_SearchTagCollectionViewCell.swift in Sources */,
CBAFCB712C0A10500054500E /* MPPositive_SearchResultsShowView.swift in Sources */,
CBAFCB482C0A10500054500E /* MPPositive_LoveSongsViewController.swift in Sources */,
CBC1FB802C50E59C00AC0633 /* MPPositive_HomeLibraryListstableViewCell.swift in Sources */,
CBAFCB792C0A10500054500E /* MPSideA_AddViewController.swift in Sources */,
CBAFCB5A2C0A10500054500E /* MPPositive_ArtistDescriptionTableViewCell.swift in Sources */,
CBAFCB272C0A10500054500E /* MPPositive_CollectionSongModel.swift in Sources */,
@ -1703,7 +1727,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1.1.2.1;
CURRENT_PROJECT_VERSION = 1.1.3.1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = T93S37G27F;
GENERATE_INFOPLIST_FILE = YES;
@ -1723,7 +1747,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1.2;
MARKETING_VERSION = 1.1.3;
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -1746,7 +1770,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1.1.2.1;
CURRENT_PROJECT_VERSION = 1.1.3.1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = T93S37G27F;
GENERATE_INFOPLIST_FILE = YES;
@ -1766,7 +1790,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1.2;
MARKETING_VERSION = 1.1.3;
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -1870,13 +1894,14 @@
/* End XCSwiftPackageProductDependency section */
/* Begin XCVersionGroup section */
CBAFC9FA2C0A10500054500E /* relax.offline.mp3.xcdatamodeld */ = {
CBC2EBC52C5203B5000ADA51 /* relax.offline.mp3.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
CBAFCAE52C0A10500054500E /* MusicPlayer.xcdatamodel */,
CBC2EBC62C5203B5000ADA51 /* MusicPlayer.xcdatamodel */,
);
currentVersion = CBAFCAE52C0A10500054500E /* MusicPlayer.xcdatamodel */;
path = relax.offline.mp3.xcdatamodeld;
currentVersion = CBC2EBC62C5203B5000ADA51 /* MusicPlayer.xcdatamodel */;
name = relax.offline.mp3.xcdatamodeld;
path = "/Users/zhou/Desktop/纳克斯互娱/relax.offline.mp3.music/relax.offline.mp3.music/MP/Common/DataBase/relax.offline.mp3.xcdatamodeld";
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};

View File

@ -27,6 +27,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
private var positiceVC:MPPositive_TabBarController!
//
private let notificationHandler = NotificationHandler()
var backgroundTask: UIBackgroundTaskIdentifier = .invalid
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//
UNUserNotificationCenter.current()
@ -192,9 +193,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
//
backgroundEntryTime = Date()
}
//
func applicationWillEnterForeground(_ application: UIApplication) {
}
//
func applicationDidBecomeActive(_ application: UIApplication) {
guard let backDate = backgroundEntryTime else {

View File

@ -5,12 +5,12 @@
"scale" : "1x"
},
{
"filename" : "Group_1597880538@2x.png",
"filename" : "艺术家@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group_1597880538@3x.png",
"filename" : "艺术家@3x.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 991 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -5,12 +5,12 @@
"scale" : "1x"
},
{
"filename" : "Group_1597880557@2x.png",
"filename" : "下载@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group_1597880557@3x.png",
"filename" : "下载@3x.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1007 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -5,12 +5,12 @@
"scale" : "1x"
},
{
"filename" : "Group_1597880531@2x.png",
"filename" : "爱心·@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group_1597880531@3x.png",
"filename" : "爱心·@3x.png",
"idiom" : "universal",
"scale" : "3x"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "蓝色背景@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "蓝色背景@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "橙色背景@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "橙色背景@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "紫色背景@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "紫色背景@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group_1597880767_1@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group_1597880767_1@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group_1597880767@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group_1597880767@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "img_v3_02d4_ee007dfc-bc8e-4d75-9906-5fe97d31c21g.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "img_v3_02d4_6fae3c41-fe4d-470e-8b9a-dc66b5e60b1g.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -2,15 +2,23 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSUserTrackingUsageDescription</key>
<string>&quot;Musiclax&quot; needs to request tracking permissions to provide a personalized advertising experience. We respect and protect your privacy and will not sell your data to third parties.</string>
<key>UIBackgroundModes</key>
<key>CFBundleURLTypes</key>
<array>
<string>audio</string>
<string>fetch</string>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>fb820013496431805</string>
</array>
</dict>
</array>
<key>FacebookAppID</key>
<string>820013496431805</string>
<key>FacebookAutoLogAppEventsEnabled</key>
<true/>
<key>FacebookClientToken</key>
<string>8e591aa271d43fdd3e7a778d59c85282</string>
<key>FacebookDisplayName</key>
<string>Musiclax</string>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-1371732277241593~3881310073</string>
<key>SKAdNetworkItems</key>
@ -212,22 +220,12 @@
<string>3qcr597p9d.skadnetwork</string>
</dict>
</array>
<key>CFBundleURLTypes</key>
<key>UIBackgroundModes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>fb820013496431805</string>
</array>
</dict>
<string>audio</string>
<string>fetch</string>
</array>
<key>FacebookAppID</key>
<string>820013496431805</string>
<key>FacebookClientToken</key>
<string>8e591aa271d43fdd3e7a778d59c85282</string>
<key>FacebookDisplayName</key>
<string>Musiclax</string>
<key>FacebookAutoLogAppEventsEnabled</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>

View File

@ -40,6 +40,7 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
}
view.backgroundColor = .init(hex: "#000000")
timer = CADisplayLink(target: self, selector: #selector(timerActionClick(_ :)))
//
timer.preferredFramesPerSecond = 10
//线
@ -133,7 +134,6 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
MPPositive_BrowseLoadViewModel.shared.reloadBrowseLists()
}
}
//广
MP_AdMobManager.shared.loadMoreAdMobs()
MP_AdMobManager.shared.showOpenAdIfAvailable(.ICE) { [weak self] (ad, isOpen) in
guard let self = self else {return}
@ -337,7 +337,6 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
//广
func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
if ad === MP_AdMobManager.shared.appOpenAd || ad === MP_AdMobManager.shared.appInterstitialAd {
print("当前展示的广告是开屏广告广告ID--\(MP_AdMobManager.shared.appOpenAd != nil ? (MP_AdMobManager.shared.appOpenAd?.adUnitID ?? ""):(MP_AdMobManager.shared.appInterstitialAd?.adUnitID ?? ""))")
if let openAd = MP_AdMobManager.shared.appOpenAd {
print("当前展示的广告是开屏广告广告ID--\(openAd.adUnitID)")
//广

View File

@ -0,0 +1,52 @@
//
// UIImageView.swift
// relax.offline.mp3.music
//
// Created by Mr.Zhou on 2024/7/23.
//
import UIKit
extension UIImage {
///
/// - Parameter rect:
/// - Returns:
func dominantColor(in rect: CGRect) -> UIColor? {
guard let cgImage = self.cgImage?.cropping(to: rect) else { return nil }
let context = CGContext(
data: nil,
width: 1,
height: 1,
bitsPerComponent: cgImage.bitsPerComponent,
bytesPerRow: cgImage.bytesPerRow,
space: cgImage.colorSpace ?? CGColorSpaceCreateDeviceRGB(),
bitmapInfo: cgImage.bitmapInfo.rawValue
)
context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: 1, height: 1))
guard let pixelData = context?.data else { return nil }
let data = pixelData.bindMemory(to: UInt8.self, capacity: 4)
let r = CGFloat(data[0]) / 255.0
let g = CGFloat(data[1]) / 255.0
let b = CGFloat(data[2]) / 255.0
let a = CGFloat(data[3]) / 255.0
return UIColor(red: r, green: g, blue: b, alpha: a)
}
func topAndBottomDominantColors() -> (topColor: UIColor?, bottomColor: UIColor?) {
guard let cgImage = self.cgImage else { return (nil, nil) }
let height = self.size.height
let topRect = CGRect(x: 0, y: 0, width: self.size.width, height: height / 2)
let bottomRect = CGRect(x: 0, y: height / 2, width: self.size.width, height: height / 2)
let topColor = self.dominantColor(in: topRect)
let bottomColor = self.dominantColor(in: bottomRect)
return (topColor, bottomColor)
}
}

View File

@ -65,6 +65,12 @@ var app_Version:String{
let bottomPadding = UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 0
///
let placeholderImage:UIImage = UIImage(named: "placeholder")!
///
let love_songBGImage:UIImage = UIImage(named: "Love Songs'bg")!
///
let love_artistBGImage:UIImage = UIImage(named: "Love Artists'bg")!
///线
let offline_songBGImage:UIImage = UIImage(named: "Offline Songs")!
///
let privacyUrl:URL = .init(string: "https://musiclax.mystrikingly.com/privacy")!
///

View File

@ -272,18 +272,18 @@ class MP_PlayerResourceLoader: NSObject, AVAssetResourceLoaderDelegate {
processRequestList(id ?? "")
}
}
///
func requestManagerIsCached(_ isCached: Bool, videoId:String){
if self.videoId == videoId {
}
}
///
func requestManagerDidComplete(withError errorCode: Int, videoId:String){
if self.videoId == videoId {
}
}
// ///
// func requestManagerIsCached(_ isCached: Bool, videoId:String){
// if self.videoId == videoId {
//
// }
// }
// ///
// func requestManagerDidComplete(withError errorCode: Int, videoId:String){
// if self.videoId == videoId {
//
// }
// }
}

View File

@ -260,46 +260,41 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont
}else {
print("播放插页广告加载失败")
}
self.loadSearchInterstitialAd { status in
if status {
print("成功加载搜索插页广告")
}else {
print("搜索插页广告加载失败")
}
}
loadSearchInterstitialAd { status in
if status {
print("成功加载搜索插页广告")
}else {
print("搜索插页广告加载失败")
}
}
}
func loadAnyAdMobs() {
guard openAdStatus else {return}
let serialQueue = DispatchQueue(label: "com.yourapp.serialQueue")
serialQueue.async { [weak self] in
self?.loadSwitchInterstitialAd { status in
if status {
print("成功加载切歌插页广告")
}else {
print("切歌插页广告加载失败")
}
self?.loadLoadInterstitialAd { status in
if status {
print("成功加载下载插页广告")
}else {
print("下载插页广告加载失败")
}
self?.loadLibraryInterstitialAd { status in
if status {
print("成功加载曲库插页广告")
}else {
print("曲库插页广告加载失败")
}
self?.loadGlobalInterstitialAd { status in
if status {
print("成功加载全局插页广告")
}else {
print("全局插页广告加载失败")
}
}
}
}
self.loadSwitchInterstitialAd { status in
if status {
print("成功加载切歌插页广告")
}else {
print("切歌插页广告加载失败")
}
}
self.loadLibraryInterstitialAd { status in
if status {
print("成功加载曲库插页广告")
}else {
print("曲库插页广告加载失败")
}
}
self.loadGlobalInterstitialAd { status in
if status {
print("成功加载全局插页广告")
}else {
print("全局插页广告加载失败")
}
}
self.loadLoadInterstitialAd { status in
if status {
print("成功加载下载插页广告")
}else {
print("下载插页广告加载失败")
}
}
}

View File

@ -66,6 +66,8 @@ class MP_AnalyticsManager: NSObject {
private let player_b_downloadfailure_error = "player_b_downloadfailure_error"
//B
private let search_pv = "search_pv"
//
private let search_from_action = "search_from_action"
//B
private let grid_mood_click = "grid_mood_click"
//SUG
@ -76,8 +78,12 @@ class MP_AnalyticsManager: NSObject {
private let search_result_pv = "search_result_pv"
//
private let search_resultsuccess_action = "search_resultsuccess_action"
//
private let create_list_action = "create_list_action"
//
private let guide_click = "guide_click"
//
private let library_click = "library_click"
private override init() {
//
@ -204,6 +210,8 @@ class MP_AnalyticsManager: NSObject {
}
}
//MARK: -
///
func user_launchAction(){
@ -374,6 +382,11 @@ class MP_AnalyticsManager: NSObject {
func grid_mood_clickAction(_ mood:String) {
Analytics.logEvent(grid_mood_click, parameters: ["mood":mood])
}
///
func search_from_actionAction(_ from:String) {
Analytics.logEvent(search_from_action, parameters: ["search from":from])
}
///SUG
func search_sug_showAction(){
Analytics.logEvent(search_sug_show, parameters: nil)
@ -392,10 +405,21 @@ class MP_AnalyticsManager: NSObject {
func search_resultsuccess_actionAction(){
Analytics.logEvent(search_resultsuccess_action, parameters: nil)
}
///
func create_list_actionAction() {
Analytics.logEvent(create_list_action, parameters: nil)
}
///
func guide_clickAction(_ result:String) {
Analytics.logEvent(guide_click, parameters: ["result":result])
}
///
func library_clickAction(_ click:String, folder:String) {
Analytics.logEvent(library_click, parameters: ["click from":click,
"folder click":folder])
}
//MARK: - 广
//
@ -471,12 +495,13 @@ class MP_AnalyticsManager: NSObject {
mediation = mediation_group_name
}
let price = valueToUSD(adValue)
let priceString = String(format: "%.5f", price)
//
let parameters:[String:Any] = ["CS_PLATFORM":responseInfo.loadedAdNetworkResponseInfo?.adSourceName ?? "Unknown",
"CS_SOURCE":responseInfo.loadedAdNetworkResponseInfo?.adSourceInstanceName ?? "Unknown",
"CS_UNIT_NAME":mediation,
"CS_CURRENCY":adValue.currencyCode,
"CS_VALUE":price,
"CS_VALUE":priceString,
"CS_STATUS":isOLD ? "Old":"New"]
//
if var totalPrices = UserDefaults.standard.array(forKey: "Session_TotalPrices") as? [Double] {
@ -670,10 +695,11 @@ class MP_AnalyticsManager: NSObject {
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":totalPrice,
"session_totalPrice":priceString,
"session_totalNumber":count]
print("当前活跃会话总价值--\(parameters)")
//

View File

@ -20,10 +20,10 @@ class MP_CacheAndArchiverManager {
private var zhoujunfeng_cacheOutTimes:TimeInterval = 172800
private init() {
}
///
///
func zhoujunfeng_checkAndCleanCacheFolder() {
//URL
let contents:[URL]!
var contents:[URL] = []
guard let cacheDirectory = createCachePath() else {return}
do{
contents = try fileManager.contentsOfDirectory(at: URL(fileURLWithPath: cacheDirectory), includingPropertiesForKeys: [.creationDateKey], options: .skipsHiddenFiles)
@ -55,6 +55,34 @@ class MP_CacheAndArchiverManager {
}
}
}
///
private func getCacheSize() -> UInt64 {
guard let cacheDirectory = createCachePath() else {return 0}
//URL
var contents:[URL] = []
do{
contents = try fileManager.contentsOfDirectory(at: URL(fileURLWithPath: cacheDirectory), includingPropertiesForKeys: [.creationDateKey], options: .skipsHiddenFiles)
}catch {
print("获取缓存文件夹内容失败:\(error.localizedDescription)")
return 0
}
//
var folderSize: UInt64 = 0
for content in contents {
if let fileSize = try? content.resourceValues(forKeys: [.fileSizeKey]).fileSize {
folderSize += UInt64(fileSize)
}
}
return folderSize
}
func getCacheSizeText() -> String {
let byteCountFormatter = ByteCountFormatter()
byteCountFormatter.allowedUnits = [.useBytes, .useKB, .useMB, .useGB]
byteCountFormatter.countStyle = .file
return byteCountFormatter.string(fromByteCount: Int64(getCacheSize()))
}
///
func cleanAllCache(_ compleHandler:((Bool) -> Void)?) {
guard let cacheDirectory = createCachePath() else {return}

View File

@ -19,7 +19,7 @@ class MP_CoreDataHandlerManager {
container.loadPersistentStores { (_, error) in
if let error = error {
//
fatalError("Failed to load persistent stores: \(error)")
print("Failed to load persistent stores: \(error)")
}else {
//
print("Successfully to load persistent stores")

View File

@ -27,7 +27,12 @@ class MP_NetWorkManager: NSObject {
//4
configuration.timeoutIntervalForRequest = 20
configuration.timeoutIntervalForResource = 20
return Alamofire.Session(configuration: configuration, interceptor: MP_CustomRetrier())
//
configuration.networkServiceType = .default
//
configuration.requestCachePolicy = .reloadIgnoringLocalCacheData
let seesion = Alamofire.Session(configuration: configuration, interceptor: MP_CustomRetrier())
return seesion
}()
///
private lazy var PlayerSeesion:Session = {
@ -175,6 +180,9 @@ class MP_NetWorkManager: NSObject {
self.monitor = NWPathMonitor()
super.init()
reloadVersion()
if let string = UserDefaults.standard.string(forKey: "Visitor_Data") {
self.visitorData = string
}
}
//
func reloadVersion() {
@ -306,7 +314,6 @@ extension MP_NetWorkManager {
//continuationcontinuation,
//
browseQueque = DispatchQueue(label: "com.request.browseQueque")
visitorData = nil
//browse
let path = header+point+browse
//url
@ -326,6 +333,7 @@ extension MP_NetWorkManager {
"client":[
//web
"clientName": "WEB_REMIX",
"visitorData":visitorData ?? "",
//访
"clientVersion": clientVersion,
"platform":"MOBILE",
@ -347,8 +355,12 @@ extension MP_NetWorkManager {
guard let self = self else {return}
switch response.result {
case .success(let value):
if value.responseContext?.visitorData != nil {
self.visitorData = value.responseContext?.visitorData
if let data = value.responseContext?.visitorData {
if data != self.visitorData {
print("Visitor_Data更改了")
self.visitorData = data
UserDefaults.standard.setValue(data, forKey: "Visitor_Data")
}
}
//
let tab = value.contents?.singleColumnBrowseResultsRenderer?.tabs?[0]
@ -634,7 +646,7 @@ extension MP_NetWorkManager {
"client":[
//web
"clientName": "WEB_REMIX",
//"visitorData":visitorData,
"visitorData":visitorData,
//访
"clientVersion": clientVersion,
"platform":"MOBILE",
@ -687,7 +699,7 @@ extension MP_NetWorkManager {
"client":[
//web
"clientName": "WEB_REMIX",
//"visitorData":visitorData,
"visitorData":visitorData,
//访
"clientVersion": clientVersion,
"platform":"MOBILE",
@ -840,7 +852,7 @@ extension MP_NetWorkManager {
"client":[
//web
"clientName": "WEB_REMIX",
//"visitorData":visitorData,
"visitorData":visitorData,
//访
"clientVersion": clientVersion,
"platform":"MOBILE",
@ -954,6 +966,7 @@ extension MP_NetWorkManager {
"context":[
"client":[
"clientName": "ANDROID_MUSIC",
"visitorData":visitorData,
"clientVersion": playerVersion,
"platform":"MOBILE",
"browserVersion":"125.0.0.0",
@ -1217,7 +1230,7 @@ extension MP_NetWorkManager {
"client":[
//web
"clientName": "WEB_REMIX",
//"visitorData":visitorData,
"visitorData":visitorData,
//访
"clientVersion": clientVersion,
"platform":"MOBILE",
@ -1279,7 +1292,7 @@ extension MP_NetWorkManager {
"client":[
//web
"clientName": "WEB_REMIX",
// "visitorData":visitorData,
"visitorData":visitorData,
//访
"clientVersion": clientVersion,
"platform":"DESKTOP",
@ -1342,7 +1355,7 @@ extension MP_NetWorkManager {
"client":[
//web
"clientName": "WEB_REMIX",
// "visitorData":visitorData,
"visitorData":visitorData,
//访
"clientVersion": clientVersion,
"platform":"MOBILE",
@ -1429,12 +1442,33 @@ extension MP_NetWorkManager {
}
} else {
print("未知错误: \(error?.localizedDescription ?? "")")
MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("No Area")
pingYoutube { status in
if status {
//ping访
MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("Can access YouTube, but not in the service area")
}else {
MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("No Area")
}
}
}
if browseRequestErrorBlock != nil {
browseRequestErrorBlock!()
}
}
///
private func pingYoutube(completion: @escaping (Bool) -> Void) {
guard let url = URL(string: "https://www.youtube.com/") else {return}
AF.request(url).response { response in
if let error = response.error {
print("Ping failed with error: \(error)")
completion(false)
} else {
print("Ping successful, response code: \(response.response?.statusCode ?? -1)")
completion(true)
}
}
}
///
private func handleError(_ url: URL, error:AFError?, status:Bool = true) {
//

View File

@ -67,11 +67,18 @@ class MP_PlayerManager:NSObject{
///
static let shared = MP_PlayerManager()
///
private lazy var player:AVPlayer = {
lazy var player:AVPlayer = {
let player = AVPlayer()
player.rate = 1
return player
}()
///
lazy var videoLayer:AVPlayerLayer = {
let layer:AVPlayerLayer = .init(player: player)
layer.videoGravity = .resizeAspect
layer.backgroundColor = UIColor.black.cgColor
return layer
}()
//
var center:MPRemoteCommandCenter?{
didSet{
@ -244,6 +251,8 @@ class MP_PlayerManager:NSObject{
NotificationCenter.notificationKey.add(observer: self, selector: #selector(netWorkReachableAction(_ :)), notificationName: .net_switch_reachable)
//
NotificationCenter.default.addObserver(self, selector: #selector(handleAudioSessionRouteChangeAction(_ :)), name: AVAudioSession.routeChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleAppStateChange(_ :)), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleAppStateChange(_ :)), name: UIApplication.willEnterForegroundNotification, object: nil)
//
let interval:CMTime = .init(seconds: 1, preferredTimescale: .init(1))
//线
@ -365,11 +374,15 @@ class MP_PlayerManager:NSObject{
}
//
suspendTimer()
MP_AnalyticsManager.shared.player_b_success_actionAction(loadPlayer?.currentVideo?.song.videoId ?? "", videoname: loadPlayer?.currentVideo?.title ?? "", artistname: loadPlayer?.currentVideo?.song.shortBylineText ?? "")
if let currentVideo = loadPlayer.currentVideo {
MP_AnalyticsManager.shared.player_b_success_actionAction(currentVideo.song.videoId ?? "", videoname: currentVideo.title ?? "", artistname: currentVideo.song.shortBylineText ?? "")
}
//
if startActionBlock != nil {
startActionBlock!()
}
}
}else {
//
@ -434,6 +447,16 @@ class MP_PlayerManager:NSObject{
break
}
}
///退
@objc private func handleAppStateChange(_ notification: Notification) {
if notification.name == UIApplication.didEnterBackgroundNotification {
//AVPlayer
videoLayer.player = nil
}else if notification.name == UIApplication.willEnterForegroundNotification {
videoLayer.player = player
}
}
///
@objc private func netWorkReachableAction(_ sender:Notification) {
//
@ -850,6 +873,40 @@ class MP_PlayerManager:NSObject{
}
}
}
func getVideoDimensions(from playerItem: AVPlayerItem, completion: @escaping (CGFloat, CGFloat) -> Void) {
guard let asset = playerItem.asset as? AVURLAsset else {
completion(0, 0)
return
}
asset.loadValuesAsynchronously(forKeys: ["tracks"]) {
var error: NSError? = nil
let status = asset.statusOfValue(forKey: "tracks", error: &error)
if status == .loaded {
let videoTracks = asset.tracks(withMediaType: .video)
guard let videoTrack = videoTracks.first else {
completion(0, 0)
return
}
let size = videoTrack.naturalSize.applying(videoTrack.preferredTransform)
completion(abs(size.width), abs(size.height))
} else {
completion(0, 0)
}
}
}
///
func isCoverVideo(playerItem: AVPlayerItem, completion: @escaping (Bool) -> Void) {
getVideoDimensions(from: playerItem) { width, height in
if width == 0 || height == 0 {
//0
completion(true)
} else {
completion(width <= 1.5 * height)
}
}
}
}

View File

@ -26,6 +26,8 @@ class MPPositive_BrowseItemModel: NSObject, Codable {
var pageType:String?
////OR/
var itemType:BrowseItemType?
}
///
enum BrowseItemType: Int, Codable{

View File

@ -0,0 +1,58 @@
//
// MPPositive_LibraryItemModel.swift
// relax.offline.mp3.music
//
// Created by Mr.Zhou on 2024/7/24.
//
import UIKit
///
class MPPositive_LibraryItemModel: NSObject {
///
var libraryType:LibraryType
///
var coverUrl:URL?
///
var title:String
///
var identifier:String?
init(libraryType: LibraryType, coverUrl: URL?, title: String, identifier: String? = nil) {
self.libraryType = libraryType
self.coverUrl = coverUrl
self.title = title
self.identifier = identifier
}
}
///Library
enum LibraryType:Int {
case love_songs = 0
case love_aritists = 1
case offline_songs = 2
case custom_playlist = 3
var image:UIImage? {
switch self {
case .love_songs:
return love_songBGImage
case .love_aritists:
return love_artistBGImage
case .offline_songs:
return offline_songBGImage
case .custom_playlist:
return placeholderImage
}
}
var icon:UIImage?{
switch self {
case .love_songs:
return UIImage(named: "Center_Songs'logo")
case .love_aritists:
return UIImage(named: "Center_Artists'logo")
case .offline_songs:
return UIImage(named: "Center_Offline'logo")
case .custom_playlist:
return nil
}
}
}

View File

@ -12,7 +12,7 @@ import CoreData
class MPPositive_SearchTagModel: NSManagedObject, MP_CoreDataManageableDelegate, MP_CoreDataOperationDelegate {
typealias ManagedObject = MPPositive_SearchTagModel
///
@NSManaged var date:Date!
@NSManaged var date:Date
///
@NSManaged var text:String!
@NSManaged var text:String
}

View File

@ -0,0 +1,60 @@
//
// MPPositive_LibraryListViewModel.swift
// relax.offline.mp3.music
//
// Created by Mr.Zhou on 2024/7/24.
//
import UIKit
class MPPositive_LibraryListViewModel: NSObject {
///
var title:String = "Library"
///View
var libraryViewModels:[MPPositive_LibraryViewModel] = []
override init() {
super.init()
}
///View
func reloadLibrarys(_ complehandler:(() -> Void)?) {
var array:[MPPositive_LibraryViewModel] = []
//
let songs = MPPositive_LoadCoreModel.shared.songViewModels
if songs.isEmpty == false, let lastUrl = songs.first?.coverURL {
//
let item = MPPositive_LibraryViewModel(.init(libraryType: .love_songs, coverUrl: lastUrl, title: "Love Songs"))
array.append(item)
}else {
let item = MPPositive_LibraryViewModel(.init(libraryType: .love_songs, coverUrl: nil, title: "Love Songs"))
array.append(item)
}
let artists = MPPositive_LoadCoreModel.shared.artistViewModels
if artists.isEmpty == false, let lastUrl = artists.first?.coverURL {
let item = MPPositive_LibraryViewModel(.init(libraryType: .love_aritists, coverUrl: lastUrl, title: "Love Artists"))
array.append(item)
}else {
let item = MPPositive_LibraryViewModel(.init(libraryType: .love_aritists, coverUrl: nil, title: "Love Artists"))
array.append(item)
}
let offlines = MPPositive_LoadCoreModel.shared.loadViewModels
if offlines.isEmpty == false, let lastUrl = offlines.first?.reviewURL {
let item = MPPositive_LibraryViewModel(.init(libraryType: .offline_songs, coverUrl: lastUrl, title: "Offline Songs"))
array.append(item)
}else {
let item = MPPositive_LibraryViewModel(.init(libraryType: .offline_songs, coverUrl: nil, title: "Offline Songs"))
array.append(item)
}
//
MPPositive_LoadCoreModel.shared.playLists.forEach { list in
if list.playList.videosArray.isEmpty == false, let lastUrl = list.coverImageURL, let title = list.title, let identifier = list.playList.playListId {
let item = MPPositive_LibraryViewModel(.init(libraryType: .custom_playlist, coverUrl: lastUrl, title: title, identifier: identifier))
array.append(item)
}
}
libraryViewModels = array
if let block = complehandler {
block()
}
}
}

View File

@ -0,0 +1,31 @@
//
// MPPositive_LibraryViewModel.swift
// relax.offline.mp3.music
//
// Created by Mr.Zhou on 2024/7/24.
//
import UIKit
import Kingfisher
class MPPositive_LibraryViewModel: NSObject {
///(使)
var cover:URL?
///
var title:String = "Text"
///
var library:MPPositive_LibraryItemModel
init(_ library: MPPositive_LibraryItemModel) {
self.library = library
super.init()
configure()
}
//
private func configure() {
//
if let coverUrl = library.coverUrl {
cover = coverUrl
}
title = library.title
}
}

View File

@ -129,7 +129,6 @@ class MPPositive_SongViewModel: NSObject {
resourcePlayerAsset = .init(resourcePlayerURL!, videoId: song.videoId, title: title ?? "")
}
resourcePlayerItem = .init(asset: resourcePlayerAsset)
}
//
if song.lyrics != nil {

View File

@ -11,6 +11,9 @@ class MPPositive_BrowseLoadViewModel: NSObject {
static let shared = MPPositive_BrowseLoadViewModel()
///()
var browseModuleLists:[MPPositive_BrowseModuleListViewModel] = []
///Library
var libraryList:MPPositive_LibraryListViewModel = .init()
//
private var isAction:Bool = false
//
@ -18,9 +21,11 @@ class MPPositive_BrowseLoadViewModel: NSObject {
override init() {
super.init()
setNetWorkBlock()
MPPositive_LoadCoreModel.shared.reloadAll()
}
//
private func setNetWorkBlock() {
//browse
MP_NetWorkManager.shared.browseRequestStateBlock = {
[weak self] (lists,isCompleted) in
@ -51,27 +56,29 @@ class MPPositive_BrowseLoadViewModel: NSObject {
//
DispatchQueue.main.async{
[weak self] in
guard let self = self else {
return
}
//
if let index = browseModuleLists.firstIndex(where: {$0.items.first?.browseItem.pageType == "MUSIC_PAGE_TYPE_ARTIST"}) {
//
let removedElement = browseModuleLists.remove(at: index)
//
browseModuleLists.insert(removedElement, at: 1)
}
//
if let index = browseModuleLists.firstIndex(where: {$0.items.first?.browseItem.pageType == "MUSIC_VIDEO_TYPE_OMV"}) {
//
let removedElement = browseModuleLists.remove(at: index)
//
browseModuleLists.append(removedElement)
}
NotificationCenter.notificationKey.post(notificationName: .positive_browses_reload)
//
if browseModuleLists.count != 0 {
cacheResponseData(browseModuleLists)
guard let self = self else {return}
libraryList.reloadLibrarys{
[weak self] in
guard let self = self else {return}
//
if let index = browseModuleLists.firstIndex(where: {$0.items.first?.browseItem.pageType == "MUSIC_PAGE_TYPE_ARTIST"}) {
//
let removedElement = browseModuleLists.remove(at: index)
//
browseModuleLists.insert(removedElement, at: 1)
}
//
if let index = browseModuleLists.firstIndex(where: {$0.items.first?.browseItem.pageType == "MUSIC_VIDEO_TYPE_OMV"}) {
//
let removedElement = browseModuleLists.remove(at: index)
//
browseModuleLists.append(removedElement)
}
NotificationCenter.notificationKey.post(notificationName: .positive_browses_reload)
//
if browseModuleLists.count != 0 {
cacheResponseData(browseModuleLists)
}
}
}
}
@ -94,6 +101,7 @@ class MPPositive_BrowseLoadViewModel: NSObject {
}
///
func reloadBrowseLists() {
MPPositive_LoadCoreModel.shared.reloadAll()
//
browseModuleLists.removeAll()
//
@ -178,8 +186,10 @@ class MPPositive_BrowseLoadViewModel: NSObject {
browseModuleLists = arrays
isRefresh = false
print("更新下拉刷新")
if let block = reloadCompleted {
block()
libraryList.reloadLibrarys{
if let block = reloadCompleted {
block()
}
}
}
}

View File

@ -26,6 +26,9 @@ class MPPositive_LoadCoreModel: NSObject {
private override init() {
super.init()
// reloadAll()
}
func reloadAll() {
reloadCollectionListViewModels(nil)
reloadCollectionArtistViewModels(nil)
reloadCollectionSongViewModel(nil)

View File

@ -138,8 +138,8 @@ class MPPositive_PlayerLoadViewModel: NSObject {
self.listViewVideos.append(contentsOf: viewModels)
//
self.currentVideo = self.listViewVideos.first(where: {$0.song.videoId == targetVideoId})
//5
self.listViewVideos = self.listViewVideos.suffix(4)
//7
self.listViewVideos = self.listViewVideos.suffix(7)
}
///
func remakeImproveData(_ completion:@escaping (() -> Void)) {

View File

@ -28,12 +28,16 @@ class MPPositive_PresentationController: UIPresentationController {
// MARK: - ()
override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
guard let _ = presentedView?.superview else {
presentedViewController.dismiss(animated: true, completion: nil)
return
}
//
switch MPPositive_ModalType {
case .PlayerList:
presentedView?.snp.makeConstraints({ (make) in
make.left.right.bottom.equalToSuperview()
make.height.equalTo(380*width)
make.height.equalTo(498*width)
})
case .MoreOperations:
presentedView?.snp.makeConstraints({ (make) in

View File

@ -111,6 +111,7 @@ extension MPPositive_TabBarController {
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)
}

View File

@ -165,7 +165,7 @@ class MPPositive_CustomPlayListViewController: MPPositive_BaseViewController, UI
coverImageView.kf.setImage(with: coverURL, placeholder: placeholderImage)
titleLabel.text = list.title
createTimeLabel.text = "Create Time: \(list.createTime.toString(.custom("YYYY/MM/dd-HH:mm")))"
playAllBtn.setTitle(" Play all (\(list.videosArray.count))", for: .normal)
playAllBtn.setTitle(" Play (\(list.videosArray.count))", for: .normal)
tableView.reloadData()
}
//

View File

@ -117,15 +117,15 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
//
songsLabel.text = "Songs \(MPPositive_LoadCoreModel.shared.songViewModels.count)"
let songCover = MPPositive_LoadCoreModel.shared.songViewModels.first?.coverURL
coverImageViews[0].kf.setImage(with: songCover, placeholder: placeholderImage)
coverImageViews[0].kf.setImage(with: songCover, placeholder: love_songBGImage)
artistsLabel.text = "Artists \(MPPositive_LoadCoreModel.shared.artistViewModels.count)"
let artistCover = MPPositive_LoadCoreModel.shared.artistViewModels.first?.coverURL
coverImageViews[1].kf.setImage(with: artistCover, placeholder: placeholderImage)
coverImageViews[1].kf.setImage(with: artistCover, placeholder: love_artistBGImage)
loadsLabel.text = "Offline \(MPPositive_LoadCoreModel.shared.loadViewModels.count)"
let loadCover = MPPositive_LoadCoreModel.shared.loadViewModels.first?.reviewURL
coverImageViews[2].kf.setImage(with: loadCover, placeholder: placeholderImage)
coverImageViews[2].kf.setImage(with: loadCover, placeholder: offline_songBGImage)
}
}
@ -219,13 +219,13 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
iconImageView.snp.makeConstraints { make in
make.width.height.equalTo(20*width)
make.left.equalToSuperview().offset(8*width)
make.bottom.equalToSuperview().offset(-8*width)
make.top.equalToSuperview().offset(13*width)
}
//
actionView.addSubview(label)
label.snp.makeConstraints { make in
make.centerY.equalTo(iconImageView)
make.left.equalTo(iconImageView.snp.right).offset(4*width)
make.left.equalTo(iconImageView.snp.left)
make.top.equalToSuperview().offset(40*width)
make.right.equalToSuperview().offset(-8*width)
}
actionView.tag = tag
@ -238,12 +238,15 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
let tag = sender.view?.tag
switch tag {
case 0:
MP_AnalyticsManager.shared.library_clickAction("tab page", folder: "love")
let loveSongsVC = MPPositive_LoveSongsViewController()
navigationController?.pushViewController(loveSongsVC, animated: true)
case 1:
MP_AnalyticsManager.shared.library_clickAction("tab page", folder: "artist")
let loveArtistsVC = MPPositive_LoveArtistsViewController()
navigationController?.pushViewController(loveArtistsVC, animated: true)
default:
MP_AnalyticsManager.shared.library_clickAction("tab page", folder: "offline")
let offlineVC = MPPositive_OfflineSongsViewController()
navigationController?.pushViewController(offlineVC, animated: true)
}
@ -275,6 +278,7 @@ extension MPPositive_LibraryViewController:JXSegmentedListContainerViewDataSourc
list.createTime = Date().timeZone()
list.addToRelationshipToCustomVideos([])
MPPositive_CustomPlayListModel.save()
MP_AnalyticsManager.shared.create_list_actionAction()
//
print("成功新建\(text)歌单")
//
@ -287,6 +291,7 @@ extension MPPositive_LibraryViewController:JXSegmentedListContainerViewDataSourc
showView.chooseBlock = {
[weak self] item in
guard let self = self else {return}
MP_AnalyticsManager.shared.library_clickAction("tab page", folder: "custom")
//
let playListVC = MPPositive_CustomPlayListViewController(item.playList)
navigationController?.pushViewController(playListVC, animated: true)

View File

@ -30,6 +30,7 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
tableView.rowHeight = UITableView.automaticDimension
tableView.dataSource = self
tableView.delegate = self
tableView.register(MPPositive_HomeLibraryListstableViewCell.self, forCellReuseIdentifier: MPPositive_HomeLibraryListstableViewCellID)
tableView.register(MPPositive_HomeSinglesTableViewCell.self, forCellReuseIdentifier: MPPositive_HomeSinglesTableViewCellID)
tableView.register(MPPositive_HomeShowTableViewCell.self, forCellReuseIdentifier: MPPositive_HomeShowTableViewCellID)
tableView.contentInset = .init(top: 0, left: 0, bottom: 70*width, right: 0)
@ -44,6 +45,7 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
tableView.mj_header = header
return tableView
}()
private let MPPositive_HomeLibraryListstableViewCellID = "MPPositive_HomeLibraryListstableViewCell"
private let MPPositive_HomeSinglesTableViewCellID = "MPPositive_HomeSinglesTableViewCell"
private let MPPositive_HomeShowTableViewCellID = "MPPositive_HomeShowTableViewCell"
private var isFirstAppearance:Bool = true
@ -56,7 +58,6 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
// private var loadViewModel:MPPositive_BrowseLoadViewModel!
override func viewDidLoad() {
super.viewDidLoad()
MP_AdMobManager.shared.loadAnyAdMobs()
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
//
requestTrackingAuthorization { idfa in
@ -118,6 +119,11 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.notificationKey.add(observer: self, selector: #selector(reloadAction(_ :)), notificationName: .positive_browses_reload)
MPPositive_BrowseLoadViewModel.shared.libraryList.reloadLibrarys{
[weak self] in
guard let self = self else {return}
reloadAction(nil)
}
if isFirstAppearance == false {
//
presentGuide()
@ -157,6 +163,7 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
//
@objc fileprivate func searchClick(_ sender:UITapGestureRecognizer) {
isFirstAppearance = false
MP_AnalyticsManager.shared.search_from_actionAction("home page")
let resultVC = MPPositive_SearchResultShowViewController()
navigationController?.pushViewController(resultVC, animated: false)
}
@ -311,86 +318,184 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
}
//MARK: - tableView
extension MPPositive_HomeViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count
if MPPositive_BrowseLoadViewModel.shared.libraryList.libraryViewModels.isEmpty {
return 1
}else {
return 2
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
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
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let first = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section].items.first, first.browseItem.itemType == .single, first.browseItem.pageType == "MUSIC_VIDEO_TYPE_ATV" {
//
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeSinglesTableViewCellID, for: indexPath) as! MPPositive_HomeSinglesTableViewCell
cell.browseViewModel = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section]
return cell
}else {
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeShowTableViewCellID, for: indexPath) as! MPPositive_HomeShowTableViewCell
cell.browseViewModel = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section]
if let first = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section].items.first, first.browseItem.itemType == .single, first.browseItem.pageType == "MUSIC_VIDEO_TYPE_OMV" {
cell.showType = .Fifth
if MPPositive_BrowseLoadViewModel.shared.libraryList.libraryViewModels.isEmpty {
if let first = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.row].items.first, first.browseItem.itemType == .single, first.browseItem.pageType == "MUSIC_VIDEO_TYPE_ATV" {
//
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeSinglesTableViewCellID, for: indexPath) as! MPPositive_HomeSinglesTableViewCell
cell.browseViewModel = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.row]
return cell
}else {
//
if MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section].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[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
}else {
cell.showType = .Third
//
if MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.row].items.first?.browseItem.pageType == "MUSIC_PAGE_TYPE_ARTIST" {
cell.showType = .Fourth
}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 ?? ""){ [weak self] listSongs in
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}
//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()
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 ?? ""){ [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 ?? "")
navigationController?.pushViewController(listVC, animated: true)
case .artist:
isFirstAppearance = false
//
let artistVC = MPPositive_ArtistShowViewController(item.browseItem.artistId ?? "")
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[indexPath.row])
navigationController?.pushViewController(moreVC, animated: true)
}
return cell
}
}else {
switch indexPath.section {
case 0:
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" {
//
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
}else {
//
if MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.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 ?? "")
navigationController?.pushViewController(listVC, animated: true)
case .artist:
isFirstAppearance = false
//
let artistVC = MPPositive_ArtistShowViewController(item.browseItem.artistId ?? "")
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 ?? ""){ [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 ?? "")
navigationController?.pushViewController(listVC, animated: true)
case .artist:
isFirstAppearance = false
//
let artistVC = MPPositive_ArtistShowViewController(item.browseItem.artistId ?? "")
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[indexPath.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.section])
navigationController?.pushViewController(moreVC, animated: true)
}
return cell
}
}
}

View File

@ -7,9 +7,22 @@
import UIKit
class MPPositive_PlayerListShowViewController: UIViewController {
class MPPositive_PlayerListShowViewController: UIViewController, UIViewControllerTransitioningDelegate {
//
private lazy var indictorImageView:UIImageView = .init(image: .init(named: "Player_Indictor'logo"))
//
private lazy var artistView:UIView = {
let artistView:UIView = createTopView("Artist", image: .init(named: "Search Artist'logo"))
//
artistView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(searchArtistClick(_ :))))
return artistView
}()
//
private lazy var listView:UIView = {
let listView:UIView = createTopView("Add playlist", image: .init(named: "Add PlayList'logo"))
listView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(addPlayListClick(_ :))))
return listView
}()
//tableView
private lazy var tableView:UITableView = {
let tableView = UITableView(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), style: .plain)
@ -25,6 +38,8 @@ class MPPositive_PlayerListShowViewController: UIViewController {
return tableView
}()
private let MPPositive_PlayerListShowTableViewCellID = "MPPositive_PlayerListShowTableViewCell"
var searchBlock:((String) -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .init(hex: "#1A1A1A")
@ -38,6 +53,34 @@ class MPPositive_PlayerListShowViewController: UIViewController {
deinit {
NotificationCenter.default.removeObserver(self)
}
//View
private func createTopView(_ title:String, image:UIImage?) -> UIView {
let backView:UIView = UIView()
backView.backgroundColor = .clear
backView.isUserInteractionEnabled = true
backView.layer.masksToBounds = false
//view
let centerView:UIView = UIView(frame: .init(x: 0, y: 0, width: 52*width, height: 52*width))
centerView.layer.masksToBounds = true
centerView.layer.cornerRadius = 26*width
centerView.backgroundColor = .init(hex: "#282828")
let iconImageView:UIImageView = .init(image: image)
centerView.addSubview(iconImageView)
iconImageView.snp.makeConstraints { make in
make.center.equalToSuperview()
make.width.height.equalTo(24*width)
}
backView.addSubview(centerView)
//Label
let label = createLabel(title, font: .systemFont(ofSize: 12*width, weight: .regular), textColor: .white, textAlignment: .center)
backView.addSubview(label)
label.snp.makeConstraints { make in
make.top.equalTo(centerView.snp.bottom).offset(6*width)
make.centerX.equalToSuperview()
}
return backView
}
private func configure() {
view.addSubview(indictorImageView)
indictorImageView.snp.makeConstraints { make in
@ -46,9 +89,21 @@ class MPPositive_PlayerListShowViewController: UIViewController {
make.height.equalTo(4*width)
make.top.equalTo(12*width)
}
view.addSubview(artistView)
artistView.snp.makeConstraints { make in
make.width.height.equalTo(52*width)
make.left.equalToSuperview().offset(18*width)
make.top.equalToSuperview().offset(48*width)
}
view.addSubview(listView)
listView.snp.makeConstraints { make in
make.width.height.equalTo(52*width)
make.left.equalTo(artistView.snp.right).offset(40*width)
make.centerY.equalTo(artistView.snp.centerY)
}
view.addSubview(tableView)
tableView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(38*width)
make.top.equalToSuperview().offset(150*width)
make.left.right.bottom.equalToSuperview()
}
}
@ -59,17 +114,50 @@ class MPPositive_PlayerListShowViewController: UIViewController {
@objc private func currentVideoReloadAction(_ sender:Notification) {
tableView.reloadData()
}
//
@objc private func searchArtistClick(_ sender:UITapGestureRecognizer) {
guard let currentVideo = MP_PlayerManager.shared.loadPlayer?.currentVideo, let subtitle = currentVideo.subtitle, subtitle.isEmpty == false else {
dismiss(animated: true)
return
}
//
dismiss(animated: true) {
[weak self] in
if let block = self?.searchBlock {
block(subtitle)
}
}
}
//
@objc private func addPlayListClick(_ sender:UITapGestureRecognizer) {
guard let currentVideo = MP_PlayerManager.shared.loadPlayer?.currentVideo else {
dismiss(animated: true)
return
}
//
MPPositive_ModalType = .MoreOperations
let chooseVC = MPPositive_ChoosePlayListViewController(currentVideo.song)
chooseVC.disMissBlock = {
[weak self] in
self?.dismiss(animated: true)
}
chooseVC.transitioningDelegate = self
chooseVC.modalPresentationStyle = .custom
present(chooseVC, animated: true)
}
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return MPPositive_PresentationController(presentedViewController: presented, presenting: presenting)
}
}
//MARK: - tableView
extension MPPositive_PlayerListShowViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//MP_PlayerManager
return MP_PlayerManager.shared.loadPlayer.songVideos.count
return MP_PlayerManager.shared.loadPlayer?.songVideos.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_PlayerListShowTableViewCellID, for: indexPath) as! MPPositive_PlayerListShowTableViewCell
cell.song = MP_PlayerManager.shared.loadPlayer.songVideos[indexPath.row]
cell.song = MP_PlayerManager.shared.loadPlayer?.songVideos[indexPath.row]
cell.removeBlock = {
[weak self] in
if MP_PlayerManager.shared.loadPlayer.songVideos.count > 1 {

View File

@ -51,6 +51,7 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
btn.addTarget(self, action: #selector(relatedContentClick(_ :)), for: .touchUpInside)
return btn
}()
//MARK: -
//
private lazy var backImageView:UIImageView = {
@ -67,8 +68,43 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.alpha = 1
blurEffectView.isUserInteractionEnabled = false
blurEffectView.contentView.addSubview(blurContentView)
blurContentView.snp.makeConstraints { make in
make.left.top.right.bottom.equalToSuperview()
}
return blurEffectView
}()
//View
private lazy var blurContentView:UIView = {
let contentView = UIView()
contentView.backgroundColor = .clear
return contentView
}()
///View
private lazy var maskNotReachableView:UIView = {
let maskView = UIView(frame: .init(x: 0, y: 0, width: 300*width, height: 35*width))
maskView.backgroundColor = .init(hex: "#000000", alpha: 0.6)
maskView.layer.masksToBounds = true
maskView.layer.cornerRadius = 21*width
//label
let noticeLabel:UILabel = createLabel("Bad connection~", font: .systemFont(ofSize: 13*width, weight: .regular), textColor: .white, textAlignment: .center, lines: 0)
maskView.addSubview(noticeLabel)
noticeLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.centerX.equalToSuperview().multipliedBy(1.2)
}
//icon
let iconImageView:UIImageView = .init(image: .init(named: "Player_NoNet'log"))
maskView.addSubview(iconImageView)
iconImageView.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.right.equalTo(noticeLabel.snp.left).offset(-10*width)
make.width.equalTo(24*width)
make.height.equalTo(24*width)
}
return maskView
}()
//MARK: -
//
private lazy var playBtn:UIButton = {
@ -219,15 +255,24 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
NotificationCenter.notificationKey.add(observer: self, selector: #selector(statusSwitchAction(_:)), notificationName: .switch_player_status)
NotificationCenter.notificationKey.add(observer: self, selector: #selector(playerTypeSwitchAction(_:)), notificationName: .player_type_switch)
NotificationCenter.notificationKey.add(observer: self, selector: #selector(deleteListAction(_:)), notificationName: .player_delete_list)
//
NotificationCenter.notificationKey.add(observer: self, selector: #selector(netWorkNotReachableAction(_:)), notificationName: .net_switch_notReachable)
NotificationCenter.notificationKey.add(observer: self, selector: #selector(netWorkReachableAction(_:)), notificationName: .net_switch_reachable)
// switchPlayBtnStatu(MP_PlayerManager.shared.getPlayState())
//
if MP_PlayerManager.shared.loadPlayer?.currentVideo != nil {
uploadUI()
}
if MP_PlayerManager.shared.videoLayer.player != MP_PlayerManager.shared.player {
MP_PlayerManager.shared.videoLayer.player = MP_PlayerManager.shared.player
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
MP_PlayerManager.shared.videoLayer.player = nil
// print("Layer")
// MP_PlayerManager.shared.videoLayer.removeFromSuperlayer()
}
//
private func configure() {
@ -289,6 +334,19 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
make.height.equalTo(480*width)
}
coverView.isHidden = false
if MP_PlayerManager.shared.videoLayer.superlayer == nil {
print("将视频Layer添加")
coverView.videoView.layer.addSublayer(MP_PlayerManager.shared.videoLayer)
MP_PlayerManager.shared.videoLayer.frame = .init(x: 0, y: 0, width: screen_Width, height: 360*width )
}
view.addSubview(maskNotReachableView)
maskNotReachableView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalTo(navView.snp.bottom)
make.width.equalTo(176*width)
make.height.equalTo(42*width)
}
maskNotReachableView.isHidden = (MP_NetWorkManager.shared.netWorkStatu == .reachable)
}
//View
private func createSwitchActionView() -> UIView {
@ -316,6 +374,8 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
//
return actionView
}
//
private func createStatueBtn(_ text:String = "text", color:UIColor, tag:Int) -> UIButton {
let btn = UIButton()
@ -380,26 +440,51 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
private func uploadUI() {
DispatchQueue.main.async {
[weak self] in
guard let self = self, MP_PlayerManager.shared.loadPlayer?.currentVideo != nil else {return}
print("\(MP_PlayerManager.shared.loadPlayer?.currentVideo?.title ?? "")刷新了页面")
guard let self = self, let currentVideo = MP_PlayerManager.shared.loadPlayer?.currentVideo else {return}
print("\(currentVideo.title ?? "")刷新了页面")
//
backImageView.kf.setImage(with: MP_PlayerManager.shared.loadPlayer.currentVideo?.coverUrl, placeholder: placeholderImage)
coverView.coverImageView.kf.setImage(with: MP_PlayerManager.shared.loadPlayer.currentVideo?.coverUrl, placeholder: placeholderImage)
coverView.titleLabel.text = MP_PlayerManager.shared.loadPlayer?.currentVideo?.title
coverView.subtitleLabel.text = MP_PlayerManager.shared.loadPlayer?.currentVideo?.subtitle
lyricsView.titleLabel.text = MP_PlayerManager.shared.loadPlayer.currentVideo?.title
lyricsView.subtitleLabel.text = MP_PlayerManager.shared.loadPlayer?.currentVideo?.subtitle
lyricsView.lyricsLabel.text = (MP_PlayerManager.shared.loadPlayer?.currentVideo?.lyrics ?? "").isEmpty == true ? "No Lyrics":MP_PlayerManager.shared.loadPlayer?.currentVideo?.lyrics
MPPositive_DownloadItemModel.fetch(predicate: .init(format: "videoId == %@", MP_PlayerManager.shared.loadPlayer?.currentVideo?.song.videoId ?? "")) { [weak self] results in
backImageView.kf.setImage(with: currentVideo.coverUrl, placeholder: placeholderImage)
coverView.coverImageView.kf.setImage(with: currentVideo.coverUrl, placeholder: placeholderImage)
coverView.titleLabel.text = currentVideo.title
coverView.subtitleLabel.text = currentVideo.subtitle
lyricsView.titleLabel.text = currentVideo.title
lyricsView.subtitleLabel.text = currentVideo.subtitle
lyricsView.lyricsLabel.text = (currentVideo.lyrics ?? "").isEmpty == true ? "No Lyrics":currentVideo.lyrics
MPPositive_DownloadItemModel.fetch(predicate: .init(format: "videoId == %@", currentVideo.song.videoId ?? "")) { [weak self] results in
self?.coverView.downloadButton.state = results.count != 0 ? .downloaded:.startDownload
}
coverView.collectionSongBtn.isSelected = MP_PlayerManager.shared.loadPlayer?.currentVideo?.isCollection ?? false
coverView.setProgress(MP_PlayerManager.shared.loadPlayer?.currentVideo?.song?.videoId ?? "")
coverView.collectionSongBtn.isSelected = currentVideo.isCollection ?? false
coverView.setProgress(currentVideo.song?.videoId ?? "")
switchPlayTypeBtnIcon(typeBtn)
if let item = currentVideo.resourcePlayerItem {
MP_PlayerManager.shared.isCoverVideo(playerItem: item) { [weak self] bool in
DispatchQueue.main.async {
self?.blurContentView.backgroundColor = bool ? .clear:.black
self?.coverView.coverImageView.isHidden = !bool
self?.coverView.videoView.isHidden = bool
}
}
}
// activityIndicator.isHidden = true
// activityIndicator.stopAnimating()
}
}
//
@objc private func netWorkNotReachableAction(_ sender:Notification) {
DispatchQueue.main.async {
[weak self] in
guard let self = self else {return}
maskNotReachableView.isHidden = false
}
}
//
@objc private func netWorkReachableAction(_ sender:Notification) {
DispatchQueue.main.async {
[weak self] in
guard let self = self else {return}
maskNotReachableView.isHidden = true
}
}
//MARK: -
//
@objc private func playerReloadAction(_ sender:Notification) {
@ -539,11 +624,8 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
////
@objc private func playClick(_ sender:UIButton) {
// guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
// MP_HUD.text("Weak connection.", delay: 2.0, completion: nil)
// return
// }
guard MP_PlayerManager.shared.loadPlayer != nil else {
guard let _ = MP_PlayerManager.shared.loadPlayer else {
return
}
//
@ -569,14 +651,20 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
}
//
@objc private func listClick(_ sender:UIButton) {
// guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
// MP_HUD.text("Weak connection.", delay: 2.0, completion: nil)
// return
// }
if MP_PlayerManager.shared.loadPlayer != nil {
guard let _ = MP_PlayerManager.shared.loadPlayer else {return}
MPPositive_Debouncer.shared.call {
[weak self] in
guard let self = self else {return}
MPPositive_ModalType = .PlayerList
let listVC = MPPositive_PlayerListShowViewController()
listVC.searchBlock = {
[weak self] (text) in
self?.dismiss(animated: true) {
if let block = self?.searchBlock {
block(text)
}
}
}
listVC.transitioningDelegate = self
listVC.modalPresentationStyle = .custom
present(listVC, animated: true)
@ -587,10 +675,6 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
}
////
@objc private func typeClick(_ sender:UIButton) {
// guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
// MP_HUD.text("Weak connection.", delay: 2.0, completion: nil)
// return
// }
MPPositive_Debouncer.shared.call {
[weak self] in
guard let self = self else {return}
@ -605,11 +689,7 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
}
//
@objc private func nextClick(_ sender:UIButton) {
// guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
// MP_HUD.text("Weak connection.", delay: 2.0, completion: nil)
// return
// }
guard MP_PlayerManager.shared.loadPlayer?.currentVideo != nil else {
guard let _ = MP_PlayerManager.shared.loadPlayer?.currentVideo else {
return
}
//广
@ -626,11 +706,8 @@ class MPPositive_PlayerViewController: MPPositive_BaseViewController, UIViewCont
}
//
@objc private func previousClick(_ sender:UIButton) {
// guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
// MP_HUD.text("Weak connection.", delay: 2.0, completion: nil)
// return
// }
guard MP_PlayerManager.shared.loadPlayer?.currentVideo != nil else {
guard let _ = MP_PlayerManager.shared.loadPlayer?.currentVideo else {
return
}
//广

View File

@ -67,6 +67,11 @@ class MPPositive_SearchResultShowViewController: MPPositive_BaseViewController,
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
[weak self] in
guard let self = self else {return}
searchTextField.becomeFirstResponder()
}
}
init(_ text:String, isShowAd:Bool = true) {

View File

@ -156,6 +156,7 @@ class MPPositive_SearchViewController: MPPositive_BaseViewController {
}
//
@objc fileprivate func searchClick(_ sender:UITapGestureRecognizer) {
MP_AnalyticsManager.shared.search_from_actionAction("search page")
let resultVC = MPPositive_SearchResultShowViewController()
navigationController?.pushViewController(resultVC, animated: false)
}
@ -199,7 +200,7 @@ extension MPPositive_SearchViewController: UICollectionViewDataSource, UICollect
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == historyCollectionView {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MPPositive_SearchTagCollectionViewCellID, for: indexPath) as! MPPositive_SearchTagCollectionViewCell
cell.setText(MPPositive_LoadCoreModel.shared.searchTags[indexPath.row].text)
cell.setText(MPPositive_LoadCoreModel.shared.searchTags[indexPath.row].text ?? "")
return cell
}else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MPPositive_SearchGrideCollectionViewCellID, for: indexPath) as! MPPositive_SearchGrideCollectionViewCell

View File

@ -0,0 +1,66 @@
//
// MPPositive_HomeLibraryListCollectionViewCell.swift
// relax.offline.mp3.music
//
// Created by Mr.Zhou on 2024/7/24.
//
import UIKit
import Kingfisher
class MPPositive_HomeLibraryListCollectionViewCell: UICollectionViewCell {
//
private lazy var coverImageView:UIImageView = {
let imageView:UIImageView = .init()
imageView.contentMode = .scaleAspectFill
imageView.layer.masksToBounds = true
imageView.layer.cornerRadius = 16*width
return imageView
}()
private lazy var iconImageView:UIImageView = {
let iconImageView:UIImageView = .init()
iconImageView.contentMode = .scaleAspectFill
return iconImageView
}()
//Label
private lazy var titleLabel:UILabel = createLabel("Title", font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left)
var library:MPPositive_LibraryViewModel!{
didSet{
coverImageView.kf.setImage(with: library.cover, placeholder: library.library.libraryType.image)
titleLabel.text = library.title
if let icon = library.library.libraryType.icon {
iconImageView.image = icon
}else {
iconImageView.image = nil
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
confirgue()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
//
private func confirgue() {
backgroundColor = .clear
layer.masksToBounds = true
addSubview(coverImageView)
coverImageView.snp.makeConstraints { make in
make.left.top.right.equalToSuperview()
make.height.equalTo(109*width)
}
addSubview(iconImageView)
iconImageView.snp.makeConstraints { make in
make.width.height.equalTo(20*width)
make.left.equalToSuperview().offset(8*width)
make.top.equalToSuperview().offset(13*width)
}
addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.top.equalTo(coverImageView.snp.bottom).offset(9*width)
make.left.right.equalToSuperview()
}
}
}

View File

@ -0,0 +1,126 @@
//
// MPPositive_HomeLibraryListstableViewCell.swift
// relax.offline.mp3.music
//
// Created by Mr.Zhou on 2024/7/24.
//
import UIKit
///Cell
class MPPositive_HomeLibraryListstableViewCell: UITableViewCell {
//Label
private lazy var titleLabel:UILabel = createLabel("Library", font: .systemFont(ofSize: 18*width, weight: .regular), textColor: .white, textAlignment: .left)
private lazy var layout:UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout()
layout.itemSize = .init(width: 109*width, height: 135*width)
layout.sectionInset = .init(top: 10*width, left: 16*width, bottom: 0, right: 16*width)
layout.minimumLineSpacing = 8*width
layout.minimumInteritemSpacing = 0
layout.scrollDirection = .horizontal
return layout
}()
//collectionView
private lazy var collectionView:UICollectionView = {
let collectionView:UICollectionView = .init(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), collectionViewLayout: layout)
collectionView.showsVerticalScrollIndicator = false
collectionView.showsHorizontalScrollIndicator = false
collectionView.backgroundColor = .clear
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(MPPositive_HomeLibraryListCollectionViewCell.self, forCellWithReuseIdentifier: MPPositive_HomeLibraryListCollectionViewCellID)
return collectionView
}()
fileprivate let MPPositive_HomeLibraryListCollectionViewCellID = "MPPositive_HomeLibraryListCollectionViewCell"
var libraryViewModels: [MPPositive_LibraryViewModel] = [] {
didSet{
collectionView.reloadData()
}
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .none
backgroundColor = .clear
configure()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
private func configure() {
//UI
contentView.addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(16*width)
make.top.equalToSuperview().offset(8*width)
make.right.equalToSuperview().offset(-16*width)
}
contentView.addSubview(collectionView)
collectionView.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom)
make.left.right.equalToSuperview()
make.bottom.equalToSuperview().offset(-25*width).priority(999)
}
}
//tableViewCell
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
let size = super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
collectionView.layoutIfNeeded()
//
let height = layout.itemSize.height + layout.sectionInset.top + layout.sectionInset.bottom
return CGSize(width: size.width, height: size.height + height)
}
}
//MARK: - collectionView
extension MPPositive_HomeLibraryListstableViewCell:UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return libraryViewModels.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MPPositive_HomeLibraryListCollectionViewCellID, for: indexPath) as! MPPositive_HomeLibraryListCollectionViewCell
cell.library = libraryViewModels[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard (libraryViewModels.count - 1) >= indexPath.row else {
return
}
let item = libraryViewModels[indexPath.row]
switch item.library.libraryType {
case .love_songs:
MP_AnalyticsManager.shared.library_clickAction("home page", folder: "love")
let loveSongsVC = MPPositive_LoveSongsViewController()
parentController()?.navigationController?.pushViewController(loveSongsVC, animated: true)
case .love_aritists:
MP_AnalyticsManager.shared.library_clickAction("home page", folder: "artist")
let loveArtistsVC = MPPositive_LoveArtistsViewController()
parentController()?.navigationController?.pushViewController(loveArtistsVC, animated: true)
case .offline_songs:
MP_AnalyticsManager.shared.library_clickAction("home page", folder: "offline")
let offlineVC = MPPositive_OfflineSongsViewController()
parentController()?.navigationController?.pushViewController(offlineVC, animated: true)
case .custom_playlist:
if let playListId = item.library.identifier {
//
MPPositive_CustomPlayListModel.fetchAll {[weak self] playList in
guard let self = self else {return}
if let list = playList.first(where: {$0.playListId == playListId}) {
MP_AnalyticsManager.shared.library_clickAction("home page", folder: "custom")
let playListVC = MPPositive_CustomPlayListViewController(list)
parentController()?.navigationController?.pushViewController(playListVC, animated: true)
}
}
}
}
MP_AdMobManager.shared.showLibraryInterstitialAdIfAvailable(completion: nil)
}
}

View File

@ -7,7 +7,7 @@ import DownloadButton
import MarqueeLabel
//BView(View)
class MPPositive_PlayerCoverView: UIView, PKDownloadButtonDelegate {
///
///
lazy var coverImageView:UIImageView = {
let imageView = UIImageView()
imageView.image = placeholderImage
@ -16,6 +16,12 @@ class MPPositive_PlayerCoverView: UIView, PKDownloadButtonDelegate {
imageView.layer.cornerRadius = 16*width
return imageView
}()
//
lazy var videoView:UIView = {
let videoView:UIView = .init()
videoView.backgroundColor = .clear
return videoView
}()
///
lazy var titleLabel:MarqueeLabel = createMarQueeLabel("Loading", font: .systemFont(ofSize: 22*width, weight: .regular), textColor: .init(hex: "#FFFFFF", alpha: 0.85))
///
@ -81,31 +87,7 @@ class MPPositive_PlayerCoverView: UIView, PKDownloadButtonDelegate {
lazy var durationLabel:UILabel = createLabel("00:00" ,font: .systemFont(ofSize: 12*width, weight: .medium), textColor: .init(hex: "#FFFFFF", alpha: 0.85), textAlignment: .left)
///Label
lazy var maxTimesLabel:UILabel = createLabel("00:00" ,font: .systemFont(ofSize: 12*width, weight: .medium), textColor: .init(hex: "#FFFFFF", alpha: 0.6), textAlignment: .right)
///View
private lazy var maskNotReachableView:UIView = {
let maskView = UIView()
maskView.backgroundColor = .init(hex: "#000000", alpha: 0.7)
maskView.layer.masksToBounds = true
maskView.layer.cornerRadius = 16*width
//icon
let iconImageView:UIImageView = .init(image: .init(named: "NoNetReache'log"))
maskView.addSubview(iconImageView)
iconImageView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.centerY.equalToSuperview().multipliedBy(0.8)
make.width.equalTo(52*width)
make.height.equalTo(42*width)
}
//label
let noticeLabel:UILabel = createLabel("Weak connection. Please check your network", font: .systemFont(ofSize: 18, weight: .medium), textColor: .white, textAlignment: .center, lines: 0)
maskView.addSubview(noticeLabel)
noticeLabel.snp.makeConstraints { make in
make.top.equalTo(iconImageView.snp.bottom).offset(20*width)
make.centerX.equalToSuperview()
make.width.equalToSuperview().multipliedBy(0.7)
}
return maskView
}()
//
var deleteBlock:(() -> Void)?
//
@ -116,9 +98,7 @@ class MPPositive_PlayerCoverView: UIView, PKDownloadButtonDelegate {
super.init(frame: frame)
backgroundColor = .clear
configure()
//
NotificationCenter.notificationKey.add(observer: self, selector: #selector(netWorkNotReachableAction(_:)), notificationName: .net_switch_notReachable)
NotificationCenter.notificationKey.add(observer: self, selector: #selector(netWorkReachableAction(_:)), notificationName: .net_switch_reachable)
NotificationCenter.notificationKey.add(observer: self, selector: #selector(downloadProgressAction(_ :)), notificationName: .download_progress_source)
NotificationCenter.notificationKey.add(observer: self, selector: #selector(downloadEndAction(_ :)), notificationName: .dowload_end_source)
@ -142,11 +122,7 @@ class MPPositive_PlayerCoverView: UIView, PKDownloadButtonDelegate {
make.centerX.equalToSuperview()
make.top.equalToSuperview().offset(12*width)
}
addSubview(maskNotReachableView)
maskNotReachableView.snp.makeConstraints { make in
make.left.right.top.bottom.equalTo(coverImageView)
}
maskNotReachableView.isHidden = (MP_NetWorkManager.shared.netWorkStatu == .reachable)
//
addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
@ -154,6 +130,12 @@ class MPPositive_PlayerCoverView: UIView, PKDownloadButtonDelegate {
make.top.equalTo(coverImageView.snp.bottom).offset(36*width)
make.right.equalTo(coverImageView.snp.right).offset(-100*width)
}
addSubview(videoView)
videoView.snp.makeConstraints { make in
make.left.top.right.equalToSuperview()
make.bottom.equalTo(titleLabel.snp.top).offset(0)
}
videoView.isHidden = true
addSubview(subtitleLabel)
subtitleLabel.snp.makeConstraints { make in
make.left.right.equalTo(titleLabel)
@ -256,22 +238,7 @@ class MPPositive_PlayerCoverView: UIView, PKDownloadButtonDelegate {
setProgress(videoId)
}
}
//
@objc private func netWorkNotReachableAction(_ sender:Notification) {
DispatchQueue.main.async {
[weak self] in
guard let self = self else {return}
maskNotReachableView.isHidden = false
}
}
//
@objc private func netWorkReachableAction(_ sender:Notification) {
DispatchQueue.main.async {
[weak self] in
guard let self = self else {return}
maskNotReachableView.isHidden = true
}
}
//
@objc private func searchSubtitleClick(_ sender:UITapGestureRecognizer) {
guard let text = subtitleLabel.text, text.isEmpty != true else {return}

View File

@ -23,7 +23,7 @@ class MPPositive_PlayerListShowTableViewCell: UITableViewCell {
///
private lazy var removeBtn:UIButton = {
let btn:UIButton = .init()
btn.setBackgroundImage(UIImage(named: "Player_ListRemove'logo"), for: .normal)
btn.setImage(UIImage(named: "Player_ListRemove'logo"), for: .normal)
btn.addTarget(self, action: #selector(removeClick(_ :)), for: .touchUpInside)
return btn
}()
@ -72,7 +72,7 @@ class MPPositive_PlayerListShowTableViewCell: UITableViewCell {
}
contentView.addSubview(removeBtn)
removeBtn.snp.makeConstraints { make in
make.width.height.equalTo(44*width)
make.width.height.equalTo(40*width)
make.centerY.equalTo(coverImageView.snp.centerY)
make.right.equalToSuperview().offset(-18*width)
}

View File

@ -190,8 +190,8 @@ extension MPPositive_SearchResultsShowView: JXSegmentedListContainerViewDataSour
return showView
}else {
//
if (loadModel.sectionLists.count-1) >= index {
let showView:MPPositive_SearchResultTypeShowView = .init(frame: listContainerView.frame, list: loadModel.sectionLists[index])
if let sectionList = loadModel?.sectionLists?[index] {
let showView:MPPositive_SearchResultTypeShowView = .init(frame: listContainerView.frame, list: sectionList)
showView.scrollBlock = {
[weak self] in
guard let self = self else {return}

View File

@ -43,6 +43,12 @@ extension MPSideA_SettingViewController: UITableViewDataSource, UITableViewDeleg
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: SettingTableViewCellID, for: indexPath) as! MPSideA_SettingTableViewCell
cell.title = titles[indexPath.row]
switch indexPath.row {
case titles.count - 1:
cell.sizeLabel.isHidden = !cleanSide
default:
cell.sizeLabel.isHidden = true
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
@ -106,6 +112,7 @@ extension MPSideA_SettingViewController: UITableViewDataSource, UITableViewDeleg
MP_HUD.hideNow()
MP_HUD.error("Failed", delay: 1.0, completion: nil)
}
tableView.reloadData()
}
}
alertController.addAction(sure)
@ -130,6 +137,7 @@ extension MPSideA_SettingViewController: UITableViewDataSource, UITableViewDeleg
}
MP_HUD.hideNow()
MP_HUD.success("Successfully", delay: 1.0, completion: nil)
tableView.reloadData()
}
alertController.addAction(sure)
present(alertController, animated: true)

View File

@ -29,7 +29,6 @@ class MPSideA_HomeViewController: MPSideA_BaseViewController {
private lazy var sectionTitles:[String] = ["", MPSideA_MusicShowType.First.title, MPSideA_MusicShowType.Second.title, MPSideA_MusicShowType.Third.title]
override func viewDidLoad() {
super.viewDidLoad()
MP_AdMobManager.shared.loadAnyAdMobs()
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
//
requestTrackingAuthorization { idfa in

View File

@ -11,11 +11,13 @@ class MPSideA_SettingTableViewCell: UITableViewCell {
@IBOutlet weak var iconImageView: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var nextImageView: UIImageView!
@IBOutlet weak var sizeLabel: UILabel!
var title:String!{
didSet{
iconImageView.image = UIImage(named: title)
titleLabel.text = title
nextImageView.isHidden = (title == "Clear Cache")
sizeLabel.text = MP_CacheAndArchiverManager.shared.getCacheSizeText()
}
}
override func awakeFromNib() {

View File

@ -84,6 +84,12 @@
</constraint>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HHW-p5-4g2">
<rect key="frame" x="318" y="25" width="41" height="20"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="3IY-8d-mQe" firstAttribute="leading" secondItem="p5m-ge-Frr" secondAttribute="trailing" constant="10" id="E92-0e-MZB">
@ -91,6 +97,7 @@
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
</userDefinedRuntimeAttributes>
</constraint>
<constraint firstItem="HHW-p5-4g2" firstAttribute="trailing" secondItem="zkg-Nc-aIA" secondAttribute="trailing" id="OXu-iy-0sz"/>
<constraint firstItem="3IY-8d-mQe" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="SjC-EV-a4b"/>
<constraint firstItem="p5m-ge-Frr" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="V5O-zu-X2t"/>
<constraint firstItem="p5m-ge-Frr" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="21" id="bNZ-uP-I6T">
@ -98,6 +105,7 @@
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
</userDefinedRuntimeAttributes>
</constraint>
<constraint firstItem="HHW-p5-4g2" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="cd0-fV-TB3"/>
<constraint firstAttribute="trailing" secondItem="zkg-Nc-aIA" secondAttribute="trailing" constant="16" id="rD1-Nd-e3i">
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="adapterScreen" value="YES"/>
@ -111,6 +119,7 @@
<connections>
<outlet property="iconImageView" destination="0OA-RG-Mvj" id="H7L-v4-o9h"/>
<outlet property="nextImageView" destination="zkg-Nc-aIA" id="Lec-GI-JWZ"/>
<outlet property="sizeLabel" destination="HHW-p5-4g2" id="jul-PL-3Gq"/>
<outlet property="titleLabel" destination="3IY-8d-mQe" id="CxU-44-zdZ"/>
</connections>
<point key="canvasLocation" x="131" y="-12"/>