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 */; };
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 */; };
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 */; };
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 */; };
@ -299,6 +300,7 @@
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>"; };
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>"; };
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>"; };
@ -751,10 +753,11 @@
isa = PBXGroup;
children = (
CBAFCA272C0A10500054500E /* MP_NetWorkManager.swift */,
CB108C862C901A5E0017C40F /* MP_LuxServerManager.swift */,
CBAFCA282C0A10500054500E /* MP_PlayerManager.swift */,
CBAFCA202C0A10500054500E /* MP_AVURLAsset.swift */,
CBAFCA1F2C0A10500054500E /* MP_AnalyticsManager.swift */,
CBB6372B2C1C17C300F1DEC9 /* MP_AdMobManager.swift */,
CBAFCA202C0A10500054500E /* MP_AVURLAsset.swift */,
CBAFCA212C0A10500054500E /* MP_CacheManager.swift */,
CBAFCA232C0A10500054500E /* MP_CoreDataHandlerManager.swift */,
CBAFCA242C0A10500054500E /* MP_DownloadManager.swift */,
@ -1287,7 +1290,7 @@
CBC2D6E62BFDF3D700E17703 /* Resources */,
0018BD0A2C1050F60066717C /* ShellScript */,
4F340A16CA4CBC1A386EF0AF /* [CP] Embed Pods Frameworks */,
D1CFD1D7A1F3154E85EE0F93 /* [CP] Copy Pods Resources */,
389B03C2C01E5C783CCE22ED /* [CP] Copy Pods Resources */,
);
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";
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 */ = {
isa = PBXShellScriptBuildPhase;
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";
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 */
/* Begin PBXSourcesBuildPhase section */
@ -1618,6 +1621,7 @@
CBAFCB732C0A10500054500E /* MPPositive_SearchSuggestionItemTableViewCell.swift in Sources */,
CBAFCB432C0A10500054500E /* MPPositive_NavigationController.swift in Sources */,
CBAFCB302C0A10500054500E /* MPPositive_BrowseModuleListViewModel.swift in Sources */,
CB108C872C901A5E0017C40F /* MP_LuxServerManager.swift in Sources */,
CBAFCBA62C0A10500054500E /* MPSideA_Home_SecondListCollectionViewCell.swift in Sources */,
CBAFCB202C0A10500054500E /* MPPositive_JsonSearchSuggestions.swift in Sources */,
CBAFCB232C0A10500054500E /* MPPositive_ArtistHeaderModel.swift in Sources */,
@ -1895,7 +1899,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1.1.9.1;
CURRENT_PROJECT_VERSION = 1.2.0.1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = RAQJ4FNZUH;
@ -1916,7 +1920,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1.9;
MARKETING_VERSION = 1.2.0;
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -1941,7 +1945,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1.1.9.1;
CURRENT_PROJECT_VERSION = 1.2.0.1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = RAQJ4FNZUH;
@ -1962,7 +1966,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1.9;
MARKETING_VERSION = 1.2.0;
PRODUCT_BUNDLE_IDENTIFIER = relax.offline.mp3.music;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

View File

@ -3,18 +3,4 @@
uuid = "B2D42C7E-B789-40F0-8339-B70A223A3889"
type = "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>

View File

@ -14,6 +14,8 @@ import Firebase
import GoogleMobileAds
import FacebookCore
import StoreKit
import UserMessagingPlatform
@_exported import IQKeyboardManagerSwift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
@ -57,8 +59,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
window?.backgroundColor = .init(hex: "#161616")
//faceBook
ApplicationDelegate.shared.application(application,didFinishLaunchingWithOptions: launchOptions)
//
positiceVC = MPPositive_TabBarController()
switch_lunch()
//
MP_AnalyticsManager.shared.user_launchAction()
@ -162,7 +162,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
//A
MPSideA_MediaCenterManager.shared.destroySideA()
MPSideA_VolumeManager.shared.destroySideA()
positiceVC = MPPositive_TabBarController()
//
let transtition = CATransition()
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"
},
{
"filename" : "img_v3_02b6_9dd8ad60-2766-4b89-9959-401f232d926g.png",
"filename" : "img_v3_02ed_b27cf77e-1e80-492f-b990-6592a6be80ag.png",
"idiom" : "universal",
"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",
"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"
},
{
"filename" : "启动页-NEW@2x.png",
"filename" : "20240909-100133.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "启动页-NEW@3x.png",
"filename" : "20240909-100133 1.png",
"idiom" : "universal",
"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"
},
{
"filename" : "蓝色背景@2x.png",
"filename" : "Group_1597880777@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "蓝色背景@3x.png",
"filename" : "Group_1597880777@3x.png",
"idiom" : "universal",
"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"
},
{
"filename" : "橙色背景@2x.png",
"filename" : "001@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "橙色背景@3x.png",
"filename" : "001@3x.png",
"idiom" : "universal",
"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"
},
{
"filename" : "紫色背景@2x.png",
"filename" : "003@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "紫色背景@3x.png",
"filename" : "003@3x.png",
"idiom" : "universal",
"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)?
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
//printCallStack()
//
requestTrackingAuthorization { idfa in
}
}
view.backgroundColor = .init(hex: "#000000")
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 {
MP_IAPManager.shared.startLunchStatus()
MPPositive_BrowseLoadViewModel.shared.getRecentlyData()
MP_LuxServerManager.shared.upDateOpenActiveEventTask()
//
MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in
if open {
@ -169,6 +164,7 @@ class MP_LunchViewController: UIViewController, GADFullScreenContentDelegate {
[weak self] in
guard let self = self else {return}
MP_IAPManager.shared.startLunchStatus()
MP_LuxServerManager.shared.upDateOpenActiveEventTask()
//
MP_AnalyticsManager.shared.getOpenStatus { [weak self] open in
guard let self = self else {return}

View File

@ -33,6 +33,8 @@ extension NotificationCenter{
struct notificationKey:NotificationKey {
///
enum Keys:String {
///
case update_reminder
///taBarItem
case switch_tabBarItem
//MARK: - A

View File

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

View File

@ -134,6 +134,14 @@
"Because you listen" = "لأنك سمعت";
///因为你喜欢
"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文本
///已成功将电子邮件地址复制到剪贴板
"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 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文本
///已成功将电子邮件地址复制到剪贴板
"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 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文本
///已成功将电子邮件地址复制到剪贴板
"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 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文本
///已成功将电子邮件地址复制到剪贴板
"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 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文本
///已成功将电子邮件地址复制到剪贴板
"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 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文本
///已成功将电子邮件地址复制到剪贴板
"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 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文本
///已成功将电子邮件地址复制到剪贴板
"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 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文本
///已成功将电子邮件地址复制到剪贴板
"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 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")!
///
@ -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]
///-绿
let greenTextColor:UIColor = .init(hex: "#80F988", alpha: 1.0)
///
var isUpDateReminder:Bool = false{
willSet{
if newValue == true {
//
NotificationCenter.notificationKey.post(notificationName: .update_reminder)
}
}
}
//MARK: -
//
@ -504,3 +513,25 @@ func printCallStack() {
let callStack = Thread.callStackSymbols
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 ?? "")
}
}
// ///
// 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 {
///URL
@ -309,7 +295,6 @@ class MP_PlayerToolConfig:NSObject {
return components.url
}
}
class MP_PlayerTaskManager:NSObject, URLSessionDataDelegate{
static var shared = MP_PlayerTaskManager()
///
@ -340,6 +325,23 @@ class MP_PlayerTaskManager:NSObject, URLSessionDataDelegate{
var titles:[String:String]!
//
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
override init() {
@ -350,6 +352,8 @@ class MP_PlayerTaskManager:NSObject, URLSessionDataDelegate{
configuration.timeoutIntervalForRequest = 30
configuration.timeoutIntervalForResource = 30
configuration.allowsCellularAccess = true
configuration.sessionSendsLaunchEvents = true
configuration.isDiscretionary = false
//
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) {
accessQueue.async {

View File

@ -99,6 +99,12 @@ class MP_AnalyticsManager: NSObject {
private let VIP_buy_success = "VIP_buy_success"
///
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() {
//
if UserDefaults.standard.bool(forKey: "UserStatus") {
@ -184,7 +190,37 @@ class MP_AnalyticsManager: NSObject {
//
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 value = js["versionCode"] as! String
if value == app_Version {
@ -499,6 +535,18 @@ class MP_AnalyticsManager: NSObject {
Analytics.logEvent(VIP_buy_failure, parameters: ["productID":productID,
"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: - 广
//
private let cold_ads_chance:String = "cold_ads_chance"
@ -643,7 +691,6 @@ class MP_AnalyticsManager: NSObject {
///
func cold_ads_closeAction() {
let parameters:[String:String] = ["CS_STATUS":isOLD ? "Old":"New"]
print("冷启动失败展示信息--\(parameters)")
Analytics.logEvent(cold_ads_close, parameters: parameters)
}
///

View File

@ -158,7 +158,9 @@ class MP_DownloadManager: NSObject {
self.downloadTasks?[nextVideoId]?.status = .downloading
}
//videoId
loadQueue.async {
self.progressStorage?[nextVideoId] = task.progress.fractionCompleted
}
//
NotificationCenter.notificationKey.post(notificationName: .download_progress_source, object: ["videoId":nextVideoId])
}
@ -191,7 +193,9 @@ class MP_DownloadManager: NSObject {
self.downloadTasks?[nextVideoId]?.status = .failed
}
downloadURLs?[nextVideoId] = nil
progressStorage?[nextVideoId] = nil
loadQueue.async {
self.progressStorage?[nextVideoId] = nil
}
songHandlers?[nextVideoId] = nil
MP_HUD.text("An error occurred while downloading. Please download again.".localizableString(), delay: 1.5, completion: nil)
session.cancel(task) { _ in
@ -214,7 +218,9 @@ class MP_DownloadManager: NSObject {
}
self.downloadURLs?[nextVideoId] = nil
self.downloadTasks?[nextVideoId] = nil
loadQueue.async {
self.progressStorage?[nextVideoId] = nil
}
self.songHandlers?[nextVideoId] = 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
}
downloadURLs?[nextVideoId] = nil
progressStorage?[nextVideoId] = nil
loadQueue.async {
self.progressStorage?[nextVideoId] = nil
}
songHandlers?[nextVideoId] = nil
switch error.localizedDescription {
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()
//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 = {
let configuration = URLSessionConfiguration.af.default
//4
configuration.timeoutIntervalForRequest = 20
configuration.timeoutIntervalForResource = 20
//
@ -42,7 +53,7 @@ class MP_NetWorkManager: NSObject {
let seesion = Alamofire.Session(configuration: configuration, interceptor: MP_CustomRetrier())
return seesion
}()
///
///
private lazy var PlayerSeesion:Session = {
let configuration = URLSessionConfiguration.af.default
configuration.timeoutIntervalForRequest = 20
@ -87,10 +98,13 @@ class MP_NetWorkManager: NSObject {
// "JP",
// "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] = [
"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] = []
///
@ -273,14 +287,14 @@ extension MP_NetWorkManager {
}
}
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}
switch response.result {
case .success(let value):
guard let data = value.data, let code = data.isoCode else {
return
}
if codes.contains(code) {
if ISOs.contains(code) {
locaton = code
}else {
locaton = "US"
@ -295,6 +309,8 @@ extension MP_NetWorkManager {
case .failure(let error):
//
handleError(url, error: error)
//US
locaton = "US"
completion(true)
}
}
@ -326,7 +342,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -415,7 +431,7 @@ extension MP_NetWorkManager {
return
}
//
var code = locaton ?? ""
var code = locaton ?? "US"
if codes.contains(code) == false {
//US
code = "US"
@ -433,7 +449,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
],
"formData":[
@ -480,7 +496,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
],
"formData":[
@ -537,7 +553,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -604,7 +620,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -660,7 +676,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -713,7 +729,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -762,7 +778,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -811,7 +827,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -869,7 +885,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -924,7 +940,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -1042,7 +1058,7 @@ extension MP_NetWorkManager {
// //
// "hl":Language_first_local,
// //
// "gl":locaton ?? ""
// "gl":locaton ?? "US"
// ]
// ],
// "playbackContext": [
@ -1099,7 +1115,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -1146,7 +1162,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -1204,7 +1220,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -1264,7 +1280,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -1326,7 +1342,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]
@ -1389,7 +1405,7 @@ extension MP_NetWorkManager {
//
"hl":Language_first_local,
//
"gl":locaton ?? ""
"gl":locaton ?? "US"
]
]
]

View File

@ -43,16 +43,4 @@ enum LibraryType:Int {
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
private var isPush:Bool = false
var pushPlayerBlock:(() -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
@ -59,6 +60,8 @@ class MPPositive_TabBarController: UITabBarController, UIViewControllerTransitio
}
bottomView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(playerClick(_ :))))
addNotification()
//
updateVersionEvent()
}
//
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(pushAction(_ :)), notificationName: .positive_nav_push)
NotificationCenter.notificationKey.add(observer: self, selector: #selector(popAction(_ :)), notificationName: .positive_nav_pop)
NotificationCenter.notificationKey.add(observer: self, selector: #selector(updateVersionEvent), notificationName: .update_reminder)
}
deinit {
//
@ -78,7 +82,19 @@ class MPPositive_TabBarController: UITabBarController, UIViewControllerTransitio
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return MPPositive_PresentationController(presentedViewController: presented, presenting: presenting)
}
//
@objc private func updateVersionEvent() {
//
guard isUpDateReminder == true else {
//
return
}
//
DispatchQueue.main.async {
//
postUpdateReminder(self)
}
}
}
//MARK: -
extension MPPositive_TabBarController {

View File

@ -30,11 +30,11 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
return array
}()
///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
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
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
private lazy var actionViews:UIView = showTopView()
///广View
@ -114,17 +114,14 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
guard let self = self else {return}
//
songsLabel.text = "\("Songs".localizableString()) \(MPPositive_LoadCoreModel.shared.songViewModels.count)"
let songCover = MPPositive_LoadCoreModel.shared.songViewModels.first?.coverURL
coverImageViews[0].kf.setImage(with: songCover, placeholder: love_songBGImage)
songsLabel.text = "\(MPPositive_LoadCoreModel.shared.songViewModels.count)"
coverImageViews[0].image = love_songBGImage
artistsLabel.text = "\("Artists".localizableString()) \(MPPositive_LoadCoreModel.shared.artistViewModels.count)"
let artistCover = MPPositive_LoadCoreModel.shared.artistViewModels.first?.coverURL
coverImageViews[1].kf.setImage(with: artistCover, placeholder: love_artistBGImage)
artistsLabel.text = "\(MPPositive_LoadCoreModel.shared.artistViewModels.count)"
coverImageViews[1].image = love_artistBGImage
loadsLabel.text = "\("Offline".localizableString()) \(MPPositive_LoadCoreModel.shared.loadViewModels.count)"
let loadCover = MPPositive_LoadCoreModel.shared.loadViewModels.first?.reviewURL
coverImageViews[2].kf.setImage(with: loadCover, placeholder: offline_songBGImage)
loadsLabel.text = "\(MPPositive_LoadCoreModel.shared.loadViewModels.count)"
coverImageViews[2].image = offline_songBGImage
}
}
@ -175,21 +172,21 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
let topView = UIView()
topView.backgroundColor = .clear
//
let first = actionView(songsLabel, text: "Center_Songs'logo", tag: 0)
let first = actionView(songsLabel, text: "SONG", tag: 0)
topView.addSubview(first)
first.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.height.width.equalTo(109*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)
second.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.height.width.equalTo(109*width)
make.centerX.equalToSuperview()
}
let third = actionView(loadsLabel, text: "Center_Offline'logo", tag: 2)
let third = actionView(loadsLabel, text: "OFFLINE", tag: 2)
topView.addSubview(third)
third.snp.makeConstraints { make in
make.centerY.equalToSuperview()
@ -200,7 +197,7 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
return topView
}
//View
private func actionView(_ label:UILabel, text:String, tag:Int) -> UIView {
private func actionView(_ countLabel:UILabel, text:String, tag:Int) -> UIView {
let actionView = UIView()
actionView.backgroundColor = .clear
//
@ -211,21 +208,18 @@ class MPPositive_LibraryViewController: MPPositive_BaseViewController, UIViewCon
coverImageViews[tag].snp.makeConstraints { make in
make.left.top.right.bottom.equalToSuperview()
}
//iconImage
let iconImageView:UIImageView = .init(image: .init(named: text))
iconImageView.contentMode = .scaleAspectFill
actionView.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)
//
let titlelLabel = createLabel(text, font: .systemFont(ofSize: 10*width, weight: .semibold), textColor: .white, textAlignment: .left)
actionView.addSubview(titlelLabel)
titlelLabel.snp.makeConstraints { make in
make.top.left.equalTo(10*width)
}
//
actionView.addSubview(label)
label.snp.makeConstraints { make in
make.left.equalTo(iconImageView.snp.left)
make.top.equalToSuperview().offset(40*width)
make.right.equalToSuperview().offset(-8*width)
//
actionView.addSubview(countLabel)
countLabel.snp.makeConstraints { make in
make.left.equalTo(titlelLabel.snp.left)
make.top.equalTo(titlelLabel.snp.bottom).offset(8*width)
make.right.equalToSuperview().offset(-10*width)
}
actionView.tag = tag
actionView.isUserInteractionEnabled = true

View File

@ -8,6 +8,7 @@
import UIKit
import MJRefresh
import Lottie
import UserMessagingPlatform
class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewControllerTransitioningDelegate{
//
private lazy var bgImageView:UIImageView = {
@ -93,8 +94,19 @@ class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewContro
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
//
requestTrackingAuthorization { idfa in
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: nil) { requestConsentError 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()

View File

@ -16,22 +16,17 @@ class MPPositive_HomeLibraryListCollectionViewCell: UICollectionViewCell {
imageView.layer.cornerRadius = 16*width
return imageView
}()
private lazy var iconImageView:UIImageView = {
let iconImageView:UIImageView = .init()
iconImageView.contentMode = .scaleAspectFill
return iconImageView
}()
//Label
private lazy var titleLabel:UILabel = createLabel("Title", font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .white, textAlignment: .left)
var library:MPPositive_LibraryViewModel!{
didSet{
switch library.library.libraryType {
case .custom_playlist:
coverImageView.kf.setImage(with: library.cover, placeholder: library.library.libraryType.image)
titleLabel.text = library.title
if let icon = library.library.libraryType.icon {
iconImageView.image = icon
}else {
iconImageView.image = nil
default:
coverImageView.image = library.library.libraryType.image
}
titleLabel.text = library.title
}
}
override init(frame: CGRect) {
@ -51,12 +46,6 @@ class MPPositive_HomeLibraryListCollectionViewCell: UICollectionViewCell {
make.left.top.right.equalToSuperview()
make.height.equalTo(109*width)
}
addSubview(iconImageView)
iconImageView.snp.makeConstraints { make in
make.width.height.equalTo(20*width)
make.left.equalToSuperview().offset(8*width)
make.top.equalToSuperview().offset(13*width)
}
addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.top.equalTo(coverImageView.snp.bottom).offset(9*width)

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(hiddenBottomViewAction(_ :)), notificationName: .sideA_hidden_show)
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) {
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: -
extension MPSideA_TabBarController: UIViewControllerTransitioningDelegate {

View File

@ -31,6 +31,10 @@ class MPSideA_AboutViewController: MPSideA_BaseViewController {
versionLabel.text = "\(NSLocalizedString("Version", comment: "版本号")) \(app_Version)"
}
@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 canelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel,handler: nil)
eventAlert.addAction(canelAction)

View File

@ -6,6 +6,7 @@
//
import UIKit
import UserMessagingPlatform
class MPSideA_HomeViewController: MPSideA_BaseViewController {
@IBOutlet weak var tableView: UITableView!{
didSet{
@ -30,8 +31,19 @@ class MPSideA_HomeViewController: MPSideA_BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
//
requestTrackingAuthorization { idfa in
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: nil) { requestConsentError 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")
}
}
}
//