feat: add favicon for NewsView

This commit is contained in:
CMK 2022-04-18 17:14:49 +08:00
parent 7772783555
commit 03af68924c
4 changed files with 67 additions and 3 deletions

View File

@ -55,6 +55,15 @@
"version": "1.2.0" "version": "1.2.0"
} }
}, },
{
"package": "FaviconFinder",
"repositoryURL": "https://github.com/will-lumley/FaviconFinder.git",
"state": {
"branch": null,
"revision": "1f74844f77f79b95c0bb0130b3a87d4f340e6d3a",
"version": "3.3.0"
}
},
{ {
"package": "FLAnimatedImage", "package": "FLAnimatedImage",
"repositoryURL": "https://github.com/Flipboard/FLAnimatedImage.git", "repositoryURL": "https://github.com/Flipboard/FLAnimatedImage.git",
@ -172,6 +181,15 @@
"version": "1.0.0" "version": "1.0.0"
} }
}, },
{
"package": "SwiftSoup",
"repositoryURL": "https://github.com/scinfu/SwiftSoup.git",
"state": {
"branch": null,
"revision": "41e7c263fb8c277e980ebcb9b0b5f6031d3d4886",
"version": "2.4.2"
}
},
{ {
"package": "Introspect", "package": "Introspect",
"repositoryURL": "https://github.com/siteline/SwiftUI-Introspect.git", "repositoryURL": "https://github.com/siteline/SwiftUI-Introspect.git",

View File

@ -37,7 +37,8 @@ let package = Package(
.package(url: "https://github.com/Alamofire/AlamofireImage.git", from: "4.1.0"), .package(url: "https://github.com/Alamofire/AlamofireImage.git", from: "4.1.0"),
.package(name: "NukeFLAnimatedImagePlugin", url: "https://github.com/kean/Nuke-FLAnimatedImage-Plugin.git", from: "8.0.0"), .package(name: "NukeFLAnimatedImagePlugin", url: "https://github.com/kean/Nuke-FLAnimatedImage-Plugin.git", from: "8.0.0"),
.package(name: "UITextView+Placeholder", url: "https://github.com/MainasuK/UITextView-Placeholder.git", from: "1.4.1"), .package(name: "UITextView+Placeholder", url: "https://github.com/MainasuK/UITextView-Placeholder.git", from: "1.4.1"),
.package(name: "Introspect", url: "https://github.com/siteline/SwiftUI-Introspect.git", from: "0.1.3") .package(name: "Introspect", url: "https://github.com/siteline/SwiftUI-Introspect.git", from: "0.1.3"),
.package(name: "FaviconFinder", url: "https://github.com/will-lumley/FaviconFinder.git", from: "3.2.2"),
], ],
targets: [ targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets are the basic building blocks of a package. A target can define a module or a test suite.
@ -95,6 +96,7 @@ let package = Package(
.product(name: "AlamofireImage", package: "AlamofireImage"), .product(name: "AlamofireImage", package: "AlamofireImage"),
.product(name: "MetaTextKit", package: "MetaTextKit"), .product(name: "MetaTextKit", package: "MetaTextKit"),
.product(name: "FLAnimatedImage", package: "FLAnimatedImage"), .product(name: "FLAnimatedImage", package: "FLAnimatedImage"),
.product(name: "FaviconFinder", package: "FaviconFinder"),
] ]
), ),
.testTarget( .testTarget(

View File

@ -9,9 +9,28 @@ import UIKit
import MastodonSDK import MastodonSDK
import MastodonLocalization import MastodonLocalization
import AlamofireImage import AlamofireImage
import FaviconFinder
extension NewsView { extension NewsView {
public func configure(link: Mastodon.Entity.Link) { public func configure(link: Mastodon.Entity.Link) {
let faviconPlaceholder = UIImage(systemName: "network")
providerFaviconImageView.image = faviconPlaceholder
if let url = URL(string: link.url) {
let token = providerFaviconImageView.tag
FaviconFinder(url: url).downloadFavicon { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let favicon):
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
guard self.providerFaviconImageView.tag == token else { return }
self.providerFaviconImageView.image = favicon.image
}
case .failure:
break
}
}
}
providerNameLabel.text = link.providerName providerNameLabel.text = link.providerName
headlineLabel.text = link.title headlineLabel.text = link.title
footnoteLabel.text = L10n.Plural.peopleTalking(link.talkingPeopleCount ?? 0) footnoteLabel.text = L10n.Plural.peopleTalking(link.talkingPeopleCount ?? 0)

View File

@ -12,6 +12,15 @@ public final class NewsView: UIView {
let container = UIStackView() let container = UIStackView()
let providerFaviconImageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.layer.masksToBounds = true
imageView.layer.cornerRadius = 2
imageView.layer.cornerCurve = .continuous
return imageView
}()
let providerNameLabel: UILabel = { let providerNameLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.font = UIFontMetrics(forTextStyle: .footnote).scaledFont(for: .systemFont(ofSize: 13, weight: .semibold)) label.font = UIFontMetrics(forTextStyle: .footnote).scaledFont(for: .systemFont(ofSize: 13, weight: .semibold))
@ -37,6 +46,7 @@ public final class NewsView: UIView {
let imageView = MediaView() let imageView = MediaView()
public func prepareForReuse() { public func prepareForReuse() {
providerFaviconImageView.tag = (0..<Int.max).randomElement() ?? -1
imageView.prepareForReuse() imageView.prepareForReuse()
} }
@ -72,12 +82,27 @@ extension NewsView {
textContainer.spacing = 4 textContainer.spacing = 4
container.addArrangedSubview(textContainer) container.addArrangedSubview(textContainer)
// providerContainer: H - [ providerFavIconImageView | providerNameLabel | (spacer) ] // providerContainer: H - [ providerFaviconImageView | providerNameLabel | (spacer) ]
let providerContainer = UIStackView() let providerContainer = UIStackView()
providerContainer.axis = .horizontal providerContainer.axis = .horizontal
providerContainer.spacing = 4
textContainer.addArrangedSubview(providerContainer) textContainer.addArrangedSubview(providerContainer)
providerFaviconImageView.translatesAutoresizingMaskIntoConstraints = false
providerContainer.addArrangedSubview(providerFaviconImageView)
providerContainer.addArrangedSubview(providerNameLabel) providerContainer.addArrangedSubview(providerNameLabel)
NSLayoutConstraint.activate([
providerFaviconImageView.heightAnchor.constraint(equalTo: providerNameLabel.heightAnchor, multiplier: 1.0).priority(.required - 10),
providerFaviconImageView.widthAnchor.constraint(equalTo: providerNameLabel.heightAnchor, multiplier: 1.0).priority(.required - 10),
])
// low priority for intrinsic size hugging
providerFaviconImageView.setContentHuggingPriority(.defaultLow - 10, for: .vertical)
providerFaviconImageView.setContentHuggingPriority(.defaultLow - 10, for: .horizontal)
// high priority but lower then layout constraint for size compression
providerFaviconImageView.setContentCompressionResistancePriority(.required - 11, for: .vertical)
providerFaviconImageView.setContentCompressionResistancePriority(.required - 11, for: .horizontal)
providerNameLabel.setContentCompressionResistancePriority(.required - 1, for: .vertical)
providerNameLabel.setContentHuggingPriority(.required - 1, for: .vertical)
// headlineLabel // headlineLabel
textContainer.addArrangedSubview(headlineLabel) textContainer.addArrangedSubview(headlineLabel)