From 16adad59f0e9aa3a310d8b6e376e6f2904c30a3d Mon Sep 17 00:00:00 2001 From: adam Date: Thu, 4 Nov 2021 07:41:39 -0500 Subject: [PATCH] Onboarding Skip --- .../Features/Onboarding/OnboardingStore.swift | 38 ++++++++--- .../Onboarding/Views/Onboarding.swift | 34 +++++----- .../OnboardingStoreTests.swift | 68 ++++++++++++++++--- 3 files changed, 101 insertions(+), 39 deletions(-) diff --git a/secant/Features/Onboarding/OnboardingStore.swift b/secant/Features/Onboarding/OnboardingStore.swift index d0e3372..645969c 100644 --- a/secant/Features/Onboarding/OnboardingStore.swift +++ b/secant/Features/Onboarding/OnboardingStore.swift @@ -11,38 +11,54 @@ import ComposableArchitecture struct OnboardingStep: Equatable, Identifiable { let id: UUID + let title: String let description: String - let imageName: String } struct OnboardingState: Equatable { var steps: IdentifiedArrayOf = Self.onboardingSteps var index = 0 var offset: CGFloat = .zero + var skippedAtindex: Int? var currentStep: OnboardingStep { steps[index] } - var nextButtonDisabled: Bool { steps.count == index + 1 } + var skipButtonDisabled: Bool { steps.count == index + 1 } var backButtonDisabled: Bool { index == 0 } - var progress: Int { - ((index + 1) * 100) / (steps.count) - } + var progress: Int { ((index + 1) * 100) / (steps.count) } } enum OnboardingAction: Equatable { - case nextPressed - case backPressed + case next + case back + case skip + case createNewWallet } let onboardingReducer = Reducer { state, action, _ in switch action { - case .backPressed: - state.index -= 1 - state.offset += 20.0 + case .back: + guard state.index > 0 else { return .none } + if let skippedFrom = state.skippedAtindex { + state.index = skippedFrom + state.skippedAtindex = nil + } else { + state.index -= 1 + state.offset += 20.0 + } return .none - case .nextPressed: + case .next: + guard state.index < state.steps.count - 1 else { return .none } state.index += 1 state.offset -= 20.0 return .none + + case .skip: + state.skippedAtindex = state.index + state.index = state.steps.count - 1 + return .none + + case .createNewWallet: + return .none } } diff --git a/secant/Features/Onboarding/Views/Onboarding.swift b/secant/Features/Onboarding/Views/Onboarding.swift index c48ec1e..16c38f0 100644 --- a/secant/Features/Onboarding/Views/Onboarding.swift +++ b/secant/Features/Onboarding/Views/Onboarding.swift @@ -15,26 +15,20 @@ struct OnboardingView: View { WithViewStore(self.store) { viewStore in VStack(spacing: 50) { HStack(spacing: 50) { - Button( - action: { viewStore.send(.backPressed) }, - label: { Text("Previous") } - ) - .disabled(viewStore.backButtonDisabled) + Button("Back") { viewStore.send(.back) } + .disabled(viewStore.backButtonDisabled) Spacer() - Button( - action: { viewStore.send(.nextPressed) }, - label: { Text("Next") } - ) - .disabled(viewStore.nextButtonDisabled) + Button("Skip") { viewStore.send(.skip) } + .disabled(viewStore.skipButtonDisabled) } .frame(height: 100) .padding(.horizontal, 50) Spacer() - Text(viewStore.currentStep.imageName) + Text(viewStore.currentStep.title) .frame(maxWidth: .infinity) .offset(y: viewStore.offset) .animation(.easeOut(duration: 0.4)) @@ -58,23 +52,29 @@ struct OnboardingView: View { } } +// swiftlint:disable line_length extension OnboardingState { static let onboardingSteps = IdentifiedArray( uniqueElements: [ OnboardingStep( id: UUID(), - description: "This is the description of the first onboarding step, please read it carefully.", - imageName: "Image" + title: "Shielded by Default", + description: "Tired of worrying about which wallet you used last? US TOO! Now you don't have to, as all funds will automatically be moved to your shielded wallet (and migrated for you)." ), OnboardingStep( id: UUID(), - description: "The second step is even more important, have to pay attention to the details here.", - imageName: "Image" + title: "Unified Addresses", + description: "Tired of worrying about which wallet you used last? US TOO! Now you don't have to, as all funds will automatically be moved to your shielded wallet (and migrated for you)." ), OnboardingStep( id: UUID(), - description: "Congratulations you made it all the way through to the end, you can use the app now!", - imageName: "Image" + title: "And so much more...", + description: "Faster reverse syncing (yes it's a thing). Liberated Payments, Social Payments, Address Books, in-line ZEC requests, wrapped Bitcoin, fractionalize NFTs, you providing liquidity for anything you want, getting that Defi, and going to Mexico." + ), + OnboardingStep( + id: UUID(), + title: "Ready for the Future", + description: "Lets get you set up!" ) ] ) diff --git a/secantTests/OnboardingTests/OnboardingStoreTests.swift b/secantTests/OnboardingTests/OnboardingStoreTests.swift index b816299..6ff7830 100644 --- a/secantTests/OnboardingTests/OnboardingStoreTests.swift +++ b/secantTests/OnboardingTests/OnboardingStoreTests.swift @@ -17,23 +17,33 @@ class OnboardingStoreTests: XCTestCase { environment: () ) - store.send(.nextPressed) { + store.send(.next) { $0.index += 1 $0.offset -= 20.0 - XCTAssertFalse($0.nextButtonDisabled) + XCTAssertFalse($0.skipButtonDisabled) XCTAssertFalse($0.backButtonDisabled) XCTAssertEqual($0.currentStep, $0.steps[1]) - XCTAssertEqual($0.progress, 66) + XCTAssertEqual($0.progress, 50) } - store.send(.nextPressed) { + store.send(.next) { $0.index += 1 $0.offset -= 20.0 - XCTAssertTrue($0.nextButtonDisabled) + XCTAssertFalse($0.skipButtonDisabled) XCTAssertFalse($0.backButtonDisabled) XCTAssertEqual($0.currentStep, $0.steps[2]) + XCTAssertEqual($0.progress, 75) + } + + store.send(.next) { + $0.index += 1 + $0.offset -= 20.0 + + XCTAssertTrue($0.skipButtonDisabled) + XCTAssertFalse($0.backButtonDisabled) + XCTAssertEqual($0.currentStep, $0.steps[3]) XCTAssertEqual($0.progress, 100) } } @@ -48,24 +58,60 @@ class OnboardingStoreTests: XCTestCase { environment: () ) - store.send(.backPressed) { + store.send(.back) { $0.index -= 1 $0.offset += 20.0 - XCTAssertFalse($0.nextButtonDisabled) + XCTAssertFalse($0.skipButtonDisabled) XCTAssertFalse($0.backButtonDisabled) XCTAssertEqual($0.currentStep, $0.steps[1]) - XCTAssertEqual($0.progress, 66) + XCTAssertEqual($0.progress, 50) } - store.send(.backPressed) { + store.send(.back) { $0.index -= 1 $0.offset += 20.0 - XCTAssertFalse($0.nextButtonDisabled) + XCTAssertFalse($0.skipButtonDisabled) XCTAssertTrue($0.backButtonDisabled) XCTAssertEqual($0.currentStep, $0.steps[0]) - XCTAssertEqual($0.progress, 33) + XCTAssertEqual($0.progress, 25) + } + } + + func testSkipOnboarding() { + let initialIndex = 1 + let initialOffset: CGFloat = .zero - 20.0 + + let store = TestStore( + initialState: OnboardingState( + index: initialIndex, + offset: initialOffset + ), + reducer: onboardingReducer, + environment: () + ) + + store.send(.skip) { + $0.index = $0.steps.count - 1 + $0.offset = initialOffset + $0.skippedAtindex = initialIndex + + XCTAssertTrue($0.skipButtonDisabled) + XCTAssertFalse($0.backButtonDisabled) + XCTAssertEqual($0.currentStep, $0.steps[3]) + XCTAssertEqual($0.progress, 100) + } + + store.send(.back) { + $0.skippedAtindex = nil + $0.index = initialIndex + $0.offset = initialOffset + + XCTAssertFalse($0.skipButtonDisabled) + XCTAssertFalse($0.backButtonDisabled) + XCTAssertEqual($0.currentStep, $0.steps[1]) + XCTAssertEqual($0.progress, 50) } } }