Onboarding State Updates
This commit is contained in:
parent
23873cc757
commit
9b46a4c9d3
|
@ -18,13 +18,18 @@ struct OnboardingStep: Equatable, Identifiable {
|
||||||
struct OnboardingState: Equatable {
|
struct OnboardingState: Equatable {
|
||||||
var steps: IdentifiedArrayOf<OnboardingStep> = Self.onboardingSteps
|
var steps: IdentifiedArrayOf<OnboardingStep> = Self.onboardingSteps
|
||||||
var index = 0
|
var index = 0
|
||||||
var offset: CGFloat = .zero
|
|
||||||
var skippedAtindex: Int?
|
var skippedAtindex: Int?
|
||||||
|
|
||||||
var currentStep: OnboardingStep { steps[index] }
|
var currentStep: OnboardingStep { steps[index] }
|
||||||
var skipButtonDisabled: Bool { steps.count == index + 1 }
|
var skipButtonDisabled: Bool { steps.count == index + 1 }
|
||||||
var backButtonDisabled: Bool { index == 0 }
|
var backButtonDisabled: Bool { index == 0 }
|
||||||
var progress: Int { ((index + 1) * 100) / (steps.count) }
|
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 {
|
enum OnboardingAction: Equatable {
|
||||||
|
@ -43,14 +48,12 @@ let onboardingReducer = Reducer<OnboardingState, OnboardingAction, Void> { state
|
||||||
state.skippedAtindex = nil
|
state.skippedAtindex = nil
|
||||||
} else {
|
} else {
|
||||||
state.index -= 1
|
state.index -= 1
|
||||||
state.offset += 20.0
|
|
||||||
}
|
}
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .next:
|
case .next:
|
||||||
guard state.index < state.steps.count - 1 else { return .none }
|
guard state.index < state.steps.count - 1 else { return .none }
|
||||||
state.index += 1
|
state.index += 1
|
||||||
state.offset -= 20.0
|
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .skip:
|
case .skip:
|
||||||
|
|
|
@ -19,6 +19,7 @@ struct OnboardingView: View {
|
||||||
.disabled(viewStore.backButtonDisabled)
|
.disabled(viewStore.backButtonDisabled)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
Button("Next") { viewStore.send(.next) }
|
||||||
|
|
||||||
Button("Skip") { viewStore.send(.skip) }
|
Button("Skip") { viewStore.send(.skip) }
|
||||||
.disabled(viewStore.skipButtonDisabled)
|
.disabled(viewStore.skipButtonDisabled)
|
||||||
|
|
|
@ -19,98 +19,139 @@ class OnboardingStoreTests: XCTestCase {
|
||||||
|
|
||||||
store.send(.next) {
|
store.send(.next) {
|
||||||
$0.index += 1
|
$0.index += 1
|
||||||
$0.offset -= 20.0
|
|
||||||
|
|
||||||
XCTAssertFalse($0.skipButtonDisabled)
|
XCTAssertFalse($0.skipButtonDisabled)
|
||||||
XCTAssertFalse($0.backButtonDisabled)
|
XCTAssertFalse($0.backButtonDisabled)
|
||||||
XCTAssertEqual($0.currentStep, $0.steps[1])
|
XCTAssertEqual($0.currentStep, $0.steps[1])
|
||||||
|
XCTAssertEqual($0.offset, -20.0)
|
||||||
XCTAssertEqual($0.progress, 50)
|
XCTAssertEqual($0.progress, 50)
|
||||||
}
|
}
|
||||||
|
|
||||||
store.send(.next) {
|
store.send(.next) {
|
||||||
$0.index += 1
|
$0.index += 1
|
||||||
$0.offset -= 20.0
|
|
||||||
|
|
||||||
XCTAssertFalse($0.skipButtonDisabled)
|
XCTAssertFalse($0.skipButtonDisabled)
|
||||||
XCTAssertFalse($0.backButtonDisabled)
|
XCTAssertFalse($0.backButtonDisabled)
|
||||||
XCTAssertEqual($0.currentStep, $0.steps[2])
|
XCTAssertEqual($0.currentStep, $0.steps[2])
|
||||||
|
XCTAssertEqual($0.offset, -40.0)
|
||||||
XCTAssertEqual($0.progress, 75)
|
XCTAssertEqual($0.progress, 75)
|
||||||
}
|
}
|
||||||
|
|
||||||
store.send(.next) {
|
store.send(.next) {
|
||||||
$0.index += 1
|
$0.index += 1
|
||||||
$0.offset -= 20.0
|
|
||||||
|
|
||||||
XCTAssertTrue($0.skipButtonDisabled)
|
XCTAssertTrue($0.skipButtonDisabled)
|
||||||
XCTAssertFalse($0.backButtonDisabled)
|
XCTAssertFalse($0.backButtonDisabled)
|
||||||
XCTAssertEqual($0.currentStep, $0.steps[3])
|
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)
|
XCTAssertEqual($0.progress, 100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDecrementingOnboarding() {
|
func testDecrementingOnboarding() {
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: OnboardingState(
|
initialState: OnboardingState(index: 2),
|
||||||
index: 2,
|
|
||||||
offset: .zero - 20.0 - 20.0
|
|
||||||
),
|
|
||||||
reducer: onboardingReducer,
|
reducer: onboardingReducer,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
|
||||||
store.send(.back) {
|
store.send(.back) {
|
||||||
$0.index -= 1
|
$0.index -= 1
|
||||||
$0.offset += 20.0
|
|
||||||
|
|
||||||
XCTAssertFalse($0.skipButtonDisabled)
|
XCTAssertFalse($0.skipButtonDisabled)
|
||||||
XCTAssertFalse($0.backButtonDisabled)
|
XCTAssertFalse($0.backButtonDisabled)
|
||||||
XCTAssertEqual($0.currentStep, $0.steps[1])
|
XCTAssertEqual($0.currentStep, $0.steps[1])
|
||||||
|
XCTAssertEqual($0.offset, -20.0)
|
||||||
XCTAssertEqual($0.progress, 50)
|
XCTAssertEqual($0.progress, 50)
|
||||||
}
|
}
|
||||||
|
|
||||||
store.send(.back) {
|
store.send(.back) {
|
||||||
$0.index -= 1
|
$0.index -= 1
|
||||||
$0.offset += 20.0
|
|
||||||
|
|
||||||
XCTAssertFalse($0.skipButtonDisabled)
|
XCTAssertFalse($0.skipButtonDisabled)
|
||||||
XCTAssertTrue($0.backButtonDisabled)
|
XCTAssertTrue($0.backButtonDisabled)
|
||||||
XCTAssertEqual($0.currentStep, $0.steps[0])
|
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)
|
XCTAssertEqual($0.progress, 25)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSkipOnboarding() {
|
func testSkipOnboarding() {
|
||||||
let initialIndex = 1
|
let initialIndex = 1
|
||||||
let initialOffset: CGFloat = .zero - 20.0
|
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: OnboardingState(
|
initialState: OnboardingState(index: initialIndex),
|
||||||
index: initialIndex,
|
|
||||||
offset: initialOffset
|
|
||||||
),
|
|
||||||
reducer: onboardingReducer,
|
reducer: onboardingReducer,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
|
||||||
store.send(.skip) {
|
store.send(.skip) {
|
||||||
$0.index = $0.steps.count - 1
|
$0.index = $0.steps.count - 1
|
||||||
$0.offset = initialOffset
|
|
||||||
$0.skippedAtindex = initialIndex
|
$0.skippedAtindex = initialIndex
|
||||||
|
|
||||||
XCTAssertTrue($0.skipButtonDisabled)
|
XCTAssertTrue($0.skipButtonDisabled)
|
||||||
XCTAssertFalse($0.backButtonDisabled)
|
XCTAssertFalse($0.backButtonDisabled)
|
||||||
XCTAssertEqual($0.currentStep, $0.steps[3])
|
XCTAssertEqual($0.currentStep, $0.steps[3])
|
||||||
|
XCTAssertEqual($0.offset, -60.0)
|
||||||
XCTAssertEqual($0.progress, 100)
|
XCTAssertEqual($0.progress, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
store.send(.back) {
|
store.send(.back) {
|
||||||
$0.skippedAtindex = nil
|
$0.skippedAtindex = nil
|
||||||
$0.index = initialIndex
|
$0.index = initialIndex
|
||||||
$0.offset = initialOffset
|
|
||||||
|
|
||||||
XCTAssertFalse($0.skipButtonDisabled)
|
XCTAssertFalse($0.skipButtonDisabled)
|
||||||
XCTAssertFalse($0.backButtonDisabled)
|
XCTAssertFalse($0.backButtonDisabled)
|
||||||
XCTAssertEqual($0.currentStep, $0.steps[1])
|
XCTAssertEqual($0.currentStep, $0.steps[1])
|
||||||
|
XCTAssertEqual($0.offset, -20.0)
|
||||||
XCTAssertEqual($0.progress, 50)
|
XCTAssertEqual($0.progress, 50)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue