mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
WIP Injecting SwiftUI via LegacyController
This commit is contained in:
parent
4b1edac9e2
commit
f38e31dc22
@ -6,7 +6,7 @@ load(
|
|||||||
"xcodeproj",
|
"xcodeproj",
|
||||||
)
|
)
|
||||||
load(
|
load(
|
||||||
"//Swiftgram/Playground:custom_bazel_path.bzl", "custom_bazel_path"
|
"@build_configuration//:variables.bzl", "telegram_bazel_path"
|
||||||
)
|
)
|
||||||
|
|
||||||
objc_library(
|
objc_library(
|
||||||
@ -24,6 +24,12 @@ swift_library(
|
|||||||
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
||||||
"//submodules/Display:Display",
|
"//submodules/Display:Display",
|
||||||
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
||||||
|
"//submodules/LegacyUI:LegacyUI",
|
||||||
|
"//submodules/LegacyComponents:LegacyComponents",
|
||||||
|
"//submodules/MediaPlayer:UniversalMediaPlayer",
|
||||||
|
],
|
||||||
|
data = [
|
||||||
|
"//Telegram:GeneratedPresentationStrings/Resources/PresentationStrings.data",
|
||||||
],
|
],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
@ -38,12 +44,15 @@ ios_application(
|
|||||||
infoplists = ["Resources/Info.plist"],
|
infoplists = ["Resources/Info.plist"],
|
||||||
minimum_os_version = "14.0",
|
minimum_os_version = "14.0",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
|
strings = [
|
||||||
|
"//Telegram:AppStringResources",
|
||||||
|
],
|
||||||
launch_storyboard = "Resources/LaunchScreen.storyboard",
|
launch_storyboard = "Resources/LaunchScreen.storyboard",
|
||||||
deps = [":PlaygroundMain", ":PlaygroundLib"],
|
deps = [":PlaygroundMain", ":PlaygroundLib"],
|
||||||
)
|
)
|
||||||
|
|
||||||
xcodeproj(
|
xcodeproj(
|
||||||
bazel_path = custom_bazel_path(),
|
bazel_path = telegram_bazel_path,
|
||||||
name = "Playground_xcodeproj",
|
name = "Playground_xcodeproj",
|
||||||
build_mode = "bazel",
|
build_mode = "bazel",
|
||||||
project_name = "Playground",
|
project_name = "Playground",
|
||||||
|
@ -4,17 +4,7 @@ Small app to quickly iterate on components testing without building an entire me
|
|||||||
|
|
||||||
## Generate Xcode project
|
## Generate Xcode project
|
||||||
|
|
||||||
### From root
|
Same as main project described in [../../Readme.md](../../Readme.md), but with `--target="Swiftgram/Playground"` parameter.
|
||||||
|
|
||||||
```shell
|
|
||||||
./Swiftgram/Playground/generate_project.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### From current directory
|
|
||||||
|
|
||||||
```shell
|
|
||||||
./generate_project.py
|
|
||||||
```
|
|
||||||
|
|
||||||
## Run generated project on simulator
|
## Run generated project on simulator
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ import Display
|
|||||||
import Foundation
|
import Foundation
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import LegacyUI
|
||||||
|
import TelegramPresentationData
|
||||||
|
|
||||||
public class SwiftUIViewControllerInteraction {
|
public class SwiftUIViewControllerInteraction {
|
||||||
let push: (ViewController) -> Void
|
let push: (ViewController) -> Void
|
||||||
@ -27,230 +29,265 @@ public class SwiftUIViewControllerInteraction {
|
|||||||
self.dismiss = dismiss
|
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 {
|
public protocol SwiftUIView: View {
|
||||||
var controllerInteraction: SwiftUIViewControllerInteraction? { get set }
|
var controllerInteraction: SwiftUIViewControllerInteraction? { get set }
|
||||||
var navigationHeight: CGFloat { get set }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MySwiftUIView: SwiftUIView {
|
struct MySwiftUIView: SwiftUIView {
|
||||||
var controllerInteraction: SwiftUIViewControllerInteraction?
|
var controllerInteraction: SwiftUIViewControllerInteraction?
|
||||||
@Binding var navigationHeight: CGFloat
|
|
||||||
|
|
||||||
|
|
||||||
var num: Int64
|
var num: Int64
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Color.orange
|
Color.orange
|
||||||
.padding(.top, 2.0 * (_navigationHeight ?? 0))
|
// 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, {})
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
hostingController.rootView.navigationHeight = navigationHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
})
|
|
||||||
hostingController.rootView.navigationHeight = navigationHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
func mySwiftUIViewController(_ num: Int64) -> ViewController {
|
||||||
let controller = SwiftUIViewController(MySwiftUIView(num: num))
|
let legacyController = LegacyController(presentation: .navigation, theme: defaultPresentationTheme, strings: defaultPresentationStrings)
|
||||||
controller.title = "Controller: \(num)"
|
legacyController.statusBar.statusBarStyle = defaultPresentationTheme.rootController.statusBarStyle.style
|
||||||
return controller
|
legacyController.title = "Controller: root"
|
||||||
|
|
||||||
|
let controller = UIHostingController(rootView: MySwiftUIView(num: num))
|
||||||
|
legacyController.bind(controller: controller)
|
||||||
|
legacyController.addChild(controller)
|
||||||
|
controller.didMove(toParent: legacyController)
|
||||||
|
|
||||||
|
|
||||||
|
return legacyController
|
||||||
}
|
}
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
from contextlib import contextmanager
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import shutil
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
# Import the locate_bazel function
|
|
||||||
sys.path.append(
|
|
||||||
os.path.join(os.path.dirname(__file__), "..", "..", "build-system", "Make")
|
|
||||||
)
|
|
||||||
from BazelLocation import locate_bazel
|
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def cwd(path):
|
|
||||||
oldpwd = os.getcwd()
|
|
||||||
os.chdir(path)
|
|
||||||
try:
|
|
||||||
yield
|
|
||||||
finally:
|
|
||||||
os.chdir(oldpwd)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# Get the current script directory
|
|
||||||
current_script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
with cwd(os.path.join(current_script_dir, "..", "..")):
|
|
||||||
bazel_path = locate_bazel(os.getcwd())
|
|
||||||
# 1. Kill all Xcode processes
|
|
||||||
subprocess.run(["killall", "Xcode"], check=False)
|
|
||||||
|
|
||||||
# 2. Delete xcodeproj.bazelrc if it exists and write a new one
|
|
||||||
bazelrc_path = os.path.join(current_script_dir, "..", "..", "xcodeproj.bazelrc")
|
|
||||||
if os.path.exists(bazelrc_path):
|
|
||||||
os.remove(bazelrc_path)
|
|
||||||
|
|
||||||
with open(bazelrc_path, "w") as f:
|
|
||||||
f.write(
|
|
||||||
textwrap.dedent(
|
|
||||||
"""
|
|
||||||
build --announce_rc
|
|
||||||
build --features=swift.use_global_module_cache
|
|
||||||
build --verbose_failures
|
|
||||||
build --features=swift.enable_batch_mode
|
|
||||||
build --features=-swift.debug_prefix_map
|
|
||||||
# build --disk_cache=
|
|
||||||
|
|
||||||
build --swiftcopt=-no-warnings-as-errors
|
|
||||||
build --copt=-Wno-error
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# 3. Delete the Xcode project if it exists
|
|
||||||
xcode_project_path = os.path.join(current_script_dir, "Playground.xcodeproj")
|
|
||||||
if os.path.exists(xcode_project_path):
|
|
||||||
shutil.rmtree(xcode_project_path)
|
|
||||||
|
|
||||||
# 4. Write content to generate_project.py
|
|
||||||
generate_project_path = os.path.join(current_script_dir, "custom_bazel_path.bzl")
|
|
||||||
with open(generate_project_path, "w") as f:
|
|
||||||
f.write("def custom_bazel_path():\n")
|
|
||||||
f.write(f' return "{bazel_path}"\n')
|
|
||||||
|
|
||||||
# 5. Run xcodeproj generator
|
|
||||||
working_dir = os.path.join(current_script_dir, "..", "..")
|
|
||||||
bazel_command = f'"{bazel_path}" run //Swiftgram/Playground:Playground_xcodeproj'
|
|
||||||
subprocess.run(bazel_command, shell=True, cwd=working_dir, check=True)
|
|
||||||
|
|
||||||
# 5. Open Xcode project
|
|
||||||
subprocess.run(["open", xcode_project_path], check=True)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -138,6 +138,10 @@ genrule(
|
|||||||
"GeneratedPresentationStrings/Sources/PresentationStrings.m",
|
"GeneratedPresentationStrings/Sources/PresentationStrings.m",
|
||||||
"GeneratedPresentationStrings/Resources/PresentationStrings.data",
|
"GeneratedPresentationStrings/Resources/PresentationStrings.data",
|
||||||
],
|
],
|
||||||
|
# MARK: Swiftgram
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
minimum_os_version = "12.0"
|
minimum_os_version = "12.0"
|
||||||
@ -253,7 +257,9 @@ filegroup(
|
|||||||
"//Swiftgram/SGStrings:SGLocalizableStrings",
|
"//Swiftgram/SGStrings:SGLocalizableStrings",
|
||||||
] + [
|
] + [
|
||||||
"{}.lproj/Localizable.strings".format(language) for language in empty_languages
|
"{}.lproj/Localizable.strings".format(language) for language in empty_languages
|
||||||
]
|
],
|
||||||
|
# MARK: Swiftgram
|
||||||
|
visibility = ["//visibility:public",],
|
||||||
)
|
)
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
|
@ -34,6 +34,9 @@ def generate_xcodeproj(build_environment: BuildEnvironment, disable_extensions,
|
|||||||
project_bazel_arguments.append(argument)
|
project_bazel_arguments.append(argument)
|
||||||
project_bazel_arguments += ['--override_repository=build_configuration={}'.format(configuration_path)]
|
project_bazel_arguments += ['--override_repository=build_configuration={}'.format(configuration_path)]
|
||||||
|
|
||||||
|
if target_name == "Swiftgram/Playground":
|
||||||
|
project_bazel_arguments += ["--swiftcopt=-no-warnings-as-errors", "--copt=-Wno-error"]#, "--swiftcopt=-DSWIFTGRAM_PLAYGROUND", "--copt=-DSWIFTGRAM_PLAYGROUND=1"]
|
||||||
|
|
||||||
if target_name == 'Telegram':
|
if target_name == 'Telegram':
|
||||||
if disable_extensions:
|
if disable_extensions:
|
||||||
project_bazel_arguments += ['--//{}:disableExtensions'.format(app_target)]
|
project_bazel_arguments += ['--//{}:disableExtensions'.format(app_target)]
|
||||||
@ -51,6 +54,10 @@ def generate_xcodeproj(build_environment: BuildEnvironment, disable_extensions,
|
|||||||
call_executable(bazel_generate_arguments)
|
call_executable(bazel_generate_arguments)
|
||||||
|
|
||||||
# MARK: Swiftgram
|
# MARK: Swiftgram
|
||||||
|
if target_name == "Swiftgram/Playground":
|
||||||
|
xcodeproj_path = 'Swiftgram/Playground/Playground.xcodeproj'
|
||||||
|
call_executable(['open', xcodeproj_path])
|
||||||
|
return
|
||||||
xcodeproj_path = 'Telegram/Swiftgram.xcodeproj'
|
xcodeproj_path = 'Telegram/Swiftgram.xcodeproj'
|
||||||
call_executable(['open', xcodeproj_path])
|
call_executable(['open', xcodeproj_path])
|
||||||
|
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
#import <LegacyComponents/TGVideoEditAdjustments.h>
|
#import <LegacyComponents/TGVideoEditAdjustments.h>
|
||||||
|
|
||||||
|
// MARK: Swiftgram
|
||||||
|
#import <VideoToolbox/VideoToolbox.h>
|
||||||
|
#import <MediaPlayer/MediaPlayer.h>
|
||||||
|
//
|
||||||
|
|
||||||
@interface TGMediaVideoFileWatcher : NSObject
|
@interface TGMediaVideoFileWatcher : NSObject
|
||||||
{
|
{
|
||||||
NSURL *_fileURL;
|
NSURL *_fileURL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user