diff --git a/Sources/EeveeSpotify/Helpers/PopUpHelper.swift b/Sources/EeveeSpotify/Helpers/PopUpHelper.swift index f94175a..361fb84 100644 --- a/Sources/EeveeSpotify/Helpers/PopUpHelper.swift +++ b/Sources/EeveeSpotify/Helpers/PopUpHelper.swift @@ -3,6 +3,8 @@ import Orion import Foundation class PopUpHelper { + + private static var isPopUpShowing = false static let sharedPresenter = type( of: Dynamic.SPTEncorePopUpPresenter @@ -15,6 +17,10 @@ class PopUpHelper { buttonText: String ) { + if isPopUpShowing { + return + } + let model = Dynamic.SPTEncorePopUpDialogModel .alloc(interface: SPTEncorePopUpDialogModel.self) .initWithTitle( @@ -32,8 +38,10 @@ class PopUpHelper { dialog.update(model) dialog.setEventHandler({ sharedPresenter.dismissPopupWithAnimate(true, clearQueue: false, completion: nil) + isPopUpShowing.toggle() }) sharedPresenter.presentPopUp(dialog) + isPopUpShowing.toggle() } } diff --git a/Sources/EeveeSpotify/Helpers/WindowHelper.swift b/Sources/EeveeSpotify/Helpers/WindowHelper.swift new file mode 100644 index 0000000..97b4800 --- /dev/null +++ b/Sources/EeveeSpotify/Helpers/WindowHelper.swift @@ -0,0 +1,26 @@ +import UIKit +import Foundation + +class WindowHelper { + + static let shared = WindowHelper() + + let window: UIWindow + let rootViewController: UIViewController + + private init() { + self.window = UIApplication.shared.windows.first! + self.rootViewController = window.rootViewController! + } + + func viewController(for view: UIView) -> UIViewController? { + var responder: UIResponder? = view + while let nextResponder = responder?.next { + if let viewController = nextResponder as? UIViewController { + return viewController + } + responder = nextResponder + } + return nil + } +} diff --git a/Sources/EeveeSpotify/Models/Extensions/String+Extension.swift b/Sources/EeveeSpotify/Models/Extensions/String+Extension.swift new file mode 100644 index 0000000..b900927 --- /dev/null +++ b/Sources/EeveeSpotify/Models/Extensions/String+Extension.swift @@ -0,0 +1,10 @@ +import Foundation + +extension String { + + static func ~= (lhs: String, rhs: String) -> Bool { + guard let regex = try? NSRegularExpression(pattern: rhs) else { return false } + let range = NSRange(location: 0, length: lhs.utf16.count) + return regex.firstMatch(in: lhs, options: [], range: range) != nil + } +} \ No newline at end of file diff --git a/Sources/EeveeSpotify/ServerSidedReminder.x.swift b/Sources/EeveeSpotify/ServerSidedReminder.x.swift new file mode 100644 index 0000000..e1edf3b --- /dev/null +++ b/Sources/EeveeSpotify/ServerSidedReminder.x.swift @@ -0,0 +1,59 @@ +import Orion +import UIKit + +class StreamQualitySettingsSectionHook: ClassHook { + + static let targetName = "StreamQualitySettingsSection" + + func shouldResetSelection() -> Bool { + + PopUpHelper.showPopUp( + message: "Very high audio quality is server-sided and is not available with this tweak.", + buttonText: "OK" + ) + + return true + } +} + +// + +func showOfflineModePopUp() { + PopUpHelper.showPopUp( + message: "Native playlist downloading is server-sided and is not available with this tweak. You can download podcast episodes though.", + buttonText: "OK" + ) +} + +class FTPDownloadActionHook: ClassHook { + + static let targetName = "ListUXPlatform_FreeTierPlaylistImpl.FTPDownloadAction" + + func execute(_ idk: Any) { + showOfflineModePopUp() + } +} + +class UIButtonHook: ClassHook { + + func setHighlighted(_ highlighted: Bool) { + + if highlighted { + + if let identifier = target.accessibilityIdentifier, identifier.contains("DownloadButton") { + + let vcDescription = String(describing: WindowHelper.shared.viewController(for: target)) + + if !(vcDescription ~= "Podcast|CreativeWorkPlatform") { + + target.removeTarget(nil, action: nil, for: .allEvents) + showOfflineModePopUp() + + return + } + } + } + + orig.setHighlighted(highlighted) + } +} \ No newline at end of file