diff --git a/Shared/Account/AccountLoginView.swift b/Shared/Account/AccountLoginView.swift index 05d2384..d420aa1 100644 --- a/Shared/Account/AccountLoginView.swift +++ b/Shared/Account/AccountLoginView.swift @@ -1,106 +1,106 @@ import SwiftUI struct AccountLoginView: View { @EnvironmentObject var model: WriteFreelyModel @State private var alertMessage: String = "" @State private var username: String = "" @State private var password: String = "" @State private var server: String = "" var body: some View { VStack { Text("Log in to publish and share your posts.") .font(.caption) .foregroundColor(.secondary) HStack { Image(systemName: "person.circle") .foregroundColor(.gray) #if os(iOS) TextField("Username", text: $username) .autocapitalization(.none) .disableAutocorrection(true) .textFieldStyle(RoundedBorderTextFieldStyle()) #else TextField("Username", text: $username) #endif } HStack { Image(systemName: "lock.circle") .foregroundColor(.gray) #if os(iOS) SecureField("Password", text: $password) .autocapitalization(.none) .disableAutocorrection(true) .textFieldStyle(RoundedBorderTextFieldStyle()) #else SecureField("Password", text: $password) #endif } HStack { Image(systemName: "link.circle") .foregroundColor(.gray) #if os(iOS) TextField("Server URL", text: $server) .keyboardType(.URL) .autocapitalization(.none) .disableAutocorrection(true) .textFieldStyle(RoundedBorderTextFieldStyle()) #else TextField("Server URL", text: $server) #endif } Spacer() if model.isLoggingIn { ProgressView("Logging in...") .padding() } else { Button(action: { #if os(iOS) hideKeyboard() #endif // If the server string is not prefixed with a scheme, prepend "https://" to it. if !(server.hasPrefix("https://") || server.hasPrefix("http://")) { server = "https://\(server)" } - print(server) // We only need the protocol and host from the URL, so drop anything else. let url = URLComponents(string: server) if let validURL = url { let scheme = validURL.scheme let host = validURL.host var hostURL = URLComponents() hostURL.scheme = scheme hostURL.host = host server = hostURL.string ?? server } else { - // TODO: - throw an error if this is an invalid URL. + model.loginErrorMessage = AccountError.invalidServerURL.localizedDescription + model.isPresentingLoginErrorAlert = true } model.login( to: URL(string: server)!, as: username, password: password ) }, label: { Text("Log In") }) .disabled( model.account.isLoggedIn || (username.isEmpty || password.isEmpty || server.isEmpty) ) .padding() } } .alert(isPresented: $model.isPresentingLoginErrorAlert) { Alert( title: Text("Error Logging In"), message: Text(model.loginErrorMessage ?? "An unknown error occurred while trying to login."), dismissButton: .default(Text("OK")) ) } } } struct AccountLoginView_Previews: PreviewProvider { static var previews: some View { AccountLoginView() .environmentObject(WriteFreelyModel()) } } diff --git a/Shared/Account/AccountModel.swift b/Shared/Account/AccountModel.swift index 25683a5..0010a44 100644 --- a/Shared/Account/AccountModel.swift +++ b/Shared/Account/AccountModel.swift @@ -1,62 +1,68 @@ import SwiftUI import WriteFreely enum AccountError: Error { case invalidPassword case usernameNotFound case serverNotFound + case invalidServerURL } extension AccountError: LocalizedError { public var errorDescription: String? { switch self { case .serverNotFound: return NSLocalizedString( "The server could not be found. Please check the information you've entered and try again.", comment: "" ) case .invalidPassword: return NSLocalizedString( "Invalid password. Please check that you've entered your password correctly and try logging in again.", comment: "" ) case .usernameNotFound: return NSLocalizedString( "Username not found. Did you use your email address by mistake?", comment: "" ) + case .invalidServerURL: + return NSLocalizedString( + "The server entered doesn't appear to be a valid URL. Please check what you've entered and try again.", + comment: "" + ) } } } struct AccountModel { @AppStorage("isLoggedIn") var isLoggedIn: Bool = false private let defaults = UserDefaults.standard let usernameStringKey = "usernameStringKey" let serverStringKey = "serverStringKey" var server: String = "" var username: String = "" private(set) var user: WFUser? mutating func login(_ user: WFUser) { self.user = user self.username = user.username ?? "" self.isLoggedIn = true defaults.set(user.username, forKey: usernameStringKey) defaults.set(server, forKey: serverStringKey) } mutating func logout() { self.user = nil self.isLoggedIn = false defaults.removeObject(forKey: usernameStringKey) defaults.removeObject(forKey: serverStringKey) } mutating func restoreState() { server = defaults.string(forKey: serverStringKey) ?? "" username = defaults.string(forKey: usernameStringKey) ?? "" } }