Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Registration #98

Draft
wants to merge 9 commits into
base: stable
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
}
}
66 changes: 19 additions & 47 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,52 +126,27 @@ 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() })

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

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

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

Expand Down
Loading