From 3c11525be489c8ff9521e3da71e05f83f10466f9 Mon Sep 17 00:00:00 2001 From: Charlie Scheer Date: Wed, 24 Jul 2024 15:46:18 -0600 Subject: [PATCH 1/8] Refactored how the auth view controller is initialized --- Simplenote/AuthViewController+Swift.swift | 24 ++++++++++------------- Simplenote/AuthViewController.h | 1 + Simplenote/AuthViewController.m | 12 ++++++++++++ Simplenote/AuthWindowController.swift | 2 +- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/Simplenote/AuthViewController+Swift.swift b/Simplenote/AuthViewController+Swift.swift index 3e75d567b..1707364fc 100644 --- a/Simplenote/AuthViewController+Swift.swift +++ b/Simplenote/AuthViewController+Swift.swift @@ -6,10 +6,6 @@ extension AuthViewController { @objc func setupInterface() { - if state == nil { - state = AuthenticationState() - } - simplenoteTitleView.stringValue = "Simplenote" simplenoteSubTitleView.textColor = .simplenoteGray50Color simplenoteSubTitleView.stringValue = NSLocalizedString("The simplest way to keep notes.", comment: "Simplenote subtitle") @@ -203,32 +199,32 @@ extension AuthViewController { ensureFirstTextFieldIsFirstResponder() } - private func authViewController(with mode: AuthenticationMode, state: AuthenticationState) -> AuthViewController { - let vc = AuthViewController() - vc.authenticator = authenticator - vc.state = state - vc.mode = mode + private func pushNewAuthViewController(with mode: AuthenticationMode, state: AuthenticationState) { + guard let authVC = AuthViewController(mode: mode, state: state) else { + return + } + authVC.authenticator = authenticator - return vc + containingNavigationController?.push(authVC) } @objc func pushEmailLoginView() { - containingNavigationController?.push(authViewController(with: .requestLoginCode, state: state)) + pushNewAuthViewController(with: .requestLoginCode, state: state) } @objc func pushSignupView() { - containingNavigationController?.push(authViewController(with: .signup, state: state)) + pushNewAuthViewController(with: .signup, state: state) } @objc func pushPasswordView() { - containingNavigationController?.push(authViewController(with: .loginWithPassword(), state: state)) + pushNewAuthViewController(with: .loginWithPassword(), state: state) } func pushCodeLoginView() { - containingNavigationController?.push(authViewController(with: .loginWithCode, state: state)) + pushNewAuthViewController(with: .loginWithCode, state: state) } } diff --git a/Simplenote/AuthViewController.h b/Simplenote/AuthViewController.h index 26e05eac4..6e5cf8836 100644 --- a/Simplenote/AuthViewController.h +++ b/Simplenote/AuthViewController.h @@ -40,6 +40,7 @@ @property (nonatomic, strong) AuthenticationMode *mode; @property (nonatomic, strong) AuthenticationState *state; +- (instancetype)initWithMode:(AuthenticationMode*)mode state:(AuthenticationState*)state; - (void)pressedLogInWithPassword; - (void)pressedLoginWithMagicLink; - (void)pressedSignUp; diff --git a/Simplenote/AuthViewController.m b/Simplenote/AuthViewController.m index 51fca537f..cc1092376 100644 --- a/Simplenote/AuthViewController.m +++ b/Simplenote/AuthViewController.m @@ -23,11 +23,23 @@ - (void)dealloc [[NSNotificationCenter defaultCenter] removeObserver: self]; } +- (instancetype)initWithMode:(AuthenticationMode*)mode state:(AuthenticationState*)state; +{ + if (self = [super init]) { + self.validator = [SPAuthenticationValidator new]; + self.mode = mode; + self.state = state; + } + + return self; +} + - (instancetype)init { if (self = [super init]) { self.validator = [SPAuthenticationValidator new]; self.mode = [AuthenticationMode onboarding]; + self.state = [AuthenticationState new]; } return self; diff --git a/Simplenote/AuthWindowController.swift b/Simplenote/AuthWindowController.swift index cf9ab2256..27487b96f 100644 --- a/Simplenote/AuthWindowController.swift +++ b/Simplenote/AuthWindowController.swift @@ -26,7 +26,7 @@ class AuthWindowController: NSWindowController, SPAuthenticationInterface { } init() { - self.authViewController = AuthViewController() + self.authViewController = AuthViewController(mode: .onboarding, state: AuthenticationState()) let navigationController = SPNavigationController(initialViewController: authViewController) let window = NSWindow(contentViewController: navigationController) window.styleMask = [.borderless, .closable, .titled, .fullSizeContentView] From 3f63677e797074bb1b678900c4131f43c1364e67 Mon Sep 17 00:00:00 2001 From: Charlie Scheer Date: Thu, 25 Jul 2024 11:05:45 -0600 Subject: [PATCH 2/8] Show code input on auth view controller --- Simplenote/AuthViewController.xib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Simplenote/AuthViewController.xib b/Simplenote/AuthViewController.xib index 202b83429..99cfdb123 100644 --- a/Simplenote/AuthViewController.xib +++ b/Simplenote/AuthViewController.xib @@ -106,7 +106,7 @@ - + From 78b48bd9352fcbf8fb1b34915f7af8ba2b2c68e8 Mon Sep 17 00:00:00 2001 From: Charlie Scheer Date: Thu, 25 Jul 2024 11:12:13 -0600 Subject: [PATCH 3/8] Added password header to sp auth with password view --- Simplenote/AuthViewController+Swift.swift | 4 ++-- Simplenote/AuthenticationMode.swift | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Simplenote/AuthViewController+Swift.swift b/Simplenote/AuthViewController+Swift.swift index 1707364fc..e3c5a0b57 100644 --- a/Simplenote/AuthViewController+Swift.swift +++ b/Simplenote/AuthViewController+Swift.swift @@ -220,7 +220,7 @@ extension AuthViewController { @objc func pushPasswordView() { - pushNewAuthViewController(with: .loginWithPassword(), state: state) + pushNewAuthViewController(with: .loginWithPassword, state: state) } func pushCodeLoginView() { @@ -235,7 +235,7 @@ extension AuthViewController { @IBAction func switchToPasswordAuth(_ sender: Any) { - mode = AuthenticationMode.loginWithPassword(header: nil) + mode = AuthenticationMode.loginWithPassword } @objc diff --git a/Simplenote/AuthenticationMode.swift b/Simplenote/AuthenticationMode.swift index b45a80eaf..3dbd75039 100644 --- a/Simplenote/AuthenticationMode.swift +++ b/Simplenote/AuthenticationMode.swift @@ -120,9 +120,9 @@ extension AuthenticationMode { /// Auth Mode: Login with Username + Password /// - static func loginWithPassword(header: String? = nil) -> AuthenticationMode { + static var loginWithPassword: AuthenticationMode { AuthenticationMode(title: NSLocalizedString("Log In with Password", comment: "LogIn Interface Title"), - header: header, + header: LoginStrings.loginWithEmailEmailHeader, inputElements: [.password], actions: [ AuthenticationActionDescriptor(name: .primary, @@ -195,6 +195,7 @@ private enum LoginStrings { static let switchAction = NSLocalizedString("Sign Up", comment: "Title of button for signing up") static let switchTip = NSLocalizedString("Need an account?", comment: "Link to create an account") static let wordpressAction = NSLocalizedString("Log in with WordPress.com", comment: "Title to use wordpress login instead of email") + static let loginWithEmailEmailHeader = NSLocalizedString("Enter the password for the account {{EMAIL}}", comment: "Header for Login With Password. Please preserve the {{EMAIL}} substring") } private enum MagicLinkStrings { From 3d352de5352a5a4b2d6fbe010d6de59587a6ef6e Mon Sep 17 00:00:00 2001 From: Charlie Scheer Date: Thu, 25 Jul 2024 11:23:16 -0600 Subject: [PATCH 4/8] Dont highlight email text when becoming first responder on back --- Simplenote.xcodeproj/project.pbxproj | 4 ++++ Simplenote/AuthViewController+Swift.swift | 8 ++++---- .../SPAuthenticationTextField+Simplenote.swift | 13 +++++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 Simplenote/SPAuthenticationTextField+Simplenote.swift diff --git a/Simplenote.xcodeproj/project.pbxproj b/Simplenote.xcodeproj/project.pbxproj index 274aef269..f4bc06741 100644 --- a/Simplenote.xcodeproj/project.pbxproj +++ b/Simplenote.xcodeproj/project.pbxproj @@ -338,6 +338,7 @@ BACA687C2C0A764C005409C1 /* KeychainPasswordItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BACA687A2C0A7634005409C1 /* KeychainPasswordItem.swift */; }; BAD4ECC026E6FC0A00881CC4 /* markdown-light.css in Resources */ = {isa = PBXBuildFile; fileRef = BAF8D5DB26AE3BE800CA9383 /* markdown-light.css */; }; BAE66CAA26AF647500398FF3 /* Remote.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA938CEB26ACFF4A00BE5A1D /* Remote.swift */; }; + BAEBDD4A2C52C14500335700 /* SPAuthenticationTextField+Simplenote.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAEBDD492C52C14500335700 /* SPAuthenticationTextField+Simplenote.swift */; }; BAF1B0C32BC9B1C500B55F73 /* NoteWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF1B0C12BC9B1C500B55F73 /* NoteWindow.swift */; }; BAF1B0C92BCEDFD400B55F73 /* NoteWindowControllersManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF1B0C72BCDDA9600B55F73 /* NoteWindowControllersManager.swift */; }; BAF4E5DE2C49C08A009B891F /* SPNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF4E5DD2C49C08A009B891F /* SPNavigationController.swift */; }; @@ -807,6 +808,7 @@ BACA68752C0A72F3005409C1 /* NSString+Intents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSString+Intents.swift"; sourceTree = ""; }; BACA68772C0A7537005409C1 /* KeychainManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainManager.swift; sourceTree = ""; }; BACA687A2C0A7634005409C1 /* KeychainPasswordItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainPasswordItem.swift; sourceTree = ""; }; + BAEBDD492C52C14500335700 /* SPAuthenticationTextField+Simplenote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SPAuthenticationTextField+Simplenote.swift"; sourceTree = ""; }; BAF1B0C12BC9B1C500B55F73 /* NoteWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteWindow.swift; sourceTree = ""; }; BAF1B0C72BCDDA9600B55F73 /* NoteWindowControllersManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteWindowControllersManager.swift; sourceTree = ""; }; BAF4E5DD2C49C08A009B891F /* SPNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPNavigationController.swift; sourceTree = ""; }; @@ -1244,6 +1246,7 @@ BA2C65CA26FE996100FA84E1 /* NSButton+Extensions.swift */, BA52005C2BC88397003F1B75 /* NSManagedObjectContext+Simplenote.swift */, BAF4E5DF2C49C17A009B891F /* NSViewController+Simplenote.swift */, + BAEBDD492C52C14500335700 /* SPAuthenticationTextField+Simplenote.swift */, ); name = Extensions; sourceTree = ""; @@ -2243,6 +2246,7 @@ B5ACE42F24785D8C00AB02C7 /* BackgroundView.swift in Sources */, B5F5415525F0137100CAF52C /* MagicLinkAuthenticator.swift in Sources */, B58A71BF258422CC00601641 /* NSBezierPath+Simplenote.swift in Sources */, + BAEBDD4A2C52C14500335700 /* SPAuthenticationTextField+Simplenote.swift in Sources */, B587D7EE2C2217B1006645CF /* LoginRemoteProtocol.swift in Sources */, BAF4E5DE2C49C08A009B891F /* SPNavigationController.swift in Sources */, B5DD0F922476309000C8DD41 /* NoteTableCellView.swift in Sources */, diff --git a/Simplenote/AuthViewController+Swift.swift b/Simplenote/AuthViewController+Swift.swift index e3c5a0b57..61f3ff68b 100644 --- a/Simplenote/AuthViewController+Swift.swift +++ b/Simplenote/AuthViewController+Swift.swift @@ -180,7 +180,7 @@ extension AuthViewController { /// @objc func ensureFirstTextFieldIsFirstResponder() { - firstVisibleTextField?.textField.becomeFirstResponder() + firstVisibleTextField?.becomeFirstResponder() view.needsDisplay = true } } @@ -280,9 +280,9 @@ extension AuthViewController { do { - let email = usernameText - let remote = LoginRemote() - try await remote.requestLoginEmail(email: email) +// let email = usernameText +// let remote = LoginRemote() +// try await remote.requestLoginEmail(email: email) pushCodeLoginView() } catch { diff --git a/Simplenote/SPAuthenticationTextField+Simplenote.swift b/Simplenote/SPAuthenticationTextField+Simplenote.swift new file mode 100644 index 000000000..69adb2d83 --- /dev/null +++ b/Simplenote/SPAuthenticationTextField+Simplenote.swift @@ -0,0 +1,13 @@ +import Simperium_OSX + +extension SPAuthenticationTextField { + @discardableResult + override open func becomeFirstResponder() -> Bool { + let responderStatus = textField.becomeFirstResponder() + + let selectedRange = textField.currentEditor()?.selectedRange + textField.currentEditor()?.selectedRange = NSMakeRange(selectedRange?.length ?? .zero, .zero) + + return responderStatus + } +} From 2e972b53d95d4c50301843245c19ff03b8cb4784 Mon Sep 17 00:00:00 2001 From: Charlie Scheer Date: Thu, 25 Jul 2024 11:29:55 -0600 Subject: [PATCH 5/8] Fixed issue going to link invalid view back made auth not clickable --- Simplenote/AuthWindowController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Simplenote/AuthWindowController.swift b/Simplenote/AuthWindowController.swift index 27487b96f..41ddf6ba9 100644 --- a/Simplenote/AuthWindowController.swift +++ b/Simplenote/AuthWindowController.swift @@ -78,8 +78,9 @@ extension AuthWindowController { } let authViewController = AuthViewController() + let navigationController = SPNavigationController(initialViewController: authViewController) authViewController.authenticator = authenticator - window.transition(to: authViewController) + window.transition(to: navigationController) } func switchToMagicLinkRequestedUI(email: String) { From dda5310bba36f8ee05487416d78a44799f9985a2 Mon Sep 17 00:00:00 2001 From: Charlie Scheer Date: Thu, 25 Jul 2024 11:31:39 -0600 Subject: [PATCH 6/8] Removed comments on code that requests login codes --- Simplenote/AuthViewController+Swift.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Simplenote/AuthViewController+Swift.swift b/Simplenote/AuthViewController+Swift.swift index 61f3ff68b..93b693ca9 100644 --- a/Simplenote/AuthViewController+Swift.swift +++ b/Simplenote/AuthViewController+Swift.swift @@ -280,9 +280,9 @@ extension AuthViewController { do { -// let email = usernameText -// let remote = LoginRemote() -// try await remote.requestLoginEmail(email: email) + let email = usernameText + let remote = LoginRemote() + try await remote.requestLoginEmail(email: email) pushCodeLoginView() } catch { From 5e08a6a96c0cbf3d63bd3f5cbfd8a85cce7f6259 Mon Sep 17 00:00:00 2001 From: Charlie Scheer Date: Fri, 26 Jul 2024 09:27:16 -0600 Subject: [PATCH 7/8] Improved back button appearance --- Simplenote/SPNavigationController.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Simplenote/SPNavigationController.swift b/Simplenote/SPNavigationController.swift index 07dedd73d..10bbe18da 100644 --- a/Simplenote/SPNavigationController.swift +++ b/Simplenote/SPNavigationController.swift @@ -62,6 +62,12 @@ class SPNavigationController: NSViewController { backButton = button backButton.isHidden = hideBackButton button.bezelStyle = .accessoryBarAction + button.cell?.isBordered = false + button.contentTintColor = .darkGray + button.wantsLayer = true + button.layer?.cornerRadius = 5 + let trackingArea = NSTrackingArea(rect: backButton.bounds, options: [.mouseEnteredAndExited, .activeAlways], owner: self) + button.addTrackingArea(trackingArea) view.addSubview(backButton) NSLayoutConstraint.activate([ @@ -192,3 +198,15 @@ class SPNavigationController: NSViewController { } } } + +// MARK: - Button Hover Color Animation +// +extension SPNavigationController { + override func mouseEntered(with event: NSEvent) { + backButton.layer?.backgroundColor = NSColor.lightGray.withAlphaComponent(0.1).cgColor + } + + override func mouseExited(with event: NSEvent) { + backButton.layer?.backgroundColor = .clear + } +} From 045295c0e5c58d80baf363cc7f40669380b91790 Mon Sep 17 00:00:00 2001 From: Charlie Scheer Date: Fri, 26 Jul 2024 09:29:40 -0600 Subject: [PATCH 8/8] Updated text for login with email button --- Simplenote/AuthenticationMode.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Simplenote/AuthenticationMode.swift b/Simplenote/AuthenticationMode.swift index 3dbd75039..e6ecd2390 100644 --- a/Simplenote/AuthenticationMode.swift +++ b/Simplenote/AuthenticationMode.swift @@ -199,7 +199,7 @@ private enum LoginStrings { } private enum MagicLinkStrings { - static let primaryAction = NSLocalizedString("Instantly Log In with Email", comment: "Title of button for logging in") + static let primaryAction = NSLocalizedString("Log in with email", comment: "Title of button for logging in") static let primaryAnimationText = NSLocalizedString("Requesting Email...", comment: "Title of button for logging in") static let secondaryAction = NSLocalizedString("Continue with Password", comment: "Continue with Password Action") static let switchAction = NSLocalizedString("Sign Up", comment: "Title of button for signing up")