Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OnboardingPreview #594

Merged
merged 11 commits into from
Jun 30, 2023
587 changes: 587 additions & 0 deletions App/BabylonWallet.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D7178C92A4AD84F005C89FF"
BuildableName = "OnboardingPreview.app"
BlueprintName = "OnboardingPreview"
ReferencedContainer = "container:BabylonWallet.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug-Dev"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug-Dev"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D7178C92A4AD84F005C89FF"
BuildableName = "OnboardingPreview.app"
BlueprintName = "OnboardingPreview"
ReferencedContainer = "container:BabylonWallet.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D7178C92A4AD84F005C89FF"
BuildableName = "OnboardingPreview.app"
BlueprintName = "OnboardingPreview"
ReferencedContainer = "container:BabylonWallet.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug-Dev">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
6 changes: 6 additions & 0 deletions App/Previews/OnboardingPreview/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
10 changes: 10 additions & 0 deletions App/Previews/OnboardingPreview/OnboardingPreview.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>
</plist>
52 changes: 52 additions & 0 deletions App/Previews/OnboardingPreview/OnboardingPreviewApp.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import FeaturesPreviewerFeature
import OnboardingFeature
import SwiftUI

// MARK: - OnboardingPreviewApp
@main
struct OnboardingPreviewApp: App {
var body: some Scene {
FeaturesPreviewer<OnboardingCoordinator>.delegateAction {
guard case let .completed(result) = $0 else {
return nil
}

return result.map(TaskResult.success)
} withReducer: { onboarding in
CombineReducers {
onboarding
.dependency(\.userDefaultsClient, .noop)
.dependency(\.appPreferencesClient, .previewValue)
.dependency(\.localAuthenticationClient.queryConfig) { .biometricsAndPasscodeSetUp }

Reduce { _, action in
if case .child(.previewResult(.delegate(.restart))) = action {
return .run { _ in
@Dependency(\.appPreferencesClient) var appPreferences
try? await appPreferences.deleteProfileAndFactorSources(false)
}
}

return .none
}
}
._printChanges()
}
}
}

// MARK: - OnboardingCoordinator + PreviewedFeature
extension OnboardingCoordinator: PreviewedFeature {
public typealias ResultFromFeature = Profile.Network.Account
}

// MARK: - OnboardingCoordinator + EmptyInitializable
extension OnboardingCoordinator: EmptyInitializable {}

// MARK: - OnboardingCoordinator.State + EmptyInitializable
extension OnboardingCoordinator.State: EmptyInitializable {}

// MARK: - OnboardingCoordinator.View + FeatureView
extension OnboardingCoordinator.View: FeatureView {
public typealias Feature = OnboardingCoordinator
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,9 @@ extension CreateAccountCoordinator {
}
}
}

extension CreateAccountCoordinator.State {
public var lastStepState: CreateAccountCoordinator.Destinations.State? {
path.last
maciek-rdx marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public struct OnboardingCoordinator: Sendable, FeatureReducer {
}

public enum DelegateAction: Sendable, Equatable {
case completed
case completed(Profile.Network.Account?)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to complete the onboarding without an account?

Copy link
Contributor Author

@maciek-rdx maciek-rdx Jun 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question! So we send .completed in two paths:

  1. Via New Wallet
  2. Via Restore From Backup

Currently, with @CyonAlexRDX we agreed to focus solely on the New Wallet/Device factor source kind, so the Restore From Backup path will return nil

}

public enum InternalAction: Sendable, Equatable {
Expand Down Expand Up @@ -48,7 +48,8 @@ public struct OnboardingCoordinator: Sendable, FeatureReducer {
public func reduce(into state: inout State, internalAction: InternalAction) -> EffectTask<Action> {
switch internalAction {
case .commitEphemeralResult(.success):
return .send(.delegate(.completed))
return sendDelegateCompleted(state: state)

case let .commitEphemeralResult(.failure(error)):
fatalError("Unable to use app, failed to commit profile, error: \(String(describing: error))")
}
Expand All @@ -65,7 +66,7 @@ public struct OnboardingCoordinator: Sendable, FeatureReducer {
return .none

case .startup(.delegate(.completed)):
return .send(.delegate(.completed))
return sendDelegateCompleted(state: state)

case .createAccountCoordinator(.delegate(.completed)):
return .task {
Expand All @@ -74,8 +75,26 @@ public struct OnboardingCoordinator: Sendable, FeatureReducer {
}
return .internal(.commitEphemeralResult(result))
}

default:
return .none
}
}

private func sendDelegateCompleted(state: State) -> EffectTask<Action> {
.send(.delegate(.completed(state.newAccount)))
}
Comment on lines +84 to +86
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should avoid special functions like this, they hide what's going on

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before that, we've had two places where .send(.delegate(.completed))) has been returned. My goal was to keep them together to eliminate the duplication and centralize the provision of state.newAccount. I don't see it as being super wrong, I pretty much followed this best practice, but fine to revert.

Just let me know @kugel3 👍

}

extension OnboardingCoordinator.State {
fileprivate var newAccount: Profile.Network.Account? {
guard
let lastStepState = (/Self.createAccountCoordinator).extract(from: self)?.lastStepState,
let newAccountCompletionState = (/CreateAccountCoordinator.Destinations.State.step3_completion).extract(from: lastStepState)
else {
return nil
}

return newAccountCompletionState.account
}
}