Replace RSCore with several local modules. Update code as needed.

This commit is contained in:
Brent Simmons
2024-03-20 20:49:15 -07:00
parent d0760f3d12
commit 2461e937bf
240 changed files with 6052 additions and 384 deletions

View File

@@ -0,0 +1,42 @@
//
// UIResponder+.swift
// RSCore
//
// Created by Maurice Parker on 11/17/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
#if os(iOS)
import UIKit
extension UIResponder {
private weak static var _currentFirstResponder: UIResponder? = nil
public static var isFirstResponderTextField: Bool {
var isTextField = false
if let firstResponder = UIResponder.currentFirstResponder {
isTextField = firstResponder.isKind(of: UITextField.self) || firstResponder.isKind(of: UITextView.self) || firstResponder.isKind(of: UISearchBar.self)
}
return isTextField
}
public static var currentFirstResponder: UIResponder? {
UIResponder._currentFirstResponder = nil
UIApplication.shared.sendAction(#selector(findFirstResponder(sender:)), to: nil, from: nil, for: nil)
return UIResponder._currentFirstResponder
}
public static func resignCurrentFirstResponder() {
if let responder = currentFirstResponder {
responder.resignFirstResponder()
}
}
@objc internal func findFirstResponder(sender: AnyObject) {
UIResponder._currentFirstResponder = self
}
}
#endif

View File

@@ -0,0 +1,41 @@
//
// UIView-Extensions.swift
// RSCore
//
// Created by Maurice Parker on 4/20/19.
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
//
#if os(iOS)
import UIKit
extension UIView {
public func setFrameIfNotEqual(_ rect: CGRect) {
if !self.frame.equalTo(rect) {
self.frame = rect
}
}
public func addChildAndPin(_ view: UIView) {
view.translatesAutoresizingMaskIntoConstraints = false
addSubview(view)
NSLayoutConstraint.activate([
safeAreaLayoutGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor),
safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor),
safeAreaLayoutGuide.topAnchor.constraint(equalTo: view.topAnchor),
safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
public func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}
}
#endif

View File

@@ -0,0 +1,68 @@
//
// UIViewController-Extensions.swift
// NetNewsWire
//
// Created by Maurice Parker on 4/15/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
#if os(iOS)
import UIKit
import SwiftUI
extension UIViewController {
// MARK: Autolayout
public func addChildAndPinView(_ controller: UIViewController) {
view.addChildAndPin(controller.view)
addChild(controller)
}
public func replaceChildAndPinView(_ controller: UIViewController) {
view.subviews.forEach { $0.removeFromSuperview() }
children.forEach { $0.removeFromParent() }
addChildAndPinView(controller)
}
// MARK: Error Handling
public func presentError(title: String, message: String, dismiss: (() -> Void)? = nil) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let dismissTitle = NSLocalizedString("OK", comment: "OK")
let dismissAction = UIAlertAction(title: dismissTitle, style: .default) { _ in
dismiss?()
}
alertController.addAction(dismissAction)
self.present(alertController, animated: true, completion: nil)
}
}
// MARK: SwiftUI
public struct ViewControllerHolder {
public weak var value: UIViewController?
}
public struct ViewControllerKey: EnvironmentKey {
public static var defaultValue: ViewControllerHolder { return ViewControllerHolder(value: nil ) }
}
extension EnvironmentValues {
public var viewController: UIViewController? {
get { return self[ViewControllerKey.self].value }
set { self[ViewControllerKey.self].value = newValue }
}
}
extension UIViewController {
public func present<Content: View>(style: UIModalPresentationStyle = .automatic, @ViewBuilder builder: () -> Content) {
let controller = UIHostingController(rootView: AnyView(EmptyView()))
controller.modalPresentationStyle = style
controller.rootView = AnyView(
builder().environment(\.viewController, controller)
)
self.present(controller, animated: true, completion: nil)
}
}
#endif

View File

@@ -0,0 +1,42 @@
//
// UIViewController+.swift
// NetNewsWire
//
// Created by Maurice Parker on 4/15/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
#if os(iOS)
import UIKit
extension UIWindow {
public var topViewController: UIViewController? {
var top = self.rootViewController
while true {
if let presented = top?.presentedViewController {
top = presented
} else if let nav = top as? UINavigationController {
top = nav.visibleViewController
} else if let tab = top as? UITabBarController {
top = tab.selectedViewController
} else if let split = top as? UISplitViewController {
switch split.displayMode {
case .allVisible:
top = split.viewControllers.first
case .primaryHidden:
top = split.viewControllers.last
default:
top = split.viewControllers.first
}
} else {
break
}
}
return top
}
}
#endif