From 9c19f4fcbce6bc58a72db55bc4a2af1da7982c29 Mon Sep 17 00:00:00 2001 From: Igor Solomennikov Date: Tue, 7 Oct 2025 09:00:52 -0700 Subject: [PATCH] Fix empty space below category bar in emoji picker sheet on iOS 15-18. --- Signal/Emoji/EmojiPickerSectionToolbar.swift | 41 ++++++++++++-------- Signal/Emoji/EmojiPickerSheet.swift | 4 +- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/Signal/Emoji/EmojiPickerSectionToolbar.swift b/Signal/Emoji/EmojiPickerSectionToolbar.swift index 3e8a146a4b..4f3bd52beb 100644 --- a/Signal/Emoji/EmojiPickerSectionToolbar.swift +++ b/Signal/Emoji/EmojiPickerSectionToolbar.swift @@ -146,10 +146,11 @@ class EmojiPickerSectionToolbar: UIView, UICollectionViewDelegate { collectionView.addConstraint(collectionView.heightAnchor.constraint(equalToConstant: collectionViewHeight)) // Prepare background. - if #available(iOS 26, *), FeatureFlags.iOS26SDKIsAvailable { + var backgroundConfigured = false +#if compiler(>=6.2) + if #available(iOS 26, *) { // Floating glass panel that encapsulates emoji category strip. // Insets are carefully configured for best on-screen appearance. -#if compiler(>=6.2) let glassEffectView = UIVisualEffectView(effect: UIGlassEffect(style: .regular)) glassEffectView.translatesAutoresizingMaskIntoConstraints = false glassEffectView.cornerConfiguration = .capsule() @@ -170,14 +171,24 @@ class EmojiPickerSectionToolbar: UIView, UICollectionViewDelegate { collectionView.topAnchor.constraint(equalTo: glassEffectView.layoutMarginsGuide.topAnchor), collectionView.bottomAnchor.constraint(equalTo: glassEffectView.layoutMarginsGuide.bottomAnchor), ]) + backgroundConfigured = true + } #endif - } else { - // Container extends to the vertical edges and to the bottom of the view. - // Collection view is pinned to the top edge and leading, trailing and bottom margins. - let collectionViewContainer: UIView + if !backgroundConfigured { + // Background stretches 500 dp below bottom edge of the screen so that there's no gap where bottom safe area is. if UIAccessibility.isReduceTransparencyEnabled { - backgroundColor = UIColor.Signal.background - collectionViewContainer = self + let backgroundView = UIView() + backgroundView.backgroundColor = UIColor.Signal.background + addSubview(backgroundView) + backgroundView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + backgroundView.topAnchor.constraint(equalTo: topAnchor), + backgroundView.leadingAnchor.constraint(equalTo: leadingAnchor), + backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 500), + backgroundView.trailingAnchor.constraint(equalTo: trailingAnchor), + ]) + + addSubview(collectionView) } else { let blurEffect = forceDarkTheme ? Theme.darkThemeBarBlurEffect : Theme.barBlurEffect let blurEffectView = UIVisualEffectView(effect: blurEffect) @@ -187,18 +198,16 @@ class EmojiPickerSectionToolbar: UIView, UICollectionViewDelegate { blurEffectView.leadingAnchor.constraint(equalTo: leadingAnchor), blurEffectView.trailingAnchor.constraint(equalTo: trailingAnchor), blurEffectView.topAnchor.constraint(equalTo: topAnchor), - blurEffectView.bottomAnchor.constraint(equalTo: bottomAnchor), + blurEffectView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 500), ]) - - collectionViewContainer = blurEffectView.contentView + blurEffectView.contentView.addSubview(collectionView) } - collectionViewContainer.addSubview(collectionView) NSLayoutConstraint.activate([ - collectionView.leadingAnchor.constraint(equalTo: collectionViewContainer.layoutMarginsGuide.leadingAnchor), - collectionView.trailingAnchor.constraint(equalTo: collectionViewContainer.layoutMarginsGuide.trailingAnchor), - collectionView.topAnchor.constraint(equalTo: collectionViewContainer.topAnchor), - collectionView.bottomAnchor.constraint(equalTo: collectionViewContainer.safeAreaLayoutGuide.bottomAnchor) + collectionView.topAnchor.constraint(equalTo: topAnchor), + collectionView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + collectionView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor), + collectionView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), ]) } diff --git a/Signal/Emoji/EmojiPickerSheet.swift b/Signal/Emoji/EmojiPickerSheet.swift index b133bf242c..d641a157e4 100644 --- a/Signal/Emoji/EmojiPickerSheet.swift +++ b/Signal/Emoji/EmojiPickerSheet.swift @@ -118,12 +118,12 @@ class EmojiPickerSheet: InteractiveSheetViewController { NSLayoutConstraint.activate([ sectionToolbar.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), sectionToolbar.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), - sectionToolbar.bottomAnchor.constraint(equalTo: contentView.keyboardLayoutGuide.topAnchor), + sectionToolbar.bottomAnchor.constraint(equalTo: keyboardLayoutGuide.topAnchor), ]) #if compiler(>=6.2) // Obscures content underneath the emoji section toolbar to improve legibility. - if #available(iOS 26, *), FeatureFlags.iOS26SDKIsAvailable { + if #available(iOS 26, *) { let scrollInteraction = UIScrollEdgeElementContainerInteraction() scrollInteraction.scrollView = collectionView scrollInteraction.edge = .bottom