Update Feeds to use higher resolution images when available. Issue #1208
This commit is contained in:
parent
55b9310f9c
commit
66b6d43408
|
@ -31,24 +31,9 @@ class MasterFeedTableViewCell : VibrantTableViewCell {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var faviconImage: UIImage? {
|
var avatarImage: UIImage? {
|
||||||
didSet {
|
didSet {
|
||||||
faviconImageView.image = faviconImage
|
avatarImageView.image = avatarImage
|
||||||
|
|
||||||
if self.traitCollection.userInterfaceStyle == .dark {
|
|
||||||
DispatchQueue.global(qos: .background).async {
|
|
||||||
if self.faviconImage?.isDark() ?? false {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.faviconImageView.backgroundColor = AppAssets.avatarBackgroundColor
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.faviconImageView.backgroundColor = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,12 +91,7 @@ class MasterFeedTableViewCell : VibrantTableViewCell {
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private let faviconImageView: UIImageView = {
|
private let avatarImageView = MasterTimelineAvatarView()
|
||||||
let imageView = NonIntrinsicImageView(image: AppAssets.faviconTemplateImage)
|
|
||||||
imageView.layer.cornerRadius = MasterFeedTableViewCellLayout.faviconCornerRadius
|
|
||||||
imageView.clipsToBounds = true
|
|
||||||
return imageView
|
|
||||||
}()
|
|
||||||
|
|
||||||
private let bottomSeparatorView: UIView = {
|
private let bottomSeparatorView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
|
@ -188,7 +168,7 @@ private extension MasterFeedTableViewCell {
|
||||||
|
|
||||||
func commonInit() {
|
func commonInit() {
|
||||||
addSubviewAtInit(unreadCountView)
|
addSubviewAtInit(unreadCountView)
|
||||||
addSubviewAtInit(faviconImageView)
|
addSubviewAtInit(avatarImageView)
|
||||||
addSubviewAtInit(titleView)
|
addSubviewAtInit(titleView)
|
||||||
addDisclosureView()
|
addDisclosureView()
|
||||||
addSubviewAtInit(bottomSeparatorView)
|
addSubviewAtInit(bottomSeparatorView)
|
||||||
|
@ -209,7 +189,7 @@ private extension MasterFeedTableViewCell {
|
||||||
}
|
}
|
||||||
|
|
||||||
func layoutWith(_ layout: MasterFeedTableViewCellLayout) {
|
func layoutWith(_ layout: MasterFeedTableViewCellLayout) {
|
||||||
faviconImageView.setFrameIfNotEqual(layout.faviconRect)
|
avatarImageView.setFrameIfNotEqual(layout.faviconRect)
|
||||||
titleView.setFrameIfNotEqual(layout.titleRect)
|
titleView.setFrameIfNotEqual(layout.titleRect)
|
||||||
unreadCountView.setFrameIfNotEqual(layout.unreadCountRect)
|
unreadCountView.setFrameIfNotEqual(layout.unreadCountRect)
|
||||||
disclosureButton?.setFrameIfNotEqual(layout.disclosureButtonRect)
|
disclosureButton?.setFrameIfNotEqual(layout.disclosureButtonRect)
|
||||||
|
@ -225,7 +205,7 @@ private extension MasterFeedTableViewCell {
|
||||||
|
|
||||||
UIView.animate(withDuration: duration) {
|
UIView.animate(withDuration: duration) {
|
||||||
self.disclosureButton?.tintColor = disclosureTintColor
|
self.disclosureButton?.tintColor = disclosureTintColor
|
||||||
self.faviconImageView.tintColor = faviconTintColor
|
self.avatarImageView.tintColor = faviconTintColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import RSCore
|
||||||
struct MasterFeedTableViewCellLayout {
|
struct MasterFeedTableViewCellLayout {
|
||||||
|
|
||||||
private static let editingControlIndent = CGFloat(integerLiteral: 40)
|
private static let editingControlIndent = CGFloat(integerLiteral: 40)
|
||||||
private static let imageSize = CGSize(width: 20, height: 20)
|
private static let imageSize = CGSize(width: 32, height: 32)
|
||||||
private static let imageMarginRight = CGFloat(integerLiteral: 11)
|
private static let imageMarginRight = CGFloat(integerLiteral: 11)
|
||||||
private static let unreadCountMarginLeft = CGFloat(integerLiteral: 8)
|
private static let unreadCountMarginLeft = CGFloat(integerLiteral: 8)
|
||||||
private static let unreadCountMarginRight = CGFloat(integerLiteral: 16)
|
private static let unreadCountMarginRight = CGFloat(integerLiteral: 16)
|
||||||
|
|
|
@ -53,6 +53,7 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil)
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(feedIconDidBecomeAvailable(_:)), name: .FeedIconDidBecomeAvailable, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(feedSettingDidChange(_:)), name: .FeedSettingDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(feedSettingDidChange(_:)), name: .FeedSettingDidChange, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(feedMetadataDidChange(_:)), name: .FeedMetadataDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(feedMetadataDidChange(_:)), name: .FeedMetadataDidChange, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(userDidAddFeed(_:)), name: .UserDidAddFeed, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(userDidAddFeed(_:)), name: .UserDidAddFeed, object: nil)
|
||||||
|
@ -106,7 +107,11 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func faviconDidBecomeAvailable(_ note: Notification) {
|
@objc func faviconDidBecomeAvailable(_ note: Notification) {
|
||||||
applyToAvailableCells(configureFavicon)
|
applyToAvailableCells(configureAvatar)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func feedIconDidBecomeAvailable(_ note: Notification) {
|
||||||
|
applyToAvailableCells(configureAvatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func feedSettingDidChange(_ note: Notification) {
|
@objc func feedSettingDidChange(_ note: Notification) {
|
||||||
|
@ -627,7 +632,7 @@ private extension MasterFeedViewController {
|
||||||
|
|
||||||
cell.name = nameFor(node)
|
cell.name = nameFor(node)
|
||||||
cell.unreadCount = coordinator.unreadCountFor(node)
|
cell.unreadCount = coordinator.unreadCountFor(node)
|
||||||
configureFavicon(cell, node)
|
configureAvatar(cell, node)
|
||||||
|
|
||||||
guard let indexPath = dataSource.indexPath(for: node) else { return }
|
guard let indexPath = dataSource.indexPath(for: node) else { return }
|
||||||
let rowsInSection = tableView.numberOfRows(inSection: indexPath.section)
|
let rowsInSection = tableView.numberOfRows(inSection: indexPath.section)
|
||||||
|
@ -639,14 +644,28 @@ private extension MasterFeedViewController {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureFavicon(_ cell: MasterFeedTableViewCell, _ node: Node) {
|
func configureAvatar(_ cell: MasterFeedTableViewCell, _ node: Node) {
|
||||||
cell.faviconImage = imageFor(node)
|
cell.avatarImage = imageFor(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
func imageFor(_ node: Node) -> UIImage? {
|
func imageFor(_ node: Node) -> UIImage? {
|
||||||
|
if let feed = node.representedObject as? Feed {
|
||||||
|
|
||||||
|
let feedIconImage = appDelegate.feedIconDownloader.icon(for: feed)
|
||||||
|
if feedIconImage != nil {
|
||||||
|
return feedIconImage
|
||||||
|
}
|
||||||
|
|
||||||
|
if let faviconImage = appDelegate.faviconDownloader.faviconAsAvatar(for: feed) {
|
||||||
|
return faviconImage
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if let smallIconProvider = node.representedObject as? SmallIconProvider {
|
if let smallIconProvider = node.representedObject as? SmallIconProvider {
|
||||||
return smallIconProvider.smallIcon
|
return smallIconProvider.smallIcon
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,30 @@ final class MasterTimelineAvatarView: UIView {
|
||||||
didSet {
|
didSet {
|
||||||
if image !== oldValue {
|
if image !== oldValue {
|
||||||
imageView.image = image
|
imageView.image = image
|
||||||
setNeedsLayout()
|
|
||||||
|
if self.traitCollection.userInterfaceStyle == .dark {
|
||||||
|
DispatchQueue.global(qos: .background).async {
|
||||||
|
if self.image?.isDark() ?? false {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.isDisconcernable = false
|
||||||
|
self.setNeedsLayout()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.isDisconcernable = true
|
||||||
|
self.setNeedsLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.setNeedsLayout()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var isDisconcernable = true
|
||||||
|
|
||||||
private let imageView: UIImageView = {
|
private let imageView: UIImageView = {
|
||||||
let imageView = NonIntrinsicImageView(image: AppAssets.faviconTemplateImage)
|
let imageView = NonIntrinsicImageView(image: AppAssets.faviconTemplateImage)
|
||||||
imageView.contentMode = .scaleAspectFit
|
imageView.contentMode = .scaleAspectFit
|
||||||
|
@ -27,10 +46,14 @@ final class MasterTimelineAvatarView: UIView {
|
||||||
return imageView
|
return imageView
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private var hasExposedVerticalBackground: Bool {
|
private var isVerticalBackgroundExposed: Bool {
|
||||||
return imageView.frame.size.height < bounds.size.height
|
return imageView.frame.size.height < bounds.size.height
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var isSymbolImage: Bool {
|
||||||
|
return imageView.image?.isSymbolImage ?? false
|
||||||
|
}
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
commonInit()
|
commonInit()
|
||||||
|
@ -51,7 +74,7 @@ final class MasterTimelineAvatarView: UIView {
|
||||||
|
|
||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
imageView.setFrameIfNotEqual(rectForImageView())
|
imageView.setFrameIfNotEqual(rectForImageView())
|
||||||
if hasExposedVerticalBackground {
|
if (isVerticalBackgroundExposed && !isSymbolImage) || !isDisconcernable {
|
||||||
backgroundColor = AppAssets.avatarBackgroundColor
|
backgroundColor = AppAssets.avatarBackgroundColor
|
||||||
} else {
|
} else {
|
||||||
backgroundColor = nil
|
backgroundColor = nil
|
||||||
|
|
Loading…
Reference in New Issue