Skip to content

Commit

Permalink
[fix/branding-login-retry] Retry Section for Branded Login Error (#1047)
Browse files Browse the repository at this point in the history
* add a error section with a retry button in branded login view

* #4786 added a retry interval of 10 seconds. In this time interval the app retries to establish the connection before a error message will be shown

* only retry for network issues

* only show retry section on network issues

* - changed retry time interval to 30 seconds
- retries minimum of 3 times

* Update ownCloud/Static Login/Interface/StaticLoginSetupViewController.swift

Co-authored-by: Felix Schwarz <fs-git@iospirit.com>

* fixed connection retry and show retry section UI

* HTTP pipeline is ready to schedule HTTP requests before the Static Login View Controller is brought up. Moved it before setting up the UIWindow

* removed connection retries output and put it into the log

Co-authored-by: Felix Schwarz <fs-git@iospirit.com>
  • Loading branch information
hosy and felix-schwarz authored Nov 12, 2021
1 parent fa81414 commit 728cf67
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 29 deletions.
5 changes: 3 additions & 2 deletions ownCloud/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// Set up license management
OCLicenseManager.shared.setupLicenseManagement()

// Set up HTTP pipelines
OCHTTPPipelineManager.setupPersistentPipelines()

// Set up app
window = ThemeWindow(frame: UIScreen.main.bounds)

Expand Down Expand Up @@ -83,8 +86,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
AppLockManager.shared.showLockscreenIfNeeded()
}

OCHTTPPipelineManager.setupPersistentPipelines() // Set up HTTP pipelines

FileProviderInterfaceManager.shared.updateDomainsFromBookmarks()

ScheduledTaskManager.shared.setup()
Expand Down
1 change: 1 addition & 0 deletions ownCloud/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"Manage Storage" = "Manage Storage";
"Access Files" = "Access Files";
"Log out" = "Log out";
"Retry" = "Retry";

