1.2.0对后台播放调整
@ -24,6 +24,7 @@
|
|||||||
CB0B36912C65EBFC004036E2 /* MPPositive_BaseShowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0B36902C65EBFC004036E2 /* MPPositive_BaseShowView.swift */; };
|
CB0B36912C65EBFC004036E2 /* MPPositive_BaseShowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0B36902C65EBFC004036E2 /* MPPositive_BaseShowView.swift */; };
|
||||||
CB0D33972C7EF73700C85816 /* MPPositive_PersonalListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0D33962C7EF73700C85816 /* MPPositive_PersonalListViewModel.swift */; };
|
CB0D33972C7EF73700C85816 /* MPPositive_PersonalListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0D33962C7EF73700C85816 /* MPPositive_PersonalListViewModel.swift */; };
|
||||||
CB0D339B2C7F2AAC00C85816 /* MPPositive_PersonalisedRecommendationsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0D339A2C7F2AAC00C85816 /* MPPositive_PersonalisedRecommendationsTableViewCell.swift */; };
|
CB0D339B2C7F2AAC00C85816 /* MPPositive_PersonalisedRecommendationsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0D339A2C7F2AAC00C85816 /* MPPositive_PersonalisedRecommendationsTableViewCell.swift */; };
|
||||||
|
CB108C872C901A5E0017C40F /* MP_LuxServerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB108C862C901A5E0017C40F /* MP_LuxServerManager.swift */; };
|
||||||
CB15B89B2C353B2400756E89 /* MP_GuideViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB15B8992C353B2400756E89 /* MP_GuideViewController.swift */; };
|
CB15B89B2C353B2400756E89 /* MP_GuideViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB15B8992C353B2400756E89 /* MP_GuideViewController.swift */; };
|
||||||
CB15B89C2C353B2400756E89 /* MP_GuideViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CB15B89A2C353B2400756E89 /* MP_GuideViewController.xib */; };
|
CB15B89C2C353B2400756E89 /* MP_GuideViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CB15B89A2C353B2400756E89 /* MP_GuideViewController.xib */; };
|
||||||
CB1E3B662C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */; };
|
CB1E3B662C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */; };
|
||||||
@ -299,6 +300,7 @@
|
|||||||
CB0B36902C65EBFC004036E2 /* MPPositive_BaseShowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_BaseShowView.swift; sourceTree = "<group>"; };
|
CB0B36902C65EBFC004036E2 /* MPPositive_BaseShowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_BaseShowView.swift; sourceTree = "<group>"; };
|
||||||
CB0D33962C7EF73700C85816 /* MPPositive_PersonalListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_PersonalListViewModel.swift; sourceTree = "<group>"; };
|
CB0D33962C7EF73700C85816 /* MPPositive_PersonalListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_PersonalListViewModel.swift; sourceTree = "<group>"; };
|
||||||
CB0D339A2C7F2AAC00C85816 /* MPPositive_PersonalisedRecommendationsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_PersonalisedRecommendationsTableViewCell.swift; sourceTree = "<group>"; };
|
CB0D339A2C7F2AAC00C85816 /* MPPositive_PersonalisedRecommendationsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_PersonalisedRecommendationsTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
CB108C862C901A5E0017C40F /* MP_LuxServerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_LuxServerManager.swift; sourceTree = "<group>"; };
|
||||||
CB15B8992C353B2400756E89 /* MP_GuideViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_GuideViewController.swift; sourceTree = "<group>"; };
|
CB15B8992C353B2400756E89 /* MP_GuideViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MP_GuideViewController.swift; sourceTree = "<group>"; };
|
||||||
CB15B89A2C353B2400756E89 /* MP_GuideViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MP_GuideViewController.xib; sourceTree = "<group>"; };
|
CB15B89A2C353B2400756E89 /* MP_GuideViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MP_GuideViewController.xib; sourceTree = "<group>"; };
|
||||||
CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CustomPlayListModel.swift; sourceTree = "<group>"; };
|
CB1E3B652C23DA8500071DEA /* MPPositive_CustomPlayListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPPositive_CustomPlayListModel.swift; sourceTree = "<group>"; };
|
||||||
@ -751,10 +753,11 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
CBAFCA272C0A10500054500E /* MP_NetWorkManager.swift */,
|
CBAFCA272C0A10500054500E /* MP_NetWorkManager.swift */,
|
||||||
|
CB108C862C901A5E0017C40F /* MP_LuxServerManager.swift */,
|
||||||
CBAFCA282C0A10500054500E /* MP_PlayerManager.swift */,
|
CBAFCA282C0A10500054500E /* MP_PlayerManager.swift */,
|
||||||
|
CBAFCA202C0A10500054500E /* MP_AVURLAsset.swift */,
|
||||||
CBAFCA1F2C0A10500054500E /* MP_AnalyticsManager.swift */,
|
CBAFCA1F2C0A10500054500E /* MP_AnalyticsManager.swift */,
|
||||||
CBB6372B2C1C17C300F1DEC9 /* MP_AdMobManager.swift */,
|
CBB6372B2C1C17C300F1DEC9 /* MP_AdMobManager.swift */,
|
||||||
CBAFCA202C0A10500054500E /* MP_AVURLAsset.swift */,
|
|
||||||
CBAFCA212C0A10500054500E /* MP_CacheManager.swift */,
|
CBAFCA212C0A10500054500E /* MP_CacheManager.swift */,
|
||||||
CBAFCA232C0A10500054500E /* MP_CoreDataHandlerManager.swift */,
|
CBAFCA232C0A10500054500E /* MP_CoreDataHandlerManager.swift */,
|
||||||
CBAFCA242C0A10500054500E /* MP_DownloadManager.swift */,
|
CBAFCA242C0A10500054500E /* MP_DownloadManager.swift */,
|
||||||
@ -1287,7 +1290,7 @@
|
|||||||
CBC2D6E62BFDF3D700E17703 /* Resources */,
|
CBC2D6E62BFDF3D700E17703 /* Resources */,
|
||||||
0018BD0A2C1050F60066717C /* ShellScript */,
|
0018BD0A2C1050F60066717C /* ShellScript */,
|
||||||
4F340A16CA4CBC1A386EF0AF /* [CP] Embed Pods Frameworks */,
|
4F340A16CA4CBC1A386EF0AF /* [CP] Embed Pods Frameworks */,
|
||||||
D1CFD1D7A1F3154E85EE0F93 /* [CP] Copy Pods Resources */,
|
389B03C2C01E5C783CCE22ED /* [CP] Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@ -1454,6 +1457,23 @@
|
|||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
|
389B03C2C01E5C783CCE22ED /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-relax.offline.mp3.music/Pods-relax.offline.mp3.music-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-relax.offline.mp3.music/Pods-relax.offline.mp3.music-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-relax.offline.mp3.music/Pods-relax.offline.mp3.music-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
4F340A16CA4CBC1A386EF0AF /* [CP] Embed Pods Frameworks */ = {
|
4F340A16CA4CBC1A386EF0AF /* [CP] Embed Pods Frameworks */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@ -1471,23 +1491,6 @@
|
|||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-relax.offline.mp3.music/Pods-relax.offline.mp3.music-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-relax.offline.mp3.music/Pods-relax.offline.mp3.music-frameworks.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
D1CFD1D7A1F3154E85EE0F93 /* [CP] Copy Pods Resources */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-relax.offline.mp3.music/Pods-relax.offline.mp3.music-resources-${CONFIGURATION}-input-files.xcfilelist",
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
|
||||||
outputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-relax.offline.mp3.music/Pods-relax.offline.mp3.music-resources-${CONFIGURATION}-output-files.xcfilelist",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-relax.offline.mp3.music/Pods-relax.offline.mp3.music-resources.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
@ -1618,6 +1621,7 @@
|
|||||||
CBAFCB732C0A10500054500E /* MPPositive_SearchSuggestionItemTableViewCell.swift in Sources */,
|
CBAFCB732C0A10500054500E /* MPPositive_SearchSuggestionItemTableViewCell.swift in Sources */,
|
||||||
CBAFCB432C0A10500054500E /* MPPositive_NavigationController.swift in Sources */,
|
CBAFCB432C0A10500054500E /* MPPositive_NavigationController.swift in Sources */,
|
||||||
CBAFCB302C0A10500054500E /* MPPositive_BrowseModuleListViewModel.swift in Sources */,
|
CBAFCB302C0A10500054500E /* MPPositive_BrowseModuleListViewModel.swift in Sources */,
|
||||||
|
CB108C872C901A5E0017C40F /* MP_LuxServerManager.swift in Sources */,
|
||||||
CBAFCBA62C0A10500054500E /* MPSideA_Home_SecondListCollectionViewCell.swift in Sources */,
|
CBAFCBA62C0A10500054500E /* MPSideA_Home_SecondListCollectionViewCell.swift in Sources */,
|
||||||
CBAFCB202C0A10500054500E /* MPPositive_JsonSearchSuggestions.swift in Sources */,
|
CBAFCB202C0A10500054500E /* MPPositive_JsonSearchSuggestions.swift in Sources */,
|
||||||
CBAFCB232C0A10500054500E /* MPPositive_ArtistHeaderModel.swift in Sources */,
|
CBAFCB232C0A10500054500E /* MPPositive_ArtistHeaderModel.swift in Sources */,
|
||||||
@ -1895,7 +1899,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
CURRENT_PROJECT_VERSION = 1.1.9.1;
|
CURRENT_PROJECT_VERSION = 1.2.0.1;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = RAQJ4FNZUH;
|
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = RAQJ4FNZUH;
|
||||||
@ -1916,7 +1920,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.1.9;
|
MARKETING_VERSION = 1.2.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
|
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@ -1941,7 +1945,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
CURRENT_PROJECT_VERSION = 1.1.9.1;
|
CURRENT_PROJECT_VERSION = 1.2.0.1;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = RAQJ4FNZUH;
|
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = RAQJ4FNZUH;
|
||||||
@ -1962,7 +1966,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.1.9;
|
MARKETING_VERSION = 1.2.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
|
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
|||||||
@ -3,18 +3,4 @@
|
|||||||
uuid = "B2D42C7E-B789-40F0-8339-B70A223A3889"
|
uuid = "B2D42C7E-B789-40F0-8339-B70A223A3889"
|
||||||
type = "0"
|
type = "0"
|
||||||
version = "2.0">
|
version = "2.0">
|
||||||
<Breakpoints>
|
|
||||||
<BreakpointProxy
|
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
|
|
||||||
<BreakpointContent
|
|
||||||
uuid = "C55B60AF-F439-4924-A399-CD9EE440654E"
|
|
||||||
shouldBeEnabled = "Yes"
|
|
||||||
ignoreCount = "0"
|
|
||||||
continueAfterRunningActions = "No"
|
|
||||||
breakpointStackSelectionBehavior = "1"
|
|
||||||
scope = "1"
|
|
||||||
stopOnStyle = "0">
|
|
||||||
</BreakpointContent>
|
|
||||||
</BreakpointProxy>
|
|
||||||
</Breakpoints>
|
|
||||||
</Bucket>
|
</Bucket>
|
||||||
|
|||||||
@ -14,6 +14,8 @@ import Firebase
|
|||||||
import GoogleMobileAds
|
import GoogleMobileAds
|
||||||
import FacebookCore
|
import FacebookCore
|
||||||
import StoreKit
|
import StoreKit
|
||||||
|
import UserMessagingPlatform
|
||||||
|
|
||||||
@_exported import IQKeyboardManagerSwift
|
@_exported import IQKeyboardManagerSwift
|
||||||
@UIApplicationMain
|
@UIApplicationMain
|
||||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
@ -57,8 +59,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
window?.backgroundColor = .init(hex: "#161616")
|
window?.backgroundColor = .init(hex: "#161616")
|
||||||
//关联faceBook
|
//关联faceBook
|
||||||
ApplicationDelegate.shared.application(application,didFinishLaunchingWithOptions: launchOptions)
|
ApplicationDelegate.shared.application(application,didFinishLaunchingWithOptions: launchOptions)
|
||||||
//初始化三个控制器
|
|
||||||
positiceVC = MPPositive_TabBarController()
|
|
||||||
switch_lunch()
|
switch_lunch()
|
||||||
//执行用户启动事件日志
|
//执行用户启动事件日志
|
||||||
MP_AnalyticsManager.shared.user_launchAction()
|
MP_AnalyticsManager.shared.user_launchAction()
|
||||||
@ -162,7 +162,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
//销毁A面所有内容
|
//销毁A面所有内容
|
||||||
MPSideA_MediaCenterManager.shared.destroySideA()
|
MPSideA_MediaCenterManager.shared.destroySideA()
|
||||||
MPSideA_VolumeManager.shared.destroySideA()
|
MPSideA_VolumeManager.shared.destroySideA()
|
||||||
|
positiceVC = MPPositive_TabBarController()
|
||||||
//动画设置
|
//动画设置
|
||||||
let transtition = CATransition()
|
let transtition = CATransition()
|
||||||
transtition.duration = 0.8
|
transtition.duration = 0.8
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 172 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 7.7 KiB |
@ -5,12 +5,12 @@
|
|||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "img_v3_02b6_9dd8ad60-2766-4b89-9959-401f232d926g.png",
|
"filename" : "img_v3_02ed_b27cf77e-1e80-492f-b990-6592a6be80ag.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "img_v3_02b6_9dd8ad60-2766-4b89-9959-401f232d926g 1.png",
|
"filename" : "img_v3_02ed_b27cf77e-1e80-492f-b990-6592a6be80ag 1.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 192 KiB |
|
After Width: | Height: | Size: 192 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Lunch/Lunch'bg.imageset/20240909-100133 1.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Lunch/Lunch'bg.imageset/20240909-100133.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
@ -5,12 +5,12 @@
|
|||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "启动页-NEW@2x.png",
|
"filename" : "20240909-100133.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "启动页-NEW@3x.png",
|
"filename" : "20240909-100133 1.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 873 KiB |
|
Before Width: | Height: | Size: 1.8 MiB |
@ -5,12 +5,12 @@
|
|||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "蓝色背景@2x.png",
|
"filename" : "Group_1597880777@2x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "蓝色背景@3x.png",
|
"filename" : "Group_1597880777@3x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
||||||
|
|||||||
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 140 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Love Songs'bg.imageset/001@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Love Songs'bg.imageset/001@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 90 KiB |
@ -5,12 +5,12 @@
|
|||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "橙色背景@2x.png",
|
"filename" : "001@2x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "橙色背景@3x.png",
|
"filename" : "001@3x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 144 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Offline Songs'bg.imageset/003@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
relax.offline.mp3.music/Assets.xcassets/Positive/Center/Offline Songs'bg.imageset/003@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 95 KiB |
@ -5,12 +5,12 @@
|
|||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "紫色背景@2x.png",
|
"filename" : "003@2x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "紫色背景@3x.png",
|
"filename" : "003@3x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 134 KiB |
@ -32,12 +32,6 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
private var switchBlock:(() -> Void)?
|
private var switchBlock:(() -> Void)?
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
|
||||||
//printCallStack()
|
|
||||||
// 请求跟踪授权
|
|
||||||
requestTrackingAuthorization { idfa in
|
|
||||||
}
|
|
||||||
}
|
|
||||||
view.backgroundColor = .init(hex: "#000000")
|
view.backgroundColor = .init(hex: "#000000")
|
||||||
timer = CADisplayLink(target: self, selector: #selector(timerActionClick(_ :)))
|
timer = CADisplayLink(target: self, selector: #selector(timerActionClick(_ :)))
|
||||||
|
|
||||||
@ -123,6 +117,7 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
guard UserDefaults.standard.bool(forKey: "MP_Into_B") != true else {
|
guard UserDefaults.standard.bool(forKey: "MP_Into_B") != true else {
|
||||||
MP_IAPManager.shared.startLunchStatus()
|
MP_IAPManager.shared.startLunchStatus()
|
||||||
MPPositive_BrowseLoadViewModel.shared.getRecentlyData()
|
MPPositive_BrowseLoadViewModel.shared.getRecentlyData()
|
||||||
|
MP_LuxServerManager.shared.upDateOpenActiveEventTask()
|
||||||
//更新开关以及响应的数据
|
//更新开关以及响应的数据
|
||||||
MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in
|
MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in
|
||||||
if open {
|
if open {
|
||||||
@ -169,6 +164,7 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
|
|||||||
[weak self] in
|
[weak self] in
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
MP_IAPManager.shared.startLunchStatus()
|
MP_IAPManager.shared.startLunchStatus()
|
||||||
|
MP_LuxServerManager.shared.upDateOpenActiveEventTask()
|
||||||
//进行开关检测
|
//进行开关检测
|
||||||
MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in
|
MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
|
|||||||
@ -33,6 +33,8 @@ extension NotificationCenter{
|
|||||||
struct notificationKey:NotificationKey {
|
struct notificationKey:NotificationKey {
|
||||||
///关键词
|
///关键词
|
||||||
enum Keys:String {
|
enum Keys:String {
|
||||||
|
///通知用户更新
|
||||||
|
case update_reminder
|
||||||
///切换taBarItem
|
///切换taBarItem
|
||||||
case switch_tabBarItem
|
case switch_tabBarItem
|
||||||
//MARK: - A面通知内容
|
//MARK: - A面通知内容
|
||||||
|
|||||||
@ -10,5 +10,4 @@
|
|||||||
///麦克风使用说明
|
///麦克风使用说明
|
||||||
"NSMicrophoneUsageDescription" = "يتطلب \"HiMelody\" منك تشغيل الميكروفون الخاص بك للتعرف على وحدات الديسيبل المحيطة وتشغيل الضوضاء البيضاء تلقائيًا نيابةً عنك. هل تريد السماح لهذا التطبيق بالوصول إلى الميكروفون الخاص بك؟";
|
"NSMicrophoneUsageDescription" = "يتطلب \"HiMelody\" منك تشغيل الميكروفون الخاص بك للتعرف على وحدات الديسيبل المحيطة وتشغيل الضوضاء البيضاء تلقائيًا نيابةً عنك. هل تريد السماح لهذا التطبيق بالوصول إلى الميكروفون الخاص بك؟";
|
||||||
///用户跟踪使用说明
|
///用户跟踪使用说明
|
||||||
"NSUserTrackingUsageDescription" = "يحتاج \"HiMelody\" إلى طلب أذونات التتبع لتوفير تجربة إعلانية مخصصة. نحن نحترم ونحمي خصوصيتك ولن نبيع بياناتك لأطراف ثالث
|
"NSUserTrackingUsageDescription" = "يحتاج \"HiMelody\" إلى طلب أذونات التتبع لتوفير تجربة إعلانية مخصصة. نحن نحترم ونحمي خصوصيتك ولن نبيع بياناتك لأطراف ثالث.";
|
||||||
.";
|
|
||||||
|
|||||||
@ -134,6 +134,14 @@
|
|||||||
"Because you listen" = "لأنك سمعت";
|
"Because you listen" = "لأنك سمعت";
|
||||||
///因为你喜欢
|
///因为你喜欢
|
||||||
"Because you like" = "لأنك تحب";
|
"Because you like" = "لأنك تحب";
|
||||||
|
///提醒用户更新
|
||||||
|
"A new version of our app is now available! We've made some exciting improvements and added new features to enhance your experience. To enjoy these updates and continue using our app seamlessly, please update to the latest version now.\nTap on 'Update' to get the latest features and enhancements." = "إصدار جديد من تطبيقنا متاح الآن! قمنا بتحسينات مثيرة وأضفنا ميزات جديدة لتعزيز تجربتك. للاستمتاع بهذه التحديثات والمتابعة في استخدام تطبيقنا بسلاسة، يرجى تحديث إلى أحدث إصدار الآن.اضغط على 'تحديث' للحصول على أحدث الميزات والتحسينات.";
|
||||||
|
///更新
|
||||||
|
"Update" = "تحديث";
|
||||||
|
///不是现在
|
||||||
|
"Not now" = "ليس الآن";
|
||||||
|
///更新提醒
|
||||||
|
"Update available" = "تحديث متاح";
|
||||||
//MARK: - HUD文本
|
//MARK: - HUD文本
|
||||||
///已成功将电子邮件地址复制到剪贴板
|
///已成功将电子邮件地址复制到剪贴板
|
||||||
"Successfully copied the e-mail address to the clipboard" = "تم نسخ عنوان البريد الإلكتروني بنجاح إلى الحافظة";
|
"Successfully copied the e-mail address to the clipboard" = "تم نسخ عنوان البريد الإلكتروني بنجاح إلى الحافظة";
|
||||||
|
|||||||
@ -134,6 +134,14 @@
|
|||||||
"Because you listen" = "Weil du es gehört hast";
|
"Because you listen" = "Weil du es gehört hast";
|
||||||
///因为你喜欢
|
///因为你喜欢
|
||||||
"Because you like" = "Weil es dir gefällt";
|
"Because you like" = "Weil es dir gefällt";
|
||||||
|
///提醒用户更新
|
||||||
|
"A new version of our app is now available! We've made some exciting improvements and added new features to enhance your experience. To enjoy these updates and continue using our app seamlessly, please update to the latest version now.\nTap on 'Update' to get the latest features and enhancements." = "Eine neue Version unserer App ist jetzt verfügbar! Wir haben aufregende Verbesserungen vorgenommen und neue Funktionen hinzugefügt, um Ihr Erlebnis zu verbessern. Um diese Updates zu genießen und unsere App nahtlos weiter zu verwenden, aktualisieren Sie bitte jetzt auf die neueste Version.\nTippen Sie auf 'Aktualisieren', um die neuesten Funktionen und Verbesserungen zu erhalten.";
|
||||||
|
///更新
|
||||||
|
"Update" = "Aktualisieren";
|
||||||
|
///不是现在
|
||||||
|
"Not now" = "Nicht jetzt";
|
||||||
|
///更新提醒
|
||||||
|
"Update available" = "Aktualisierung verfügbar";
|
||||||
//MARK: - HUD文本
|
//MARK: - HUD文本
|
||||||
///已成功将电子邮件地址复制到剪贴板
|
///已成功将电子邮件地址复制到剪贴板
|
||||||
"Successfully copied the e-mail address to the clipboard" = "E-Mail-Adresse erfolgreich in die Zwischenablage kopiert";
|
"Successfully copied the e-mail address to the clipboard" = "E-Mail-Adresse erfolgreich in die Zwischenablage kopiert";
|
||||||
|
|||||||
@ -134,6 +134,14 @@
|
|||||||
"Because you listen" = "Because you listen";
|
"Because you listen" = "Because you listen";
|
||||||
///因为你喜欢
|
///因为你喜欢
|
||||||
"Because you like" = "Because you like";
|
"Because you like" = "Because you like";
|
||||||
|
///提醒用户更新
|
||||||
|
"A new version of our app is now available! We've made some exciting improvements and added new features to enhance your experience. To enjoy these updates and continue using our app seamlessly, please update to the latest version now.\nTap on 'Update' to get the latest features and enhancements." = "A new version of our app is now available! We've made some exciting improvements and added new features to enhance your experience. To enjoy these updates and continue using our app seamlessly, please update to the latest version now.\nTap on 'Update' to get the latest features and enhancements.";
|
||||||
|
///更新
|
||||||
|
"Update" = "Update";
|
||||||
|
///不是现在
|
||||||
|
"Not now" = "Not now";
|
||||||
|
///更新提醒
|
||||||
|
"Update available" = "Update available";
|
||||||
//MARK: - HUD文本
|
//MARK: - HUD文本
|
||||||
///已成功将电子邮件地址复制到剪贴板
|
///已成功将电子邮件地址复制到剪贴板
|
||||||
"Successfully copied the e-mail address to the clipboard" = "Successfully copied the e-mail address to the clipboard";
|
"Successfully copied the e-mail address to the clipboard" = "Successfully copied the e-mail address to the clipboard";
|
||||||
|
|||||||
@ -134,6 +134,14 @@
|
|||||||
"Because you listen" = "Porque has escuchado";
|
"Because you listen" = "Porque has escuchado";
|
||||||
///因为你喜欢
|
///因为你喜欢
|
||||||
"Because you like" = "Porque te gusta";
|
"Because you like" = "Porque te gusta";
|
||||||
|
///提醒用户更新
|
||||||
|
"A new version of our app is now available! We've made some exciting improvements and added new features to enhance your experience. To enjoy these updates and continue using our app seamlessly, please update to the latest version now.\nTap on 'Update' to get the latest features and enhancements." = "¡Una nueva versión de nuestra aplicación ya está disponible! Hemos realizado emocionantes mejoras y añadido nuevas características para mejorar tu experiencia. Para disfrutar de estas actualizaciones y seguir utilizando nuestra aplicación sin problemas, por favor actualiza a la última versión ahora.\n¡Toca en 'Actualizar' para obtener las últimas características y mejoras.";
|
||||||
|
///更新
|
||||||
|
"Update" = "Actualizar";
|
||||||
|
///不是现在
|
||||||
|
"Not now" = "Ahora no";
|
||||||
|
///更新提醒
|
||||||
|
"Update available" = "Actualización disponible";
|
||||||
//MARK: - HUD文本
|
//MARK: - HUD文本
|
||||||
///已成功将电子邮件地址复制到剪贴板
|
///已成功将电子邮件地址复制到剪贴板
|
||||||
"Successfully copied the e-mail address to the clipboard" = "Dirección de correo electrónico copiada correctamente al portapapeles";
|
"Successfully copied the e-mail address to the clipboard" = "Dirección de correo electrónico copiada correctamente al portapapeles";
|
||||||
|
|||||||
@ -134,6 +134,14 @@
|
|||||||
"Because you listen" = "Parce que tu as entendu";
|
"Because you listen" = "Parce que tu as entendu";
|
||||||
///因为你喜欢
|
///因为你喜欢
|
||||||
"Because you like" = "Parce que tu aimes";
|
"Because you like" = "Parce que tu aimes";
|
||||||
|
///提醒用户更新
|
||||||
|
"A new version of our app is now available! We've made some exciting improvements and added new features to enhance your experience. To enjoy these updates and continue using our app seamlessly, please update to the latest version now.\nTap on 'Update' to get the latest features and enhancements." = "Une nouvelle version de notre application est désormais disponible ! Nous avons apporté des améliorations passionnantes et ajouté de nouvelles fonctionnalités pour améliorer votre expérience. Pour profiter de ces mises à jour et continuer à utiliser notre application sans problème, veuillez mettre à jour vers la dernière version maintenant.\nAppuyez sur 'Mettre à jour' pour obtenir les dernières fonctionnalités et améliorations.";
|
||||||
|
///更新
|
||||||
|
"Update" = "Mettre à jour";
|
||||||
|
///不是现在
|
||||||
|
"Not now" = "Pas maintenant";
|
||||||
|
///更新提醒
|
||||||
|
"Update available" = "Mise à jour disponible";
|
||||||
//MARK: - HUD文本
|
//MARK: - HUD文本
|
||||||
///已成功将电子邮件地址复制到剪贴板
|
///已成功将电子邮件地址复制到剪贴板
|
||||||
"Successfully copied the e-mail address to the clipboard" = "Adresse e-mail copiée avec succès dans le presse-papiers";
|
"Successfully copied the e-mail address to the clipboard" = "Adresse e-mail copiée avec succès dans le presse-papiers";
|
||||||
|
|||||||
@ -134,6 +134,14 @@
|
|||||||
"Because you listen" = "Perché hai sentito";
|
"Because you listen" = "Perché hai sentito";
|
||||||
///因为你喜欢
|
///因为你喜欢
|
||||||
"Because you like" = "Perché ti piace";
|
"Because you like" = "Perché ti piace";
|
||||||
|
///提醒用户更新
|
||||||
|
"A new version of our app is now available! We've made some exciting improvements and added new features to enhance your experience. To enjoy these updates and continue using our app seamlessly, please update to the latest version now.\nTap on 'Update' to get the latest features and enhancements." = "Una nuova versione della nostra app è ora disponibile! Abbiamo apportato eccitanti miglioramenti e aggiunto nuove funzionalità per migliorare la tua esperienza. Per godere di questi aggiornamenti e continuare ad utilizzare la nostra app senza intoppi, ti preghiamo di aggiornare alla versione più recente ora.\nTocca su 'Aggiorna' per ottenere le ultime funzionalità e miglioramenti.";
|
||||||
|
///更新
|
||||||
|
"Update" = "Aggiorna";
|
||||||
|
///不是现在
|
||||||
|
"Not now" = "Non ora";
|
||||||
|
///更新提醒
|
||||||
|
"Update available" = "Aggiornamento disponibile";
|
||||||
//MARK: - HUD文本
|
//MARK: - HUD文本
|
||||||
///已成功将电子邮件地址复制到剪贴板
|
///已成功将电子邮件地址复制到剪贴板
|
||||||
"Successfully copied the e-mail address to the clipboard" = "Indirizzo email copiato con successo negli appunti";
|
"Successfully copied the e-mail address to the clipboard" = "Indirizzo email copiato con successo negli appunti";
|
||||||
|
|||||||
@ -134,6 +134,14 @@
|
|||||||
"Because you listen" = "Porque você ouviu";
|
"Because you listen" = "Porque você ouviu";
|
||||||
///因为你喜欢
|
///因为你喜欢
|
||||||
"Because you like" = "Porque você gosta";
|
"Because you like" = "Porque você gosta";
|
||||||
|
///提醒用户更新
|
||||||
|
"A new version of our app is now available! We've made some exciting improvements and added new features to enhance your experience. To enjoy these updates and continue using our app seamlessly, please update to the latest version now.\nTap on 'Update' to get the latest features and enhancements." = "Uma nova versão do nosso aplicativo já está disponível! Fizemos melhorias emocionantes e adicionamos novos recursos para aprimorar sua experiência. Para aproveitar essas atualizações e continuar usando nosso aplicativo sem problemas, por favor atualize para a última versão agora.\nToque em 'Atualizar' para obter os últimos recursos e melhorias.";
|
||||||
|
///更新
|
||||||
|
"Update" = "Atualizar";
|
||||||
|
///不是现在
|
||||||
|
"Not now" = "Não agora";
|
||||||
|
///更新提醒
|
||||||
|
"Update available" = "Atualização disponível";
|
||||||
//MARK: - HUD文本
|
//MARK: - HUD文本
|
||||||
///已成功将电子邮件地址复制到剪贴板
|
///已成功将电子邮件地址复制到剪贴板
|
||||||
"Successfully copied the e-mail address to the clipboard" = "Endereço de e-mail copiado com sucesso para a área de transferência";
|
"Successfully copied the e-mail address to the clipboard" = "Endereço de e-mail copiado com sucesso para a área de transferência";
|
||||||
|
|||||||
@ -134,6 +134,14 @@
|
|||||||
"Because you listen" = "çünkü duydun";
|
"Because you listen" = "çünkü duydun";
|
||||||
///因为你喜欢
|
///因为你喜欢
|
||||||
"Because you like" = "çünkü seviyorsun";
|
"Because you like" = "çünkü seviyorsun";
|
||||||
|
///提醒用户更新
|
||||||
|
"A new version of our app is now available! We've made some exciting improvements and added new features to enhance your experience. To enjoy these updates and continue using our app seamlessly, please update to the latest version now.\nTap on 'Update' to get the latest features and enhancements." = "Uygulamamızın yeni bir sürümü artık kullanılabilir! Heyecan verici iyileştirmeler yaptık ve deneyiminizi artırmak için yeni özellikler ekledik. Bu güncellemelerden yararlanmak ve uygulamamızı sorunsuz bir şekilde kullanmaya devam etmek için lütfen şimdi en son sürüme güncelleyin.\nEn son özellikleri ve geliştirmeleri almak için 'Güncelle'ye dokunun.";
|
||||||
|
///更新
|
||||||
|
"Update" = "Güncelle";
|
||||||
|
///不是现在
|
||||||
|
"Not now" = "Şimdi değil";
|
||||||
|
///更新提醒
|
||||||
|
"Update available" = "Güncelleme mevcut";
|
||||||
//MARK: - HUD文本
|
//MARK: - HUD文本
|
||||||
///已成功将电子邮件地址复制到剪贴板
|
///已成功将电子邮件地址复制到剪贴板
|
||||||
"Successfully copied the e-mail address to the clipboard" = "Herhangi bir yorumunuz veya öneriniz varsa lütfen aşağıdaki e-posta adresinden bizimle iletişime geçin.";
|
"Successfully copied the e-mail address to the clipboard" = "Herhangi bir yorumunuz veya öneriniz varsa lütfen aşağıdaki e-posta adresinden bizimle iletişime geçin.";
|
||||||
|
|||||||
@ -70,7 +70,7 @@ let love_songBGImage:UIImage = UIImage(named: "Love Songs'bg")!
|
|||||||
///收藏歌手占位图
|
///收藏歌手占位图
|
||||||
let love_artistBGImage:UIImage = UIImage(named: "Love Artists'bg")!
|
let love_artistBGImage:UIImage = UIImage(named: "Love Artists'bg")!
|
||||||
///离线下载占位图
|
///离线下载占位图
|
||||||
let offline_songBGImage:UIImage = UIImage(named: "Offline Songs")!
|
let offline_songBGImage:UIImage = UIImage(named: "Offline Songs'bg")!
|
||||||
///隐私政策网址
|
///隐私政策网址
|
||||||
let privacyUrl:URL = .init(string: "https://musiclax.mystrikingly.com/privacy")!
|
let privacyUrl:URL = .init(string: "https://musiclax.mystrikingly.com/privacy")!
|
||||||
///用户协议网址
|
///用户协议网址
|
||||||
@ -81,6 +81,15 @@ let gradientTextColors:[CGColor] = [UIColor(red: 0, green: 0.863, blue: 1, alpha
|
|||||||
UIColor(red: 0.776, green: 1, blue: 0.639, alpha: 1).cgColor]
|
UIColor(red: 0.776, green: 1, blue: 0.639, alpha: 1).cgColor]
|
||||||
///常用文本颜色-绿色
|
///常用文本颜色-绿色
|
||||||
let greenTextColor:UIColor = .init(hex: "#80F988", alpha: 1.0)
|
let greenTextColor:UIColor = .init(hex: "#80F988", alpha: 1.0)
|
||||||
|
///是否需要提醒用户更新
|
||||||
|
var isUpDateReminder:Bool = false{
|
||||||
|
willSet{
|
||||||
|
if newValue == true {
|
||||||
|
//新值为更新提醒,发布通知
|
||||||
|
NotificationCenter.notificationKey.post(notificationName: .update_reminder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//MARK: - 全局变量与方法
|
//MARK: - 全局变量与方法
|
||||||
//存储默认配置值
|
//存储默认配置值
|
||||||
@ -504,3 +513,25 @@ func printCallStack() {
|
|||||||
let callStack = Thread.callStackSymbols
|
let callStack = Thread.callStackSymbols
|
||||||
print("Call Stack: \(callStack)")
|
print("Call Stack: \(callStack)")
|
||||||
}
|
}
|
||||||
|
///弹出一个更新通知弹窗
|
||||||
|
func postUpdateReminder(_ observe:UIViewController) {
|
||||||
|
let alter = UIAlertController(title: "Update available".localizableString(), message: "A new version of our app is now available! We've made some exciting improvements and added new features to enhance your experience. To enjoy these updates and continue using our app seamlessly, please update to the latest version now.\nTap on 'Update' to get the latest features and enhancements.".localizableString(), preferredStyle: .alert)
|
||||||
|
//取消
|
||||||
|
let not = UIAlertAction(title: "Not now".localizableString(), style: .cancel) { action in
|
||||||
|
//用户取消更新事件
|
||||||
|
MP_AnalyticsManager.shared.update_reminder_cancelAction()
|
||||||
|
print("用户取消更新")
|
||||||
|
}
|
||||||
|
alter.addAction(not)
|
||||||
|
let updata = UIAlertAction(title: "Update".localizableString(), style: .destructive) { action in
|
||||||
|
//用户确定更新事件
|
||||||
|
MP_AnalyticsManager.shared.update_reminder_sureAction()
|
||||||
|
//跳转AppStore
|
||||||
|
if let url = URL(string: "https://apps.apple.com/app/6502973957") {
|
||||||
|
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alter.addAction(updata)
|
||||||
|
MP_AnalyticsManager.shared.update_reminder_showAction()
|
||||||
|
observe.present(alter, animated: true)
|
||||||
|
}
|
||||||
|
|||||||
@ -272,22 +272,8 @@ class MP_PlayerResourceLoader: NSObject, AVAssetResourceLoaderDelegate {
|
|||||||
processRequestList(id ?? "")
|
processRequestList(id ?? "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// /// 缓存结果
|
|
||||||
// func requestManagerIsCached(_ isCached: Bool, videoId:String){
|
|
||||||
// if self.videoId == videoId {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// /// 接收数据完成
|
|
||||||
// func requestManagerDidComplete(withError errorCode: Int, videoId:String){
|
|
||||||
// if self.videoId == videoId {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///媒体播放器工具配置
|
///媒体播放器工具配置
|
||||||
class MP_PlayerToolConfig:NSObject {
|
class MP_PlayerToolConfig:NSObject {
|
||||||
///自定义URL链接
|
///自定义URL链接
|
||||||
@ -309,7 +295,6 @@ class MP_PlayerToolConfig:NSObject {
|
|||||||
return components.url
|
return components.url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MP_PlayerTaskManager:NSObject, URLSessionDataDelegate{
|
class MP_PlayerTaskManager:NSObject, URLSessionDataDelegate{
|
||||||
static var shared = MP_PlayerTaskManager()
|
static var shared = MP_PlayerTaskManager()
|
||||||
///请求代理
|
///请求代理
|
||||||
@ -340,6 +325,23 @@ class MP_PlayerTaskManager:NSObject, URLSessionDataDelegate{
|
|||||||
var titles:[String:String]!
|
var titles:[String:String]!
|
||||||
//后台加载执行任务
|
//后台加载执行任务
|
||||||
var sessionCompletionHandler: (() -> Void)?
|
var sessionCompletionHandler: (() -> Void)?
|
||||||
|
//后台任务ID
|
||||||
|
var backgroundTaskID: UIBackgroundTaskIdentifier?
|
||||||
|
//开始后台任务
|
||||||
|
func beginBackgroundTask() {
|
||||||
|
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
|
||||||
|
// 在系统终止后台任务时调用
|
||||||
|
UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
|
||||||
|
self.backgroundTaskID = UIBackgroundTaskIdentifier.invalid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//结束后台任务
|
||||||
|
func endBackgroundTask() {
|
||||||
|
if let backgroundTaskID = backgroundTaskID {
|
||||||
|
UIApplication.shared.endBackgroundTask(backgroundTaskID)
|
||||||
|
self.backgroundTaskID = UIBackgroundTaskIdentifier.invalid
|
||||||
|
}
|
||||||
|
}
|
||||||
//默认任务最大数
|
//默认任务最大数
|
||||||
private var maxCount = 4
|
private var maxCount = 4
|
||||||
override init() {
|
override init() {
|
||||||
@ -350,6 +352,8 @@ class MP_PlayerTaskManager:NSObject, URLSessionDataDelegate{
|
|||||||
configuration.timeoutIntervalForRequest = 30
|
configuration.timeoutIntervalForRequest = 30
|
||||||
configuration.timeoutIntervalForResource = 30
|
configuration.timeoutIntervalForResource = 30
|
||||||
configuration.allowsCellularAccess = true
|
configuration.allowsCellularAccess = true
|
||||||
|
configuration.sessionSendsLaunchEvents = true
|
||||||
|
configuration.isDiscretionary = false
|
||||||
//实现会话
|
//实现会话
|
||||||
session = .init(configuration: configuration, delegate: self, delegateQueue: nil)
|
session = .init(configuration: configuration, delegate: self, delegateQueue: nil)
|
||||||
//初始化
|
//初始化
|
||||||
@ -533,6 +537,11 @@ class MP_PlayerTaskManager:NSObject, URLSessionDataDelegate{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//后台触发任务时
|
||||||
|
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
|
||||||
|
print("任务已经全部完成了")
|
||||||
|
}
|
||||||
|
|
||||||
//重试机制
|
//重试机制
|
||||||
private func retryTask(task:URLSessionTask) {
|
private func retryTask(task:URLSessionTask) {
|
||||||
accessQueue.async {
|
accessQueue.async {
|
||||||
|
|||||||
@ -99,6 +99,12 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
private let VIP_buy_success = "VIP_buy_success"
|
private let VIP_buy_success = "VIP_buy_success"
|
||||||
///购买失败
|
///购买失败
|
||||||
private let VIP_buy_failure = "VIP_buy_failure"
|
private let VIP_buy_failure = "VIP_buy_failure"
|
||||||
|
///弹出更新框
|
||||||
|
private let update_reminder_show = "update_reminder_show"
|
||||||
|
///取消更新
|
||||||
|
private let update_reminder_cancel = "update_reminder_cancel"
|
||||||
|
///确认更新
|
||||||
|
private let update_reminder_sure = "update_reminder_sure"
|
||||||
private override init() {
|
private override init() {
|
||||||
//获取用户是新用户还是老用户
|
//获取用户是新用户还是老用户
|
||||||
if UserDefaults.standard.bool(forKey: "UserStatus") {
|
if UserDefaults.standard.bool(forKey: "UserStatus") {
|
||||||
@ -184,7 +190,37 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
//更新通知
|
//更新通知
|
||||||
scheduleDailyNotifications()
|
scheduleDailyNotifications()
|
||||||
}
|
}
|
||||||
|
//是否需要弹出更新弹窗
|
||||||
|
if let updateReminder = self.remoteConfig.configValue(forKey: "updateReminder").jsonValue as? [String:Any] {
|
||||||
|
//检索是否需要更新
|
||||||
|
if let statu = updateReminder["statu"] as? Bool, let version = updateReminder["versionCode"] as? String {
|
||||||
|
//获得更新状态,根据更新状态确定是否需要弹出广告
|
||||||
|
if statu {
|
||||||
|
//需要更新,检索当前版本是否为最新的版本
|
||||||
|
if version == app_Version {
|
||||||
|
//不用更新
|
||||||
|
isUpDateReminder = false
|
||||||
|
print("无需更新")
|
||||||
|
}else {
|
||||||
|
//需要更新
|
||||||
|
isUpDateReminder = true
|
||||||
|
print("需要更新")
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
//不用更新
|
||||||
|
isUpDateReminder = false
|
||||||
|
print("无需更新")
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
//不用更新
|
||||||
|
isUpDateReminder = false
|
||||||
|
print("无需更新")
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
//不用更新
|
||||||
|
isUpDateReminder = false
|
||||||
|
print("无需更新")
|
||||||
|
}
|
||||||
let js = self.remoteConfig.configValue(forKey: "openStatus").jsonValue as! [String:Any]
|
let js = self.remoteConfig.configValue(forKey: "openStatus").jsonValue as! [String:Any]
|
||||||
let value = js["versionCode"] as! String
|
let value = js["versionCode"] as! String
|
||||||
if value == app_Version {
|
if value == app_Version {
|
||||||
@ -499,6 +535,18 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
Analytics.logEvent(VIP_buy_failure, parameters: ["productID":productID,
|
Analytics.logEvent(VIP_buy_failure, parameters: ["productID":productID,
|
||||||
"buy_error":error])
|
"buy_error":error])
|
||||||
}
|
}
|
||||||
|
///弹出更新框
|
||||||
|
func update_reminder_showAction() {
|
||||||
|
Analytics.logEvent(update_reminder_show, parameters: nil)
|
||||||
|
}
|
||||||
|
///确认更新
|
||||||
|
func update_reminder_sureAction() {
|
||||||
|
Analytics.logEvent(update_reminder_sure, parameters: nil)
|
||||||
|
}
|
||||||
|
///取消更新
|
||||||
|
func update_reminder_cancelAction() {
|
||||||
|
Analytics.logEvent(update_reminder_cancel, parameters: nil)
|
||||||
|
}
|
||||||
//MARK: - 广告埋点事件
|
//MARK: - 广告埋点事件
|
||||||
//冷启动展示机会
|
//冷启动展示机会
|
||||||
private let cold_ads_chance:String = "cold_ads_chance"
|
private let cold_ads_chance:String = "cold_ads_chance"
|
||||||
@ -643,7 +691,6 @@ class MP_AnalyticsManager: NSObject {
|
|||||||
///冷启动关闭
|
///冷启动关闭
|
||||||
func cold_ads_closeAction() {
|
func cold_ads_closeAction() {
|
||||||
let parameters:[String:String] = ["CS_STATUS":isOLD ? "Old":"New"]
|
let parameters:[String:String] = ["CS_STATUS":isOLD ? "Old":"New"]
|
||||||
print("冷启动失败展示信息--\(parameters)")
|
|
||||||
Analytics.logEvent(cold_ads_close, parameters: parameters)
|
Analytics.logEvent(cold_ads_close, parameters: parameters)
|
||||||
}
|
}
|
||||||
///热启动展示机会
|
///热启动展示机会
|
||||||
|
|||||||
@ -158,7 +158,9 @@ class MP_DownloadManager: NSObject {
|
|||||||
self.downloadTasks?[nextVideoId]?.status = .downloading
|
self.downloadTasks?[nextVideoId]?.status = .downloading
|
||||||
}
|
}
|
||||||
//更新对应任务(videoId)的进度值
|
//更新对应任务(videoId)的进度值
|
||||||
|
loadQueue.async {
|
||||||
self.progressStorage?[nextVideoId] = task.progress.fractionCompleted
|
self.progressStorage?[nextVideoId] = task.progress.fractionCompleted
|
||||||
|
}
|
||||||
//执行下载进度更新代理
|
//执行下载进度更新代理
|
||||||
NotificationCenter.notificationKey.post(notificationName: .download_progress_source, object: ["videoId":nextVideoId])
|
NotificationCenter.notificationKey.post(notificationName: .download_progress_source, object: ["videoId":nextVideoId])
|
||||||
}
|
}
|
||||||
@ -191,7 +193,9 @@ class MP_DownloadManager: NSObject {
|
|||||||
self.downloadTasks?[nextVideoId]?.status = .failed
|
self.downloadTasks?[nextVideoId]?.status = .failed
|
||||||
}
|
}
|
||||||
downloadURLs?[nextVideoId] = nil
|
downloadURLs?[nextVideoId] = nil
|
||||||
progressStorage?[nextVideoId] = nil
|
loadQueue.async {
|
||||||
|
self.progressStorage?[nextVideoId] = nil
|
||||||
|
}
|
||||||
songHandlers?[nextVideoId] = nil
|
songHandlers?[nextVideoId] = nil
|
||||||
MP_HUD.text("An error occurred while downloading. Please download again.".localizableString(), delay: 1.5, completion: nil)
|
MP_HUD.text("An error occurred while downloading. Please download again.".localizableString(), delay: 1.5, completion: nil)
|
||||||
session.cancel(task) { _ in
|
session.cancel(task) { _ in
|
||||||
@ -214,7 +218,9 @@ class MP_DownloadManager: NSObject {
|
|||||||
}
|
}
|
||||||
self.downloadURLs?[nextVideoId] = nil
|
self.downloadURLs?[nextVideoId] = nil
|
||||||
self.downloadTasks?[nextVideoId] = nil
|
self.downloadTasks?[nextVideoId] = nil
|
||||||
|
loadQueue.async {
|
||||||
self.progressStorage?[nextVideoId] = nil
|
self.progressStorage?[nextVideoId] = nil
|
||||||
|
}
|
||||||
self.songHandlers?[nextVideoId] = nil
|
self.songHandlers?[nextVideoId] = nil
|
||||||
//告知用户下载成功
|
//告知用户下载成功
|
||||||
MP_HUD.downloadText("Download Successfull".localizableString(), delay: 1.0, completion: nil)
|
MP_HUD.downloadText("Download Successfull".localizableString(), delay: 1.0, completion: nil)
|
||||||
@ -240,7 +246,9 @@ class MP_DownloadManager: NSObject {
|
|||||||
self.downloadTasks?[nextVideoId]?.status = .failed
|
self.downloadTasks?[nextVideoId]?.status = .failed
|
||||||
}
|
}
|
||||||
downloadURLs?[nextVideoId] = nil
|
downloadURLs?[nextVideoId] = nil
|
||||||
progressStorage?[nextVideoId] = nil
|
loadQueue.async {
|
||||||
|
self.progressStorage?[nextVideoId] = nil
|
||||||
|
}
|
||||||
songHandlers?[nextVideoId] = nil
|
songHandlers?[nextVideoId] = nil
|
||||||
switch error.localizedDescription {
|
switch error.localizedDescription {
|
||||||
case "The operation couldn’t be completed. No space left on device":
|
case "The operation couldn’t be completed. No space left on device":
|
||||||
|
|||||||
@ -0,0 +1,305 @@
|
|||||||
|
//
|
||||||
|
// MP_LuxServerManager.swift
|
||||||
|
// relax.offline.mp3.music
|
||||||
|
//
|
||||||
|
// Created by Mr.Zhou on 2024/9/10.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import Alamofire
|
||||||
|
import Security
|
||||||
|
import AdSupport
|
||||||
|
///自家后台管理器
|
||||||
|
class MP_LuxServerManager: NSObject {
|
||||||
|
//单例工具
|
||||||
|
static let shared = MP_LuxServerManager()
|
||||||
|
///keychain关键词
|
||||||
|
private let service = "relax.offline.mp3.music.deviceIdentifier"
|
||||||
|
//MARK: - URL
|
||||||
|
///基础链接
|
||||||
|
private let baseUrl:String = "https://openapi.lux-ad.com"
|
||||||
|
///报活链接
|
||||||
|
private let activeUrl:String = "/statistic/appdatacollection/saveAppData"
|
||||||
|
///报错链接
|
||||||
|
private let errorUrl:String = "/statistic/applogscollection/save"
|
||||||
|
|
||||||
|
//MARK: - 通用参数值
|
||||||
|
///唯一的设备UUID(重装应用后,也会使用该设备ID)
|
||||||
|
private var uuID:String{
|
||||||
|
get{
|
||||||
|
return getDeviceUUID()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///用户ID(每次重装应用都会生成一个新的用户ID)
|
||||||
|
private var userID:String{
|
||||||
|
get{
|
||||||
|
return getUserID()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///IDFA广告跟踪ID(检索用户是否具备权限,无权限/位置状态返回内容则是由0构成的字符串;具备权限则会返回正常的跟踪ID)
|
||||||
|
private let IDFAID:String = ASIdentifierManager.shared().advertisingIdentifier.uuidString
|
||||||
|
///渠道
|
||||||
|
private let channel:String = "ios"
|
||||||
|
///包名
|
||||||
|
private let pkgName:String = "relax.offline.mp3.music"
|
||||||
|
///事件名
|
||||||
|
private var eventName:String {
|
||||||
|
get{
|
||||||
|
return getEventName()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///当前时间节点毫秒数
|
||||||
|
private var timestamp:Int64 {
|
||||||
|
get{
|
||||||
|
//获取当前时间值
|
||||||
|
let now = Date()
|
||||||
|
//获取时间缀,并转为毫秒级别
|
||||||
|
let currentTimestampInMillisInt:Int64 = Int64(now.timeIntervalSince1970 * 1000)
|
||||||
|
return currentTimestampInMillisInt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// 设备类型
|
||||||
|
private var deviceVersion: String {
|
||||||
|
return UIDevice.current.name
|
||||||
|
}
|
||||||
|
///系统版本
|
||||||
|
private var osVersion:String {
|
||||||
|
return UIDevice.current.systemVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - 会话
|
||||||
|
///后台会话
|
||||||
|
private lazy var LuxSession:Session = {
|
||||||
|
let configuration = URLSessionConfiguration.af.default
|
||||||
|
///超时设置
|
||||||
|
configuration.timeoutIntervalForRequest = 20
|
||||||
|
configuration.timeoutIntervalForResource = 20
|
||||||
|
// 可调整网络服务类型
|
||||||
|
configuration.networkServiceType = .default
|
||||||
|
let seesion = Alamofire.Session(configuration: configuration, interceptor: MP_CustomRetrier())
|
||||||
|
return seesion
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
///报活参数结构
|
||||||
|
/**
|
||||||
|
{
|
||||||
|
"eventName": "app_open",
|
||||||
|
"timestamp": 1711522237247,
|
||||||
|
"uuid": "c1c4c016cd6276b41e2447653fe5a9b2",
|
||||||
|
"app_version": "1.5.4",
|
||||||
|
"channel": "google",
|
||||||
|
"country": "cn",
|
||||||
|
"device": "android",
|
||||||
|
"language": "zh",
|
||||||
|
"pkgName": "com.master.ae.safevpn",
|
||||||
|
"userId": "55a7fa0c-be84-44b9-a73e-a4256dbb30ee",
|
||||||
|
"adId": "995772a9-7748-418e-bef4-10ca1ad1abe1",
|
||||||
|
"createdOn": "2022-03-10T12:15:50.000Z",
|
||||||
|
"data": {
|
||||||
|
"property1": {},
|
||||||
|
"property2": {}
|
||||||
|
}
|
||||||
|
}**/
|
||||||
|
|
||||||
|
//MARK: - 报活操作
|
||||||
|
///实现报活会话
|
||||||
|
func upDateOpenActiveEventTask() {
|
||||||
|
//生成报活链接
|
||||||
|
guard let url = URL(string: baseUrl+activeUrl) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//生成参数
|
||||||
|
let parameters:[String:Any] = [
|
||||||
|
"userId":userID,
|
||||||
|
"ad_id":IDFAID,
|
||||||
|
"uuid":uuID,
|
||||||
|
"device":deviceVersion,
|
||||||
|
"appVersion":app_Version,
|
||||||
|
"language":Language_first_local,
|
||||||
|
"channel":channel,
|
||||||
|
"pkgName":pkgName,
|
||||||
|
"eventName":eventName,
|
||||||
|
"country":Language_first_local,
|
||||||
|
"dataStr":"Active",
|
||||||
|
"timestamp":timestamp
|
||||||
|
]
|
||||||
|
postUpDateOpenActiveEvent(url, parameters: parameters){
|
||||||
|
[weak self] statu in
|
||||||
|
guard let self = self, statu == true else {return}
|
||||||
|
//检索更多报活信息,并执行报活任务
|
||||||
|
var loads = loadPendingActivities()
|
||||||
|
guard loads.isEmpty == false else {return}
|
||||||
|
var indicesToRemove: [Int] = []
|
||||||
|
let dispatchGroup = DispatchGroup()
|
||||||
|
for (index, item) in loads.enumerated() {
|
||||||
|
dispatchGroup.enter()
|
||||||
|
postUpDateOpenActiveEvent(url, parameters: item, isRepeat: true) { [weak self] statu in
|
||||||
|
guard let self = self, statu == true else {
|
||||||
|
dispatchGroup.leave()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//报活成功,将成功的报活信息移除
|
||||||
|
indicesToRemove.append(index)
|
||||||
|
dispatchGroup.leave()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dispatchGroup.notify(queue: .main) {
|
||||||
|
[weak self] in
|
||||||
|
guard let self = self else {return}
|
||||||
|
// 删除收集的索引
|
||||||
|
for index in indicesToRemove.sorted(by: >) {
|
||||||
|
loads.remove(at: index)
|
||||||
|
}
|
||||||
|
reloadActivities(loads)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//执行报活
|
||||||
|
private func postUpDateOpenActiveEvent(_ url:URL, parameters:[String:Any], isRepeat:Bool = false, completion:((Bool) -> Void)?) {
|
||||||
|
LuxSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonActive.self) { [weak self] (response) in
|
||||||
|
guard let self = self else {return}
|
||||||
|
switch response.result {
|
||||||
|
case .success(let value):
|
||||||
|
print("成功报活:\(value)")
|
||||||
|
completion?(true)
|
||||||
|
case .failure(let error):
|
||||||
|
print("报活失败,失败错误:\(error.localizedDescription)")
|
||||||
|
if isRepeat == false {
|
||||||
|
//非重复信息,报活信息存入表中
|
||||||
|
saveActivity(parameters)
|
||||||
|
}
|
||||||
|
completion?(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//保存未加载
|
||||||
|
private func saveActivity(_ parameters:[String:Any]) {
|
||||||
|
var pendingActivities = loadPendingActivities()
|
||||||
|
pendingActivities.append(parameters)
|
||||||
|
if let encoded = try? JSONSerialization.data(withJSONObject: pendingActivities, options: []) {
|
||||||
|
UserDefaults.standard.set(encoded, forKey: "relax.offline.mp3.music.Activities")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//更新未加载信息
|
||||||
|
private func reloadActivities(_ loads:[[String:Any]]) {
|
||||||
|
if let encoded = try? JSONSerialization.data(withJSONObject: loads, options: []) {
|
||||||
|
UserDefaults.standard.set(encoded, forKey: "relax.offline.mp3.music.Activities")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//加载未上传的报活信息
|
||||||
|
private func loadPendingActivities() -> [[String:Any]] {
|
||||||
|
if let savedData = UserDefaults.standard.data(forKey: "relax.offline.mp3.music.Activities"),
|
||||||
|
let decoded = try? JSONSerialization.jsonObject(with: savedData, options: []) as? [[String: Any]] {
|
||||||
|
return decoded
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - 设备ID
|
||||||
|
///获得设备ID
|
||||||
|
private func getDeviceUUID() -> String {
|
||||||
|
if let uuid = loadUUIDFromKeychain() {
|
||||||
|
return uuid
|
||||||
|
} else {
|
||||||
|
let newUUID = UUID().uuidString
|
||||||
|
saveUUIDToKeychain(uuid: newUUID)
|
||||||
|
return newUUID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// 从 Keychain 中加载 UUID
|
||||||
|
private func loadUUIDFromKeychain() -> String? {
|
||||||
|
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
|
||||||
|
kSecAttrService as String: service,
|
||||||
|
kSecReturnData as String: true,
|
||||||
|
kSecMatchLimit as String: kSecMatchLimitOne]
|
||||||
|
|
||||||
|
var dataTypeRef: AnyObject? = nil
|
||||||
|
let status = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
|
||||||
|
if status == errSecSuccess {
|
||||||
|
if let data = dataTypeRef as? Data,
|
||||||
|
let uuid = String(data: data, encoding: .utf8) {
|
||||||
|
return uuid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 保存 UUID 到 Keychain
|
||||||
|
private func saveUUIDToKeychain(uuid: String) {
|
||||||
|
if let data = uuid.data(using: .utf8) {
|
||||||
|
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
|
||||||
|
kSecAttrService as String: service,
|
||||||
|
kSecValueData as String: data]
|
||||||
|
SecItemAdd(query as CFDictionary, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//MARK: - 用户ID
|
||||||
|
///获取用户ID
|
||||||
|
private func getUserID() -> String {
|
||||||
|
//检索Userdefaults的userID
|
||||||
|
if let userID = UserDefaults.standard.string(forKey: "relax.offline.mp3.music.userIdentifier") {
|
||||||
|
return userID
|
||||||
|
}else {
|
||||||
|
let newUUID = UIDevice.current.identifierForVendor?.uuidString ?? UUID().uuidString
|
||||||
|
//存入UserDefaults
|
||||||
|
UserDefaults.standard.set(newUUID, forKey: "relax.offline.mp3.music.userIdentifier")
|
||||||
|
return newUUID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///报活事件名
|
||||||
|
private func getEventName() -> String {
|
||||||
|
//检索
|
||||||
|
if UserDefaults.standard.string(forKey: "relax.offline.mp3.music.firstEvent") != nil {
|
||||||
|
return "app_open"
|
||||||
|
}else {
|
||||||
|
UserDefaults.standard.set("first_open", forKey: "relax.offline.mp3.music.firstEvent")
|
||||||
|
return "first_open"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//MARK: - 报错操作
|
||||||
|
//上传报错日志
|
||||||
|
func updateErrorLogEventTask(_ level:ErrorLevel, title:String, message:String) {
|
||||||
|
//生成报错链接
|
||||||
|
guard let url = URL(string: baseUrl+errorUrl) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//生成参数
|
||||||
|
let parameters:[String:Any] = [
|
||||||
|
"pkgName":pkgName,
|
||||||
|
"appVersion":app_Version,
|
||||||
|
"os":osVersion,
|
||||||
|
"device":deviceVersion,
|
||||||
|
"Level":level.rawValue,
|
||||||
|
"title":title,
|
||||||
|
"message":message,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
///报活信息结构
|
||||||
|
struct JsonActive:Codable {
|
||||||
|
let message:String?
|
||||||
|
let status:String?
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case message = "message"
|
||||||
|
case status = "status"
|
||||||
|
}
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
message = try values.decodeIfPresent(String.self, forKey: .message)
|
||||||
|
status = try values.decodeIfPresent(String.self, forKey: .status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///报错类型
|
||||||
|
enum ErrorLevel:Int {
|
||||||
|
case debug = 1
|
||||||
|
case info = 2
|
||||||
|
case warn = 3
|
||||||
|
case error = 4
|
||||||
|
case crash = 5
|
||||||
|
}
|
||||||
@ -29,10 +29,21 @@ class MP_NetWorkManager: NSObject {
|
|||||||
//单例工具
|
//单例工具
|
||||||
static let shared = MP_NetWorkManager()
|
static let shared = MP_NetWorkManager()
|
||||||
//MARK: - 网络请求会话
|
//MARK: - 网络请求会话
|
||||||
///会话实例
|
///IP信息加载会话实例
|
||||||
|
private lazy var IPSession:Session = {
|
||||||
|
let configuration = URLSessionConfiguration.af.default
|
||||||
|
configuration.timeoutIntervalForRequest = 8
|
||||||
|
configuration.timeoutIntervalForResource = 8
|
||||||
|
// 可调整网络服务类型
|
||||||
|
configuration.networkServiceType = .default
|
||||||
|
// 可调整缓存策略
|
||||||
|
configuration.requestCachePolicy = .reloadIgnoringLocalCacheData
|
||||||
|
let seesion = Alamofire.Session(configuration: configuration, interceptor: MP_CustomRetrier())
|
||||||
|
return seesion
|
||||||
|
}()
|
||||||
|
///预览资源加载会话实例
|
||||||
private lazy var MPSession:Session = {
|
private lazy var MPSession:Session = {
|
||||||
let configuration = URLSessionConfiguration.af.default
|
let configuration = URLSessionConfiguration.af.default
|
||||||
//最多同时执行4条
|
|
||||||
configuration.timeoutIntervalForRequest = 20
|
configuration.timeoutIntervalForRequest = 20
|
||||||
configuration.timeoutIntervalForResource = 20
|
configuration.timeoutIntervalForResource = 20
|
||||||
// 可调整网络服务类型
|
// 可调整网络服务类型
|
||||||
@ -42,7 +53,7 @@ class MP_NetWorkManager: NSObject {
|
|||||||
let seesion = Alamofire.Session(configuration: configuration, interceptor: MP_CustomRetrier())
|
let seesion = Alamofire.Session(configuration: configuration, interceptor: MP_CustomRetrier())
|
||||||
return seesion
|
return seesion
|
||||||
}()
|
}()
|
||||||
///播放资源会话实例
|
///播放资源加载会话实例
|
||||||
private lazy var PlayerSeesion:Session = {
|
private lazy var PlayerSeesion:Session = {
|
||||||
let configuration = URLSessionConfiguration.af.default
|
let configuration = URLSessionConfiguration.af.default
|
||||||
configuration.timeoutIntervalForRequest = 20
|
configuration.timeoutIntervalForRequest = 20
|
||||||
@ -87,10 +98,13 @@ class MP_NetWorkManager: NSObject {
|
|||||||
// "JP",
|
// "JP",
|
||||||
// "KR"
|
// "KR"
|
||||||
]
|
]
|
||||||
///允许访问的区域Code(对部分内容进行塞选)
|
///允许访问Youtube音乐的地区Code
|
||||||
|
private let ISOs:[String] = ["DZ","LB","AS","LY","AR","LI","AW","LT","AU","LU","AT","MY","AZ","MT","BH","MX","BD","MA","BY","NP","BE","NL","BM","NZ","BO","NI","BA","NG","BR","MK","BG","MP","KH","NO","CA","OM","KY","PK","CL","PA","CO","PG","CR","PY","HR","PE","CY","PH","CZ","PL","DK","PT","DO","PR","EC","QA","EG","RE","SV","RO","EE","FI","SA","FR","SN","GF","RS","PF","SG","GE","SK","DE","SI","GH","ZA","GR","KR","GP","ES","GU","LK","GT","SE","HN","CH","HK","TW","HU","TZ","IS","TH","IN","TN","ID","IQ","TC","IE","VI","IL","UG","IT","UA","JM","AE","JP","GB","JO","US","KZ","UY","KE","VE","KW","VN","LA","YE","LV","ZW"]
|
||||||
|
///允许访问排行榜的区域Code(对部分内容进行塞选)
|
||||||
private let codes:[String] = [
|
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"
|
"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] = []
|
private var trashKeyWords:[String] = []
|
||||||
///设置禁止关键词
|
///设置禁止关键词
|
||||||
@ -273,14 +287,14 @@ extension MP_NetWorkManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private func requestPostIPInfo(_ url:URL, completion:@escaping((Bool) -> Void)) {
|
private func requestPostIPInfo(_ url:URL, completion:@escaping((Bool) -> Void)) {
|
||||||
MPSession.request(url, method: .get, encoding: JSONEncoding.default).responseDecodable(of: JsonIPInfo.self) { [weak self] (response) in
|
IPSession.request(url, method: .get, encoding: JSONEncoding.default).responseDecodable(of: JsonIPInfo.self) { [weak self] (response) in
|
||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
switch response.result {
|
switch response.result {
|
||||||
case .success(let value):
|
case .success(let value):
|
||||||
guard let data = value.data, let code = data.isoCode else {
|
guard let data = value.data, let code = data.isoCode else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if codes.contains(code) {
|
if ISOs.contains(code) {
|
||||||
locaton = code
|
locaton = code
|
||||||
}else {
|
}else {
|
||||||
locaton = "US"
|
locaton = "US"
|
||||||
@ -295,6 +309,8 @@ extension MP_NetWorkManager {
|
|||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
// 请求失败,处理错误
|
// 请求失败,处理错误
|
||||||
handleError(url, error: error)
|
handleError(url, error: error)
|
||||||
|
//请求失败默认为US
|
||||||
|
locaton = "US"
|
||||||
completion(true)
|
completion(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,7 +342,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -415,7 +431,7 @@ extension MP_NetWorkManager {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
//异步执行任务
|
//异步执行任务
|
||||||
var code = locaton ?? ""
|
var code = locaton ?? "US"
|
||||||
if codes.contains(code) == false {
|
if codes.contains(code) == false {
|
||||||
//没有包含在内,默认替换为US美国国家码
|
//没有包含在内,默认替换为US美国国家码
|
||||||
code = "US"
|
code = "US"
|
||||||
@ -433,7 +449,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"formData":[
|
"formData":[
|
||||||
@ -480,7 +496,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"formData":[
|
"formData":[
|
||||||
@ -537,7 +553,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -604,7 +620,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -660,7 +676,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -713,7 +729,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -762,7 +778,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -811,7 +827,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -869,7 +885,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -924,7 +940,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -1042,7 +1058,7 @@ extension MP_NetWorkManager {
|
|||||||
// //语言
|
// //语言
|
||||||
// "hl":Language_first_local,
|
// "hl":Language_first_local,
|
||||||
// //地址
|
// //地址
|
||||||
// "gl":locaton ?? ""
|
// "gl":locaton ?? "US"
|
||||||
// ]
|
// ]
|
||||||
// ],
|
// ],
|
||||||
// "playbackContext": [
|
// "playbackContext": [
|
||||||
@ -1099,7 +1115,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -1146,7 +1162,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -1204,7 +1220,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -1264,7 +1280,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -1326,7 +1342,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -1389,7 +1405,7 @@ extension MP_NetWorkManager {
|
|||||||
//语言
|
//语言
|
||||||
"hl":Language_first_local,
|
"hl":Language_first_local,
|
||||||
//地址
|
//地址
|
||||||
"gl":locaton ?? ""
|
"gl":locaton ?? "US"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
@ -43,16 +43,4 @@ enum LibraryType:Int {
|
|||||||
return placeholderImage
|
return placeholderImage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var icon:UIImage?{
|
|
||||||
switch self {
|
|
||||||
case .love_songs:
|
|
||||||
return UIImage(named: "Center_Songs'logo")
|
|
||||||
case .love_aritists:
|
|
||||||
return UIImage(named: "Center_Artists'logo")
|
|
||||||
case .offline_songs:
|
|
||||||
return UIImage(named: "Center_Offline'logo")
|
|
||||||
case .custom_playlist:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ class MPPositive_TabBarController: UITabBarController, UIViewControllerTransitio
|
|||||||
}
|
}
|
||||||
//是否Push
|
//是否Push
|
||||||
private var isPush:Bool = false
|
private var isPush:Bool = false
|
||||||
|
|
||||||
var pushPlayerBlock:(() -> Void)?
|
var pushPlayerBlock:(() -> Void)?
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
@ -59,6 +60,8 @@ class MPPositive_TabBarController: UITabBarController, UIViewControllerTransitio
|
|||||||
}
|
}
|
||||||
bottomView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(playerClick(_ :))))
|
bottomView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(playerClick(_ :))))
|
||||||
addNotification()
|
addNotification()
|
||||||
|
//触发更新弹窗
|
||||||
|
updateVersionEvent()
|
||||||
}
|
}
|
||||||
//监听通知
|
//监听通知
|
||||||
private func addNotification() {
|
private func addNotification() {
|
||||||
@ -70,6 +73,7 @@ class MPPositive_TabBarController: UITabBarController, UIViewControllerTransitio
|
|||||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(bottomAnimationAction(_:)), notificationName: .player_delete_list)
|
NotificationCenter.notificationKey.add(observer: self, selector: #selector(bottomAnimationAction(_:)), notificationName: .player_delete_list)
|
||||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(pushAction(_ :)), notificationName: .positive_nav_push)
|
NotificationCenter.notificationKey.add(observer: self, selector: #selector(pushAction(_ :)), notificationName: .positive_nav_push)
|
||||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(popAction(_ :)), notificationName: .positive_nav_pop)
|
NotificationCenter.notificationKey.add(observer: self, selector: #selector(popAction(_ :)), notificationName: .positive_nav_pop)
|
||||||
|
NotificationCenter.notificationKey.add(observer: self, selector: #selector(updateVersionEvent), notificationName: .update_reminder)
|
||||||
}
|
}
|
||||||
deinit {
|
deinit {
|
||||||
//移除所有监听
|
//移除所有监听
|
||||||
@ -78,7 +82,19 @@ class MPPositive_TabBarController: UITabBarController, UIViewControllerTransitio
|
|||||||
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
|
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
|
||||||
return MPPositive_PresentationController(presentedViewController: presented, presenting: presenting)
|
return MPPositive_PresentationController(presentedViewController: presented, presenting: presenting)
|
||||||
}
|
}
|
||||||
|
//处理版本更新
|
||||||
|
@objc private func updateVersionEvent() {
|
||||||
|
//判断是否需要更新
|
||||||
|
guard isUpDateReminder == true else {
|
||||||
|
//不需要更新
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//需要更新
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
//触发更新
|
||||||
|
postUpdateReminder(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//MARK: - 通知处理
|
//MARK: - 通知处理
|
||||||
extension MPPositive_TabBarController {
|
extension MPPositive_TabBarController {
|
||||||
|
|||||||
@ -30,11 +30,11 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
|
|||||||
return array
|
return array
|
||||||
}()
|
}()
|
||||||
///收藏单曲Label
|
///收藏单曲Label
|
||||||
private lazy var songsLabel:UILabel = createLabel("0", font: .systemFont(ofSize: 12*width, weight: .light), textColor: .white, textAlignment: .left)
|
private lazy var songsLabel:UILabel = createLabel("0", font: .systemFont(ofSize: 26*width, weight: .bold), textColor: .white, textAlignment: .left)
|
||||||
///收藏歌手Label
|
///收藏歌手Label
|
||||||
private lazy var artistsLabel:UILabel = createLabel("0", font: .systemFont(ofSize: 12*width, weight: .light), textColor: .white, textAlignment: .left)
|
private lazy var artistsLabel:UILabel = createLabel("0", font: .systemFont(ofSize: 26*width, weight: .bold), textColor: .white, textAlignment: .left)
|
||||||
///下载单曲Label
|
///下载单曲Label
|
||||||
private lazy var loadsLabel:UILabel = createLabel("0", font: .systemFont(ofSize: 12*width, weight: .light), textColor: .white, textAlignment: .left)
|
private lazy var loadsLabel:UILabel = createLabel("0", font: .systemFont(ofSize: 26*width, weight: .bold), textColor: .white, textAlignment: .left)
|
||||||
///事件View组
|
///事件View组
|
||||||
private lazy var actionViews:UIView = showTopView()
|
private lazy var actionViews:UIView = showTopView()
|
||||||
///广告View
|
///广告View
|
||||||
@ -114,17 +114,14 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
|
|||||||
guard let self = self else {return}
|
guard let self = self else {return}
|
||||||
|
|
||||||
//封面设置
|
//封面设置
|
||||||
songsLabel.text = "\("Songs".localizableString()) \(MPPositive_LoadCoreModel.shared.songViewModels.count)"
|
songsLabel.text = "\(MPPositive_LoadCoreModel.shared.songViewModels.count)"
|
||||||
let songCover = MPPositive_LoadCoreModel.shared.songViewModels.first?.coverURL
|
coverImageViews[0].image = love_songBGImage
|
||||||
coverImageViews[0].kf.setImage(with: songCover, placeholder: love_songBGImage)
|
|
||||||
|
|
||||||
artistsLabel.text = "\("Artists".localizableString()) \(MPPositive_LoadCoreModel.shared.artistViewModels.count)"
|
artistsLabel.text = "\(MPPositive_LoadCoreModel.shared.artistViewModels.count)"
|
||||||
let artistCover = MPPositive_LoadCoreModel.shared.artistViewModels.first?.coverURL
|
coverImageViews[1].image = love_artistBGImage
|
||||||
coverImageViews[1].kf.setImage(with: artistCover, placeholder: love_artistBGImage)
|
|
||||||
|
|
||||||
loadsLabel.text = "\("Offline".localizableString()) \(MPPositive_LoadCoreModel.shared.loadViewModels.count)"
|
loadsLabel.text = "\(MPPositive_LoadCoreModel.shared.loadViewModels.count)"
|
||||||
let loadCover = MPPositive_LoadCoreModel.shared.loadViewModels.first?.reviewURL
|
coverImageViews[2].image = offline_songBGImage
|
||||||
coverImageViews[2].kf.setImage(with: loadCover, placeholder: offline_songBGImage)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,21 +172,21 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
|
|||||||
let topView = UIView()
|
let topView = UIView()
|
||||||
topView.backgroundColor = .clear
|
topView.backgroundColor = .clear
|
||||||
//添加事件按钮
|
//添加事件按钮
|
||||||
let first = actionView(songsLabel, text: "Center_Songs'logo", tag: 0)
|
let first = actionView(songsLabel, text: "SONG", tag: 0)
|
||||||
topView.addSubview(first)
|
topView.addSubview(first)
|
||||||
first.snp.makeConstraints { make in
|
first.snp.makeConstraints { make in
|
||||||
make.centerY.equalToSuperview()
|
make.centerY.equalToSuperview()
|
||||||
make.height.width.equalTo(109*width)
|
make.height.width.equalTo(109*width)
|
||||||
make.left.equalToSuperview().offset(16*width)
|
make.left.equalToSuperview().offset(16*width)
|
||||||
}
|
}
|
||||||
let second = actionView(artistsLabel, text: "Center_Artists'logo", tag: 1)
|
let second = actionView(artistsLabel, text: "ARTIST", tag: 1)
|
||||||
topView.addSubview(second)
|
topView.addSubview(second)
|
||||||
second.snp.makeConstraints { make in
|
second.snp.makeConstraints { make in
|
||||||
make.centerY.equalToSuperview()
|
make.centerY.equalToSuperview()
|
||||||
make.height.width.equalTo(109*width)
|
make.height.width.equalTo(109*width)
|
||||||
make.centerX.equalToSuperview()
|
make.centerX.equalToSuperview()
|
||||||
}
|
}
|
||||||
let third = actionView(loadsLabel, text: "Center_Offline'logo", tag: 2)
|
let third = actionView(loadsLabel, text: "OFFLINE", tag: 2)
|
||||||
topView.addSubview(third)
|
topView.addSubview(third)
|
||||||
third.snp.makeConstraints { make in
|
third.snp.makeConstraints { make in
|
||||||
make.centerY.equalToSuperview()
|
make.centerY.equalToSuperview()
|
||||||
@ -200,7 +197,7 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
|
|||||||
return topView
|
return topView
|
||||||
}
|
}
|
||||||
//生成一个事件View块
|
//生成一个事件View块
|
||||||
private func actionView(_ label:UILabel, text:String, tag:Int) -> UIView {
|
private func actionView(_ countLabel:UILabel, text:String, tag:Int) -> UIView {
|
||||||
let actionView = UIView()
|
let actionView = UIView()
|
||||||
actionView.backgroundColor = .clear
|
actionView.backgroundColor = .clear
|
||||||
//设置圆角
|
//设置圆角
|
||||||
@ -211,21 +208,18 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
|
|||||||
coverImageViews[tag].snp.makeConstraints { make in
|
coverImageViews[tag].snp.makeConstraints { make in
|
||||||
make.left.top.right.bottom.equalToSuperview()
|
make.left.top.right.bottom.equalToSuperview()
|
||||||
}
|
}
|
||||||
//添加一个iconImage
|
//添加一个主标题
|
||||||
let iconImageView:UIImageView = .init(image: .init(named: text))
|
let titlelLabel = createLabel(text, font: .systemFont(ofSize: 10*width, weight: .semibold), textColor: .white, textAlignment: .left)
|
||||||
iconImageView.contentMode = .scaleAspectFill
|
actionView.addSubview(titlelLabel)
|
||||||
actionView.addSubview(iconImageView)
|
titlelLabel.snp.makeConstraints { make in
|
||||||
iconImageView.snp.makeConstraints { make in
|
make.top.left.equalTo(10*width)
|
||||||
make.width.height.equalTo(20*width)
|
|
||||||
make.left.equalToSuperview().offset(8*width)
|
|
||||||
make.top.equalToSuperview().offset(13*width)
|
|
||||||
}
|
}
|
||||||
//添加一个标题
|
//添加一个数量标题
|
||||||
actionView.addSubview(label)
|
actionView.addSubview(countLabel)
|
||||||
label.snp.makeConstraints { make in
|
countLabel.snp.makeConstraints { make in
|
||||||
make.left.equalTo(iconImageView.snp.left)
|
make.left.equalTo(titlelLabel.snp.left)
|
||||||
make.top.equalToSuperview().offset(40*width)
|
make.top.equalTo(titlelLabel.snp.bottom).offset(8*width)
|
||||||
make.right.equalToSuperview().offset(-8*width)
|
make.right.equalToSuperview().offset(-10*width)
|
||||||
}
|
}
|
||||||
actionView.tag = tag
|
actionView.tag = tag
|
||||||
actionView.isUserInteractionEnabled = true
|
actionView.isUserInteractionEnabled = true
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
import MJRefresh
|
import MJRefresh
|
||||||
import Lottie
|
import Lottie
|
||||||
|
import UserMessagingPlatform
|
||||||
class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewControllerTransitioningDelegate{
|
class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewControllerTransitioningDelegate{
|
||||||
//背景图片
|
//背景图片
|
||||||
private lazy var bgImageView:UIImageView = {
|
private lazy var bgImageView:UIImageView = {
|
||||||
@ -93,8 +94,19 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
|
|||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||||||
// 请求跟踪授权
|
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: nil) { requestConsentError in
|
||||||
requestTrackingAuthorization { idfa in
|
if let consentError = requestConsentError {
|
||||||
|
print("[UMP] GoogleUMP error=\(consentError.localizedDescription)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
print("[UMP] GoogleUMP success")
|
||||||
|
UMPConsentForm.loadAndPresentIfRequired(from: self) { loadAndPresentError in
|
||||||
|
if let consentError = loadAndPresentError {
|
||||||
|
print("[UMP] GoogleUMP error=\(consentError.localizedDescription)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
print("[UMP] GoogleUMP success")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MP_IAPManager.shared.systemRestorePurchases()
|
MP_IAPManager.shared.systemRestorePurchases()
|
||||||
|
|||||||
@ -16,22 +16,17 @@ class MPPositive_HomeLibraryListCollectionViewCell: UICollectionViewCell {
|
|||||||
imageView.layer.cornerRadius = 16*width
|
imageView.layer.cornerRadius = 16*width
|
||||||
return imageView
|
return imageView
|
||||||
}()
|
}()
|
||||||
private lazy var iconImageView:UIImageView = {
|
|
||||||
let iconImageView:UIImageView = .init()
|
|
||||||
iconImageView.contentMode = .scaleAspectFill
|
|
||||||
return iconImageView
|
|
||||||
}()
|
|
||||||
//标题Label
|
//标题Label
|
||||||
private lazy var titleLabel:UILabel = createLabel("Title", font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left)
|
private lazy var titleLabel:UILabel = createLabel("Title", font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left)
|
||||||
var library:MPPositive_LibraryViewModel!{
|
var library:MPPositive_LibraryViewModel!{
|
||||||
didSet{
|
didSet{
|
||||||
|
switch library.library.libraryType {
|
||||||
|
case .custom_playlist:
|
||||||
coverImageView.kf.setImage(with: library.cover, placeholder: library.library.libraryType.image)
|
coverImageView.kf.setImage(with: library.cover, placeholder: library.library.libraryType.image)
|
||||||
titleLabel.text = library.title
|
default:
|
||||||
if let icon = library.library.libraryType.icon {
|
coverImageView.image = library.library.libraryType.image
|
||||||
iconImageView.image = icon
|
|
||||||
}else {
|
|
||||||
iconImageView.image = nil
|
|
||||||
}
|
}
|
||||||
|
titleLabel.text = library.title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
@ -51,12 +46,6 @@ class MPPositive_HomeLibraryListCollectionViewCell: UICollectionViewCell {
|
|||||||
make.left.top.right.equalToSuperview()
|
make.left.top.right.equalToSuperview()
|
||||||
make.height.equalTo(109*width)
|
make.height.equalTo(109*width)
|
||||||
}
|
}
|
||||||
addSubview(iconImageView)
|
|
||||||
iconImageView.snp.makeConstraints { make in
|
|
||||||
make.width.height.equalTo(20*width)
|
|
||||||
make.left.equalToSuperview().offset(8*width)
|
|
||||||
make.top.equalToSuperview().offset(13*width)
|
|
||||||
}
|
|
||||||
addSubview(titleLabel)
|
addSubview(titleLabel)
|
||||||
titleLabel.snp.makeConstraints { make in
|
titleLabel.snp.makeConstraints { make in
|
||||||
make.top.equalTo(coverImageView.snp.bottom).offset(9*width)
|
make.top.equalTo(coverImageView.snp.bottom).offset(9*width)
|
||||||
|
|||||||
@ -87,6 +87,9 @@ class MPSideA_TabBarController: UITabBarController, GADFullScreenContentDelegate
|
|||||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(displayBottomViewAction(_ :)), notificationName: .sideA_display_show)
|
NotificationCenter.notificationKey.add(observer: self, selector: #selector(displayBottomViewAction(_ :)), notificationName: .sideA_display_show)
|
||||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(hiddenBottomViewAction(_ :)), notificationName: .sideA_hidden_show)
|
NotificationCenter.notificationKey.add(observer: self, selector: #selector(hiddenBottomViewAction(_ :)), notificationName: .sideA_hidden_show)
|
||||||
NotificationCenter.notificationKey.add(observer: self, selector: #selector(renameMusicAction(_ :)), notificationName: .sideA_rename_music)
|
NotificationCenter.notificationKey.add(observer: self, selector: #selector(renameMusicAction(_ :)), notificationName: .sideA_rename_music)
|
||||||
|
NotificationCenter.notificationKey.add(observer: self, selector: #selector(updateVersionEvent), notificationName: .update_reminder)
|
||||||
|
//触发更新弹窗
|
||||||
|
updateVersionEvent()
|
||||||
}
|
}
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
@ -118,6 +121,19 @@ class MPSideA_TabBarController: UITabBarController, GADFullScreenContentDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//处理版本更新
|
||||||
|
@objc private func updateVersionEvent() {
|
||||||
|
//判断是否需要更新
|
||||||
|
guard isUpDateReminder == true else {
|
||||||
|
//不需要更新
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//需要更新
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
//触发更新
|
||||||
|
postUpdateReminder(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//MARK: - 事件处理
|
//MARK: - 事件处理
|
||||||
extension MPSideA_TabBarController: UIViewControllerTransitioningDelegate {
|
extension MPSideA_TabBarController: UIViewControllerTransitioningDelegate {
|
||||||
|
|||||||
@ -31,6 +31,10 @@ class MPSideA_AboutViewController: MPSideA_BaseViewController {
|
|||||||
versionLabel.text = "\(NSLocalizedString("Version", comment: "版本号")) \(app_Version)"
|
versionLabel.text = "\(NSLocalizedString("Version", comment: "版本号")) \(app_Version)"
|
||||||
}
|
}
|
||||||
@objc private func versionClick(){
|
@objc private func versionClick(){
|
||||||
|
guard isUpDateReminder == false else {
|
||||||
|
postUpdateReminder(self)
|
||||||
|
return
|
||||||
|
}
|
||||||
let eventAlert = UIAlertController(title: NSLocalizedString("Version Update", comment: ""), message: NSLocalizedString("is the latest Version", comment: ""), preferredStyle: .alert)
|
let eventAlert = UIAlertController(title: NSLocalizedString("Version Update", comment: ""), message: NSLocalizedString("is the latest Version", comment: ""), preferredStyle: .alert)
|
||||||
let canelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel,handler: nil)
|
let canelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel,handler: nil)
|
||||||
eventAlert.addAction(canelAction)
|
eventAlert.addAction(canelAction)
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import UserMessagingPlatform
|
||||||
class MPSideA_HomeViewController: MPSideA_BaseViewController {
|
class MPSideA_HomeViewController: MPSideA_BaseViewController {
|
||||||
@IBOutlet weak var tableView: UITableView!{
|
@IBOutlet weak var tableView: UITableView!{
|
||||||
didSet{
|
didSet{
|
||||||
@ -30,8 +31,19 @@ class MPSideA_HomeViewController: MPSideA_BaseViewController {
|
|||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||||||
// 请求跟踪授权
|
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: nil) { requestConsentError in
|
||||||
requestTrackingAuthorization { idfa in
|
if let consentError = requestConsentError {
|
||||||
|
print("[UMP] GoogleUMP error=\(consentError.localizedDescription)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
print("[UMP] GoogleUMP success")
|
||||||
|
UMPConsentForm.loadAndPresentIfRequired(from: self) { loadAndPresentError in
|
||||||
|
if let consentError = loadAndPresentError {
|
||||||
|
print("[UMP] GoogleUMP error=\(consentError.localizedDescription)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
print("[UMP] GoogleUMP success")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//触发音乐缺失闭包
|
//触发音乐缺失闭包
|
||||||
|
|||||||