Impressia/Vernissage/Views/SignInView/SignInView.swift

121 lines
4.7 KiB
Swift
Raw Normal View History

2022-12-31 16:31:05 +01:00
//
// https://mczachurski.dev
// Copyright © 2022 Marcin Czachurski and the repository contributors.
2023-03-28 10:35:38 +02:00
// Licensed under the Apache License 2.0.
2022-12-31 16:31:05 +01:00
//
import SwiftUI
2023-02-19 10:32:38 +01:00
import PixelfedKit
2023-01-29 19:11:44 +01:00
import AuthenticationServices
2022-12-31 16:31:05 +01:00
struct SignInView: View {
@Environment(\.managedObjectContext) private var viewContext
2023-01-11 13:16:43 +01:00
@Environment(\.dismiss) private var dismiss
2023-02-03 15:16:30 +01:00
2022-12-31 16:31:05 +01:00
@EnvironmentObject var applicationState: ApplicationState
2023-02-03 15:16:30 +01:00
@EnvironmentObject var client: Client
2022-12-31 16:31:05 +01:00
2023-02-21 08:36:14 +01:00
@State private var serverAddress = String.empty()
@State private var instructionsUrlString:String?
2023-02-01 13:22:43 +01:00
@State private var instances: [Instance] = []
2023-02-01 13:35:29 +01:00
2023-02-20 16:41:18 +01:00
var onSignedIn: ((_ accountData: AccountData) -> Void)?
2022-12-31 16:31:05 +01:00
var body: some View {
2023-01-29 19:11:44 +01:00
List {
2023-02-21 08:36:14 +01:00
Section {
2023-01-29 19:11:44 +01:00
VStack(alignment: .center) {
HStack(alignment: .center, spacing: 4) {
2023-03-13 13:53:36 +01:00
TextField("signin.title.serverAddress", text: $serverAddress)
2023-01-29 19:11:44 +01:00
.onSubmit {
2023-02-01 13:22:43 +01:00
let baseAddress = self.getServerAddress(uri: self.serverAddress)
self.signIn(baseAddress: baseAddress)
2023-01-29 19:11:44 +01:00
}
.textInputAutocapitalization(.never)
.keyboardType(.URL)
.disableAutocorrection(true)
2023-03-08 12:07:43 +01:00
.clearButton(text: $serverAddress)
2023-01-29 19:11:44 +01:00
2023-03-13 13:53:36 +01:00
Button(NSLocalizedString("signin.title.signIn", comment: "Sign in")) {
2023-02-19 12:49:44 +01:00
HapticService.shared.fireHaptic(of: .buttonPress)
2023-02-01 13:22:43 +01:00
let baseAddress = self.getServerAddress(uri: self.serverAddress)
self.signIn(baseAddress: baseAddress)
}
.buttonStyle(.borderedProminent)
.padding(.vertical, 4)
2023-01-29 19:11:44 +01:00
}
2022-12-31 16:31:05 +01:00
}
2023-03-08 12:07:43 +01:00
.buttonStyle(PlainButtonStyle())
2023-02-21 08:36:14 +01:00
} header: {
2023-03-13 13:53:36 +01:00
Text("signin.title.enterServerAddress", comment: "Enter server address")
2023-02-21 08:36:14 +01:00
} footer: {
if let instructionsUrlString = self.instructionsUrlString,
let instructionsUrl = URL(string: instructionsUrlString) {
HStack {
Spacer()
2023-03-13 13:53:36 +01:00
Link(NSLocalizedString("signin.title.howToJoinLink", comment: "How to join Pixelfed"), destination: instructionsUrl)
2023-02-21 08:36:14 +01:00
.font(.caption)
}
}
2023-01-29 19:11:44 +01:00
}
2023-03-13 13:53:36 +01:00
Section("signin.title.chooseServer") {
2023-02-01 13:22:43 +01:00
if self.instances.isEmpty {
HStack {
Spacer()
LoadingIndicator()
Spacer()
}
}
ForEach(self.instances, id: \.uri) { instance in
2023-02-21 07:05:06 +01:00
InstanceRowView(instance: instance) { uri in
2023-02-01 13:22:43 +01:00
let baseAddress = self.getServerAddress(uri: uri)
self.signIn(baseAddress: baseAddress)
2022-12-31 16:31:05 +01:00
}
}
}
2023-01-29 19:11:44 +01:00
}
2023-02-01 13:22:43 +01:00
.onFirstAppear {
2023-02-21 08:36:14 +01:00
let metadata = await AppMetadataService.shared.metadata()
self.instances = await self.client.instances.instances(instanceUrls: metadata.instances)
self.instructionsUrlString = metadata.instructionsUrl
2022-12-31 16:31:05 +01:00
}
2023-03-13 13:53:36 +01:00
.navigationTitle("signin.navigationBar.title")
2022-12-31 16:31:05 +01:00
.navigationBarTitleDisplayMode(.inline)
}
2023-01-29 19:11:44 +01:00
2023-02-01 13:22:43 +01:00
private func signIn(baseAddress: String) {
2023-01-29 19:11:44 +01:00
Task {
do {
let authorizationSession = AuthorizationSession()
2023-02-20 16:41:18 +01:00
try await AuthorizationService.shared.sign(in: baseAddress, session: authorizationSession) { accountData in
onSignedIn?(accountData)
DispatchQueue.main.sync {
2023-01-29 19:11:44 +01:00
dismiss()
}
}
} catch let error as AuthorisationError {
ErrorService.shared.handle(error, message: error.localizedDescription, showToastr: true)
}
catch {
2023-03-13 13:53:36 +01:00
ErrorService.shared.handle(error, message: "signin.error.communicationFailed", showToastr: true)
2023-01-29 19:11:44 +01:00
}
}
}
2023-02-01 13:22:43 +01:00
private func getServerAddress(uri: String) -> String {
2023-02-21 22:41:20 +01:00
var address = uri.trimmingCharacters(in: .whitespacesAndNewlines)
address = address.trimmingCharacters(in: CharacterSet.init(charactersIn: "/\\"))
if !address.starts(with: "https://") {
return "https://\(address)"
2023-01-29 19:11:44 +01:00
}
2023-02-21 22:41:20 +01:00
return address
2023-01-29 19:11:44 +01:00
}
2022-12-31 16:31:05 +01:00
}