Onboarding State Updates

This commit is contained in:
adam 2021-11-05 07:26:20 -05:00
parent 23873cc757
commit 9b46a4c9d3
3 changed files with 65 additions and 20 deletions

View File

@ -18,13 +18,18 @@ struct OnboardingStep: Equatable, Identifiable {
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 skipButtonDisabled: Bool { steps.count == index + 1 }
var backButtonDisabled: Bool { index == 0 }
var progress: Int { ((index + 1) * 100) / (steps.count) }
var offset: CGFloat {
let maxOffset = CGFloat(-60)
let stepOffset = CGFloat(maxOffset / CGFloat(steps.count - 1))
guard index != 0 else { return .zero }
return stepOffset * CGFloat(index)
}
}
enum OnboardingAction: Equatable {
@ -43,14 +48,12 @@ let onboardingReducer = Reducer<OnboardingState, OnboardingAction, Void> { state
state.skippedAtindex = nil
} else {
state.index -= 1
state.offset += 20.0
}
return .none
case .next:
guard state.index < state.steps.count - 1 else { return .none }
state.index += 1
state.offset -= 20.0
return .none
case .skip:

View File

@ -19,6 +19,7 @@ struct OnboardingView: View {
.disabled(viewStore.backButtonDisabled)
Spacer()
Button("Next") { viewStore.send(.next) }
Button("Skip") { viewStore.send(.skip) }
.disabled(viewStore.skipButtonDisabled)

View File

@ -19,98 +19,139 @@ class OnboardingStoreTests: XCTestCase {
store.send(.next) {
$0.index += 1
$0.offset -= 20.0
XCTAssertFalse($0.skipButtonDisabled)
XCTAssertFalse($0.backButtonDisabled)
XCTAssertEqual($0.currentStep, $0.steps[1])
XCTAssertEqual($0.offset, -20.0)
XCTAssertEqual($0.progress, 50)
}
store.send(.next) {
$0.index += 1
$0.offset -= 20.0
XCTAssertFalse($0.skipButtonDisabled)
XCTAssertFalse($0.backButtonDisabled)
XCTAssertEqual($0.currentStep, $0.steps[2])
XCTAssertEqual($0.offset, -40.0)
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.offset, -60.0)
XCTAssertEqual($0.progress, 100)
}
}
func testIncrementingPastTotalStepsDoesNothing() {
let store = TestStore(
initialState: OnboardingState(index: 3),
reducer: onboardingReducer,
environment: ()
)
store.send(.next) {
XCTAssertTrue($0.skipButtonDisabled)
XCTAssertFalse($0.backButtonDisabled)
XCTAssertEqual($0.currentStep, $0.steps[3])
XCTAssertEqual($0.offset, -60.0)
XCTAssertEqual($0.progress, 100)
}
store.send(.next) {
XCTAssertTrue($0.skipButtonDisabled)
XCTAssertFalse($0.backButtonDisabled)
XCTAssertEqual($0.currentStep, $0.steps[3])
XCTAssertEqual($0.offset, -60.0)
XCTAssertEqual($0.progress, 100)
}
}
func testDecrementingOnboarding() {
let store = TestStore(
initialState: OnboardingState(
index: 2,
offset: .zero - 20.0 - 20.0
),
initialState: OnboardingState(index: 2),
reducer: onboardingReducer,
environment: ()
)
store.send(.back) {
$0.index -= 1
$0.offset += 20.0
XCTAssertFalse($0.skipButtonDisabled)
XCTAssertFalse($0.backButtonDisabled)
XCTAssertEqual($0.currentStep, $0.steps[1])
XCTAssertEqual($0.offset, -20.0)
XCTAssertEqual($0.progress, 50)
}
store.send(.back) {
$0.index -= 1
$0.offset += 20.0
XCTAssertFalse($0.skipButtonDisabled)
XCTAssertTrue($0.backButtonDisabled)
XCTAssertEqual($0.currentStep, $0.steps[0])
XCTAssertEqual($0.offset, 0.0)
XCTAssertEqual($0.progress, 25)
}
}
func testDecrementingPastFirstStepDoesNothing() {
let store = TestStore(
initialState: OnboardingState(),
reducer: onboardingReducer,
environment: ()
)
store.send(.back) {
XCTAssertFalse($0.skipButtonDisabled)
XCTAssertTrue($0.backButtonDisabled)
XCTAssertEqual($0.currentStep, $0.steps[0])
XCTAssertEqual($0.offset, 0.0)
XCTAssertEqual($0.progress, 25)
}
store.send(.back) {
XCTAssertFalse($0.skipButtonDisabled)
XCTAssertTrue($0.backButtonDisabled)
XCTAssertEqual($0.currentStep, $0.steps[0])
XCTAssertEqual($0.offset, 0.0)
XCTAssertEqual($0.progress, 25)
}
}
func testSkipOnboarding() {
let initialIndex = 1
let initialOffset: CGFloat = .zero - 20.0
let store = TestStore(
initialState: OnboardingState(
index: initialIndex,
offset: initialOffset
),
initialState: OnboardingState(index: initialIndex),
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.offset, -60.0)
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.offset, -20.0)
XCTAssertEqual($0.progress, 50)
}
}