Refactors internal Inspect code
This commit is contained in:
parent
56f08c54e0
commit
8befb327b0
|
@ -1,178 +0,0 @@
|
|||
import SwiftUI
|
||||
import SwiftBackports
|
||||
|
||||
#if os(iOS) || os(macOS)
|
||||
internal extension PlatformView {
|
||||
func ancestor<ViewType: PlatformView>(ofType type: ViewType.Type) -> ViewType? {
|
||||
var view = superview
|
||||
|
||||
while let s = view {
|
||||
if let typed = s as? ViewType {
|
||||
return typed
|
||||
}
|
||||
view = s.superview
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var host: PlatformView? {
|
||||
var view = superview
|
||||
|
||||
while let s = view {
|
||||
if NSStringFromClass(type(of: s)).contains("ViewHost") {
|
||||
return s
|
||||
}
|
||||
view = s.superview
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sibling<ViewType: PlatformView>(ofType type: ViewType.Type) -> ViewType? {
|
||||
guard let superview = superview, let index = superview.subviews.firstIndex(of: self) else { return nil }
|
||||
|
||||
var views = superview.subviews
|
||||
views.remove(at: index)
|
||||
|
||||
for subview in views.reversed() {
|
||||
if let typed = subview as? ViewType {
|
||||
return typed
|
||||
} else if let typed = subview.descendent(ofType: type) {
|
||||
return typed
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func descendent<ViewType: PlatformView>(ofType type: ViewType.Type) -> ViewType? {
|
||||
for subview in subviews {
|
||||
if let typed = subview as? ViewType {
|
||||
return typed
|
||||
} else if let typed = subview.descendent(ofType: type) {
|
||||
return typed
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
internal struct Inspector {
|
||||
var hostView: PlatformView
|
||||
var sourceView: PlatformView
|
||||
var sourceController: PlatformViewController
|
||||
|
||||
func `any`<ViewType: PlatformView>(ofType: ViewType.Type) -> ViewType? {
|
||||
ancestor(ofType: ViewType.self)
|
||||
?? sibling(ofType: ViewType.self)
|
||||
?? descendent(ofType: ViewType.self)
|
||||
}
|
||||
|
||||
func ancestor<ViewType: PlatformView>(ofType: ViewType.Type) -> ViewType? {
|
||||
hostView.ancestor(ofType: ViewType.self)
|
||||
}
|
||||
|
||||
func sibling<ViewType: PlatformView>(ofType: ViewType.Type) -> ViewType? {
|
||||
hostView.sibling(ofType: ViewType.self)
|
||||
}
|
||||
|
||||
func descendent<ViewType: PlatformView>(ofType: ViewType.Type) -> ViewType? {
|
||||
hostView.descendent(ofType: ViewType.self)
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
private func inject<Wrapped>(_ wrapped: Wrapped) -> some View where Wrapped: View {
|
||||
overlay(wrapped.frame(width: 0, height: 0))
|
||||
}
|
||||
|
||||
func inspect<ViewType: PlatformView>(selector: @escaping (_ inspector: Inspector) -> ViewType?, customize: @escaping (ViewType) -> Void) -> some View {
|
||||
inject(InspectionView(selector: selector, customize: customize))
|
||||
}
|
||||
|
||||
func controller(_ customize: @escaping (PlatformViewController?) -> Void) -> some View {
|
||||
inspect { inspector in
|
||||
inspector.sourceController.view
|
||||
} customize: { view in
|
||||
customize(view.parentController)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct InspectionView<ViewType: PlatformView>: View {
|
||||
let selector: (Inspector) -> ViewType?
|
||||
let customize: (ViewType) -> Void
|
||||
|
||||
var body: some View {
|
||||
Representable(parent: self)
|
||||
}
|
||||
}
|
||||
|
||||
private class SourceView: PlatformView {
|
||||
required init() {
|
||||
super.init(frame: .zero)
|
||||
isHidden = true
|
||||
#if os(iOS)
|
||||
isUserInteractionEnabled = false
|
||||
#endif
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if os(iOS)
|
||||
private extension InspectionView {
|
||||
struct Representable: UIViewRepresentable {
|
||||
let parent: InspectionView
|
||||
|
||||
func makeUIView(context: Context) -> UIView { .init() }
|
||||
func updateUIView(_ view: UIView, context: Context) {
|
||||
DispatchQueue.main.async {
|
||||
guard let host = view.host else { return }
|
||||
|
||||
let inspector = Inspector(
|
||||
hostView: host,
|
||||
sourceView: view,
|
||||
sourceController: view.parentController
|
||||
?? view.window?.rootViewController
|
||||
?? UIViewController()
|
||||
)
|
||||
|
||||
guard let targetView = parent.selector(inspector) else { return }
|
||||
parent.customize(targetView)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#elseif os(macOS)
|
||||
private extension InspectionView {
|
||||
struct Representable: NSViewRepresentable {
|
||||
let parent: InspectionView
|
||||
|
||||
func makeNSView(context: Context) -> NSView {
|
||||
.init(frame: .zero)
|
||||
}
|
||||
|
||||
func updateNSView(_ view: NSView, context: Context) {
|
||||
DispatchQueue.main.async {
|
||||
guard let host = view.host else { return }
|
||||
|
||||
let inspector = Inspector(
|
||||
hostView: host,
|
||||
sourceView: view,
|
||||
sourceController: view.parentController ?? NSViewController(nibName: nil, bundle: nil)
|
||||
)
|
||||
|
||||
guard let targetView = parent.selector(inspector) else { return }
|
||||
parent.customize(targetView)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,292 @@
|
|||
import SwiftUI
|
||||
import SwiftBackports
|
||||
|
||||
#if os(iOS) || os(macOS)
|
||||
|
||||
internal extension PlatformViewController {
|
||||
func ancestor<ControllerType: PlatformViewController>(ofType type: ControllerType.Type) -> ControllerType? {
|
||||
var controller = parent
|
||||
while let c = controller {
|
||||
if let typed = c as? ControllerType {
|
||||
return typed
|
||||
}
|
||||
controller = c.parent
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sibling<ControllerType: PlatformViewController>(ofType type: ControllerType.Type) -> ControllerType? {
|
||||
guard let controller = parent, let index = controller.children.firstIndex(of: self) else { return nil }
|
||||
|
||||
var children = controller.children
|
||||
children.remove(at: index)
|
||||
|
||||
for c in children.reversed() {
|
||||
if let typed = c as? ControllerType {
|
||||
return typed
|
||||
} else if let typed = c.descendent(ofType: type) {
|
||||
return typed
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func descendent<ControllerType: PlatformViewController>(ofType type: ControllerType.Type) -> ControllerType? {
|
||||
for c in children {
|
||||
if let typed = c as? ControllerType {
|
||||
return typed
|
||||
} else if let typed = c.descendent(ofType: type) {
|
||||
return typed
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
internal extension PlatformView {
|
||||
func ancestor<ViewType: PlatformView>(ofType type: ViewType.Type) -> ViewType? {
|
||||
var view = superview
|
||||
while let s = view {
|
||||
if let typed = s as? ViewType {
|
||||
return typed
|
||||
}
|
||||
view = s.superview
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sibling<ViewType: PlatformView>(ofType type: ViewType.Type) -> ViewType? {
|
||||
guard let superview = superview, let index = superview.subviews.firstIndex(of: self) else { return nil }
|
||||
|
||||
var views = superview.subviews
|
||||
views.remove(at: index)
|
||||
|
||||
for subview in views.reversed() {
|
||||
if let typed = subview as? ViewType {
|
||||
return typed
|
||||
} else if let typed = subview.descendent(ofType: type) {
|
||||
return typed
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func descendent<ViewType: PlatformView>(ofType type: ViewType.Type) -> ViewType? {
|
||||
for subview in subviews {
|
||||
if let typed = subview as? ViewType {
|
||||
return typed
|
||||
} else if let typed = subview.descendent(ofType: type) {
|
||||
return typed
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var host: PlatformView? {
|
||||
var view = superview
|
||||
while let s = view {
|
||||
if NSStringFromClass(type(of: s)).contains("ViewHost") {
|
||||
return s
|
||||
}
|
||||
view = s.superview
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
internal struct Inspector {
|
||||
var hostView: PlatformView
|
||||
var sourceView: PlatformView
|
||||
var sourceController: PlatformViewController
|
||||
|
||||
func `any`<ViewType: PlatformView>(ofType: ViewType.Type) -> ViewType? {
|
||||
ancestor(ofType: ViewType.self)
|
||||
?? sibling(ofType: ViewType.self)
|
||||
?? descendent(ofType: ViewType.self)
|
||||
}
|
||||
|
||||
func ancestor<ViewType: PlatformView>(ofType: ViewType.Type) -> ViewType? {
|
||||
hostView.ancestor(ofType: ViewType.self)
|
||||
}
|
||||
|
||||
func sibling<ViewType: PlatformView>(ofType: ViewType.Type) -> ViewType? {
|
||||
hostView.sibling(ofType: ViewType.self)
|
||||
}
|
||||
|
||||
func descendent<ViewType: PlatformView>(ofType: ViewType.Type) -> ViewType? {
|
||||
hostView.descendent(ofType: ViewType.self)
|
||||
}
|
||||
|
||||
func `any`<ControllerType: PlatformViewController>(ofType: ControllerType.Type) -> ControllerType? {
|
||||
ancestor(ofType: ControllerType.self)
|
||||
?? sibling(ofType: ControllerType.self)
|
||||
?? descendent(ofType: ControllerType.self)
|
||||
}
|
||||
|
||||
func ancestor<ControllerType: PlatformViewController>(ofType: ControllerType.Type) -> ControllerType? {
|
||||
sourceController.ancestor(ofType: ControllerType.self)
|
||||
}
|
||||
|
||||
func sibling<ControllerType: PlatformViewController>(ofType: ControllerType.Type) -> ControllerType? {
|
||||
sourceController.sibling(ofType: ControllerType.self)
|
||||
}
|
||||
|
||||
func descendent<ControllerType: PlatformViewController>(ofType: ControllerType.Type) -> ControllerType? {
|
||||
sourceController.descendent(ofType: ControllerType.self)
|
||||
}
|
||||
}
|
||||
|
||||
internal struct Proxy<T> {
|
||||
let inspector: Inspector
|
||||
let instance: T
|
||||
}
|
||||
|
||||
extension View {
|
||||
private func inject<Wrapped>(_ wrapped: Wrapped) -> some View where Wrapped: View {
|
||||
overlay(wrapped.frame(width: 0, height: 0))
|
||||
}
|
||||
|
||||
func `any`<T: PlatformView>(forType type: T.Type, body: @escaping (Proxy<T>) -> Void) -> some View {
|
||||
inject(InspectionView { inspector in
|
||||
inspector.any(ofType: T.self)
|
||||
} customize: { proxy in
|
||||
body(proxy)
|
||||
})
|
||||
}
|
||||
|
||||
func ancestor<T: PlatformView>(forType type: T.Type, body: @escaping (Proxy<T>) -> Void) -> some View {
|
||||
inject(InspectionView { inspector in
|
||||
inspector.ancestor(ofType: T.self)
|
||||
} customize: { proxy in
|
||||
body(proxy)
|
||||
})
|
||||
}
|
||||
|
||||
func sibling<T: PlatformView>(forType type: T.Type, body: @escaping (Proxy<T>) -> Void) -> some View {
|
||||
inject(InspectionView { inspector in
|
||||
inspector.sibling(ofType: T.self)
|
||||
} customize: { proxy in
|
||||
body(proxy)
|
||||
})
|
||||
}
|
||||
|
||||
func descendent<T: PlatformView>(forType type: T.Type, body: @escaping (Proxy<T>) -> Void) -> some View {
|
||||
inject(InspectionView { inspector in
|
||||
inspector.descendent(ofType: T.self)
|
||||
} customize: { proxy in
|
||||
body(proxy)
|
||||
})
|
||||
}
|
||||
|
||||
func `any`<T: PlatformViewController>(forType type: T.Type, body: @escaping (Proxy<T>) -> Void) -> some View {
|
||||
inject(InspectionView { inspector in
|
||||
inspector.any(ofType: T.self)
|
||||
} customize: { proxy in
|
||||
body(proxy)
|
||||
})
|
||||
}
|
||||
|
||||
func ancestor<T: PlatformViewController>(forType type: T.Type, body: @escaping (Proxy<T>) -> Void) -> some View {
|
||||
inject(InspectionView { inspector in
|
||||
inspector.ancestor(ofType: T.self)
|
||||
} customize: { proxy in
|
||||
body(proxy)
|
||||
})
|
||||
}
|
||||
|
||||
func sibling<T: PlatformViewController>(forType type: T.Type, body: @escaping (Proxy<T>) -> Void) -> some View {
|
||||
inject(InspectionView { inspector in
|
||||
inspector.sibling(ofType: T.self)
|
||||
} customize: { proxy in
|
||||
body(proxy)
|
||||
})
|
||||
}
|
||||
|
||||
func descendent<T: PlatformViewController>(forType type: T.Type, body: @escaping (Proxy<T>) -> Void) -> some View {
|
||||
inject(InspectionView { inspector in
|
||||
inspector.descendent(ofType: T.self)
|
||||
} customize: { proxy in
|
||||
body(proxy)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private struct InspectionView<T>: View {
|
||||
let selector: (Inspector) -> T?
|
||||
let customize: (Proxy<T>) -> Void
|
||||
|
||||
var body: some View {
|
||||
Representable(parent: self)
|
||||
}
|
||||
}
|
||||
|
||||
private class SourceView: PlatformView {
|
||||
required init() {
|
||||
super.init(frame: .zero)
|
||||
isHidden = true
|
||||
#if os(iOS)
|
||||
isUserInteractionEnabled = false
|
||||
#endif
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if os(iOS)
|
||||
private extension InspectionView {
|
||||
struct Representable: UIViewRepresentable {
|
||||
let parent: InspectionView
|
||||
|
||||
func makeUIView(context: Context) -> UIView { .init() }
|
||||
func updateUIView(_ view: UIView, context: Context) {
|
||||
DispatchQueue.main.async {
|
||||
guard let host = view.host else { return }
|
||||
|
||||
let inspector = Inspector(
|
||||
hostView: host,
|
||||
sourceView: view,
|
||||
sourceController: view.parentController
|
||||
?? view.window?.rootViewController
|
||||
?? UIViewController()
|
||||
)
|
||||
|
||||
guard let target = parent.selector(inspector) else { return }
|
||||
parent.customize(.init(inspector: inspector, instance: target))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#elseif os(macOS)
|
||||
private extension InspectionView {
|
||||
struct Representable: NSViewRepresentable {
|
||||
let parent: InspectionView
|
||||
|
||||
func makeNSView(context: Context) -> NSView {
|
||||
.init(frame: .zero)
|
||||
}
|
||||
|
||||
func updateNSView(_ view: NSView, context: Context) {
|
||||
DispatchQueue.main.async {
|
||||
guard let host = view.host else { return }
|
||||
|
||||
let inspector = Inspector(
|
||||
hostView: host,
|
||||
sourceView: view,
|
||||
sourceController: view.parentController ?? NSViewController(nibName: nil, bundle: nil)
|
||||
)
|
||||
|
||||
guard let target = parent.selector(inspector) else { return }
|
||||
parent.customize(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -21,9 +21,7 @@ extension Backport where Wrapped == Any {
|
|||
} else {
|
||||
TitleAndIconLabelStyle().makeBody(configuration: configuration)
|
||||
#if os(iOS)
|
||||
.inspect { inspector in
|
||||
inspector.ancestor(ofType: UINavigationBar.self)
|
||||
} customize: { _ in
|
||||
.ancestor(forType: UINavigationBar.self) { _ in
|
||||
isToolbarElement = true
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,9 +28,8 @@ extension Backport where Wrapped: View {
|
|||
#if os(iOS)
|
||||
wrapped
|
||||
.environment(\.backportRefresh, Backport<Any>.RefreshAction(action))
|
||||
.inspect { inspector in
|
||||
inspector.sibling(ofType: UIScrollView.self)
|
||||
} customize: { scrollView in
|
||||
.any(forType: UIScrollView.self) { proxy in
|
||||
let scrollView = proxy.instance
|
||||
guard scrollView.refreshControl == nil else { return }
|
||||
scrollView.refreshControl = RefreshControl {
|
||||
await action()
|
||||
|
|
|
@ -122,18 +122,19 @@ struct ToolbarModifier: ViewModifier {
|
|||
func body(content: Content) -> some View {
|
||||
content
|
||||
.navigationBarItems(leading: leading, trailing: trailing)
|
||||
.controller { controller in
|
||||
.ancestor(forType: UIViewController.self) { proxy in
|
||||
let controller = proxy.instance
|
||||
if !principalItems.isEmpty {
|
||||
controller?.navigationItem.titleView = UIHostingController(
|
||||
controller.navigationItem.titleView = UIHostingController(
|
||||
rootView: principal.backport.largeScale(),
|
||||
ignoreSafeArea: false
|
||||
).view
|
||||
controller?.navigationItem.titleView?.backgroundColor = .clear
|
||||
controller.navigationItem.titleView?.backgroundColor = .clear
|
||||
}
|
||||
|
||||
if !bottomBarItems.isEmpty {
|
||||
controller?.navigationController?.setToolbarHidden(false, animated: false)
|
||||
controller?.toolbarItems = bottomBarItems.map {
|
||||
controller.navigationController?.setToolbarHidden(false, animated: false)
|
||||
controller.toolbarItems = bottomBarItems.map {
|
||||
let view = UIHostingController(rootView: $0.content.backport.largeScale()).view!
|
||||
view.backgroundColor = .clear
|
||||
return .init(customView: view)
|
||||
|
|
|
@ -11,8 +11,8 @@ internal struct ToolbarBackgroundModifier: ViewModifier {
|
|||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.controller { controller in
|
||||
wrapper.controller = controller
|
||||
.ancestor(forType: UIViewController.self) { proxy in
|
||||
wrapper.controller = proxy.instance
|
||||
}
|
||||
.backport.task {
|
||||
updateNavigationBar()
|
||||
|
|
|
@ -94,15 +94,11 @@ private struct AutoCapitalizationModifier: ViewModifier {
|
|||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.inspect { inspector in
|
||||
inspector.any(ofType: UITextField.self)
|
||||
} customize: { view in
|
||||
view.autocapitalizationType = capitalization
|
||||
.any(forType: UITextField.self) { proxy in
|
||||
proxy.instance.autocapitalizationType = capitalization
|
||||
}
|
||||
.inspect { inspector in
|
||||
inspector.any(ofType: UITextView.self)
|
||||
} customize: { view in
|
||||
view.autocapitalizationType = capitalization
|
||||
.any(forType: UITextView.self) { proxy in
|
||||
proxy.instance.autocapitalizationType = capitalization
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,8 @@ private struct FocusModifier<Value: Hashable>: ViewModifier {
|
|||
content
|
||||
// this ensures when the field goes out of view, it doesn't retain focus
|
||||
.onWillDisappear { focused = nil }
|
||||
.inspect { inspector in
|
||||
inspector.sibling(ofType: UITextField.self)
|
||||
} customize: { view in
|
||||
.sibling(forType: UITextField.self) { proxy in
|
||||
let view = proxy.instance
|
||||
coordinator.observe(field: view)
|
||||
|
||||
coordinator.onBegin = {
|
||||
|
|
|
@ -43,33 +43,23 @@ extension Backport where Wrapped: View {
|
|||
/// - Parameter disabled: A Boolean that indicates whether scrolling is
|
||||
/// disabled.
|
||||
public func scrollDisabled(_ disabled: Bool) -> some View {
|
||||
#if os(iOS)
|
||||
wrapped
|
||||
.environment(\.backportIsScrollEnabled, !disabled)
|
||||
.inspect { inspector in
|
||||
#if os(iOS)
|
||||
inspector.sibling(ofType: UIScrollView.self)
|
||||
?? inspector.ancestor(ofType: UIScrollView.self)
|
||||
?? inspector.descendent(ofType: UIScrollView.self)
|
||||
#elseif os(macOS)
|
||||
inspector.sibling(ofType: NSScrollView.self)
|
||||
?? inspector.ancestor(ofType: NSScrollView.self)
|
||||
?? inspector.descendent(ofType: NSScrollView.self)
|
||||
#endif
|
||||
} customize: { scrollView in
|
||||
#if os(iOS)
|
||||
#if os(iOS)
|
||||
.any(forType: UIScrollView.self) { proxy in
|
||||
let scrollView = proxy.instance
|
||||
scrollView.isScrollEnabled = !disabled
|
||||
scrollView.alwaysBounceVertical = !disabled
|
||||
scrollView.alwaysBounceHorizontal = !disabled
|
||||
#elseif os(macOS)
|
||||
}
|
||||
#endif
|
||||
#if os(macOS)
|
||||
.any(forType: NSScrollView.self) { proxy in
|
||||
let scrollView = proxy.instance
|
||||
scrollView.hasHorizontalScroller = !disabled
|
||||
scrollView.hasVerticalScroller = !disabled
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
wrapped
|
||||
.environment(\.backportIsScrollEnabled, !disabled)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,18 +37,12 @@ extension Backport where Wrapped: View {
|
|||
///
|
||||
/// - Returns: A view with the specified scroll indicator visibility.
|
||||
public func scrollIndicators(_ visibility: Backport<Any>.ScrollIndicatorVisibility, axes: Axis.Set = [.vertical]) -> some View {
|
||||
#if os(iOS)
|
||||
wrapped
|
||||
.environment(\.backportHorizontalScrollIndicatorVisibility, axes.contains(.horizontal) ? visibility : .automatic)
|
||||
.environment(\.backportVerticalScrollIndicatorVisibility, axes.contains(.vertical) ? visibility : .automatic)
|
||||
.inspect { inspector in
|
||||
#if os(iOS)
|
||||
inspector.sibling(ofType: UIScrollView.self)
|
||||
#else
|
||||
inspector.sourceView
|
||||
#endif
|
||||
} customize: { scrollView in
|
||||
#if os(iOS)
|
||||
#if os(iOS)
|
||||
.sibling(forType: UIScrollView.self) { proxy in
|
||||
let scrollView = proxy.instance
|
||||
if axes.contains(.horizontal) {
|
||||
scrollView.showsHorizontalScrollIndicator = visibility.scrollViewVisible
|
||||
scrollView.alwaysBounceHorizontal = true
|
||||
|
@ -62,13 +56,8 @@ extension Backport where Wrapped: View {
|
|||
} else {
|
||||
scrollView.alwaysBounceVertical = false
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
wrapped
|
||||
.environment(\.backportHorizontalScrollIndicatorVisibility, axes.contains(.horizontal) ? visibility : .automatic)
|
||||
.environment(\.backportVerticalScrollIndicatorVisibility, axes.contains(.vertical) ? visibility : .automatic)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,25 +42,15 @@ extension Backport where Wrapped: View {
|
|||
///
|
||||
/// - Returns: A view that uses the specified keyboard dismissal mode.
|
||||
public func scrollDismissesKeyboard(_ mode: Backport<Any>.ScrollDismissesKeyboardMode) -> some View {
|
||||
#if os(iOS)
|
||||
wrapped
|
||||
.environment(\.backportScrollDismissesKeyboardMode, mode)
|
||||
.inspect { inspector in
|
||||
#if os(iOS)
|
||||
inspector.sibling(ofType: UIScrollView.self)
|
||||
#else
|
||||
inspector.sourceView
|
||||
#endif
|
||||
} customize: { scrollView in
|
||||
#if os(iOS)
|
||||
#if os(iOS)
|
||||
.sibling(forType: UIScrollView.self) { proxy in
|
||||
let scrollView = proxy.instance
|
||||
guard scrollView.keyboardDismissMode != mode.scrollViewDismissMode else { return }
|
||||
scrollView.keyboardDismissMode = mode.scrollViewDismissMode
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
wrapped
|
||||
.environment(\.backportScrollDismissesKeyboardMode, mode)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -134,14 +134,11 @@ private struct SubmitModifier: ViewModifier {
|
|||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.inspect { inspector in
|
||||
inspector.any(ofType: UITextView.self)
|
||||
} customize: { view in
|
||||
view.returnKeyType = label.returnKeyType
|
||||
.any(forType: UITextView.self) { proxy in
|
||||
proxy.instance.returnKeyType = label.returnKeyType
|
||||
}
|
||||
.inspect { inspector in
|
||||
inspector.any(ofType: UITextField.self)
|
||||
} customize: { view in
|
||||
.any(forType: UITextField.self) { proxy in
|
||||
let view = proxy.instance
|
||||
view.returnKeyType = label.returnKeyType
|
||||
coordinator.onReturn = { submit() }
|
||||
coordinator.observe(view: view)
|
||||
|
|
Loading…
Reference in New Issue