initial commit

This commit is contained in:
Filip
2026-03-11 16:06:00 +01:00
parent b3c69053f6
commit 5fd80e6dd6
127 changed files with 39684 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
import SwiftUI
struct LoginView: View {
@Bindable var viewModel: AuthViewModel
var appState: AppState
var body: some View {
NavigationStack {
ScrollView {
VStack(spacing: 20) {
Image(systemName: "lock.shield.fill")
.font(.system(size: 60))
.foregroundStyle(.blue)
.padding(.top, 40)
Text("Encrypted Chat")
.font(.largeTitle.bold())
Text("End-to-end encrypted messaging")
.font(.subheadline)
.foregroundStyle(.secondary)
VStack(spacing: 16) {
// Server config
DisclosureGroup("Server") {
TextField("Host", text: $viewModel.serverHost)
.textContentType(.URL)
.autocapitalization(.none)
TextField("Port", text: $viewModel.serverPort)
.keyboardType(.numberPad)
Toggle("Use TLS", isOn: $viewModel.useTLS)
}
.padding(.horizontal)
TextField("Email", text: $viewModel.email)
.textContentType(.emailAddress)
.keyboardType(.emailAddress)
.autocapitalization(.none)
.textFieldStyle(.roundedBorder)
SecureField("Password", text: $viewModel.password)
.textContentType(.password)
.textFieldStyle(.roundedBorder)
if viewModel.mode == .register {
TextField("Username", text: $viewModel.username)
.textContentType(.username)
.autocapitalization(.none)
.textFieldStyle(.roundedBorder)
SecureField("Confirm Password", text: $viewModel.confirmPassword)
.textFieldStyle(.roundedBorder)
}
if let error = viewModel.errorMessage {
Text(error)
.foregroundStyle(.red)
.font(.caption)
.multilineTextAlignment(.center)
}
Button(action: {
Task {
if viewModel.mode == .login {
await viewModel.login(appState: appState)
} else {
await viewModel.register(appState: appState)
}
}
}) {
if viewModel.isLoading {
ProgressView()
.frame(maxWidth: .infinity)
} else {
Text(viewModel.mode == .login ? "Login" : "Register")
.frame(maxWidth: .infinity)
}
}
.buttonStyle(.borderedProminent)
.disabled(viewModel.isLoading)
Button(viewModel.mode == .login ? "Don't have an account? Register" : "Already have an account? Login") {
viewModel.mode = viewModel.mode == .login ? .register : .login
viewModel.errorMessage = nil
}
.font(.caption)
}
.padding(.horizontal, 32)
}
}
.sheet(isPresented: $viewModel.showConfirmation) {
ConfirmationSheet(viewModel: viewModel, appState: appState)
}
}
}
}
struct ConfirmationSheet: View {
@Bindable var viewModel: AuthViewModel
var appState: AppState
var body: some View {
VStack(spacing: 20) {
Text("Confirm Registration")
.font(.title2.bold())
if let msg = viewModel.registrationMessage {
Text(msg)
.font(.subheadline)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
}
TextField("Confirmation Code", text: $viewModel.confirmationCode)
.textFieldStyle(.roundedBorder)
.keyboardType(.numberPad)
if let error = viewModel.errorMessage {
Text(error)
.foregroundStyle(.red)
.font(.caption)
}
Button("Confirm") {
Task {
await viewModel.confirmRegistration(appState: appState)
}
}
.buttonStyle(.borderedProminent)
.disabled(viewModel.isLoading)
}
.padding(32)
}
}

View File

@@ -0,0 +1,49 @@
import SwiftUI
struct PairingView: View {
var appState: AppState
@State private var pairingCode = ""
@State private var isWaiting = false
@State private var statusMessage: String?
var body: some View {
VStack(spacing: 24) {
Image(systemName: "iphone.and.arrow.forward")
.font(.system(size: 48))
.foregroundStyle(.blue)
Text("Device Pairing")
.font(.title2.bold())
Text("Enter the 8-digit pairing code shown on your other device.")
.font(.subheadline)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
TextField("Pairing Code", text: $pairingCode)
.textFieldStyle(.roundedBorder)
.keyboardType(.numberPad)
.frame(maxWidth: 200)
if let status = statusMessage {
Text(status)
.font(.caption)
.foregroundStyle(status.contains("Error") ? .red : .secondary)
}
if isWaiting {
ProgressView("Waiting for authorization...")
}
Button("Start Pairing") {
Task {
// Pairing implementation would go here
statusMessage = "Pairing not yet implemented"
}
}
.buttonStyle(.borderedProminent)
.disabled(pairingCode.count != 8 || isWaiting)
}
.padding(32)
}
}

View File

@@ -0,0 +1,4 @@
import SwiftUI
// Registration is handled within LoginView via mode toggle.
// This file exists for potential future separation.