From c8f3ba11fb757ae4709889a72cd738c11ff9fbe6 Mon Sep 17 00:00:00 2001 From: ChronicLynx <29527680+ChronicLynx@users.noreply.github.com> Date: Fri, 7 Mar 2025 14:28:24 -0700 Subject: [PATCH 1/5] Fix UI getting stuck when transition animation is interrupted --- SignalUI/ImageEditor/ImageEditorCropViewController.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/SignalUI/ImageEditor/ImageEditorCropViewController.swift b/SignalUI/ImageEditor/ImageEditorCropViewController.swift index 12d7c364780..c5afcb0b19b 100644 --- a/SignalUI/ImageEditor/ImageEditorCropViewController.swift +++ b/SignalUI/ImageEditor/ImageEditorCropViewController.swift @@ -948,8 +948,7 @@ extension ImageEditorCropViewController { @objc private func didTapCancel() { - transitionUI(toState: .initial, animated: true) { finished in - guard finished else { return } + transitionUI(toState: .initial, animated: true) { _ in self.dismiss(animated: false) } } @@ -957,8 +956,7 @@ extension ImageEditorCropViewController { @objc private func didTapDone() { model.replace(transform: transform) - transitionUI(toState: .initial, animated: true) { finished in - guard finished else { return } + transitionUI(toState: .initial, animated: true) { _ in self.dismiss(animated: false) } } From c04459a2ddc3ae8415cc158845c66601ea41dc3a Mon Sep 17 00:00:00 2001 From: ChronicLynx <29527680+ChronicLynx@users.noreply.github.com> Date: Fri, 7 Mar 2025 15:15:36 -0700 Subject: [PATCH 2/5] Move contrainContent and updateImageViewTransform outside the animation block --- SignalUI/ImageEditor/ImageEditorCropViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SignalUI/ImageEditor/ImageEditorCropViewController.swift b/SignalUI/ImageEditor/ImageEditorCropViewController.swift index c5afcb0b19b..3d5c2abb15e 100644 --- a/SignalUI/ImageEditor/ImageEditorCropViewController.swift +++ b/SignalUI/ImageEditor/ImageEditorCropViewController.swift @@ -425,11 +425,11 @@ class ImageEditorCropViewController: OWSViewController { imageView.layer.cornerRadius = imageCornerRadius if animated { + constrainContent(to: layoutGuide) + updateImageViewTransform() UIView.animate(withDuration: animationDuration, animations: { setControlsHiddenBlock() - self.constrainContent(to: layoutGuide) - self.updateImageViewTransform() // Animate layout changes made within bottomBar.setControls(hidden:). self.view.setNeedsDisplay() self.view.layoutIfNeeded() From 98f19128a48811ac50a0acb3fc35da268458bb4c Mon Sep 17 00:00:00 2001 From: ChronicLynx <29527680+ChronicLynx@users.noreply.github.com> Date: Fri, 7 Mar 2025 17:12:21 -0700 Subject: [PATCH 3/5] Restore navigation controls if animation is interrupted --- .../ImageEditorCropViewController.swift | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/SignalUI/ImageEditor/ImageEditorCropViewController.swift b/SignalUI/ImageEditor/ImageEditorCropViewController.swift index 3d5c2abb15e..9a59b3d23cc 100644 --- a/SignalUI/ImageEditor/ImageEditorCropViewController.swift +++ b/SignalUI/ImageEditor/ImageEditorCropViewController.swift @@ -395,6 +395,12 @@ class ImageEditorCropViewController: OWSViewController { case initial case final } + + private func updateControlsVisibility(hidden: Bool) { + self.footerView.alpha = hidden ? 0 : 1 + self.cropView.setState(hidden ? .initial : .normal, animated: false) + self.bottomBar.setControls(hidden: hidden) + } private func transitionUI(toState state: UIState, animated: Bool, completion: ((Bool) -> Void)? = nil) { let layoutGuide: UILayoutGuide = { @@ -405,12 +411,6 @@ class ImageEditorCropViewController: OWSViewController { }() let hideControls = state == .initial - let setControlsHiddenBlock = { - let alpha: CGFloat = hideControls ? 0 : 1 - self.footerView.alpha = alpha - self.cropView.setState(state == .initial ? .initial : .normal, animated: false) - self.bottomBar.setControls(hidden: hideControls) - } let animationDuration: TimeInterval = 0.15 @@ -425,18 +425,19 @@ class ImageEditorCropViewController: OWSViewController { imageView.layer.cornerRadius = imageCornerRadius if animated { - constrainContent(to: layoutGuide) - updateImageViewTransform() + UIView.animate(withDuration: animationDuration, animations: { - setControlsHiddenBlock() + self.updateControlsVisibility(hidden: hideControls) + self.constrainContent(to: layoutGuide) + self.updateImageViewTransform() // Animate layout changes made within bottomBar.setControls(hidden:). self.view.setNeedsDisplay() self.view.layoutIfNeeded() }, completion: completion) } else { - setControlsHiddenBlock() + updateControlsVisibility(hidden: hideControls) constrainContent(to: layoutGuide) updateImageViewTransform() completion?(true) @@ -948,7 +949,13 @@ extension ImageEditorCropViewController { @objc private func didTapCancel() { - transitionUI(toState: .initial, animated: true) { _ in + transitionUI(toState: .initial, animated: true) { finished in + + // Fallback to reveal controls in case of an animation interruption + guard finished else { + self.updateControlsVisibility(hidden: false) + return + } self.dismiss(animated: false) } } @@ -956,7 +963,13 @@ extension ImageEditorCropViewController { @objc private func didTapDone() { model.replace(transform: transform) - transitionUI(toState: .initial, animated: true) { _ in + transitionUI(toState: .initial, animated: true) { finished in + + // Fallback to reveal controls in case of an animation interruption + guard finished else { + self.updateControlsVisibility(hidden: false) + return + } self.dismiss(animated: false) } } From 673b8eec6b4acf0ac644efbf94f77b44753fb73c Mon Sep 17 00:00:00 2001 From: ChronicLynx <29527680+ChronicLynx@users.noreply.github.com> Date: Fri, 7 Mar 2025 17:53:39 -0700 Subject: [PATCH 4/5] Reset crop to default state in the event of animation interruption --- SignalUI/ImageEditor/ImageEditorCropViewController.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SignalUI/ImageEditor/ImageEditorCropViewController.swift b/SignalUI/ImageEditor/ImageEditorCropViewController.swift index 9a59b3d23cc..75e195649a5 100644 --- a/SignalUI/ImageEditor/ImageEditorCropViewController.swift +++ b/SignalUI/ImageEditor/ImageEditorCropViewController.swift @@ -954,6 +954,7 @@ extension ImageEditorCropViewController { // Fallback to reveal controls in case of an animation interruption guard finished else { self.updateControlsVisibility(hidden: false) + self.didTapReset() return } self.dismiss(animated: false) @@ -968,6 +969,7 @@ extension ImageEditorCropViewController { // Fallback to reveal controls in case of an animation interruption guard finished else { self.updateControlsVisibility(hidden: false) + self.didTapReset() return } self.dismiss(animated: false) From 1130ba58e38442157eb1b8baa723a7c02a4892b7 Mon Sep 17 00:00:00 2001 From: ChronicLynx <29527680+ChronicLynx@users.noreply.github.com> Date: Fri, 7 Mar 2025 18:30:58 -0700 Subject: [PATCH 5/5] Ensure image cornerRadius is reset in the case of animation interruption --- SignalUI/ImageEditor/ImageEditorCropViewController.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SignalUI/ImageEditor/ImageEditorCropViewController.swift b/SignalUI/ImageEditor/ImageEditorCropViewController.swift index 75e195649a5..66382072a2c 100644 --- a/SignalUI/ImageEditor/ImageEditorCropViewController.swift +++ b/SignalUI/ImageEditor/ImageEditorCropViewController.swift @@ -954,6 +954,7 @@ extension ImageEditorCropViewController { // Fallback to reveal controls in case of an animation interruption guard finished else { self.updateControlsVisibility(hidden: false) + self.imageView.layer.cornerRadius = 0 self.didTapReset() return } @@ -969,6 +970,7 @@ extension ImageEditorCropViewController { // Fallback to reveal controls in case of an animation interruption guard finished else { self.updateControlsVisibility(hidden: false) + self.imageView.layer.cornerRadius = 0 self.didTapReset() return }