Skip to content

Commit

Permalink
refactor(OnboardingViewController): Abstracted away the post login an…
Browse files Browse the repository at this point in the history
…d register code to be able to use it from elsewhere.

feat: UpsaleViewController actions are performing the auth actions like expected.
  • Loading branch information
adrien-coye committed Dec 11, 2024
1 parent 93bbb8e commit 28552a8
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 83 deletions.
22 changes: 22 additions & 0 deletions kDrive/AppRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import InfomaniakCore
import InfomaniakCoreUIKit
import InfomaniakDI
import InfomaniakLogin
import kDriveCore
import kDriveResources
import SafariServices
Expand All @@ -33,6 +34,7 @@ public struct AppRouter: AppNavigable {
@LazyInjectService private var reviewManager: ReviewManageable
@LazyInjectService private var availableOfflineManager: AvailableOfflineManageable
@LazyInjectService private var accountManager: AccountManageable
@LazyInjectService private var infomaniakLogin: InfomaniakLoginable

@LazyInjectService var backgroundDownloadSessionManager: BackgroundDownloadSessionManager
@LazyInjectService var backgroundUploadSessionManager: BackgroundUploadSessionManager
Expand Down Expand Up @@ -444,6 +446,26 @@ public struct AppRouter: AppNavigable {
viewController.present(vc, animated: true)
}

@MainActor public func showRegister(delegate: InfomaniakLoginDelegate) {
guard let topMostViewController else {
return
}

MatomoUtils.track(eventWithCategory: .account, name: "openCreationWebview")
let registerViewController = RegisterViewController.instantiateInNavigationController(delegate: delegate)
topMostViewController.present(registerViewController, animated: true)
}

@MainActor public func showLogin(delegate: InfomaniakLoginDelegate) {
guard let topMostViewController else {
return
}

infomaniakLogin.webviewLoginFrom(viewController: topMostViewController,
hideCreateAccountButton: true,
delegate: delegate)
}

// MARK: AppExtensionRouter

public func showStore(from viewController: UIViewController, driveFileManager: DriveFileManager) {
Expand Down
16 changes: 11 additions & 5 deletions kDrive/UI/Controller/Files/File List/FileListViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ extension SortType: Selectable {
class FileListViewController: UICollectionViewController, SwipeActionCollectionViewDelegate,
SwipeActionCollectionViewDataSource, FilesHeaderViewDelegate, SceneStateRestorable {
@LazyInjectService var accountManager: AccountManageable
@LazyInjectService var router: AppNavigable

// MARK: - Constants

Expand Down Expand Up @@ -301,15 +302,20 @@ class FileListViewController: UICollectionViewController, SwipeActionCollectionV

// Create an account
upsaleViewController.freeTrialCallback = { [weak self] in
self?.dismiss(animated: true)
// TODO: Present login
// MatomoUtils.track(eventWithCategory: .account, name: "openCreationWebview")
// present(RegisterViewController.instantiateInNavigationController(delegate: self), animated: true)
guard let self else { return }
self.dismiss(animated: true) {
let loginDelegateHandler = LoginDelegateHandler()
self.router.showRegister(delegate: loginDelegateHandler)
}
}

// Let the user login with the onboarding
upsaleViewController.loginCallback = { [weak self] in
self?.dismiss(animated: true)
guard let self else { return }
self.dismiss(animated: true) {
let loginDelegateHandler = LoginDelegateHandler()
self.router.showLogin(delegate: loginDelegateHandler)
}
}

let floatingPanel = UpsaleFloatingPanelController(upsaleViewController: upsaleViewController)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ extension SaveFileViewController: FooterButtonDelegate {
private func savePublicShareToDrive(sourceDriveId: Int,
destinationDriveId: Int,
fileIds: [Int],
exceptIds: [Int]) async {
exceptIds: [Int]) async throws {
defer {
dismiss(animated: true)
}
Expand Down
117 changes: 117 additions & 0 deletions kDrive/UI/Controller/LoginDelegateHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
Infomaniak kDrive - iOS App
Copyright (C) 2024 Infomaniak Network SA

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import CocoaLumberjackSwift
import InfomaniakCore
import InfomaniakDI
import InfomaniakLogin
import kDriveCore
import kDriveResources
import Lottie
import UIKit

/// Something to abstract away from the view the post login/register logic
public class LoginDelegateHandler: InfomaniakLoginDelegate {
@LazyInjectService var accountManager: AccountManageable
@LazyInjectService var router: AppNavigable

var didStartLoginCompletion: (() -> Void)?
var didCompleteLoginCompletion: (() -> Void)?
var didFailLoginWithErrorCompletion: ((Error) -> Void)?

public init(didCompleteLoginCompletion: (() -> Void)? = nil) {
self.didCompleteLoginCompletion = didCompleteLoginCompletion
}

@MainActor public func didCompleteLoginWith(code: String, verifier: String) {
guard let topMostViewController = router.topMostViewController else { return }

MatomoUtils.track(eventWithCategory: .account, name: "loggedIn")
let previousAccount = accountManager.currentAccount

didStartLoginCompletion?()

Task {
do {
_ = try await accountManager.createAndSetCurrentAccount(code: code, codeVerifier: verifier)
guard let currentDriveFileManager = accountManager.currentDriveFileManager else {
throw DriveError.NoDriveError.noDriveFileManager
}

MatomoUtils.connectUser()
goToMainScreen(with: currentDriveFileManager)
} catch {
didCompleteLoginWithError(error, previousAccount: previousAccount, topMostViewController: topMostViewController)
}

didCompleteLoginCompletion?()
}
}

@MainActor private func goToMainScreen(with driveFileManager: DriveFileManager) {
UserDefaults.shared.legacyIsFirstLaunch = false
UserDefaults.shared.numberOfConnections = 1
_ = router.showMainViewController(driveFileManager: driveFileManager, selectedIndex: nil)
}

private func didCompleteLoginWithError(_ error: Error,
previousAccount: Account?,
topMostViewController: UIViewController) {
DDLogError("Error on didCompleteLoginWith \(error)")

if let previousAccount {
accountManager.switchAccount(newAccount: previousAccount)
}

if let noDriveError = error as? InfomaniakCore.ApiError, noDriveError.code == DriveError.noDrive.code {
let driveErrorVC = DriveErrorViewController.instantiate(errorType: .noDrive, drive: nil)
topMostViewController.present(driveErrorVC, animated: true)
} else if let driveError = error as? DriveError,
driveError == .noDrive
|| driveError == .productMaintenance
|| driveError == .driveMaintenance
|| driveError == .blocked {
let errorViewType: DriveErrorViewController.DriveErrorViewType
switch driveError {
case .productMaintenance, .driveMaintenance:
errorViewType = .maintenance
case .blocked:
errorViewType = .blocked
default:
errorViewType = .noDrive
}

let driveErrorVC = DriveErrorViewController.instantiate(errorType: errorViewType, drive: nil)
topMostViewController.present(driveErrorVC, animated: true)
} else {
let metadata = [
"Underlying Error": error.asAFError?.underlyingError.debugDescription ?? "Not an AFError"
]
SentryDebug.capture(error: error, context: metadata, contextKey: "Error")

topMostViewController.okAlert(
title: KDriveResourcesStrings.Localizable.errorTitle,
message: KDriveResourcesStrings.Localizable.errorConnection
)
}
}

public func didFailLoginWith(error: Error) {
didFailLoginWithErrorCompletion?(error)
}
}
102 changes: 25 additions & 77 deletions kDrive/UI/Controller/OnboardingViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import Lottie
import UIKit

class OnboardingViewController: UIViewController {
@LazyInjectService var router: AppNavigable

@IBOutlet var navigationBar: UINavigationBar!
@IBOutlet var collectionView: UICollectionView!
@IBOutlet var pageControl: UIPageControl!
Expand All @@ -47,6 +49,27 @@ class OnboardingViewController: UIViewController {
var addUser = false
var slides: [Slide] = []

private lazy var loginDelegateHandler: LoginDelegateHandler = {
let loginDelegateHandler = LoginDelegateHandler()
loginDelegateHandler.didStartLoginCompletion = { [weak self] in
guard let self else { return }
signInButton.setLoading(true)
registerButton.isEnabled = false
}
loginDelegateHandler.didCompleteLoginCompletion = { [weak self] in
guard let self else { return }
self.signInButton.setLoading(false)
self.registerButton.isEnabled = true
self.endBackgroundTask()
}
loginDelegateHandler.didFailLoginWithErrorCompletion = { [weak self] _ in
guard let self else { return }
self.signInButton.setLoading(false)
self.registerButton.isEnabled = true
}
return loginDelegateHandler
}()

private var backgroundTaskIdentifier: UIBackgroundTaskIdentifier = .invalid

override func viewDidLoad() {
Expand Down Expand Up @@ -130,26 +153,17 @@ class OnboardingViewController: UIViewController {
SentryDebug.capture(message: "Background task expired while logging in")
self?.endBackgroundTask()
}
infomaniakLogin.webviewLoginFrom(viewController: self,
hideCreateAccountButton: true,
delegate: self)
router.showLogin(delegate: loginDelegateHandler)
}

@IBAction func registerButtonPressed(_ sender: Any) {
MatomoUtils.track(eventWithCategory: .account, name: "openCreationWebview")
present(RegisterViewController.instantiateInNavigationController(delegate: self), animated: true)
router.showRegister(delegate: loginDelegateHandler)
}

@IBAction func closeButtonPressed(_ sender: Any) {
dismiss(animated: true)
}

private func goToMainScreen(with driveFileManager: DriveFileManager) {
UserDefaults.shared.legacyIsFirstLaunch = false
UserDefaults.shared.numberOfConnections = 1
appNavigable.showMainViewController(driveFileManager: driveFileManager, selectedIndex: nil)
}

private func updateButtonsState() {
if pageControl.currentPage == slides.count - 1 {
if buttonContentView.isHidden {
Expand Down Expand Up @@ -260,69 +274,3 @@ extension OnboardingViewController: UICollectionViewDelegate, UICollectionViewDa
updateButtonsState()
}
}

// MARK: - Infomaniak Login Delegate

extension OnboardingViewController: InfomaniakLoginDelegate {
func didCompleteLoginWith(code: String, verifier: String) {
MatomoUtils.track(eventWithCategory: .account, name: "loggedIn")
let previousAccount = accountManager.currentAccount
signInButton.setLoading(true)
registerButton.isEnabled = false
Task {
do {
_ = try await accountManager.createAndSetCurrentAccount(code: code, codeVerifier: verifier)
guard let currentDriveFileManager = accountManager.currentDriveFileManager else {
throw DriveError.NoDriveError.noDriveFileManager
}
signInButton.setLoading(false)
registerButton.isEnabled = true
MatomoUtils.connectUser()
goToMainScreen(with: currentDriveFileManager)
} catch {
DDLogError("Error on didCompleteLoginWith \(error)")

if let previousAccount {
accountManager.switchAccount(newAccount: previousAccount)
}
signInButton.setLoading(false)
registerButton.isEnabled = true
if let noDriveError = error as? InfomaniakCore.ApiError, noDriveError.code == DriveError.noDrive.code {
let driveErrorVC = DriveErrorViewController.instantiate(errorType: .noDrive, drive: nil)
present(driveErrorVC, animated: true)
} else if let driveError = error as? DriveError,
driveError == .noDrive
|| driveError == .productMaintenance
|| driveError == .driveMaintenance
|| driveError == .blocked {
let errorViewType: DriveErrorViewController.DriveErrorViewType
switch driveError {
case .productMaintenance, .driveMaintenance:
errorViewType = .maintenance
case .blocked:
errorViewType = .blocked
default:
errorViewType = .noDrive
}
let driveErrorVC = DriveErrorViewController.instantiate(errorType: errorViewType, drive: nil)
present(driveErrorVC, animated: true)
} else {
let metadata = [
"Underlying Error": error.asAFError?.underlyingError.debugDescription ?? "Not an AFError"
]
SentryDebug.capture(error: error, context: metadata, contextKey: "Error")
okAlert(
title: KDriveResourcesStrings.Localizable.errorTitle,
message: KDriveResourcesStrings.Localizable.errorConnection
)
}
}
endBackgroundTask()
}
}

func didFailLoginWith(error: Error) {
signInButton.setLoading(false)
registerButton.isEnabled = true
}
}
7 changes: 7 additions & 0 deletions kDriveCore/Utils/AppNavigable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import Foundation
import InfomaniakCore
import InfomaniakLogin
import UIKit

/// Something that can navigate to specific places of the kDrive app
Expand Down Expand Up @@ -45,6 +46,12 @@ public protocol RouterAppNavigable {
driveFileManager: DriveFileManager,
files: [ImportedFile]
)

/// Present login webView on top of the topMostViewController
@MainActor func showLogin(delegate: InfomaniakLoginDelegate)

/// Present register webView on top of the topMostViewController
@MainActor func showRegister(delegate: InfomaniakLoginDelegate)
}

/// Routing methods available from both the AppExtension mode and App
Expand Down

0 comments on commit 28552a8

Please sign in to comment.