This commit is contained in:
Kyle Bashour 2022-11-14 13:26:25 -08:00
parent daeb2ef70f
commit ae24f95e31
3 changed files with 59 additions and 13 deletions

View File

@ -5,12 +5,17 @@
// Created by Kyle Bashour on 11/11/22. // Created by Kyle Bashour on 11/11/22.
// //
import AlamofireImage
import LinkPresentation
import MastodonAsset import MastodonAsset
import MastodonCore import MastodonCore
import OpenGraph import OpenGraph
import UIKit import UIKit
public final class OpenGraphView: UIControl { public final class LinkPreviewButton: UIControl {
private var linkPresentationTask: Task<Void, Error>?
private var url: URL?
private let containerStackView = UIStackView() private let containerStackView = UIStackView()
private let labelStackView = UIStackView() private let labelStackView = UIStackView()
@ -27,17 +32,20 @@ public final class OpenGraphView: UIControl {
layer.borderColor = ThemeService.shared.currentTheme.value.separator.cgColor layer.borderColor = ThemeService.shared.currentTheme.value.separator.cgColor
backgroundColor = ThemeService.shared.currentTheme.value.systemElevatedBackgroundColor backgroundColor = ThemeService.shared.currentTheme.value.systemElevatedBackgroundColor
titleLabel.numberOfLines = 0 titleLabel.numberOfLines = 2
titleLabel.setContentCompressionResistancePriority(.defaultLow - 1, for: .horizontal) titleLabel.setContentCompressionResistancePriority(.defaultLow - 1, for: .horizontal)
titleLabel.text = "This is where I'd put a title... if I had one" titleLabel.text = "This is where I'd put a title... if I had one"
titleLabel.textColor = Asset.Colors.Label.primary.color titleLabel.textColor = Asset.Colors.Label.primary.color
subtitleLabel.text = "Subtitle" subtitleLabel.text = "Subtitle"
subtitleLabel.numberOfLines = 1
subtitleLabel.setContentCompressionResistancePriority(.defaultLow - 1, for: .horizontal) subtitleLabel.setContentCompressionResistancePriority(.defaultLow - 1, for: .horizontal)
subtitleLabel.textColor = Asset.Colors.Label.secondary.color subtitleLabel.textColor = Asset.Colors.Label.secondary.color
subtitleLabel.font = UIFontMetrics(forTextStyle: .subheadline).scaledFont(for: .systemFont(ofSize: 15, weight: .regular), maximumPointSize: 20) subtitleLabel.font = UIFontMetrics(forTextStyle: .subheadline).scaledFont(for: .systemFont(ofSize: 15, weight: .regular), maximumPointSize: 20)
imageView.backgroundColor = UIColor.black.withAlphaComponent(0.15) imageView.backgroundColor = UIColor.black.withAlphaComponent(0.15)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
labelStackView.addArrangedSubview(titleLabel) labelStackView.addArrangedSubview(titleLabel)
labelStackView.addArrangedSubview(subtitleLabel) labelStackView.addArrangedSubview(subtitleLabel)
@ -55,12 +63,13 @@ public final class OpenGraphView: UIControl {
containerStackView.translatesAutoresizingMaskIntoConstraints = false containerStackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
containerStackView.heightAnchor.constraint(equalToConstant: 80), containerStackView.heightAnchor.constraint(equalToConstant: 85),
containerStackView.topAnchor.constraint(equalTo: topAnchor), containerStackView.topAnchor.constraint(equalTo: topAnchor),
containerStackView.bottomAnchor.constraint(equalTo: bottomAnchor), containerStackView.bottomAnchor.constraint(equalTo: bottomAnchor),
containerStackView.leadingAnchor.constraint(equalTo: leadingAnchor), containerStackView.leadingAnchor.constraint(equalTo: leadingAnchor),
containerStackView.trailingAnchor.constraint(equalTo: trailingAnchor), containerStackView.trailingAnchor.constraint(equalTo: trailingAnchor),
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor), imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
imageView.heightAnchor.constraint(equalTo: heightAnchor),
]) ])
} }
@ -68,8 +77,37 @@ public final class OpenGraphView: UIControl {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
public func configure(content: String) { public func configure(url: URL, trimmed: String) {
self.subtitleLabel.text = content guard url != self.url else {
return
}
reset()
subtitleLabel.text = trimmed
self.url = url
linkPresentationTask = Task {
do {
let metadata = try await LPMetadataProvider().startFetchingMetadata(for: url)
guard !Task.isCancelled else {
return
}
self.titleLabel.text = metadata.title
if let result = try await metadata.imageProvider?.loadImageData() {
let image = UIImage(data: result.data)
guard !Task.isCancelled else {
return
}
self.imageView.image = image
}
} catch {
self.subtitleLabel.text = "Error loading link preview"
}
}
} }
public override func didMoveToWindow() { public override func didMoveToWindow() {
@ -79,4 +117,12 @@ public final class OpenGraphView: UIControl {
layer.borderWidth = 1 / window.screen.scale layer.borderWidth = 1 / window.screen.scale
} }
} }
private func reset() {
linkPresentationTask?.cancel()
url = nil
imageView.image = nil
titleLabel.text = nil
subtitleLabel.text = nil
}
} }

