Merge pull request #113 from adamstener/onboarding

Onboarding: Skip Functionality
This commit is contained in:
Francisco Gindre 2021-11-04 11:45:24 -03:00 committed by GitHub
commit 3068e6a168
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 101 additions and 39 deletions

View File

@ -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<OnboardingStep> = 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<OnboardingState, OnboardingAction, Void> { 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
}
}

View File

@ -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!"
)
]
)

View File

@ -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)
}
}
}