From 6f7c4ddbe80984b8b1c13eee56c6a29f5879d160 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Tue, 15 Jan 2019 11:28:26 +0100 Subject: [PATCH] [fix/sdkupdates] SDK updates, improved maintenance mode support and bugfixes (#200) * - Minor memory optimizations - Updated to latest SDK * - Save changes prior to merge with master * - Convert to Swift 4.2 * - Further Swift 4.2 changes * - Update to latest SDK develop commit * - Adapting APP to latest SDK changes - maintenance mode support - replacing uses of reachability monitor with OCCore.connectionStatus * - Added back ownCloudUI.framework to copy phase of ownCloud target - Updated to latest SDK * - Add support for OCLogToggle in Settings - App now logs current log settings at launch * - Fix issues in ClientQueryViewController related to UITableView not reloading when its view controller is not "visible": - no longer uses items from table view cells to initiate actions - detects if UITableView.reloadData is set to do nothing and repeats the call in viewWillAppear - The fixed issue was causing https://github.com/owncloud/ios-app/issues/178 and possibly others * - Remove last traces of OCMocking.framework from ownCloud app target, make sure it's only built, linked to and copied in the ownCloudTests target * - Fix EarlGrey/CocoaPods workspace / build errors * - Adopt new OCLogger tags APIs in Log.swift and FileProviderExtension * - Update SDK * - Remove superfluous [FP] from log message * - Make sure DisplayViewController uses the updated version of an item after downloading it instead of the (now) outdated original version * - Update to latest SDK * - Fixing thumbnail aspect ratio and removing duplicate code in NamingViewController (https://github.com/owncloud/ios-app/issues/141) * - Update SDK * - Exit editing mode in the server list when the user selects an existing or adds a new bookmark (as reported by @mneuwert) * - Adapt app code base to change in OCError Swift conversion (following OCErrorAuthorizationCancelled typo correction) * - Fix https://github.com/owncloud/ios-app/issues/152: if the user cancels OAuth2, an error is no longer shown (and errors are better to read with recent SDK updates) * - Update to latest SDK * - Make ProgressSummarizer only consider Progress objects with descriptions, resolving "ghost" progress bars without any information in them * - Adapt to change of name of OCConnectionIssue to OCIssue * - Update to latest SDK - ConnectionIssueViewController - added option to provide a block to be called when dismissal has finished - normalize code formatting - UIAlertController+OCIssue - added option to provide a completionHandler that's called when the user made a choice - ClientRootViewController - switched issue and alert presentation to use a AsyncSequentialQueue to present them in order and not on top of each other - fixed a bug where a UIViewController that's in the process of being dismissed led to a failure to present alerts and issues * - Make DisplayViewController use OCCoreOptionReturnImmediatelyIfOfflineOrUnavailable and fix a typo (#179) * - Added priority summaries to ProgressSummarizer - Fixed a crash bug in ImageDisplayViewController - Removed core connection status interpretation from ClientQueryViewController - Added core connection status tracking to ClientRootViewController and utilize priority summaries to display offline or server in maintenance mode status messages * - Switching to fix/sdkUpdates branch * Version Bump to 91 * Delete unneeded workspace file ownCloud.xcworkspace/xcshareddata/ * Version Bump to 92 * Version Bump to 93 * - Update ios-sdk to latest ios-sdk master --- README.md | 1 + ios-sdk | 2 +- .../FileProviderExtension.m | 4 +- ownCloud.xcodeproj/project.pbxproj | 16 +- .../Bookmarks/BookmarkViewController.swift | 8 +- .../ConnectionIssueViewController.swift | 192 +++++++++--------- .../CreateFolderAction.swift | 4 +- .../Actions+Extensions/DuplicateAction.swift | 4 +- .../Client/Actions/NamingViewController.swift | 36 +--- .../Client/ClientQueryViewController.swift | 13 +- .../Client/ClientRootViewController.swift | 78 ++++++- ...xtension.swift => OCIssue+Extension.swift} | 12 +- .../ServerListTableViewController.swift | 7 + .../Progress/ProgressSummarizer.swift | 96 ++++++--- ....swift => UIAlertController+OCIssue.swift} | 7 +- ownCloud/Viewer/DisplayViewController.swift | 29 ++- .../Viewer/ImageDisplayViewController.swift | 20 +- ownCloudTests/Login/CreateBookmarkTests.swift | 32 +-- 18 files changed, 334 insertions(+), 227 deletions(-) rename ownCloud/SDK Extensions/{OCConnectionIssue+Extension.swift => OCIssue+Extension.swift} (76%) rename ownCloud/UIKit Extensions/{UIAlertController+OCConnectionIssue.swift => UIAlertController+OCIssue.swift} (91%) diff --git a/README.md b/README.md index 39ec1f49a..dd4230309 100644 --- a/README.md +++ b/README.md @@ -29,3 +29,4 @@ Easy starting points are also reviewing [pull requests](https://github.com/owncl * Also you can check other [channels](https://talk.owncloud.com/directory) for support. **License:** [GPLv3](https://github.com/owncloud/ios-app/LICENSE) + diff --git a/ios-sdk b/ios-sdk index efb1c47ef..4360354db 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit efb1c47efdbd2d53ed8d3424e6007c86b18d39ad +Subproject commit 4360354db33d3301a222f0fdebceb24cfc2b43fa diff --git a/ownCloud File Provider/FileProviderExtension.m b/ownCloud File Provider/FileProviderExtension.m index 7884e8eb2..a71dcca28 100644 --- a/ownCloud File Provider/FileProviderExtension.m +++ b/ownCloud File Provider/FileProviderExtension.m @@ -701,11 +701,11 @@ - (OCCore *)core return (_core); } -- (void)core:(OCCore *)core handleError:(NSError *)error issue:(OCConnectionIssue *)issue +- (void)core:(OCCore *)core handleError:(NSError *)error issue:(OCIssue *)issue { OCLogDebug(@"CORE ERROR: error=%@, issue=%@", error, issue); - if (issue.type == OCConnectionIssueTypeMultipleChoice) + if (issue.type == OCIssueTypeMultipleChoice) { [issue cancel]; } diff --git a/ownCloud.xcodeproj/project.pbxproj b/ownCloud.xcodeproj/project.pbxproj index 0fe20713c..4eabdfdb0 100644 --- a/ownCloud.xcodeproj/project.pbxproj +++ b/ownCloud.xcodeproj/project.pbxproj @@ -112,8 +112,8 @@ DC42244A207CAFAA0006A2A6 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC422449207CAFAA0006A2A6 /* Theme.swift */; }; DC42244C207CAFBB0006A2A6 /* ThemeCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC42244B207CAFBB0006A2A6 /* ThemeCollection.swift */; }; DC422450207CB2500006A2A6 /* NSObject+ThemeApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC42244F207CB2500006A2A6 /* NSObject+ThemeApplication.swift */; }; - DC434D1320D7A8F100740056 /* UIAlertController+OCConnectionIssue.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC434D1220D7A8F100740056 /* UIAlertController+OCConnectionIssue.swift */; }; - DC4FEAE7209E3A7700D4476B /* OCConnectionIssue+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4FEAE6209E3A7700D4476B /* OCConnectionIssue+Extension.swift */; }; + DC434D1320D7A8F100740056 /* UIAlertController+OCIssue.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC434D1220D7A8F100740056 /* UIAlertController+OCIssue.swift */; }; + DC4FEAE7209E3A7700D4476B /* OCIssue+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4FEAE6209E3A7700D4476B /* OCIssue+Extension.swift */; }; DC4FEAEA209E48E800D4476B /* DispatchQueueTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4FEAE9209E48E800D4476B /* DispatchQueueTools.swift */; }; DC6428D02081406800493A01 /* CollapsibleProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC6428CF2081406800493A01 /* CollapsibleProgressBar.swift */; }; DC680576212DF548006C3B1F /* CertificateManagementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC680575212DF548006C3B1F /* CertificateManagementViewController.swift */; }; @@ -489,8 +489,8 @@ DC422449207CAFAA0006A2A6 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; DC42244B207CAFBB0006A2A6 /* ThemeCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeCollection.swift; sourceTree = ""; }; DC42244F207CB2500006A2A6 /* NSObject+ThemeApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSObject+ThemeApplication.swift"; sourceTree = ""; }; - DC434D1220D7A8F100740056 /* UIAlertController+OCConnectionIssue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAlertController+OCConnectionIssue.swift"; sourceTree = ""; }; - DC4FEAE6209E3A7700D4476B /* OCConnectionIssue+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OCConnectionIssue+Extension.swift"; sourceTree = ""; }; + DC434D1220D7A8F100740056 /* UIAlertController+OCIssue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAlertController+OCIssue.swift"; sourceTree = ""; }; + DC4FEAE6209E3A7700D4476B /* OCIssue+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OCIssue+Extension.swift"; sourceTree = ""; }; DC4FEAE9209E48E800D4476B /* DispatchQueueTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchQueueTools.swift; sourceTree = ""; }; DC6428CF2081406800493A01 /* CollapsibleProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleProgressBar.swift; sourceTree = ""; }; DC680575212DF548006C3B1F /* CertificateManagementViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CertificateManagementViewController.swift; sourceTree = ""; }; @@ -749,7 +749,7 @@ DCE974BB207EACA60069FC2B /* UIImage+Extension.swift */, DC018F8220A0F56300135198 /* UIView+Animation.swift */, 6E83C78320A33C180066EC23 /* LAContext+Extension.swift */, - DC434D1220D7A8F100740056 /* UIAlertController+OCConnectionIssue.swift */, + DC434D1220D7A8F100740056 /* UIAlertController+OCIssue.swift */, DC248C66213E7DB00067FE94 /* NSLayoutConstraint+Extension.swift */, 6EADE9362192E235006821B3 /* UIImagePickerController+Extension.swift */, ); @@ -1094,7 +1094,7 @@ 23EC77572137F3DD0032D4E6 /* OCExtensionType+Extension.swift */, DCE5E8B72080D8D9005F60CE /* OCItem+Extension.swift */, DC136581208223F000FC0F60 /* OCBookmark+Extension.swift */, - DC4FEAE6209E3A7700D4476B /* OCConnectionIssue+Extension.swift */, + DC4FEAE6209E3A7700D4476B /* OCIssue+Extension.swift */, ); path = "SDK Extensions"; sourceTree = ""; @@ -1675,8 +1675,8 @@ DC321261207EB01B00DB171D /* ThemeImage.swift in Sources */, DC7DBA54207FA80C00E7337D /* TVGImage.swift in Sources */, 6E586CFE2199A75900F680C4 /* MoveAction.swift in Sources */, - DC4FEAE7209E3A7700D4476B /* OCConnectionIssue+Extension.swift in Sources */, - DC434D1320D7A8F100740056 /* UIAlertController+OCConnectionIssue.swift in Sources */, + DC4FEAE7209E3A7700D4476B /* OCIssue+Extension.swift in Sources */, + DC434D1320D7A8F100740056 /* UIAlertController+OCIssue.swift in Sources */, 6E586D002199A78E00F680C4 /* DeleteAction.swift in Sources */, DC3317CE2084966700E36C8F /* ThemeTableViewCell.swift in Sources */, 6E83C77E20A32C1B0066EC23 /* SettingsSection.swift in Sources */, diff --git a/ownCloud/Bookmarks/BookmarkViewController.swift b/ownCloud/Bookmarks/BookmarkViewController.swift index 58444d4d6..460b1c0c9 100644 --- a/ownCloud/Bookmarks/BookmarkViewController.swift +++ b/ownCloud/Bookmarks/BookmarkViewController.swift @@ -318,7 +318,7 @@ class BookmarkViewController: StaticTableViewController { if issue != nil { // Parse issue for display if let displayIssues = issue?.prepareForDisplay() { - if displayIssues.displayLevel.rawValue >= OCConnectionIssueLevel.warning.rawValue { + if displayIssues.displayLevel.rawValue >= OCIssueLevel.warning.rawValue { // Present issues if the level is >= warning let issuesViewController = ConnectionIssueViewController(displayIssues: displayIssues, completion: { [weak self] (response) in switch response { @@ -374,19 +374,21 @@ class BookmarkViewController: StaticTableViewController { self.bookmark?.authenticationData = authMethodData self.userActionSave() } else { - var issue : OCConnectionIssue? + var issue : OCIssue? let nsError = error as NSError? if let embeddedIssue = nsError?.embeddedIssue() { issue = embeddedIssue } else { - issue = OCConnectionIssue(forError: error, level: .error, issueHandler: nil) + issue = OCIssue(forError: error, level: .error, issueHandler: nil) } if nsError?.isOCError(withCode: .authorizationFailed) == true { // Shake self.navigationController?.view.shakeHorizontally() self.updateInputFocus(fallbackRow: self.passwordRow) + } else if nsError?.isOCError(withCode: .authorizationCancelled) == true { + // User cancelled authorization, no reaction needed } else { let issuesViewController = ConnectionIssueViewController(displayIssues: issue?.prepareForDisplay(), completion: { [weak self] (response) in switch response { diff --git a/ownCloud/Bookmarks/Issues/Issues Subclasses/ConnectionIssueViewController.swift b/ownCloud/Bookmarks/Issues/Issues Subclasses/ConnectionIssueViewController.swift index 4a8804962..a1e93a85f 100644 --- a/ownCloud/Bookmarks/Issues/Issues Subclasses/ConnectionIssueViewController.swift +++ b/ownCloud/Bookmarks/Issues/Issues Subclasses/ConnectionIssueViewController.swift @@ -7,50 +7,53 @@ // /* - * Copyright (C) 2018, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ +* Copyright (C) 2018, ownCloud GmbH. +* +* This code is covered by the GNU Public License Version 3. +* +* For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ +* You should have received a copy of this license along with this program. If not, see . +* +*/ import UIKit import ownCloudSDK import ownCloudUI enum ConnectionResponse { - case cancel - case approve - case dismiss + case cancel + case approve + case dismiss } class ConnectionIssueViewController: IssuesViewController { - private var displayIssues : DisplayIssues? + private var displayIssues : DisplayIssues? + private var dismissedHandler : (() -> Void)? - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + init(displayIssues issues: DisplayIssues?, buttons: [IssueButton]? = nil, title: String? = nil) { + super.init(buttons: buttons, title: title) - init(displayIssues issues: DisplayIssues?, buttons: [IssueButton]? = nil, title: String? = nil) { - super.init(buttons: buttons, title: title) + displayIssues = issues + } - displayIssues = issues - } + convenience init(displayIssues issues: DisplayIssues?, title: String? = nil, completion:@escaping (ConnectionResponse) -> Void, dismissedHandler dismissedHandlerBlock: (() -> Void)? = nil) { + var useButtons : [IssueButton]? + var useTitle = title - convenience init(displayIssues issues: DisplayIssues?, title: String? = nil, completion:@escaping (ConnectionResponse) -> Void) { - var useButtons : [IssueButton]? - var useTitle = title + self.init(displayIssues: issues, buttons: nil, title: useTitle) - self.init(displayIssues: issues, buttons: nil, title: useTitle) + self.dismissedHandler = dismissedHandlerBlock - if let displayLevel = issues?.displayLevel { - switch displayLevel { + if let displayLevel = issues?.displayLevel { + switch displayLevel { case .informal: if title == nil { - useTitle = "Review Connection".localized + useTitle = "Review Connection".localized } useButtons = [ @@ -61,7 +64,7 @@ class ConnectionIssueViewController: IssuesViewController { case .warning: if title == nil { - useTitle = "Review Connection".localized + useTitle = "Review Connection".localized } useButtons = [ @@ -76,7 +79,7 @@ class ConnectionIssueViewController: IssuesViewController { case .error: if title == nil { - useTitle = "Error".localized + useTitle = "Error".localized } useButtons = [ @@ -84,80 +87,87 @@ class ConnectionIssueViewController: IssuesViewController { completion(.dismiss) self?.dismiss(animated: true)}, accessibilityIdentifier: "ok-button") ] + } + + self.headerTitle = useTitle + self.buttons = useButtons } + } - self.headerTitle = useTitle - self.buttons = useButtons + override func viewDidLoad() { + super.viewDidLoad() + self.tableView?.dataSource = self } - } - override func viewDidLoad() { - super.viewDidLoad() - self.tableView?.dataSource = self - } + override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) { + super.dismiss(animated: flag) { + completion?() + self.dismissedHandler?() + } + } } extension ConnectionIssueViewController { - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if let issue = displayIssues?.displayIssues[indexPath.row], issue.type == OCConnectionIssueType.certificate { - OCCertificateDetailsViewNode.certificateDetailsViewNodes(for: issue.certificate, withValidationCompletionHandler: { (certificateNodes) in - let certDetails: NSAttributedString = OCCertificateDetailsViewNode .attributedString(withCertificateDetails: certificateNodes) - DispatchQueue.main.async { - let issuesVC = CertificateViewController(localizedDescription: certDetails) - issuesVC.modalPresentationStyle = .overCurrentContext - self.present(issuesVC, animated: true, completion: nil) - } - }) - } - } + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if let issue = displayIssues?.displayIssues[indexPath.row], issue.type == OCIssueType.certificate { + OCCertificateDetailsViewNode.certificateDetailsViewNodes(for: issue.certificate, withValidationCompletionHandler: { (certificateNodes) in + let certDetails: NSAttributedString = OCCertificateDetailsViewNode .attributedString(withCertificateDetails: certificateNodes) + DispatchQueue.main.async { + let issuesVC = CertificateViewController(localizedDescription: certDetails) + issuesVC.modalPresentationStyle = .overCurrentContext + self.present(issuesVC, animated: true, completion: nil) + } + }) + } + } } extension ConnectionIssueViewController: UITableViewDataSource { - func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return displayIssues?.displayIssues.count ?? 0 - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: IssuesViewControllerCellIdentifier, for: indexPath) - let issue = (displayIssues?.displayIssues[indexPath.row])! - cell.detailTextLabel?.text = issue.localizedDescription - cell.textLabel?.text = issue.localizedTitle - cell.textLabel?.numberOfLines = 0 - - var color: UIColor = .black - cell.selectionStyle = .none - - if issue.type == OCConnectionIssueType.certificate { - cell.accessoryType = .disclosureIndicator - cell.accessoryView?.backgroundColor = .blue - } else { - cell.accessoryType = .none + func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return displayIssues?.displayIssues.count ?? 0 } - switch issue.level { - case .warning: - color = Theme.shared.activeCollection.warningColor - case .informal: - color = Theme.shared.activeCollection.informativeColor - case .error: - color = Theme.shared.activeCollection.errorColor - } - - cell.textLabel?.attributedText = NSAttributedString(string: issue.localizedTitle, attributes: [ - .foregroundColor : color, - .font : UIFont.systemFont(ofSize: 18, weight: .semibold) - ]) - - cell.detailTextLabel?.attributedText = NSAttributedString(string: issue.localizedDescription, attributes: [ - .foregroundColor : UIColor(hex: 0x4F4F4F), - .font : UIFont.systemFont(ofSize: 15, weight: .regular) - ]) - cell.detailTextLabel?.numberOfLines = 0 - return cell - } + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: IssuesViewControllerCellIdentifier, for: indexPath) + let issue = (displayIssues?.displayIssues[indexPath.row])! + cell.detailTextLabel?.text = issue.localizedDescription + cell.textLabel?.text = issue.localizedTitle + cell.textLabel?.numberOfLines = 0 + + var color: UIColor = .black + cell.selectionStyle = .none + + if issue.type == OCIssueType.certificate { + cell.accessoryType = .disclosureIndicator + cell.accessoryView?.backgroundColor = .blue + } else { + cell.accessoryType = .none + } + + switch issue.level { + case .warning: + color = Theme.shared.activeCollection.warningColor + case .informal: + color = Theme.shared.activeCollection.informativeColor + case .error: + color = Theme.shared.activeCollection.errorColor + } + + cell.textLabel?.attributedText = NSAttributedString(string: issue.localizedTitle, attributes: [ + .foregroundColor : color, + .font : UIFont.systemFont(ofSize: 18, weight: .semibold) + ]) + + cell.detailTextLabel?.attributedText = NSAttributedString(string: issue.localizedDescription, attributes: [ + .foregroundColor : UIColor(hex: 0x4F4F4F), + .font : UIFont.systemFont(ofSize: 15, weight: .regular) + ]) + cell.detailTextLabel?.numberOfLines = 0 + return cell + } } diff --git a/ownCloud/Client/Actions/Actions+Extensions/CreateFolderAction.swift b/ownCloud/Client/Actions/Actions+Extensions/CreateFolderAction.swift index 5cfa0c5bb..e2420eb85 100644 --- a/ownCloud/Client/Actions/Actions+Extensions/CreateFolderAction.swift +++ b/ownCloud/Client/Actions/Actions+Extensions/CreateFolderAction.swift @@ -37,14 +37,14 @@ class CreateFolderAction : Action { // MARK: - Action implementation override func run() { guard context.items.count > 0 else { - completed(with: NSError(ocError: OCError.itemNotFound)) + completed(with: NSError(ocError: .itemNotFound)) return } let item = context.items.first guard item != nil else { - completed(with: NSError(ocError: OCError.itemNotFound)) + completed(with: NSError(ocError: .itemNotFound)) return } diff --git a/ownCloud/Client/Actions/Actions+Extensions/DuplicateAction.swift b/ownCloud/Client/Actions/Actions+Extensions/DuplicateAction.swift index 05b701b84..e69a3a423 100644 --- a/ownCloud/Client/Actions/Actions+Extensions/DuplicateAction.swift +++ b/ownCloud/Client/Actions/Actions+Extensions/DuplicateAction.swift @@ -35,7 +35,7 @@ class DuplicateAction : Action { // MARK: - Action implementation override func run() { guard context.items.count > 0, let core = self.core else { - completed(with: NSError(ocError: OCError.itemNotFound)) + completed(with: NSError(ocError: .itemNotFound)) return } @@ -43,7 +43,7 @@ class DuplicateAction : Action { let rootItem = item.parentItem(from: core) guard rootItem != nil else { - completed(with: NSError(ocError: OCError.itemNotFound)) + completed(with: NSError(ocError: .itemNotFound)) return } diff --git a/ownCloud/Client/Actions/NamingViewController.swift b/ownCloud/Client/Actions/NamingViewController.swift index aa5d98ed1..17bdab789 100644 --- a/ownCloud/Client/Actions/NamingViewController.swift +++ b/ownCloud/Client/Actions/NamingViewController.swift @@ -55,19 +55,21 @@ class NamingViewController: UIViewController { private let thumbnailSize = CGSize(width: 150.0, height: 150.0) - init(with item: OCItem, core: OCCore? = nil, stringValidator: StringValidatorHandler? = nil, completion: @escaping (String?, NamingViewController) -> Void) { + init(with item: OCItem? = nil, core: OCCore? = nil, defaultName: String? = nil, stringValidator: StringValidatorHandler? = nil, completion: @escaping (String?, NamingViewController) -> Void) { self.item = item self.core = core self.completion = completion self.stringValidator = stringValidator - self.defaultName = nil + self.defaultName = defaultName blurView = UIVisualEffectView.init(effect: UIBlurEffect(style: .regular)) stackView = UIStackView(frame: .zero) thumbnailContainer = UIView(frame: .zero) + thumbnailImageView = UIImageView(frame: .zero) + thumbnailImageView.contentMode = .scaleAspectFit nameContainer = UIView(frame: .zero) nameTextField = UITextField(frame: .zero) @@ -81,30 +83,12 @@ class NamingViewController: UIViewController { super.init(nibName: nil, bundle: nil) } - init(with core: OCCore? = nil, defaultName: String, stringValidator: StringValidatorHandler? = nil, completion: @escaping (String?, NamingViewController) -> Void) { - self.item = nil - self.core = core - self.completion = completion - self.stringValidator = stringValidator - self.defaultName = defaultName - - blurView = UIVisualEffectView.init(effect: UIBlurEffect(style: .regular)) - - stackView = UIStackView(frame: .zero) - - thumbnailContainer = UIView(frame: .zero) - thumbnailImageView = UIImageView(frame: .zero) - - nameContainer = UIView(frame: .zero) - nameTextField = UITextField(frame: .zero) - - textfieldCenterYAnchorConstraint = nameTextField.centerYAnchor.constraint(equalTo: nameContainer.centerYAnchor) - textfieldTopAnchorConstraint = nameTextField.topAnchor.constraint(equalTo: nameContainer.topAnchor, constant: 15) - thumbnailContainerWidthAnchorConstraint = thumbnailContainer.widthAnchor.constraint(equalToConstant: 200) - thumbnailContainerWidthAnchorConstraint.priority = .init(999) - thumbnailHeightAnchorConstraint = thumbnailImageView.heightAnchor.constraint(equalToConstant: 150) + convenience init(with item: OCItem, core: OCCore? = nil, stringValidator: StringValidatorHandler? = nil, completion: @escaping (String?, NamingViewController) -> Void) { + self.init(with: item, core: core, defaultName: nil, stringValidator: stringValidator, completion: completion) + } - super.init(nibName: nil, bundle: nil) + convenience init(with core: OCCore? = nil, defaultName: String, stringValidator: StringValidatorHandler? = nil, completion: @escaping (String?, NamingViewController) -> Void) { + self.init(with: nil, core: core, defaultName: defaultName, stringValidator: stringValidator, completion: completion) } required init?(coder aDecoder: NSCoder) { @@ -116,7 +100,7 @@ class NamingViewController: UIViewController { } override func viewDidLoad() { - super.viewDidLoad() + super.viewDidLoad() stackViewLeftAnchorConstraint = stackView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 0) stackViewRightAnchorConstraint = stackView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor, constant: 0) diff --git a/ownCloud/Client/ClientQueryViewController.swift b/ownCloud/Client/ClientQueryViewController.swift index 41c144e09..dd1835055 100644 --- a/ownCloud/Client/ClientQueryViewController.swift +++ b/ownCloud/Client/ClientQueryViewController.swift @@ -188,18 +188,7 @@ class ClientQueryViewController: UITableViewController, Themeable { summary.message = "Started…".localized case .contentsFromCache: - if let connectionStatus = core?.connectionStatus { - switch connectionStatus { - case .online: - summary.message = "Contents from cache.".localized - - case .offline: - summary.message = "Offline. Contents from cache.".localized - - case .unavailable: - summary.message = "Server down for maintenance. Contents from cache.".localized - } - } + summary.message = "Contents from cache.".localized case .waitingForServerReply: summary.message = "Waiting for server response…".localized diff --git a/ownCloud/Client/ClientRootViewController.swift b/ownCloud/Client/ClientRootViewController.swift index bf9c6bb5d..bc84bf2b5 100644 --- a/ownCloud/Client/ClientRootViewController.swift +++ b/ownCloud/Client/ClientRootViewController.swift @@ -26,6 +26,23 @@ class ClientRootViewController: UITabBarController { var progressBar : CollapsibleProgressBar? var progressSummarizer : ProgressSummarizer? + var connectionStatusObservation : NSKeyValueObservation? + var connectionStatusSummary : ProgressSummary? { + willSet { + if newValue != nil { + progressSummarizer?.pushPrioritySummary(summary: newValue!) + } + } + + didSet { + if oldValue != nil { + progressSummarizer?.popPrioritySummary(summary: oldValue!) + } + } + } + + var alertQueue : AsyncSequentialQueue = AsyncSequentialQueue() + init(bookmark inBookmark: OCBookmark) { let openProgress = Progress() @@ -37,21 +54,26 @@ class ClientRootViewController: UITabBarController { if progressSummarizer != nil { progressSummarizer?.addObserver(self) { [weak self] (summarizer, summary) in var useSummary : ProgressSummary = summary + let prioritySummary : ProgressSummary? = summarizer.prioritySummary if (summary.progress == 1) && (summarizer.fallbackSummary != nil) { useSummary = summarizer.fallbackSummary ?? summary } + if prioritySummary != nil { + useSummary = prioritySummary! + } + self?.progressBar?.update(with: useSummary.message, progress: Float(useSummary.progress)) - self?.progressBar?.autoCollapse = (summarizer.fallbackSummary == nil) || (useSummary.progressCount == 0) + self?.progressBar?.autoCollapse = ((summarizer.fallbackSummary == nil) || (useSummary.progressCount == 0)) && (prioritySummary == nil) } } openProgress.localizedDescription = "Connecting…".localized progressSummarizer?.startTracking(progress: openProgress) - core = OCCoreManager.shared.requestCore(for: bookmark, completionHandler: { (_, error) in + core = OCCoreManager.shared.requestCore(for: bookmark, completionHandler: { (core, error) in if error == nil { self.coreReady() } @@ -60,6 +82,23 @@ class ClientRootViewController: UITabBarController { openProgress.completedUnitCount = 1 openProgress.totalUnitCount = 1 + self.connectionStatusObservation = core?.observe(\OCCore.connectionStatus, options: [.initial], changeHandler: { [weak self] (observedCore, _) in + var summary : ProgressSummary? = ProgressSummary(indeterminate: true, progress: 1.0, message: nil, progressCount: 1) + + switch observedCore.connectionStatus { + case .online: + summary = nil + + case .offline: + summary?.message = "Offline. Contents from cache.".localized + + case .unavailable: + summary?.message = "Server down for maintenance. Contents from cache.".localized + } + + self?.connectionStatusSummary = summary + }) + self.progressSummarizer?.stopTracking(progress: openProgress) }) core?.delegate = self @@ -70,6 +109,11 @@ class ClientRootViewController: UITabBarController { } deinit { + connectionStatusObservation = nil + + if let statusSummary = connectionStatusSummary { + ProgressSummarizer.shared(forBookmark: bookmark).popPrioritySummary(summary: statusSummary) + } ProgressSummarizer.shared(forBookmark: bookmark).removeObserver(self) if core?.delegate === self { @@ -127,9 +171,10 @@ class ClientRootViewController: UITabBarController { } extension ClientRootViewController : OCCoreDelegate { - func core(_ core: OCCore!, handleError error: Error!, issue: OCConnectionIssue!) { - OnMainThread { - var presentIssue : OCConnectionIssue? = issue + func core(_ core: OCCore!, handleError error: Error!, issue: OCIssue!) { + alertQueue.async { (queueCompletionHandler) in + var presentIssue : OCIssue? = issue + var queueCompletionHandlerScheduled : Bool = false if error != nil { if let nsError : NSError = error as NSError? { @@ -138,12 +183,16 @@ extension ClientRootViewController : OCCoreDelegate { message: "The server declined access with the credentials stored for this connection.".localized, preferredStyle: .alert) - alertController.addAction(UIAlertAction(title: "Ignore".localized, style: .destructive, handler: nil)) + alertController.addAction(UIAlertAction(title: "Ignore".localized, style: .destructive, handler: { (_) in + queueCompletionHandler() + })) alertController.addAction(UIAlertAction(title: "Edit".localized, style: .default, handler: { (_) in let presentingViewController = self.presentingViewController let editBookmark = self.bookmark + queueCompletionHandler() + self.closeClient(completion: { if presentingViewController != nil, let serverListNavigationController = presentingViewController as? UINavigationController, @@ -154,6 +203,7 @@ extension ClientRootViewController : OCCoreDelegate { })) self.present(alertController, animated: true, completion: nil) + queueCompletionHandlerScheduled = true return } @@ -161,17 +211,17 @@ extension ClientRootViewController : OCCoreDelegate { } if issue == nil && error != nil { - presentIssue = OCConnectionIssue(forError: error, level: .error, issueHandler: nil) + presentIssue = OCIssue(forError: error, level: .error, issueHandler: nil) } if presentIssue != nil { var presentViewController : UIViewController? if presentIssue?.type == .multipleChoice { - presentViewController = UIAlertController(with: presentIssue!) + presentViewController = UIAlertController(with: presentIssue!, completion: queueCompletionHandler) } else { presentViewController = ConnectionIssueViewController(displayIssues: presentIssue?.prepareForDisplay(), completion: { (response) in - switch response { + switch response { case .cancel: presentIssue?.reject() @@ -180,19 +230,27 @@ extension ClientRootViewController : OCCoreDelegate { case .dismiss: break } + queueCompletionHandler() }) } if presentViewController != nil { var hostViewController : UIViewController = self - while hostViewController.presentedViewController != nil { + while hostViewController.presentedViewController != nil, + hostViewController.presentedViewController?.isBeingDismissed == false { hostViewController = hostViewController.presentedViewController! } + queueCompletionHandlerScheduled = true + hostViewController.present(presentViewController!, animated: true, completion: nil) } } + + if !queueCompletionHandlerScheduled { + queueCompletionHandler() + } } } } diff --git a/ownCloud/SDK Extensions/OCConnectionIssue+Extension.swift b/ownCloud/SDK Extensions/OCIssue+Extension.swift similarity index 76% rename from ownCloud/SDK Extensions/OCConnectionIssue+Extension.swift rename to ownCloud/SDK Extensions/OCIssue+Extension.swift index bb1ad52b2..ebf2553fe 100644 --- a/ownCloud/SDK Extensions/OCConnectionIssue+Extension.swift +++ b/ownCloud/SDK Extensions/OCIssue+Extension.swift @@ -1,5 +1,5 @@ // -// OCConnectionIssue+Extension.swift +// OCIssue+Extension.swift // ownCloud // // Created by Felix Schwarz on 05.05.18. @@ -20,15 +20,15 @@ import UIKit import ownCloudSDK struct DisplayIssues { - var targetIssue : OCConnectionIssue //!< The issue to send the approve or decline message to - var displayLevel : OCConnectionIssueLevel //!< The issue level to be used for display - var displayIssues: [OCConnectionIssue] //!< The selection of issues to be used for display + var targetIssue : OCIssue //!< The issue to send the approve or decline message to + var displayLevel : OCIssueLevel //!< The issue level to be used for display + var displayIssues: [OCIssue] //!< The selection of issues to be used for display var primaryCertificate : OCCertificate? //!< The first certificate found among the issues } -extension OCConnectionIssue { +extension OCIssue { func prepareForDisplay() -> DisplayIssues { - var displayIssues: [OCConnectionIssue] = [] + var displayIssues: [OCIssue] = [] var primaryCertificate: OCCertificate? = self.certificate switch self.type { diff --git a/ownCloud/Server List/ServerListTableViewController.swift b/ownCloud/Server List/ServerListTableViewController.swift index da9432efe..e752e52c8 100644 --- a/ownCloud/Server List/ServerListTableViewController.swift +++ b/ownCloud/Server List/ServerListTableViewController.swift @@ -205,6 +205,13 @@ class ServerListTableViewController: UITableViewController, Themeable { let viewController : BookmarkViewController = BookmarkViewController(bookmark) let navigationController : ThemeNavigationController = ThemeNavigationController(rootViewController: viewController) + // Exit editing mode (unfortunately, self.isEditing = false will not do the trick as it leaves the left bar button unchanged as "Done") + if self.tableView.isEditing, + let target = self.navigationItem.leftBarButtonItem?.target, + let action = self.navigationItem.leftBarButtonItem?.action { + _ = target.perform(action, with: self) + } + self.present(navigationController, animated: true, completion: nil) } diff --git a/ownCloud/UI Elements/Progress/ProgressSummarizer.swift b/ownCloud/UI Elements/Progress/ProgressSummarizer.swift index 41071abe4..29ef14211 100644 --- a/ownCloud/UI Elements/Progress/ProgressSummarizer.swift +++ b/ownCloud/UI Elements/Progress/ProgressSummarizer.swift @@ -216,6 +216,45 @@ class ProgressSummarizer: NSObject { } } + // MARK: - Priority summaries (to be used in favor of everything else whenever they exist) + internal var _prioritySummary : ProgressSummary? + public var prioritySummary : ProgressSummary? { + set(newPrioritySummary) { + if _prioritySummary != newPrioritySummary { + _prioritySummary = newPrioritySummary + self.setNeedsUpdate() + } + } + + get { + return _prioritySummary + } + } + + private var prioritySummaries : [ProgressSummary] = [] + + func pushPrioritySummary(summary : ProgressSummary) { + OCSynchronized(self) { + prioritySummaries.append(summary) + + self.prioritySummary = summary + } + } + + func popPrioritySummary(summary : ProgressSummary) { + OCSynchronized(self) { + if let index = prioritySummaries.index(of: summary) { + prioritySummaries.remove(at: index) + + if prioritySummaries.count == 0 { + self.prioritySummary = nil + } else if prioritySummaries.count == index { + self.prioritySummary = prioritySummaries.last + } + } + } + } + // MARK: - Change notifications private var observers : [ProgressSummaryNotificationObserver] = [] func addObserver(_ observer: AnyObject, notificationBlock: @escaping ProgressSummarizerNotificationBlock) { @@ -244,38 +283,47 @@ class ProgressSummarizer: NSObject { var completedProgress : [Progress]? OCSynchronized(self) { - for progress in trackedProgress { - if progress.isIndeterminate { - summary.indeterminate = true - } - - if progress.isFinished { - if completedProgress == nil { - completedProgress = [] - } - completedProgress?.append(progress) - } + var usedProgress : Int = 0 + for progress in trackedProgress { + // Only consider progress objects that have a description (those without have to be considered to be not active and/or unsuitable) if let message = progress.localizedDescription { - // Pick the first localized description that we encounter as message, because it's also the oldest, longest-running one. - if summary.message == nil { - summary.message = message + if message.count > 0 { + if progress.isIndeterminate { + summary.indeterminate = true + } + + if progress.isFinished { + if completedProgress == nil { + completedProgress = [] + } + completedProgress?.append(progress) + } + + // Pick the first localized description that we encounter as message, because it's also the oldest, longest-running one. + if summary.message == nil { + summary.message = message + } + + if !progress.isIndeterminate { + totalUnitCount += progress.totalUnitCount + completedUnitCount += progress.completedUnitCount + + if progress.totalUnitCount > 0 { + totalFraction += 1 + completedFraction += progress.fractionCompleted + } + } + + usedProgress += 1 } } - - totalUnitCount += progress.totalUnitCount - completedUnitCount += progress.completedUnitCount - - if progress.totalUnitCount > 0 { - totalFraction += 1 - completedFraction += progress.fractionCompleted - } } - summary.progressCount = trackedProgress.count + summary.progressCount = usedProgress if totalUnitCount == 0 { - if trackedProgress.count == 0 { + if usedProgress == 0 { summary.progress = 1 } else { summary.indeterminate = true diff --git a/ownCloud/UIKit Extensions/UIAlertController+OCConnectionIssue.swift b/ownCloud/UIKit Extensions/UIAlertController+OCIssue.swift similarity index 91% rename from ownCloud/UIKit Extensions/UIAlertController+OCConnectionIssue.swift rename to ownCloud/UIKit Extensions/UIAlertController+OCIssue.swift index dea6ca890..31fbfd0db 100644 --- a/ownCloud/UIKit Extensions/UIAlertController+OCConnectionIssue.swift +++ b/ownCloud/UIKit Extensions/UIAlertController+OCIssue.swift @@ -1,5 +1,5 @@ // -// UIAlertController+OCConnectionIssue.swift +// UIAlertController+OCIssue.swift // ownCloud // // Created by Felix Schwarz on 18.06.18. @@ -9,7 +9,7 @@ import UIKit import ownCloudSDK -extension OCConnectionIssueChoice { +extension OCIssueChoice { var alertActionStyle : UIAlertAction.Style { switch type { case .cancel: @@ -25,13 +25,14 @@ extension OCConnectionIssueChoice { } extension UIAlertController { - convenience init(with issue: OCConnectionIssue) { + convenience init(with issue: OCIssue, completion: (() -> Void)? = nil) { self.init(title: issue.localizedTitle, message: issue.localizedDescription, preferredStyle: .alert) for choice in issue.choices { self.addAction(UIAlertAction.init(title: choice.label, style: choice.alertActionStyle, handler: { (_) in issue.selectChoice(choice) + completion?() })) } } diff --git a/ownCloud/Viewer/DisplayViewController.swift b/ownCloud/Viewer/DisplayViewController.swift index 953b745ed..d3755bbf3 100644 --- a/ownCloud/Viewer/DisplayViewController.swift +++ b/ownCloud/Viewer/DisplayViewController.swift @@ -28,7 +28,7 @@ struct DisplayViewConfiguration { enum DisplayViewState { case hasNetworkConnection case noNetworkConnection - case downloading(progess: Progress) + case downloading(progress: Progress) case errorDownloading(error: Error?) case canceledDownload case notSupportedMimeType @@ -222,24 +222,23 @@ class DisplayViewController: UIViewController { } @objc func downloadItem(sender: Any?) { -// self.showPreviewButton?.isHidden = true - if core.connectionStatus == .online { - if let downloadProgress = self.core.downloadItem(item, options: nil, resultHandler: { [weak self] (error, _, latestItem, file) in - guard error == nil else { - OnMainThread { + if let downloadProgress = self.core.downloadItem(item, options: [ .returnImmediatelyIfOfflineOrUnavailable : true ], resultHandler: { [weak self] (error, _, latestItem, file) in + guard error == nil else { + OnMainThread { + if (error as NSError?)?.isOCError(withCode: .itemNotAvailableOffline) == true { + self?.state = .noNetworkConnection + } else { self?.state = .errorDownloading(error: error!) } - return - } - OnMainThread { - self?.item = latestItem - self?.source = file!.url } - }) { - self.state = .downloading(progess: downloadProgress) + return + } + OnMainThread { + self?.item = latestItem + self?.source = file!.url } - } else { - self.state = .noNetworkConnection + }) { + self.state = .downloading(progress: downloadProgress) } } diff --git a/ownCloud/Viewer/ImageDisplayViewController.swift b/ownCloud/Viewer/ImageDisplayViewController.swift index 84ba248a5..36b7a3a0c 100644 --- a/ownCloud/Viewer/ImageDisplayViewController.swift +++ b/ownCloud/Viewer/ImageDisplayViewController.swift @@ -6,6 +6,16 @@ // Copyright © 2018 ownCloud GmbH. All rights reserved. // +/* + * Copyright (C) 2018, ownCloud GmbH. + * + * This code is covered by the GNU Public License Version 3. + * + * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ + * You should have received a copy of this license along with this program. If not, see . + * + */ + import UIKit import ownCloudSDK @@ -33,10 +43,9 @@ class ImageDisplayViewController : DisplayViewController { scrollView!.topAnchor.constraint(equalTo: view.topAnchor) ]) - do { - let data = try Data(contentsOf: source) - let image = UIImage(data: data) - scrollView?.display(image: image!) + if let data = try? Data(contentsOf: source), + let image = UIImage(data: data) { + scrollView?.display(image: image) tapToZoomGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapToZoom)) tapToZoomGestureRecognizer.numberOfTapsRequired = 2 @@ -47,8 +56,7 @@ class ImageDisplayViewController : DisplayViewController { tapToZoomGestureRecognizer.delegate = self tapToHideBarsGestureRecognizer.delegate = self - - } catch { + } else { let alert = UIAlertController(with: "Error".localized, message: "Could not get the picture".localized, okLabel: "OK") self.parent?.present(alert, animated: true) { self.parent?.dismiss(animated: true) diff --git a/ownCloudTests/Login/CreateBookmarkTests.swift b/ownCloudTests/Login/CreateBookmarkTests.swift index d31577f37..4b0b392a6 100644 --- a/ownCloudTests/Login/CreateBookmarkTests.swift +++ b/ownCloudTests/Login/CreateBookmarkTests.swift @@ -16,7 +16,7 @@ import ownCloudMocking class CreateBookmarkTests: XCTestCase { public typealias OCMPrepareForSetupCompletionHandler = @convention(block) - (_ issue: OCConnectionIssue, _ suggestedURL: NSURL, _ supportedMethods: [OCAuthenticationMethodIdentifier], _ preferredAuthenticationMethods: [OCAuthenticationMethodIdentifier]) -> Void + (_ issue: OCIssue, _ suggestedURL: NSURL, _ supportedMethods: [OCAuthenticationMethodIdentifier], _ preferredAuthenticationMethods: [OCAuthenticationMethodIdentifier]) -> Void public typealias OCMPrepareForSetup = @convention(block) (_ options: NSDictionary, _ completionHandler: OCMPrepareForSetupCompletionHandler) -> Void @@ -77,7 +77,7 @@ class CreateBookmarkTests: XCTestCase { let mockUrlServer = "http://mocked.owncloud.server.com" let authMethods: [OCAuthenticationMethodIdentifier] = [OCAuthenticationMethodIdentifier.basicAuth, OCAuthenticationMethodIdentifier.oAuth2] - let issue: OCConnectionIssue = OCConnectionIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Informal issue description"]), level: .informal, issueHandler: nil) + let issue: OCIssue = OCIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Informal issue description"]), level: .informal, issueHandler: nil) //Mock mockOCConnectionPrepareForSetup(mockUrlServer: mockUrlServer, authMethods: authMethods, issue: issue) @@ -113,7 +113,7 @@ class CreateBookmarkTests: XCTestCase { let mockUrlServer = "http://mocked.owncloud.server.com" let authMethods: [OCAuthenticationMethodIdentifier] = [OCAuthenticationMethodIdentifier.basicAuth, OCAuthenticationMethodIdentifier.oAuth2] - let issue: OCConnectionIssue = OCConnectionIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Warning issue description"]), level: .warning, issueHandler: nil) + let issue: OCIssue = OCIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Warning issue description"]), level: .warning, issueHandler: nil) //Mock mockOCConnectionPrepareForSetup(mockUrlServer: mockUrlServer, authMethods: authMethods, issue: issue) @@ -140,7 +140,7 @@ class CreateBookmarkTests: XCTestCase { let mockUrlServer = "http://mocked.owncloud.server.com" let authMethods: [OCAuthenticationMethodIdentifier] = [OCAuthenticationMethodIdentifier.basicAuth, OCAuthenticationMethodIdentifier.oAuth2] - let issue: OCConnectionIssue = OCConnectionIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Warning issue description"]), level: .warning, issueHandler: nil) + let issue: OCIssue = OCIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Warning issue description"]), level: .warning, issueHandler: nil) //Mock mockOCConnectionPrepareForSetup(mockUrlServer: mockUrlServer, authMethods: authMethods, issue: issue) @@ -177,7 +177,7 @@ class CreateBookmarkTests: XCTestCase { let mockUrlServer = "http://mocked.owncloud.server.com" let authMethods: [OCAuthenticationMethodIdentifier] = [OCAuthenticationMethodIdentifier.basicAuth, OCAuthenticationMethodIdentifier.oAuth2] - let issue: OCConnectionIssue = OCConnectionIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Warning issue description"]), level: .warning, issueHandler: nil) + let issue: OCIssue = OCIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Warning issue description"]), level: .warning, issueHandler: nil) //Mock mockOCConnectionPrepareForSetup(mockUrlServer: mockUrlServer, authMethods: authMethods, issue: issue) @@ -206,7 +206,7 @@ class CreateBookmarkTests: XCTestCase { let mockUrlServer = "http://mocked.owncloud.server.com" let authMethods: [OCAuthenticationMethodIdentifier] = [OCAuthenticationMethodIdentifier.basicAuth, OCAuthenticationMethodIdentifier.oAuth2] - let issue: OCConnectionIssue = OCConnectionIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Error issue description"]), level: .error, issueHandler: nil) + let issue: OCIssue = OCIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Error issue description"]), level: .error, issueHandler: nil) //Mock mockOCConnectionPrepareForSetup(mockUrlServer: mockUrlServer, authMethods: authMethods, issue: issue) @@ -247,7 +247,7 @@ class CreateBookmarkTests: XCTestCase { OCAuthenticationMethodIdentifier.oAuth2] if let certificate: OCCertificate = UtilsTests.getCertificate(mockUrlServer: mockUrlServer) { - let issue: OCConnectionIssue = OCConnectionIssue.init(for: certificate, validationResult: OCCertificateValidationResult.userAccepted, url: URL(string: mockUrlServer), level: .warning, issueHandler: nil) + let issue: OCIssue = OCIssue.init(for: certificate, validationResult: OCCertificateValidationResult.userAccepted, url: URL(string: mockUrlServer), level: .warning, issueHandler: nil) //Mock mockOCConnectionPrepareForSetup(mockUrlServer: mockUrlServer, authMethods: authMethods, issue: issue) @@ -279,7 +279,7 @@ class CreateBookmarkTests: XCTestCase { OCAuthenticationMethodIdentifier.oAuth2] if let certificate: OCCertificate = UtilsTests.getCertificate(mockUrlServer: mockUrlServer) { - let issue: OCConnectionIssue = OCConnectionIssue.init(for: certificate, validationResult: OCCertificateValidationResult.userAccepted, url: URL(string: mockUrlServer), level: .warning, issueHandler: nil) + let issue: OCIssue = OCIssue.init(for: certificate, validationResult: OCCertificateValidationResult.userAccepted, url: URL(string: mockUrlServer), level: .warning, issueHandler: nil) //Mock mockOCConnectionPrepareForSetup(mockUrlServer: mockUrlServer, authMethods: authMethods, issue: issue) @@ -312,7 +312,7 @@ class CreateBookmarkTests: XCTestCase { OCAuthenticationMethodIdentifier.oAuth2] if let certificate: OCCertificate = UtilsTests.getCertificate(mockUrlServer: mockUrlServer) { - let issue: OCConnectionIssue = OCConnectionIssue.init(for: certificate, validationResult: OCCertificateValidationResult.userAccepted, url: URL(string: mockUrlServer), level: .warning, issueHandler: nil) + let issue: OCIssue = OCIssue.init(for: certificate, validationResult: OCCertificateValidationResult.userAccepted, url: URL(string: mockUrlServer), level: .warning, issueHandler: nil) //Mock mockOCConnectionPrepareForSetup(mockUrlServer: mockUrlServer, authMethods: authMethods, issue: issue) @@ -345,7 +345,7 @@ class CreateBookmarkTests: XCTestCase { OCAuthenticationMethodIdentifier.oAuth2] if let certificate: OCCertificate = UtilsTests.getCertificate(mockUrlServer: mockUrlServer) { - let issue: OCConnectionIssue = OCConnectionIssue.init(for: certificate, validationResult: OCCertificateValidationResult.userAccepted, url: URL(string: mockUrlServer), level: .warning, issueHandler: nil) + let issue: OCIssue = OCIssue.init(for: certificate, validationResult: OCCertificateValidationResult.userAccepted, url: URL(string: mockUrlServer), level: .warning, issueHandler: nil) //Mock mockOCConnectionPrepareForSetup(mockUrlServer: mockUrlServer, authMethods: authMethods, issue: issue) @@ -376,7 +376,7 @@ class CreateBookmarkTests: XCTestCase { let mockUrlServer = "http://mocked.owncloud.server.com" let authMethods: [OCAuthenticationMethodIdentifier] = [OCAuthenticationMethodIdentifier.oAuth2, OCAuthenticationMethodIdentifier.basicAuth] - let issue: OCConnectionIssue = OCConnectionIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Error description"]), level: .warning, issueHandler: nil) + let issue: OCIssue = OCIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Error description"]), level: .warning, issueHandler: nil) let authenticationMethodIdentifier = OCAuthenticationMethodIdentifier.oAuth2 as NSString let tokenResponse:[String : String] = ["access_token" : "RyFyDu1wH0Wvd8KlCP0Qeo9dlTqWajgvWHNqSdfl9bVD6Wp72CGikmgSkvUaAMML", @@ -425,7 +425,7 @@ class CreateBookmarkTests: XCTestCase { let mockUrlServer = "http://mocked.owncloud.server.com" let authMethods: [OCAuthenticationMethodIdentifier] = [OCAuthenticationMethodIdentifier.oAuth2, OCAuthenticationMethodIdentifier.basicAuth] - let issue: OCConnectionIssue = OCConnectionIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Error description"]), level: .informal, issueHandler: nil) + let issue: OCIssue = OCIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Error description"]), level: .informal, issueHandler: nil) let authenticationMethodIdentifier = OCAuthenticationMethodIdentifier.oAuth2 let tokenResponse:[String : String] = ["access_token" : "RyFyDu1wH0Wvd8KlCP0Qeo9dlTqWajgvWHNqSdfl9bVD6Wp72CGikmgSkvUaAMML", @@ -467,7 +467,7 @@ class CreateBookmarkTests: XCTestCase { let password = "test" let authMethods: [OCAuthenticationMethodIdentifier] = [OCAuthenticationMethodIdentifier.basicAuth, OCAuthenticationMethodIdentifier.oAuth2] - let issue: OCConnectionIssue = OCConnectionIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Error description"]), level: .warning, issueHandler: nil) + let issue: OCIssue = OCIssue(forError: NSError(domain: "mocked.owncloud.server.com", code: 1033, userInfo: [NSLocalizedDescriptionKey: "Error description"]), level: .warning, issueHandler: nil) let error: NSError? = nil let authenticationMethodIdentifier = OCAuthenticationMethodIdentifier.basicAuth @@ -509,7 +509,7 @@ class CreateBookmarkTests: XCTestCase { OCAuthenticationMethodIdentifier.oAuth2] let errorURL: NSError = NSError(domain: "mocked.owncloud.server.com", code: 1000, userInfo: [NSLocalizedDescriptionKey: "Error URL"]) - let issue: OCConnectionIssue = OCConnectionIssue(forError: errorURL, level: .informal, issueHandler: nil) + let issue: OCIssue = OCIssue(forError: errorURL, level: .informal, issueHandler: nil) let authenticationMethodIdentifier = OCAuthenticationMethodIdentifier.basicAuth let dictionary:Dictionary = ["BasicAuthString" : "Basic YWRtaW46YWRtaW4=", @@ -553,7 +553,7 @@ class CreateBookmarkTests: XCTestCase { OCAuthenticationMethodIdentifier.oAuth2] let errorURL: NSError = NSError(domain: "mocked.owncloud.server.com", code: 1000, userInfo: [NSLocalizedDescriptionKey: "Error URL"]) - let issue: OCConnectionIssue = OCConnectionIssue(forError: errorURL, level: .informal, issueHandler: nil) + let issue: OCIssue = OCIssue(forError: errorURL, level: .informal, issueHandler: nil) let authenticationMethodIdentifier = OCAuthenticationMethodIdentifier.basicAuth let dictionary:Dictionary = ["BasicAuthString" : "Basic YWRtaW46YWRtaW4=", @@ -586,7 +586,7 @@ class CreateBookmarkTests: XCTestCase { } // MARK: - Mocks - func mockOCConnectionPrepareForSetup(mockUrlServer: String, authMethods: [OCAuthenticationMethodIdentifier], issue: OCConnectionIssue) { + func mockOCConnectionPrepareForSetup(mockUrlServer: String, authMethods: [OCAuthenticationMethodIdentifier], issue: OCIssue) { let completionHandlerBlock : OCMPrepareForSetup = { (dict, mockedBlock) in let url: NSURL = NSURL(fileURLWithPath: mockUrlServer)