jellyflood/Swiftfin/App/PreferenceUIHosting/PreferenceUIHostingSwizzlin...

80 lines
2.2 KiB
Swift

//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2022 Jellyfin & Jellyfin Contributors
//
import SwiftUI
import SwizzleSwift
import UIKit
// MARK: - wrapper view
/// Wrapper view that will apply swizzling to make iOS query the child view for preference settings.
/// Used in combination with PreferenceUIHostingController.
///
/// Source: https://gist.github.com/Amzd/01e1f69ecbc4c82c8586dcd292b1d30d
struct PreferenceUIHostingControllerView<Wrapped: View>: UIViewControllerRepresentable {
init(@ViewBuilder wrappedView: @escaping () -> Wrapped) {
_ = UIViewController.preferenceSwizzling
self.wrappedView = wrappedView
}
var wrappedView: () -> Wrapped
func makeUIViewController(context: Context) -> PreferenceUIHostingController {
PreferenceUIHostingController(wrappedView: wrappedView())
}
func updateUIViewController(_ uiViewController: PreferenceUIHostingController, context: Context) {}
}
// MARK: - swizzling uiviewcontroller extensions
extension UIViewController {
static var preferenceSwizzling: Void = {
Swizzle(UIViewController.self) {
#selector(getter: childForScreenEdgesDeferringSystemGestures) <-> #selector(swizzled_childForScreenEdgesDeferringSystemGestures)
#selector(getter: childForHomeIndicatorAutoHidden) <-> #selector(swizzled_childForHomeIndicatorAutoHidden)
}
}()
}
extension UIViewController {
@objc
func swizzled_childForScreenEdgesDeferringSystemGestures() -> UIViewController? {
if self is PreferenceUIHostingController {
// dont continue searching
return nil
} else {
return search()
}
}
@objc
func swizzled_childForHomeIndicatorAutoHidden() -> UIViewController? {
if self is PreferenceUIHostingController {
// dont continue searching
return nil
} else {
return search()
}
}
private func search() -> PreferenceUIHostingController? {
if let result = children.compactMap({ $0 as? PreferenceUIHostingController }).first {
return result
}
for child in children {
if let result = child.search() {
return result
}
}
return nil
}
}