From 69b085705f2af4c5dfe93278a228c12caa6c3379 Mon Sep 17 00:00:00 2001 From: Andreas Bauer Date: Wed, 18 Dec 2024 09:08:07 +0100 Subject: [PATCH] Add InfoButton for list rows (#50) # Add InfoButton for list rows ## :recycle: Current situation & Problem This PR adds a new icon-only `InfoButton` that is useful in List views to provide additional context to a row element. ## :gear: Release Notes * Added new `InfoButton`. ## :books: Documentation Added the new button to the documentation catalog. ## :white_check_mark: Testing Tested via UI tests. ## :pencil: Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md): - [x] I agree to follow the [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md). --- Package.swift | 2 +- .../SpeziValidation/ValidationEngine.swift | 10 +- .../CapturedValidationState.swift | 9 +- .../ReceiveValidationModifier.swift | 18 ++- .../SpeziViews/SpeziViews.docc/SpeziViews.md | 2 + .../SpeziViews/Views/Button/InfoButton.swift | 69 ++++++++++++ .../Views/Controls/CaseIterablePicker.swift | 2 +- .../SpeziViews/Views/List/ListHeader.swift | 105 ++++++++++++++++++ Tests/SpeziViewsTests/SnapshotTests.swift | 18 +++ ...estListHeader.list-header-instructions.png | Bin 0 -> 91480 bytes .../testListHeader.list-header.png | Bin 0 -> 76128 bytes Tests/UITests/TestApp/Localizable.xcstrings | 6 + ...tonTestView.swift => ButtonTestView.swift} | 21 +++- .../TestApp/ViewsTests/SpeziViewsTests.swift | 10 +- .../SpeziViews/ViewsTests.swift | 14 ++- .../UITests/UITests.xcodeproj/project.pbxproj | 12 +- 16 files changed, 267 insertions(+), 31 deletions(-) create mode 100644 Sources/SpeziViews/Views/Button/InfoButton.swift create mode 100644 Sources/SpeziViews/Views/List/ListHeader.swift create mode 100644 Tests/SpeziViewsTests/__Snapshots__/SnapshotTests/testListHeader.list-header-instructions.png create mode 100644 Tests/SpeziViewsTests/__Snapshots__/SnapshotTests/testListHeader.list-header.png rename Tests/UITests/TestApp/ViewsTests/{AsyncButtonTestView.swift => ButtonTestView.swift} (72%) diff --git a/Package.swift b/Package.swift index 340b1a2..9b618ea 100644 --- a/Package.swift +++ b/Package.swift @@ -28,7 +28,7 @@ let package = Package( .library(name: "SpeziValidation", targets: ["SpeziValidation"]) ], dependencies: [ - .package(url: "https://github.com/StanfordSpezi/Spezi.git", from: "1.3.0"), + .package(url: "https://github.com/StanfordSpezi/Spezi.git", from: "1.8.0"), .package(url: "https://github.com/apple/swift-collections.git", from: "1.1.0"), .package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git", from: "1.17.0") ] + swiftLintPackage(), diff --git a/Sources/SpeziValidation/ValidationEngine.swift b/Sources/SpeziValidation/ValidationEngine.swift index 776995f..5b89ec2 100644 --- a/Sources/SpeziValidation/ValidationEngine.swift +++ b/Sources/SpeziValidation/ValidationEngine.swift @@ -17,7 +17,8 @@ import SwiftUI /// processed input and a the respective recovery suggestions for failed ``ValidationRule``s. /// The state of the `ValidationEngine` is updated on each invocation of ``runValidation(input:)`` or ``submit(input:debounce:)``. @Observable -public class ValidationEngine: Identifiable { +@MainActor +public final class ValidationEngine: Identifiable { /// Determines the source of the last validation run. private enum Source: Equatable { /// The last validation was run due to change in text field or keyboard submit. @@ -31,7 +32,7 @@ public class ValidationEngine: Identifiable { /// Unique identifier for this validation engine. - public var id: ObjectIdentifier { + public nonisolated var id: ObjectIdentifier { ObjectIdentifier(self) } @@ -134,7 +135,6 @@ public class ValidationEngine: Identifiable { self.init(rules: validationRules, debounceFor: debounceDuration, configuration: configuration) } - @MainActor private func computeFailedValidations(input: String) -> [FailedValidationResult] { var results: [FailedValidationResult] = [] @@ -153,7 +153,6 @@ public class ValidationEngine: Identifiable { } - @MainActor private func computeValidation(input: String, source: Source) { self.source = source self.inputWasEmpty = input.isEmpty @@ -174,7 +173,6 @@ public class ValidationEngine: Identifiable { /// there not further calls to this method for the configured `debounceDuration`. If set to `false` the method /// will run immediately. Note that the validation will still run instantly, if we are currently in an invalid state /// to ensure input validity is reported immediately. - @MainActor public func submit(input: String, debounce: Bool = false) { if !debounce || computedInputValid == false { // we compute instantly, if debounce is false or if we are in a invalid state @@ -191,12 +189,10 @@ public class ValidationEngine: Identifiable { /// /// The input is considered valid if all ``ValidationRule``s succeed. /// - Parameter input: The input to validate. - @MainActor public func runValidation(input: String) { computeValidation(input: input, source: .manual) } - @MainActor private func debounce(_ task: @escaping () -> Void) { debounceTask = Task { try? await Task.sleep(for: debounceDuration) diff --git a/Sources/SpeziValidation/ValidationState/CapturedValidationState.swift b/Sources/SpeziValidation/ValidationState/CapturedValidationState.swift index c3a52c0..96dee1d 100644 --- a/Sources/SpeziValidation/ValidationState/CapturedValidationState.swift +++ b/Sources/SpeziValidation/ValidationState/CapturedValidationState.swift @@ -16,9 +16,10 @@ import SwiftUI /// /// This particularly allows to run a validation from the outside of a view. @dynamicMemberLookup +@MainActor public struct CapturedValidationState { - private let engine: ValidationEngine - private let input: String + private nonisolated let engine: ValidationEngine + private nonisolated let input: String private let focusState: FocusState.Binding init(engine: ValidationEngine, input: String, focus focusState: FocusState.Binding) { @@ -46,8 +47,8 @@ public struct CapturedValidationState { } -extension CapturedValidationState: Equatable { - public static func == (lhs: CapturedValidationState, rhs: CapturedValidationState) -> Bool { +extension CapturedValidationState: Equatable, Sendable { + public static nonisolated func == (lhs: CapturedValidationState, rhs: CapturedValidationState) -> Bool { lhs.engine === rhs.engine && lhs.input == rhs.input } } diff --git a/Sources/SpeziValidation/ValidationState/ReceiveValidationModifier.swift b/Sources/SpeziValidation/ValidationState/ReceiveValidationModifier.swift index 0c36ee4..9dc3ee0 100644 --- a/Sources/SpeziValidation/ValidationState/ReceiveValidationModifier.swift +++ b/Sources/SpeziValidation/ValidationState/ReceiveValidationModifier.swift @@ -9,6 +9,16 @@ import SwiftUI +@MainActor +private struct IsolatedValidationBinding: Sendable { + let state: ValidationState.Binding + + init(_ state: ValidationState.Binding) { + self.state = state + } +} + + /// Provide access to validation state to the parent view. /// /// The internal preference key to provide parent views access to all configured ``ValidationEngine`` and input @@ -36,8 +46,12 @@ extension View { /// - Parameter state: The binding to the ``ValidationState``. /// - Returns: The modified view. public func receiveValidation(in state: ValidationState.Binding) -> some View { - onPreferenceChange(CapturedValidationStateKey.self) { entries in - state.wrappedValue = ValidationContext(entries: entries) + let binding = IsolatedValidationBinding(state) + + return onPreferenceChange(CapturedValidationStateKey.self) { entries in + Task { @Sendable @MainActor in + binding.state.wrappedValue = ValidationContext(entries: entries) + } } } } diff --git a/Sources/SpeziViews/SpeziViews.docc/SpeziViews.md b/Sources/SpeziViews/SpeziViews.docc/SpeziViews.md index 0363514..e4e331c 100644 --- a/Sources/SpeziViews/SpeziViews.docc/SpeziViews.md +++ b/Sources/SpeziViews/SpeziViews.docc/SpeziViews.md @@ -58,12 +58,14 @@ Default layouts and utilities to automatically adapt your view layouts to dynami - ``DynamicHStack`` - ``ListRow`` - ``DescriptionGridRow`` +- ``ListHeader`` ### Controls - ``AsyncButton`` - ``SwiftUICore/EnvironmentValues/processingDebounceDuration`` - ``CanvasView`` +- ``InfoButton`` - ``DismissButton`` - ``CaseIterablePicker`` diff --git a/Sources/SpeziViews/Views/Button/InfoButton.swift b/Sources/SpeziViews/Views/Button/InfoButton.swift new file mode 100644 index 0000000..dde6133 --- /dev/null +++ b/Sources/SpeziViews/Views/Button/InfoButton.swift @@ -0,0 +1,69 @@ +// +// This source file is part of the Stanford Spezi open-source project +// +// SPDX-FileCopyrightText: 2024 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +/// Icon-only info button. +/// +/// You can use this button, e.g., on the trailing side of a list row to provide additional information about an entity. +public struct InfoButton: View { + private let label: Text + private let action: () -> Void + + public var body: some View { + Button(action: action) { + SwiftUI.Label { + label + } icon: { + Image(systemName: "info.circle") // swiftlint:disable:this accessibility_label_for_image + } + } + .labelStyle(.iconOnly) + .font(.title3) + .foregroundColor(.accentColor) + .buttonStyle(.borderless) // ensure button is clickable next to the other button + .accessibilityIdentifier("info-button") + .accessibilityAction(named: label, action) + } + + /// Create a new info button. + /// - Parameters: + /// - label: The text label. This is not shown but useful for accessibility. + /// - action: The button action. + public init(_ label: Text, action: @escaping () -> Void) { + self.label = label + self.action = action + } + + /// Create a new info button. + /// - Parameters: + /// - resource: The localized button label. This is not shown but useful for accessibility. + /// - action: The button action. + public init(_ resource: LocalizedStringResource, action: @escaping () -> Void) { + self.label = Text(resource) + self.action = action + } +} + + +#if DEBUG +#Preview { + List { + Button { + print("Primary") + } label: { + ListRow("Entry") { + InfoButton("Entry Info") { + print("Info") + } + } + } + } +} +#endif diff --git a/Sources/SpeziViews/Views/Controls/CaseIterablePicker.swift b/Sources/SpeziViews/Views/Controls/CaseIterablePicker.swift index f69d42a..709ba2c 100644 --- a/Sources/SpeziViews/Views/Controls/CaseIterablePicker.swift +++ b/Sources/SpeziViews/Views/Controls/CaseIterablePicker.swift @@ -142,7 +142,7 @@ extension CaseIterablePicker where Value: AnyOptional { // swiftlint:disable:thi /// Create a new case-iterable picker. /// - Parameters: /// - titleKey: The picker label. - /// - value: The value binding. + /// - selection: The value binding. public init(_ titleKey: LocalizedStringResource, selection: Binding) where Label == Text { self.init(selection: selection) { Text(titleKey) diff --git a/Sources/SpeziViews/Views/List/ListHeader.swift b/Sources/SpeziViews/Views/List/ListHeader.swift new file mode 100644 index 0000000..eadada1 --- /dev/null +++ b/Sources/SpeziViews/Views/List/ListHeader.swift @@ -0,0 +1,105 @@ +// +// This source file is part of the Spezi open-source project +// +// SPDX-FileCopyrightText: 2024 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import SwiftUI + + +/// Header view for Lists or Forms. +/// +/// A header view that can be used in List or Form views. +public struct ListHeader: View { + private let image: Image + private let title: Title + private let instructions: Instructions + + + public var body: some View { + VStack { + VStack { + image + .foregroundColor(.accentColor) + .symbolRenderingMode(.multicolor) + .font(.custom("XXL", size: 50, relativeTo: .title)) + .accessibilityHidden(true) + title + .accessibilityAddTraits(.isHeader) + .font(.title) + .bold() + .padding(.bottom, 4) + } + .accessibilityElement(children: .combine) + instructions + .padding([.leading, .trailing], 25) + } + .multilineTextAlignment(.center) + .frame(maxWidth: .infinity) + } + + /// Create a new list header. + /// - Parameters: + /// - image: The image view. + /// - title: The title view. + public init(@ViewBuilder image: () -> Image, @ViewBuilder title: () -> Title) where Instructions == EmptyView { + self.init(image: image, title: title) { + EmptyView() + } + } + + /// Create a new list header. + /// - Parameters: + /// - image: The image view. + /// - title: The title view. + /// - instructions: The instructions subheadline. + public init(@ViewBuilder image: () -> Image, @ViewBuilder title: () -> Title, @ViewBuilder instructions: () -> Instructions) { + self.image = image() + self.title = title() + self.instructions = instructions() + } + + /// Create a new list header. + /// - Parameters: + /// - systemImage: The name of the system symbol image. + /// - title: The title view. + public init(systemImage: String, @ViewBuilder title: () -> Title) where Image == SwiftUI.Image, Instructions == EmptyView { + // swiftlint:disable:next accessibility_label_for_image + self.init(image: { SwiftUI.Image(systemName: systemImage) }, title: title) { + EmptyView() + } + } + + /// Create a new list header. + /// - Parameters: + /// - systemImage: The name of the system symbol image. + /// - title: The title view. + /// - instructions: The instructions subheadline. + public init(systemImage: String, @ViewBuilder title: () -> Title, @ViewBuilder instructions: () -> Instructions) where Image == SwiftUI.Image { + // swiftlint:disable:next accessibility_label_for_image + self.init(image: { SwiftUI.Image(systemName: systemImage) }, title: title, instructions: instructions) + } +} + + +#if DEBUG +#Preview { + List { + ListHeader(systemImage: "person.fill.badge.plus") { + Text("Create a new Account", bundle: .module) + } instructions: { + Text("Please fill out the details below to create your new account.", bundle: .module) + } + } +} + +#Preview { + List { + ListHeader(systemImage: "person.fill.badge.plus") { + Text("Create a new Account", bundle: .module) + } + } +} +#endif diff --git a/Tests/SpeziViewsTests/SnapshotTests.swift b/Tests/SpeziViewsTests/SnapshotTests.swift index 641cb3e..ee69f18 100644 --- a/Tests/SpeziViewsTests/SnapshotTests.swift +++ b/Tests/SpeziViewsTests/SnapshotTests.swift @@ -187,4 +187,22 @@ final class SnapshotTests: XCTestCase { Text("World") } } + + @MainActor + func testListHeader() { + let listHeader0 = ListHeader(systemImage: "person.fill.badge.plus") { + Text("Create a new Account", bundle: .module) + } instructions: { + Text("Please fill out the details below to create your new account.", bundle: .module) + } + + let listHeader1 = ListHeader(systemImage: "person.fill.badge.plus") { + Text("Create a new Account", bundle: .module) + } + +#if os(iOS) + assertSnapshot(of: listHeader0, as: .image(layout: .device(config: .iPhone13Pro)), named: "list-header-instructions") + assertSnapshot(of: listHeader1, as: .image(layout: .device(config: .iPhone13Pro)), named: "list-header") +#endif + } } diff --git a/Tests/SpeziViewsTests/__Snapshots__/SnapshotTests/testListHeader.list-header-instructions.png b/Tests/SpeziViewsTests/__Snapshots__/SnapshotTests/testListHeader.list-header-instructions.png new file mode 100644 index 0000000000000000000000000000000000000000..ee9f8b6fcc32b0d6d02423e8c94f487e0e580b94 GIT binary patch literal 91480 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 VusnN_yXiN?FP)f(pNuc&KLK)62<-p> literal 0 HcmV?d00001 diff --git a/Tests/SpeziViewsTests/__Snapshots__/SnapshotTests/testListHeader.list-header.png b/Tests/SpeziViewsTests/__Snapshots__/SnapshotTests/testListHeader.list-header.png new file mode 100644 index 0000000000000000000000000000000000000000..348ac17ffd1bc1e9758d49f4615eae2faa4489f5 GIT binary patch literal 76128 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 literal 0 HcmV?d00001 diff --git a/Tests/UITests/TestApp/Localizable.xcstrings b/Tests/UITests/TestApp/Localizable.xcstrings index 8021305..0886cb8 100644 --- a/Tests/UITests/TestApp/Localizable.xcstrings +++ b/Tests/UITests/TestApp/Localizable.xcstrings @@ -76,6 +76,12 @@ }, "Enter your details" : { + }, + "Entity" : { + + }, + "Entity Info" : { + }, "Error Description" : { diff --git a/Tests/UITests/TestApp/ViewsTests/AsyncButtonTestView.swift b/Tests/UITests/TestApp/ViewsTests/ButtonTestView.swift similarity index 72% rename from Tests/UITests/TestApp/ViewsTests/AsyncButtonTestView.swift rename to Tests/UITests/TestApp/ViewsTests/ButtonTestView.swift index 28bad6c..3c46b4f 100644 --- a/Tests/UITests/TestApp/ViewsTests/AsyncButtonTestView.swift +++ b/Tests/UITests/TestApp/ViewsTests/ButtonTestView.swift @@ -23,10 +23,12 @@ enum CustomError: Error, LocalizedError { } -struct AsyncButtonTestView: View { +struct ButtonTestView: View { @State private var showCompleted = false @State private var viewState: ViewState = .idle + @State private var showInfo = false + var body: some View { List { if showCompleted { @@ -49,6 +51,21 @@ struct AsyncButtonTestView: View { } .disabled(showCompleted) .viewStateAlert(state: $viewState) + + Section { + HStack { + Button { + viewState = .error(CustomError.error) + } label: { + Text("Entity") + .foregroundStyle(.primary) + } + Spacer() + InfoButton("Entity Info") { + showCompleted = true + } + } + } } } } @@ -57,7 +74,7 @@ struct AsyncButtonTestView: View { #if DEBUG struct AsyncButtonTestView_Previews: PreviewProvider { static var previews: some View { - AsyncButtonTestView() + ButtonTestView() } } #endif diff --git a/Tests/UITests/TestApp/ViewsTests/SpeziViewsTests.swift b/Tests/UITests/TestApp/ViewsTests/SpeziViewsTests.swift index 6d9fe2f..bb5036e 100644 --- a/Tests/UITests/TestApp/ViewsTests/SpeziViewsTests.swift +++ b/Tests/UITests/TestApp/ViewsTests/SpeziViewsTests.swift @@ -27,7 +27,7 @@ enum SpeziViewsTests: String, TestAppTests { case conditionalModifier = "Conditional Modifier" case defaultErrorOnly = "Default Error Only" case defaultErrorDescription = "Default Error Description" - case asyncButton = "Async Button" + case button = "Buttons" case listRow = "List Row" case managedViewUpdate = "Managed View Update" case caseIterablePicker = "Case Iterable Picker" @@ -130,8 +130,8 @@ enum SpeziViewsTests: String, TestAppTests { @ViewBuilder @MainActor - private var asyncButton: some View { - AsyncButtonTestView() + private var button: some View { + ButtonTestView() } @MainActor @@ -172,8 +172,8 @@ enum SpeziViewsTests: String, TestAppTests { defaultErrorOnly case .defaultErrorDescription: defaultErrorDescription - case .asyncButton: - asyncButton + case .button: + button case .listRow: listRow case .managedViewUpdate: diff --git a/Tests/UITests/TestAppUITests/SpeziViews/ViewsTests.swift b/Tests/UITests/TestAppUITests/SpeziViews/ViewsTests.swift index 4c6755a..f51926c 100644 --- a/Tests/UITests/TestAppUITests/SpeziViews/ViewsTests.swift +++ b/Tests/UITests/TestAppUITests/SpeziViews/ViewsTests.swift @@ -140,7 +140,7 @@ final class ViewsTests: XCTestCase { } @MainActor - func testAsyncButtonView() throws { + func testButtonsView() throws { let app = XCUIApplication() app.launch() @@ -151,8 +151,8 @@ final class ViewsTests: XCTestCase { app.collectionViews.firstMatch.swipeUp() // on visionOS the AsyncButton is out of the frame due to the window size #endif - XCTAssert(app.buttons["Async Button"].waitForExistence(timeout: 2)) - app.buttons["Async Button"].tap() + XCTAssert(app.buttons["Buttons"].waitForExistence(timeout: 2)) + app.buttons["Buttons"].tap() XCTAssert(app.buttons["Hello World"].waitForExistence(timeout: 2)) app.buttons["Hello World"].tap() @@ -174,6 +174,14 @@ final class ViewsTests: XCTestCase { alerts.buttons["OK"].tap() XCTAssert(app.buttons["Hello Throwing World"].isEnabled) + + XCTAssert(app.buttons.matching(identifier: "info-button").firstMatch.exists) + app.buttons.matching(identifier: "info-button").firstMatch.tap() + + XCTAssertFalse(alerts.staticTexts["Custom Error"].exists) + + XCTAssert(app.staticTexts["Action executed"].waitForExistence(timeout: 2)) + app.buttons["Reset"].tap() } @MainActor diff --git a/Tests/UITests/UITests.xcodeproj/project.pbxproj b/Tests/UITests/UITests.xcodeproj/project.pbxproj index e0036d2..a152109 100644 --- a/Tests/UITests/UITests.xcodeproj/project.pbxproj +++ b/Tests/UITests/UITests.xcodeproj/project.pbxproj @@ -33,7 +33,7 @@ A97880972A4C4E6500150B2F /* ModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97880962A4C4E6500150B2F /* ModelTests.swift */; }; A97880992A4C524D00150B2F /* DefaultErrorDescriptionTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A97880982A4C524D00150B2F /* DefaultErrorDescriptionTestView.swift */; }; A978809B2A4C52F100150B2F /* EnvironmentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A978809A2A4C52F100150B2F /* EnvironmentTests.swift */; }; - A998A94F2A609A9E0030624D /* AsyncButtonTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A998A94E2A609A9E0030624D /* AsyncButtonTestView.swift */; }; + A998A94F2A609A9E0030624D /* ButtonTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A998A94E2A609A9E0030624D /* ButtonTestView.swift */; }; A99A65122AF57CA200E63582 /* FocusedValidationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A99A65112AF57CA200E63582 /* FocusedValidationTests.swift */; }; A99A65152AF5923800E63582 /* ValidationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A99A65142AF5923800E63582 /* ValidationTests.swift */; }; A9A3535B2AF60A9E00661848 /* DefaultValidationRules.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9A3535A2AF60A9E00661848 /* DefaultValidationRules.swift */; }; @@ -84,7 +84,7 @@ A97880962A4C4E6500150B2F /* ModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelTests.swift; sourceTree = ""; }; A97880982A4C524D00150B2F /* DefaultErrorDescriptionTestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultErrorDescriptionTestView.swift; sourceTree = ""; }; A978809A2A4C52F100150B2F /* EnvironmentTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnvironmentTests.swift; sourceTree = ""; }; - A998A94E2A609A9E0030624D /* AsyncButtonTestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncButtonTestView.swift; sourceTree = ""; }; + A998A94E2A609A9E0030624D /* ButtonTestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonTestView.swift; sourceTree = ""; }; A99A65112AF57CA200E63582 /* FocusedValidationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FocusedValidationTests.swift; sourceTree = ""; }; A99A65142AF5923800E63582 /* ValidationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationTests.swift; sourceTree = ""; }; A9A3535A2AF60A9E00661848 /* DefaultValidationRules.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultValidationRules.swift; sourceTree = ""; }; @@ -177,7 +177,7 @@ 2FA9485D29DE90710081C086 /* ViewsTests */ = { isa = PBXGroup; children = ( - A998A94E2A609A9E0030624D /* AsyncButtonTestView.swift */, + A998A94E2A609A9E0030624D /* ButtonTestView.swift */, 2FA9486029DE90720081C086 /* CanvasTestView.swift */, A90575B32CD03B2C00B94001 /* CaseIterablePickerTests.swift */, 97A0A50F2B8D7FD7006102EF /* ConditionalModifierTestView.swift */, @@ -374,7 +374,7 @@ 97EE16AC2B16D5AB004D25A3 /* OperationStateTestView.swift in Sources */, 9731B58F2B167053007676C0 /* ViewStateMapperView.swift in Sources */, A9F85B742B32A05C005F16E6 /* ViewStateExample.swift in Sources */, - A998A94F2A609A9E0030624D /* AsyncButtonTestView.swift in Sources */, + A998A94F2A609A9E0030624D /* ButtonTestView.swift in Sources */, 2FA9486A29DE90720081C086 /* GeometryReaderTestView.swift in Sources */, A9F85B722B32A052005F16E6 /* NameFieldsExample.swift in Sources */, 2FA9486729DE90720081C086 /* CanvasTestView.swift in Sources */, @@ -823,7 +823,7 @@ repositoryURL = "https://github.com/StanfordBDHG/XCTestExtensions"; requirement = { kind = upToNextMinorVersion; - minimumVersion = 0.4.9; + minimumVersion = 1.1.0; }; }; A9BA82B22C29FF7C00472FF3 /* XCRemoteSwiftPackageReference "Spezi" */ = { @@ -831,7 +831,7 @@ repositoryURL = "https://github.com/StanfordSpezi/Spezi.git"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 1.3.0; + minimumVersion = 1.8.0; }; }; /* End XCRemoteSwiftPackageReference section */