diff --git a/relax.offline.mp3.music.xcodeproj/project.pbxproj b/relax.offline.mp3.music.xcodeproj/project.pbxproj index 15b4ee5..06c6f6d 100644 --- a/relax.offline.mp3.music.xcodeproj/project.pbxproj +++ b/relax.offline.mp3.music.xcodeproj/project.pbxproj @@ -23,6 +23,10 @@ CB1E3B662C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */; }; CB1E3B682C23E09100071DEA /* MPPositive_CustomVideoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB1E3B672C23E09100071DEA /* MPPositive_CustomVideoModel.swift */; }; CB20A0702C53BDBF00FC5AFC /* MP_WebVisitorDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB20A06F2C53BDBF00FC5AFC /* MP_WebVisitorDataManager.swift */; }; + CB2CAAD42C59DC1100EF691D /* MPPositive_TrashListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB2CAAD32C59DC1100EF691D /* MPPositive_TrashListModel.swift */; }; + CB2CAAD72C5A1AC500EF691D /* MP_IAPViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CB2CAAD62C5A1AC500EF691D /* MP_IAPViewController.xib */; }; + CB2CAAD82C5A1AC500EF691D /* MP_IAPViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB2CAAD52C5A1AC500EF691D /* MP_IAPViewController.swift */; }; + CB4FA4D92C5CDC4A0027C949 /* relax.offline.mp3.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CB4FA4D72C5CDC4A0027C949 /* relax.offline.mp3.xcdatamodeld */; }; CB7FC5422C2AA01F00292A43 /* FacebookAEM in Frameworks */ = {isa = PBXBuildFile; productRef = CB7FC5412C2AA01F00292A43 /* FacebookAEM */; }; CB7FC5442C2AA01F00292A43 /* FacebookBasics in Frameworks */ = {isa = PBXBuildFile; productRef = CB7FC5432C2AA01F00292A43 /* FacebookBasics */; }; CB7FC5462C2AA01F00292A43 /* FacebookCore in Frameworks */ = {isa = PBXBuildFile; productRef = CB7FC5452C2AA01F00292A43 /* FacebookCore */; }; @@ -238,7 +242,6 @@ 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 */; }; - CBC2EBCA2C5277F1000ADA51 /* relax.offline.mp3.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CBC2EBC82C5277F1000ADA51 /* 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 */; }; @@ -274,6 +277,10 @@ CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CustomPlayListModel.swift; sourceTree = ""; }; CB1E3B672C23E09100071DEA /* MPPositive_CustomVideoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CustomVideoModel.swift; sourceTree = ""; }; CB20A06F2C53BDBF00FC5AFC /* MP_WebVisitorDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_WebVisitorDataManager.swift; sourceTree = ""; }; + CB2CAAD32C59DC1100EF691D /* MPPositive_TrashListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_TrashListModel.swift; sourceTree = ""; }; + CB2CAAD52C5A1AC500EF691D /* MP_IAPViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_IAPViewController.swift; sourceTree = ""; }; + CB2CAAD62C5A1AC500EF691D /* MP_IAPViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MP_IAPViewController.xib; sourceTree = ""; }; + CB4FA4D82C5CDC4A0027C949 /* MusicPlayer.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MusicPlayer.xcdatamodel; sourceTree = ""; }; CB7FC5472C2AC25C00292A43 /* MPPositive_CenterListSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CenterListSearchView.swift; sourceTree = ""; }; CBAFC9F22C0A10500054500E /* MP_BaseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MP_BaseViewController.swift; sourceTree = ""; }; CBAFC9F32C0A10500054500E /* MP_LunchViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MP_LunchViewController.swift; sourceTree = ""; }; @@ -485,7 +492,6 @@ CBC2D6FA2BFDF3D800E17703 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; CBC2D6FC2BFDF3D800E17703 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; CBC2D7792BFDF4B900E17703 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; - CBC2EBC92C5277F1000ADA51 /* MusicPlayer.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MusicPlayer.xcdatamodel; sourceTree = ""; }; CBC3F2B12C3E76160075DC74 /* MPPositive_AdModelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_AdModelModel.swift; sourceTree = ""; }; CBC81FB92C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_HomeSinglesTableViewCell.swift; sourceTree = ""; }; CBC81FBB2C3696230028143B /* MPPositive_HomeSingleCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_HomeSingleCollectionViewCell.swift; sourceTree = ""; }; @@ -562,6 +568,8 @@ CBAFC9F42C0A10500054500E /* MP_LunchViewController.xib */, CB15B8992C353B2400756E89 /* MP_GuideViewController.swift */, CB15B89A2C353B2400756E89 /* MP_GuideViewController.xib */, + CB2CAAD52C5A1AC500EF691D /* MP_IAPViewController.swift */, + CB2CAAD62C5A1AC500EF691D /* MP_IAPViewController.xib */, ); path = Controllers; sourceTree = ""; @@ -586,7 +594,7 @@ CBAFC9FB2C0A10500054500E /* DataBase */ = { isa = PBXGroup; children = ( - CBC2EBC82C5277F1000ADA51 /* relax.offline.mp3.xcdatamodeld */, + CB4FA4D72C5CDC4A0027C949 /* relax.offline.mp3.xcdatamodeld */, ); path = DataBase; sourceTree = ""; @@ -750,6 +758,7 @@ CBAFCA462C0A10500054500E /* MPPositive_SongItemModel.swift */, CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */, CB1E3B672C23E09100071DEA /* MPPositive_CustomVideoModel.swift */, + CB2CAAD32C59DC1100EF691D /* MPPositive_TrashListModel.swift */, ); path = Models; sourceTree = ""; @@ -1306,6 +1315,7 @@ CBAFCB022C0A10500054500E /* Howling Wind.mp3 in Resources */, CBAFCB842C0A10500054500E /* MPSideA_DeleteViewController.xib in Resources */, CBAFCB822C0A10500054500E /* MPSideA_CenterViewController.xib in Resources */, + CB2CAAD72C5A1AC500EF691D /* MP_IAPViewController.xib in Resources */, CBAFCB062C0A10500054500E /* waterfall.mp3 in Resources */, CBAFCAFE2C0A10500054500E /* Beach.mp3 in Resources */, CBC2D7D42BFDF4B900E17703 /* PrivacyInfo.xcprivacy in Resources */, @@ -1412,6 +1422,7 @@ CBC81FBA2C3694990028143B /* MPPositive_HomeSinglesTableViewCell.swift in Sources */, CBAFCB252C0A10500054500E /* MPPositive_CollectionArtistModel.swift in Sources */, CBAFCB702C0A10500054500E /* MPPositive_SearchResultShowTableViewCell.swift in Sources */, + CB2CAAD42C59DC1100EF691D /* MPPositive_TrashListModel.swift in Sources */, CBAFCB662C0A10500054500E /* MPPositive_HomeShowTableViewCell.swift in Sources */, CBAFCB352C0A10500054500E /* MPPositive_ListAlbumListViewModel.swift in Sources */, CBB75FDD2C4F7AA60041665D /* UIImageView.swift in Sources */, @@ -1424,10 +1435,12 @@ CBAFCAF52C0A10500054500E /* CoreDataDelegete.swift in Sources */, CBAFCB5B2C0A10500054500E /* MPPositive_ArtistShowCollectionViewCell.swift in Sources */, CBAFCB182C0A10500054500E /* MPPositive_JsonArtistMore.swift in Sources */, + CB4FA4D92C5CDC4A0027C949 /* relax.offline.mp3.xcdatamodeld in Sources */, CBAFCB982C0A10500054500E /* MPSideA_CustomTabBarItem.swift in Sources */, CBAFCB5D2C0A10500054500E /* MPPositive_ArtistShowListableViewCell.swift in Sources */, CBAFCB7D2C0A10500054500E /* MPSideA_PresentationController.swift in Sources */, CBAFCB2D2C0A10500054500E /* MPPositive_ArtistContentListViewModel.swift in Sources */, + CB2CAAD82C5A1AC500EF691D /* MP_IAPViewController.swift in Sources */, CBC1FB7E2C509BB400AC0633 /* MPPositive_LibraryListViewModel.swift in Sources */, CBAFCB992C0A10500054500E /* MPSideA_CustomTabBarView.swift in Sources */, CBAFCB342C0A10500054500E /* MPPositive_DownloadViewModel.swift in Sources */, @@ -1446,7 +1459,6 @@ CBAFCB7B2C0A10500054500E /* MPSideA_BaseViewController.swift in Sources */, CBAFCB102C0A10500054500E /* MP_NetWorkManager.swift in Sources */, CBAFCB9D2C0A10500054500E /* MPSideA_SettingTableViewCell.swift in Sources */, - CBC2EBCA2C5277F1000ADA51 /* relax.offline.mp3.xcdatamodeld in Sources */, CBAFCAEC2C0A10500054500E /* AVPlayerItem.swift in Sources */, CBAFCB7E2C0A10500054500E /* MPSideA_TabBarController.swift in Sources */, CBAFCB1D2C0A10500054500E /* MPPositive_JsonPlayer.swift in Sources */, @@ -1730,10 +1742,12 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1.1.4.1; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1.1.5.1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = T93S37G27F; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = RAQJ4FNZUH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = relax.offline.mp3.music/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Musiclax; @@ -1751,10 +1765,11 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.4; + MARKETING_VERSION = 1.1.5; PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Musiclax_Development; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1773,10 +1788,12 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1.1.4.1; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1.1.5.1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = T93S37G27F; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = RAQJ4FNZUH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = relax.offline.mp3.music/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Musiclax; @@ -1794,10 +1811,11 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.4; + MARKETING_VERSION = 1.1.5; PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Musiclax_Development; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1898,12 +1916,12 @@ /* End XCSwiftPackageProductDependency section */ /* Begin XCVersionGroup section */ - CBC2EBC82C5277F1000ADA51 /* relax.offline.mp3.xcdatamodeld */ = { + CB4FA4D72C5CDC4A0027C949 /* relax.offline.mp3.xcdatamodeld */ = { isa = XCVersionGroup; children = ( - CBC2EBC92C5277F1000ADA51 /* MusicPlayer.xcdatamodel */, + CB4FA4D82C5CDC4A0027C949 /* MusicPlayer.xcdatamodel */, ); - currentVersion = CBC2EBC92C5277F1000ADA51 /* MusicPlayer.xcdatamodel */; + currentVersion = CB4FA4D82C5CDC4A0027C949 /* 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 = ""; diff --git a/relax.offline.mp3.music/AppDelegate.swift b/relax.offline.mp3.music/AppDelegate.swift index 84a5969..70aeb4c 100644 --- a/relax.offline.mp3.music/AppDelegate.swift +++ b/relax.offline.mp3.music/AppDelegate.swift @@ -13,6 +13,7 @@ import Tiercel import Firebase import GoogleMobileAds import FacebookCore +import StoreKit @_exported import IQKeyboardManagerSwift @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -61,7 +62,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { switch_lunch() //执行用户启动事件日志 MP_AnalyticsManager.shared.user_launchAction() -// NotificationCenter.default.addObserver(self, selector: #selector(appWillTerminateAction(_ :)), name:UIApplication.willTerminateNotification, object: nil) return true } func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:] ) -> Bool { diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/Contents.json new file mode 100644 index 0000000..6862088 --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/Contents.json @@ -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 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/大背景@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/大背景@2x.png new file mode 100644 index 0000000..51e58c6 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/大背景@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/大背景@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/大背景@3x.png new file mode 100644 index 0000000..5950c4f Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP A'bg.imageset/大背景@3x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/AD图标@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/AD图标@2x.png new file mode 100644 index 0000000..ccb721e Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/AD图标@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/AD图标@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/AD图标@3x.png new file mode 100644 index 0000000..3bdeefd Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/AD图标@3x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/Contents.json new file mode 100644 index 0000000..67ee2d2 --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP AD'logo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "AD图标@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "AD图标@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/Contents.json new file mode 100644 index 0000000..6862088 --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/Contents.json @@ -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 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/大背景@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/大背景@2x.png new file mode 100644 index 0000000..43b3bf7 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/大背景@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/大背景@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/大背景@3x.png new file mode 100644 index 0000000..519ed5c Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP B'bg.imageset/大背景@3x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/Contents.json new file mode 100644 index 0000000..4598792 --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/Contents.json @@ -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 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/未选中框@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/未选中框@2x.png new file mode 100644 index 0000000..5c87e2d Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/未选中框@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/未选中框@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/未选中框@3x.png new file mode 100644 index 0000000..a5c005c Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Choose'logo.imageset/未选中框@3x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/Contents.json new file mode 100644 index 0000000..a33e356 --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/Contents.json @@ -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 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/选中框@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/选中框@2x.png new file mode 100644 index 0000000..9f03e53 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/选中框@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/选中框@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/选中框@3x.png new file mode 100644 index 0000000..5ce02bd Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Chooseed'logo.imageset/选中框@3x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/Contents.json new file mode 100644 index 0000000..b1fe4db --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/Contents.json @@ -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 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/下载图标@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/下载图标@2x.png new file mode 100644 index 0000000..59c9968 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/下载图标@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/下载图标@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/下载图标@3x.png new file mode 100644 index 0000000..eb0a201 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Dn'logo.imageset/下载图标@3x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/Contents.json new file mode 100644 index 0000000..4c5f258 --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/Contents.json @@ -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 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/音乐图标@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/音乐图标@2x.png new file mode 100644 index 0000000..e811462 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/音乐图标@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/音乐图标@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/音乐图标@3x.png new file mode 100644 index 0000000..1fcf207 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Mu'logo.imageset/音乐图标@3x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/Contents.json new file mode 100644 index 0000000..3ee24a1 --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "btn_square@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "btn_square@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/btn_square@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/btn_square@2x.png new file mode 100644 index 0000000..c183f83 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/btn_square@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/btn_square@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/btn_square@3x.png new file mode 100644 index 0000000..fa089cd Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Out'logo.imageset/btn_square@3x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/85_@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/85_@2x.png new file mode 100644 index 0000000..5ffc71d Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/85_@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/85_@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/85_@3x.png new file mode 100644 index 0000000..4a7d444 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/85_@3x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/Contents.json new file mode 100644 index 0000000..889973b --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/IAP Save'bg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "85_@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "85_@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/Contents.json new file mode 100644 index 0000000..01b7bb4 --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/Contents.json @@ -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 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/盾@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/盾@2x.png new file mode 100644 index 0000000..557c866 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/盾@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/盾@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/盾@3x.png new file mode 100644 index 0000000..0d7ee24 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/No mandatory'logo.imageset/盾@3x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Contents.json new file mode 100644 index 0000000..907684d --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Rights@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Rights@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Rights@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Rights@2x.png new file mode 100644 index 0000000..4fff6e4 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Rights@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Rights@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Rights@3x.png new file mode 100644 index 0000000..5e04822 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/Rights'logo.imageset/Rights@3x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Contents.json b/relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Contents.json new file mode 100644 index 0000000..c562d54 --- /dev/null +++ b/relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Group_1597880776@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Group_1597880776@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Group_1597880776@2x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Group_1597880776@2x.png new file mode 100644 index 0000000..da33cda Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Group_1597880776@2x.png differ diff --git a/relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Group_1597880776@3x.png b/relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Group_1597880776@3x.png new file mode 100644 index 0000000..ff4d884 Binary files /dev/null and b/relax.offline.mp3.music/Assets.xcassets/IAP/VIP'logo.imageset/Group_1597880776@3x.png differ diff --git a/relax.offline.mp3.music/MP/Common/Base(公用基类)/Controllers/MP_IAPViewController.swift b/relax.offline.mp3.music/MP/Common/Base(公用基类)/Controllers/MP_IAPViewController.swift new file mode 100644 index 0000000..1ec1da8 --- /dev/null +++ b/relax.offline.mp3.music/MP/Common/Base(公用基类)/Controllers/MP_IAPViewController.swift @@ -0,0 +1,177 @@ +// +// MP_IAPViewController.swift +// relax.offline.mp3.music +// +// Created by Mr.Zhou on 2024/7/31. +// + +import UIKit + +///内购选中图片 +let IAPChooseedImage:UIImage? = .init(named: "IAP Chooseed'logo") +///内购未选中图片 +let IAPChooseImage:UIImage? = .init(named: "IAP Choose'logo") +///内购页面(A/B面样式区别) +class MP_IAPViewController: UIViewController { + //样式版,根据A/B面决定 + @IBOutlet weak var bgImageView: UIImageView! + @IBOutlet weak var scrollView: UIScrollView! + var isType:Bool = false + @IBOutlet weak var aConstraint: NSLayoutConstraint! + @IBOutlet weak var bConstraint: NSLayoutConstraint! + @IBOutlet weak var adView: UIView! + @IBOutlet weak var adLabel: UILabel! + @IBOutlet weak var musicView: UIView! + @IBOutlet weak var musicLabel: UILabel! + @IBOutlet weak var downloadView: UIView! + @IBOutlet weak var downloadLabel: UILabel! + @IBOutlet weak var weekView: UIView!{ + didSet{ + weekView.isUserInteractionEnabled = true + weekView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(chooseLevelClick(_ :)))) + } + } + @IBOutlet weak var weekImageView: UIImageView! + @IBOutlet weak var weekPriceLabel: UILabel! + @IBOutlet weak var yearView: UIView!{ + didSet{ + yearView.isUserInteractionEnabled = true + yearView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(chooseLevelClick(_ :)))) + } + } + @IBOutlet weak var yearImageView: UIImageView! + @IBOutlet weak var yearPriceLabel: UILabel! + @IBOutlet weak var lifeView: UIView!{ + didSet{ + lifeView.isUserInteractionEnabled = true + lifeView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(chooseLevelClick(_ :)))) + } + } + @IBOutlet weak var lifeImageView: UIImageView! + @IBOutlet weak var lifePriceLabel: UILabel! + var privacyBlock:(() -> Void)? + var termsBlock:(() -> Void)? + //选择的等级 + private var level:Int? + override func viewDidLoad() { + super.viewDidLoad() + scrollView.contentInsetAdjustmentBehavior = .never + MP_IAPManager.shared.requestProducts() + //根据isType调整约束(A/B面样式存在差距) + if isType { + //B面 + bgImageView.image = UIImage(named: "IAP B'bg") + aConstraint.priority = .init(500) + bConstraint.priority = .init(999) + //展示所有的权益 + musicView.isHidden = false + downloadView.isHidden = false + + }else { + //A面 + bgImageView.image = UIImage(named: "IAP A'bg") + aConstraint.priority = .init(999) + bConstraint.priority = .init(500) + //隐藏权益 + musicView.isHidden = true + downloadView.isHidden = true + } + //实现文本填充 + adLabel.attributedText = setSubstring("Ad-free experience, NO ADs!!", coloredText: "NO ADs!!") + musicLabel.text = "All \"YouTube\" music & videos" + downloadLabel.text = "Unlimited Downloads" + + //设置价格文本 + weekPriceLabel.attributedText = setPriceText(1.99) + yearPriceLabel.attributedText = setPriceText(14.99) + lifePriceLabel.attributedText = setPriceText(24.99) + } + //根据文本内容调整显示颜色 + private func setSubstring(_ fullText:String, coloredText:String) -> NSAttributedString { + //调整展示颜色 + let attributedString = NSMutableAttributedString(string: fullText, attributes: [.foregroundColor:UIColor.white, .font:UIFont.systemFont(ofSize: 16*width)]) + let attributes: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor(hex: "#80F988")] + if let range = fullText.range(of: coloredText) { + let nsRange = NSRange(range, in: fullText) + attributedString.addAttributes(attributes, range: nsRange) + } + return attributedString + } + //设置价格副文本 + private func setPriceText(_ price:Double) -> NSAttributedString { + let font = UIFont(name: "DINAlternate-Bold", size: 24*width) ?? .systemFont(ofSize: 24*width, weight: .bold) + let attributedString = NSMutableAttributedString(string: "$\(price)", attributes: [.foregroundColor:UIColor.white, .font:font]) + attributedString.addAttributes([.font:UIFont(name: "DINAlternate-Bold", size: 16*width) ?? .systemFont(ofSize: 16*width, weight: .bold)], range: .init(location: 0, length: 1)) + return attributedString + } + + //退出页面 + @IBAction func dismissClick(_ sender: UIButton) { + dismiss(animated: true) + } + //选择档位 + @objc private func chooseLevelClick(_ sender:UITapGestureRecognizer) { + let tag = sender.view?.tag ?? 0 + switch tag { + case 0://选择了第一档 + weekPriceLabel.setGradientTextColor(gradientTextColors) + weekImageView.image = IAPChooseedImage + + yearPriceLabel.cleanGradientTextColor() + yearImageView.image = IAPChooseImage + lifePriceLabel.cleanGradientTextColor() + lifeImageView.image = IAPChooseImage + case 1://选择了第二档 + yearPriceLabel.setGradientTextColor(gradientTextColors) + yearImageView.image = IAPChooseedImage + + weekPriceLabel.cleanGradientTextColor() + weekImageView.image = IAPChooseImage + lifePriceLabel.cleanGradientTextColor() + lifeImageView.image = IAPChooseImage + default://选择了第三档 + lifePriceLabel.setGradientTextColor(gradientTextColors) + lifeImageView.image = IAPChooseedImage + + weekPriceLabel.cleanGradientTextColor() + weekImageView.image = IAPChooseImage + yearPriceLabel.cleanGradientTextColor() + yearImageView.image = IAPChooseImage + } + level = tag + } + //继续购买 + @IBAction func continueClick(_ sender: UIButton) { + guard let level = level else { + MP_HUD.onlytext("Please select your membership type", delay: 1.0, completion: nil) + return + } + guard MP_NetWorkManager.shared.netWorkStatu == .reachable else { + MP_HUD.onlytext("Bad connection~", delay: 1.0, completion: nil) + return + } + MP_IAPManager.shared.purchaseProduct(level) + } + //刷新商店 + @IBAction func reStoreClick(_ sender: UIButton) { + MP_IAPManager.shared.restorePurchases() + } + //协议 + @IBAction func privacyClick(_ sender: UIButton) { + dismiss(animated: true) { + [weak self] in + if let block = self?.privacyBlock { + block() + } + } + } + //用户服务 + @IBAction func termsClick(_ sender: UIButton) { + dismiss(animated: true) { + [weak self] in + if let block = self?.termsBlock { + block() + } + } + } +} diff --git a/relax.offline.mp3.music/MP/Common/Base(公用基类)/Controllers/MP_IAPViewController.xib b/relax.offline.mp3.music/MP/Common/Base(公用基类)/Controllers/MP_IAPViewController.xib new file mode 100644 index 0000000..d5d6b57 --- /dev/null +++ b/relax.offline.mp3.music/MP/Common/Base(公用基类)/Controllers/MP_IAPViewController.xib @@ -0,0 +1,611 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/relax.offline.mp3.music/MP/Common/Base(公用基类)/Controllers/MP_LunchViewController.swift b/relax.offline.mp3.music/MP/Common/Base(公用基类)/Controllers/MP_LunchViewController.swift index 4677d3c..bb75e72 100644 --- a/relax.offline.mp3.music/MP/Common/Base(公用基类)/Controllers/MP_LunchViewController.swift +++ b/relax.offline.mp3.music/MP/Common/Base(公用基类)/Controllers/MP_LunchViewController.swift @@ -121,6 +121,7 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate { private func switchAOrBAction() { //首先检测之前是否进入过B面 guard UserDefaults.standard.bool(forKey: "MP_Into_B") != true else { + MP_IAPManager.shared.startLunchStatus() //更新开关以及响应的数据 MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in if open { @@ -166,6 +167,7 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate { MP_NetWorkManager.shared.performTaskNetWrokAvailable { [weak self] in guard let self = self else {return} + MP_IAPManager.shared.startLunchStatus() //进行开关检测 MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in guard let self = self else {return} diff --git a/relax.offline.mp3.music/MP/Common/Extension(扩展)/String.swift b/relax.offline.mp3.music/MP/Common/Extension(扩展)/String.swift index ce85709..eb38543 100644 --- a/relax.offline.mp3.music/MP/Common/Extension(扩展)/String.swift +++ b/relax.offline.mp3.music/MP/Common/Extension(扩展)/String.swift @@ -46,3 +46,37 @@ extension Range where Bound == String.Index { return NSRange(location: utf16IndexStart, length: utf16IndexEnd - utf16IndexStart) } } +///扩展UILabel +extension UILabel { + ///设置文本渐变色 + func setGradientTextColor(_ colors:[CGColor]) { + self.layoutIfNeeded() + //设置一个渐变层 + let gradientLayer = CAGradientLayer() + gradientLayer.colors = colors + gradientLayer.startPoint = CGPoint(x: 0, y: 0.5) + gradientLayer.endPoint = CGPoint(x: 1, y: 0.5) + gradientLayer.frame = self.bounds + //设置一个文本层 + let textLayer = CATextLayer() + textLayer.frame = self.bounds + textLayer.string = self.attributedText + textLayer.isWrapped = true + textLayer.truncationMode = .end + textLayer.alignmentMode = .center + textLayer.contentsScale = UIScreen.main.scale + gradientLayer.mask = textLayer + //添加层级 + self.layer.addSublayer(gradientLayer) + } + ///清理文本渐变色 + func cleanGradientTextColor() { + self.layoutIfNeeded() + //判断是否具备渐变色层 + for item in layer.sublayers ?? [] { + if item is CAGradientLayer { + item.removeFromSuperlayer() + } + } + } +} diff --git a/relax.offline.mp3.music/MP/Common/Macro(宏定义与全局量)/Macro.swift b/relax.offline.mp3.music/MP/Common/Macro(宏定义与全局量)/Macro.swift index ca7ad56..0db53de 100644 --- a/relax.offline.mp3.music/MP/Common/Macro(宏定义与全局量)/Macro.swift +++ b/relax.offline.mp3.music/MP/Common/Macro(宏定义与全局量)/Macro.swift @@ -75,6 +75,10 @@ let offline_songBGImage:UIImage = UIImage(named: "Offline Songs")! let privacyUrl:URL = .init(string: "https://musiclax.mystrikingly.com/privacy")! ///用户协议网址 let serviceUrl:URL = .init(string: "https://musiclax.mystrikingly.com/terms")! +///常用渐变色组合值 +let gradientTextColors:[CGColor] = [UIColor(red: 0, green: 0.863, blue: 1, alpha: 1).cgColor, + UIColor(red: 0, green: 1, blue: 0.561, alpha: 1).cgColor, + UIColor(red: 0.776, green: 1, blue: 0.639, alpha: 1).cgColor] //MARK: - 全局变量与方法 //存储默认配置值 diff --git a/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_AdMobManager.swift b/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_AdMobManager.swift index 6f12610..87ac31d 100644 --- a/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_AdMobManager.swift +++ b/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_AdMobManager.swift @@ -15,6 +15,14 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont private let sharedInstance = GADMobileAds.sharedInstance() ///广告总开关 private var openAdStatus:Bool = true + ///设置广告总开关 + func setOpenAdStatus(_ bool:Bool) { + DispatchQueue.main.async { + [weak self] in + guard let self = self else {return} + openAdStatus = bool + } + } ///广告过期时间(50分钟) private let expirationTime:TimeInterval = 3000 @@ -753,7 +761,10 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont var completePlayInterstitialAdBlock:(() -> Void)? //异步加载播放插页广告 func loadPlayInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) { - guard openAdStatus else {return} + guard openAdStatus else { + completion(false) + return + } // 检测当前是否有广告或者有广告正在加载 if isLoadingPlayInterstitialAd || isPlayInterstitialAdAvailable() { // 有广告或有广告在加载 @@ -802,7 +813,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont } ///播放插页广告展示 func showPlayInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) { - guard openAdStatus else {return} + guard openAdStatus else { + return + } // 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。 guard !interstitialSwitch, !isShowingPlayInterstitialAd else { return } //检索是否存在插页间隔时间 @@ -869,7 +882,10 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont var completeSwitchInterstitialAdBlock:(() -> Void)? //异步加载切歌插页广告 func loadSwitchInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) { - guard openAdStatus else {return} + guard openAdStatus else { + completion(false) + return + } // 检测当前是否有广告或者有广告正在加载 if isLoadingSwitchInterstitialAd || isSwitchInterstitialAdAvailable() { // 有广告或有广告在加载 @@ -917,7 +933,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont } ///切歌插页广告展示 func showSwitchInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) { - guard openAdStatus else {return} + guard openAdStatus else { + return + } // 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。 guard !interstitialSwitch, !isShowingSwitchInterstitialAd else { return } //检索是否存在插页间隔时间 @@ -983,7 +1001,10 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont var completeLoadInterstitialAdBlock:(() -> Void)? //异步加载下载插页广告 func loadLoadInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) { - guard openAdStatus else {return} + guard openAdStatus else { + completion(false) + return + } // 检测当前是否有广告或者有广告正在加载 if isLoadingLoadInterstitialAd || isLoadInterstitialAdAvailable() { // 有广告或有广告在加载 @@ -1031,7 +1052,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont } ///下载插页广告展示 func showLoadInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) { - guard openAdStatus else {return} + guard openAdStatus else { + return + } // 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。 guard !interstitialSwitch, !isShowingLoadInterstitialAd else { return } //检索是否存在插页间隔时间 @@ -1116,7 +1139,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont var onLibraryNativeAdBlock:(() -> Void)? ///配置搜索原生广告加载器 func configureLibraryNativeAd(rootController vc:UIViewController) { - guard openAdStatus else {return} + guard openAdStatus else { + return + } if libraryViewController == nil { libraryViewController = vc } @@ -1222,7 +1247,10 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont } //异步加载曲库插页广告 func loadLibraryInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) { - guard openAdStatus else {return} + guard openAdStatus else { + completion(false) + return + } // 检测当前是否有广告或者有广告正在加载 if isLoadingLibraryInterstitialAd || isLibraryInterstitialAdAvailable() { // 有广告或有广告在加载 @@ -1270,7 +1298,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont } ///曲库插页广告展示 func showLibraryInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) { - guard openAdStatus else {return} + guard openAdStatus else { + return + } // 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。 guard !interstitialSwitch, !isShowingLibraryInterstitialAd else { return } //检索是否存在插页间隔时间 @@ -1339,7 +1369,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont var completeGlobalInterstitialAdBlock:(() -> Void)? //异步加载全局插页广告 func loadGlobalInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) { - guard openAdStatus else {return} + guard openAdStatus else { + return + } // 检测当前是否有广告或者有广告正在加载 if isLoadingGlobalInterstitialAd || isGlobalInterstitialAdAvailable() { // 有广告或有广告在加载 @@ -1375,7 +1407,9 @@ class MP_AdMobManager: NSObject, GADAudioVideoManagerDelegate, GADFullScreenCont } ///全局插页广告展示 func showGlobalInterstitialAdIfAvailable(completion:((GADInterstitialAd) -> Void)?) { - guard openAdStatus else {return} + guard openAdStatus else { + return + } // 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。 guard !interstitialSwitch, !isShowingGlobalInterstitialAd else { return } //检索是否存在插页间隔时间 diff --git a/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_AnalyticsManager.swift b/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_AnalyticsManager.swift index 8656cd5..bc438a2 100644 --- a/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_AnalyticsManager.swift +++ b/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_AnalyticsManager.swift @@ -144,6 +144,28 @@ class MP_AnalyticsManager: NSObject { } MP_AdMobManager.shared.reloadAdMobIDs() } + //更新禁用名单 + if let trashLists = self.remoteConfig.configValue(forKey: "trashLists").jsonValue as? [String:Any], let lists = trashLists["lists"] as? [[String:Any]] { + //将名单中所有处于启用状态的内容提取出来 + var array:[MPPositive_TrashListModel] = lists.map({.init($0)}) + array = array.filter({$0.statu == true}) + //将启用的禁止名单进行分发 + var trashKeyWords:[String] = [] + var trashSingerIDs:[String] = [] + var trashVideoIDs:[String] = [] + array.forEach { item in + trashKeyWords.append(contentsOf: item.keyWords) + trashSingerIDs.append(item.singerID) + trashVideoIDs.append(contentsOf: item.videoIDs) + } + //去除所有为空的字符 + trashKeyWords = trashKeyWords.filter({$0.isEmpty == false}) + MP_NetWorkManager.shared.setTrashKeyWords(trashKeyWords) + trashSingerIDs = trashSingerIDs.filter({$0.isEmpty == false}) + MP_NetWorkManager.shared.setTrashSingerIds(trashSingerIDs) + trashVideoIDs = trashVideoIDs.filter({$0.isEmpty == false}) + MP_NetWorkManager.shared.setTrashVideoIds(trashVideoIDs) + } //更新版本数据设置 if let versionData = self.remoteConfig.configValue(forKey: "dataVersion").jsonValue as? [String:String] { //对数据进行更新 @@ -786,3 +808,4 @@ class MP_AnalyticsManager: NSObject { return losAngelesTimeString } } + diff --git a/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_IAPManager.swift b/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_IAPManager.swift index 13d6c01..59e76fe 100644 --- a/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_IAPManager.swift +++ b/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_IAPManager.swift @@ -10,9 +10,9 @@ import StoreKit ///内部购买项目管理器 class MP_IAPManager: NSObject { ///单例 - let shared = MP_IAPManager() + static let shared = MP_IAPManager() ///产品ID(根据开关获取) - private var productIdentifiers:[String] = ["6587553652","6587553795","6587554369"] + private var productIdentifiers:[String] = ["1weekvip","1yearvip","lifetimevip"] ///产品请求(根据ID获取产品信息) private var productsRequest:SKProductsRequest? ///可用产品组 @@ -20,13 +20,22 @@ class MP_IAPManager: NSObject { override init() { super.init() + SKPaymentQueue.default().add(self) } - //执行产品请求 + deinit { + SKPaymentQueue.default().remove(self) + } + ///执行产品请求 func requestProducts() { + guard MP_NetWorkManager.shared.netWorkStatu == .reachable else { + //无网络 + print("无网络状况,无法获得产品") + return + } //清空可用产品 availableProducts = [] //将产品ID转为Set集合 - var setStrings:Set = Set(productIdentifiers) + let setStrings:Set = Set(productIdentifiers) //初始化产品请求 productsRequest = SKProductsRequest(productIdentifiers: setStrings) //实现请求代理 @@ -34,11 +43,73 @@ class MP_IAPManager: NSObject { //开始执行请求 productsRequest?.start() } + ///对指定产品进行购买 + func purchaseProduct(_ index:Int) { + //检索用户选择的产品 + guard availableProducts.indices.contains(index) else { + //越界了,说明广告总数出了问题,重新请求 + MP_HUD.onlytext("Try again!", delay: 1.0, completion: nil) + requestProducts() + return + } + let id = productIdentifiers[index] + if let product = availableProducts.first(where: {$0.productIdentifier == id}) { + //将产品转为交易项 + let payment = SKPayment(product: product) + //将交易项添加进购买线程中 + SKPaymentQueue.default().add(payment) + MP_HUD.loading() + } + } + ///用户重新检索交易 + func restorePurchases() { + MP_HUD.loading() + //更新信息 + SKPaymentQueue.default().restoreCompletedTransactions() + } + ///系统自动检索 + func systemRestorePurchases() { + let receiptURL = Bundle.main.appStoreReceiptURL + guard let receipt = try? Data(contentsOf: receiptURL!) else { + // 收据不存在 + print("没有收据,广告默认开") + //不能调用AppStore,默认使用广告 + MP_AdMobManager.shared.setOpenAdStatus(true) + return + } + //收据,重置交易记录 + SKPaymentQueue.default().restoreCompletedTransactions() + } + ///启动时检索是否购买了广告 + func startLunchStatus() { + //判断是否存在用户收据 + let receiptURL = Bundle.main.appStoreReceiptURL + guard let receipt = try? Data(contentsOf: receiptURL!) else { + // 收据不存在 + print("没有收据,广告默认开") + //不能调用AppStore,默认使用广告 + MP_AdMobManager.shared.setOpenAdStatus(true) + return + } + //有收据 + print("有收据,开始检索本地信息") + reloadOpenStatus() + } + ///更新广告状态 + func reloadOpenStatus() { + //更新广告开关状态 + if isProductPurchased(productId: productIdentifiers[0]) || isProductPurchased(productId: productIdentifiers[1]) || isProductPurchased(productId: productIdentifiers[2]){ + //设置广告开关为关 + MP_AdMobManager.shared.setOpenAdStatus(false) + }else { + MP_AdMobManager.shared.setOpenAdStatus(true) + } + } } //MARK: - SKProductsRequestDelegate -extension MP_IAPManager: SKProductsRequestDelegate { - //产品请求回调执行 +extension MP_IAPManager: SKProductsRequestDelegate, SKPaymentTransactionObserver { + ///产品请求回调执行 func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { //获得可用产品 availableProducts = response.products @@ -48,5 +119,175 @@ extension MP_IAPManager: SKProductsRequestDelegate { print("无可用产品") return } + //产品可用,检索产品内容 + for (index, item) in availableProducts.enumerated() { + print("第\(index)号产品--\(item)") + } + } + ///产品请求失败 + func request(_ request: SKRequest, didFailWithError error: any Error) { + print("Failed to fetch products: \(error.localizedDescription)") + } + ///当交易的状况发生变化后 + func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { + //遍历交易项 + transactions.forEach { item in + //检索每笔交易的情况 + switch item.transactionState { + case .purchasing://交易中 + break + case .purchased://用户已经付款了 + complete(transaction: item) + case .failed://交易失败了 + fail(transaction: item) + case .restored://交易重置 + restore(transaction: item) + case .deferred://等待外部操作 + break + @unknown default: + break + } + } + } + ///重置交易状况 + func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { + print("已重启交易") + MP_HUD.hideNow() + //确定用户是否购买过订单 + if queue.transactions.isEmpty { + //用户ID没有购买过任何与当前产品有关的交易 + print("没有购买产品/交易已过期") + productIdentifiers.forEach { item in + cleanPurchase(productId: item) + } + MP_AdMobManager.shared.setOpenAdStatus(true) + } + } + func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: any Error) { + print("重启交易失败") + MP_HUD.error("The current transaction failed, \(error.localizedDescription)", delay: 1.0, completion: nil) + //清理所有的VIP信息 + productIdentifiers.forEach { item in + cleanPurchase(productId: item) + } + MP_AdMobManager.shared.setOpenAdStatus(true) + } + //存入交易信息值 + private func storePurchase(productId: String) { + if isProductPurchased(productId: productId) == false { + var purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String] ?? [] + purchasedProducts.append(productId) + UserDefaults.standard.set(purchasedProducts, forKey: "PurchasedProducts") + } + } + //检索用户是否购买该产品VIP产品 + private func isProductPurchased(productId: String) -> Bool { + let purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String] ?? [] + return purchasedProducts.contains(productId) + } + //清理对应的广告ID + private func cleanPurchase(productId: String) { + if isProductPurchased(productId: productId) { + var purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String] ?? [] + purchasedProducts.removeAll(where: {$0 == productId}) + UserDefaults.standard.set(purchasedProducts, forKey: "PurchasedProducts") + } + } + ///交易完成 + private func complete(transaction: SKPaymentTransaction) { + MP_HUD.success("Successfully purchased", delay: 1.0, completion: nil) + print("Transaction completed successfully.") + // 存储购买信息 + self.storePurchase(productId: transaction.payment.productIdentifier) + SKPaymentQueue.default().finishTransaction(transaction) + //更新广告开关状态 + reloadOpenStatus() + } + //重启交易 + private func restore(transaction: SKPaymentTransaction) { + print("Transaction restored.") + // 存储购买信息 + self.storePurchase(productId: transaction.payment.productIdentifier) + SKPaymentQueue.default().finishTransaction(transaction) + //更新广告开关状态 + reloadOpenStatus() + } + ///交易失败 + private func fail(transaction: SKPaymentTransaction) { + //检索错误 + if let error = transaction.error as NSError? { + if error.code != SKError.paymentCancelled.rawValue { + MP_HUD.error("The current transaction failed, \(error.localizedDescription)", delay: 1.0, completion: nil) + } else { + MP_HUD.onlytext("The current transaction has been canceled", delay: 1.0, completion: nil) + } + } + } + //获取收据信息 + func fetchReceipt() -> String? { + guard let receiptURL = Bundle.main.appStoreReceiptURL else { return nil } + guard let receiptData = try? Data(contentsOf: receiptURL) else { return nil } + return receiptData.base64EncodedString(options: []) + } + //验证收据信息 + func validateReceipt(completion: @escaping (Bool) -> Void) { + guard MP_NetWorkManager.shared.netWorkStatu == .reachable else { + completion(false) + return + } + //获取收据信息 + guard let receiptString = fetchReceipt() else { + completion(false) + return + } + //生成请求参数 + let requestDictionary = ["receipt-data": receiptString, + "password": "d29627e4f78b4b50a0ce5166acd8aa9f" ] + guard JSONSerialization.isValidJSONObject(requestDictionary) else { + completion(false) + return + } + + do { + let requestData = try JSONSerialization.data(withJSONObject: requestDictionary) + #if DEBUG + let validationURLString = "https://sandbox.itunes.apple.com/verifyReceipt" + #else + let validationURLString = "https://buy.itunes.apple.com/verifyReceipt" + #endif + guard let validationURL = URL(string: validationURLString) else { + completion(false) + return + } + //创建请求 + var request = URLRequest(url: validationURL) + request.httpMethod = "POST" + request.cachePolicy = .reloadIgnoringCacheData + request.httpBody = requestData + //设置会话 + let session = URLSession.shared + //执行任务 + let task = session.dataTask(with: request) { data, response, error in + guard error == nil, let data = data else { + completion(false) + return + } + + do { + if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] { + print("Receipt validation response: \(jsonResponse)") + // 根据苹果的验证响应处理购买信息 + completion(true) + } else { + completion(false) + } + } catch { + completion(false) + } + } + task.resume() + } catch { + completion(false) + } } } diff --git a/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_NetWorkManager.swift b/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_NetWorkManager.swift index af68d5d..6c0e152 100644 --- a/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_NetWorkManager.swift +++ b/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_NetWorkManager.swift @@ -83,6 +83,26 @@ class MP_NetWorkManager: NSObject { private let codes:[String] = [ "CL","GB","ID","IN","IT","IL","HU","NZ","ES","UY","UA","UG","GT","TR","TZ","SA","RS","SV","CH","SE","JP","PT","NO","NG","NI","ZA","MX","PE","US","RO","LU","KE","ZW","CZ","CA","HN","NL","KR","CR","CO","FI","FR","EC","RU","DO","DK","BO","PL","IS","BE","BR","PA","PY","AU","AT","EE","IE","EG","AE","AR","ZZ" ] + ///禁止关键词 + private var trashKeyWords:[String] = [] + ///设置禁止关键词 + func setTrashKeyWords(_ words:[String]){ + trashKeyWords = words + } + ///禁止歌手(id组) + private var trashSingerIds:[String] = [] + ///设置禁用歌手 + func setTrashSingerIds(_ ids:[String]) { + trashSingerIds = ids + } + ///禁止歌曲(id组) + private var trashVideoIds:[String] = [] + ///设置禁用歌曲 + func setTrashVideoIds(_ ids:[String]) { + trashVideoIds = ids + } + ///禁止下载 + private var isAllowedDownload:Bool = true //网络状态 enum NetWorkStatus: String { case notReachable = "网络不可用" @@ -1237,6 +1257,15 @@ extension MP_NetWorkManager { print("Url is Incorrect") return } + //检索关键词 + guard trashKeyWords.contains(text) == false else { + //是禁用关键词 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) { + print("是禁用关键词") + completion([]) + } + return + } //设置参数 let parameters:[String:Any] = [ "query":text, @@ -1537,8 +1566,8 @@ extension MP_NetWorkManager { if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) { browse.items.append(.init(item)) } - }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer { - browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer))) + }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) { + browse.items.append(.init(d)) } }) browses.append(browse) @@ -1618,8 +1647,8 @@ extension MP_NetWorkManager { if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) { browse.items.append(.init(item)) } - }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer { - browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer))) + }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) { + browse.items.append(.init(d)) } }) browses.append(browse) @@ -1649,8 +1678,8 @@ extension MP_NetWorkManager { if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) { items.append(.init(item)) } - }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer { - items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer))) + }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) { + items.append(.init(d)) } }) }else if let musicShelfRenderer = content.musicShelfRenderer{ @@ -1660,8 +1689,8 @@ extension MP_NetWorkManager { if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) { items.append(.init(item)) } - }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer { - items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer))) + }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) { + items.append(.init(d)) } }) } @@ -1681,8 +1710,8 @@ extension MP_NetWorkManager { if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) { items.append(.init(item)) } - }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer { - items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer))) + }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) { + items.append(.init(d)) } }) }else if let musicShelfRenderer = content.musicShelfRenderer{ @@ -1692,8 +1721,8 @@ extension MP_NetWorkManager { if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) { items.append(.init(item)) } - }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer { - items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer))) + }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) { + items.append(.init(d)) } }) } @@ -1785,8 +1814,8 @@ extension MP_NetWorkManager { params = musicCarouselShelfRenderer.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.first?.navigationEndpoint?.browseEndpoint?.params //解析模块内容 musicCarouselShelfRenderer.contents?.forEach({ item in - if item.musicTwoRowItemRenderer != nil { - itemViews.append(.init(parsingMusicTwoRowItemRenderer(item.musicTwoRowItemRenderer!))) + if let musicTwoRowItemRenderer = item.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) { + itemViews.append(.init(d)) } }) } @@ -1817,8 +1846,8 @@ extension MP_NetWorkManager { if let gridRenderer = content.gridRenderer { //是专辑列表 gridRenderer.items?.forEach({ item in - if let musicTwoRowItemRenderer = item.musicTwoRowItemRenderer { - array.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer))) + if let musicTwoRowItemRenderer = item.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) { + array.append(.init(d)) } continuation = gridRenderer.continuations?.first?.nextContinuationData?.continuation clickTrackingParams = gridRenderer.continuations?.first?.nextContinuationData?.clickTrackingParams @@ -1928,7 +1957,9 @@ extension MP_NetWorkManager { browse.items.append(.init(item)) } }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer { - browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer))) + if let item = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) { + browse.items.append(.init(item)) + } } }) if browse.items.isEmpty != true { @@ -1943,7 +1974,9 @@ extension MP_NetWorkManager { browse.items.append(.init(item)) } }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer { - browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer))) + if let item = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) { + browse.items.append(.init(item)) + } } }) if browse.items.isEmpty != true { @@ -2109,9 +2142,10 @@ extension MP_NetWorkManager { if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) { list.items.append(.init(item)) } - }else if content.musicTwoRowItemRenderer != nil { - let item = parsingMusicTwoRowItemRenderer(content.musicTwoRowItemRenderer!) - list.items.append(.init(item)) + }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer{ + if let item = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) { + list.items.append(.init(item)) + } } }) sectionLists.append(list) @@ -2213,49 +2247,54 @@ extension MP_NetWorkManager { if let contents = musicCardShelfRenderer.contents { contents.forEach { content in //生成更多内容块 - let item = MPPositive_BrowseItemModel() - if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, (musicResponsiveListItemRenderer.playlistItemData != nil || musicResponsiveListItemRenderer.navigationEndpoint != nil) && (musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE"){ - if let trackingParams = musicResponsiveListItemRenderer.trackingParams { - item.clickTrackingParams = trackingParams - } - //设置预览图 - item.coverUrls = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""}) - //设置一级标题与二级标题 - for (index, flexColumn) in (musicResponsiveListItemRenderer.flexColumns ?? []).enumerated() { - if index == 0 { - //一级标题 - item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) - }else { - //二级标题 - item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "") - } - } - item.playListId = musicResponsiveListItemRenderer.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId - //设置id和类型 - if musicResponsiveListItemRenderer.playlistItemData != nil { - //是单曲 - item.itemType = .single - item.videoId = musicResponsiveListItemRenderer.playlistItemData?.videoId - }else { - //是专辑列表/艺术家 - item.browseId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId - let pageType = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType - if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" { - //判断细分 - if pageType == "MUSIC_PAGE_TYPE_ARTIST" { - item.artistId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId - //是艺术家 - item.itemType = .artist - }else { - //是列表/专辑 - item.itemType = .list - } - } + if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) { + if item.title != nil && item.itemType != nil, item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" { + resultList.previewItemViews.append(.init(item)) } } - if item.title != nil && item.itemType != nil, item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" { - resultList.previewItemViews.append(.init(item)) - } +// let item = MPPositive_BrowseItemModel() +// if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, (musicResponsiveListItemRenderer.playlistItemData != nil || musicResponsiveListItemRenderer.navigationEndpoint != nil) && (musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE"){ +// if let trackingParams = musicResponsiveListItemRenderer.trackingParams { +// item.clickTrackingParams = trackingParams +// } +// //设置预览图 +// item.coverUrls = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""}) +// //设置一级标题与二级标题 +// for (index, flexColumn) in (musicResponsiveListItemRenderer.flexColumns ?? []).enumerated() { +// if index == 0 { +// //一级标题 +// item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) +// }else { +// //二级标题 +// item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "") +// } +// } +// item.playListId = musicResponsiveListItemRenderer.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId +// //设置id和类型 +// if musicResponsiveListItemRenderer.playlistItemData != nil { +// //是单曲 +// item.itemType = .single +// item.videoId = musicResponsiveListItemRenderer.playlistItemData?.videoId +// }else { +// //是专辑列表/艺术家 +// item.browseId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId +// let pageType = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType +// if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" { +// //判断细分 +// if pageType == "MUSIC_PAGE_TYPE_ARTIST" { +// item.artistId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId +// //是艺术家 +// item.itemType = .artist +// }else { +// //是列表/专辑 +// item.itemType = .list +// } +// } +// } +// } +// if item.title != nil && item.itemType != nil, item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" { +// resultList.previewItemViews.append(.init(item)) +// } } } //由于是最佳结果模块,所以没有query和params值 @@ -2285,6 +2324,13 @@ extension MP_NetWorkManager { return item.item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" }) } + //移除每一个被禁止的内容 + resultListSections.forEach { list in + list.previewItemViews = list.previewItemViews.filter({ item in + return (trashSingerIds.contains(item.item.artistId ?? "") == false) && (trashVideoIds.contains(item.item.videoId ?? "") == false) + }) + } + resultListSections = resultListSections.filter({$0.previewItemViews.count != 0}) return resultListSections } @@ -2296,47 +2342,52 @@ extension MP_NetWorkManager { contents.forEach({ content in //专辑/列表/单曲视频/艺术家 let item = MPPositive_BrowseItemModel() - if (content.musicResponsiveListItemRenderer?.playlistItemData != nil || content.musicResponsiveListItemRenderer?.navigationEndpoint != nil) && (content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE") { - //设置内容块的封面 - item.coverUrls = content.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""}) - //设置一级标题与二级标题 - for (index, flexColumn) in (content.musicResponsiveListItemRenderer?.flexColumns ?? []).enumerated() { - if index == 0 { - //一级标题 - item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) - }else { - //二级标题 - item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "") - } - } - item.playListId = content.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId - //设置id和类型 - if content.musicResponsiveListItemRenderer?.playlistItemData != nil { - //是单曲 - item.itemType = .single - item.videoId = content.musicResponsiveListItemRenderer?.playlistItemData?.videoId - }else { - //是专辑列表/艺术家 - item.browseId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId - let pageType = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType - if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" { - //判断细分 - if pageType == "MUSIC_PAGE_TYPE_ARTIST" { - item.artistId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId - //是艺术家 - item.itemType = .artist - }else { - //是列表/专辑 - item.itemType = .list - } - } - } + if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) { //添加内容块 if item.itemType != nil { array.append(.init(item)) } } - +// if (content.musicResponsiveListItemRenderer?.playlistItemData != nil || content.musicResponsiveListItemRenderer?.navigationEndpoint != nil) && (content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE") { +// //设置内容块的封面 +// item.coverUrls = content.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""}) +// //设置一级标题与二级标题 +// for (index, flexColumn) in (content.musicResponsiveListItemRenderer?.flexColumns ?? []).enumerated() { +// if index == 0 { +// //一级标题 +// item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) +// }else { +// //二级标题 +// item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "") +// } +// } +// item.playListId = content.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId +// //设置id和类型 +// if content.musicResponsiveListItemRenderer?.playlistItemData != nil { +// //是单曲 +// item.itemType = .single +// item.videoId = content.musicResponsiveListItemRenderer?.playlistItemData?.videoId +// }else { +// //是专辑列表/艺术家 +// item.browseId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId +// let pageType = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType +// if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" { +// //判断细分 +// if pageType == "MUSIC_PAGE_TYPE_ARTIST" { +// item.artistId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId +// //是艺术家 +// item.itemType = .artist +// }else { +// //是列表/专辑 +// item.itemType = .list +// } +// } +// } +// //添加内容块 +// if item.itemType != nil { +// array.append(.init(item)) +// } +// } }) } var continuation:String? @@ -2346,6 +2397,9 @@ extension MP_NetWorkManager { continuation = continuations.nextContinuationData?.continuation clickTrackingParams = continuations.nextContinuationData?.clickTrackingParams } + array = array.filter({ item in + return (trashSingerIds.contains(item.item.artistId ?? "") == false) && (trashVideoIds.contains(item.item.videoId ?? "") == false) + }) array = array.filter({$0.item.itemType != nil}) return (array, continuation, clickTrackingParams) } @@ -2355,46 +2409,52 @@ extension MP_NetWorkManager { if let contents = musicShelfContinuation.contents { ///解析内容块 contents.forEach({ content in - //专辑/列表/单曲视频/艺术家 - let item = MPPositive_BrowseItemModel() - //设置内容块的封面 - item.coverUrls = content.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""}) - //设置一级标题与二级标题 - for (index, flexColumn) in (content.musicResponsiveListItemRenderer?.flexColumns ?? []).enumerated() { - if index == 0 { - //一级标题 - item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) - }else { - //二级标题 - item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "") + if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) { + //添加内容块 + if item.itemType != nil { + array.append(.init(item)) } } - item.playListId = content.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId - //设置id和类型 - if content.musicResponsiveListItemRenderer?.playlistItemData != nil { - //是单曲 - item.itemType = .single - item.videoId = content.musicResponsiveListItemRenderer?.playlistItemData?.videoId - }else { - //是专辑列表/艺术家 - item.browseId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId - let pageType = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType - if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" { - //判断细分 - if pageType == "MUSIC_PAGE_TYPE_ARTIST" { - item.artistId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId - //是艺术家 - item.itemType = .artist - }else { - //是列表/专辑 - item.itemType = .list - } - } - } - //添加内容块 - if item.itemType != nil { - array.append(.init(item)) - } +// //专辑/列表/单曲视频/艺术家 +// let item = MPPositive_BrowseItemModel() +// //设置内容块的封面 +// item.coverUrls = content.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""}) +// //设置一级标题与二级标题 +// for (index, flexColumn) in (content.musicResponsiveListItemRenderer?.flexColumns ?? []).enumerated() { +// if index == 0 { +// //一级标题 +// item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) +// }else { +// //二级标题 +// item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "") +// } +// } +// item.playListId = content.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId +// //设置id和类型 +// if content.musicResponsiveListItemRenderer?.playlistItemData != nil { +// //是单曲 +// item.itemType = .single +// item.videoId = content.musicResponsiveListItemRenderer?.playlistItemData?.videoId +// }else { +// //是专辑列表/艺术家 +// item.browseId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId +// let pageType = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType +// if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" { +// //判断细分 +// if pageType == "MUSIC_PAGE_TYPE_ARTIST" { +// item.artistId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId +// //是艺术家 +// item.itemType = .artist +// }else { +// //是列表/专辑 +// item.itemType = .list +// } +// } +// } +// //添加内容块 +// if item.itemType != nil { +// array.append(.init(item)) +// } }) } var continuation:String? @@ -2404,6 +2464,9 @@ extension MP_NetWorkManager { continuation = continuations.nextContinuationData?.continuation clickTrackingParams = continuations.nextContinuationData?.clickTrackingParams } + array = array.filter({ item in + return (trashSingerIds.contains(item.item.artistId ?? "") == false) && (trashVideoIds.contains(item.item.videoId ?? "") == false) + }) array = array.filter({$0.item.itemType != nil}) return (array, continuation, clickTrackingParams) } @@ -2412,7 +2475,6 @@ extension MP_NetWorkManager { private func parsingMusicResponsiveListItemRenderer(_ musicResponsiveListItemRenderer: RootMusicResponsiveListItemRenderer) -> MPPositive_BrowseItemModel? { //生成一个音乐模型接收数据 let item = MPPositive_BrowseItemModel() - //预览图片路径 item.coverUrls = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.compactMap({$0.url}) if let clickTrackingParams = musicResponsiveListItemRenderer.trackingParams { @@ -2424,7 +2486,7 @@ extension MP_NetWorkManager { item.itemType = .single item.videoId = playlistItemData.videoId //设置主副标题 - guard var flexColumns = musicResponsiveListItemRenderer.flexColumns, flexColumns.isEmpty != true else { + guard var flexColumns = musicResponsiveListItemRenderer.flexColumns, flexColumns.isEmpty == false else { return nil } //主标题为第一位,同时VideoId,PlayListId,pageType都以第一个flexColumn为主 @@ -2441,16 +2503,33 @@ extension MP_NetWorkManager { //设置副标题,通常为作者/专辑 flexColumns.forEach { flexColumn in item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "") + if let ari = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first(where: {$0.navigationEndpoint?.browseEndpoint != nil}) { + if ari.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType == "MUSIC_PAGE_TYPE_ARTIST", let id = ari.navigationEndpoint?.browseEndpoint?.browseId { + //这个文本指向作者,获取作者ID + item.artistId = id + } + } } //继续补完videoId,检索是否具备playListId,当playListId为空时,说明并没有成功补完,需要使用菜单结构补全内容 guard (item.playListId ?? "").isEmpty == true else { - //不为空,说明需要的数据已经补完了 - return item + //判断是否禁止的作者或者禁止的音乐 + if (trashSingerIds.contains(item.artistId ?? "")) == false && (trashVideoIds.contains(item.videoId ?? "")) == false { + return item + }else { + //禁止内容 + return nil + } } //未补完,继续 if let watchItem = musicResponsiveListItemRenderer.menu?.menuRenderer?.items?.first(where: {$0.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint != nil}) { item.playListId = watchItem.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId - return item + //判断是否禁止的作者或者禁止的音乐 + if (trashSingerIds.contains(item.artistId ?? "")) == false && (trashVideoIds.contains(item.videoId ?? "")) == false { + return item + }else { + //禁止内容 + return nil + } }else { //补完失败 return nil @@ -2470,6 +2549,12 @@ extension MP_NetWorkManager { //设置副标题,通常为作者/专辑 flexColumns.forEach { flexColumn in item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "") + if let ari = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first(where: {$0.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType == "MUSIC_PAGE_TYPE_ARTIST"}) { + //这个文本指向作者,获取作者ID + if let id = ari.navigationEndpoint?.browseEndpoint?.browseId { + item.artistId = id + } + } } //设置预览Id guard let browseEndpoint = navigationEndpoint.browseEndpoint else { @@ -2490,7 +2575,12 @@ extension MP_NetWorkManager { }else if pageType == "MUSIC_PAGE_TYPE_ARTIST" { //艺术家 item.itemType = .artist - return item + item.artistId = item.browseId + if (trashSingerIds.contains(item.artistId ?? "")) == false { + return item + }else { + return nil + } }else { return nil } @@ -2499,7 +2589,7 @@ extension MP_NetWorkManager { } } //解析musicResponsiveListItemRenderer(三组件结构) - private func parsingMusicTwoRowItemRenderer(_ musicTwoRowItemRenderer: RootMusicTwoRowItemRenderer) -> MPPositive_BrowseItemModel { + private func parsingMusicTwoRowItemRenderer(_ musicTwoRowItemRenderer: RootMusicTwoRowItemRenderer) -> MPPositive_BrowseItemModel? { //生成一个音乐模型接收数据 let item = MPPositive_BrowseItemModel() //封面路径 @@ -2508,6 +2598,10 @@ extension MP_NetWorkManager { item.title = musicTwoRowItemRenderer.title?.runs?.reduce("", { $0 + ($1.text ?? "")}) //副标题 item.subtitle = musicTwoRowItemRenderer.subtitle?.runs?.reduce("", { $0 + ($1.text ?? "")}) + //获取这个预览项的作者(有的话) + if let art = musicTwoRowItemRenderer.subtitle?.runs?.first(where: {$0.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType == "MUSIC_PAGE_TYPE_ARTIST"}) { + item.artistId = art.navigationEndpoint?.browseEndpoint?.browseId + } if let clickTrackingParams = musicTwoRowItemRenderer.navigationEndpoint?.clickTrackingParams { item.clickTrackingParams = clickTrackingParams } @@ -2533,7 +2627,11 @@ extension MP_NetWorkManager { item.browseId = browseEndpoint.browseId } } - return item + if (trashSingerIds.contains(item.artistId ?? "")) == false { + return item + }else { + return nil + } } } //MARK: - 解析资源加密 diff --git a/relax.offline.mp3.music/MP/MPPositive/Models/JsonStructs(js文件结构)/MPPositive_JsonBrowse.swift b/relax.offline.mp3.music/MP/MPPositive/Models/JsonStructs(js文件结构)/MPPositive_JsonBrowse.swift index 6e2a97a..d7b98b7 100644 --- a/relax.offline.mp3.music/MP/MPPositive/Models/JsonStructs(js文件结构)/MPPositive_JsonBrowse.swift +++ b/relax.offline.mp3.music/MP/MPPositive/Models/JsonStructs(js文件结构)/MPPositive_JsonBrowse.swift @@ -659,6 +659,8 @@ struct RootMusicResponsiveListItemRenderer: Codable { let text:String? ///文本导航 let navigationEndpoint:NavigationEndpoint? + + enum CodingKeys: String, CodingKey { case text = "text" case navigationEndpoint = "navigationEndpoint" @@ -674,14 +676,18 @@ struct RootMusicResponsiveListItemRenderer: Codable { let clickTrackingParams:String? ///资源特化 let watchEndpoint:WatchEndpoint? + ///导向其他 + let browseEndpoint:BrowseEndpoint? enum CodingKeys: String, CodingKey { case clickTrackingParams = "clickTrackingParams" case watchEndpoint = "watchEndpoint" + case browseEndpoint = "browseEndpoint" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) clickTrackingParams = try values.decodeIfPresent(String.self, forKey: .clickTrackingParams) watchEndpoint = try values.decodeIfPresent(WatchEndpoint.self, forKey: .watchEndpoint) + browseEndpoint = try values.decodeIfPresent(BrowseEndpoint.self, forKey: .browseEndpoint) } //导向播放 struct WatchEndpoint: Codable { @@ -724,6 +730,41 @@ struct RootMusicResponsiveListItemRenderer: Codable { } } } + //导向其他 + struct BrowseEndpoint: Codable { + let browseId:String? + let browseEndpointContextSupportedConfigs:BrowseEndpointContextSupportedConfigs? + enum CodingKeys: String, CodingKey { + case browseId = "browseId" + case browseEndpointContextSupportedConfigs = "browseEndpointContextSupportedConfigs" + } + init(from decoder: Decoder) throws { + let values = try decoder.container(keyedBy: CodingKeys.self) + browseId = try values.decodeIfPresent(String.self, forKey: .browseId) + browseEndpointContextSupportedConfigs = try values.decodeIfPresent(BrowseEndpointContextSupportedConfigs.self, forKey: .browseEndpointContextSupportedConfigs) + } + struct BrowseEndpointContextSupportedConfigs: Codable { + let browseEndpointContextMusicConfig:BrowseEndpointContextMusicConfig? + enum CodingKeys: String, CodingKey { + case browseEndpointContextMusicConfig = "browseEndpointContextMusicConfig" + } + init(from decoder: Decoder) throws { + let values = try decoder.container(keyedBy: CodingKeys.self) + browseEndpointContextMusicConfig = try values.decodeIfPresent(BrowseEndpointContextMusicConfig.self, forKey: .browseEndpointContextMusicConfig) + } + struct BrowseEndpointContextMusicConfig: Codable { + let pageType:String? + + enum CodingKeys: String, CodingKey { + case pageType = "pageType" + } + init(from decoder: Decoder) throws { + let values = try decoder.container(keyedBy: CodingKeys.self) + pageType = try values.decodeIfPresent(String.self, forKey: .pageType) + } + } + } + } } } } @@ -984,13 +1025,59 @@ struct RootMusicTwoRowItemRenderer: Codable { } struct Run: Codable { let text:String? + let navigationEndpoint:NavigationEndpoint? enum CodingKeys: String, CodingKey { case text = "text" - + case navigationEndpoint = "navigationEndpoint" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) text = try values.decodeIfPresent(String.self, forKey: .text) + navigationEndpoint = try values.decodeIfPresent(NavigationEndpoint.self, forKey: .navigationEndpoint) + } + struct NavigationEndpoint: Codable { + let browseEndpoint:BrowseEndpoint? + enum CodingKeys: String, CodingKey { + case browseEndpoint = "browseEndpoint" + + } + init(from decoder: Decoder) throws { + let values = try decoder.container(keyedBy: CodingKeys.self) + browseEndpoint = try values.decodeIfPresent(BrowseEndpoint.self, forKey: .browseEndpoint) + } + struct BrowseEndpoint: Codable { + let browseId:String? + let browseEndpointContextSupportedConfigs:BrowseEndpointContextSupportedConfigs? + enum CodingKeys: String, CodingKey { + case browseId = "browseId" + case browseEndpointContextSupportedConfigs = "browseEndpointContextSupportedConfigs" + } + init(from decoder: Decoder) throws { + let values = try decoder.container(keyedBy: CodingKeys.self) + browseId = try values.decodeIfPresent(String.self, forKey: .browseId) + browseEndpointContextSupportedConfigs = try values.decodeIfPresent(BrowseEndpointContextSupportedConfigs.self, forKey: .browseEndpointContextSupportedConfigs) + } + struct BrowseEndpointContextSupportedConfigs: Codable { + let browseEndpointContextMusicConfig:BrowseEndpointContextMusicConfig? + enum CodingKeys: String, CodingKey { + case browseEndpointContextMusicConfig = "browseEndpointContextMusicConfig" + } + init(from decoder: Decoder) throws { + let values = try decoder.container(keyedBy: CodingKeys.self) + browseEndpointContextMusicConfig = try values.decodeIfPresent(BrowseEndpointContextMusicConfig.self, forKey: .browseEndpointContextMusicConfig) + } + struct BrowseEndpointContextMusicConfig: Codable { + let pageType:String? + enum CodingKeys: String, CodingKey { + case pageType = "pageType" + } + init(from decoder: Decoder) throws { + let values = try decoder.container(keyedBy: CodingKeys.self) + pageType = try values.decodeIfPresent(String.self, forKey: .pageType) + } + } + } + } } } } diff --git a/relax.offline.mp3.music/MP/MPPositive/Models/Models/MPPositive_TrashListModel.swift b/relax.offline.mp3.music/MP/MPPositive/Models/Models/MPPositive_TrashListModel.swift new file mode 100644 index 0000000..99ff6ba --- /dev/null +++ b/relax.offline.mp3.music/MP/MPPositive/Models/Models/MPPositive_TrashListModel.swift @@ -0,0 +1,40 @@ +// +// MPPositive_TrashListModel.swift +// relax.offline.mp3.music +// +// Created by Mr.Zhou on 2024/7/31. +// + +import UIKit +///禁用名单模型 +class MPPositive_TrashListModel: NSObject { + ///禁用状态 + var statu:Bool = false + ///禁用歌手 + var name:String = "" + ///禁用关键词组 + var keyWords:[String] = [] + ///禁用歌手ID + var singerID:String = "" + ///禁用歌曲ID组 + var videoIDs:[String] = [] + + init(_ dict:[String:Any]) { + super.init() + if let statu = dict["statu"] as? Bool { + self.statu = statu + } + if let name = dict["name"] as? String { + self.name = name + } + if let keyWords = dict["keyWords"] as? [String] { + self.keyWords = keyWords + } + if let singerID = dict["singerID"] as? String{ + self.singerID = singerID + } + if let videoIDs = dict["videoIDs"] as? [String]{ + self.videoIDs = videoIDs + } + } +} diff --git a/relax.offline.mp3.music/MP/MPPositive/Models/ViewModels/LoadViewModels/MPPositive_RecommendLoadViewModel.swift b/relax.offline.mp3.music/MP/MPPositive/Models/ViewModels/LoadViewModels/MPPositive_RecommendLoadViewModel.swift index 301af59..66b832a 100644 --- a/relax.offline.mp3.music/MP/MPPositive/Models/ViewModels/LoadViewModels/MPPositive_RecommendLoadViewModel.swift +++ b/relax.offline.mp3.music/MP/MPPositive/Models/ViewModels/LoadViewModels/MPPositive_RecommendLoadViewModel.swift @@ -15,8 +15,8 @@ class MPPositive_RecommendLoadViewModel: NSObject { [weak self] in guard let self = self else {return} //得到了搜索结果 - if resultReloadBlock != nil { - resultReloadBlock!() + if let block = resultReloadBlock { + block() } } } diff --git a/relax.offline.mp3.music/MP/MPPositive/Models/ViewModels/LoadViewModels/MPPositive_SearchResultsLoadViewModel.swift b/relax.offline.mp3.music/MP/MPPositive/Models/ViewModels/LoadViewModels/MPPositive_SearchResultsLoadViewModel.swift index f7c4ca3..9e95824 100644 --- a/relax.offline.mp3.music/MP/MPPositive/Models/ViewModels/LoadViewModels/MPPositive_SearchResultsLoadViewModel.swift +++ b/relax.offline.mp3.music/MP/MPPositive/Models/ViewModels/LoadViewModels/MPPositive_SearchResultsLoadViewModel.swift @@ -15,8 +15,8 @@ class MPPositive_SearchResultsLoadViewModel: NSObject { [weak self] in guard let self = self else {return} //得到了搜索结果 - if resultReloadBlock != nil { - resultReloadBlock!() + if let block = resultReloadBlock { + block() } } } @@ -43,7 +43,9 @@ class MPPositive_SearchResultsLoadViewModel: NSObject { } } MP_NetWorkManager.shared.requestSearchPreviewResults(text) { [weak self] results in - self?.sectionLists = results + guard let self = self else {return} + MP_HUD.hideNow() + sectionLists = results } } } diff --git a/relax.offline.mp3.music/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_HomeViewController.swift b/relax.offline.mp3.music/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_HomeViewController.swift index 10d94f4..fa236c0 100644 --- a/relax.offline.mp3.music/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_HomeViewController.swift +++ b/relax.offline.mp3.music/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_HomeViewController.swift @@ -21,6 +21,29 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro btn.addTarget(self, action: #selector(menuRightClick(_ :)), for: .touchUpInside) return btn }() + //ViP按钮 + private lazy var vipImageView:UIImageView = { + let imageView:UIImageView = UIImageView(image: .init(named: "VIP'logo")) + imageView.isUserInteractionEnabled = true + imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(vipIAPClick(_ :)))) + return imageView + }() + //斜向标题Label + private lazy var musicLaxLabel:UILabel = { + let label = UILabel() + label.text = "MusicLax" + // Create a bold italic font + if let boldItalicFontDescriptor = UIFont.systemFont(ofSize: 20*width, weight: .bold).fontDescriptor.withSymbolicTraits([.traitBold, .traitItalic]) { + let boldItalicFont = UIFont(descriptor: boldItalicFontDescriptor, size: 20*width) + label.font = boldItalicFont + } else { + label.font = UIFont.boldSystemFont(ofSize: 20*width) + } + label.textColor = .white + return label + }() + //搜索栏 + private lazy var searchView = createSearchView() //tableView private lazy var tableView:UITableView = { let tableView = UITableView(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), style: .plain) @@ -63,6 +86,7 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro requestTrackingAuthorization { idfa in } } + MP_IAPManager.shared.systemRestorePurchases() setTitle("") confirgue() if MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count == 0 { @@ -263,31 +287,55 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro //MARK: - UI生成与配置 //配置 private func confirgue() { - let searchView = createSearchView() - navView.addSubview(searchView) - searchView.snp.makeConstraints { make in - make.width.equalTo(300*width) - make.height.equalTo(32*width) - make.left.equalToSuperview().offset(18*width) - make.centerY.equalToSuperview() + navView.frame = .init(x: 0, y: statusBarHeight, width: screen_Width, height: 90*width) + if memuBtn.superview == nil { + navView.addSubview(memuBtn) + memuBtn.snp.makeConstraints { make in + make.right.equalToSuperview().offset(-16*width) + make.top.equalToSuperview().offset(16*width) + make.width.height.equalTo(24*width) + } } - view.addSubview(bgImageView) - bgImageView.snp.makeConstraints { make in - make.top.right.left.equalToSuperview() - make.height.equalTo(981*width) + if vipImageView.superview == nil { + navView.addSubview(vipImageView) + vipImageView.snp.makeConstraints { make in + make.centerY.equalTo(memuBtn.snp.centerY) + make.right.equalTo(memuBtn.snp.left).offset(-10*width) + make.width.equalTo(51*width) + make.height.equalTo(32*width) + } } - view.addSubview(tableView) - navView.addSubview(memuBtn) - memuBtn.snp.makeConstraints { make in - make.right.equalToSuperview().offset(-16*width) - make.centerY.equalToSuperview() - make.width.height.equalTo(24*width) + if musicLaxLabel.superview == nil { + navView.addSubview(musicLaxLabel) + musicLaxLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16*width) + make.centerY.equalTo(memuBtn) + } + musicLaxLabel.setGradientTextColor(gradientTextColors) } - tableView.snp.makeConstraints { make in - make.top.equalTo(navView.snp.bottom).offset(32*width) - make.left.right.bottom.equalToSuperview() + if searchView.superview == nil { + navView.addSubview(searchView) + searchView.snp.makeConstraints { make in + make.width.equalTo(340*width) + make.height.equalTo(32*width) + make.centerX.equalToSuperview() + make.bottom.equalToSuperview().offset(-9*width) + } + } + if bgImageView.superview == nil { + view.addSubview(bgImageView) + bgImageView.snp.makeConstraints { make in + make.top.right.left.equalToSuperview() + make.height.equalTo(981*width) + } + } + if tableView.superview == nil { + view.addSubview(tableView) + tableView.snp.makeConstraints { make in + make.top.equalTo(navView.snp.bottom).offset(15*width) + make.left.right.bottom.equalToSuperview() + } } - } //MARK: - 页面刷新 //页面刷新 @@ -315,6 +363,34 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro setVC.cleanSide = true navigationController?.pushViewController(setVC, animated: true) } + //弹出VIP页面 + @objc private func vipIAPClick(_ sender:UITapGestureRecognizer) { + view.endEditing(true) + let iapVC = MP_IAPViewController() + iapVC.isType = true + iapVC.privacyBlock = { + [weak self] in + guard let self = self else {return} + MP_NetWorkManager.shared.requestNetworkPermission(oberve: self) { + [weak self] in + let privacyVC = MPSideA_PrivacyViewController() + self?.navigationController?.pushViewController(privacyVC, animated: true) + } + } + iapVC.termsBlock = { + [weak self] in + guard let self = self else {return} + MP_NetWorkManager.shared.requestNetworkPermission(oberve: self) { + [weak self] in + let serviceVC = MPSideA_ServiceViewController() + self?.navigationController?.pushViewController(serviceVC, animated: true) + } + } + iapVC.modalPresentationStyle = .fullScreen + + present(iapVC, animated: true) + } + } //MARK: - tableView extension MPPositive_HomeViewController: UITableViewDataSource, UITableViewDelegate { diff --git a/relax.offline.mp3.music/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ListShowViewController.swift b/relax.offline.mp3.music/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ListShowViewController.swift index 664a6c3..7e74c0f 100644 --- a/relax.offline.mp3.music/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ListShowViewController.swift +++ b/relax.offline.mp3.music/MP/MPPositive/ViewControllers/Home(首页,各项列表页,艺术家页)/MPPositive_ListShowViewController.swift @@ -207,12 +207,14 @@ class MPPositive_ListShowViewController: MPPositive_BaseViewController, UIViewCo make.left.equalToSuperview().offset(18*width) make.height.equalTo(32*width) make.bottom.equalTo(blurView.snp.bottom).offset(-29*width) +// make.width.equalTo(90*width) } view.addSubview(shuffleBtn) shuffleBtn.snp.makeConstraints { make in make.left.equalTo(playAllBtn.snp.right).offset(18*width) make.height.equalTo(32*width) make.centerY.equalTo(playAllBtn) +// make.width.equalTo(90*width) } view.addSubview(collectionListBtn) collectionListBtn.snp.makeConstraints { make in diff --git a/relax.offline.mp3.music/MP/MPPositive/Views/Search/MPPositive_SearchResultsShowView.swift b/relax.offline.mp3.music/MP/MPPositive/Views/Search/MPPositive_SearchResultsShowView.swift index 911cafd..594e442 100644 --- a/relax.offline.mp3.music/MP/MPPositive/Views/Search/MPPositive_SearchResultsShowView.swift +++ b/relax.offline.mp3.music/MP/MPPositive/Views/Search/MPPositive_SearchResultsShowView.swift @@ -34,11 +34,10 @@ class MPPositive_SearchResultsShowView: UIView { } //搜索成功了 MP_AnalyticsManager.shared.search_result_pvAction() - loadModel.resultReloadBlock = { + loadModel?.resultReloadBlock = { [weak self] in //刷新分页控制器 guard let self = self else {return} - MP_HUD.hideNow() isHidden = false MP_AnalyticsManager.shared.search_resultsuccess_actionAction() if let loadModel = loadModel, let titles = loadModel.sectionLists?.compactMap({$0.title ?? ""}) { diff --git a/relax.offline.mp3.music/MP/MPSideA/ViewControllers/Home(音乐资源列表)/MPSideA_HomeViewController.swift b/relax.offline.mp3.music/MP/MPSideA/ViewControllers/Home(音乐资源列表)/MPSideA_HomeViewController.swift index baa63a2..505f013 100644 --- a/relax.offline.mp3.music/MP/MPSideA/ViewControllers/Home(音乐资源列表)/MPSideA_HomeViewController.swift +++ b/relax.offline.mp3.music/MP/MPSideA/ViewControllers/Home(音乐资源列表)/MPSideA_HomeViewController.swift @@ -71,7 +71,37 @@ class MPSideA_HomeViewController: MPSideA_BaseViewController { tableView.reloadData() } } -// //当音乐播放器状态改变时 + @IBAction func menueClick(_ sender: UIButton) { + let setVC = MPSideA_SettingViewController() + setVC.cleanSide = false + navigationController?.pushViewController(setVC, animated: true) + } + @IBAction func vipClick(_ sender: UIButton) { + view.endEditing(true) + let iapVC = MP_IAPViewController() + iapVC.isType = false + iapVC.privacyBlock = { + [weak self] in + guard let self = self else {return} + MP_NetWorkManager.shared.requestNetworkPermission(oberve: self) { + [weak self] in + let privacyVC = MPSideA_PrivacyViewController() + self?.navigationController?.pushViewController(privacyVC, animated: true) + } + } + iapVC.termsBlock = { + [weak self] in + guard let self = self else {return} + MP_NetWorkManager.shared.requestNetworkPermission(oberve: self) { + [weak self] in + let serviceVC = MPSideA_ServiceViewController() + self?.navigationController?.pushViewController(serviceVC, animated: true) + } + } + iapVC.modalPresentationStyle = .fullScreen + present(iapVC, animated: true) + } + // //当音乐播放器状态改变时 // @objc private func switchPlayerStateAction(_ sender:Notification) { // //刷新页面内容 // tableView.reloadData() diff --git a/relax.offline.mp3.music/MP/MPSideA/ViewControllers/Home(音乐资源列表)/MPSideA_HomeViewController.xib b/relax.offline.mp3.music/MP/MPSideA/ViewControllers/Home(音乐资源列表)/MPSideA_HomeViewController.xib index 8cfbbae..a189224 100644 --- a/relax.offline.mp3.music/MP/MPSideA/ViewControllers/Home(音乐资源列表)/MPSideA_HomeViewController.xib +++ b/relax.offline.mp3.music/MP/MPSideA/ViewControllers/Home(音乐资源列表)/MPSideA_HomeViewController.xib @@ -9,7 +9,7 @@ - + @@ -31,26 +31,100 @@ - + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + +