From 3d522a579203f8800039c45f935914f5586491b7 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:44:51 -0500 Subject: [PATCH] Bugfix FXIOS-10392 [Menu] CFR's text is cut off: "Find what you need faster, fro..." (backport #22813) (#22882) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bugfix FXIOS-10392 [Menu] CFR's text is cut off (#22813) * FXIOS-10392 #22779 ⁃ [Menu Redesign] Menu CFR's text is cut off: "Find what you need faster, fro..." * Don't show CFR for iPhones that are in landscape Dismiss CFR on device rotation Moved the CFR for iPads, inside the Menu, not on the top as for iPhones Refactored some code * Checking size class instead of userInterfaceIdiom (cherry picked from commit c8ab224d44ed1628478eec7a58d277588b2f6b3c) Co-authored-by: dicarobinho <61138287+dicarobinho@users.noreply.github.com> --- .../ContextualHintView.swift | 2 + .../Views/MainMenuViewController.swift | 93 ++++++++++++++----- .../ContextualHintEligibilityUtility.swift | 10 +- 3 files changed, 80 insertions(+), 25 deletions(-) diff --git a/BrowserKit/Sources/ComponentLibrary/ContextualHintView/ContextualHintView.swift b/BrowserKit/Sources/ComponentLibrary/ContextualHintView/ContextualHintView.swift index 31d0ef35e633..810607447c91 100644 --- a/BrowserKit/Sources/ComponentLibrary/ContextualHintView/ContextualHintView.swift +++ b/BrowserKit/Sources/ComponentLibrary/ContextualHintView/ContextualHintView.swift @@ -38,12 +38,14 @@ public class ContextualHintView: UIView, ThemeApplicable { label.font = FXFontStyles.Regular.headline.scaledFont() label.textAlignment = .left label.numberOfLines = 0 + label.adjustsFontForContentSizeCategory = true } private lazy var descriptionLabel: UILabel = .build { label in label.font = FXFontStyles.Regular.body.scaledFont() label.textAlignment = .left label.numberOfLines = 0 + label.adjustsFontForContentSizeCategory = true } private lazy var actionButton: LinkButton = .build { button in diff --git a/firefox-ios/Client/Frontend/Browser/MainMenu/Views/MainMenuViewController.swift b/firefox-ios/Client/Frontend/Browser/MainMenu/Views/MainMenuViewController.swift index 6b8d141cc4d6..3d05bcae3f0f 100644 --- a/firefox-ios/Client/Frontend/Browser/MainMenu/Views/MainMenuViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/MainMenu/Views/MainMenuViewController.swift @@ -21,13 +21,17 @@ class MainMenuViewController: UIViewController, FeatureFlaggable { private struct UX { static let hintViewCornerRadius: CGFloat = 20 - static let hintViewHeight: CGFloat = 120 + static let hintViewHeight: CGFloat = 140 static let hintViewMargin: CGFloat = 20 } typealias SubscriberStateType = MainMenuState // MARK: - UI/UX elements private lazy var menuContent: MenuMainView = .build() + private var hintView: ContextualHintView = .build { view in + view.isAccessibilityElement = true + } + private var hintViewHeightConstraint: NSLayoutConstraint? // MARK: - Properties var notificationCenter: NotificationProtocol @@ -40,12 +44,18 @@ class MainMenuViewController: UIViewController, private var menuState: MainMenuState private let logger: Logger - private var hintView: ContextualHintView = .build() - let viewProvider: ContextualHintViewProvider var currentWindowUUID: UUID? { return windowUUID } + private var isRegularSizeClass: Bool { + traitCollection.horizontalSizeClass == .regular && + traitCollection.verticalSizeClass == .regular + } + + // Used to save the last screen orientation + private var lastOrientation: UIDeviceOrientation + // MARK: - Initializers init( windowUUID: WindowUUID, @@ -62,6 +72,7 @@ class MainMenuViewController: UIViewController, menuState = MainMenuState(windowUUID: windowUUID) viewProvider = ContextualHintViewProvider(forHintType: .mainMenu, with: profile) + self.lastOrientation = UIDevice.current.orientation super.init(nibName: nil, bundle: nil) setupNotifications(forObserver: self, @@ -153,8 +164,15 @@ class MainMenuViewController: UIViewController, override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) - coordinator.animate(alongsideTransition: { _ in - self.adjustLayout() + coordinator.animate(alongsideTransition: { [weak self] _ in + guard let self else { return } + // We should dismiss CFR when device is rotating + if UIDevice.current.orientation != lastOrientation { + lastOrientation = UIDevice.current.orientation + self.adjustLayout(isDeviceRotating: true) + } else { + self.adjustLayout() + } }, completion: nil) } @@ -199,16 +217,27 @@ class MainMenuViewController: UIViewController, if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first { window.addSubview(hintView) - NSLayoutConstraint.activate([ - hintView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: UX.hintViewMargin), - hintView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -UX.hintViewMargin), - hintView.bottomAnchor.constraint(equalTo: menuContent.accountHeaderView.topAnchor, - constant: -UX.hintViewMargin), - hintView.heightAnchor.constraint(equalToConstant: UX.hintViewHeight) - ]) + if isRegularSizeClass { + NSLayoutConstraint.activate([ + hintView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: UX.hintViewMargin * 4), + hintView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -UX.hintViewMargin * 4), + hintView.topAnchor.constraint(equalTo: menuContent.accountHeaderView.topAnchor, + constant: UX.hintViewMargin) + ]) + } else { + NSLayoutConstraint.activate([ + hintView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: UX.hintViewMargin), + hintView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -UX.hintViewMargin), + hintView.bottomAnchor.constraint(equalTo: menuContent.accountHeaderView.topAnchor, + constant: -UX.hintViewMargin) + ]) + } + hintViewHeightConstraint = hintView.heightAnchor.constraint(equalToConstant: UX.hintViewHeight) + hintViewHeightConstraint?.isActive = true } hintView.layer.cornerRadius = UX.hintViewCornerRadius hintView.layer.masksToBounds = true + adjustLayout() } // MARK: - Redux @@ -316,23 +345,39 @@ class MainMenuViewController: UIViewController, menuA11yLabel: .MainMenu.TabsSection.AccessibilityLabels.MainMenu) } - private func adjustLayout() { + private func adjustLayout(isDeviceRotating: Bool = false) { menuContent.accountHeaderView.adjustLayout() + if isDeviceRotating { + hintView.removeFromSuperview() + } else { + if let screenHeight = view.window?.windowScene?.screen.bounds.height { + let maxHeight: CGFloat = if isRegularSizeClass { + view.frame.height / 2 + } else { + screenHeight - view.frame.height - UX.hintViewMargin * 4 + } + let height = min(UIFontMetrics.default.scaledValue(for: UX.hintViewHeight), maxHeight) + let contentSizeCategory = UIApplication.shared.preferredContentSizeCategory + hintViewHeightConstraint?.constant = + contentSizeCategory.isAccessibilityCategory ? height : UX.hintViewHeight + } + } + view.setNeedsLayout() + view.layoutIfNeeded() } private func shouldDisplayHintView() -> Bool { - // 1. Present hint if it was not presented before, - // 2. feature is enabled and - // 3. is not fresh install - if viewProvider.shouldPresentContextualHint() && - featureFlags.isFeatureEnabled(.menuRefactorHint, checking: .buildOnly) { - if InstallType.get() == .fresh { - viewProvider.markContextualHintPresented() - return false - } - return true + // Don't display CFR in landscape mode for iPhones + if !isRegularSizeClass && UIDevice.current.orientation != .portrait { + return false + } + + // Don't display CFR for fresh installs + if InstallType.get() == .fresh { + viewProvider.markContextualHintPresented() + return false } - return false + return viewProvider.shouldPresentContextualHint() ? true : false } // MARK: - UIAdaptivePresentationControllerDelegate diff --git a/firefox-ios/Client/Frontend/ContextualHint/ContextualHintEligibilityUtility.swift b/firefox-ios/Client/Frontend/ContextualHint/ContextualHintEligibilityUtility.swift index 09b1009eae66..8734edf58955 100644 --- a/firefox-ios/Client/Frontend/ContextualHint/ContextualHintEligibilityUtility.swift +++ b/firefox-ios/Client/Frontend/ContextualHint/ContextualHintEligibilityUtility.swift @@ -45,7 +45,7 @@ struct ContextualHintEligibilityUtility: ContextualHintEligibilityUtilityProtoco case .toolbarLocation: hintTypeShouldBePresented = isSearchBarLocationFeatureEnabled case .mainMenu: - hintTypeShouldBePresented = true + hintTypeShouldBePresented = canMenuCFRBePresented case .inactiveTabs: hintTypeShouldBePresented = true case .shoppingExperience: @@ -65,6 +65,14 @@ struct ContextualHintEligibilityUtility: ContextualHintEligibilityUtilityProtoco return overlayState?.inOverlayMode ?? false } + /// Determine if the CFR for Menu is presentable. + /// + /// It's presentable on these conditions: + /// - menu-hint flag is enabled + private var canMenuCFRBePresented: Bool { + return featureFlags.isFeatureEnabled(.menuRefactorHint, checking: .buildOnly) ? true : false + } + /// If device is iPhone we present JumpBackIn and SyncTab CFRs only after Toolbar CFR has been /// presented if the feature is enabled. If the Toolbar CFR flag is disabled or the device /// is iPad (toolbar CFR is not presented on iPad) we bypass it