From aac514827d73115149ed5b79146d685876cc9f30 Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 26 Feb 2024 02:39:48 +0800 Subject: [PATCH] Bump watchOS target and update App related (#40) * Bump watchOS target and fix available issue * Update AppGraph * Update OpenGraph to add profile support * Add GraphDelegate and update App related --- Package.resolved | 2 +- Package.swift | 2 +- .../AppStructure/AppOrganization/App.swift | 2 - .../AppOrganization/Graph/AppGraph.swift | 73 +++++++++++++++++++ .../Profile/FinishLaunchTestAction.swift | 30 ++++++++ .../AppOrganization/TODO/AppGraph.swift | 22 ------ .../TODO/FallbackDelegateBox.swift | 7 +- .../TODO/OpenSwiftUIApplication.swift | 6 +- .../KeyboardShortcut/EventModifiers.swift | 1 - .../Internal/Graph/GraphDelegate.swift | 13 ++++ .../Internal/Graph/GraphHost.swift | 43 +++++++++-- .../OpenSwiftUI/Test/_PerformanceTest.swift | 12 ++- .../Views/View/Extension/View_Font.swift | 1 - .../include/OpenSwiftUI_SPI.h | 10 ++- 14 files changed, 179 insertions(+), 45 deletions(-) create mode 100644 Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift create mode 100644 Sources/OpenSwiftUI/AppStructure/AppOrganization/Profile/FinishLaunchTestAction.swift delete mode 100644 Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift create mode 100644 Sources/OpenSwiftUI/Internal/Graph/GraphDelegate.swift diff --git a/Package.resolved b/Package.resolved index 4ba7be1..484f7fa 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,7 +6,7 @@ "location" : "https://github.com/OpenSwiftUIProject/OpenGraph", "state" : { "branch" : "main", - "revision" : "6133e9f737077b5c75ff33dee1c2c969cb5d91b4" + "revision" : "45bd9b86eb917e1bd56ead3ef51ca82beca94a70" } }, { diff --git a/Package.swift b/Package.swift index 6ba620d..4394801 100644 --- a/Package.swift +++ b/Package.swift @@ -70,7 +70,7 @@ let package = Package( .macOS(.v10_15), .macCatalyst(.v13), .tvOS(.v13), - .watchOS(.v6), + .watchOS(.v7), // WKApplicationMain is available for watchOS 7.0+ .visionOS(.v1), ], products: [ diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/App.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/App.swift index 24c10cc..c65d169 100644 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/App.swift +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/App.swift @@ -67,7 +67,6 @@ /// } /// } /// -@available(watchOS 7.0, *) public protocol App { /// The type of scene representing the content of the app. /// @@ -108,7 +107,6 @@ public protocol App { init() } -@available(watchOS 7.0, *) extension App { /// Initializes and runs the app. /// diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift new file mode 100644 index 0000000..e3931b6 --- /dev/null +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Graph/AppGraph.swift @@ -0,0 +1,73 @@ +// +// AppGraph.swift +// OpenSwiftUI +// +// Created by Kyle on 2023/9/22. +// Lastest Version: iOS 15.5 +// Status: WIP +// ID: A363922CEBDF47986D9772B903C8737A + +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif os(WASI) +import WASILibc +#endif +internal import OpenGraphShims + +final class AppGraph: GraphHost { + static var shared: AppGraph? = nil + static var delegateBox: AnyFallbackDelegateBox? = nil + + private struct LaunchProfileOptions: OptionSet { + let rawValue: Int32 + static var profile: LaunchProfileOptions { .init(rawValue: 1 << 1) } + } + + private lazy var launchProfileOptions: LaunchProfileOptions = { + let env = getenv("OPENSWIFTUI_PROFILE_LAUNCH") + if let env { + return .init(rawValue: atoi(env)) + } else { + return [] + } + }() + + var didCollectLaunchProfile: Bool = false + + // TODO + init(app: some App) { + let data = GraphHost.Data() + super.init(data: data) + } + + // MARK: - Override Methods + + // MARK: - Profile related + + func extendedLaunchTestName() -> String? { nil } + + func startProfilingIfNecessary() { + guard !didCollectLaunchProfile else { + return + } + if launchProfileOptions.contains(.profile) { + OGGraph.startProfiling() + } + } + + func stopProfilingIfNecessary() { + guard !didCollectLaunchProfile else { + return + } + didCollectLaunchProfile = true + if launchProfileOptions.contains(.profile) { + OGGraph.stopProfiling() + } + if !launchProfileOptions.isEmpty { + // /tmp/graph.ag-gzon + OGGraph.archiveJSON(name: nil) + } + } +} diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/Profile/FinishLaunchTestAction.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Profile/FinishLaunchTestAction.swift new file mode 100644 index 0000000..3ff6e26 --- /dev/null +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/Profile/FinishLaunchTestAction.swift @@ -0,0 +1,30 @@ +// +// FinishLaunchTestAction.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/2/25. +// Lastest Version: iOS 15.5 +// Status: Complete + +#if os(iOS) +import UIKit +#elseif os(macOS) +import AppKit +#endif + +struct FinishLaunchTestAction { + func callAsFunction() { + AppGraph.shared?.stopProfilingIfNecessary() + #if os(iOS) + UIApplication.shared.finishedTest(UIApplication.shared._launchTestName()) + #else + fatalError("Unimplemented for other platform") + #endif + } +} + +extension EnvironmentValues { + var finishLaunchTest: FinishLaunchTestAction { + FinishLaunchTestAction() + } +} diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift deleted file mode 100644 index 24e01b9..0000000 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/AppGraph.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// AppGraph.swift -// OpenSwiftUI -// -// Created by Kyle on 2023/9/22. -// Lastest Version: iOS 15.5 -// Status: WIP -// ID: A363922CEBDF47986D9772B903C8737A - -#if canImport(Darwin) -@available(watchOS 7.0, *) -final class AppGraph: GraphHost { - init(app _: some App) {} - - static var shared: AppGraph? = nil - static var delegateBox: AnyFallbackDelegateBox? = nil - - func extendedLaunchTestName() -> String? { nil } - - func startProfilingIfNecessary() {} -} -#endif diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/FallbackDelegateBox.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/FallbackDelegateBox.swift index c591247..e120cc6 100644 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/FallbackDelegateBox.swift +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/FallbackDelegateBox.swift @@ -6,7 +6,6 @@ // Lastest Version: iOS 15.5 // Status: WIP -#if canImport(Darwin) import Foundation #if OPENSWIFTUI_OPENCOMBINE import OpenCombine @@ -39,6 +38,10 @@ class FallbackDelegateBox: AnyFallbackDelegateBox { } override var delegate: NSObject? { + // FIXME: error: constructing an object of class type 'Delegate' with a metatype value must use a 'required' initializer + #if !canImport(Darwin) + return nil + #else switch storage { case let .type(type): let delegate = type.init() @@ -47,6 +50,6 @@ class FallbackDelegateBox: AnyFallbackDelegateBox { case let .instance(delegate): return delegate } + #endif } } -#endif diff --git a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift index 7d4beff..d34fd4a 100644 --- a/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift +++ b/Sources/OpenSwiftUI/AppStructure/AppOrganization/TODO/OpenSwiftUIApplication.swift @@ -31,18 +31,14 @@ private final class OpenSwiftUIApplication: NSApplication { import Foundation #endif -@available(watchOS 7.0, *) func runApp(_ app: some App) -> Never { - #if canImport(Darwin) let graph = AppGraph(app: app) graph.startProfilingIfNecessary() -// graph.instantiate() + graph.instantiate() AppGraph.shared = graph - #endif KitRendererCommon() } -@available(watchOS 7.0, *) private func KitRendererCommon() -> Never { let argc = CommandLine.argc let argv = CommandLine.unsafeArgv diff --git a/Sources/OpenSwiftUI/EventHandling/InputEvents/KeyboardShortcut/EventModifiers.swift b/Sources/OpenSwiftUI/EventHandling/InputEvents/KeyboardShortcut/EventModifiers.swift index a5e8655..b8c060b 100644 --- a/Sources/OpenSwiftUI/EventHandling/InputEvents/KeyboardShortcut/EventModifiers.swift +++ b/Sources/OpenSwiftUI/EventHandling/InputEvents/KeyboardShortcut/EventModifiers.swift @@ -6,7 +6,6 @@ // Lastest Version: iOS 15.5 // Status: Complete -@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) @frozen public struct EventModifiers: OptionSet { public let rawValue: Int public init(rawValue: Int) { diff --git a/Sources/OpenSwiftUI/Internal/Graph/GraphDelegate.swift b/Sources/OpenSwiftUI/Internal/Graph/GraphDelegate.swift new file mode 100644 index 0000000..0ab76db --- /dev/null +++ b/Sources/OpenSwiftUI/Internal/Graph/GraphDelegate.swift @@ -0,0 +1,13 @@ +// +// GraphDelegate.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/2/26. +// Lastest Version: iOS 15.5 +// Status: Complete + +protocol GraphDelegate: AnyObject { + func updateGraph(body: (GraphHost) -> V) -> V + func graphDidChange() + func preferencesDidChange() +} diff --git a/Sources/OpenSwiftUI/Internal/Graph/GraphHost.swift b/Sources/OpenSwiftUI/Internal/Graph/GraphHost.swift index fab39cf..476179e 100644 --- a/Sources/OpenSwiftUI/Internal/Graph/GraphHost.swift +++ b/Sources/OpenSwiftUI/Internal/Graph/GraphHost.swift @@ -3,21 +3,50 @@ internal import OpenGraphShims class GraphHost { - -// var data: Data -// var isInstantiated: Swift.Bool + var data: Data + var isInstantiated: Bool // var hostPreferenceValues: OptionalAttribute // var lastHostPreferencesSeed: VersionSeed -// var pendingTransactions: [SwiftUI.(AsyncTransaction in _30C09FF16BC95EC5173809B57186CAC3)] +// var pendingTransactions: [AsyncTransaction] // var inTransaction: Bool // var continuations: [() -> ()] // var mayDeferUpdate: Bool // var removedState: RemovedState + // FIXME static var isUpdating = false + + // private static let shared = OGGraphCreate() + // MARK: - non final methods -// private static let shared = OGGraphCreate() + init(data: Data) { + self.data = data + isInstantiated = false + // TODO + } + + func invalidate() { + // TODO + } + + var graphDelegate: GraphDelegate? { nil } + var parentHost: GraphHost? { nil } + func instantiateOutputs() {} + func uninstantiateOutputs() {} + func timeDidChange() {} + func isHiddenForReuseDidChange() {} + + // MARK: - final methods + + final func instantiate() { + guard !isInstantiated else { + return + } + graphDelegate?.updateGraph { _ in } + instantiateOutputs() + isInstantiated = true + } } // MARK: - GraphHost.Data @@ -40,6 +69,10 @@ extension GraphHost { @Attribute var transaction: Transaction var inputs: _GraphInputs + + init() { + fatalError("TODO") + } } } diff --git a/Sources/OpenSwiftUI/Test/_PerformanceTest.swift b/Sources/OpenSwiftUI/Test/_PerformanceTest.swift index 76a19e4..1c08019 100644 --- a/Sources/OpenSwiftUI/Test/_PerformanceTest.swift +++ b/Sources/OpenSwiftUI/Test/_PerformanceTest.swift @@ -35,24 +35,30 @@ extension _BenchmarkHost { public func _started(test: _PerformanceTest) { #if os(iOS) UIApplication.shared.startedTest(test.name) + #elseif os(macOS) + NSApplication.shared.startedTest(test.name) #else - fatalError("TODO") + fatalError("Unimplemented for other platform") #endif } public func _finished(test: _PerformanceTest) { #if os(iOS) UIApplication.shared.finishedTest(test.name) + #elseif os(macOS) + NSApplication.shared.finishedTest(test.name) #else - fatalError("TODO") + fatalError("Unimplemented for other platform") #endif } public func _failed(test: _PerformanceTest) { #if os(iOS) UIApplication.shared.failedTest(test.name, withFailure: nil) + #elseif os(macOS) + NSApplication.shared.failedTest(test.name, withFailure: nil) #else - fatalError("TODO") + fatalError("Unimplemented for other platform") #endif } } diff --git a/Sources/OpenSwiftUI/Views/View/Extension/View_Font.swift b/Sources/OpenSwiftUI/Views/View/Extension/View_Font.swift index ab10071..36651fb 100644 --- a/Sources/OpenSwiftUI/Views/View/Extension/View_Font.swift +++ b/Sources/OpenSwiftUI/Views/View/Extension/View_Font.swift @@ -53,7 +53,6 @@ extension View { } } -@available(iOS 13.0, *) extension View { @inline(__always) func defaultFont(_ font: Font?) -> some View { diff --git a/Sources/OpenSwiftUIShims/include/OpenSwiftUI_SPI.h b/Sources/OpenSwiftUIShims/include/OpenSwiftUI_SPI.h index 5ca9230..200a61c 100644 --- a/Sources/OpenSwiftUIShims/include/OpenSwiftUI_SPI.h +++ b/Sources/OpenSwiftUIShims/include/OpenSwiftUI_SPI.h @@ -14,9 +14,15 @@ - (void)startedTest:(nullable NSString *)name; - (void)finishedTest:(nullable NSString *)name; - (void)failedTest:(nullable NSString *)name withFailure:(nullable NSError*)failure; +- (nullable NSString *)_launchTestName; +@end +#elif __has_include() +#import +@interface NSApplication (OpenSwiftUI_SPI) +- (void)startedTest:(nullable NSString *)name; +- (void)finishedTest:(nullable NSString *)name; +- (void)failedTest:(nullable NSString *)name withFailure:(nullable NSError*)failure; @end -#else - #endif #endif /* OpenSwiftUI_SPI_h */