Merge branch 'main' into 147_phrase_preamble_screen
This commit is contained in:
commit
28c7cf98b5
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0xA0",
|
||||||
|
"green" : "0x81",
|
||||||
|
"red" : "0x6E"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0xA0",
|
||||||
|
"green" : "0x81",
|
||||||
|
"red" : "0x6E"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -113,7 +113,9 @@ extension AppState {
|
||||||
static var placeholder: Self {
|
static var placeholder: Self {
|
||||||
.init(
|
.init(
|
||||||
homeState: .placeholder,
|
homeState: .placeholder,
|
||||||
onboardingState: .init(),
|
onboardingState: .init(
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
phraseValidationState: RecoveryPhraseValidationState.placeholder,
|
phraseValidationState: RecoveryPhraseValidationState.placeholder,
|
||||||
phraseDisplayState: RecoveryPhraseDisplayState(
|
phraseDisplayState: RecoveryPhraseDisplayState(
|
||||||
phrase: .placeholder
|
phrase: .placeholder
|
||||||
|
|
|
@ -20,12 +20,15 @@ struct AppView: View {
|
||||||
.navigationViewStyle(StackNavigationViewStyle())
|
.navigationViewStyle(StackNavigationViewStyle())
|
||||||
|
|
||||||
case .onboarding:
|
case .onboarding:
|
||||||
OnboardingScreen(
|
NavigationView {
|
||||||
store: store.scope(
|
OnboardingScreen(
|
||||||
state: \.onboardingState,
|
store: store.scope(
|
||||||
action: AppAction.onboarding
|
state: \.onboardingState,
|
||||||
|
action: AppAction.onboarding
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
|
.navigationViewStyle(StackNavigationViewStyle())
|
||||||
|
|
||||||
case .startup:
|
case .startup:
|
||||||
ZStack(alignment: .topTrailing) {
|
ZStack(alignment: .topTrailing) {
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// ImportWalletStore.swift
|
||||||
|
// secant-testnet
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 02/25/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import ComposableArchitecture
|
||||||
|
|
||||||
|
typealias ImportWalletStore = Store<ImportWalletState, ImportWalletAction>
|
||||||
|
|
||||||
|
struct ImportWalletState: Equatable {
|
||||||
|
@BindableState var importedSeedPhrase: String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ImportWalletAction: Equatable, BindableAction {
|
||||||
|
case importRecoveryPhrase
|
||||||
|
case importPrivateOrViewingKey
|
||||||
|
case binding(BindingAction<ImportWalletState>)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ImportWalletEnvironment { }
|
||||||
|
|
||||||
|
extension ImportWalletEnvironment {
|
||||||
|
static let demo = Self()
|
||||||
|
|
||||||
|
static let live = Self()
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias ImportWalletReducer = Reducer<ImportWalletState, ImportWalletAction, ImportWalletEnvironment>
|
||||||
|
|
||||||
|
extension ImportWalletReducer {
|
||||||
|
static let `default` = ImportWalletReducer { _, action, _ in
|
||||||
|
switch action {
|
||||||
|
case .importRecoveryPhrase:
|
||||||
|
// TODO: once connected to SDK, use the state.importedSeedPhrase (Issue #166)
|
||||||
|
return .none
|
||||||
|
|
||||||
|
case .importPrivateOrViewingKey:
|
||||||
|
return .none
|
||||||
|
|
||||||
|
case .binding:
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.binding()
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
//
|
||||||
|
// ImportSeedEditor.swift
|
||||||
|
// secant-testnet
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 02/25/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import ComposableArchitecture
|
||||||
|
|
||||||
|
struct ImportSeedEditor: View {
|
||||||
|
var store: ImportWalletStore
|
||||||
|
|
||||||
|
/// Clearance of the black color for the TextEditor under the text (.dark colorScheme)
|
||||||
|
init(store: ImportWalletStore) {
|
||||||
|
self.store = store
|
||||||
|
UITextView.appearance().backgroundColor = .clear
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
WithViewStore(store) { viewStore in
|
||||||
|
TextEditor(text: viewStore.binding(\.$importedSeedPhrase))
|
||||||
|
.importSeedEditorModifier()
|
||||||
|
.padding(28)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ImportSeedEditorModifier: ViewModifier {
|
||||||
|
func body(content: Content) -> some View {
|
||||||
|
content
|
||||||
|
.foregroundColor(Asset.Colors.Text.importSeedEditor.color)
|
||||||
|
.padding()
|
||||||
|
.background(Color.white)
|
||||||
|
.cornerRadius(4)
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: 4)
|
||||||
|
.stroke(Color.black, lineWidth: 2)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension View {
|
||||||
|
func importSeedEditorModifier() -> some View {
|
||||||
|
modifier(ImportSeedEditorModifier())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ImportSeedInputField_Previews: PreviewProvider {
|
||||||
|
static let width: CGFloat = 400
|
||||||
|
static let height: CGFloat = 200
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
Group {
|
||||||
|
ImportSeedEditor(store: .demo)
|
||||||
|
.frame(width: width, height: height)
|
||||||
|
.applyScreenBackground()
|
||||||
|
.preferredColorScheme(.light)
|
||||||
|
|
||||||
|
ImportSeedEditor(store: .demo)
|
||||||
|
.frame(width: width, height: height)
|
||||||
|
.applyScreenBackground()
|
||||||
|
.preferredColorScheme(.dark)
|
||||||
|
}
|
||||||
|
.previewLayout(.fixed(width: width + 50, height: height + 50))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
//
|
||||||
|
// ImportWalletView.swift
|
||||||
|
// secant-testnet
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 02/25/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import ComposableArchitecture
|
||||||
|
|
||||||
|
struct ImportWalletView: View {
|
||||||
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
|
||||||
|
var store: ImportWalletStore
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
WithViewStore(store) { viewStore in
|
||||||
|
VStack {
|
||||||
|
VStack(alignment: .leading, spacing: 30) {
|
||||||
|
HStack {
|
||||||
|
Button("Back") { presentationMode.wrappedValue.dismiss() }
|
||||||
|
.navigationButtonStyle
|
||||||
|
.frame(width: 75, height: 40)
|
||||||
|
|
||||||
|
Text("importWallet.title")
|
||||||
|
.titleText()
|
||||||
|
}
|
||||||
|
|
||||||
|
Text("importWallet.description")
|
||||||
|
.paragraphText()
|
||||||
|
.lineSpacing(4)
|
||||||
|
.opacity(0.53)
|
||||||
|
}
|
||||||
|
.padding(18)
|
||||||
|
|
||||||
|
ImportSeedEditor(store: store)
|
||||||
|
.frame(width: nil, height: 200, alignment: .center)
|
||||||
|
|
||||||
|
Button("importWallet.button.importPhrase") {
|
||||||
|
viewStore.send(.importRecoveryPhrase)
|
||||||
|
}
|
||||||
|
.activeButtonStyle
|
||||||
|
.importWalletButtonLayout()
|
||||||
|
|
||||||
|
Button("importWallet.button.importPrivateKey") {
|
||||||
|
viewStore.send(.importPrivateOrViewingKey)
|
||||||
|
}
|
||||||
|
.secondaryButtonStyle
|
||||||
|
.importWalletButtonLayout()
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.navigationBarHidden(true)
|
||||||
|
.applyScreenBackground()
|
||||||
|
.scrollableWhenScaledUp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// swiftlint:disable:next private_over_fileprivate strict_fileprivate
|
||||||
|
fileprivate struct ImportWalletButtonLayout: ViewModifier {
|
||||||
|
func body(content: Content) -> some View {
|
||||||
|
content
|
||||||
|
.frame(
|
||||||
|
minWidth: 0,
|
||||||
|
maxWidth: .infinity,
|
||||||
|
minHeight: 64,
|
||||||
|
maxHeight: .infinity,
|
||||||
|
alignment: .center
|
||||||
|
)
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.padding(.horizontal, 28)
|
||||||
|
.transition(.opacity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension View {
|
||||||
|
func importWalletButtonLayout() -> some View {
|
||||||
|
modifier(ImportWalletButtonLayout())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ImportWalletStore {
|
||||||
|
static let demo = Store(
|
||||||
|
initialState: .placeholder,
|
||||||
|
reducer: .default,
|
||||||
|
environment: .demo
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ImportWalletState {
|
||||||
|
static let placeholder = ImportWalletState(importedSeedPhrase: "")
|
||||||
|
|
||||||
|
static let live = ImportWalletState(importedSeedPhrase: "")
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ImportWalletView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
ImportWalletView(store: .demo)
|
||||||
|
.preferredColorScheme(.light)
|
||||||
|
|
||||||
|
ImportWalletView(store: .demo)
|
||||||
|
.preferredColorScheme(.dark)
|
||||||
|
|
||||||
|
ImportWalletView(store: .demo)
|
||||||
|
.previewDevice(PreviewDevice(rawValue: "iPhone SE (2nd generation)"))
|
||||||
|
.preferredColorScheme(.light)
|
||||||
|
.environment(\.sizeCategory, .accessibilityLarge)
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,14 @@ import Foundation
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import ComposableArchitecture
|
import ComposableArchitecture
|
||||||
|
|
||||||
|
typealias OnboardingViewStore = ViewStore<OnboardingState, OnboardingAction>
|
||||||
|
|
||||||
struct OnboardingState: Equatable {
|
struct OnboardingState: Equatable {
|
||||||
|
enum Route: Equatable, CaseIterable {
|
||||||
|
case createNewWallet
|
||||||
|
case importExistingWallet
|
||||||
|
}
|
||||||
|
|
||||||
struct Step: Equatable, Identifiable {
|
struct Step: Equatable, Identifiable {
|
||||||
let id: UUID
|
let id: UUID
|
||||||
let title: LocalizedStringKey
|
let title: LocalizedStringKey
|
||||||
|
@ -21,7 +28,8 @@ struct OnboardingState: Equatable {
|
||||||
var steps: IdentifiedArrayOf<Step> = Self.onboardingSteps
|
var steps: IdentifiedArrayOf<Step> = Self.onboardingSteps
|
||||||
var index = 0
|
var index = 0
|
||||||
var skippedAtindex: Int?
|
var skippedAtindex: Int?
|
||||||
|
var route: Route?
|
||||||
|
|
||||||
var currentStep: Step { steps[index] }
|
var currentStep: Step { steps[index] }
|
||||||
var isFinalStep: Bool { steps.count == index + 1 }
|
var isFinalStep: Bool { steps.count == index + 1 }
|
||||||
var isInitialStep: Bool { index == 0 }
|
var isInitialStep: Bool { index == 0 }
|
||||||
|
@ -32,20 +40,43 @@ struct OnboardingState: Equatable {
|
||||||
guard index != 0 else { return .zero }
|
guard index != 0 else { return .zero }
|
||||||
return stepOffset * CGFloat(index)
|
return stepOffset * CGFloat(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Import Wallet
|
||||||
|
var importWalletState: ImportWalletState
|
||||||
|
}
|
||||||
|
|
||||||
|
extension OnboardingViewStore {
|
||||||
|
func bindingForRoute(_ route: OnboardingState.Route) -> Binding<Bool> {
|
||||||
|
self.binding(
|
||||||
|
get: { $0.route == route },
|
||||||
|
send: { isActive in
|
||||||
|
return .updateRoute(isActive ? route : nil)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum OnboardingAction: Equatable {
|
enum OnboardingAction: Equatable {
|
||||||
case next
|
case next
|
||||||
case back
|
case back
|
||||||
case skip
|
case skip
|
||||||
|
case updateRoute(OnboardingState.Route?)
|
||||||
case createNewWallet
|
case createNewWallet
|
||||||
case importExistingWallet
|
case importExistingWallet
|
||||||
|
case importWallet(ImportWalletAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias OnboardingReducer = Reducer<OnboardingState, OnboardingAction, Void>
|
typealias OnboardingReducer = Reducer<OnboardingState, OnboardingAction, Void>
|
||||||
|
|
||||||
extension OnboardingReducer {
|
extension OnboardingReducer {
|
||||||
static let `default` = Reducer<OnboardingState, OnboardingAction, Void> { state, action, _ in
|
static let `default` = OnboardingReducer.combine(
|
||||||
|
[
|
||||||
|
onboardingReducer,
|
||||||
|
importWalletReducer
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
private static let onboardingReducer = OnboardingReducer { state, action, _ in
|
||||||
switch action {
|
switch action {
|
||||||
case .back:
|
case .back:
|
||||||
guard state.index > 0 else { return .none }
|
guard state.index > 0 else { return .none }
|
||||||
|
@ -68,11 +99,26 @@ extension OnboardingReducer {
|
||||||
state.index = state.steps.count - 1
|
state.index = state.steps.count - 1
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
|
case .updateRoute(let route):
|
||||||
|
state.route = route
|
||||||
|
return .none
|
||||||
|
|
||||||
case .createNewWallet:
|
case .createNewWallet:
|
||||||
|
state.route = .createNewWallet
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .importExistingWallet:
|
case .importExistingWallet:
|
||||||
|
state.route = .importExistingWallet
|
||||||
|
return .none
|
||||||
|
|
||||||
|
case .importWallet(let route):
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static let importWalletReducer: OnboardingReducer = ImportWalletReducer.default.pullback(
|
||||||
|
state: \OnboardingState.importWalletState,
|
||||||
|
action: /OnboardingAction.importWallet,
|
||||||
|
environment: { _ in ImportWalletEnvironment.live }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,9 @@ struct Onboarding_Previews: PreviewProvider {
|
||||||
Group {
|
Group {
|
||||||
OnboardingView(
|
OnboardingView(
|
||||||
store: Store(
|
store: Store(
|
||||||
initialState: OnboardingState(),
|
initialState: OnboardingState(
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
|
|
@ -92,6 +92,7 @@ internal enum Asset {
|
||||||
internal static let body = ColorAsset(name: "Body")
|
internal static let body = ColorAsset(name: "Body")
|
||||||
internal static let button = ColorAsset(name: "Button")
|
internal static let button = ColorAsset(name: "Button")
|
||||||
internal static let heading = ColorAsset(name: "Heading")
|
internal static let heading = ColorAsset(name: "Heading")
|
||||||
|
internal static let importSeedEditor = ColorAsset(name: "ImportSeedEditor")
|
||||||
internal static let medium = ColorAsset(name: "Medium")
|
internal static let medium = ColorAsset(name: "Medium")
|
||||||
internal static let regular = ColorAsset(name: "Regular")
|
internal static let regular = ColorAsset(name: "Regular")
|
||||||
internal static let secondaryButtonText = ColorAsset(name: "SecondaryButtonText")
|
internal static let secondaryButtonText = ColorAsset(name: "SecondaryButtonText")
|
||||||
|
|
|
@ -41,14 +41,12 @@
|
||||||
"validationFailed.description" = "Your placed words did not match your secret recovery phrase.";
|
"validationFailed.description" = "Your placed words did not match your secret recovery phrase.";
|
||||||
"validationFailed.incorrectBackupDescription" = "Remember, you can't recover your funds if you lose (or incorrectly save) these 24 words.";
|
"validationFailed.incorrectBackupDescription" = "Remember, you can't recover your funds if you lose (or incorrectly save) these 24 words.";
|
||||||
"validationFailed.button.tryAgain" = "I'm ready to try again";
|
"validationFailed.button.tryAgain" = "I'm ready to try again";
|
||||||
|
|
||||||
// MARK: - Recovery Phrase Test Preamble
|
// MARK: - Import Wallet Screen
|
||||||
"recoveryPhraseTestPreamble.title" = "First things first";
|
"importWallet.title" = "Wallet Import";
|
||||||
"recoveryPhraseTestPreamble.paragraph1" = "It is important to understand that you are in charge here. Great, right? YOU get to be the bank!";
|
"importWallet.description" = "You can import your backed up wallet by entering your backup recovery phrase (aka seed phrase) now.";
|
||||||
"recoveryPhraseTestPreamble.paragraph2" = "But it also means that YOU are the customer, and you need to be self-reliant.";
|
"importWallet.button.importPhrase" = "Import Recovery Phrase";
|
||||||
"recoveryPhraseTestPreamble.paragraph3" = "So how do you recover funds that you've hidden on a completely decentralized and private block-chain?";
|
"importWallet.button.importPrivateKey" = "Import a private or viewing key";
|
||||||
"recoveryPhraseTestPreamble.button.goNext" = "By understanding and preparing";
|
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Common & Shared
|
// MARK: - Common & Shared
|
||||||
"Back" = "Back";
|
"Back" = "Back";
|
||||||
|
|
|
@ -127,7 +127,10 @@ extension OnboardingContentView {
|
||||||
struct OnboardingContentView_Previews: PreviewProvider {
|
struct OnboardingContentView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let store = Store(
|
let store = Store(
|
||||||
initialState: OnboardingState(index: 0),
|
initialState: OnboardingState(
|
||||||
|
index: 0,
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
|
|
@ -23,12 +23,12 @@ struct OnboardingFooterView: View {
|
||||||
viewStore.send(.createNewWallet)
|
viewStore.send(.createNewWallet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.createButtonStyle
|
.activeButtonStyle
|
||||||
.onboardingFooterButtonLayout()
|
.onboardingFooterButtonLayout()
|
||||||
|
|
||||||
Button("onboarding.button.importWallet") {
|
Button("onboarding.button.importWallet") {
|
||||||
withAnimation(.easeInOut(duration: animationDuration)) {
|
withAnimation(.easeInOut(duration: animationDuration)) {
|
||||||
viewStore.send(.createNewWallet)
|
viewStore.send(.importExistingWallet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.secondaryButtonStyle
|
.secondaryButtonStyle
|
||||||
|
@ -52,6 +52,17 @@ struct OnboardingFooterView: View {
|
||||||
.padding(.vertical, 20)
|
.padding(.vertical, 20)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.navigationLinkEmpty(
|
||||||
|
isActive: viewStore.bindingForRoute(.importExistingWallet),
|
||||||
|
destination: {
|
||||||
|
ImportWalletView(
|
||||||
|
store: store.scope(
|
||||||
|
state: \.importWalletState,
|
||||||
|
action: OnboardingAction.importWallet
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +86,10 @@ extension View {
|
||||||
struct OnboardingFooterView_Previews: PreviewProvider {
|
struct OnboardingFooterView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let store = Store<OnboardingState, OnboardingAction>(
|
let store = Store<OnboardingState, OnboardingAction>(
|
||||||
initialState: OnboardingState(index: 3),
|
initialState: OnboardingState(
|
||||||
|
index: 3,
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
|
|
@ -63,7 +63,10 @@ struct OnboardingHeaderView: View {
|
||||||
struct OnboardingHeaderView_Previews: PreviewProvider {
|
struct OnboardingHeaderView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let store = Store<OnboardingState, OnboardingAction>(
|
let store = Store<OnboardingState, OnboardingAction>(
|
||||||
initialState: OnboardingState(index: 0),
|
initialState: OnboardingState(
|
||||||
|
index: 0,
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,7 +10,6 @@ import ComposableArchitecture
|
||||||
|
|
||||||
struct OnboardingScreen: View {
|
struct OnboardingScreen: View {
|
||||||
let store: Store<OnboardingState, OnboardingAction>
|
let store: Store<OnboardingState, OnboardingAction>
|
||||||
let animationDuration: CGFloat = 0.8
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
GeometryReader { proxy in
|
GeometryReader { proxy in
|
||||||
|
@ -42,6 +41,7 @@ struct OnboardingScreen: View {
|
||||||
OnboardingFooterView(store: store)
|
OnboardingFooterView(store: store)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.navigationBarHidden(true)
|
||||||
.applyScreenBackground()
|
.applyScreenBackground()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,9 @@ struct OnboardingScreen_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
OnboardingScreen(
|
OnboardingScreen(
|
||||||
store: Store(
|
store: Store(
|
||||||
initialState: OnboardingState(),
|
initialState: OnboardingState(
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
@ -60,7 +62,9 @@ struct OnboardingScreen_Previews: PreviewProvider {
|
||||||
|
|
||||||
OnboardingScreen(
|
OnboardingScreen(
|
||||||
store: Store(
|
store: Store(
|
||||||
initialState: OnboardingState(),
|
initialState: OnboardingState(
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
@ -70,7 +74,9 @@ struct OnboardingScreen_Previews: PreviewProvider {
|
||||||
|
|
||||||
OnboardingScreen(
|
OnboardingScreen(
|
||||||
store: Store(
|
store: Store(
|
||||||
initialState: OnboardingState(),
|
initialState: OnboardingState(
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
@ -80,7 +86,9 @@ struct OnboardingScreen_Previews: PreviewProvider {
|
||||||
|
|
||||||
OnboardingScreen(
|
OnboardingScreen(
|
||||||
store: Store(
|
store: Store(
|
||||||
initialState: OnboardingState(),
|
initialState: OnboardingState(
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
@ -90,7 +98,9 @@ struct OnboardingScreen_Previews: PreviewProvider {
|
||||||
|
|
||||||
OnboardingScreen(
|
OnboardingScreen(
|
||||||
store: Store(
|
store: Store(
|
||||||
initialState: OnboardingState(),
|
initialState: OnboardingState(
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
@ -100,7 +110,9 @@ struct OnboardingScreen_Previews: PreviewProvider {
|
||||||
|
|
||||||
OnboardingScreen(
|
OnboardingScreen(
|
||||||
store: Store(
|
store: Store(
|
||||||
initialState: OnboardingState(),
|
initialState: OnboardingState(
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,7 +9,6 @@ import SwiftUI
|
||||||
|
|
||||||
struct OnboardingProgressStyle: ProgressViewStyle {
|
struct OnboardingProgressStyle: ProgressViewStyle {
|
||||||
let height: CGFloat = 3
|
let height: CGFloat = 3
|
||||||
let animation: Animation = .easeInOut
|
|
||||||
let gradient = LinearGradient(
|
let gradient = LinearGradient(
|
||||||
colors: [
|
colors: [
|
||||||
Asset.Colors.ProgressIndicator.gradientLeft.color,
|
Asset.Colors.ProgressIndicator.gradientLeft.color,
|
||||||
|
@ -53,7 +52,7 @@ struct OnboardingProgressStyle: ProgressViewStyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(height: height)
|
.frame(height: height)
|
||||||
.animation(animation)
|
// FIXME: .animation(.easeInOut) breaks the Onboarding UI when onAppear, fallback to .linear for now
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,9 @@ import ComposableArchitecture
|
||||||
class OnboardingStoreTests: XCTestCase {
|
class OnboardingStoreTests: XCTestCase {
|
||||||
func testIncrementingOnboarding() {
|
func testIncrementingOnboarding() {
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: OnboardingState(),
|
initialState: OnboardingState(
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
@ -50,7 +52,10 @@ class OnboardingStoreTests: XCTestCase {
|
||||||
|
|
||||||
func testIncrementingPastTotalStepsDoesNothing() {
|
func testIncrementingPastTotalStepsDoesNothing() {
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: OnboardingState(index: 3),
|
initialState: OnboardingState(
|
||||||
|
index: 3,
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
@ -74,7 +79,10 @@ class OnboardingStoreTests: XCTestCase {
|
||||||
|
|
||||||
func testDecrementingOnboarding() {
|
func testDecrementingOnboarding() {
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: OnboardingState(index: 2),
|
initialState: OnboardingState(
|
||||||
|
index: 2,
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
@ -102,7 +110,9 @@ class OnboardingStoreTests: XCTestCase {
|
||||||
|
|
||||||
func testDecrementingPastFirstStepDoesNothing() {
|
func testDecrementingPastFirstStepDoesNothing() {
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: OnboardingState(),
|
initialState: OnboardingState(
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
@ -128,7 +138,10 @@ class OnboardingStoreTests: XCTestCase {
|
||||||
let initialIndex = 1
|
let initialIndex = 1
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: OnboardingState(index: initialIndex),
|
initialState: OnboardingState(
|
||||||
|
index: initialIndex,
|
||||||
|
importWalletState: .placeholder
|
||||||
|
),
|
||||||
reducer: OnboardingReducer.default,
|
reducer: OnboardingReducer.default,
|
||||||
environment: ()
|
environment: ()
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue