From d4253f09a6b06507282e641e9272041baead4a10 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Thu, 29 Jun 2023 16:05:55 +0100 Subject: [PATCH 1/6] wip --- Sources/PlatformVersion.swift | 132 ++++++++++++++++++-------------- Tests/Tests/PlatformTests.swift | 2 +- 2 files changed, 75 insertions(+), 59 deletions(-) diff --git a/Sources/PlatformVersion.swift b/Sources/PlatformVersion.swift index 194b5974..25f5af0c 100644 --- a/Sources/PlatformVersion.swift +++ b/Sources/PlatformVersion.swift @@ -1,195 +1,211 @@ import Foundation +public enum PlatformVersionCondition { + case past + case current + case future +} + public protocol PlatformVersion { - var isCurrent: Bool { get } + var condition: PlatformVersionCondition { get } +} + +extension PlatformVersion { + var isCurrent: Bool { + condition == .current + } + + var isCurrentOrPast: Bool { + condition == .current || condition == .past + } } public struct iOSVersion: PlatformVersion { - public let isCurrent: Bool + public let condition: PlatformVersionCondition - public init(isCurrent: () -> Bool) { - self.isCurrent = isCurrent() + public init(condition: () -> PlatformVersionCondition) { + self.condition = condition() } } extension iOSVersion { public static let v13 = iOSVersion { if #available(iOS 14, *) { - return false + return .past } if #available(iOS 13, *) { - return true + return .current } - return false + return .future } public static let v14 = iOSVersion { if #available(iOS 15, *) { - return false + return .past } if #available(iOS 14, *) { - return true + return .current } - return false + return .future } public static let v15 = iOSVersion { if #available(iOS 16, *) { - return false + return .past } if #available(iOS 15, *) { - return true + return .current } - return false + return .future } public static let v16 = iOSVersion { if #available(iOS 17, *) { - return false + return .past } if #available(iOS 16, *) { - return true + return .current } - return false + return .future } public static let v17 = iOSVersion { if #available(iOS 18, *) { - return false + return .past } if #available(iOS 17, *) { - return true + return .current } - return false + return .future } } public struct tvOSVersion: PlatformVersion { - public let isCurrent: Bool + public let condition: PlatformVersionCondition - public init(isCurrent: () -> Bool) { - self.isCurrent = isCurrent() + public init(condition: () -> PlatformVersionCondition) { + self.condition = condition() } } extension tvOSVersion { public static let v13 = tvOSVersion { if #available(tvOS 14, *) { - return false + return .past } if #available(tvOS 13, *) { - return true + return .current } - return false + return .future } public static let v14 = tvOSVersion { if #available(tvOS 15, *) { - return false + return .past } if #available(tvOS 14, *) { - return true + return .current } - return false + return .future } public static let v15 = tvOSVersion { if #available(tvOS 16, *) { - return false + return .past } if #available(tvOS 15, *) { - return true + return .current } - return false + return .future } public static let v16 = tvOSVersion { if #available(tvOS 17, *) { - return false + return .past } if #available(tvOS 16, *) { - return true + return .current } - return false + return .future } public static let v17 = tvOSVersion { if #available(tvOS 18, *) { - return false + return .past } if #available(tvOS 17, *) { - return true + return .current } - return false + return .future } } public struct macOSVersion: PlatformVersion { - public let isCurrent: Bool + public let condition: PlatformVersionCondition - public init(isCurrent: () -> Bool) { - self.isCurrent = isCurrent() + public init(condition: () -> PlatformVersionCondition) { + self.condition = condition() } } extension macOSVersion { public static let v10_15 = macOSVersion { if #available(macOS 11, *) { - return false + return .past } if #available(macOS 10.15, *) { - return true + return .current } - return false + return .future } public static let v10_15_4 = macOSVersion { if #available(macOS 11, *) { - return false + return .past } if #available(macOS 10.15.4, *) { - return true + return .current } - return false + return .future } public static let v11 = macOSVersion { if #available(macOS 12, *) { - return false + return .past } if #available(macOS 11, *) { - return true + return .current } - return false + return .future } public static let v12 = macOSVersion { if #available(macOS 13, *) { - return false + return .past } if #available(macOS 12, *) { - return true + return .current } - return false + return .future } public static let v13 = macOSVersion { if #available(macOS 14, *) { - return false + return .past } if #available(macOS 13, *) { - return true + return .current } - return false + return .future } public static let v14 = macOSVersion { if #available(macOS 15, *) { - return false + return .past } if #available(macOS 14, *) { - return true + return .current } - return false + return .future } } diff --git a/Tests/Tests/PlatformTests.swift b/Tests/Tests/PlatformTests.swift index 0c736fa3..14436b19 100644 --- a/Tests/Tests/PlatformTests.swift +++ b/Tests/Tests/PlatformTests.swift @@ -1,4 +1,4 @@ -import SwiftUIIntrospect +@testable import SwiftUIIntrospect import XCTest final class PlatformTests: XCTestCase { From fcf24885705780b2bcd925d28e78c4640835b376 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Thu, 29 Jun 2023 16:24:42 +0100 Subject: [PATCH 2/6] wip --- Sources/Introspect.swift | 6 ++-- Sources/IntrospectionSelector.swift | 1 - Sources/PlatformViewVersion.swift | 45 +++++++++++++++++++++++------ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/Sources/Introspect.swift b/Sources/Introspect.swift index 19008a0e..a1baaac5 100644 --- a/Sources/Introspect.swift +++ b/Sources/Introspect.swift @@ -41,7 +41,7 @@ extension View { /// ``` public func introspect( _ viewType: SwiftUIViewType, - on platforms: (PlatformViewVersions)..., + on platforms: (PlatformViewVersionGroup)..., scope: IntrospectionScope? = nil, customize: @escaping (PlatformSpecificEntity) -> Void ) -> some View { @@ -57,12 +57,12 @@ struct IntrospectModifier], + platforms: [PlatformViewVersionGroup], scope: IntrospectionScope?, customize: @escaping (PlatformSpecificEntity) -> Void ) { self.scope = scope ?? viewType.scope - if let platform = platforms.first(where: \.isCurrent) { + if let platform = platforms.first(where: \.containsCurrent) { self.selector = platform.selector ?? .default } else { self.selector = nil diff --git a/Sources/IntrospectionSelector.swift b/Sources/IntrospectionSelector.swift index 3b93efa1..ccb5b09c 100644 --- a/Sources/IntrospectionSelector.swift +++ b/Sources/IntrospectionSelector.swift @@ -1,4 +1,3 @@ -@_spi(Internals) public struct IntrospectionSelector { @_spi(Internals) public static var `default`: Self { .from(Target.self, selector: { $0 }) } diff --git a/Sources/PlatformViewVersion.swift b/Sources/PlatformViewVersion.swift index 9684a552..6faef892 100644 --- a/Sources/PlatformViewVersion.swift +++ b/Sources/PlatformViewVersion.swift @@ -1,17 +1,17 @@ import SwiftUI -public struct PlatformViewVersions { - let isCurrent: Bool +public struct PlatformViewVersionGroup { + let containsCurrent: Bool let selector: IntrospectionSelector? private init( _ versions: [PlatformViewVersion] ) { if let currentVersion = versions.first(where: \.isCurrent) { - self.isCurrent = true + self.containsCurrent = true self.selector = currentVersion.selector } else { - self.isCurrent = false + self.containsCurrent = false self.selector = nil } } @@ -36,14 +36,41 @@ public typealias tvOSViewVersion = PlatformViewVersion -public struct PlatformViewVersion { - let isCurrent: Bool - let selector: IntrospectionSelector? +public enum PlatformViewVersion { + case available(Version, IntrospectionSelector?) + case unavailable + + var isCurrent: Bool { + switch self { + case .available(let version, _): + return version.isCurrent + case .unavailable: + return false + } + } + + var isCurrentOrPast: Bool { + switch self { + case .available(let version, _): + return version.isCurrentOrPast + case .unavailable: + return false + } + } + + var selector: IntrospectionSelector? { + switch self { + case .available(_, let selector): + return selector + case .unavailable: + return nil + } + } } extension PlatformViewVersion { @_spi(Internals) public init(for version: Version, selector: IntrospectionSelector? = nil) { - self.init(isCurrent: version.isCurrent, selector: selector) + self = .available(version, selector) } @_spi(Internals) public static func unavailable(file: StaticString = #file, line: UInt = #line) -> Self { @@ -60,6 +87,6 @@ extension PlatformViewVersion { https://github.com/siteline/swiftui-introspect/issues/new?title=`\(fileName):\(line)`+should+be+marked+unavailable """ ) - return Self(isCurrent: false, selector: nil) + return .unavailable } } From 2c572aa951144408e05297d600d77bb774b6c2e6 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Thu, 29 Jun 2023 16:29:11 +0100 Subject: [PATCH 3/6] wip --- Sources/Introspect.swift | 29 +++++++++++++++++++++++++++-- Sources/PlatformViewVersion.swift | 30 ++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/Sources/Introspect.swift b/Sources/Introspect.swift index a1baaac5..d4e4c24b 100644 --- a/Sources/Introspect.swift +++ b/Sources/Introspect.swift @@ -45,7 +45,17 @@ extension View { scope: IntrospectionScope? = nil, customize: @escaping (PlatformSpecificEntity) -> Void ) -> some View { - self.modifier(IntrospectModifier(viewType, platforms: platforms, scope: scope, customize: customize)) + self.modifier(IntrospectModifier(viewType, on: platforms, scope: scope, customize: customize)) + } + + @_spi(Advanced) + public func introspect( + _ viewType: SwiftUIViewType, + onOrAfter platforms: (PlatformViewVersionSingle)..., + scope: IntrospectionScope? = nil, + customize: @escaping (PlatformSpecificEntity) -> Void + ) -> some View { + self.modifier(IntrospectModifier(viewType, onOrAfter: platforms, scope: scope, customize: customize)) } } @@ -57,7 +67,7 @@ struct IntrospectModifier], + on platforms: [PlatformViewVersionGroup], scope: IntrospectionScope?, customize: @escaping (PlatformSpecificEntity) -> Void ) { @@ -70,6 +80,21 @@ struct IntrospectModifier], + scope: IntrospectionScope?, + customize: @escaping (PlatformSpecificEntity) -> Void + ) { + self.scope = scope ?? viewType.scope + if let platform = platforms.first(where: \.isCurrentOrPast) { + self.selector = platform.selector ?? .default + } else { + self.selector = nil + } + self.customize = customize + } + func body(content: Content) -> some View { if let selector { content diff --git a/Sources/PlatformViewVersion.swift b/Sources/PlatformViewVersion.swift index 6faef892..81cfc15c 100644 --- a/Sources/PlatformViewVersion.swift +++ b/Sources/PlatformViewVersion.swift @@ -29,6 +29,36 @@ public struct PlatformViewVersionGroup { + let isCurrentOrPast: Bool + let selector: IntrospectionSelector? + + private init( + _ version: PlatformViewVersion + ) { + if version.isCurrentOrPast { + self.isCurrentOrPast = true + self.selector = version.selector + } else { + self.isCurrentOrPast = false + self.selector = nil + } + } + + public static func iOS(_ version: iOSViewVersion) -> Self { + Self(version) + } + + public static func tvOS(_ version: tvOSViewVersion) -> Self { + Self(version) + } + + public static func macOS(_ version: macOSViewVersion) -> Self { + Self(version) + } +} + public typealias iOSViewVersion = PlatformViewVersion public typealias tvOSViewVersion = From ab5da451929e3901d60ad7db3184ad549c4aa87e Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Thu, 29 Jun 2023 16:33:09 +0100 Subject: [PATCH 4/6] wip --- Sources/IntrospectionSelector.swift | 1 + Sources/PlatformViewVersion.swift | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Sources/IntrospectionSelector.swift b/Sources/IntrospectionSelector.swift index ccb5b09c..3b93efa1 100644 --- a/Sources/IntrospectionSelector.swift +++ b/Sources/IntrospectionSelector.swift @@ -1,3 +1,4 @@ +@_spi(Internals) public struct IntrospectionSelector { @_spi(Internals) public static var `default`: Self { .from(Target.self, selector: { $0 }) } diff --git a/Sources/PlatformViewVersion.swift b/Sources/PlatformViewVersion.swift index 81cfc15c..ba996c19 100644 --- a/Sources/PlatformViewVersion.swift +++ b/Sources/PlatformViewVersion.swift @@ -67,8 +67,8 @@ public typealias macOSViewVersion public enum PlatformViewVersion { - case available(Version, IntrospectionSelector?) - case unavailable + @_spi(Private) case available(Version, IntrospectionSelector?) + @_spi(Private) case unavailable var isCurrent: Bool { switch self { From db79feb8b703daa209dc538a9f448ffceaaeac05 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Thu, 29 Jun 2023 16:33:54 +0100 Subject: [PATCH 5/6] wip --- Tests/Tests.xcodeproj/project.pbxproj | 12 ++++++------ ...latformTests.swift => PlatformVersionTests.swift} | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) rename Tests/Tests/{PlatformTests.swift => PlatformVersionTests.swift} (99%) diff --git a/Tests/Tests.xcodeproj/project.pbxproj b/Tests/Tests.xcodeproj/project.pbxproj index 0c191f36..1c1de178 100644 --- a/Tests/Tests.xcodeproj/project.pbxproj +++ b/Tests/Tests.xcodeproj/project.pbxproj @@ -38,7 +38,7 @@ D50E2F782A2B9F6600BAFB03 /* StepperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58119D12A23A77C0081F853 /* StepperTests.swift */; }; D50E2F792A2B9F6600BAFB03 /* ColorPickerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58119D92A23B7700081F853 /* ColorPickerTests.swift */; }; D50E2F7A2A2B9F6600BAFB03 /* ToggleWithButtonStyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D575068D2A27D4DC00A628E4 /* ToggleWithButtonStyleTests.swift */; }; - D50E2F7B2A2B9F6600BAFB03 /* PlatformTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F0BE6729C0DC4900AD95AB /* PlatformTests.swift */; }; + D50E2F7B2A2B9F6600BAFB03 /* PlatformVersionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F0BE6729C0DC4900AD95AB /* PlatformVersionTests.swift */; }; D50E2F7C2A2B9F6600BAFB03 /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58CE15729C621DD0081BFB0 /* TestUtils.swift */; }; D50E2F7D2A2B9F6600BAFB03 /* PickerWithSegmentedStyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57506772A27BBBD00A628E4 /* PickerWithSegmentedStyleTests.swift */; }; D50E2F7E2A2B9F6600BAFB03 /* TabViewWithPageStyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58119CD2A23A4A70081F853 /* TabViewWithPageStyleTests.swift */; }; @@ -109,7 +109,7 @@ D5ADFAD72A4A4653009494FD /* PopoverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5ADFACF2A4A3E54009494FD /* PopoverTests.swift */; }; D5B67B842A0D318F007D5D9B /* TextFieldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B67B832A0D318F007D5D9B /* TextFieldTests.swift */; }; D5F0BE4D29C0DBE800AD95AB /* TestsHostApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F0BE4C29C0DBE800AD95AB /* TestsHostApp.swift */; }; - D5F0BE6A29C0DC4900AD95AB /* PlatformTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F0BE6729C0DC4900AD95AB /* PlatformTests.swift */; }; + D5F0BE6A29C0DC4900AD95AB /* PlatformVersionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F0BE6729C0DC4900AD95AB /* PlatformVersionTests.swift */; }; D5F8D5ED2A1E7B490054E9AB /* NavigationViewWithStackStyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F8D5EC2A1E7B490054E9AB /* NavigationViewWithStackStyleTests.swift */; }; D5F8D5EF2A1E87950054E9AB /* NavigationViewWithColumnsStyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F8D5EE2A1E87950054E9AB /* NavigationViewWithColumnsStyleTests.swift */; }; /* End PBXBuildFile section */ @@ -193,7 +193,7 @@ D5F0BE4929C0DBE800AD95AB /* TestsHostApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestsHostApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; D5F0BE4C29C0DBE800AD95AB /* TestsHostApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestsHostApp.swift; sourceTree = ""; }; D5F0BE5D29C0DC0000AD95AB /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - D5F0BE6729C0DC4900AD95AB /* PlatformTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlatformTests.swift; sourceTree = ""; }; + D5F0BE6729C0DC4900AD95AB /* PlatformVersionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlatformVersionTests.swift; sourceTree = ""; }; D5F8D5EC2A1E7B490054E9AB /* NavigationViewWithStackStyleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationViewWithStackStyleTests.swift; sourceTree = ""; }; D5F8D5EE2A1E87950054E9AB /* NavigationViewWithColumnsStyleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationViewWithColumnsStyleTests.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -330,7 +330,7 @@ isa = PBXGroup; children = ( D5B67B852A0D3193007D5D9B /* ViewTypes */, - D5F0BE6729C0DC4900AD95AB /* PlatformTests.swift */, + D5F0BE6729C0DC4900AD95AB /* PlatformVersionTests.swift */, D58CE15729C621DD0081BFB0 /* TestUtils.swift */, ); path = Tests; @@ -545,7 +545,7 @@ D50E2F782A2B9F6600BAFB03 /* StepperTests.swift in Sources */, D50E2F792A2B9F6600BAFB03 /* ColorPickerTests.swift in Sources */, D50E2F7A2A2B9F6600BAFB03 /* ToggleWithButtonStyleTests.swift in Sources */, - D50E2F7B2A2B9F6600BAFB03 /* PlatformTests.swift in Sources */, + D50E2F7B2A2B9F6600BAFB03 /* PlatformVersionTests.swift in Sources */, D50E2F7C2A2B9F6600BAFB03 /* TestUtils.swift in Sources */, D50E2F7D2A2B9F6600BAFB03 /* PickerWithSegmentedStyleTests.swift in Sources */, D50E2F7E2A2B9F6600BAFB03 /* TabViewWithPageStyleTests.swift in Sources */, @@ -610,7 +610,7 @@ D5ADFAD22A4A41CB009494FD /* SignInWithAppleButtonTests.swift in Sources */, D58119DA2A23B7700081F853 /* ColorPickerTests.swift in Sources */, D575068E2A27D4DC00A628E4 /* ToggleWithButtonStyleTests.swift in Sources */, - D5F0BE6A29C0DC4900AD95AB /* PlatformTests.swift in Sources */, + D5F0BE6A29C0DC4900AD95AB /* PlatformVersionTests.swift in Sources */, D58CE15829C621DD0081BFB0 /* TestUtils.swift in Sources */, D57506782A27BBBD00A628E4 /* PickerWithSegmentedStyleTests.swift in Sources */, D58119CE2A23A4A70081F853 /* TabViewWithPageStyleTests.swift in Sources */, diff --git a/Tests/Tests/PlatformTests.swift b/Tests/Tests/PlatformVersionTests.swift similarity index 99% rename from Tests/Tests/PlatformTests.swift rename to Tests/Tests/PlatformVersionTests.swift index 14436b19..e8973128 100644 --- a/Tests/Tests/PlatformTests.swift +++ b/Tests/Tests/PlatformVersionTests.swift @@ -1,7 +1,7 @@ @testable import SwiftUIIntrospect import XCTest -final class PlatformTests: XCTestCase { +final class PlatformVersionTests: XCTestCase { func test_iOS() { #if os(iOS) if #available(iOS 17, *) { From 8f35c98e7e8dc9960fa67e8545b5008ae86b9285 Mon Sep 17 00:00:00 2001 From: David Roman <2538074+davdroman@users.noreply.github.com> Date: Thu, 29 Jun 2023 16:48:52 +0100 Subject: [PATCH 6/6] wip --- Sources/PlatformVersion.swift | 4 ++-- Tests/Tests/PlatformVersionTests.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/PlatformVersion.swift b/Sources/PlatformVersion.swift index 25f5af0c..99191629 100644 --- a/Sources/PlatformVersion.swift +++ b/Sources/PlatformVersion.swift @@ -11,11 +11,11 @@ public protocol PlatformVersion { } extension PlatformVersion { - var isCurrent: Bool { + public var isCurrent: Bool { condition == .current } - var isCurrentOrPast: Bool { + public var isCurrentOrPast: Bool { condition == .current || condition == .past } } diff --git a/Tests/Tests/PlatformVersionTests.swift b/Tests/Tests/PlatformVersionTests.swift index e8973128..a4914246 100644 --- a/Tests/Tests/PlatformVersionTests.swift +++ b/Tests/Tests/PlatformVersionTests.swift @@ -1,4 +1,4 @@ -@testable import SwiftUIIntrospect +import SwiftUIIntrospect import XCTest final class PlatformVersionTests: XCTestCase {