2022-12-02 12:46:48 +01:00
|
|
|
//
|
|
|
|
// LoginView.swift
|
|
|
|
// BeReal
|
|
|
|
//
|
|
|
|
// Created by Javier Cicchelli on 30/11/2022.
|
|
|
|
// Copyright © 2022 Röck+Cöde. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import SwiftUI
|
|
|
|
|
|
|
|
struct LoginView: View {
|
|
|
|
|
|
|
|
// MARK: States
|
|
|
|
|
2022-12-02 19:27:21 +01:00
|
|
|
@State private var containerTopPadding: CGFloat = 0
|
2022-12-02 12:46:48 +01:00
|
|
|
|
|
|
|
// MARK: Body
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
ScrollView(
|
|
|
|
.vertical,
|
|
|
|
showsIndicators: false
|
|
|
|
) {
|
2022-12-02 19:27:21 +01:00
|
|
|
LoginContainer()
|
2022-12-02 12:46:48 +01:00
|
|
|
.padding(.horizontal, 24)
|
2022-12-02 19:27:21 +01:00
|
|
|
.padding(.top, containerTopPadding)
|
2022-12-02 12:46:48 +01:00
|
|
|
}
|
|
|
|
.background(Color.red)
|
|
|
|
.overlay(ViewHeightGeometry())
|
|
|
|
.onPreferenceChange(ViewHeightPreferenceKey.self) { height in
|
2022-12-02 19:27:21 +01:00
|
|
|
containerTopPadding = height * 0.1
|
2022-12-02 12:46:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Views
|
|
|
|
|
|
|
|
fileprivate extension LoginView {
|
2022-12-02 19:27:21 +01:00
|
|
|
struct LoginContainer: View {
|
|
|
|
|
|
|
|
// MARK: States
|
|
|
|
|
|
|
|
@State private var isAuthenticating: Bool = false
|
2022-12-02 12:46:48 +01:00
|
|
|
@State private var username: String = .empty
|
|
|
|
@State private var password: String = .empty
|
|
|
|
@State private var errorMessage: String?
|
|
|
|
|
2022-12-02 19:27:21 +01:00
|
|
|
// MARK: Body
|
|
|
|
|
2022-12-02 12:46:48 +01:00
|
|
|
var body: some View {
|
2022-12-02 19:27:21 +01:00
|
|
|
VStack(spacing: 32) {
|
|
|
|
Text("login.title.text")
|
2022-12-02 12:46:48 +01:00
|
|
|
.font(.largeTitle)
|
|
|
|
.fontWeight(.bold)
|
2022-12-02 19:27:21 +01:00
|
|
|
.foregroundColor(.primary)
|
2022-12-02 12:46:48 +01:00
|
|
|
|
|
|
|
LoginForm(
|
|
|
|
username: $username,
|
|
|
|
password: $password,
|
|
|
|
errorMessage: $errorMessage
|
2022-12-02 19:27:21 +01:00
|
|
|
) {
|
|
|
|
// TODO: login with the username and password.
|
|
|
|
}
|
2022-12-02 12:46:48 +01:00
|
|
|
|
|
|
|
Button {
|
2022-12-02 19:27:21 +01:00
|
|
|
// TODO: login with the username and password.
|
2022-12-02 12:46:48 +01:00
|
|
|
} label: {
|
2022-12-02 19:27:21 +01:00
|
|
|
Label {
|
|
|
|
Text("login.button.log_in.text")
|
|
|
|
.fontWeight(.semibold)
|
|
|
|
} icon: {
|
|
|
|
if isAuthenticating {
|
|
|
|
ProgressView()
|
|
|
|
} else {
|
|
|
|
EmptyView()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.labelStyle(LogInLabelStyle())
|
2022-12-02 12:46:48 +01:00
|
|
|
}
|
2022-12-02 19:27:21 +01:00
|
|
|
.tint(.orange)
|
|
|
|
.buttonStyle(.borderedProminent)
|
|
|
|
.buttonBorderShape(.roundedRectangle(radius: 8))
|
|
|
|
.controlSize(.large)
|
|
|
|
.disabled(isLoginDisabled)
|
2022-12-02 12:46:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ViewHeightGeometry: View {
|
|
|
|
var body: some View {
|
|
|
|
GeometryReader { proxy in
|
|
|
|
Color.clear.preference(
|
|
|
|
key: ViewHeightPreferenceKey.self,
|
|
|
|
value: proxy.size.height + proxy.safeAreaInsets.top + proxy.safeAreaInsets.bottom
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-02 19:27:21 +01:00
|
|
|
// MARK: - Label styles
|
|
|
|
|
|
|
|
private extension LoginView.LoginContainer {
|
|
|
|
struct LogInLabelStyle: LabelStyle {
|
|
|
|
func makeBody(configuration: Configuration) -> some View {
|
|
|
|
HStack(spacing: 8) {
|
|
|
|
Spacer()
|
|
|
|
|
|
|
|
configuration.title
|
|
|
|
.font(.body)
|
|
|
|
.foregroundColor(.primary)
|
|
|
|
|
|
|
|
configuration.icon
|
|
|
|
.tint(.primary)
|
|
|
|
|
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Helpers
|
|
|
|
|
|
|
|
private extension LoginView.LoginContainer {
|
|
|
|
var isLoginDisabled: Bool {
|
|
|
|
username.isEmpty || password.isEmpty
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-02 12:46:48 +01:00
|
|
|
// MARK: - Preference keys
|
|
|
|
|
|
|
|
struct ViewHeightPreferenceKey: PreferenceKey {
|
|
|
|
static var defaultValue: CGFloat = 0
|
|
|
|
|
|
|
|
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
|
|
|
|
value = nextValue()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Previews
|
|
|
|
|
|
|
|
struct LoginView_Previews: PreviewProvider {
|
|
|
|
static var previews: some View {
|
|
|
|
LoginView()
|
|
|
|
}
|
|
|
|
}
|