- reimagined the way the onboarding is composed - the bare bone is now a VStack instead of a ZStack - there is no use of GeometryReader anymore
This commit is contained in:
parent
d11a67cee1
commit
1cf49e7b72
|
@ -12,7 +12,7 @@ struct OnboardingScreen: View {
|
||||||
let store: Store<OnboardingFlowReducer.State, OnboardingFlowReducer.Action>
|
let store: Store<OnboardingFlowReducer.State, OnboardingFlowReducer.Action>
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
GeometryReader { proxy in
|
VStack {
|
||||||
ZStack {
|
ZStack {
|
||||||
OnboardingHeaderView(
|
OnboardingHeaderView(
|
||||||
store: store.scope(
|
store: store.scope(
|
||||||
|
@ -32,14 +32,12 @@ struct OnboardingScreen: View {
|
||||||
)
|
)
|
||||||
.zIndex(1)
|
.zIndex(1)
|
||||||
|
|
||||||
OnboardingContentView(
|
OnboardingContentView(store: store)
|
||||||
store: store,
|
|
||||||
width: proxy.size.width,
|
|
||||||
height: proxy.size.height
|
|
||||||
)
|
|
||||||
|
|
||||||
OnboardingFooterView(store: store)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
OnboardingFooterView(store: store)
|
||||||
}
|
}
|
||||||
.navigationBarHidden(true)
|
.navigationBarHidden(true)
|
||||||
.applyScreenBackground()
|
.applyScreenBackground()
|
||||||
|
@ -81,7 +79,8 @@ struct OnboardingScreen_Previews: PreviewProvider {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.preferredColorScheme(.light)
|
.preferredColorScheme(.light)
|
||||||
.previewDevice(PreviewDevice(rawValue: "iPhone 12 Pro"))
|
.previewDevice(PreviewDevice(rawValue: "iPhone 14 Pro"))
|
||||||
|
.environment(\.sizeCategory, .accessibilityLarge)
|
||||||
|
|
||||||
OnboardingScreen(
|
OnboardingScreen(
|
||||||
store: Store(
|
store: Store(
|
||||||
|
@ -114,6 +113,6 @@ struct OnboardingScreen_Previews: PreviewProvider {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.preferredColorScheme(.dark)
|
.preferredColorScheme(.dark)
|
||||||
.previewDevice(PreviewDevice(rawValue: "iPhone 12 Pro"))
|
.previewDevice(PreviewDevice(rawValue: "iPhone 14 Pro"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,69 +10,51 @@ import ComposableArchitecture
|
||||||
|
|
||||||
struct OnboardingContentView: View {
|
struct OnboardingContentView: View {
|
||||||
let store: Store<OnboardingFlowReducer.State, OnboardingFlowReducer.Action>
|
let store: Store<OnboardingFlowReducer.State, OnboardingFlowReducer.Action>
|
||||||
let width: Double
|
|
||||||
let height: Double
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
WithViewStore(self.store) { viewStore in
|
WithViewStore(self.store) { viewStore in
|
||||||
let scale = imageScale
|
|
||||||
let imageWidth: CGFloat = width * scale
|
|
||||||
let imageXOffset: CGFloat = (width - imageWidth) / 2
|
|
||||||
|
|
||||||
let image = viewStore.steps[viewStore.index].background
|
let image = viewStore.steps[viewStore.index].background
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.scaledToFit()
|
||||||
.frame(width: imageWidth)
|
|
||||||
.offset(x: imageXOffset)
|
|
||||||
|
|
||||||
let title = Text(viewStore.steps[viewStore.index].title)
|
let title = Text(viewStore.steps[viewStore.index].title)
|
||||||
.titleText()
|
.titleText()
|
||||||
.lineLimit(0)
|
.lineLimit(0)
|
||||||
.minimumScaleFactor(0.1)
|
.minimumScaleFactor(0.1)
|
||||||
.padding(EdgeInsets(top: 0, leading: 10, bottom: 5, trailing: 10))
|
.padding(.vertical, 10)
|
||||||
|
|
||||||
let text = Text(viewStore.steps[viewStore.index].description)
|
let text = Text(viewStore.steps[viewStore.index].description)
|
||||||
.paragraphText()
|
.paragraphText()
|
||||||
.lineSpacing(2)
|
.lineSpacing(2)
|
||||||
.padding(EdgeInsets(top: 0, leading: 10, bottom: 10, trailing: 10))
|
.minimumScaleFactor(0.1)
|
||||||
|
.padding(.horizontal, 20)
|
||||||
|
|
||||||
if viewStore.isFinalStep {
|
if viewStore.isFinalStep {
|
||||||
VStack(alignment: .leading) {
|
VStack {
|
||||||
title
|
HStack {
|
||||||
.padding(.top, 73 * imageScale)
|
title
|
||||||
|
.padding(.top, 60)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 20)
|
||||||
text
|
text
|
||||||
image
|
image
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VStack(alignment: .leading) {
|
VStack {
|
||||||
image
|
image
|
||||||
title
|
HStack {
|
||||||
|
title
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 20)
|
||||||
text
|
text
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Following computations are necessary to handle properly sizing and positioning of elements
|
|
||||||
/// on different devices (apects). iPhone SE and iPhone 8 are similar aspect family devices
|
|
||||||
/// while iPhone X, 11, etc are different family devices, capable to use more of the space.
|
|
||||||
extension OnboardingContentView {
|
|
||||||
var imageScale: CGFloat {
|
|
||||||
// Just to be sure that we counting with exactly 3 decimal points.
|
|
||||||
let aspectRatio = (floor(height / width * 1000)) / 1000
|
|
||||||
|
|
||||||
/// iPhone SE or iPhone 8 for example
|
|
||||||
if aspectRatio <= 1.725 {
|
|
||||||
return 0.7
|
|
||||||
} else {
|
|
||||||
return 1.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OnboardingContentView_Previews: PreviewProvider {
|
struct OnboardingContentView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let store = Store(
|
let store = Store(
|
||||||
|
@ -119,9 +101,9 @@ extension OnboardingContentView_Previews {
|
||||||
.zIndex(1)
|
.zIndex(1)
|
||||||
|
|
||||||
OnboardingContentView(
|
OnboardingContentView(
|
||||||
store: store,
|
store: store
|
||||||
width: proxy.size.width,
|
// width: proxy.size.width,
|
||||||
height: proxy.size.height
|
// height: proxy.size.height
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,26 +15,27 @@ struct OnboardingFooterView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
WithViewStore(self.store) { viewStore in
|
WithViewStore(self.store) { viewStore in
|
||||||
VStack(spacing: 5) {
|
VStack(spacing: 5) {
|
||||||
Spacer()
|
|
||||||
|
|
||||||
if viewStore.isFinalStep {
|
if viewStore.isFinalStep {
|
||||||
Button("onboarding.button.newWallet") {
|
Button("onboarding.button.newWallet") {
|
||||||
viewStore.send(.createNewWallet, animation: .easeInOut(duration: animationDuration))
|
viewStore.send(.createNewWallet, animation: .easeInOut(duration: animationDuration))
|
||||||
}
|
}
|
||||||
.activeButtonStyle
|
.activeButtonStyle
|
||||||
.onboardingFooterButtonLayout()
|
.onboardingFooterButtonLayout()
|
||||||
|
.minimumScaleFactor(0.1)
|
||||||
|
|
||||||
Button("onboarding.button.importWallet") {
|
Button("onboarding.button.importWallet") {
|
||||||
viewStore.send(.importExistingWallet, animation: .easeInOut(duration: animationDuration))
|
viewStore.send(.importExistingWallet, animation: .easeInOut(duration: animationDuration))
|
||||||
}
|
}
|
||||||
.secondaryButtonStyle
|
.secondaryButtonStyle
|
||||||
.onboardingFooterButtonLayout()
|
.onboardingFooterButtonLayout()
|
||||||
|
.minimumScaleFactor(0.1)
|
||||||
} else {
|
} else {
|
||||||
Button("Next") {
|
Button("Next") {
|
||||||
viewStore.send(.next, animation: .easeInOut(duration: animationDuration))
|
viewStore.send(.next, animation: .easeInOut(duration: animationDuration))
|
||||||
}
|
}
|
||||||
.primaryButtonStyle
|
.primaryButtonStyle
|
||||||
.onboardingFooterButtonLayout()
|
.onboardingFooterButtonLayout()
|
||||||
|
.minimumScaleFactor(0.1)
|
||||||
|
|
||||||
ProgressView(
|
ProgressView(
|
||||||
String(format: "%02d", viewStore.index + 1),
|
String(format: "%02d", viewStore.index + 1),
|
||||||
|
@ -46,6 +47,7 @@ struct OnboardingFooterView: View {
|
||||||
.padding(.vertical, 20)
|
.padding(.vertical, 20)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.padding(.top, 10)
|
||||||
.navigationLinkEmpty(
|
.navigationLinkEmpty(
|
||||||
isActive: viewStore.bindingForDestination(.importExistingWallet),
|
isActive: viewStore.bindingForDestination(.importExistingWallet),
|
||||||
destination: {
|
destination: {
|
||||||
|
@ -93,7 +95,8 @@ struct OnboardingFooterView_Previews: PreviewProvider {
|
||||||
OnboardingFooterView(store: store)
|
OnboardingFooterView(store: store)
|
||||||
.applyScreenBackground()
|
.applyScreenBackground()
|
||||||
.preferredColorScheme(.light)
|
.preferredColorScheme(.light)
|
||||||
.previewDevice("iPhone 13 Pro Max")
|
.previewDevice("iPhone 14 Pro")
|
||||||
|
.environment(\.sizeCategory, .accessibilityLarge)
|
||||||
|
|
||||||
OnboardingFooterView(store: store)
|
OnboardingFooterView(store: store)
|
||||||
.applyScreenBackground()
|
.applyScreenBackground()
|
||||||
|
|
|
@ -33,6 +33,7 @@ struct OnboardingHeaderView: View {
|
||||||
.navigationButtonStyle
|
.navigationButtonStyle
|
||||||
.frame(width: 75)
|
.frame(width: 75)
|
||||||
.disabled(viewStore.isInitialStep)
|
.disabled(viewStore.isInitialStep)
|
||||||
|
.minimumScaleFactor(0.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
@ -44,6 +45,7 @@ struct OnboardingHeaderView: View {
|
||||||
.navigationButtonStyle
|
.navigationButtonStyle
|
||||||
.disabled(viewStore.isFinalStep)
|
.disabled(viewStore.isFinalStep)
|
||||||
.frame(width: 75)
|
.frame(width: 75)
|
||||||
|
.minimumScaleFactor(0.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 30)
|
.padding(.horizontal, 30)
|
||||||
|
@ -51,7 +53,6 @@ struct OnboardingHeaderView: View {
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding(.top, 5)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ extension Text {
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
content
|
content
|
||||||
.foregroundColor(Asset.Colors.Text.heading.color)
|
.foregroundColor(Asset.Colors.Text.heading.color)
|
||||||
.font(.custom(FontFamily.Rubik.regular.name, size: 33, relativeTo: .callout))
|
.font(.custom(FontFamily.Rubik.medium.name, size: 33, relativeTo: .callout))
|
||||||
.shadow(color: Asset.Colors.Text.captionTextShadow.color, radius: 1, x: 0, y: 1)
|
.shadow(color: Asset.Colors.Text.captionTextShadow.color, radius: 1, x: 0, y: 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue