1.2.0对后台播放调整

This commit is contained in:
QinFendeZhou 2024-09-11 18:21:34 +08:00
parent e4ccb15a73
commit 864f19ca7a
70 changed files with 667 additions and 169 deletions

View File

@ -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 = "";

View File

@ -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>

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -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"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

@ -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"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 873 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

View File

@ -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"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

View File

@ -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"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

View File

@ -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"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

View File

@ -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}

View File

@ -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

View File

@ -10,5 +10,4 @@
///麦克风使用说明 ///麦克风使用说明
"NSMicrophoneUsageDescription" = "يتطلب \"HiMelody\" منك تشغيل الميكروفون الخاص بك للتعرف على وحدات الديسيبل المحيطة وتشغيل الضوضاء البيضاء تلقائيًا نيابةً عنك. هل تريد السماح لهذا التطبيق بالوصول إلى الميكروفون الخاص بك؟"; "NSMicrophoneUsageDescription" = "يتطلب \"HiMelody\" منك تشغيل الميكروفون الخاص بك للتعرف على وحدات الديسيبل المحيطة وتشغيل الضوضاء البيضاء تلقائيًا نيابةً عنك. هل تريد السماح لهذا التطبيق بالوصول إلى الميكروفون الخاص بك؟";
///用户跟踪使用说明 ///用户跟踪使用说明
"NSUserTrackingUsageDescription" = "يحتاج \"HiMelody\" إلى طلب أذونات التتبع لتوفير تجربة إعلانية مخصصة. نحن نحترم ونحمي خصوصيتك ولن نبيع بياناتك لأطراف ثالث "NSUserTrackingUsageDescription" = "يحتاج \"HiMelody\" إلى طلب أذونات التتبع لتوفير تجربة إعلانية مخصصة. نحن نحترم ونحمي خصوصيتك ولن نبيع بياناتك لأطراف ثالث.";
.";

View File

@ -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" = "تم نسخ عنوان البريد الإلكتروني بنجاح إلى الحافظة";

View File

@ -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";

View File

@ -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";

View File

@ -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";

View File

@ -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";

View File

@ -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";

View File

@ -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";

View File

@ -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.";

View File

@ -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)
}

View File

@ -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 {

View File

@ -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)
} }
/// ///

View File

@ -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 couldnt be completed. No space left on device": case "The operation couldnt be completed. No space left on device":

View File

@ -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()
}
}
///IDID
private var userID:String{
get{
return getUserID()
}
}
///IDFA广ID(/0ID)
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 {
//UserdefaultsuserID
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
}

View File

@ -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 ///访YoutubeCode
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"
] ]
] ]
] ]

View File

@ -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
}
}
} }

View File

@ -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 {

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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 {

View File

@ -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)

View File

@ -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")
}
} }
} }
// //