From 0faea45485693ae7f00c947f4f2100079ec8eb7c Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Fri, 23 Dec 2022 10:27:07 -0500 Subject: [PATCH 1/7] Allow AltViewController text to scroll --- .../MediaPreview/AltViewController.swift | 19 +++++++++---------- .../MastodonExtension/UIEdgeInsets.swift | 3 +++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Mastodon/Scene/MediaPreview/AltViewController.swift b/Mastodon/Scene/MediaPreview/AltViewController.swift index 305487397..16a9c078c 100644 --- a/Mastodon/Scene/MediaPreview/AltViewController.swift +++ b/Mastodon/Scene/MediaPreview/AltViewController.swift @@ -24,6 +24,11 @@ class AltViewController: UIViewController { @MainActor required dynamic init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + override func loadView() { + super.loadView() + view.translatesAutoresizingMaskIntoConstraints = false + } override func viewDidLoad() { super.viewDidLoad() @@ -38,22 +43,16 @@ class AltViewController: UIViewController { right: 0 ) label.font = .preferredFont(forTextStyle: .callout) - label.isScrollEnabled = false + label.isScrollEnabled = true label.backgroundColor = .clear label.isOpaque = false label.isEditable = false label.tintColor = .white label.text = alt - view.translatesAutoresizingMaskIntoConstraints = false view.addSubview(label) - NSLayoutConstraint.activate( - NSLayoutConstraint.constraints(withVisualFormat: "V:|-[label]-|", metrics: nil, views: ["label": label]) - ) - NSLayoutConstraint.activate( - NSLayoutConstraint.constraints(withVisualFormat: "H:|-(8)-[label]-(8)-|", metrics: nil, views: ["label": label]) - ) + label.pinToParent(padding: UIEdgeInsets(horizontal: 8, vertical: 0)) NSLayoutConstraint.activate([ label.widthAnchor.constraint(lessThanOrEqualToConstant: 400), ]) @@ -63,8 +62,8 @@ class AltViewController: UIViewController { super.viewDidLayoutSubviews() UIView.performWithoutAnimation { preferredContentSize = CGSize( - width: label.intrinsicContentSize.width + 16, - height: label.intrinsicContentSize.height + view.layoutMargins.top + view.layoutMargins.bottom + width: label.contentSize.width + 16, + height: label.contentSize.height + view.layoutMargins.top + view.layoutMargins.bottom ) } } diff --git a/MastodonSDK/Sources/MastodonExtension/UIEdgeInsets.swift b/MastodonSDK/Sources/MastodonExtension/UIEdgeInsets.swift index 8436ff5d2..ea69bcefc 100644 --- a/MastodonSDK/Sources/MastodonExtension/UIEdgeInsets.swift +++ b/MastodonSDK/Sources/MastodonExtension/UIEdgeInsets.swift @@ -8,6 +8,9 @@ import UIKit extension UIEdgeInsets { + public init(horizontal: CGFloat, vertical: CGFloat) { + self.init(top: vertical, left: horizontal, bottom: vertical, right: horizontal) + } public static func constant(_ offset: CGFloat) -> Self { UIEdgeInsets(top: offset, left: offset, bottom: offset, right: offset) } From 2a161886a1bb630c1724153f1460367badcd5aa3 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Fri, 23 Dec 2022 10:57:53 -0500 Subject: [PATCH 2/7] Improve HUDButton contrast --- MastodonSDK/Sources/MastodonUI/View/Button/HUDButton.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/MastodonSDK/Sources/MastodonUI/View/Button/HUDButton.swift b/MastodonSDK/Sources/MastodonUI/View/Button/HUDButton.swift index 566100bb6..07d70e74e 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Button/HUDButton.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Button/HUDButton.swift @@ -12,18 +12,17 @@ public class HUDButton: UIView { public static let height: CGFloat = 30 let background: UIVisualEffectView = { - let backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .systemUltraThinMaterial)) - backgroundView.alpha = 0.9 + let backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .systemThinMaterial)) backgroundView.layer.masksToBounds = true backgroundView.layer.cornerRadius = HUDButton.height * 0.5 return backgroundView }() - let vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: UIBlurEffect(style: .systemUltraThinMaterial))) + let vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: UIBlurEffect(style: .systemThinMaterial))) public let button: UIButton = { let button = HighlightDimmableButton() - button.expandEdgeInsets = UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10) + button.expandEdgeInsets = .constant(-10) button.contentEdgeInsets = .constant(7) button.imageView?.tintColor = .label button.titleLabel?.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .bold)) From b8b59674f305c19ef17d7d26960e7634368b1a96 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Fri, 23 Dec 2022 11:14:04 -0500 Subject: [PATCH 3/7] Fix scroll insets, increase contrast --- Mastodon/Scene/MediaPreview/AltViewController.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Mastodon/Scene/MediaPreview/AltViewController.swift b/Mastodon/Scene/MediaPreview/AltViewController.swift index 16a9c078c..9a11d20f8 100644 --- a/Mastodon/Scene/MediaPreview/AltViewController.swift +++ b/Mastodon/Scene/MediaPreview/AltViewController.swift @@ -49,10 +49,13 @@ class AltViewController: UIViewController { label.isEditable = false label.tintColor = .white label.text = alt + label.textContainerInset = UIEdgeInsets(horizontal: 8, vertical: 16) + label.verticalScrollIndicatorInsets.bottom = 4 + view.backgroundColor = .systemBackground view.addSubview(label) - label.pinToParent(padding: UIEdgeInsets(horizontal: 8, vertical: 0)) + label.pinToParent() NSLayoutConstraint.activate([ label.widthAnchor.constraint(lessThanOrEqualToConstant: 400), ]) From d0812f4275636b7609bbec3226c95d85c1e4099f Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Fri, 23 Dec 2022 11:31:53 -0500 Subject: [PATCH 4/7] Further improve HUDButton contrast --- MastodonSDK/Sources/MastodonUI/View/Button/HUDButton.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MastodonSDK/Sources/MastodonUI/View/Button/HUDButton.swift b/MastodonSDK/Sources/MastodonUI/View/Button/HUDButton.swift index 07d70e74e..26dda32d6 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Button/HUDButton.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Button/HUDButton.swift @@ -12,13 +12,13 @@ public class HUDButton: UIView { public static let height: CGFloat = 30 let background: UIVisualEffectView = { - let backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .systemThinMaterial)) + let backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) backgroundView.layer.masksToBounds = true backgroundView.layer.cornerRadius = HUDButton.height * 0.5 return backgroundView }() - let vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: UIBlurEffect(style: .systemThinMaterial))) + let vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: UIBlurEffect(style: .systemMaterial))) public let button: UIButton = { let button = HighlightDimmableButton() From 752d76c8be0b533f6340e29e22c762bee8d52ef3 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Fri, 23 Dec 2022 12:08:46 -0500 Subject: [PATCH 5/7] fix sizing if the text view does not need to scroll --- .../Scene/MediaPreview/AltViewController.swift | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Mastodon/Scene/MediaPreview/AltViewController.swift b/Mastodon/Scene/MediaPreview/AltViewController.swift index 9a11d20f8..5fba21b1f 100644 --- a/Mastodon/Scene/MediaPreview/AltViewController.swift +++ b/Mastodon/Scene/MediaPreview/AltViewController.swift @@ -9,7 +9,14 @@ import SwiftUI class AltViewController: UIViewController { private var alt: String - let label = UITextView() + let label = { + if #available(iOS 16, *) { + // TODO: update code below to use TextKit 2 when dropping iOS 15 support + return UITextView(usingTextLayoutManager: false) + } else { + return UITextView() + } + }() init(alt: String, sourceView: UIView?) { self.alt = alt @@ -49,7 +56,8 @@ class AltViewController: UIViewController { label.isEditable = false label.tintColor = .white label.text = alt - label.textContainerInset = UIEdgeInsets(horizontal: 8, vertical: 16) + label.textContainerInset = UIEdgeInsets(top: 12, left: 8, bottom: 8, right: 8) + label.contentInsetAdjustmentBehavior = .always label.verticalScrollIndicatorInsets.bottom = 4 view.backgroundColor = .systemBackground @@ -64,9 +72,10 @@ class AltViewController: UIViewController { override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() UIView.performWithoutAnimation { + let size = label.layoutManager.boundingRect(forGlyphRange: NSMakeRange(0, (label.textStorage.string as NSString).length), in: label.textContainer).size preferredContentSize = CGSize( - width: label.contentSize.width + 16, - height: label.contentSize.height + view.layoutMargins.top + view.layoutMargins.bottom + width: size.width + (8 + label.textContainer.lineFragmentPadding) * 2, + height: size.height + 12 + (label.textContainer.lineFragmentPadding * 2) ) } } From d553dd4f6292cd3ae217c9007de51bf7ce67dad1 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Fri, 23 Dec 2022 14:16:41 -0500 Subject: [PATCH 6/7] Resize text when Dynamic Type style updates --- Mastodon/Scene/MediaPreview/AltViewController.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Mastodon/Scene/MediaPreview/AltViewController.swift b/Mastodon/Scene/MediaPreview/AltViewController.swift index 5fba21b1f..668771fac 100644 --- a/Mastodon/Scene/MediaPreview/AltViewController.swift +++ b/Mastodon/Scene/MediaPreview/AltViewController.swift @@ -79,6 +79,11 @@ class AltViewController: UIViewController { ) } } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + label.font = .preferredFont(forTextStyle: .callout) + } } // MARK: UIPopoverPresentationControllerDelegate From f26f36a60bf386e9b0936d91363dfbbb152d41aa Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Mon, 26 Dec 2022 15:29:01 +0100 Subject: [PATCH 7/7] Slightly adjust code (#806) Renaming, remove iOS-checks. --- .../MediaPreview/AltViewController.swift | 62 +++++++++---------- .../MediaPreviewViewController.swift | 2 +- .../View/Content/MediaAltTextOverlay.swift | 2 - .../MastodonUI/View/Content/MediaView.swift | 37 ++++------- 4 files changed, 43 insertions(+), 60 deletions(-) diff --git a/Mastodon/Scene/MediaPreview/AltViewController.swift b/Mastodon/Scene/MediaPreview/AltViewController.swift index 668771fac..05a3e5b09 100644 --- a/Mastodon/Scene/MediaPreview/AltViewController.swift +++ b/Mastodon/Scene/MediaPreview/AltViewController.swift @@ -8,18 +8,33 @@ import SwiftUI class AltViewController: UIViewController { - private var alt: String - let label = { + let textView = { + let textView: UITextView + if #available(iOS 16, *) { // TODO: update code below to use TextKit 2 when dropping iOS 15 support - return UITextView(usingTextLayoutManager: false) + textView = UITextView(usingTextLayoutManager: false) } else { - return UITextView() + textView = UITextView() } + + textView.textContainer.maximumNumberOfLines = 0 + textView.textContainer.lineBreakMode = .byWordWrapping + textView.font = .preferredFont(forTextStyle: .callout) + textView.isScrollEnabled = true + textView.backgroundColor = .clear + textView.isOpaque = false + textView.isEditable = false + textView.tintColor = .white + textView.textContainerInset = UIEdgeInsets(top: 12, left: 8, bottom: 8, right: 8) + textView.contentInsetAdjustmentBehavior = .always + textView.verticalScrollIndicatorInsets.bottom = 4 + + return textView }() init(alt: String, sourceView: UIView?) { - self.alt = alt + textView.text = alt super.init(nibName: nil, bundle: nil) self.modalPresentationStyle = .popover self.popoverPresentationController?.delegate = self @@ -40,49 +55,32 @@ class AltViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - label.translatesAutoresizingMaskIntoConstraints = false - label.textContainer.maximumNumberOfLines = 0 - label.textContainer.lineBreakMode = .byWordWrapping - label.textContainerInset = UIEdgeInsets( - top: 8, - left: 0, - bottom: -label.textContainer.lineFragmentPadding, - right: 0 - ) - label.font = .preferredFont(forTextStyle: .callout) - label.isScrollEnabled = true - label.backgroundColor = .clear - label.isOpaque = false - label.isEditable = false - label.tintColor = .white - label.text = alt - label.textContainerInset = UIEdgeInsets(top: 12, left: 8, bottom: 8, right: 8) - label.contentInsetAdjustmentBehavior = .always - label.verticalScrollIndicatorInsets.bottom = 4 - + textView.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = .systemBackground - view.addSubview(label) + view.addSubview(textView) - label.pinToParent() + textView.pinToParent() NSLayoutConstraint.activate([ - label.widthAnchor.constraint(lessThanOrEqualToConstant: 400), + textView.widthAnchor.constraint(lessThanOrEqualToConstant: 400), ]) } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() UIView.performWithoutAnimation { - let size = label.layoutManager.boundingRect(forGlyphRange: NSMakeRange(0, (label.textStorage.string as NSString).length), in: label.textContainer).size + + let size = textView.layoutManager.boundingRect(forGlyphRange: NSMakeRange(0, (textView.textStorage.string as NSString).length), in: textView.textContainer).size + preferredContentSize = CGSize( - width: size.width + (8 + label.textContainer.lineFragmentPadding) * 2, - height: size.height + 12 + (label.textContainer.lineFragmentPadding * 2) + width: size.width + (8 + textView.textContainer.lineFragmentPadding) * 2, + height: size.height + 12 + (textView.textContainer.lineFragmentPadding) * 2 ) } } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) - label.font = .preferredFont(forTextStyle: .callout) + textView.font = .preferredFont(forTextStyle: .callout) } } diff --git a/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift b/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift index 1200c7d85..ede0be296 100644 --- a/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift +++ b/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift @@ -181,9 +181,9 @@ extension MediaPreviewViewController { @objc private func altButtonPressed(_ sender: UIButton) { guard let alt = viewModel.altText else { return } + present(AltViewController(alt: alt, sourceView: sender), animated: true) } - } // MARK: - MediaPreviewingViewController diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/MediaAltTextOverlay.swift b/MastodonSDK/Sources/MastodonUI/View/Content/MediaAltTextOverlay.swift index fec17f1ee..a625be292 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/MediaAltTextOverlay.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/MediaAltTextOverlay.swift @@ -7,7 +7,6 @@ import SwiftUI -@available(iOS 15.0, *) struct MediaAltTextOverlay: View { var altDescription: String? @@ -69,7 +68,6 @@ struct MediaAltTextOverlay: View { } } -@available(iOS 15.0, *) struct MediaAltTextOverlay_Previews: PreviewProvider { static var previews: some View { MediaAltTextOverlay(altDescription: "Hello, world!") diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift index a140d9737..ba5a09572 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift @@ -73,20 +73,12 @@ public final class MediaView: UIView { return label }() - let _altViewController: UIViewController! = { - if #available(iOS 15.0, *) { - let vc = UIHostingController(rootView: MediaAltTextOverlay()) - vc.view.backgroundColor = .clear - return vc - } else { - return nil - } + let altViewController: UIHostingController = { + let vc = UIHostingController(rootView: MediaAltTextOverlay()) + vc.view.backgroundColor = .clear + return vc }() - @available(iOS 15.0, *) - var altViewController: UIHostingController { - _altViewController as! UIHostingController - } - + public override init(frame: CGRect) { super.init(frame: frame) _init() @@ -228,9 +220,8 @@ extension MediaView { } else { accessibilityLabel = altDescription } - if #available(iOS 15.0, *) { - altViewController.rootView.altDescription = altDescription - } + + altViewController.rootView.altDescription = altDescription } private func layoutBlurhash() { @@ -262,11 +253,9 @@ extension MediaView { } private func layoutAlt() { - if #available(iOS 15.0, *) { - altViewController.view.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(altViewController.view) - altViewController.view.pinToParent() - } + altViewController.view.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(altViewController.view) + altViewController.view.pinToParent() } public func prepareForReuse() { @@ -304,10 +293,8 @@ extension MediaView { container.removeFromSuperview() container.removeConstraints(container.constraints) - if #available(iOS 15.0, *) { - altViewController.rootView.altDescription = nil - } - + altViewController.rootView.altDescription = nil + // reset configuration configuration = nil }