update welcome view and registration view

This commit is contained in:
Satindar Dhillon 2022-05-24 14:44:50 -07:00
parent 89164a353f
commit 9bfb50f8d8
15 changed files with 113 additions and 315 deletions

View file

@ -84,69 +84,10 @@ final class RegistrationViewModel: ObservableObject {
}
}
struct RegistrationView: View {
@EnvironmentObject var authenticator: Authenticator
@EnvironmentObject var dataService: DataService
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@StateObject private var viewModel = RegistrationViewModel()
var authenticationView: some View {
VStack(spacing: 0) {
VStack(spacing: 28) {
if horizontalSizeClass == .regular {
Spacer()
}
VStack(alignment: .center, spacing: 16) {
Text(LocalText.registrationViewHeadline)
.font(.appTitle)
.multilineTextAlignment(.center)
.padding(.bottom, horizontalSizeClass == .compact ? 0 : 50)
.padding(.top, horizontalSizeClass == .compact ? 30 : 0)
AppleSignInButton {
viewModel.handleAppleSignInCompletion(result: $0, authenticator: authenticator)
}
if AppKeys.sharedInstance?.iosClientGoogleId != nil {
GoogleAuthButton {
viewModel.handleGoogleAuth(authenticator: authenticator)
}
}
}
if let loginError = viewModel.loginError {
LoginErrorMessageView(loginError: loginError)
}
Spacer()
}
.frame(maxWidth: 316)
.padding(.horizontal, 16)
}
}
var body: some View {
if let registrationState = viewModel.registrationState {
if case let RegistrationViewModel.RegistrationState.createProfile(userProfile) = registrationState {
CreateProfileView(userProfile: userProfile)
} else if case let RegistrationViewModel.RegistrationState.newAppleSignUp(userProfile) = registrationState {
NewAppleSignupView(
userProfile: userProfile,
showProfileEditView: { viewModel.registrationState = .createProfile(userProfile: userProfile) }
)
} else {
authenticationView
}
} else {
authenticationView
}
}
}
private func presentingViewController() -> PlatformViewController? {
#if os(iOS)
return UIApplication.shared.windows
let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
return scene?.windows
.filter(\.isKeyWindow)
.first?
.rootViewController

View file

@ -7,9 +7,12 @@ import Views
struct WelcomeView: View {
@EnvironmentObject var dataService: DataService
@EnvironmentObject var authenticator: Authenticator
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@StateObject private var viewModel = RegistrationViewModel()
@State private var showRegistrationView = false
@State private var isKeyboardOnScreen = false
@State private var showDebugModal = false
@State private var selectedEnvironment = AppEnvironment.initialAppEnvironment
@ -19,68 +22,121 @@ struct WelcomeView: View {
}
}
@ViewBuilder func userInteractiveView(width: CGFloat) -> some View {
Group {
if showRegistrationView {
RegistrationView()
} else {
GetStartedView(showRegistrationView: $showRegistrationView)
}
var headlineView: some View {
VStack(alignment: .leading, spacing: 8) {
Text("Everything you read. Safe, organized, and easy to share.")
.font(.appLargeTitle)
Button(
action: { print("learn more button tapped") },
label: {
HStack(spacing: 4) {
Text("Learn more")
Image(systemName: "arrow.right")
}
.font(.appTitleThree)
}
)
.foregroundColor(.appGrayTextContrast)
}
.frame(width: width)
.zIndex(2)
}
@ViewBuilder func primaryContent() -> some View {
if horizontalSizeClass == .compact {
GeometryReader { geometry in
ZStack(alignment: .leading) {
Color.systemBackground
.edgesIgnoringSafeArea(.all)
var footerView: some View {
Text("By signing up, you agree to Omnivores\nTerms of Service and Privacy Policy")
.font(.appSubheadline)
}
if geometry.size.width < geometry.size.height, !isKeyboardOnScreen {
VStack {
Color.appDeepBackground.frame(height: 100)
Spacer()
var logoView: some View {
Image.omnivoreTitleLogo
.gesture(
TapGesture(count: 2)
.onEnded {
if !Bundle.main.isAppStoreBuild {
showDebugModal = true
}
.edgesIgnoringSafeArea(.all)
}
)
}
VStack {
if geometry.size.width < geometry.size.height, !isKeyboardOnScreen {
RegistrationHeroImageView(tapGestureHandler: handleHiddenGestureAction)
}
userInteractiveView(width: geometry.size.width)
Spacer()
}
var authProviderButtonStack: some View {
let buttonGroup = Group {
AppleSignInButton {
viewModel.handleAppleSignInCompletion(result: $0, authenticator: authenticator)
}
if AppKeys.sharedInstance?.iosClientGoogleId != nil {
GoogleAuthButton {
viewModel.handleGoogleAuth(authenticator: authenticator)
}
}
} else {
GeometryReader { geometry in
ZStack(alignment: .leading) {
SplitColorBackground(width: geometry.size.width)
VStack {
TitleLogoView(handleHiddenGestureAction: handleHiddenGestureAction)
Spacer()
}
.padding()
HStack(spacing: 0) {
userInteractiveView(width: geometry.size.width * 0.5)
ReadingIllustrationXXLView(width: geometry.size.width * 0.5)
}
}
}
return VStack(alignment: .center, spacing: 16) {
if horizontalSizeClass == .regular {
HStack { buttonGroup }
} else {
buttonGroup
}
if let loginError = viewModel.loginError {
LoginErrorMessageView(loginError: loginError)
}
}
}
var compactContent: some View {
VStack(alignment: .leading) {
logoView
Spacer()
headlineView
Spacer()
authProviderButtonStack
Spacer()
footerView
}
.padding()
}
var wideContent: some View {
GeometryReader { _ in
VStack(alignment: .leading) {
logoView
Spacer()
headlineView
Spacer()
authProviderButtonStack
Spacer()
footerView
}
.padding()
}
}
public var body: some View {
primaryContent()
.sheet(isPresented: $showDebugModal) {
DebugMenuView(selectedEnvironment: $selectedEnvironment)
ZStack(alignment: .leading) {
Color.appDeepBackground
.edgesIgnoringSafeArea(.all)
if let registrationState = viewModel.registrationState {
if case let RegistrationViewModel.RegistrationState.createProfile(userProfile) = registrationState {
CreateProfileView(userProfile: userProfile)
} else if case let RegistrationViewModel.RegistrationState.newAppleSignUp(userProfile) = registrationState {
NewAppleSignupView(
userProfile: userProfile,
showProfileEditView: { viewModel.registrationState = .createProfile(userProfile: userProfile) }
)
} else {
EmptyView() // will never be caled
}
} else {
if horizontalSizeClass == .compact {
compactContent
} else {
wideContent
}
}
.onReceive(Publishers.keyboardHeight) { isKeyboardOnScreen = $0 > 1 }
.onAppear { selectedEnvironment = dataService.appEnvironment }
}
.sheet(isPresented: $showDebugModal) {
DebugMenuView(selectedEnvironment: $selectedEnvironment)
}
.task { selectedEnvironment = dataService.appEnvironment }
}
}

View file

@ -5,9 +5,9 @@
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x9F",
"green" : "0xEA",
"red" : "0xFF"
"blue" : "0xA8",
"green" : "0xEB",
"red" : "0xFB"
}
},
"idiom" : "universal"
@ -23,9 +23,9 @@
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x9F",
"green" : "0xEA",
"red" : "0xFF"
"blue" : "0xA8",
"green" : "0xEB",
"red" : "0xFB"
}
},
"idiom" : "universal"

View file

@ -3,10 +3,7 @@ import SwiftUI
public extension Image {
static var smallOmnivoreLogo: Image { Image("_smallOmnivoreLogo", bundle: .module) }
static var omnivoreTitleLogo: Image { Image("_omnivoreTitleLogo", bundle: .module) }
static var readingIllustration: Image { Image("_readingIllustration", bundle: .module) }
static var readingIllustrationXXL: Image { Image("_readingIllustrationXXL", bundle: .module) }
static var googleIcon: Image { Image("_googleIcon", bundle: .module) }
static var feedItemPlaceholder: Image { Image("_feedItemPlaceholder", bundle: .module) }
static var sunHorizon: Image { Image("_sun-horizon", bundle: .module) }
static var mountains: Image { Image("_mountains", bundle: .module) }
static var moon: Image { Image("_moon", bundle: .module) }

View file

@ -1,12 +0,0 @@
{
"images" : [
{
"filename" : "imagePlaceholder.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -1,23 +0,0 @@
{
"images" : [
{
"filename" : "Mask Group.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Mask Group@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Mask Group@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 614 KiB

View file

@ -1,12 +0,0 @@
{
"images" : [
{
"filename" : "XXLIllustration.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

View file

@ -1,25 +0,0 @@
import SwiftUI
public struct RegistrationHeroImageView: View {
let tapGestureHandler: () -> Void
public init(tapGestureHandler: @escaping () -> Void) {
self.tapGestureHandler = tapGestureHandler
}
public var body: some View {
ZStack(alignment: .topLeading) {
Image.readingIllustration
.resizable()
.aspectRatio(contentMode: .fit)
Image.omnivoreTitleLogo
.padding()
.gesture(
TapGesture(count: 2)
.onEnded {
tapGestureHandler()
}
)
}
}
}

View file

@ -1,41 +0,0 @@
import Models
import SwiftUI
struct ToggleAuthFlowButton: View {
let authFlow: AuthFlow
let action: () -> Void
var buttonTitle: String {
switch authFlow {
case .signIn:
return "Dont have an account? "
case .signUp:
return "Already have an account? "
}
}
var buttonTitleSuffix: String {
switch authFlow {
case .signIn:
return "Sign Up"
case .signUp:
return "Log In"
}
}
var body: some View {
Button(
action: action,
label: {
Text(buttonTitle)
.font(.appFootnote)
.foregroundColor(.appGrayText)
+ Text(buttonTitleSuffix)
.underline()
.font(.appFootnote)
.foregroundColor(.red)
}
)
.buttonStyle(PlainButtonStyle())
}
}

View file

@ -1,83 +0,0 @@
import SwiftUI
public struct ReadingIllustrationXXLView: View {
let width: CGFloat
public init(width: CGFloat) {
self.width = width
}
public var body: some View {
Image.readingIllustrationXXL
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: width)
.clipped()
.edgesIgnoringSafeArea([.vertical, .trailing])
}
}
public struct TitleLogoView: View {
let handleHiddenGestureAction: () -> Void
public init(handleHiddenGestureAction: @escaping () -> Void) {
self.handleHiddenGestureAction = handleHiddenGestureAction
}
public var body: some View {
Image.omnivoreTitleLogo
.renderingMode(.template)
.foregroundColor(.appGrayTextContrast)
.frame(height: 40)
.gesture(
TapGesture(count: 2)
.onEnded {
handleHiddenGestureAction()
}
)
}
}
public struct GetStartedView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@Binding var showRegistrationView: Bool
public init(showRegistrationView: Binding<Bool>) {
self._showRegistrationView = showRegistrationView
}
public var body: some View {
HStack {
VStack(alignment: .leading, spacing: 32) {
Text("A better social\nreading experience\nstarts with Omnivore.")
.font(.appTitle)
.multilineTextAlignment(.leading)
BorderedButton(color: .appGrayTextContrast, text: "Get Started") {
showRegistrationView = true
}
.frame(width: 220)
}
.padding(.leading, horizontalSizeClass == .compact ? 16 : 80)
.padding(.top, horizontalSizeClass == .compact ? 16 : 0)
Spacer()
}
}
}
public struct SplitColorBackground: View {
let width: CGFloat
public init(width: CGFloat) {
self.width = width
}
public var body: some View {
HStack(spacing: 0) {
Color.systemBackground.frame(width: width * 0.5)
Color.appBackground.frame(width: width * 0.5)
}
.edgesIgnoringSafeArea(.all)
}
}