NetNewsWire/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell...

266 lines
6.8 KiB
Swift
Raw Normal View History

//
// MasterTimelineTableViewCell.swift
// NetNewsWire
//
// Created by Brent Simmons on 8/31/15.
// Copyright © 2015 Ranchero Software, LLC. All rights reserved.
//
import UIKit
import RSCore
2019-10-22 09:35:47 +02:00
class MasterTimelineTableViewCell: VibrantTableViewCell {
private let titleView = MasterTimelineTableViewCell.multiLineUILabel()
2019-04-29 21:40:14 +02:00
private let summaryView = MasterTimelineTableViewCell.multiLineUILabel()
private let unreadIndicatorView = MasterUnreadIndicatorView(frame: CGRect.zero)
private let dateView = MasterTimelineTableViewCell.singleLineUILabel()
private let feedNameView = MasterTimelineTableViewCell.singleLineUILabel()
2019-09-18 00:00:23 +02:00
private lazy var avatarView = MasterTimelineAvatarView()
private lazy var starView = {
2019-04-26 13:30:00 +02:00
return NonIntrinsicImageView(image: AppAssets.timelineStarImage)
}()
2019-10-25 22:52:32 +02:00
private let separatorAccent: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
return view
}()
var cellData: MasterTimelineCellData! {
didSet {
updateSubviews()
}
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
override func applyThemeProperties() {
super.applyThemeProperties()
let highlightedTextColor = AppAssets.vibrantTextColor
titleView.highlightedTextColor = highlightedTextColor
summaryView.highlightedTextColor = highlightedTextColor
dateView.highlightedTextColor = highlightedTextColor
feedNameView.highlightedTextColor = highlightedTextColor
2019-10-25 22:52:32 +02:00
backgroundColor = AppAssets.timelineBackgroundColor
}
override var frame: CGRect {
didSet {
setNeedsLayout()
}
}
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
unreadIndicatorView.isSelected = isHighlighted || isSelected
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
unreadIndicatorView.isSelected = isHighlighted || isSelected
}
2019-04-29 21:40:14 +02:00
override func sizeThatFits(_ size: CGSize) -> CGSize {
let layout = updatedLayout(width: size.width)
return CGSize(width: size.width, height: layout.height)
2019-04-29 21:40:14 +02:00
}
override func layoutSubviews() {
super.layoutSubviews()
let layout = updatedLayout(width: bounds.width)
unreadIndicatorView.setFrameIfNotEqual(layout.unreadIndicatorRect)
starView.setFrameIfNotEqual(layout.starRect)
2019-09-18 00:00:23 +02:00
avatarView.setFrameIfNotEqual(layout.avatarImageRect)
setFrame(for: titleView, rect: layout.titleRect)
setFrame(for: summaryView, rect: layout.summaryRect)
feedNameView.setFrameIfNotEqual(layout.feedNameRect)
dateView.setFrameIfNotEqual(layout.dateRect)
2019-04-29 21:40:14 +02:00
separatorInset = layout.separatorInsets
2019-10-25 22:52:32 +02:00
if traitCollection.userInterfaceStyle == .light {
let separatorAccentRect = CGRect(x: safeAreaInsets.left, y: frame.height - 2, width: frame.width - safeAreaInsets.right - safeAreaInsets.left, height: 1)
separatorAccent.setFrameIfNotEqual(separatorAccentRect)
} else {
separatorAccent.setFrameIfNotEqual(.zero)
2019-10-25 22:52:32 +02:00
}
}
func setAvatarImage(_ image: UIImage) {
2019-09-18 00:00:23 +02:00
avatarView.image = image
}
}
// MARK: - Private
private extension MasterTimelineTableViewCell {
static func singleLineUILabel() -> UILabel {
let label = NonIntrinsicLabel()
label.lineBreakMode = .byTruncatingTail
label.allowsDefaultTighteningForTruncation = false
2019-04-29 21:40:14 +02:00
label.adjustsFontForContentSizeCategory = true
return label
}
static func multiLineUILabel() -> UILabel {
let label = NonIntrinsicLabel()
label.numberOfLines = 0
label.lineBreakMode = .byTruncatingTail
label.allowsDefaultTighteningForTruncation = false
2019-04-29 21:40:14 +02:00
label.adjustsFontForContentSizeCategory = true
return label
}
func setFrame(for label: UILabel, rect: CGRect) {
if Int(floor(rect.height)) == 0 || Int(floor(rect.width)) == 0 {
hideView(label)
} else {
showView(label)
label.setFrameIfNotEqual(rect)
}
}
func addSubviewAtInit(_ view: UIView, hidden: Bool) {
addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
view.isHidden = hidden
}
func commonInit() {
addSubviewAtInit(titleView, hidden: false)
addSubviewAtInit(summaryView, hidden: true)
addSubviewAtInit(unreadIndicatorView, hidden: true)
addSubviewAtInit(dateView, hidden: false)
addSubviewAtInit(feedNameView, hidden: true)
2019-09-18 00:00:23 +02:00
addSubviewAtInit(avatarView, hidden: true)
addSubviewAtInit(starView, hidden: true)
2019-10-25 22:52:32 +02:00
addSubviewAtInit(separatorAccent, hidden: false)
}
func updatedLayout(width: CGFloat) -> MasterTimelineCellLayout {
2019-04-30 00:19:08 +02:00
if UIApplication.shared.preferredContentSizeCategory.isAccessibilityCategory {
return MasterTimelineAccessibilityCellLayout(width: width, insets: safeAreaInsets, cellData: cellData)
2019-04-30 00:19:08 +02:00
} else {
return MasterTimelineDefaultCellLayout(width: width, insets: safeAreaInsets, cellData: cellData)
2019-04-30 00:19:08 +02:00
}
}
func updateTitleView() {
2019-04-30 00:19:08 +02:00
titleView.font = MasterTimelineDefaultCellLayout.titleFont
titleView.textColor = .label
updateTextFieldText(titleView, cellData?.title)
}
func updateSummaryView() {
2019-04-30 00:19:08 +02:00
summaryView.font = MasterTimelineDefaultCellLayout.summaryFont
summaryView.textColor = .label
2019-04-29 21:40:14 +02:00
updateTextFieldText(summaryView, cellData?.summary)
}
func updateDateView() {
2019-04-30 00:19:08 +02:00
dateView.font = MasterTimelineDefaultCellLayout.dateFont
dateView.textColor = .secondaryLabel
updateTextFieldText(dateView, cellData.dateString)
}
func updateTextFieldText(_ label: UILabel, _ text: String?) {
let s = text ?? ""
if label.text != s {
label.text = s
setNeedsLayout()
}
}
func updateFeedNameView() {
if cellData.showFeedName {
showView(feedNameView)
2019-04-30 00:19:08 +02:00
feedNameView.font = MasterTimelineDefaultCellLayout.feedNameFont
feedNameView.textColor = .secondaryLabel
updateTextFieldText(feedNameView, cellData.feedName)
} else {
hideView(feedNameView)
}
}
func updateUnreadIndicator() {
showOrHideView(unreadIndicatorView, cellData.read || cellData.starred)
unreadIndicatorView.setNeedsDisplay()
}
func updateStarView() {
showOrHideView(starView, !cellData.starred)
}
func updateAvatar() {
guard let image = cellData.avatar, cellData.showAvatar else {
makeAvatarEmpty()
return
}
2019-09-18 00:00:23 +02:00
showView(avatarView)
avatarView.layer.cornerRadius = MasterTimelineDefaultCellLayout.avatarCornerRadius
avatarView.clipsToBounds = true
2019-09-18 00:00:23 +02:00
if avatarView.image !== cellData.avatar {
avatarView.image = image
setNeedsLayout()
}
}
func makeAvatarEmpty() {
2019-09-18 00:00:23 +02:00
if avatarView.image != nil {
avatarView.image = nil
setNeedsLayout()
}
2019-09-18 00:00:23 +02:00
hideView(avatarView)
}
func hideView(_ view: UIView) {
if !view.isHidden {
view.isHidden = true
}
}
func showView(_ view: UIView) {
if view.isHidden {
view.isHidden = false
}
}
func showOrHideView(_ view: UIView, _ shouldHide: Bool) {
shouldHide ? hideView(view) : showView(view)
}
func updateSubviews() {
updateTitleView()
updateSummaryView()
updateDateView()
updateFeedNameView()
updateUnreadIndicator()
updateStarView()
updateAvatar()
}
}