I have this view in SwiftUI; it works as expected, and for the most part, works great. My only concern with it is that it feels extremely clunky. Reading through the view itself is very difficult. Does anyone have recommendations for cleaning this thing up?
Effectively, the sign in and register pages both have the same options, and there are only minor text differences. however you'll notice I've got some buttons that seem to repeat, but I don't see the need in extracting to its own view because this is the only place it'll be used.
struct RegisterOptionsView: View {
@EnvironmentObject var baseNavVM: BaseLaunchViewModel
@ObservedObject var registerOptionsViewModel = RegisterOptionsViewModel()
@State var isLoggingIn = false
var body: some View {
ZStack {
VStack(spacing: 20) {
NavigationLink(destination: getDestination(), isActive: $registerOptionsViewModel.shouldNavigateToRegister) { EmptyView() }
.navigationTitle(isLoggingIn ? "Login" : "Register")
Spacer()
VStack(spacing: 30) {
VStack {
Text("Stello")
.font(Fonts.title)
Text("[STEL'-LO]")
.font(Fonts.body)
Text("VERB, GREEK")
.font(Fonts.body)
}
StelloDivider()
Text("SENT WITH A PURPOSE")
.font(Fonts.subheading)
.multilineTextAlignment(.center)
}
Spacer()
// MARK: - APPLE SIGN IN
VStack {
Button(action: {
registerOptionsViewModel.selectedLoginOption = .apple
withAnimation {
isLoggingIn ? baseNavVM.loggedIn = true :
registerOptionsViewModel.shouldNavigateToRegister.toggle()
}
}, label: {
HStack(spacing: 16) {
Image(systemName: "applelogo")
.font(.system(size: 20))
Text(isLoggingIn ? "Sign in with Apple" : "Register with Apple")
.font(Fonts.button)
}
}).buttonStyle(StelloFillButtonStyle())
.offset(y: 32 )
.frame(height: registerOptionsViewModel.showOptions ? 0 : 60 )
.hidden(registerOptionsViewModel.showOptions)
// MARK: - Forgot Password
Group {
NavigationLink(destination: Text("Forgot Password"), label: {
Text("Forgot Password?")
.font(Fonts.body)
.underline()
.foregroundColor(.blue)
})
.frame(height: !isLoggingIn ? 0 : 60 )
.hidden(!isLoggingIn)
.navigationTitle("Password Recovery")
// MARK: - Email
Button(action: {
registerOptionsViewModel.selectedLoginOption = .email
withAnimation {
isLoggingIn ? baseNavVM.loggedIn = true :
registerOptionsViewModel.shouldNavigateToRegister.toggle()
}
}, label: {
Text(isLoggingIn ? "Email" : "Register with Email")
.font(Fonts.button)
}).buttonStyle(StelloFillButtonStyle())
//MARK: - Facebook
Button(action: {
registerOptionsViewModel.selectedLoginOption = .facebook
withAnimation {
isLoggingIn ? baseNavVM.loggedIn = true :
registerOptionsViewModel.shouldNavigateToRegister.toggle()
}
}, label: {
Text(isLoggingIn ? "Facebook" : "Register with Facebook")
.font(Fonts.button)
}).buttonStyle(StelloFillButtonStyle())
//MARK: - Google
Button(action: {
registerOptionsViewModel.selectedLoginOption = .google
withAnimation {
isLoggingIn ? baseNavVM.loggedIn = true :
registerOptionsViewModel.shouldNavigateToRegister.toggle()
}
}, label: {
Text(isLoggingIn ? "Google" : "Register with Google")
.font(Fonts.button)
}).buttonStyle(StelloFillButtonStyle())
}
.frame(height: !registerOptionsViewModel.showOptions ? 0 : 60 )
.hidden(!registerOptionsViewModel.showOptions)
// MARK: - Other Options
Button(action: {
withAnimation(.easeInOut) {
registerOptionsViewModel.showOptions.toggle()
}
}, label: {
if !registerOptionsViewModel.showOptions {
Text("Other Options")
.font(Fonts.button)
} else {
Text("Cancel")
.font(Fonts.button)
}
}).buttonStyle(StelloFillButtonStyle())
}
}
.padding(.horizontal)
}
}
// MARK: - View Functions
func getDestination() -> AnyView {
switch registerOptionsViewModel.selectedLoginOption {
case .apple:
return AnyView(Text("Apple"))
case .email:
return AnyView(Text("Email"))
case .facebook:
return AnyView(Text("Facebook"))
case .google:
return AnyView(Text("Google"))
default:
return AnyView(EmptyView())
}
}
}