/* Bookmark Info */
"Bookmark Metadata" = "Bookmark Metadata";
Expand Down
3 changes: 3 additions & 0 deletions ownCloud/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {

// UIWindowScene delegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Set up HTTP pipelines
OCHTTPPipelineManager.setupPersistentPipelines()

if let windowScene = scene as? UIWindowScene {
window = ThemeWindow(windowScene: windowScene)
var navigationController: UINavigationController?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,18 @@ class StaticLoginSetupViewController : StaticLoginStepViewController {
var profile : StaticLoginProfile
var bookmark : OCBookmark?
var busySection : StaticTableViewSection?
var retrySection : StaticTableViewSection?

private var urlString : String?
private var username : String?
private var password : String?
private var passwordRow : StaticTableViewRow?
private var isAuthenticating = false
private var retryTimeout : Date?
private let retryInterval : TimeInterval = 30
private var retries : Int = 0
private let numberOfRetries : Int = 3
private let busySectionMessageLabel : UILabel = UILabel()

init(loginViewController theLoginViewController: StaticLoginViewController, profile theProfile: StaticLoginProfile) {
profile = theProfile
Expand Down Expand Up @@ -160,39 +166,53 @@ class StaticLoginSetupViewController : StaticLoginStepViewController {
tokenMaskSection.addStaticHeader(title: profile.welcome!, message: profile.promptForTokenAuth)

if VendorServices.shared.canAddAccount, OCBookmarkManager.shared.bookmarks.count > 0 {
let (proceedButton, cancelButton) = tokenMaskSection.addButtonFooter(proceedLabel: "Continue", cancelLabel: "Cancel")
let (proceedButton, cancelButton) = tokenMaskSection.addButtonFooter(proceedLabel: "Continue".localized, cancelLabel: "Cancel".localized)
proceedButton?.addTarget(self, action: #selector(self.startAuthentication), for: .touchUpInside)
cancelButton?.addTarget(self, action: #selector(self.cancel(_:)), for: .touchUpInside)
} else {
let (proceedButton, _) = tokenMaskSection.addButtonFooter(proceedLabel: "Continue", proceedItemStyle: .welcome, cancelLabel: nil)
let (proceedButton, _) = tokenMaskSection.addButtonFooter(proceedLabel: "Continue".localized, proceedItemStyle: .welcome, cancelLabel: nil)
proceedButton?.addTarget(self, action: #selector(self.startAuthentication), for: .touchUpInside)
}

return tokenMaskSection
}

func retrySection(issues: DisplayIssues) -> StaticTableViewSection {
let retrySection : StaticTableViewSection = StaticTableViewSection(headerTitle: nil, identifier: "retrySection")

for issue in issues.displayIssues {
if let title = issue.localizedTitle, let localizedDescription = issue.localizedDescription {
retrySection.add(row: StaticTableViewRow(message: localizedDescription, title: title))
}
}

let (proceedButton, _) = retrySection.addButtonFooter(proceedLabel: "Retry".localized, proceedItemStyle: .welcome, cancelLabel: nil)
proceedButton?.addTarget(self, action: #selector(proceedWithLogin), for: .touchUpInside)

return retrySection
}

func busySection(message: String) -> StaticTableViewSection {
let busySection : StaticTableViewSection = StaticTableViewSection(headerTitle: nil, identifier: "busySection")
let activityIndicator : UIActivityIndicatorView = UIActivityIndicatorView(style: Theme.shared.activeCollection.activityIndicatorViewStyle)
let containerView : FullWidthHeaderView = FullWidthHeaderView()
let centerView : UIView = UIView()
let messageLabel : UILabel = UILabel()

containerView.translatesAutoresizingMaskIntoConstraints = false
centerView.translatesAutoresizingMaskIntoConstraints = false
messageLabel.translatesAutoresizingMaskIntoConstraints = false
busySectionMessageLabel.translatesAutoresizingMaskIntoConstraints = false
activityIndicator.translatesAutoresizingMaskIntoConstraints = false

centerView.addSubview(activityIndicator)
centerView.addSubview(messageLabel)
centerView.addSubview(busySectionMessageLabel)

containerView.addSubview(centerView)

containerView.addThemeApplier({ (_, collection, _) in
messageLabel.applyThemeCollection(collection, itemStyle: .welcomeMessage)
self.busySectionMessageLabel.applyThemeCollection(collection, itemStyle: .welcomeMessage)
})

messageLabel.text = message
busySectionMessageLabel.text = message

NSLayoutConstraint.activate([
activityIndicator.widthAnchor.constraint(equalToConstant: 30),
Expand All @@ -201,9 +221,9 @@ class StaticLoginSetupViewController : StaticLoginStepViewController {
activityIndicator.topAnchor.constraint(equalTo: centerView.topAnchor),
activityIndicator.bottomAnchor.constraint(equalTo: centerView.bottomAnchor),

messageLabel.centerYAnchor.constraint(equalTo: centerView.centerYAnchor),
messageLabel.leftAnchor.constraint(equalTo: activityIndicator.rightAnchor, constant: 20),
messageLabel.rightAnchor.constraint(equalTo: centerView.rightAnchor),
busySectionMessageLabel.centerYAnchor.constraint(equalTo: centerView.centerYAnchor),
busySectionMessageLabel.leftAnchor.constraint(equalTo: activityIndicator.rightAnchor, constant: 20),
busySectionMessageLabel.rightAnchor.constraint(equalTo: centerView.rightAnchor),

centerView.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 40),
centerView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor),
Expand Down Expand Up @@ -288,7 +308,7 @@ class StaticLoginSetupViewController : StaticLoginStepViewController {
}
}

func proceedWithLogin() {
@objc func proceedWithLogin() {
guard self.bookmark != nil else {
let alertController = ThemedAlertController(title: "Missing Profile URL".localized, message: String(format: "The Profile '%@' does not have a URL configured.\nPlease provide a URL via configuration or MDM.".localized, profile.name ?? ""), preferredStyle: .alert)

Expand All @@ -306,6 +326,9 @@ class StaticLoginSetupViewController : StaticLoginStepViewController {
if let onboardingSection = self.sectionForIdentifier("onboardingSection") {
self.removeSection(onboardingSection)
}
if let retrySection = self.sectionForIdentifier("retrySection") {
self.removeSection(retrySection)
}

if busySection == nil {
busySection = self.busySection(message: "Contacting server…".localized)
Expand Down Expand Up @@ -448,27 +471,39 @@ class StaticLoginSetupViewController : StaticLoginStepViewController {
var proceed : Bool = true

if let issue = connectionIssue {
proceed = self.show(issue: issue, proceed: { () in
if self.retryTimeout == nil {
self.retryTimeout = Date().addingTimeInterval(self.retryInterval)
}
if let retryDate = self.retryTimeout, ((Date() < retryDate) || self.retries <= self.numberOfRetries), issue.issues?.first?.error?.isNetworkConnectionError == true {
self.retries += 1
proceed = false
OnMainThread {
if isInitialRequest {
self.determineSupportedAuthMethod(false)
}
Log.warning(String(format: "%@ (%ld)", "Contacting server…".localized, self.retries))
self.determineSupportedAuthMethod(false)
}
}, cancel: { () in
OnMainThread {
if self.profile.canConfigureURL {
if let busySection = self.busySection, busySection.attached {
self.removeSection(busySection)
} else {
proceed = self.show(issue: issue, proceed: { () in
OnMainThread {
if isInitialRequest {
self.determineSupportedAuthMethod(false)
}
self.addSection(self.urlSection())
if OCBookmarkManager.shared.bookmarks.count == 0, self.profile.isOnboardingEnabled, self.sectionForIdentifier("onboardingSection") == nil {
self.addSection(self.onboardingSection())
}
}, cancel: { () in
OnMainThread {
if self.profile.canConfigureURL {
if let busySection = self.busySection, busySection.attached {
self.removeSection(busySection)
}
self.addSection(self.urlSection())
if OCBookmarkManager.shared.bookmarks.count == 0, self.profile.isOnboardingEnabled, self.sectionForIdentifier("onboardingSection") == nil {
self.addSection(self.onboardingSection())
}
} else {
self.cancel(nil)
}
} else {
self.cancel(nil)
}
}
})
})
}
}

if proceed {
Expand Down Expand Up @@ -548,6 +583,10 @@ class StaticLoginSetupViewController : StaticLoginStepViewController {
if let busySection = self.busySection, busySection.attached {
self.removeSection(busySection)
}
self.retrySection = self.retrySection(issues: displayIssues)
if let retrySection = self.retrySection, issue.issues?.first?.error?.isNetworkConnectionError == true {
self.addSection(retrySection)
}

IssuesCardViewController.present(on: loginViewController, issue: issue, displayIssues: displayIssues, completion: { [weak issue] (response) in
switch response {
Expand Down

0 comments on commit 728cf67

Please sign in to comment.