Skip to content

Commit

Permalink
Implement new account registration
Browse files Browse the repository at this point in the history
see #20
  • Loading branch information
kiliankoe committed May 1, 2020
1 parent a54983f commit 121d9f8
Show file tree
Hide file tree
Showing 9 changed files with 309 additions and 49 deletions.
12 changes: 12 additions & 0 deletions Nio.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
393411C723903C94003B49B8 /* EventCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393411C623903C94003B49B8 /* EventCollection.swift */; };
393411C923904428003B49B8 /* MXEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393411C823904428003B49B8 /* MXEvent.swift */; };
393411D1239087D2003B49B8 /* EventCollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393411D0239087D2003B49B8 /* EventCollectionTests.swift */; };
3955DD31245B81A200827F07 /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3955DD30245B81A200827F07 /* RegistrationView.swift */; };
3955DD33245B824E00827F07 /* LoginFormTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3955DD32245B824E00827F07 /* LoginFormTextField.swift */; };
3955DD35245B9D2100827F07 /* URL+Homeserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3955DD34245B9D2100827F07 /* URL+Homeserver.swift */; };
3970DC942385A8BE00EFE31B /* KeyboardObserving in Frameworks */ = {isa = PBXBuildFile; productRef = 3970DC932385A8BE00EFE31B /* KeyboardObserving */; };
3984654523B7ECBA006C173B /* MXURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3984654423B7ECBA006C173B /* MXURL.swift */; };
3984654823B8D809006C173B /* SDWebImageSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 3984654723B8D809006C173B /* SDWebImageSwiftUI */; };
Expand Down Expand Up @@ -133,6 +136,9 @@
393411D0239087D2003B49B8 /* EventCollectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventCollectionTests.swift; sourceTree = "<group>"; };
393411D2239087D2003B49B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3955DD36245C371C00827F07 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
3955DD30245B81A200827F07 /* RegistrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistrationView.swift; sourceTree = "<group>"; };
3955DD32245B824E00827F07 /* LoginFormTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginFormTextField.swift; sourceTree = "<group>"; };
3955DD34245B9D2100827F07 /* URL+Homeserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Homeserver.swift"; sourceTree = "<group>"; };
3984654423B7ECBA006C173B /* MXURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXURL.swift; sourceTree = "<group>"; };
3997DCCF245732F000763C07 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
39B834BF243FC42000AE1EA0 /* TypingIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypingIndicatorView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -210,6 +216,8 @@
isa = PBXGroup;
children = (
39C931F423846966004449E1 /* LoginView.swift */,
3955DD30245B81A200827F07 /* RegistrationView.swift */,
3955DD32245B824E00827F07 /* LoginFormTextField.swift */,
3902B8A42395A77800698B87 /* LoadingView.swift */,
);
path = Authentication;
Expand Down Expand Up @@ -404,6 +412,7 @@
CAC46D6223A278F40079C24F /* PreviewProvider+Enumeration.swift */,
39BA0722240B3C9A00FD28C6 /* MXCredentials+Keychain.swift */,
39BA0726240B534600FD28C6 /* Color+allAccent.swift */,
3955DD34245B9D2100827F07 /* URL+Homeserver.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -709,11 +718,13 @@
392389892386FD3900B2E1DF /* MXClient+Publisher.swift in Sources */,
3984654523B7ECBA006C173B /* MXURL.swift in Sources */,
392389D2238F2E6F00B2E1DF /* NIORoom.swift in Sources */,
3955DD33245B824E00827F07 /* LoginFormTextField.swift in Sources */,
4B058B5624573A570059BC75 /* EditEvent.swift in Sources */,
392221AE243A0508004D8794 /* GroupedReactionsView.swift in Sources */,
3923898F2388707E00B2E1DF /* RoomListItemView.swift in Sources */,
39C931DD2384328A004449E1 /* AppDelegate.swift in Sources */,
393411C923904428003B49B8 /* MXEvent.swift in Sources */,
3955DD35245B9D2100827F07 /* URL+Homeserver.swift in Sources */,
3923898D238859D100B2E1DF /* MX+Identifiable.swift in Sources */,
CAC46D5B23A2734C0079C24F /* EnvironmentValues.swift in Sources */,
39C932072384BB13004449E1 /* RecentRoomsView.swift in Sources */,
Expand All @@ -733,6 +744,7 @@
392389CC238EBB1500B2E1DF /* ReverseList.swift in Sources */,
392389942388899200B2E1DF /* Formatter.swift in Sources */,
39BA0723240B3C9A00FD28C6 /* MXCredentials+Keychain.swift in Sources */,
3955DD31245B81A200827F07 /* RegistrationView.swift in Sources */,
392221AC2438149D004D8794 /* RoomMemberEventView.swift in Sources */,
392221B4243D1627004D8794 /* RoomPowerLevelsEventView.swift in Sources */,
CAC46D6323A278F40079C24F /* PreviewProvider+Enumeration.swift in Sources */,
Expand Down
27 changes: 27 additions & 0 deletions Nio/AccountStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,33 @@ class AccountStore: ObservableObject {
self.session?.removeListener(self.listenReference)
}

// MARK: - Registration

func register(username: String, password: String, homeserver: URL) {
self.loginState = .authenticating

self.client = MXRestClient(homeServer: homeserver, unrecognizedCertificateHandler: nil)
self.client?.register(username: username, password: password) { response in
switch response {
case .failure(let error):
self.loginState = .failure(error)
case .success(let credentials):
self.credentials = credentials
credentials.save(to: self.keychain)

self.sync { result in
switch result {
case .failure(let error):
// Does this make sense? The login itself didn't fail, but syncing did.
self.loginState = .failure(error)
case .success(let state):
self.loginState = state
}
}
}
}
}

