diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 6aa026e..355ebe9 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -18,10 +18,10 @@ jobs: fail-fast: false matrix: include: - - xcode: "Xcode_15.0.1" - runsOn: macos-13 - - xcode: "Xcode_14.3.1" - runsOn: macos-13 + - xcode: "Xcode_16.0" + runsOn: macos-15 + - xcode: "Xcode_15.4" + runsOn: macos-14 steps: - uses: actions/checkout@v4 - name: Select Xcode diff --git a/Binaries/PrefireBinary.artifactbundle/prefire-3.0.1-macos/bin/prefire b/Binaries/PrefireBinary.artifactbundle/prefire-3.0.1-macos/bin/prefire index 568966b..e3cce35 100755 Binary files a/Binaries/PrefireBinary.artifactbundle/prefire-3.0.1-macos/bin/prefire and b/Binaries/PrefireBinary.artifactbundle/prefire-3.0.1-macos/bin/prefire differ diff --git a/Package.swift b/Package.swift index 33764a5..d349621 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.8 +// swift-tools-version: 6.0 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription diff --git a/Package@swift-5.10.swift b/Package@swift-5.10.swift new file mode 100644 index 0000000..01f0315 --- /dev/null +++ b/Package@swift-5.10.swift @@ -0,0 +1,53 @@ +// swift-tools-version: 5.10 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Prefire", + platforms: [.iOS(.v14)], + products: [ + .library( + name: "Prefire", + targets: ["Prefire"] + ), + .plugin( + name: "PrefirePlaybookPlugin", + targets: ["PrefirePlaybookPlugin"] + ), + .plugin( + name: "PrefireTestsPlugin", + targets: ["PrefireTestsPlugin"] + ), + ], + targets: [ + .target( + name: "Prefire", + dependencies: [] + ), + .plugin( + name: "PrefirePlaybookPlugin", + capability: .buildTool(), + dependencies: [ + "PrefireBinary", + "PrefireSourcery", + ] + ), + .plugin( + name: "PrefireTestsPlugin", + capability: .buildTool(), + dependencies: [ + "PrefireBinary", + "PrefireSourcery", + ] + ), + .binaryTarget( + name: "PrefireBinary", + path: "Binaries/PrefireBinary.artifactbundle" + ), + .binaryTarget( + name: "PrefireSourcery", + path: "PrefireExecutable/Binaries/PrefireSourcery.artifactbundle" + ), + ] +) diff --git a/PrefireExecutable/Sources/prefire/Previews/PreviewLoader+Playbook.swift b/PrefireExecutable/Sources/prefire/Previews/PreviewLoader+Playbook.swift index b346410..56995db 100644 --- a/PrefireExecutable/Sources/prefire/Previews/PreviewLoader+Playbook.swift +++ b/PrefireExecutable/Sources/prefire/Previews/PreviewLoader+Playbook.swift @@ -18,6 +18,7 @@ extension PreviewLoader { return yamlSettings + """ + @MainActor private struct MacroPreviews { static var previews: [PreviewModel] = [ \(previewModels) diff --git a/Sources/Prefire/Playbook/PlaybookView.swift b/Sources/Prefire/Playbook/PlaybookView.swift index 646c3cd..b5602bc 100644 --- a/Sources/Prefire/Playbook/PlaybookView.swift +++ b/Sources/Prefire/Playbook/PlaybookView.swift @@ -4,8 +4,8 @@ import SwiftUI extension CGFloat { static let scale: CGFloat = 0.55 static let infoViewHeight: CGFloat = 42 - static let screenHeight = UIScreen.main.bounds.height - static let screeenWidth = UIScreen.main.bounds.width + @MainActor static let screenHeight = UIScreen.main.bounds.height + @MainActor static let screenWidth = UIScreen.main.bounds.width } /// View to show different states of components and screens @@ -78,7 +78,7 @@ public struct PlaybookView: View { private func componentList(for name: String) -> some View { ScrollView(.horizontal, showsIndicators: false) { HStack(alignment: .top, spacing: 16) { - ForEach($viewModels) { $viewModel in + ForEach($viewModels, id: \.id) { $viewModel in if viewModel.name == name || viewModel.story == name { VStack { if !isComponent { @@ -102,10 +102,7 @@ public struct PlaybookView: View { } struct PreviewView: View, Identifiable { - @inlinable - var id: String { - viewModel.id - } + let id: String let isComponent: Bool @@ -116,6 +113,16 @@ public struct PlaybookView: View { @Binding var sectionNames: [String] @Environment(\.colorScheme) private var colorScheme + init(isComponent: Bool, selectedId: Binding, navigationLinkTriggered: Binding, viewModel: Binding, viewModels: Binding<[PreviewModel]>, sectionNames: Binding<[String]>) { + self.id = viewModel.wrappedValue.id + self.isComponent = isComponent + _selectedId = selectedId + _navigationLinkTriggered = navigationLinkTriggered + _viewModel = viewModel + _viewModels = viewModels + _sectionNames = sectionNames + } + var body: some View { Button(action: { selectedId = viewModel.id @@ -160,12 +167,13 @@ public struct PlaybookView: View { let id: String let isScreen: Bool var view: Content - @Environment(\.safeAreaInsets) private var safeAreaInsets + + @State private var safeAreaInsets = UIApplication.shared.windows.first?.safeAreaInsets ?? UIEdgeInsets() var body: some View { view .allowsHitTesting(false) - .frame(width: .screeenWidth) + .frame(width: .screenWidth) .transformIf(isScreen) { view in view.frame(height: .screenHeight - safeAreaInsets.top + safeAreaInsets.bottom - .infoViewHeight) } diff --git a/Sources/Prefire/Playbook/SafeAreaEnviroment.swift b/Sources/Prefire/Playbook/SafeAreaEnviroment.swift deleted file mode 100644 index 9669d61..0000000 --- a/Sources/Prefire/Playbook/SafeAreaEnviroment.swift +++ /dev/null @@ -1,19 +0,0 @@ -import SwiftUI - -private struct SafeAreaInsetsKey: EnvironmentKey { - static var defaultValue: EdgeInsets { - UIApplication.shared.windows.first?.safeAreaInsets.swiftUiInsets ?? EdgeInsets() - } -} - -public extension EnvironmentValues { - var safeAreaInsets: EdgeInsets { - self[SafeAreaInsetsKey.self] - } -} - -private extension UIEdgeInsets { - var swiftUiInsets: EdgeInsets { - EdgeInsets(top: top, leading: left, bottom: bottom, trailing: right) - } -} diff --git a/Sources/Prefire/Preview/PreferenceKeys.swift b/Sources/Prefire/Preview/PreferenceKeys.swift index 3d31b8d..673e1d4 100644 --- a/Sources/Prefire/Preview/PreferenceKeys.swift +++ b/Sources/Prefire/Preview/PreferenceKeys.swift @@ -1,7 +1,7 @@ import SwiftUI public struct UserStoryPreferenceKey: PreferenceKey { - public static var defaultValue: PreviewModel.UserStory? + public static let defaultValue: PreviewModel.UserStory? = nil public static func reduce(value: inout PreviewModel.UserStory?, nextValue: () -> PreviewModel.UserStory?) { value = nextValue() @@ -22,7 +22,7 @@ public extension View { // MARK: - State public struct StatePreferenceKey: PreferenceKey { - public static var defaultValue: PreviewModel.State? + public static let defaultValue: PreviewModel.State? = nil public static func reduce(value: inout PreviewModel.State?, nextValue: () -> PreviewModel.State?) { value = nextValue() @@ -43,7 +43,7 @@ public extension View { // MARK: - Snapshot Attributes public struct DelayPreferenceKey: PreferenceKey { - public static var defaultValue: TimeInterval = 0.0 + public static let defaultValue: TimeInterval = 0.0 public static func reduce(value: inout TimeInterval, nextValue: () -> TimeInterval) { value = nextValue() @@ -51,7 +51,7 @@ public struct DelayPreferenceKey: PreferenceKey { } public struct PrecisionPreferenceKey: PreferenceKey { - public static var defaultValue: Float = 1.0 + public static let defaultValue: Float = 1.0 public static func reduce(value: inout Float, nextValue: () -> Float) { value = nextValue() @@ -59,7 +59,7 @@ public struct PrecisionPreferenceKey: PreferenceKey { } public struct PerceptualPrecisionPreferenceKey: PreferenceKey { - public static var defaultValue: Float = 1.0 + public static let defaultValue: Float = 1.0 public static func reduce(value: inout Float, nextValue: () -> Float) { value = nextValue() diff --git a/Sources/Prefire/Preview/PreviewModel.swift b/Sources/Prefire/Preview/PreviewModel.swift index 58a7a14..f4a4623 100644 --- a/Sources/Prefire/Preview/PreviewModel.swift +++ b/Sources/Prefire/Preview/PreviewModel.swift @@ -52,6 +52,7 @@ public struct PreviewModel: Identifiable { /// The time from when a view was created (`.init`) to when it was shown (`.onAppear`) public var renderTime: String? + @MainActor public init( id: String? = nil, content: @escaping () -> any View, @@ -66,6 +67,7 @@ public struct PreviewModel: Identifiable { self.device = device } + @MainActor public init( id: String? = nil, content: @escaping () -> UIView, @@ -76,6 +78,7 @@ public struct PreviewModel: Identifiable { self.init(id: id, content: { AnyView(ViewRepresentable(view: content())) }, name: name, type: type, device: device) } + @MainActor public init( id: String? = nil, content: @escaping () -> UIViewController, diff --git a/Templates/PreviewModels.stencil b/Templates/PreviewModels.stencil index 48ae80d..64f6b78 100644 --- a/Templates/PreviewModels.stencil +++ b/Templates/PreviewModels.stencil @@ -11,6 +11,7 @@ import {{ import }} {% endfor %} public enum PreviewModels { + @MainActor public static var models: [PreviewModel] = { var views: [PreviewModel] = [] #if !PLAYBOOK_DISABLED @@ -28,6 +29,7 @@ public enum PreviewModels { }() @inlinable + @MainActor static func createModel(for preview: Preview.Type, name: String) -> [PreviewModel] { var views: [PreviewModel] = [] diff --git a/Templates/PreviewTests.stencil b/Templates/PreviewTests.stencil index 3141ff1..20d0ff1 100644 --- a/Templates/PreviewTests.stencil +++ b/Templates/PreviewTests.stencil @@ -116,12 +116,12 @@ class PreviewTests: XCTestCase { #if canImport(AccessibilitySnapshot) let vc = UIHostingController(rootView: matchingView) vc.view.frame = UIScreen.main.bounds - assertSnapshot( + + SnapshotTesting.assertSnapshot( matching: vc, - as: .wait(for: delay, on: .accessibilityImage(showActivationPoints: .always)), - named: prefireSnapshot.name.flatMap { $0 + ".accessibility" }{% if argument.file %}, + as: .wait(for: delay, on: .accessibilityImage(showActivationPoints: .always)){% if argument.file %}, file: file{% endif %}, - testName: prefireSnapshot.name + testName: prefireSnapshot.name + ".accessibility" ) #endif return failure