diff --git a/design/cloud-symbols-thick.idraw b/design/cloud-symbols-thick.idraw index 31bf26ac9..d2419194b 100644 Binary files a/design/cloud-symbols-thick.idraw and b/design/cloud-symbols-thick.idraw differ diff --git a/ios-sdk b/ios-sdk index 36e4ea564..ed2969d14 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 36e4ea5640cf9cc7914cccc4eca6088e84884ffd +Subproject commit ed2969d14ba1cbb5b5b6216a800894b36aa6c25f diff --git a/ownCloud/UI Elements/Progress/ProgressSummarizer.swift b/ownCloud/UI Elements/Progress/ProgressSummarizer.swift index 4183fa635..a2e64fc7c 100644 --- a/ownCloud/UI Elements/Progress/ProgressSummarizer.swift +++ b/ownCloud/UI Elements/Progress/ProgressSummarizer.swift @@ -48,7 +48,9 @@ class ProgressSummarizer: NSObject { deinit { OCSynchronized(self) { - for progress in trackedProgress { + let existingTrackedProgress = trackedProgress + + for progress in existingTrackedProgress { self.stopTracking(progress: progress, remove: false) } } diff --git a/ownCloud/UI Elements/ProgressView.swift b/ownCloud/UI Elements/ProgressView.swift index 396f44161..3bad7e561 100644 --- a/ownCloud/UI Elements/ProgressView.swift +++ b/ownCloud/UI Elements/ProgressView.swift @@ -26,42 +26,63 @@ class ProgressView: UIView, Themeable { private let dimensions : CGSize = CGSize(width: 30, height: 30) private let circleLineWidth : CGFloat = 3 -// private var progressObservationFractionCompleted : NSKeyValueObservation? -// private var progressObservationIsIndeterminate : NSKeyValueObservation? -// private var progressObservationCancelled : NSKeyValueObservation? -// private var progressObservationFinished : NSKeyValueObservation? - + private var _observerRegistered : Bool = false + private var _progress : Progress? var progress : Progress? { - willSet { - if newValue !== progress, progress != nil { - progress?.removeObserver(self, forKeyPath: "fractionCompleted") - progress?.removeObserver(self, forKeyPath: "indeterminate") - progress?.removeObserver(self, forKeyPath: "cancelled") - progress?.removeObserver(self, forKeyPath: "finished") + set { + OCSynchronized(self) { + if _observerRegistered, let progress = _progress { + progress.removeObserver(self, forKeyPath: "fractionCompleted") + progress.removeObserver(self, forKeyPath: "indeterminate") + progress.removeObserver(self, forKeyPath: "cancelled") + progress.removeObserver(self, forKeyPath: "finished") + + _observerRegistered = false + } + + _progress = newValue + + if !_observerRegistered, let progress = newValue { + progress.addObserver(self, forKeyPath: "fractionCompleted", options: [], context: nil) + progress.addObserver(self, forKeyPath: "indeterminate", options: [], context: nil) + progress.addObserver(self, forKeyPath: "cancelled", options: [], context: nil) + progress.addObserver(self, forKeyPath: "finished", options: [], context: nil) + + _observerRegistered = true + } + + if Thread.isMainThread { + CATransaction.begin() + CATransaction.setDisableActions(true) + CATransaction.setAnimationDuration(0) + } else { + Log.log("Progress not set on main thread") + } + + self.update() + + if Thread.isMainThread { + CATransaction.commit() + } } } - didSet { - CATransaction.begin() - CATransaction.setDisableActions(true) - CATransaction.setAnimationDuration(0) + get { + var progress : Progress? - if let newProgress = progress { - newProgress.addObserver(self, forKeyPath: "fractionCompleted", options: [], context: nil) - newProgress.addObserver(self, forKeyPath: "indeterminate", options: [], context: nil) - newProgress.addObserver(self, forKeyPath: "cancelled", options: [], context: nil) - newProgress.addObserver(self, forKeyPath: "finished", options: [], context: nil) + OCSynchronized(self) { + progress = _progress } - self.update() - - CATransaction.commit() + return progress } } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if (object as? Progress) === progress { - self.update() + OnMainThread { + self.update() + } } else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) } @@ -139,7 +160,7 @@ class ProgressView: UIView, Themeable { return } - if let progress = progress { + if let progress = self.progress { self.spinning = progress.isIndeterminate || progress.isCancelled diff --git a/ownCloudTests/Security/PasscodeTests.swift b/ownCloudTests/Security/PasscodeTests.swift index 800f6d47c..bcd427b5b 100644 --- a/ownCloudTests/Security/PasscodeTests.swift +++ b/ownCloudTests/Security/PasscodeTests.swift @@ -39,6 +39,7 @@ class PasscodeTests: XCTestCase { // Show the passcode AppLockManager.shared.showLockscreenIfNeeded() + EarlGrey.waitForElement(accessibilityID: "number1Button") // Tap the number buttons EarlGrey.select(elementWithMatcher: grey_accessibilityID("number1Button")).perform(grey_tap()) @@ -46,6 +47,8 @@ class PasscodeTests: XCTestCase { EarlGrey.select(elementWithMatcher: grey_accessibilityID("number1Button")).perform(grey_tap()) EarlGrey.select(elementWithMatcher: grey_accessibilityID("number1Button")).perform(grey_tap()) + EarlGrey.waitForElement(accessibilityID: "addServer") + // Asserts EarlGrey.select(elementWithMatcher: grey_accessibilityID("addServer")).assert(grey_sufficientlyVisible()) } @@ -61,6 +64,7 @@ class PasscodeTests: XCTestCase { // Show the passcode AppLockManager.shared.showLockscreenIfNeeded() + EarlGrey.waitForElement(accessibilityID: "number1Button") // Tap the number buttons EarlGrey.select(elementWithMatcher: grey_accessibilityID("number1Button")).perform(grey_tap()) @@ -87,10 +91,12 @@ class PasscodeTests: XCTestCase { EarlGrey.select(elementWithMatcher: grey_accessibilityID("number1Button")).perform(grey_tap()) EarlGrey.select(elementWithMatcher: grey_text("Cancel".localized)).perform(grey_tap()) + EarlGrey.waitForElementMissing(accessibilityID: "number1Button") + // Asserts EarlGrey.select(elementWithMatcher: grey_accessibilityID("passcodeSwitchIdentifier")).assert(grey_switchWithOnState(false)) - //Reset status + // Reset status EarlGrey.select(elementWithMatcher: grey_text("ownCloud")).perform(grey_tap()) } @@ -115,6 +121,8 @@ class PasscodeTests: XCTestCase { EarlGrey.select(elementWithMatcher: grey_accessibilityID("number1Button")).perform(grey_tap()) EarlGrey.select(elementWithMatcher: grey_text("Cancel".localized)).perform(grey_tap()) + EarlGrey.waitForElementMissing(accessibilityID: "number1Button") + // Asserts EarlGrey.select(elementWithMatcher: grey_accessibilityID("passcodeSwitchIdentifier")).assert(grey_switchWithOnState(false)) @@ -171,6 +179,8 @@ class PasscodeTests: XCTestCase { EarlGrey.select(elementWithMatcher: grey_accessibilityID("number1Button")).perform(grey_tap()) EarlGrey.select(elementWithMatcher: grey_accessibilityID("number1Button")).perform(grey_tap()) + EarlGrey.waitForElementMissing(accessibilityID: "number1Button") + // Asserts EarlGrey.select(elementWithMatcher: grey_accessibilityID("passcodeSwitchIdentifier")).assert(grey_switchWithOnState(false)) EarlGrey.select(elementWithMatcher: grey_accessibilityID("lockFrequency")).assert(grey_notVisible()) @@ -196,6 +206,8 @@ class PasscodeTests: XCTestCase { EarlGrey.select(elementWithMatcher: grey_accessibilityID("number1Button")).perform(grey_tap()) EarlGrey.select(elementWithMatcher: grey_text("Cancel".localized)).perform(grey_tap()) + EarlGrey.waitForElementMissing(accessibilityID: "number1Button") + // Asserts EarlGrey.select(elementWithMatcher: grey_accessibilityID("passcodeSwitchIdentifier")).assert(grey_switchWithOnState(true)) EarlGrey.select(elementWithMatcher: grey_accessibilityID("lockFrequency")).assert(grey_sufficientlyVisible())