From 48a336b0491dbfe63a122cc5e6dbe79e85862c04 Mon Sep 17 00:00:00 2001 From: Kamol Date: Sun, 14 Mar 2021 07:49:33 +0000 Subject: [PATCH 1/2] [iOS-55] Implemented initial steps of SignInWith Apple. Implemented AuthManager class for all social auth's --- DoSport/DoSport.xcodeproj/project.pbxproj | 12 +++ .../DoSport/Application/AppCoordinator.swift | 7 +- DoSport/DoSport/Flow/Auth/AuthAssembly.swift | 7 +- .../DoSport/Flow/Auth/AuthCoordinator.swift | 1 + DoSport/DoSport/Flow/Auth/AuthView.swift | 100 ++++++++++++------ .../Flow/Auth/AuthViewController.swift | 20 +++- .../OnBoardingCoordinator.swift | 8 +- .../SocialMediaSignIn/AuthManager.swift | 83 +++++++++++++++ DoSport/Podfile.lock | 2 +- 9 files changed, 197 insertions(+), 43 deletions(-) create mode 100644 DoSport/DoSport/Service/SocialMediaSignIn/AuthManager.swift diff --git a/DoSport/DoSport.xcodeproj/project.pbxproj b/DoSport/DoSport.xcodeproj/project.pbxproj index fab09ca5..1e6bcc25 100644 --- a/DoSport/DoSport.xcodeproj/project.pbxproj +++ b/DoSport/DoSport.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ 6511D76C25B0CC880063EF76 /* FormTextFieldView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6511D76B25B0CC880063EF76 /* FormTextFieldView.swift */; }; 6511D77125B0DB130063EF76 /* DSTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6511D77025B0DB130063EF76 /* DSTextField.swift */; }; 6511D77625B0E5A10063EF76 /* DSButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6511D77525B0E5A10063EF76 /* DSButton.swift */; }; + 651FBF0225FDE5F10018C6B1 /* AuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 651FBF0125FDE5F10018C6B1 /* AuthManager.swift */; }; 6527303425C1B15B00550ED1 /* FeedFilterButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6527303325C1B15B00550ED1 /* FeedFilterButtonsView.swift */; }; 65294D9A25B38311003E7ED2 /* DatePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65294D9925B38311003E7ED2 /* DatePicker.swift */; }; 6529500C258D6EE2002AA621 /* UIColor+inits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6529500B258D6EE2002AA621 /* UIColor+inits.swift */; }; @@ -301,6 +302,7 @@ 6511D76B25B0CC880063EF76 /* FormTextFieldView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormTextFieldView.swift; sourceTree = ""; }; 6511D77025B0DB130063EF76 /* DSTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DSTextField.swift; sourceTree = ""; }; 6511D77525B0E5A10063EF76 /* DSButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DSButton.swift; sourceTree = ""; }; + 651FBF0125FDE5F10018C6B1 /* AuthManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthManager.swift; sourceTree = ""; }; 6527303325C1B15B00550ED1 /* FeedFilterButtonsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedFilterButtonsView.swift; sourceTree = ""; }; 65294D9925B38311003E7ED2 /* DatePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatePicker.swift; sourceTree = ""; }; 6529500B258D6EE2002AA621 /* UIColor+inits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+inits.swift"; sourceTree = ""; }; @@ -611,6 +613,14 @@ path = PasswordEntry; sourceTree = ""; }; + 651FBF0025FDE5E50018C6B1 /* SocialMediaSignIn */ = { + isa = PBXGroup; + children = ( + 651FBF0125FDE5F10018C6B1 /* AuthManager.swift */, + ); + path = SocialMediaSignIn; + sourceTree = ""; + }; 6531791D25D10DF6001DBA4B /* EventCreate */ = { isa = PBXGroup; children = ( @@ -1292,6 +1302,7 @@ CEDEB83B258CE0EF007B2BCA /* Service */ = { isa = PBXGroup; children = ( + 651FBF0025FDE5E50018C6B1 /* SocialMediaSignIn */, CEDEB83C258CE0FE007B2BCA /* Network */, ); path = Service; @@ -1731,6 +1742,7 @@ 6568F8ED25B4F98200225043 /* FeedView.swift in Sources */, CE0A6B58258FBA26007E02CC /* CustomPageControl.swift in Sources */, 65A62A0925E70109000AA184 /* DSEventCardView.swift in Sources */, + 651FBF0225FDE5F10018C6B1 /* AuthManager.swift in Sources */, 653DA7D025B3590A000263C9 /* ImagePicker.swift in Sources */, 6572954825D9540500996440 /* TableViewMemberCell.swift in Sources */, 65CD774425EB3ECE00D042FD /* SoundListDataSource.swift in Sources */, diff --git a/DoSport/DoSport/Application/AppCoordinator.swift b/DoSport/DoSport/Application/AppCoordinator.swift index 753e0eb2..4b82de36 100644 --- a/DoSport/DoSport/Application/AppCoordinator.swift +++ b/DoSport/DoSport/Application/AppCoordinator.swift @@ -26,7 +26,12 @@ final class AppCoordinator: Coordinator { let coordinator: Coordinator if isAuthorised { - coordinator = MainTabBarCoordinator(navController: navigationController) + if #available(iOS 13.0, *) { + coordinator = AuthCoordinator(navController: navigationController) + } else { + coordinator = MainTabBarCoordinator(navController: navigationController) + } + self.store(coordinator: coordinator) coordinator.start() } else { diff --git a/DoSport/DoSport/Flow/Auth/AuthAssembly.swift b/DoSport/DoSport/Flow/Auth/AuthAssembly.swift index ca9d137a..8fbb3d21 100644 --- a/DoSport/DoSport/Flow/Auth/AuthAssembly.swift +++ b/DoSport/DoSport/Flow/Auth/AuthAssembly.swift @@ -7,11 +7,16 @@ import Foundation +@available(iOS 13.0, *) final class AuthAssembly: Assembly { func makeModule() -> AuthViewController { let viewModel = AuthViewModel() - let viewController = AuthViewController(viewModel: viewModel) + let viewController: AuthViewController + + let authManeger: AuthManagerProtocol = AuthManager() + viewController = AuthViewController(viewModel: viewModel, authManeger: authManeger) + return viewController } } diff --git a/DoSport/DoSport/Flow/Auth/AuthCoordinator.swift b/DoSport/DoSport/Flow/Auth/AuthCoordinator.swift index 2fd51388..bc78463c 100644 --- a/DoSport/DoSport/Flow/Auth/AuthCoordinator.swift +++ b/DoSport/DoSport/Flow/Auth/AuthCoordinator.swift @@ -7,6 +7,7 @@ import UIKit +@available(iOS 13.0, *) final class AuthCoordinator: Coordinator { let rootViewController: AuthViewController diff --git a/DoSport/DoSport/Flow/Auth/AuthView.swift b/DoSport/DoSport/Flow/Auth/AuthView.swift index 378ffa83..a8c12825 100644 --- a/DoSport/DoSport/Flow/Auth/AuthView.swift +++ b/DoSport/DoSport/Flow/Auth/AuthView.swift @@ -6,11 +6,12 @@ // import UIKit -import SnapKit +import AuthenticationServices protocol AuthViewDelegate: AnyObject { func submitButtonTapped(with text: String) func regionSelectionButtonTapped() + func appleSignInButtomClicked() } final class AuthView: UIView { @@ -60,7 +61,13 @@ final class AuthView: UIView { return $0 }(CommonButton(title: Texts.Auth.submit, state: .normal)) - //MARK: - Init + @available(iOS 13.0, *) + private lazy var appleSignInButton: ASAuthorizationAppleIDButton = { + $0.addTarget(self, action: #selector(handleAppleSignInButton), for: .touchUpInside) + return $0 + }(ASAuthorizationAppleIDButton()) + + //MARK: Init init() { super.init(frame: .zero) @@ -80,7 +87,20 @@ final class AuthView: UIView { object: nil ) - addSubviews(logoImageView,titleLabel,descriptionLabel,phoneNumberAddView,regulationsLabel,submitButton) + addSubviews( + logoImageView, + titleLabel, + descriptionLabel, + phoneNumberAddView, + regulationsLabel, + submitButton + ) + + if #available(iOS 13.0, *) { + addSubview(appleSignInButton) + } else { + + } } required init?(coder: NSCoder) { @@ -128,29 +148,61 @@ final class AuthView: UIView { $0.height.equalTo(descriptionLabel) } - submitButton.snp.makeConstraints { - if #available(iOS 11.0, *) { - $0.bottom.equalTo(self.safeAreaLayoutGuide.snp.bottom).offset(-20) - $0.width.centerX.height.equalTo(phoneNumberAddView) - } else { - $0.bottom.equalToSuperview().offset(-16) - $0.width.centerX.height.equalTo(phoneNumberAddView) + if #available(iOS 13.0, *) { + appleSignInButton.snp.makeConstraints { + $0.centerX.equalToSuperview() + $0.width.equalToSuperview() + $0.centerY.equalToSuperview() + $0.height.equalTo(submitButton.snp.height) } + } else { + } + + submitButton.snp.makeConstraints { + $0.bottom.equalTo(self.safeAreaInsets.bottom).offset(-20) + $0.width.centerX.height.equalTo(phoneNumberAddView) + } + } +} + +//MARK: Public API + +extension AuthView { + + func bind(callingCode: String) { + phoneNumberAddView.bind(callingCode: callingCode) + submitButton.bind(state: .normal) // for test purposes, can be removed + layoutIfNeeded() + } + + func becomeTextFieldResponder() { + phoneNumberAddView.becomeResponder() + } + + func removeTextFieldResponder() { + phoneNumberAddView.removeFirstResponder() } +} + +//MARK: Actions + +@objc private extension AuthView { - //MARK: - Actions + func handleAppleSignInButton() { + delegate?.appleSignInButtomClicked() + } - @objc private func handleSubmitButton() { + func handleSubmitButton() { let text = phoneNumberAddView.text delegate?.submitButtonTapped(with: text) } - @objc private func handleRegionSelectionButton() { + func handleRegionSelectionButton() { delegate?.regionSelectionButtonTapped() } - @objc private func handleKeybordWillShow(_ notification: Notification) { + func handleKeybordWillShow(_ notification: Notification) { guard let userInfo = notification.userInfo, let keyboardFrame = ( @@ -163,28 +215,10 @@ final class AuthView: UIView { } } - @objc private func handleKeybordWillHide() { + func handleKeybordWillHide() { UIView.animate(withDuration: 0.3) { self.submitButton.transform = .identity } } } -//MARK: - Public Methods - -extension AuthView { - func bind(callingCode: String) { - phoneNumberAddView.bind(callingCode: callingCode) - submitButton.bind(state: .normal) // for test purposes, can be removed - layoutIfNeeded() - } - - func becomeTextFieldResponder() { - phoneNumberAddView.becomeResponder() - } - - func removeTextFieldResponder() { - phoneNumberAddView.removeFirstResponder() - } -} - diff --git a/DoSport/DoSport/Flow/Auth/AuthViewController.swift b/DoSport/DoSport/Flow/Auth/AuthViewController.swift index c1006843..e5ae92cc 100644 --- a/DoSport/DoSport/Flow/Auth/AuthViewController.swift +++ b/DoSport/DoSport/Flow/Auth/AuthViewController.swift @@ -7,21 +7,25 @@ import UIKit +@available(iOS 13.0, *) final class AuthViewController: UIViewController { weak var coordinator: AuthCoordinator? private let viewModel: AuthViewModel + private let authManager: AuthManagerProtocol? + private lazy var authView = self.view as! AuthView override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } - // MARK: - Init + // MARK: Init - init(viewModel: AuthViewModel) { + init(viewModel: AuthViewModel, authManeger: AuthManagerProtocol?) { self.viewModel = viewModel + self.authManager = authManeger super.init(nibName: nil, bundle: nil) } @@ -29,7 +33,7 @@ final class AuthViewController: UIViewController { fatalError("init(coder:) has not been implemented") } - // MARK: - Life Cycle + // MARK: Life Cycle override func loadView() { let view = AuthView() @@ -39,7 +43,7 @@ final class AuthViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - + } /// Hide navigation bar before this ViewController will appear @@ -69,7 +73,15 @@ final class AuthViewController: UIViewController { } } +//MARK: - AuthViewDelegate - + +@available(iOS 13.0, *) extension AuthViewController: AuthViewDelegate { + + func appleSignInButtomClicked() { + authManager?.signInWithApple(for: self) + } + func regionSelectionButtonTapped() { coordinator?.goToCountryListModule { callingCode in self.authView.bind(callingCode: callingCode) diff --git a/DoSport/DoSport/Flow/OnBoardViewController/OnBoardingCoordinator.swift b/DoSport/DoSport/Flow/OnBoardViewController/OnBoardingCoordinator.swift index c9a5c3b6..4408672b 100644 --- a/DoSport/DoSport/Flow/OnBoardViewController/OnBoardingCoordinator.swift +++ b/DoSport/DoSport/Flow/OnBoardViewController/OnBoardingCoordinator.swift @@ -28,8 +28,10 @@ final class OnBoardingCoordinator: Coordinator { } func goToAuthView() { - let coordiator = AuthCoordinator(navController: navigationController) - store(coordinator: coordiator) - coordiator.start() + if #available(iOS 13.0, *) { + let coordiator = AuthCoordinator(navController: navigationController) + store(coordinator: coordiator) + coordiator.start() + } } } diff --git a/DoSport/DoSport/Service/SocialMediaSignIn/AuthManager.swift b/DoSport/DoSport/Service/SocialMediaSignIn/AuthManager.swift new file mode 100644 index 00000000..849ad81b --- /dev/null +++ b/DoSport/DoSport/Service/SocialMediaSignIn/AuthManager.swift @@ -0,0 +1,83 @@ +// +// AuthManager.swift +// DoSport +// +// Created by Komolbek Ibragimov on 14/03/2021. +// + +import AuthenticationServices +import UIKit.UIViewController + +@available(iOS 13.0, *) +protocol AuthManagerProtocol: class { + func signInWithApple(for viewController: UIViewController) + func signInWithGoogle() + func signInWithFacebook() +} + +public final class AuthManager: NSObject { + + private weak var viewContorller: UIViewController? + + //MARK: Init + + public override init() { + super.init() + } +} + +//MARK: - AuthManagerProtocol - + +@available(iOS 13.0, *) +extension AuthManager: AuthManagerProtocol { + + func signInWithApple(for viewController: UIViewController) { + self.viewContorller = viewController + + let appleIDProvider = ASAuthorizationAppleIDProvider() + let request = appleIDProvider.createRequest() + request.requestedScopes = [.fullName, .email] + + let authorizationController = ASAuthorizationController(authorizationRequests: [request]) + authorizationController.delegate = self + authorizationController.presentationContextProvider = self + authorizationController.performRequests() + } + + func signInWithGoogle() { + + } + + func signInWithFacebook() { + + } +} + +//MARK: - SignIn With Apple - + +@available(iOS 13.0, *) +extension AuthManager: ASAuthorizationControllerDelegate { + + public func authorizationController( + controller: ASAuthorizationController, + didCompleteWithAuthorization authorization: ASAuthorization + ) { + + } +} + +@available(iOS 13.0, *) +extension AuthManager: ASAuthorizationControllerPresentationContextProviding { + + public func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor { + guard let window = self.viewContorller?.view.window else { + return ASPresentationAnchor() + } + + return window + } +} + +//MARK: - Sign In With FaceBook - + +//MARK: - Sign In With Google - diff --git a/DoSport/Podfile.lock b/DoSport/Podfile.lock index 99b8c73f..c42f7ec6 100644 --- a/DoSport/Podfile.lock +++ b/DoSport/Podfile.lock @@ -39,4 +39,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 16f7b1f33026e0fcdaf7badee7a8d5f907a6f3d3 -COCOAPODS: 1.10.0.rc.1 +COCOAPODS: 1.10.0 From dcb89d35ab5ba414ee8874d881029a4a521afdb8 Mon Sep 17 00:00:00 2001 From: Kamol Date: Sun, 14 Mar 2021 08:01:32 +0000 Subject: [PATCH 2/2] [iOS-55] Added DS_Store to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index d2d7ea58..c5017d35 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # Xcode # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore +../.DS_Store +.DS_Store +DoSport/.DS_Store ## User settings xcuserdata/