Skip to content

Fix views staying hidden when shown during their hide animation - #6349

Open
jan-grzybek wants to merge 1 commit into
signalapp:mainfrom
jan-grzybek:fix-media-caption-toolbar-button-visibility
Open

jan-grzybek wants to merge 1 commit into
signalapp:mainfrom
jan-grzybek:fix-media-caption-toolbar-button-visibility

Conversation

@jan-grzybek

@jan-grzybek jan-grzybek commented Sep 17, 2026 •

Copy link
Copy Markdown

Contributor checklist

Administrative:

Commits and testing:

  • My commits are rebased on the latest main branch.
  • My commits are well-structured for review.
  • My change has been thoroughly tested, and I am not aware of any regressions to existing features or behaviors.
  • I have tested my contribution on these devices:
  • iPhone 18 Pro Simulator, iOS 27.0
  • iPhone 17 Pro Simulator, iOS 26.5

Description

UIView.setIsHidden(_:using:) and setIsHidden(_:withAnimationDuration:completion:) (used by setIsHidden(_:animated:completion:)) only set isHidden once a hide animation completes. A show requested before then is compared against the stale isHidden and ignored, and the hide's completion then hides the view anyway.

Steps to reproduce on main (media review screen with a single photo):

  1. Quickly tap the "view once" button twice.
  2. View once is off again, but the caption field is empty and doesn't respond to taps, so no caption can be entered. The Add Media button is also missing.

The same can happen to any view using these helpers when a show and a hide are requested in quick succession.

This change tracks the most recent animated change per view (as an associated object), shared by both variants:

  • A new change supersedes any pending one, including a change whose animator hasn't started yet or doesn't finish at its end (for example, one that is stopped or reversed).
  • Only the most recent change's animation and completion modify the view.
  • Changes without animation apply immediately.
  • A show un-hides the view even if its alpha is 0. Previously it only faded alpha in and left the view hidden.

Behavior for changes that don't overlap is unchanged, including calling completion synchronously when no animation is needed. It builds on the simplification in 1a77385. Both methods now have doc comments describing this behavior.

Testing:

  • Added UIKitAnimationsTest to SignalUITests: 14 tests covering both variants with real animators, waiting on completions rather than fixed delays. 8 of them fail on main: a show during a hide (animated and not, for both variants), a show before the hide's animator has started, a show during a hide while the same animator also changes the view's alpha, showing a hidden view whose alpha is 0, and a hide without animation during a hide (which leaves alpha at 0). The other 6 pass on main and guard against regressions, such as a repeated hide, or a hide whose first animator is reversed or never started.
  • Reproduced the steps above on main and verified they no longer reproduce with this change. Also checked that view once toggles normally, that editing the caption, the Done button and sending still work, and that the media viewer's controls hide and show on tap (setIsHidden(_:animated:)).
  • SignalUITests pass on both simulators except RecipientPickerViewControllerTests.testPhoneNumberFinderParseResults, which fails the same way on main (it depends on the device region).
  • Scripts/precommit.py with SwiftFormat 0.60.1 reports no changes.

🤖 Generated with Claude Code

`UIView.setIsHidden(_:using:)` and `setIsHidden(_:withAnimationDuration:completion:)`
only set `isHidden` once a hide animation completes. A show requested
before then was compared against the stale `isHidden` and ignored, and
the hide's completion then hid the view anyway. A show also never un-hid
a view whose alpha was 0.

In the media review screen, for example, turning "view once" on and off
in quick succession leaves the caption field hidden, so no caption can be
entered, and the Add Media button missing.

Track the most recent animated change per view instead. It supersedes any
pending change, including one whose animator hasn't started yet or doesn't
finish at its end, and only its own animation and completion modify the
view. Changes without animation apply immediately. Both variants share
this logic.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jan-grzybek
jan-grzybek force-pushed the fix-media-caption-toolbar-button-visibility branch from fa02200 to 4bd6ce1 Compare September 17, 2026 16:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant