From ed580541f0597c82e80d453c05522f440531c724 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Sat, 26 Nov 2022 14:29:30 -0500 Subject: [PATCH] Merge top buttons into a single parent view (also fix tapping just outside a HUDButton) --- Mastodon/Scene/MediaPreview/HUDButton.swift | 8 ++++ .../MediaPreviewViewController.swift | 46 +++++++++++++++---- ...wViewControllerAnimatedTransitioning.swift | 14 +++--- 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/Mastodon/Scene/MediaPreview/HUDButton.swift b/Mastodon/Scene/MediaPreview/HUDButton.swift index 0089ebcb1..e82fba0f6 100644 --- a/Mastodon/Scene/MediaPreview/HUDButton.swift +++ b/Mastodon/Scene/MediaPreview/HUDButton.swift @@ -63,4 +63,12 @@ class HUDButton: UIView { super.traitCollectionDidChange(previousTraitCollection) button.titleLabel?.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .bold)) } + + override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + button.point(inside: button.convert(point, from: self), with: event) + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + button + } } diff --git a/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift b/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift index 3c9821eb6..eaf740a2b 100644 --- a/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift +++ b/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift @@ -24,7 +24,32 @@ final class MediaPreviewViewController: UIViewController, NeedsDependency { let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) let pagingViewController = MediaPreviewPagingViewController() - + + let topToolbar: UIStackView = { + class TouchTransparentStackView: UIStackView { + // allow button hit boxes to grow outside of this view’s bounds + override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + subviews.contains { $0.point(inside: $0.convert(point, from: self), with: event) } + } + + // allow taps on blank areas to pass through + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + let view = super.hitTest(point, with: event) + if view == self { + return nil + } + return view + } + } + + let stackView = TouchTransparentStackView() + stackView.axis = .horizontal + stackView.distribution = .equalSpacing + stackView.alignment = .fill + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + let closeButton = HUDButton { button in button.setImage(UIImage(systemName: "xmark", withConfiguration: UIImage.SymbolConfiguration(pointSize: 16, weight: .bold))!, for: .normal) } @@ -56,18 +81,19 @@ extension MediaPreviewViewController { visualEffectView.pinTo(to: pagingViewController.view) pagingViewController.didMove(toParent: self) - view.addSubview(closeButton) + view.addSubview(topToolbar) + NSLayoutConstraint.activate([ + topToolbar.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor, constant: 12), + topToolbar.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor), + topToolbar.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor), + ]) + + topToolbar.addArrangedSubview(closeButton) NSLayoutConstraint.activate([ - closeButton.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor, constant: 12), - closeButton.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor), closeButton.widthAnchor.constraint(equalToConstant: HUDButton.height).priority(.defaultHigh), ]) - view.addSubview(altButton) - NSLayoutConstraint.activate([ - altButton.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor, constant: 12), - altButton.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor), - ]) + topToolbar.addArrangedSubview(altButton) viewModel.mediaPreviewImageViewControllerDelegate = self @@ -121,7 +147,7 @@ extension MediaPreviewViewController { .sink { [weak self] showingChrome in UIView.animate(withDuration: 0.3) { self?.setNeedsStatusBarAppearanceUpdate() - self?.closeButton.alpha = showingChrome ? 1 : 0 + self?.topToolbar.alpha = showingChrome ? 1 : 0 } } .store(in: &disposeBag) diff --git a/Mastodon/Scene/Transition/MediaPreview/MediaHostToMediaPreviewViewControllerAnimatedTransitioning.swift b/Mastodon/Scene/Transition/MediaPreview/MediaHostToMediaPreviewViewControllerAnimatedTransitioning.swift index 7bf81f0b0..44cb68428 100644 --- a/Mastodon/Scene/Transition/MediaPreview/MediaHostToMediaPreviewViewControllerAnimatedTransitioning.swift +++ b/Mastodon/Scene/Transition/MediaPreview/MediaHostToMediaPreviewViewControllerAnimatedTransitioning.swift @@ -81,8 +81,8 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning { transitionItem.transitionView = transitionImageView transitionContext.containerView.addSubview(transitionImageView) - toVC.closeButton.alpha = 0 - + toVC.topToolbar.alpha = 0 + if UIAccessibility.isReduceTransparencyEnabled { toVC.visualEffectView.alpha = 0 } @@ -101,7 +101,7 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning { toVC.pagingViewController.view.alpha = 1 transitionImageView.removeFromSuperview() UIView.animate(withDuration: 0.33, delay: 0, options: [.curveEaseInOut]) { - toVC.closeButton.alpha = 1 + toVC.topToolbar.alpha = 1 } transitionContext.completeTransition(position == .end) } @@ -138,13 +138,13 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning { } } - // update close button + // update top toolbar UIView.animate(withDuration: 0.33, delay: 0, options: [.curveEaseInOut]) { - fromVC.closeButton.alpha = 0 + fromVC.topToolbar.alpha = 0 } animator.addCompletion { position in UIView.animate(withDuration: 0.33, delay: 0, options: [.curveEaseInOut]) { - fromVC.closeButton.alpha = position == .end ? 0 : 1 + fromVC.topToolbar.alpha = position == .end ? 0 : 1 } } @@ -202,7 +202,7 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning { mediaPreviewTransitionContext.snapshot.contentMode = .scaleAspectFill mediaPreviewTransitionContext.snapshot.clipsToBounds = true transitionMaskView.addSubview(mediaPreviewTransitionContext.snapshot) - fromVC.view.bringSubviewToFront(fromVC.closeButton) + fromVC.view.bringSubviewToFront(fromVC.topToolbar) transitionItem.transitionView = mediaPreviewTransitionContext.transitionView transitionItem.snapshotTransitioning = mediaPreviewTransitionContext.snapshot