From 5e9cc430c64aced7add9465c87d7a8e7ddbd884d Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 12 Sep 2020 13:25:23 -0400 Subject: [PATCH] Use cross fade transitions for displaying gallery and asset picker if Reduce Motion/Prefer Cross Fade is enabled Closes #108 --- Tusker.xcodeproj/project.pbxproj | 4 +++ .../xcshareddata/swiftpm/Package.resolved | 2 +- Tusker/Extensions/UIAccessibility.swift | 21 +++++++++++++++ .../LargeImageExpandAnimationController.swift | 27 ++++++++++++++++++- .../LargeImageShrinkAnimationController.swift | 22 +++++++++++++++ 5 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 Tusker/Extensions/UIAccessibility.swift diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index 076dad3e..fd4f8e69 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -252,6 +252,7 @@ D6D3F4C424FDB6B700EC4A6A /* View+ConditionalModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D3F4C324FDB6B700EC4A6A /* View+ConditionalModifier.swift */; }; D6D3FDE024F41B8400FF50A5 /* ComposeContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D3FDDF24F41B8400FF50A5 /* ComposeContainerView.swift */; }; D6D3FDE224F46A8D00FF50A5 /* ComposeUIState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D3FDE124F46A8D00FF50A5 /* ComposeUIState.swift */; }; + D6D4CC91250D2C3100FCCF8D /* UIAccessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4CC90250D2C3100FCCF8D /* UIAccessibility.swift */; }; D6D4DDD0212518A000E1C4BB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDCF212518A000E1C4BB /* AppDelegate.swift */; }; D6D4DDD7212518A200E1C4BB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D6D4DDD6212518A200E1C4BB /* Assets.xcassets */; }; D6D4DDDA212518A200E1C4BB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6D4DDD8212518A200E1C4BB /* LaunchScreen.storyboard */; }; @@ -573,6 +574,7 @@ D6D3F4C324FDB6B700EC4A6A /* View+ConditionalModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+ConditionalModifier.swift"; sourceTree = ""; }; D6D3FDDF24F41B8400FF50A5 /* ComposeContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeContainerView.swift; sourceTree = ""; }; D6D3FDE124F46A8D00FF50A5 /* ComposeUIState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeUIState.swift; sourceTree = ""; }; + D6D4CC90250D2C3100FCCF8D /* UIAccessibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAccessibility.swift; sourceTree = ""; }; D6D4DDCC212518A000E1C4BB /* Tusker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tusker.app; sourceTree = BUILT_PRODUCTS_DIR; }; D6D4DDCF212518A000E1C4BB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; D6D4DDD6212518A200E1C4BB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -1104,6 +1106,7 @@ D67895BB24671E6D00D4CD9E /* PKDrawing+Render.swift */, D690797224A4EF9700023A34 /* UIBezierPath+Helpers.swift */, D6D3F4C324FDB6B700EC4A6A /* View+ConditionalModifier.swift */, + D6D4CC90250D2C3100FCCF8D /* UIAccessibility.swift */, ); path = Extensions; sourceTree = ""; @@ -1851,6 +1854,7 @@ D6B053AE23BD322B00A066FA /* AssetPickerSheetContainerViewController.swift in Sources */, D6C693EF216192C2007D6A6D /* TuskerNavigationDelegate.swift in Sources */, D6C94D872139E62700CB5196 /* LargeImageViewController.swift in Sources */, + D6D4CC91250D2C3100FCCF8D /* UIAccessibility.swift in Sources */, D627943E23A564D400D38C68 /* ExploreViewController.swift in Sources */, D6B053AB23BD2F1400A066FA /* AssetCollectionViewCell.swift in Sources */, D622757A24EE21D900B82A16 /* ComposeAttachmentRow.swift in Sources */, diff --git a/Tusker.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Tusker.xcworkspace/xcshareddata/swiftpm/Package.resolved index 110ab82c..d2904e53 100644 --- a/Tusker.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Tusker.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -15,7 +15,7 @@ "repositoryURL": "https://git.shadowfacts.net/shadowfacts/SheetController.git", "state": { "branch": "master", - "revision": "7ac34efeabb5b5eb08fcf3d1235dbc9ca0441662", + "revision": "ab77ad89b449b8c415441a6ac97e0922d6900dcc", "version": null } }, diff --git a/Tusker/Extensions/UIAccessibility.swift b/Tusker/Extensions/UIAccessibility.swift new file mode 100644 index 00000000..a612f505 --- /dev/null +++ b/Tusker/Extensions/UIAccessibility.swift @@ -0,0 +1,21 @@ +// +// UIAccessibility.swift +// Tusker +// +// Created by Shadowfacts on 9/12/20. +// Copyright © 2020 Shadowfacts. All rights reserved. +// + +import UIKit + +extension UIAccessibility { + + static var prefersCrossFadeTransitionsBackwardsCompat: Bool { + if #available(iOS 14.0, *) { + return prefersCrossFadeTransitions + } else { + return isReduceMotionEnabled + } + } + +} diff --git a/Tusker/Screens/Large Image/Transitions/LargeImageExpandAnimationController.swift b/Tusker/Screens/Large Image/Transitions/LargeImageExpandAnimationController.swift index 9738e93a..6d35fe2b 100644 --- a/Tusker/Screens/Large Image/Transitions/LargeImageExpandAnimationController.swift +++ b/Tusker/Screens/Large Image/Transitions/LargeImageExpandAnimationController.swift @@ -38,7 +38,11 @@ extension LargeImageAnimatableViewController { class LargeImageExpandAnimationController: NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { - return 0.4 + if UIAccessibility.prefersCrossFadeTransitionsBackwardsCompat { + return 0.2 + } else { + return 0.4 + } } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { @@ -47,6 +51,11 @@ class LargeImageExpandAnimationController: NSObject, UIViewControllerAnimatedTra return } + if UIAccessibility.prefersCrossFadeTransitionsBackwardsCompat { + animateCrossFadeTransition(using: transitionContext) + return + } + let containerView = transitionContext.containerView containerView.addSubview(toVC.view) @@ -112,4 +121,20 @@ class LargeImageExpandAnimationController: NSObject, UIViewControllerAnimatedTra } } + func animateCrossFadeTransition(using transitionContext: UIViewControllerContextTransitioning) { + guard let toVC = transitionContext.viewController(forKey: .to) as? LargeImageAnimatableViewController else { + return + } + + transitionContext.containerView.addSubview(toVC.view) + toVC.view.alpha = 0 + + let duration = transitionDuration(using: transitionContext) + UIView.animate(withDuration: duration) { + toVC.view.alpha = 1 + } completion: { (_) in + transitionContext.completeTransition(!transitionContext.transitionWasCancelled) + } + } + } diff --git a/Tusker/Screens/Large Image/Transitions/LargeImageShrinkAnimationController.swift b/Tusker/Screens/Large Image/Transitions/LargeImageShrinkAnimationController.swift index d6da2c3e..456c665c 100644 --- a/Tusker/Screens/Large Image/Transitions/LargeImageShrinkAnimationController.swift +++ b/Tusker/Screens/Large Image/Transitions/LargeImageShrinkAnimationController.swift @@ -27,6 +27,11 @@ class LargeImageShrinkAnimationController: NSObject, UIViewControllerAnimatedTra return } + if UIAccessibility.prefersCrossFadeTransitionsBackwardsCompat && !transitionContext.isInteractive { + animateCrossFadeTransition(using: transitionContext) + return + } + guard let sourceView = fromVC.animationSourceView, let sourceFrame = fromVC.sourceViewFrame(in: toVC.view), let image = fromVC.animationImage else { @@ -86,4 +91,21 @@ class LargeImageShrinkAnimationController: NSObject, UIViewControllerAnimatedTra }) } + func animateCrossFadeTransition(using transitionContext: UIViewControllerContextTransitioning) { + guard let fromVC = transitionContext.viewController(forKey: .from) as? LargeImageAnimatableViewController, + let toVC = transitionContext.viewController(forKey: .to) else { + return + } + + transitionContext.containerView.addSubview(toVC.view) + transitionContext.containerView.addSubview(fromVC.view) + + let duration = transitionDuration(using: transitionContext) + UIView.animate(withDuration: duration) { + fromVC.view.alpha = 0 + } completion: { (_) in + transitionContext.completeTransition(!transitionContext.transitionWasCancelled) + } + } + }