mirror of
https://github.com/mastodon/mastodon-ios
synced 2025-04-11 22:58:02 +02:00
Merge pull request #823 from mastodon/806-alt-scroll
Alt-Scroll-Adjustments
This commit is contained in:
commit
df9154a220
@ -8,11 +8,33 @@
|
||||
import SwiftUI
|
||||
|
||||
class AltViewController: UIViewController {
|
||||
private var alt: String
|
||||
let label = UITextView()
|
||||
let textView = {
|
||||
let textView: UITextView
|
||||
|
||||
if #available(iOS 16, *) {
|
||||
// TODO: update code below to use TextKit 2 when dropping iOS 15 support
|
||||
textView = UITextView(usingTextLayoutManager: false)
|
||||
} else {
|
||||
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
|
||||
@ -24,50 +46,42 @@ 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()
|
||||
|
||||
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 = false
|
||||
label.backgroundColor = .clear
|
||||
label.isOpaque = false
|
||||
label.isEditable = false
|
||||
label.tintColor = .white
|
||||
label.text = alt
|
||||
textView.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.backgroundColor = .systemBackground
|
||||
view.addSubview(textView)
|
||||
|
||||
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])
|
||||
)
|
||||
textView.pinToParent()
|
||||
NSLayoutConstraint.activate([
|
||||
label.widthAnchor.constraint(lessThanOrEqualToConstant: 400),
|
||||
textView.widthAnchor.constraint(lessThanOrEqualToConstant: 400),
|
||||
])
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
UIView.performWithoutAnimation {
|
||||
|
||||
let size = textView.layoutManager.boundingRect(forGlyphRange: NSMakeRange(0, (textView.textStorage.string as NSString).length), in: textView.textContainer).size
|
||||
|
||||
preferredContentSize = CGSize(
|
||||
width: label.intrinsicContentSize.width + 16,
|
||||
height: label.intrinsicContentSize.height + view.layoutMargins.top + view.layoutMargins.bottom
|
||||
width: size.width + (8 + textView.textContainer.lineFragmentPadding) * 2,
|
||||
height: size.height + 12 + (textView.textContainer.lineFragmentPadding) * 2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||
super.traitCollectionDidChange(previousTraitCollection)
|
||||
textView.font = .preferredFont(forTextStyle: .callout)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: UIPopoverPresentationControllerDelegate
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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: .systemMaterial))
|
||||
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: .systemMaterial)))
|
||||
|
||||
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))
|
||||
|
@ -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!")
|
||||
|
@ -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<MediaAltTextOverlay> = {
|
||||
let vc = UIHostingController(rootView: MediaAltTextOverlay())
|
||||
vc.view.backgroundColor = .clear
|
||||
return vc
|
||||
}()
|
||||
@available(iOS 15.0, *)
|
||||
var altViewController: UIHostingController<MediaAltTextOverlay> {
|
||||
_altViewController as! UIHostingController<MediaAltTextOverlay>
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user