// MARK: - Login & Sync

@Published var loginState: LoginState = .loggedOut
Expand Down
51 changes: 51 additions & 0 deletions Nio/Authentication/LoginFormTextField.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import SwiftUI

struct LoginFormTextField: View {
@Environment(\.colorScheme) var colorScheme

var placeholder: String
@Binding var text: String
var onEditingChanged: ((Bool) -> Void)?

var isSecure = false

var buttonIcon: String?
var buttonAction: (() -> Void)?

var body: some View {
ZStack {
Capsule(style: .continuous)
.foregroundColor(colorScheme == .light ? Color(#colorLiteral(red: 0.9395676295, green: 0.9395676295, blue: 0.9395676295, alpha: 1)) : Color(#colorLiteral(red: 0.2293992357, green: 0.2293992357, blue: 0.2293992357, alpha: 1)))
.frame(height: 50)
if isSecure {
SecureField(placeholder, text: $text)
.padding()
.textContentType(.password)
} else {
HStack {
TextField(placeholder, text: $text, onEditingChanged: onEditingChanged ?? { _ in })
.padding()
.autocapitalization(.none)
.disableAutocorrection(true)
if buttonIcon != nil && buttonAction != nil {
Button(action: {
self.buttonAction!()
}, label: {
Image(systemName: buttonIcon!)
})
.padding()
}
}
}
}
.frame(maxWidth: 400)
}
}

struct LoginFormTextField_Previews: PreviewProvider {
static var previews: some View {
LoginFormTextField(placeholder: "Username", text: .constant(""))
.padding()
.previewLayout(.sizeThatFits)
}
}
70 changes: 22 additions & 48 deletions Nio/Authentication/LoginView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import SwiftMatrixSDK

struct LoginContainerView: View {
@EnvironmentObject var store: AccountStore
@EnvironmentObject var settings: AppSettings

@State private var username = ""
@State private var password = ""
Expand All @@ -18,18 +19,16 @@ struct LoginContainerView: View {
isLoginEnabled: isLoginEnabled,
onLogin: login,
guessHomeserverURL: guessHomeserverURL)
.sheet(isPresented: $showingRegisterView) {
RegistrationContainerView()
.accentColor(self.settings.accentColor)
.environmentObject(self.store)
}
}

private func login() {
var homeserver = self.homeserver.isEmpty ? "https://matrix.org" : self.homeserver

// If there's no scheme at all, the URLComponents initializer below will think it's a path with no hostname.
if !homeserver.contains("//") {
homeserver = "https://\(homeserver)"
}
var homeserverURLComponents = URLComponents(string: homeserver)
homeserverURLComponents?.scheme = "https"
guard let homeserverURL = homeserverURLComponents?.url else {
let homeserver = self.homeserver.isEmpty ? "https://matrix.org" : self.homeserver
guard let homeserverURL = URL(homeserverString: homeserver) else {
// TODO: Handle error
print("Invalid homeserver URL '\(homeserver)'")
return
Expand Down Expand Up @@ -86,9 +85,6 @@ struct LoginView: View {
Spacer()
}
.keyboardObserving()
.sheet(isPresented: $showingRegisterView) {
Text(L10n.Login.registerNotYetImplemented)
}
}

var buttons: some View {
Expand Down Expand Up @@ -117,6 +113,7 @@ struct LoginTitleView: View {
let nio = Text("Nio").foregroundColor(.accentColor)

return VStack {
// FIXME: This probably breaks localisation.
(Text(L10n.Login.welcomeHeader) + nio + Text("!"))
.font(.title)
.bold()
Expand All @@ -129,55 +126,32 @@ struct LoginForm: View {
@Binding var username: String
@Binding var password: String
@Binding var homeserver: String

let guessHomeserverURL: () -> Void

var body: some View {
VStack {
FormTextField(title: L10n.Login.Form.username, text: $username, onEditingChanged: { _ in
self.guessHomeserverURL()
})
LoginFormTextField(placeholder: L10n.Login.Form.username,
text: $username,
onEditingChanged: { _ in self.guessHomeserverURL() })
.padding(.horizontal)

FormTextField(title: L10n.Login.Form.password, text: $password, isSecure: true)
LoginFormTextField(placeholder: L10n.Login.Form.password,
text: $password,
isSecure: true)
.padding(.horizontal)

LoginFormTextField(placeholder: L10n.Login.Form.homeserver,
text: $homeserver)
.padding(.horizontal)

FormTextField(title: L10n.Login.Form.homeserver, text: $homeserver)
Text(L10n.Login.Form.homeserverOptionalExplanation)
.font(.caption)
.foregroundColor(.gray)
}
}
}

private struct FormTextField: View {
@Environment(\.colorScheme) var colorScheme

var title: String
@Binding var text: String
var onEditingChanged: ((Bool) -> Void)?

var isSecure = false

var body: some View {
ZStack {
Capsule(style: .continuous)
.foregroundColor(colorScheme == .light ? Color(#colorLiteral(red: 0.9395676295, green: 0.9395676295, blue: 0.9395676295, alpha: 1)) : Color(#colorLiteral(red: 0.2293992357, green: 0.2293992357, blue: 0.2293992357, alpha: 1)))
.frame(height: 50)
if isSecure {
SecureField(title, text: $text)
.padding()
.textContentType(.password)
} else {
TextField(title, text: $text, onEditingChanged: onEditingChanged ?? { _ in })
.padding()
.autocapitalization(.none)
.disableAutocorrection(true)
}
}
.padding(.horizontal)
.frame(maxWidth: 400)
}
}

struct LoginView_Previews: PreviewProvider {
static var previews: some View {
LoginView(username: .constant(""),
Expand Down
Loading

0 comments on commit 121d9f8

Please sign in to comment.