Skip to content

Commit

Permalink
PR Review Andi & Philipp
Browse files Browse the repository at this point in the history
Modifications:

* replace `protocol` `OnboardingIdentifiableView` with simple
  conformance to `View & Identifiable`
* create a new view modifier `.id(_:)` wrapping any `View` in a `struct
  OnboardingIdenfiableView` which is `View & Identifiable` and contains
  the specified `id` as a property
* hoist `OnboardingStepIdentifier` overloaded intializers into different
  `OnboardingNavigationPath.append()` methods
* remove `OnboardingIdentifiableTestViewDefault`
  • Loading branch information
felixschlegel committed Apr 12, 2024
1 parent 5b3ff1a commit 8edfc57
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,10 @@ public class OnboardingNavigationPath {
/// - Parameters:
/// - onboardingStepType: The type of the onboarding `View` which should be displayed next. Must be declared within the ``OnboardingStack``.
public func append(_ onboardingStepType: any View.Type) {
let onboardingStepIdentifier = OnboardingStepIdentifier(fromType: onboardingStepType)
let onboardingStepIdentifier = OnboardingStepIdentifier(
onboardingStepType: String(describing: onboardingStepType),
custom: false
)
guard onboardingSteps.keys.contains(onboardingStepIdentifier) else {
print("""
"Warning: Invocation of `OnboardingNavigationPath.append(_:)` with an Onboarding view
Expand All @@ -162,27 +165,30 @@ public class OnboardingNavigationPath {
/// - Parameters:
/// - customView: A custom onboarding `View` instance that should be shown next in the onboarding flow.
/// It isn't required to declare this view within the ``OnboardingStack``.
public func append(customView: any View) {
let customOnboardingStepIdentifier = OnboardingStepIdentifier(fromView: customView, custom: true)
public func append<V: View>(customView: V) {
let customOnboardingStepIdentifier = OnboardingStepIdentifier(
onboardingStepType: String(describing: V.self),
custom: true
)
customOnboardingSteps[customOnboardingStepIdentifier] = customView

appendToInternalNavigationPath(of: customOnboardingStepIdentifier)
}

/// Moves the navigation path to the custom identifiable view.
/// Moves the navigation path to the custom `Identifiable` view.
///
/// - Note: The custom identifiable `View` does not have to be declared within the ``OnboardingStack``.
/// - Note: The custom `View` does not have to be declared within the ``OnboardingStack``.
/// Resulting from that, the internal state of the ``OnboardingNavigationPath`` is still referencing to the last regular `OnboardingStep`.
///
/// - Parameters:
/// - identifiableView: An instance of ``OnboardingIdentifiableView`` that should be shown next in the onboarding flow.
/// - customView: A custom onboarding `View` instance that should be shown next in the onboarding flow.
/// It isn't required to declare this view within the ``OnboardingStack``.
public func append(identifiableView: any OnboardingIdentifiableView) {
public func append<V: View & Identifiable>(customView: V) {
let customOnboardingStepIdentifier = OnboardingStepIdentifier(
fromIdentifiableView: identifiableView,
onboardingStepType: String(describing: customView.id),
custom: true
)
customOnboardingSteps[customOnboardingStepIdentifier] = identifiableView
customOnboardingSteps[customOnboardingStepIdentifier] = customView

appendToInternalNavigationPath(of: customOnboardingStepIdentifier)
}
Expand Down Expand Up @@ -211,8 +217,11 @@ public class OnboardingNavigationPath {
self.onboardingStepsOrder.removeAll(keepingCapacity: true)

for view in views {
let onboardingStepIdentifier = OnboardingStepIdentifier(fromView: view)

let onboardingStepIdentifier = OnboardingStepIdentifier(
onboardingStepType: String(describing: type(of: view)),
custom: false
)

guard self.onboardingSteps[onboardingStepIdentifier] == nil else {
preconditionFailure("""
SpeziOnboarding: Duplicate Onboarding step of type `\(onboardingStepIdentifier.onboardingStepType)` identified.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,4 @@ import SwiftUI
struct OnboardingStepIdentifier: Hashable, Codable {
let onboardingStepType: String
let custom: Bool


init(fromType type: any View.Type, custom: Bool = false) {
self.onboardingStepType = String(describing: type)
self.custom = custom
}


init(fromView view: any View, custom: Bool = false) {
self.onboardingStepType = String(describing: type(of: view))
self.custom = custom
}

init(fromIdentifiableView view: any OnboardingIdentifiableView, custom: Bool = false) {
self.onboardingStepType = view.id
self.custom = custom
}
}
37 changes: 0 additions & 37 deletions Sources/SpeziOnboarding/OnboardingIdentifiableView.swift

This file was deleted.

39 changes: 39 additions & 0 deletions Sources/SpeziOnboarding/OnboardingIdentifiableViewModifier.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// 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

/// Wrap `Content` `View` in an `Identifiable` `View`.
public struct OnboardingIdentifiableView<Content>: View, Identifiable where Content: View {
/// Unique identifier of the wrapped `View`.
public let id: String
/// Wrapped `View`.
public var body: Content
}

struct OnboardingIdentifiableViewModifier: ViewModifier {
let identifier: String

func body(content: Content) -> some View {
OnboardingIdentifiableView(
id: self.identifier,
body: content
)
}
}


extension View {
/// `ViewModifier` assigning an identifier to the `View` it is applied to.
/// When applying this modifier repeatedly, the outermost ``id(_:)`` counts.
/// - Parameters:
/// - identifier: The `String` identifier given to the view.
public func id(_ identifier: String) -> some View {
modifier(OnboardingIdentifiableViewModifier(identifier: identifier))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import SpeziOnboarding
import SwiftUI

struct OnboardingIdentifiableTestViewCustom: OnboardingIdentifiableView {
struct OnboardingIdentifiableTestViewCustom: View, Identifiable {
var id: String

@Environment(OnboardingNavigationPath.self) private var path
Expand All @@ -21,7 +21,7 @@ struct OnboardingIdentifiableTestViewCustom: OnboardingIdentifiableView {

Button {
if self.id == "ID: 1" {
path.append(identifiableView: OnboardingIdentifiableTestViewCustom(id: "ID: 2"))
path.append(customView: OnboardingIdentifiableTestViewCustom(id: "ID: 2"))
} else {
path.nextStep()
}
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion Tests/UITests/TestApp/Views/OnboardingStartTestView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ struct OnboardingStartTestView: View {
}

Button {
path.append(identifiableView: OnboardingIdentifiableTestViewDefault())
path.append(customView: OnboardingIdentifiableTestViewCustom(id: "ID: 1"))
} label: {
Text("Onboarding Identifiable View")
}
Expand Down
3 changes: 0 additions & 3 deletions Tests/UITests/TestAppUITests/SpeziOnboardingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -430,9 +430,6 @@ final class OnboardingTests: XCTestCase { // swiftlint:disable:this type_body_le
app.launch()
app.buttons["Onboarding Identifiable View"].tap()

XCTAssert(app.staticTexts["OnboardingIdentifiableTestViewDefault"].waitForExistence(timeout: 2))
app.buttons["Next"].tap()

XCTAssert(app.staticTexts["ID: 1"].waitForExistence(timeout: 2))
app.buttons["Next"].tap()

Expand Down
4 changes: 0 additions & 4 deletions Tests/UITests/UITests.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
2F6D139A28F5F386007C25D6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2F6D139928F5F386007C25D6 /* Assets.xcassets */; };
2FA7382C290ADFAA007ACEB9 /* TestApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA7382B290ADFAA007ACEB9 /* TestApp.swift */; };
61040A1D2BAFA2F600EDD4EC /* OnboardingIdentifiableTestViewCustom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61040A1B2BAFA2F600EDD4EC /* OnboardingIdentifiableTestViewCustom.swift */; };
61040A1E2BAFA2F600EDD4EC /* OnboardingIdentifiableTestViewDefault.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61040A1C2BAFA2F600EDD4EC /* OnboardingIdentifiableTestViewDefault.swift */; };
970D444B2A6F031200756FE2 /* OnboardingConsentMarkdownTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 970D444A2A6F031200756FE2 /* OnboardingConsentMarkdownTestView.swift */; };
970D444F2A6F048A00756FE2 /* OnboardingWelcomeTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 970D444E2A6F048A00756FE2 /* OnboardingWelcomeTestView.swift */; };
970D44512A6F04ED00756FE2 /* OnboardingSequentialTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 970D44502A6F04ED00756FE2 /* OnboardingSequentialTestView.swift */; };
Expand Down Expand Up @@ -49,7 +48,6 @@
2FA7382B290ADFAA007ACEB9 /* TestApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestApp.swift; sourceTree = "<group>"; };
2FB0758A299DDB9000C0B37F /* TestApp.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = TestApp.xctestplan; sourceTree = "<group>"; };
61040A1B2BAFA2F600EDD4EC /* OnboardingIdentifiableTestViewCustom.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingIdentifiableTestViewCustom.swift; sourceTree = "<group>"; };
61040A1C2BAFA2F600EDD4EC /* OnboardingIdentifiableTestViewDefault.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingIdentifiableTestViewDefault.swift; sourceTree = "<group>"; };
970D444A2A6F031200756FE2 /* OnboardingConsentMarkdownTestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingConsentMarkdownTestView.swift; sourceTree = "<group>"; };
970D444E2A6F048A00756FE2 /* OnboardingWelcomeTestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingWelcomeTestView.swift; sourceTree = "<group>"; };
970D44502A6F04ED00756FE2 /* OnboardingSequentialTestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingSequentialTestView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -137,7 +135,6 @@
isa = PBXGroup;
children = (
61040A1B2BAFA2F600EDD4EC /* OnboardingIdentifiableTestViewCustom.swift */,
61040A1C2BAFA2F600EDD4EC /* OnboardingIdentifiableTestViewDefault.swift */,
97A8FF2F2A74606A008CD91A /* HelperViews */,
970D44522A6F0B1900756FE2 /* OnboardingStartTestView.swift */,
970D444E2A6F048A00756FE2 /* OnboardingWelcomeTestView.swift */,
Expand Down Expand Up @@ -300,7 +297,6 @@
2FA7382C290ADFAA007ACEB9 /* TestApp.swift in Sources */,
97A8FF2E2A7444FC008CD91A /* OnboardingCustomTestView2.swift in Sources */,
2F61BDC929DD3CC000D71D33 /* OnboardingTestsView.swift in Sources */,
61040A1E2BAFA2F600EDD4EC /* OnboardingIdentifiableTestViewDefault.swift in Sources */,
61040A1D2BAFA2F600EDD4EC /* OnboardingIdentifiableTestViewCustom.swift in Sources */,
97C6AF7F2ACC94450060155B /* OnboardingFlow+PreviewSimulator.swift in Sources */,
97C6AF7D2ACC92CB0060155B /* OnboardingConsentMarkdownRenderingView.swift in Sources */,
Expand Down

0 comments on commit 8edfc57

Please sign in to comment.