B面1.1.3,视频播放实现
@ -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;
|
||||
};
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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"
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 991 B |
|
Before Width: | Height: | Size: 1.8 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Center_Artists'logo.imageset/艺术家@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Center_Artists'logo.imageset/艺术家@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
@ -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"
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 600 B |
|
Before Width: | Height: | Size: 1007 B |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Center_Offline'logo.imageset/下载@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 723 B |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Center_Offline'logo.imageset/下载@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
@ -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"
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 675 B |
|
Before Width: | Height: | Size: 1.2 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Center_Songs'logo.imageset/爱心·@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 797 B |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Center_Songs'logo.imageset/爱心·@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
22
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Love Artists'bg.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Love Artists'bg.imageset/蓝色背景@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Love Artists'bg.imageset/蓝色背景@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 140 KiB |
22
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Love Songs'bg.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Love Songs'bg.imageset/橙色背景@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Love Songs'bg.imageset/橙色背景@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 144 KiB |
22
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Offline Songs.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Offline Songs.imageset/紫色背景@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Offline Songs.imageset/紫色背景@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 134 KiB |
22
relax.offline.mp3.music/Assets.xcassets/Positive/More/Add PlayList'logo.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 780 B |
|
After Width: | Height: | Size: 1.3 KiB |
22
relax.offline.mp3.music/Assets.xcassets/Positive/More/Search Artist'logo.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
22
relax.offline.mp3.music/Assets.xcassets/Positive/Player/Player_NoNet'log.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 951 B |
|
After Width: | Height: | Size: 696 B |
@ -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>"Musiclax" 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>
|
||||
|
||||
@ -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)")
|
||||
//上传广告收益
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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")!
|
||||
///用户协议网址
|
||||
|
||||
@ -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 {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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("下载插页广告加载失败")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)")
|
||||
//发布事件
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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 {
|
||||
//实行串行异步队列,进行多次请求。由于第一次之后的请求都必须携带对应的continuation编码,所以串行队列。直到最后一次请求的continuation值为空,销毁队列
|
||||
// 实例化串行队列
|
||||
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) {
|
||||
// 根据错误类型处理
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -26,6 +26,8 @@ class MPPositive_BrowseItemModel: NSObject, Codable {
|
||||
var pageType:String?
|
||||
///是单曲/视频OR列表/歌单
|
||||
var itemType:BrowseItemType?
|
||||
|
||||
|
||||
}
|
||||
///预览个体类型
|
||||
enum BrowseItemType: Int, Codable{
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -129,7 +129,6 @@ class MPPositive_SongViewModel: NSObject {
|
||||
resourcePlayerAsset = .init(resourcePlayerURL!, videoId: song.videoId, title: title ?? "")
|
||||
}
|
||||
resourcePlayerItem = .init(asset: resourcePlayerAsset)
|
||||
|
||||
}
|
||||
//更新歌词
|
||||
if song.lyrics != nil {
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,9 @@ class MPPositive_LoadCoreModel: NSObject {
|
||||
|
||||
private override init() {
|
||||
super.init()
|
||||
// reloadAll()
|
||||
}
|
||||
func reloadAll() {
|
||||
reloadCollectionListViewModels(nil)
|
||||
reloadCollectionArtistViewModels(nil)
|
||||
reloadCollectionSongViewModel(nil)
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
//搜索状态刷新
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
}
|
||||
//切歌广告
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,7 @@ import DownloadButton
|
||||
import MarqueeLabel
|
||||
//B面播放器封面View(封面,标题,副标题,收藏,下载,进度条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}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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"/>
|
||||
|
||||