another.im-ios/ConversationsClassic/View/Entering/LoginScreen.swift
2024-08-11 17:04:42 +02:00

137 lines
4.4 KiB
Swift

import Combine
import Martin
import SwiftUI
struct LoginScreen: View {
@Environment(\.router) var router
@EnvironmentObject var clientsStore: ClientsStore
enum Field {
case userJid
case password
}
@FocusState private var focus: Field?
@State private var isLoading = false
@State private var isError = false
#if DEBUG
@State private var jidStr: String = "nartest1@conversations.im"
@State private var pass: String = "nartest12345"
// @State private var jidStr: String = "test1@test.anal.company"
// @State private var pass: String = "12345"
#else
@State private var jidStr: String = ""
@State private var pass: String = ""
#endif
public var body: some View {
ZStack {
// background
Color.Material.Background.light
.ignoresSafeArea()
// content
VStack(spacing: 32) {
// icon
Image.logo
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 120, height: 120)
// texts
VStack(spacing: 10) {
Text(L10n.Login.title)
.font(.head1l)
.foregroundColor(.Material.Text.main)
.fixedSize(horizontal: true, vertical: false)
Text(L10n.Login.subtitle)
.font(.body2)
.foregroundColor(.Material.Text.sub)
.multilineTextAlignment(.center)
.fixedSize(horizontal: false, vertical: true)
}
VStack(spacing: 16) {
UniversalInputCollection.TextField(
prompt: L10n.Login.Hint.jid,
text: $jidStr,
focus: $focus,
fieldType: .userJid,
contentType: .emailAddress,
keyboardType: .emailAddress,
submitLabel: .next,
action: {
focus = .password
}
)
UniversalInputCollection.SecureField(
prompt: L10n.Login.Hint.password,
text: $pass,
focus: $focus,
fieldType: .password,
submitLabel: .go,
action: {
focus = nil
}
)
Button {
Task {
await tryLogin()
}
} label: {
Text(L10n.Login.btn)
}
.buttonStyle(PrimaryButtonStyle())
.disabled(!loginInputValid)
Button {
router.dismissScreen()
} label: {
Text("\(Image(systemName: "chevron.left")) \(L10n.Global.back)")
.foregroundColor(.Material.Elements.active)
.font(.body2)
}
}
}
.padding(.horizontal, 32)
}
.if(isLoading) {
$0.loadingOverlay()
}
.alert(isPresented: $isError) {
Alert(
title: Text(L10n.Global.Error.title),
message: Text(L10n.Login.error),
dismissButton: .default(Text(L10n.Global.ok))
)
}
}
private var loginInputValid: Bool {
!jidStr.isEmpty && !pass.isEmpty && UniversalInputCollection.Validators.isEmail(jidStr)
}
private func tryLogin() async {
isLoading = true
// login with fake timeout
async let sleep: Void? = try? await Task.sleep(nanoseconds: 1 * NSEC_PER_SEC)
async let request = await Client.tryLogin(with: .init(bareJid: jidStr, pass: pass, isActive: true))
let result = await(request, sleep).0
switch result {
case .success(let client):
clientsStore.addNewClient(client)
isLoading = false
isError = false
case .failure:
isLoading = false
isError = true
}
}
}