Skip to content

Commit bd92b2a

Browse files
committed
WIP
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> WIP Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> WIP Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> WIP Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> WIP Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> WIP Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> Finish Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> WIP Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
1 parent 3089502 commit bd92b2a

File tree

7 files changed

+244
-184
lines changed

7 files changed

+244
-184
lines changed

Brand/NCBrand.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ let userAgent: String = {
7373
var doNotAskPasscodeAtStartup: Bool = false
7474
var disable_source_code_in_settings: Bool = false
7575
var enforce_passcode_lock = false
76+
var use_in_app_browser_for_login = true
7677

7778
// (name: "Name 1", url: "https://cloud.nextcloud.com"),(name: "Name 2", url: "https://cloud.nextcloud.com")
7879
var enforce_servers: [(name: String, url: String)] = []

Nextcloud.xcodeproj/project.pbxproj

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
F310B1EF2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = F310B1EE2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift */; };
6868
F314F1142A30E2DE00BC7FAB /* View+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E8A390295DC5E0006CB2D0 /* View+Extension.swift */; };
6969
F321DA8A2B71205A00DDA0E6 /* NCTrashSelectTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F321DA892B71205A00DDA0E6 /* NCTrashSelectTabBar.swift */; };
70+
F32FADA92D1176E3007035E2 /* UIButton+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32FADA82D1176DE007035E2 /* UIButton+Extension.swift */; };
7071
F33918C42C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F33918C32C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift */; };
7172
F33918C52C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F33918C32C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift */; };
7273
F33918C62C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F33918C32C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift */; };
@@ -168,6 +169,7 @@
168169
F3BB464D2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F3BB464C2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib */; };
169170
F3BB46522A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */; };
170171
F3BB46542A3A1E9D00461F6E /* CCCellMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */; };
172+
F3CA33842D10726E00672333 /* NCLoginPollModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3CA33832D10726E00672333 /* NCLoginPollModel.swift */; };
171173
F3E173B02C9AF637006D177A /* ScreenAwakeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173AF2C9AF637006D177A /* ScreenAwakeManager.swift */; };
172174
F3E173C02C9B1067006D177A /* AwakeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173BF2C9B1067006D177A /* AwakeMode.swift */; };
173175
F3E173C12C9B1067006D177A /* AwakeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E173BF2C9B1067006D177A /* AwakeMode.swift */; };
@@ -1201,6 +1203,7 @@
12011203
D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActivityTableViewCell.swift; sourceTree = "<group>"; };
12021204
F310B1EE2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCViewerMedia+VisionKit.swift"; sourceTree = "<group>"; };
12031205
F321DA892B71205A00DDA0E6 /* NCTrashSelectTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCTrashSelectTabBar.swift; sourceTree = "<group>"; };
1206+
F32FADA82D1176DE007035E2 /* UIButton+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Extension.swift"; sourceTree = "<group>"; };
12041207
F33918C32C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileNameValidator+Extensions.swift"; sourceTree = "<group>"; };
12051208
F33EE6F12BF4C9B200CA1A51 /* PKCS12.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PKCS12.swift; sourceTree = "<group>"; };
12061209
F343A4B22A1E01FF00DDA874 /* PHAsset+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PHAsset+Extension.swift"; sourceTree = "<group>"; };
@@ -1223,6 +1226,7 @@
12231226
F3BB464C2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCMoreAppSuggestionsCell.xib; sourceTree = "<group>"; };
12241227
F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMoreAppSuggestionsCell.swift; sourceTree = "<group>"; };
12251228
F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCCellMore.swift; sourceTree = "<group>"; };
1229+
F3CA33832D10726E00672333 /* NCLoginPollModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginPollModel.swift; sourceTree = "<group>"; };
12261230
F3E173AF2C9AF637006D177A /* ScreenAwakeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenAwakeManager.swift; sourceTree = "<group>"; };
12271231
F3E173BF2C9B1067006D177A /* AwakeMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AwakeMode.swift; sourceTree = "<group>"; };
12281232
F3EF2E0B2BFCF3810025EF46 /* NCLoginPoll.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginPoll.swift; sourceTree = "<group>"; };
@@ -2038,6 +2042,15 @@
20382042
path = Cells;
20392043
sourceTree = "<group>";
20402044
};
2045+
F3CA33802D106FF900672333 /* Poll */ = {
2046+
isa = PBXGroup;
2047+
children = (
2048+
F3EF2E0B2BFCF3810025EF46 /* NCLoginPoll.swift */,
2049+
F3CA33832D10726E00672333 /* NCLoginPollModel.swift */,
2050+
);
2051+
path = Poll;
2052+
sourceTree = "<group>";
2053+
};
20412054
F3E173BE2C9B1057006D177A /* ScreenAwakeManager */ = {
20422055
isa = PBXGroup;
20432056
children = (
@@ -2622,6 +2635,7 @@
26222635
F7A0D14E259229FA008F8A13 /* Extensions */ = {
26232636
isa = PBXGroup;
26242637
children = (
2638+
F32FADA82D1176DE007035E2 /* UIButton+Extension.swift */,
26252639
F7AC1CAF28AB94490032D99F /* Array+Extension.swift */,
26262640
F7817CF729801A3500FFBC65 /* Data+Extension.swift */,
26272641
AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */,
@@ -2733,14 +2747,14 @@
27332747
F7BFFA621A24D7300044ED85 /* Login */ = {
27342748
isa = PBXGroup;
27352749
children = (
2750+
F3CA33802D106FF900672333 /* Poll */,
27362751
F702F2F025EE5CDA008F8E80 /* NCLogin.storyboard */,
27372752
F702F2F625EE5CEC008F8E80 /* NCLogin.swift */,
27382753
F738D48F2756740100CD1D38 /* NCLoginNavigationController.swift */,
27392754
F745B252222D88AE00346520 /* NCLoginQRCode.swift */,
27402755
F7AE00F4230D5F9E007ACF8A /* NCLoginProvider.swift */,
27412756
F7BC287D26663F6C004D46C5 /* NCViewCertificateDetails.storyboard */,
27422757
F7BC287F26663F85004D46C5 /* NCViewCertificateDetails.swift */,
2743-
F3EF2E0B2BFCF3810025EF46 /* NCLoginPoll.swift */,
27442758
);
27452759
path = Login;
27462760
sourceTree = "<group>";
@@ -4287,8 +4301,10 @@
42874301
F7AE00F8230E81CB007ACF8A /* NCBrowserWeb.swift in Sources */,
42884302
F77DD6A82C5CC093009448FB /* NCSession.swift in Sources */,
42894303
F702F30825EE5D47008F8E80 /* NCPopupViewController.swift in Sources */,
4304+
F3CA33842D10726E00672333 /* NCLoginPollModel.swift in Sources */,
42904305
F733598125C1C188002ABA72 /* NCAskAuthorization.swift in Sources */,
42914306
370D26AF248A3D7A00121797 /* NCCellProtocol.swift in Sources */,
4307+
F32FADA92D1176E3007035E2 /* UIButton+Extension.swift in Sources */,
42924308
F768822C2C0DD1E7001CF441 /* NCKeychain.swift in Sources */,
42934309
F7BFFD282C8846020029A201 /* NCHud.swift in Sources */,
42944310
F71CD6CA2930D7B1006C95C1 /* NCApplicationHandle.swift in Sources */,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// UIButton+Extension.swift
3+
// Nextcloud
4+
//
5+
// Created by Milen Pivchev on 17.12.24.
6+
// Copyright © 2024 Marino Faggiana. All rights reserved.
7+
//
8+
9+
extension UIButton {
10+
func hideButtonAndShowSpinner(tint: UIColor = .white) {
11+
self.isHidden = true
12+
13+
let spinnerTag = Int(bitPattern: Unmanaged.passUnretained(self).toOpaque())
14+
if self.superview?.subviews.first(where: { view -> Bool in
15+
return view.isKind(of: UIActivityIndicatorView.self) && view.tag == spinnerTag
16+
}) != nil {
17+
return
18+
}
19+
20+
let spinner = UIActivityIndicatorView(style: .medium)
21+
spinner.tag = spinnerTag
22+
spinner.color = tint
23+
spinner.startAnimating()
24+
spinner.center = self.center
25+
self.superview?.addSubview(spinner)
26+
spinner.translatesAutoresizingMaskIntoConstraints = false
27+
spinner.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
28+
spinner.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
29+
}
30+
31+
func hideSpinnerAndShowButton() {
32+
let spinnerTag = Int(bitPattern: Unmanaged.passUnretained(self).toOpaque())
33+
let spinner = self.superview?.subviews.first(where: { view -> Bool in
34+
return view.isKind(of: UIActivityIndicatorView.self) && view.tag == spinnerTag
35+
})
36+
37+
spinner?.removeFromSuperview()
38+
self.isHidden = false
39+
}
40+
}

iOSClient/Login/NCLogin.swift

Lines changed: 94 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import UIKit
2626
import NextcloudKit
2727
import SwiftEntryKit
2828
import SwiftUI
29+
import SafariServices
2930

3031
class 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

Comments
 (0)