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
|
|
|
}
|