View File

@ -330,8 +330,8 @@ extension StatusView.ViewModel {
fatalError() fatalError()
} }
statusView.linkPreview.configure(content: trimmed) statusView.linkPreviewButton.configure(url: url, trimmed: trimmed)
statusView.setLinkPreviewDisplay() statusView.setLinkPreviewButtonDisplay()
} }
} else { } else {
statusView.contentMetaText.reset() statusView.contentMetaText.reset()

View File

@ -114,7 +114,7 @@ public final class StatusView: UIView {
return metaText return metaText
}() }()
public let linkPreview = OpenGraphView() public let linkPreviewButton = LinkPreviewButton()
// content warning // content warning
public let spoilerOverlayView = SpoilerOverlayView() public let spoilerOverlayView = SpoilerOverlayView()
@ -219,7 +219,7 @@ public final class StatusView: UIView {
setMediaDisplay(isDisplay: false) setMediaDisplay(isDisplay: false)
setPollDisplay(isDisplay: false) setPollDisplay(isDisplay: false)
setFilterHintLabelDisplay(isDisplay: false) setFilterHintLabelDisplay(isDisplay: false)
setLinkPreviewDisplay(isDisplay: false) setLinkPreviewButtonDisplay(isDisplay: false)
} }
public override init(frame: CGRect) { public override init(frame: CGRect) {
@ -392,8 +392,8 @@ extension StatusView.Style {
// status content // status content
statusView.contentContainer.addArrangedSubview(statusView.contentMetaText.textView) statusView.contentContainer.addArrangedSubview(statusView.contentMetaText.textView)
statusView.containerStackView.setCustomSpacing(16, after: statusView.contentMetaText.textView) statusView.containerStackView.setCustomSpacing(16, after: statusView.contentMetaText.textView)
statusView.contentContainer.addArrangedSubview(statusView.linkPreview) statusView.contentContainer.addArrangedSubview(statusView.linkPreviewButton)
statusView.containerStackView.setCustomSpacing(16, after: statusView.linkPreview) statusView.containerStackView.setCustomSpacing(16, after: statusView.linkPreviewButton)
statusView.spoilerOverlayView.translatesAutoresizingMaskIntoConstraints = false statusView.spoilerOverlayView.translatesAutoresizingMaskIntoConstraints = false
statusView.containerStackView.addSubview(statusView.spoilerOverlayView) statusView.containerStackView.addSubview(statusView.spoilerOverlayView)
@ -545,8 +545,8 @@ extension StatusView {
filterHintLabel.isHidden = !isDisplay filterHintLabel.isHidden = !isDisplay
} }
func setLinkPreviewDisplay(isDisplay: Bool = true) { func setLinkPreviewButtonDisplay(isDisplay: Bool = true) {
linkPreview.isHidden = !isDisplay linkPreviewButton.isHidden = !isDisplay
} }
// container width // container width