mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
wip
This commit is contained in:
parent
f38e31dc22
commit
aee63afc1a
@ -3,6 +3,7 @@ import SwiftUI
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
|
||||
let SHOW_SAFE_AREA = false
|
||||
|
||||
@objc(AppDelegate)
|
||||
final class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
@ -18,7 +19,6 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
hostView.containerView.backgroundColor = UIColor.white
|
||||
self.window = window
|
||||
|
||||
|
||||
let navigationController = NavigationController(
|
||||
mode: .single,
|
||||
theme: NavigationControllerTheme(
|
||||
@ -30,7 +30,49 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
|
||||
mainWindow.viewController = navigationController
|
||||
|
||||
navigationController.setViewControllers([mySwiftUIViewController(0)], animated: false)
|
||||
let rootViewController = mySwiftUIViewController(0)
|
||||
|
||||
if SHOW_SAFE_AREA {
|
||||
// Add insets visualization
|
||||
rootViewController.view.layoutMargins = .zero
|
||||
rootViewController.view.subviews.forEach { $0.removeFromSuperview() }
|
||||
|
||||
let topInsetView = UIView()
|
||||
let leftInsetView = UIView()
|
||||
let rightInsetView = UIView()
|
||||
let bottomInsetView = UIView()
|
||||
|
||||
[topInsetView, leftInsetView, rightInsetView, bottomInsetView].forEach {
|
||||
$0.backgroundColor = .systemRed
|
||||
$0.alpha = 0.3
|
||||
rootViewController.view.addSubview($0)
|
||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
topInsetView.topAnchor.constraint(equalTo: rootViewController.view.topAnchor),
|
||||
topInsetView.leadingAnchor.constraint(equalTo: rootViewController.view.leadingAnchor),
|
||||
topInsetView.trailingAnchor.constraint(equalTo: rootViewController.view.trailingAnchor),
|
||||
topInsetView.bottomAnchor.constraint(equalTo: rootViewController.view.safeAreaLayoutGuide.topAnchor),
|
||||
|
||||
leftInsetView.topAnchor.constraint(equalTo: rootViewController.view.topAnchor),
|
||||
leftInsetView.leadingAnchor.constraint(equalTo: rootViewController.view.leadingAnchor),
|
||||
leftInsetView.bottomAnchor.constraint(equalTo: rootViewController.view.bottomAnchor),
|
||||
leftInsetView.trailingAnchor.constraint(equalTo: rootViewController.view.safeAreaLayoutGuide.leadingAnchor),
|
||||
|
||||
rightInsetView.topAnchor.constraint(equalTo: rootViewController.view.topAnchor),
|
||||
rightInsetView.trailingAnchor.constraint(equalTo: rootViewController.view.trailingAnchor),
|
||||
rightInsetView.bottomAnchor.constraint(equalTo: rootViewController.view.bottomAnchor),
|
||||
rightInsetView.leadingAnchor.constraint(equalTo: rootViewController.view.safeAreaLayoutGuide.trailingAnchor),
|
||||
|
||||
bottomInsetView.bottomAnchor.constraint(equalTo: rootViewController.view.bottomAnchor),
|
||||
bottomInsetView.leadingAnchor.constraint(equalTo: rootViewController.view.leadingAnchor),
|
||||
bottomInsetView.trailingAnchor.constraint(equalTo: rootViewController.view.trailingAnchor),
|
||||
bottomInsetView.topAnchor.constraint(equalTo: rootViewController.view.safeAreaLayoutGuide.bottomAnchor)
|
||||
])
|
||||
}
|
||||
|
||||
navigationController.setViewControllers([rootViewController], animated: false)
|
||||
|
||||
self.window?.makeKeyAndVisible()
|
||||
|
||||
|
@ -6,288 +6,62 @@ import UIKit
|
||||
import LegacyUI
|
||||
import TelegramPresentationData
|
||||
|
||||
public class SwiftUIViewControllerInteraction {
|
||||
let push: (ViewController) -> Void
|
||||
let present: (
|
||||
_ controller: ViewController,
|
||||
_ in: PresentationContextType,
|
||||
_ with: ViewControllerPresentationArguments?
|
||||
) -> Void
|
||||
let dismiss: (_ animated: Bool, _ completion: (() -> Void)?) -> Void
|
||||
|
||||
init(
|
||||
push: @escaping (ViewController) -> Void,
|
||||
present: @escaping (
|
||||
_ controller: ViewController,
|
||||
_ in: PresentationContextType,
|
||||
_ with: ViewControllerPresentationArguments?
|
||||
) -> Void,
|
||||
dismiss: @escaping (_ animated: Bool, _ completion: (() -> Void)?) -> Void
|
||||
) {
|
||||
self.push = push
|
||||
self.present = present
|
||||
self.dismiss = dismiss
|
||||
}
|
||||
}
|
||||
//
|
||||
//public protocol SwiftUIView: View {
|
||||
// var controllerInteraction: SwiftUIViewControllerInteraction? { get set }
|
||||
//}
|
||||
//
|
||||
//struct MySwiftUIView: SwiftUIView {
|
||||
// var controllerInteraction: SwiftUIViewControllerInteraction?
|
||||
//
|
||||
//
|
||||
// var num: Int64
|
||||
//
|
||||
// var body: some View {
|
||||
// Color.orange
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//struct CustomButtonStyle: ButtonStyle {
|
||||
// func makeBody(configuration: Configuration) -> some View {
|
||||
// configuration.label
|
||||
// .padding()
|
||||
// .background(Color.blue)
|
||||
// .foregroundColor(.white)
|
||||
// .cornerRadius(8)
|
||||
// .frame(height: 44) // Set a fixed height for all buttons
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//private final class SwiftUIViewControllerNode<Content: SwiftUIView>: ASDisplayNode {
|
||||
// private let hostingController: UIHostingController<Content>
|
||||
// private var isDismissed = false
|
||||
// private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)?
|
||||
//
|
||||
// init(swiftUIView: Content) {
|
||||
// self.hostingController = UIHostingController(rootView: swiftUIView)
|
||||
// super.init()
|
||||
//
|
||||
// // For debugging
|
||||
// self.backgroundColor = .red.withAlphaComponent(0.3)
|
||||
// hostingController.view.backgroundColor = .blue.withAlphaComponent(0.3)
|
||||
// }
|
||||
//
|
||||
// override func didLoad() {
|
||||
// super.didLoad()
|
||||
//
|
||||
// // Defer the setup to ensure we have a valid view controller hierarchy
|
||||
// DispatchQueue.main.async { [weak self] in
|
||||
// self?.setupHostingController()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private func setupHostingController() {
|
||||
// guard let viewController = findViewController() else {
|
||||
// assert(true, "Error: Could not find a parent view controller")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// viewController.addChild(hostingController)
|
||||
// view.addSubview(hostingController.view)
|
||||
// hostingController.didMove(toParent: viewController)
|
||||
//
|
||||
// // Ensure the hosting controller's view has a size
|
||||
// hostingController.view.frame = self.bounds
|
||||
//
|
||||
// print("SwiftUIViewControllerNode setup - Node frame: \(self.frame), Hosting view frame: \(hostingController.view.frame)")
|
||||
// }
|
||||
//
|
||||
// private func findViewController() -> UIViewController? {
|
||||
// var responder: UIResponder? = self.view
|
||||
// while let nextResponder = responder?.next {
|
||||
// if let viewController = nextResponder as? UIViewController {
|
||||
// return viewController
|
||||
// }
|
||||
// responder = nextResponder
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// override func layout() {
|
||||
// super.layout()
|
||||
// hostingController.view.frame = self.bounds
|
||||
// print("SwiftUIViewControllerNode layout - Node frame: \(self.frame), Hosting view frame: \(hostingController.view.frame)")
|
||||
// }
|
||||
//
|
||||
// func containerLayoutUpdated(
|
||||
// layout: ContainerViewLayout,
|
||||
// navigationHeight: CGFloat,
|
||||
// transition: ContainedViewLayoutTransition
|
||||
// ) {
|
||||
// if self.isDismissed {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// self.validLayout = (layout, navigationHeight)
|
||||
//
|
||||
// let frame = CGRect(
|
||||
// origin: CGPoint(x: 0, y: 0),
|
||||
// size: CGSize(
|
||||
// width: layout.size.width,
|
||||
// height: layout.size.height
|
||||
// )
|
||||
// )
|
||||
//
|
||||
// transition.updateFrame(node: self, frame: frame)
|
||||
//
|
||||
// print("containerLayoutUpdated - New frame: \(frame)")
|
||||
//
|
||||
// // Ensure hosting controller view is updated
|
||||
// hostingController.view.frame = bounds
|
||||
// }
|
||||
//
|
||||
// func animateOut(completion: @escaping () -> Void) {
|
||||
// guard let (layout, navigationHeight) = validLayout else {
|
||||
// completion()
|
||||
// return
|
||||
// }
|
||||
// self.isDismissed = true
|
||||
// let transition: ContainedViewLayoutTransition = .animated(duration: 0.4, curve: .spring)
|
||||
//
|
||||
// let frame = CGRect(
|
||||
// origin: CGPoint(x: 0, y: 0),
|
||||
// size: CGSize(
|
||||
// width: layout.size.width,
|
||||
// height: layout.size.height
|
||||
// )
|
||||
// )
|
||||
//
|
||||
// transition.updateFrame(node: self, frame: frame, completion: { _ in
|
||||
// completion()
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// override func didEnterHierarchy() {
|
||||
// super.didEnterHierarchy()
|
||||
// print("SwiftUIViewControllerNode entered hierarchy")
|
||||
// }
|
||||
//
|
||||
// override func didExitHierarchy() {
|
||||
// super.didExitHierarchy()
|
||||
// hostingController.willMove(toParent: nil)
|
||||
// hostingController.view.removeFromSuperview()
|
||||
// hostingController.removeFromParent()
|
||||
// print("SwiftUIViewControllerNode exited hierarchy")
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//public final class SwiftUIViewController<Content: SwiftUIView>: ViewController {
|
||||
// private var swiftUIView: Content
|
||||
//
|
||||
// public init(
|
||||
// _ swiftUIView: Content,
|
||||
// navigationBarTheme: NavigationBarTheme = NavigationBarTheme(
|
||||
// buttonColor: ACCENT_COLOR,
|
||||
// disabledButtonColor: .gray,
|
||||
// primaryTextColor: .black,
|
||||
// backgroundColor: .clear,
|
||||
// enableBackgroundBlur: true,
|
||||
// separatorColor: .gray,
|
||||
// badgeBackgroundColor: THEME.navigationBar.badgeBackgroundColor,
|
||||
// badgeStrokeColor: THEME.navigationBar.badgeStrokeColor,
|
||||
// badgeTextColor: THEME.navigationBar.badgeTextColor
|
||||
// ),
|
||||
// navigationBarStrings: NavigationBarStrings = NavigationBarStrings(
|
||||
// back: "Back",
|
||||
// close: "Close"
|
||||
// )
|
||||
// ) {
|
||||
// self.swiftUIView = swiftUIView
|
||||
// super.init(navigationBarPresentationData: NavigationBarPresentationData(
|
||||
// theme: navigationBarTheme,
|
||||
// strings: navigationBarStrings
|
||||
// ))
|
||||
//
|
||||
// self.swiftUIView.controllerInteraction = SwiftUIViewControllerInteraction(
|
||||
// push: { [weak self] c in
|
||||
// guard let strongSelf = self else { return }
|
||||
// strongSelf.push(c)
|
||||
// },
|
||||
// present: { [weak self] c, context, args in
|
||||
// guard let strongSelf = self else { return }
|
||||
// strongSelf.present(c, in: context, with: args)
|
||||
// },
|
||||
// dismiss: { [weak self] animated, completion in
|
||||
// guard let strongSelf = self else { return }
|
||||
// strongSelf.dismiss(animated: animated, completion: completion)
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// @available(*, unavailable)
|
||||
// required init(coder _: NSCoder) {
|
||||
// fatalError("init(coder:) has not been implemented")
|
||||
// }
|
||||
//
|
||||
// override public func loadDisplayNode() {
|
||||
// self.displayNode = SwiftUIViewControllerNode<Content>(swiftUIView: swiftUIView)
|
||||
// }
|
||||
//
|
||||
// override public func containerLayoutUpdated(
|
||||
// _ layout: ContainerViewLayout,
|
||||
// transition: ContainedViewLayoutTransition
|
||||
// ) {
|
||||
// super.containerLayoutUpdated(layout, transition: transition)
|
||||
//
|
||||
// (self.displayNode as! SwiftUIViewControllerNode<Content>).containerLayoutUpdated(
|
||||
// layout: layout,
|
||||
// navigationHeight: navigationLayout(layout: layout).navigationFrame.maxY,
|
||||
// transition: transition
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// public func animateOut(completion: @escaping () -> Void) {
|
||||
// (self.displayNode as! SwiftUIViewControllerNode<Content>)
|
||||
// .animateOut(completion: completion)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//
|
||||
//func mySwiftUIViewController(_ num: Int64) -> ViewController {
|
||||
// let controller = SwiftUIViewController(MySwiftUIView(num: num))
|
||||
// controller.title = "Controller: \(num)"
|
||||
// return controller
|
||||
//}
|
||||
|
||||
|
||||
public protocol SwiftUIView: View {
|
||||
var controllerInteraction: SwiftUIViewControllerInteraction? { get set }
|
||||
}
|
||||
|
||||
struct MySwiftUIView: SwiftUIView {
|
||||
var controllerInteraction: SwiftUIViewControllerInteraction?
|
||||
struct MySwiftUIView: View {
|
||||
weak var wrapperController: LegacyController?
|
||||
|
||||
var num: Int64
|
||||
|
||||
var body: some View {
|
||||
Color.orange
|
||||
// VStack {
|
||||
// Button("Push") {
|
||||
// self.controllerInteraction?.push(mySwiftUIViewController(num + 1))
|
||||
// }
|
||||
// Button("Modal") {
|
||||
// self.controllerInteraction?.present(mySwiftUIViewController(num + 1), .window(.root), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
// }
|
||||
// Button("Dismiss") {
|
||||
// self.controllerInteraction?.dismiss(true, {})
|
||||
// }
|
||||
// }
|
||||
VStack {
|
||||
Text("Hello, World!")
|
||||
.font(.title)
|
||||
.foregroundColor(.black)
|
||||
|
||||
Spacer(minLength: 0)
|
||||
|
||||
Button("Push") {
|
||||
self.wrapperController?.push(mySwiftUIViewController(num + 1))
|
||||
}.buttonStyle(AppleButtonStyle())
|
||||
Spacer()
|
||||
Button("Modal") {
|
||||
self.wrapperController?.present(mySwiftUIViewController(num + 1), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}.buttonStyle(AppleButtonStyle())
|
||||
Spacer()
|
||||
if num > 0 {
|
||||
Button("Dismiss") {
|
||||
self.wrapperController?.dismiss()
|
||||
}.buttonStyle(AppleButtonStyle())
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
// .frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(Color.green)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct AppleButtonStyle: ButtonStyle {
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
configuration.label
|
||||
.font(.headline)
|
||||
.foregroundColor(.white)
|
||||
.padding()
|
||||
.frame(minWidth: 0, maxWidth: .infinity)
|
||||
.background(Color.blue)
|
||||
.cornerRadius(10)
|
||||
.scaleEffect(configuration.isPressed ? 0.95 : 1)
|
||||
.opacity(configuration.isPressed ? 0.9 : 1)
|
||||
}
|
||||
}
|
||||
|
||||
func mySwiftUIViewController(_ num: Int64) -> ViewController {
|
||||
let legacyController = LegacyController(presentation: .navigation, theme: defaultPresentationTheme, strings: defaultPresentationStrings)
|
||||
legacyController.statusBar.statusBarStyle = defaultPresentationTheme.rootController.statusBarStyle.style
|
||||
legacyController.title = "Controller: root"
|
||||
legacyController.title = "Controller: \(num)"
|
||||
|
||||
let controller = UIHostingController(rootView: MySwiftUIView(num: num))
|
||||
let swiftUIView = MySwiftUIView(wrapperController: legacyController, num: num)
|
||||
let controller = UIHostingController(rootView: swiftUIView)
|
||||
legacyController.bind(controller: controller)
|
||||
legacyController.addChild(controller)
|
||||
controller.didMove(toParent: legacyController)
|
||||
|
||||
|
||||
return legacyController
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import Display
|
||||
import SwiftSignalKit
|
||||
import LegacyComponents
|
||||
import TelegramPresentationData
|
||||
import SwiftUI
|
||||
|
||||
public enum LegacyControllerPresentation {
|
||||
case custom
|
||||
@ -475,6 +476,10 @@ open class LegacyController: ViewController, PresentableController {
|
||||
self?.dismiss()
|
||||
}
|
||||
}
|
||||
if self.legacyController.isHosting {
|
||||
self.addChild(self.legacyController)
|
||||
self.legacyController.didMove(toParent: legacyController)
|
||||
}
|
||||
}
|
||||
|
||||
override open func loadDisplayNode() {
|
||||
@ -614,6 +619,11 @@ open class LegacyController: ViewController, PresentableController {
|
||||
if previousSizeClass != updatedSizeClass {
|
||||
self.sizeClass.set(SSignal.single(updatedSizeClass.rawValue as NSNumber))
|
||||
}
|
||||
if let sai = self.controllerNode.controllerView?.safeAreaInsets {
|
||||
print("Safe area 1", sai)
|
||||
}
|
||||
print("Safe area 2", self.controllerNode.safeAreaInsets)
|
||||
print("Safe area 3", self.view.safeAreaInsets)
|
||||
}
|
||||
|
||||
override open func dismiss(completion: (() -> Void)? = nil) {
|
||||
@ -636,3 +646,24 @@ open class LegacyController: ViewController, PresentableController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension LegacyController {
|
||||
|
||||
// private func syncLegacyControllerSafeArea() {
|
||||
// let recommendedSafeAreaInsets = self.contextImpl.safeAreaInset()
|
||||
// let currentSafeAreaInsets = self.legacyController.view.safeAreaInsets
|
||||
// let additionalInsets = UIEdgeInsets(top: recommendedSafeAreaInsets.top - currentSafeAreaInsets.top, left: recommendedSafeAreaInsets.left - currentSafeAreaInsets.left, bottom: recommendedSafeAreaInsets.bottom - currentSafeAreaInsets.bottom, right: recommendedSafeAreaInsets.left - currentSafeAreaInsets.right)
|
||||
// self.legacyController.additionalSafeAreaInsets = additionalInsets
|
||||
// self.legacyController.viewSafeAreaInsetsDidChange()
|
||||
// self.legacyController.view.setNeedsLayout()
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
// MARK: Swiftgram
|
||||
private protocol AnyUIHostingViewController: AnyObject {}
|
||||
extension UIHostingController: AnyUIHostingViewController {}
|
||||
|
||||
extension UIViewController {
|
||||
var isHosting: Bool { self is AnyUIHostingViewController }
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user