@@ -26,6 +26,7 @@ import UIKit
2626import NextcloudKit
2727import SwiftEntryKit
2828import SwiftUI
29+ import SafariServices
2930
3031class NCLogin : UIViewController , UITextFieldDelegate , NCLoginQRCodeDelegate {
3132 @IBOutlet weak var imageBrand : UIImageView !
@@ -46,10 +47,6 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
4647
4748 private var shareAccounts : [ NKShareAccounts . DataAccounts ] ?
4849
49- var loginFlowV2Token = " "
50- var loginFlowV2Endpoint = " "
51- var loginFlowV2Login = " "
52-
5350 /// The URL that will show up on the URL field when this screen appears
5451 var urlBase = " "
5552
@@ -62,6 +59,12 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
6259 private var p12Data : Data ?
6360 private var p12Password : String ?
6461
62+ var pollTimer : DispatchSourceTimer ?
63+
64+ var ncLoginPollModel = NCLoginPollModel ( )
65+
66+ var loginFlowInProgress = false
67+
6568 // MARK: - View Life Cycle
6669
6770 override func viewDidLoad( ) {
@@ -182,11 +185,11 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
182185 enforceServersButton. menu = . init( title: NSLocalizedString ( " _servers_ " , comment: " " ) , children: actions)
183186 enforceServersButton. showsMenuAsPrimaryAction = true
184187 enforceServersButton. configuration? . titleTextAttributesTransformer =
185- UIConfigurationTextAttributesTransformer { incoming in
186- var outgoing = incoming
187- outgoing. font = UIFont . systemFont ( ofSize: 13 )
188- return outgoing
189- }
188+ UIConfigurationTextAttributesTransformer { incoming in
189+ var outgoing = incoming
190+ outgoing. font = UIFont . systemFont ( ofSize: 13 )
191+ return outgoing
192+ }
190193 }
191194 }
192195
@@ -283,7 +286,6 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
283286 }
284287
285288 @IBAction func actionQRCode( _ sender: Any ) {
286-
287289 let qrCode = NCLoginQRCode ( delegate: self )
288290 qrCode. scan ( )
289291 }
@@ -316,6 +318,7 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
316318 guard var url = baseUrlTextField. text? . trimmingCharacters ( in: . whitespacesAndNewlines) else { return }
317319 if url. hasSuffix ( " / " ) { url = String ( url. dropLast ( ) ) }
318320 if url. isEmpty { return }
321+
319322 // Check whether baseUrl contain protocol. If not add https:// by default.
320323 if url. hasPrefix ( " https " ) == false && url. hasPrefix ( " http " ) == false {
321324 url = " https:// " + url
@@ -326,26 +329,41 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
326329
327330 func isUrlValid( url: String , user: String ? = nil ) {
328331 loginButton. isEnabled = false
329- NextcloudKit . shared. getServerStatus ( serverUrl: url) { _, serverInfoResult in
332+ loginButton. hideButtonAndShowSpinner ( )
333+
334+ NextcloudKit . shared. getServerStatus ( serverUrl: url) { [ self ] _, serverInfoResult in
330335 switch serverInfoResult {
331336 case . success( let serverInfo) :
332337 if let host = URL ( string: url) ? . host {
333338 NCNetworking . shared. writeCertificate ( host: host)
334339 }
335- NextcloudKit . shared. getLoginFlowV2 ( serverUrl: url) { token, endpoint, login, _, error in
336- self . loginButton. isEnabled = true
340+ NextcloudKit . shared. getLoginFlowV2 ( serverUrl: url) { [ self ] token, endpoint, login, _, error in
337341 // Login Flow V2
338342 if error == . success, let token, let endpoint, let login {
339- let vc = UIHostingController ( rootView: NCLoginPoll ( loginFlowV2Token: token, loginFlowV2Endpoint: endpoint, loginFlowV2Login: login) )
340- self . present ( vc, animated: true )
343+ guard let url = URL ( string: login) else { return }
344+ let vc : UIViewController
345+
346+ poll ( loginFlowV2Token: token, loginFlowV2Endpoint: endpoint, loginFlowV2Login: login)
347+
348+ if NCBrandOptions . shared. use_in_app_browser_for_login {
349+ let safariVC = SFSafariViewController ( url: url)
350+ safariVC. delegate = self
351+ vc = safariVC
352+ } else {
353+ vc = UIHostingController ( rootView: NCLoginPoll ( loginFlowV2Login: login, model: ncLoginPollModel) )
354+ }
355+
356+ present ( vc, animated: true )
341357 } else if serverInfo. versionMajor < NCGlobal . shared. nextcloudVersion12 { // No login flow available
342358 let alertController = UIAlertController ( title: NSLocalizedString ( " _error_ " , comment: " " ) , message: NSLocalizedString ( " _webflow_not_available_ " , comment: " " ) , preferredStyle: . alert)
343359 alertController. addAction ( UIAlertAction ( title: NSLocalizedString ( " _ok_ " , comment: " " ) , style: . default, handler: { _ in } ) )
344- self . present ( alertController, animated: true , completion: { } )
360+ present ( alertController, animated: true , completion: { } )
345361 }
346362 }
347363 case . failure( let error) :
348- self . loginButton. isEnabled = true
364+ loginButton. hideSpinnerAndShowButton ( )
365+ loginButton. isEnabled = true
366+
349367 if error. errorCode == NSURLErrorServerCertificateUntrusted {
350368 let alertController = UIAlertController ( title: NSLocalizedString ( " _ssl_certificate_untrusted_ " , comment: " " ) , message: NSLocalizedString ( " _connect_server_anyway_ " , comment: " " ) , preferredStyle: . alert)
351369 alertController. addAction ( UIAlertAction ( title: NSLocalizedString ( " _yes_ " , comment: " " ) , style: . default, handler: { _ in
@@ -473,7 +491,6 @@ extension NCLogin: ClientCertificateDelegate, UIDocumentPickerDelegate {
473491 let alertEnterPassword = UIAlertController ( title: NSLocalizedString ( " _client_cert_enter_password_ " , comment: " " ) , message: " " , preferredStyle: . alert)
474492 alertEnterPassword. addAction ( UIAlertAction ( title: NSLocalizedString ( " _cancel_ " , comment: " " ) , style: . cancel, handler: nil ) )
475493 alertEnterPassword. addAction ( UIAlertAction ( title: NSLocalizedString ( " _ok_ " , comment: " " ) , style: . default, handler: { _ in
476- // let documentProviderMenu = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.pkcs12])
477494 NCNetworking . shared. p12Data = try ? Data ( contentsOf: urls [ 0 ] )
478495 NCNetworking . shared. p12Password = alertEnterPassword. textFields ? [ 0 ] . text
479496 self . login ( )
@@ -491,4 +508,63 @@ extension NCLogin: ClientCertificateDelegate, UIDocumentPickerDelegate {
491508 alertWrongPassword. addAction ( UIAlertAction ( title: NSLocalizedString ( " _ok_ " , comment: " " ) , style: . default) )
492509 present ( alertWrongPassword, animated: true )
493510 }
511+
512+ func poll( loginFlowV2Token: String , loginFlowV2Endpoint: String , loginFlowV2Login: String ) {
513+ let queue = DispatchQueue . global ( qos: . background)
514+ pollTimer = DispatchSource . makeTimerSource ( queue: queue)
515+
516+ guard let timer = pollTimer else { return }
517+
518+ timer. schedule ( deadline: . now( ) , repeating: . seconds( 1 ) , leeway: . seconds( 1 ) )
519+ timer. setEventHandler ( handler: {
520+ DispatchQueue . main. async {
521+ let controller = UIApplication . shared. firstWindow? . rootViewController as? NCMainTabBarController
522+ NextcloudKit . shared. getLoginFlowV2Poll ( token: loginFlowV2Token, endpoint: loginFlowV2Endpoint) { [ self ] server, loginName, appPassword, _, error in
523+ if error == . success, let urlBase = server, let user = loginName, let appPassword {
524+ loginFlowInProgress = true
525+ ncLoginPollModel. isLoading = true
526+
527+ NCAccount ( ) . createAccount ( urlBase: urlBase, user: user, password: appPassword, controller: controller) { account, error in
528+
529+ if error == . success {
530+ let window = UIApplication . shared. firstWindow
531+ if let controller = window? . rootViewController as? NCMainTabBarController {
532+ controller. account = account
533+ controller. dismiss ( animated: true , completion: nil )
534+ } else {
535+ if let controller = UIStoryboard ( name: " Main " , bundle: nil ) . instantiateInitialViewController ( ) as? NCMainTabBarController {
536+ controller. account = account
537+ controller. modalPresentationStyle = . fullScreen
538+ controller. view. alpha = 0
539+
540+ window? . rootViewController = controller
541+ window? . makeKeyAndVisible ( )
542+
543+ if let scene = window? . windowScene {
544+ SceneManager . shared. register ( scene: scene, withRootViewController: controller)
545+ }
546+
547+ UIView . animate ( withDuration: 0.5 ) {
548+ controller. view. alpha = 1
549+ }
550+ }
551+ }
552+ }
553+ }
554+ }
555+ }
556+ }
557+ } )
558+
559+ timer. resume ( )
560+ }
561+ }
562+
563+ extension NCLogin : SFSafariViewControllerDelegate {
564+ func safariViewControllerDidFinish( _ controller: SFSafariViewController ) {
565+ if !loginFlowInProgress {
566+ loginButton. isEnabled = true
567+ loginButton. hideSpinnerAndShowButton ( )
568+ }
569+ }
494570}
0 commit comments