implement dynamic type for master feed list
This commit is contained in:
parent
5fc3fee12d
commit
d7391b208d
|
@ -64,7 +64,6 @@
|
||||||
51C452772265091600C03939 /* MultilineUILabelSizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452702265091600C03939 /* MultilineUILabelSizer.swift */; };
|
51C452772265091600C03939 /* MultilineUILabelSizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452702265091600C03939 /* MultilineUILabelSizer.swift */; };
|
||||||
51C452782265091600C03939 /* MasterTimelineCellData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452712265091600C03939 /* MasterTimelineCellData.swift */; };
|
51C452782265091600C03939 /* MasterTimelineCellData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452712265091600C03939 /* MasterTimelineCellData.swift */; };
|
||||||
51C452792265091600C03939 /* MasterTimelineTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452722265091600C03939 /* MasterTimelineTableViewCell.swift */; };
|
51C452792265091600C03939 /* MasterTimelineTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452722265091600C03939 /* MasterTimelineTableViewCell.swift */; };
|
||||||
51C4527A2265091600C03939 /* SingleLineUILabelSizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452732265091600C03939 /* SingleLineUILabelSizer.swift */; };
|
|
||||||
51C4527B2265091600C03939 /* MasterUnreadIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452742265091600C03939 /* MasterUnreadIndicatorView.swift */; };
|
51C4527B2265091600C03939 /* MasterUnreadIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452742265091600C03939 /* MasterUnreadIndicatorView.swift */; };
|
||||||
51C4527C2265091600C03939 /* MasterTimelineCellLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452752265091600C03939 /* MasterTimelineCellLayout.swift */; };
|
51C4527C2265091600C03939 /* MasterTimelineCellLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C452752265091600C03939 /* MasterTimelineCellLayout.swift */; };
|
||||||
51C4527F2265092C00C03939 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C4527E2265092C00C03939 /* DetailViewController.swift */; };
|
51C4527F2265092C00C03939 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C4527E2265092C00C03939 /* DetailViewController.swift */; };
|
||||||
|
@ -117,6 +116,8 @@
|
||||||
51F85BF52273625800C787DC /* Bundle-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF42273625800C787DC /* Bundle-Extensions.swift */; };
|
51F85BF52273625800C787DC /* Bundle-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF42273625800C787DC /* Bundle-Extensions.swift */; };
|
||||||
51F85BF722749FA100C787DC /* UIFont-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF622749FA100C787DC /* UIFont-Extensions.swift */; };
|
51F85BF722749FA100C787DC /* UIFont-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF622749FA100C787DC /* UIFont-Extensions.swift */; };
|
||||||
51F85BF92274AA7B00C787DC /* UIBarButtonItem-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */; };
|
51F85BF92274AA7B00C787DC /* UIBarButtonItem-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */; };
|
||||||
|
51F85BFB2275D85000C787DC /* Array-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BFA2275D85000C787DC /* Array-Extensions.swift */; };
|
||||||
|
51F85BFD2275DCA800C787DC /* SingleLineUILabelSizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BFC2275DCA800C787DC /* SingleLineUILabelSizer.swift */; };
|
||||||
6581C73820CED60100F4AD34 /* SafariExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6581C73720CED60100F4AD34 /* SafariExtensionHandler.swift */; };
|
6581C73820CED60100F4AD34 /* SafariExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6581C73720CED60100F4AD34 /* SafariExtensionHandler.swift */; };
|
||||||
6581C73A20CED60100F4AD34 /* SafariExtensionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6581C73920CED60100F4AD34 /* SafariExtensionViewController.swift */; };
|
6581C73A20CED60100F4AD34 /* SafariExtensionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6581C73920CED60100F4AD34 /* SafariExtensionViewController.swift */; };
|
||||||
6581C73D20CED60100F4AD34 /* SafariExtensionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6581C73B20CED60100F4AD34 /* SafariExtensionViewController.xib */; };
|
6581C73D20CED60100F4AD34 /* SafariExtensionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6581C73B20CED60100F4AD34 /* SafariExtensionViewController.xib */; };
|
||||||
|
@ -651,7 +652,6 @@
|
||||||
51C452702265091600C03939 /* MultilineUILabelSizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilineUILabelSizer.swift; sourceTree = "<group>"; };
|
51C452702265091600C03939 /* MultilineUILabelSizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilineUILabelSizer.swift; sourceTree = "<group>"; };
|
||||||
51C452712265091600C03939 /* MasterTimelineCellData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MasterTimelineCellData.swift; sourceTree = "<group>"; };
|
51C452712265091600C03939 /* MasterTimelineCellData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MasterTimelineCellData.swift; sourceTree = "<group>"; };
|
||||||
51C452722265091600C03939 /* MasterTimelineTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MasterTimelineTableViewCell.swift; sourceTree = "<group>"; };
|
51C452722265091600C03939 /* MasterTimelineTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MasterTimelineTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
51C452732265091600C03939 /* SingleLineUILabelSizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleLineUILabelSizer.swift; sourceTree = "<group>"; };
|
|
||||||
51C452742265091600C03939 /* MasterUnreadIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MasterUnreadIndicatorView.swift; sourceTree = "<group>"; };
|
51C452742265091600C03939 /* MasterUnreadIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MasterUnreadIndicatorView.swift; sourceTree = "<group>"; };
|
||||||
51C452752265091600C03939 /* MasterTimelineCellLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MasterTimelineCellLayout.swift; sourceTree = "<group>"; };
|
51C452752265091600C03939 /* MasterTimelineCellLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MasterTimelineCellLayout.swift; sourceTree = "<group>"; };
|
||||||
51C4527E2265092C00C03939 /* DetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = "<group>"; };
|
51C4527E2265092C00C03939 /* DetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -672,6 +672,8 @@
|
||||||
51F85BF42273625800C787DC /* Bundle-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle-Extensions.swift"; sourceTree = "<group>"; };
|
51F85BF42273625800C787DC /* Bundle-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle-Extensions.swift"; sourceTree = "<group>"; };
|
||||||
51F85BF622749FA100C787DC /* UIFont-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont-Extensions.swift"; sourceTree = "<group>"; };
|
51F85BF622749FA100C787DC /* UIFont-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont-Extensions.swift"; sourceTree = "<group>"; };
|
||||||
51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem-Extensions.swift"; sourceTree = "<group>"; };
|
51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem-Extensions.swift"; sourceTree = "<group>"; };
|
||||||
|
51F85BFA2275D85000C787DC /* Array-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array-Extensions.swift"; sourceTree = "<group>"; };
|
||||||
|
51F85BFC2275DCA800C787DC /* SingleLineUILabelSizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleLineUILabelSizer.swift; sourceTree = "<group>"; };
|
||||||
6581C73320CED60000F4AD34 /* Subscribe to Feed.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Subscribe to Feed.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
6581C73320CED60000F4AD34 /* Subscribe to Feed.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Subscribe to Feed.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
6581C73420CED60100F4AD34 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
6581C73420CED60100F4AD34 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||||
6581C73720CED60100F4AD34 /* SafariExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariExtensionHandler.swift; sourceTree = "<group>"; };
|
6581C73720CED60100F4AD34 /* SafariExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariExtensionHandler.swift; sourceTree = "<group>"; };
|
||||||
|
@ -972,6 +974,7 @@
|
||||||
51C45245226506C800C03939 /* Extensions */ = {
|
51C45245226506C800C03939 /* Extensions */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
51F85BFA2275D85000C787DC /* Array-Extensions.swift */,
|
||||||
51F85BF42273625800C787DC /* Bundle-Extensions.swift */,
|
51F85BF42273625800C787DC /* Bundle-Extensions.swift */,
|
||||||
5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */,
|
5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */,
|
||||||
5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */,
|
5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */,
|
||||||
|
@ -1021,7 +1024,7 @@
|
||||||
51C452712265091600C03939 /* MasterTimelineCellData.swift */,
|
51C452712265091600C03939 /* MasterTimelineCellData.swift */,
|
||||||
51C452752265091600C03939 /* MasterTimelineCellLayout.swift */,
|
51C452752265091600C03939 /* MasterTimelineCellLayout.swift */,
|
||||||
51C452742265091600C03939 /* MasterUnreadIndicatorView.swift */,
|
51C452742265091600C03939 /* MasterUnreadIndicatorView.swift */,
|
||||||
51C452732265091600C03939 /* SingleLineUILabelSizer.swift */,
|
51F85BFC2275DCA800C787DC /* SingleLineUILabelSizer.swift */,
|
||||||
51C452702265091600C03939 /* MultilineUILabelSizer.swift */,
|
51C452702265091600C03939 /* MultilineUILabelSizer.swift */,
|
||||||
);
|
);
|
||||||
path = Cell;
|
path = Cell;
|
||||||
|
@ -2233,6 +2236,7 @@
|
||||||
51C45291226509C800C03939 /* SmartFeed.swift in Sources */,
|
51C45291226509C800C03939 /* SmartFeed.swift in Sources */,
|
||||||
51C452A722650A3D00C03939 /* RSImage-Extensions.swift in Sources */,
|
51C452A722650A3D00C03939 /* RSImage-Extensions.swift in Sources */,
|
||||||
51C45269226508F600C03939 /* MasterFeedTableViewCell.swift in Sources */,
|
51C45269226508F600C03939 /* MasterFeedTableViewCell.swift in Sources */,
|
||||||
|
51F85BFD2275DCA800C787DC /* SingleLineUILabelSizer.swift in Sources */,
|
||||||
51C4528F226509BD00C03939 /* UnreadFeed.swift in Sources */,
|
51C4528F226509BD00C03939 /* UnreadFeed.swift in Sources */,
|
||||||
5183CCDD226F1F5C0010922C /* NavigationProgressView.swift in Sources */,
|
5183CCDD226F1F5C0010922C /* NavigationProgressView.swift in Sources */,
|
||||||
51C452772265091600C03939 /* MultilineUILabelSizer.swift in Sources */,
|
51C452772265091600C03939 /* MultilineUILabelSizer.swift in Sources */,
|
||||||
|
@ -2278,11 +2282,11 @@
|
||||||
5115CAF42266301400B21BCE /* AddContainerViewController.swift in Sources */,
|
5115CAF42266301400B21BCE /* AddContainerViewController.swift in Sources */,
|
||||||
51C45297226509E300C03939 /* DefaultFeedsImporter.swift in Sources */,
|
51C45297226509E300C03939 /* DefaultFeedsImporter.swift in Sources */,
|
||||||
512E094D2268B8AB00BDCFDD /* DeleteCommand.swift in Sources */,
|
512E094D2268B8AB00BDCFDD /* DeleteCommand.swift in Sources */,
|
||||||
|
51F85BFB2275D85000C787DC /* Array-Extensions.swift in Sources */,
|
||||||
51C452AC22650FD200C03939 /* AppNotifications.swift in Sources */,
|
51C452AC22650FD200C03939 /* AppNotifications.swift in Sources */,
|
||||||
51C452762265091600C03939 /* MasterTimelineViewController.swift in Sources */,
|
51C452762265091600C03939 /* MasterTimelineViewController.swift in Sources */,
|
||||||
5183CCE9226F68D90010922C /* RefreshTimer.swift in Sources */,
|
5183CCE9226F68D90010922C /* RefreshTimer.swift in Sources */,
|
||||||
51C452882265093600C03939 /* AddFeedViewController.swift in Sources */,
|
51C452882265093600C03939 /* AddFeedViewController.swift in Sources */,
|
||||||
51C4527A2265091600C03939 /* SingleLineUILabelSizer.swift in Sources */,
|
|
||||||
51C4529B22650A1000C03939 /* FaviconDownloader.swift in Sources */,
|
51C4529B22650A1000C03939 /* FaviconDownloader.swift in Sources */,
|
||||||
5183CCE3226F314C0010922C /* ProgressTableViewController.swift in Sources */,
|
5183CCE3226F314C0010922C /* ProgressTableViewController.swift in Sources */,
|
||||||
512E09012268907400BDCFDD /* MasterFeedTableViewSectionHeader.swift in Sources */,
|
512E09012268907400BDCFDD /* MasterFeedTableViewSectionHeader.swift in Sources */,
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// Array-Extensions.swift
|
||||||
|
// NetNewsWire-iOS
|
||||||
|
//
|
||||||
|
// Created by Maurice Parker on 4/28/19.
|
||||||
|
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension Array where Element == CGRect {
|
||||||
|
|
||||||
|
func maxY() -> CGFloat {
|
||||||
|
|
||||||
|
var y: CGFloat = 0.0
|
||||||
|
self.forEach { y = Swift.max(y, $0.maxY) }
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,7 +19,8 @@ class MasterFeedTableViewCell : UITableViewCell {
|
||||||
|
|
||||||
weak var delegate: MasterFeedTableViewCellDelegate?
|
weak var delegate: MasterFeedTableViewCellDelegate?
|
||||||
var allowDisclosureSelection = false
|
var allowDisclosureSelection = false
|
||||||
|
private var layout: MasterFeedTableViewCellLayout?
|
||||||
|
|
||||||
override var accessibilityLabel: String? {
|
override var accessibilityLabel: String? {
|
||||||
set {}
|
set {}
|
||||||
get {
|
get {
|
||||||
|
@ -52,6 +53,7 @@ class MasterFeedTableViewCell : UITableViewCell {
|
||||||
var shouldShowImage = false {
|
var shouldShowImage = false {
|
||||||
didSet {
|
didSet {
|
||||||
if shouldShowImage != oldValue {
|
if shouldShowImage != oldValue {
|
||||||
|
resetLayout()
|
||||||
setNeedsLayout()
|
setNeedsLayout()
|
||||||
}
|
}
|
||||||
faviconImageView.image = shouldShowImage ? faviconImage : nil
|
faviconImageView.image = shouldShowImage ? faviconImage : nil
|
||||||
|
@ -66,6 +68,7 @@ class MasterFeedTableViewCell : UITableViewCell {
|
||||||
if unreadCountView.unreadCount != newValue {
|
if unreadCountView.unreadCount != newValue {
|
||||||
unreadCountView.unreadCount = newValue
|
unreadCountView.unreadCount = newValue
|
||||||
unreadCountView.isHidden = (newValue < 1)
|
unreadCountView.isHidden = (newValue < 1)
|
||||||
|
resetLayout()
|
||||||
setNeedsLayout()
|
setNeedsLayout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +81,7 @@ class MasterFeedTableViewCell : UITableViewCell {
|
||||||
set {
|
set {
|
||||||
if titleView.text != newValue {
|
if titleView.text != newValue {
|
||||||
titleView.text = newValue
|
titleView.text = newValue
|
||||||
|
resetLayout()
|
||||||
setNeedsDisplay()
|
setNeedsDisplay()
|
||||||
setNeedsLayout()
|
setNeedsLayout()
|
||||||
}
|
}
|
||||||
|
@ -87,7 +91,6 @@ class MasterFeedTableViewCell : UITableViewCell {
|
||||||
private let titleView: UILabel = {
|
private let titleView: UILabel = {
|
||||||
let label = NonIntrinsicLabel()
|
let label = NonIntrinsicLabel()
|
||||||
label.numberOfLines = 0
|
label.numberOfLines = 0
|
||||||
label.lineBreakMode = .byTruncatingTail
|
|
||||||
label.allowsDefaultTighteningForTruncation = false
|
label.allowsDefaultTighteningForTruncation = false
|
||||||
label.adjustsFontForContentSizeCategory = true
|
label.adjustsFontForContentSizeCategory = true
|
||||||
label.font = .preferredFont(forTextStyle: .body)
|
label.font = .preferredFont(forTextStyle: .body)
|
||||||
|
@ -98,7 +101,7 @@ class MasterFeedTableViewCell : UITableViewCell {
|
||||||
return UIImageView(image: AppAssets.feedImage)
|
return UIImageView(image: AppAssets.feedImage)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private let unreadCountView = MasterFeedUnreadCountView(frame: CGRect.zero)
|
private var unreadCountView = MasterFeedUnreadCountView(frame: CGRect.zero)
|
||||||
private var showingEditControl = false
|
private var showingEditControl = false
|
||||||
private var disclosureButton: UIButton?
|
private var disclosureButton: UIButton?
|
||||||
|
|
||||||
|
@ -107,16 +110,30 @@ class MasterFeedTableViewCell : UITableViewCell {
|
||||||
commonInit()
|
commonInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func prepareForReuse() {
|
||||||
|
layout = nil
|
||||||
|
unreadCountView.setNeedsLayout()
|
||||||
|
unreadCountView.setNeedsDisplay()
|
||||||
|
}
|
||||||
|
|
||||||
override func willTransition(to state: UITableViewCell.StateMask) {
|
override func willTransition(to state: UITableViewCell.StateMask) {
|
||||||
super.willTransition(to: state)
|
super.willTransition(to: state)
|
||||||
showingEditControl = state.contains(.showingEditControl)
|
showingEditControl = state.contains(.showingEditControl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func sizeThatFits(_ size: CGSize) -> CGSize {
|
||||||
|
if layout == nil {
|
||||||
|
resetLayout()
|
||||||
|
}
|
||||||
|
return CGSize(width: bounds.width, height: layout!.height)
|
||||||
|
}
|
||||||
|
|
||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
let shouldShowDisclosure = !(showingEditControl && showsReorderControl)
|
if layout == nil {
|
||||||
let layout = MasterFeedTableViewCellLayout(cellSize: bounds.size, insets: safeAreaInsets, shouldShowImage: shouldShowImage, label: titleView, unreadCountView: unreadCountView, showingEditingControl: showingEditControl, indent: indentationLevel == 1, shouldShowDisclosure: shouldShowDisclosure)
|
resetLayout()
|
||||||
layoutWith(layout)
|
}
|
||||||
|
layoutWith(layout!)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func buttonPressed(_ sender: UIButton) {
|
@objc func buttonPressed(_ sender: UIButton) {
|
||||||
|
@ -168,6 +185,11 @@ private extension MasterFeedTableViewCell {
|
||||||
view.translatesAutoresizingMaskIntoConstraints = false
|
view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resetLayout() {
|
||||||
|
let shouldShowDisclosure = !(showingEditControl && showsReorderControl)
|
||||||
|
layout = MasterFeedTableViewCellLayout(cellSize: bounds.size, insets: safeAreaInsets, shouldShowImage: shouldShowImage, label: titleView, unreadCountView: unreadCountView, showingEditingControl: showingEditControl, indent: indentationLevel == 1, shouldShowDisclosure: shouldShowDisclosure)
|
||||||
|
}
|
||||||
|
|
||||||
func layoutWith(_ layout: MasterFeedTableViewCellLayout) {
|
func layoutWith(_ layout: MasterFeedTableViewCellLayout) {
|
||||||
faviconImageView.setFrameIfNotEqual(layout.faviconRect)
|
faviconImageView.setFrameIfNotEqual(layout.faviconRect)
|
||||||
titleView.setFrameIfNotEqual(layout.titleRect)
|
titleView.setFrameIfNotEqual(layout.titleRect)
|
||||||
|
|
|
@ -25,6 +25,8 @@ struct MasterFeedTableViewCellLayout {
|
||||||
let unreadCountRect: CGRect
|
let unreadCountRect: CGRect
|
||||||
let disclosureButtonRect: CGRect
|
let disclosureButtonRect: CGRect
|
||||||
|
|
||||||
|
let height: CGFloat
|
||||||
|
|
||||||
init(cellSize: CGSize, insets: UIEdgeInsets, shouldShowImage: Bool, label: UILabel, unreadCountView: MasterFeedUnreadCountView, showingEditingControl: Bool, indent: Bool, shouldShowDisclosure: Bool) {
|
init(cellSize: CGSize, insets: UIEdgeInsets, shouldShowImage: Bool, label: UILabel, unreadCountView: MasterFeedUnreadCountView, showingEditingControl: Bool, indent: Bool, shouldShowDisclosure: Bool) {
|
||||||
|
|
||||||
var initialIndent = MasterFeedTableViewCellLayout.marginLeft + insets.left
|
var initialIndent = MasterFeedTableViewCellLayout.marginLeft + insets.left
|
||||||
|
@ -41,21 +43,7 @@ struct MasterFeedTableViewCellLayout {
|
||||||
var rFavicon = CGRect.zero
|
var rFavicon = CGRect.zero
|
||||||
if shouldShowImage {
|
if shouldShowImage {
|
||||||
rFavicon = CGRect(x: bounds.origin.x, y: 0.0, width: MasterFeedTableViewCellLayout.imageSize.width, height: MasterFeedTableViewCellLayout.imageSize.height)
|
rFavicon = CGRect(x: bounds.origin.x, y: 0.0, width: MasterFeedTableViewCellLayout.imageSize.width, height: MasterFeedTableViewCellLayout.imageSize.height)
|
||||||
rFavicon = MasterFeedTableViewCellLayout.centerVertically(rFavicon, bounds)
|
|
||||||
}
|
}
|
||||||
self.faviconRect = rFavicon
|
|
||||||
|
|
||||||
// Title
|
|
||||||
let labelSize = SingleLineUILabelSizer.size(for: label.text ?? "", font: label.font!)
|
|
||||||
|
|
||||||
var rLabel = CGRect(x: 0.0, y: 0.0, width: labelSize.width, height: labelSize.height)
|
|
||||||
if shouldShowImage {
|
|
||||||
rLabel.origin.x = rFavicon.maxX + MasterFeedTableViewCellLayout.imageMarginRight
|
|
||||||
} else {
|
|
||||||
rLabel.origin.x = bounds.minX
|
|
||||||
}
|
|
||||||
|
|
||||||
rLabel = MasterFeedTableViewCellLayout.centerVertically(rLabel, bounds)
|
|
||||||
|
|
||||||
// Unread Count
|
// Unread Count
|
||||||
let unreadCountSize = unreadCountView.intrinsicContentSize
|
let unreadCountSize = unreadCountView.intrinsicContentSize
|
||||||
|
@ -63,44 +51,54 @@ struct MasterFeedTableViewCellLayout {
|
||||||
|
|
||||||
var rUnread = CGRect.zero
|
var rUnread = CGRect.zero
|
||||||
if !unreadCountIsHidden {
|
if !unreadCountIsHidden {
|
||||||
|
|
||||||
rUnread.size = unreadCountSize
|
rUnread.size = unreadCountSize
|
||||||
rUnread.origin.x = bounds.maxX -
|
rUnread.origin.x = bounds.maxX -
|
||||||
(unreadCountSize.width + MasterFeedTableViewCellLayout.unreadCountMarginRight + MasterFeedTableViewCellLayout.disclosureButtonSize.width)
|
(unreadCountSize.width + MasterFeedTableViewCellLayout.unreadCountMarginRight + MasterFeedTableViewCellLayout.disclosureButtonSize.width)
|
||||||
rUnread = MasterFeedTableViewCellLayout.centerVertically(rUnread, bounds)
|
|
||||||
|
|
||||||
// Cap the Title width based on the unread indicator button
|
|
||||||
let labelMaxX = rUnread.minX - MasterFeedTableViewCellLayout.unreadCountMarginLeft
|
|
||||||
if rLabel.maxX > labelMaxX {
|
|
||||||
rLabel.size.width = labelMaxX - rLabel.minX
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
self.unreadCountRect = rUnread
|
|
||||||
|
|
||||||
// Disclosure Button
|
// Disclosure Button
|
||||||
var rDisclosure = CGRect.zero
|
var rDisclosure = CGRect.zero
|
||||||
if shouldShowDisclosure {
|
if shouldShowDisclosure {
|
||||||
|
|
||||||
rDisclosure.size = MasterFeedTableViewCellLayout.disclosureButtonSize
|
rDisclosure.size = MasterFeedTableViewCellLayout.disclosureButtonSize
|
||||||
rDisclosure.origin.x = bounds.maxX - MasterFeedTableViewCellLayout.disclosureButtonSize.width
|
rDisclosure.origin.x = bounds.maxX - MasterFeedTableViewCellLayout.disclosureButtonSize.width
|
||||||
rDisclosure = MasterFeedTableViewCellLayout.centerVertically(rDisclosure, bounds)
|
|
||||||
|
|
||||||
// Cap the Title width based on the disclosure button
|
|
||||||
let labelMaxX = rDisclosure.minX
|
|
||||||
if rLabel.maxX > labelMaxX {
|
|
||||||
rLabel.size.width = labelMaxX - rLabel.minX
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
self.disclosureButtonRect = rDisclosure
|
|
||||||
|
|
||||||
|
// Title
|
||||||
|
let labelWidth = bounds.width - (rFavicon.width + MasterFeedTableViewCellLayout.imageMarginRight + MasterFeedTableViewCellLayout.unreadCountMarginLeft + rUnread.width + MasterFeedTableViewCellLayout.unreadCountMarginRight + rDisclosure.width)
|
||||||
|
let labelSizeInfo = MultilineUILabelSizer.size(for: label.text ?? "", font: label.font, numberOfLines: 0, width: Int(floor(labelWidth)))
|
||||||
|
|
||||||
// Cap the Title width based on total width
|
var rLabel = CGRect(x: 0.0, y: 0.0, width: labelSizeInfo.size.width, height: labelSizeInfo.size.height)
|
||||||
if rLabel.maxX > bounds.maxX {
|
if shouldShowImage {
|
||||||
rLabel.size.width = bounds.maxX - rLabel.minX
|
rLabel.origin.x = rFavicon.maxX + MasterFeedTableViewCellLayout.imageMarginRight
|
||||||
|
} else {
|
||||||
|
rLabel.origin.x = bounds.minX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine cell height
|
||||||
|
let cellHeight = [rFavicon, rLabel, rUnread, rDisclosure].maxY()
|
||||||
|
|
||||||
|
// Center in Cell
|
||||||
|
let newBounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.width, height: cellHeight)
|
||||||
|
|
||||||
|
if shouldShowImage {
|
||||||
|
rFavicon = MasterFeedTableViewCellLayout.centerVertically(rFavicon, newBounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !unreadCountIsHidden {
|
||||||
|
rUnread = MasterFeedTableViewCellLayout.centerVertically(rUnread, newBounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldShowDisclosure {
|
||||||
|
rDisclosure = MasterFeedTableViewCellLayout.centerVertically(rDisclosure, newBounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
rLabel = MasterFeedTableViewCellLayout.centerVertically(rLabel, newBounds)
|
||||||
|
|
||||||
|
// Assign the properties
|
||||||
|
self.height = cellHeight
|
||||||
|
self.faviconRect = rFavicon
|
||||||
|
self.unreadCountRect = rUnread
|
||||||
|
self.disclosureButtonRect = rDisclosure
|
||||||
self.titleRect = rLabel
|
self.titleRect = rLabel
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ import UIKit
|
||||||
|
|
||||||
class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView {
|
class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView {
|
||||||
|
|
||||||
|
private var layout: MasterFeedTableViewCellLayout?
|
||||||
|
|
||||||
override var accessibilityLabel: String? {
|
override var accessibilityLabel: String? {
|
||||||
set {}
|
set {}
|
||||||
get {
|
get {
|
||||||
|
@ -57,7 +59,6 @@ class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView {
|
||||||
private let titleView: UILabel = {
|
private let titleView: UILabel = {
|
||||||
let label = NonIntrinsicLabel()
|
let label = NonIntrinsicLabel()
|
||||||
label.numberOfLines = 0
|
label.numberOfLines = 0
|
||||||
label.lineBreakMode = .byTruncatingTail
|
|
||||||
label.allowsDefaultTighteningForTruncation = false
|
label.allowsDefaultTighteningForTruncation = false
|
||||||
label.adjustsFontForContentSizeCategory = true
|
label.adjustsFontForContentSizeCategory = true
|
||||||
label.font = .preferredFont(forTextStyle: .body)
|
label.font = .preferredFont(forTextStyle: .body)
|
||||||
|
@ -81,12 +82,20 @@ class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView {
|
||||||
commonInit()
|
commonInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func sizeThatFits(_ size: CGSize) -> CGSize {
|
||||||
|
if layout == nil {
|
||||||
|
resetLayout()
|
||||||
|
}
|
||||||
|
return CGSize(width: bounds.width, height: layout!.height)
|
||||||
|
}
|
||||||
|
|
||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
let layout = MasterFeedTableViewCellLayout(cellSize: bounds.size, insets: safeAreaInsets, shouldShowImage: false, label: titleView, unreadCountView: unreadCountView, showingEditingControl: false, indent: true, shouldShowDisclosure: true)
|
if layout == nil {
|
||||||
layoutWith(layout)
|
resetLayout()
|
||||||
|
}
|
||||||
|
layoutWith(layout!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +124,10 @@ private extension MasterFeedTableViewSectionHeader {
|
||||||
view.translatesAutoresizingMaskIntoConstraints = false
|
view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resetLayout() {
|
||||||
|
layout = MasterFeedTableViewCellLayout(cellSize: bounds.size, insets: safeAreaInsets, shouldShowImage: false, label: titleView, unreadCountView: unreadCountView, showingEditingControl: false, indent: true, shouldShowDisclosure: true)
|
||||||
|
}
|
||||||
|
|
||||||
func layoutWith(_ layout: MasterFeedTableViewCellLayout) {
|
func layoutWith(_ layout: MasterFeedTableViewCellLayout) {
|
||||||
titleView.setFrameIfNotEqual(layout.titleRect)
|
titleView.setFrameIfNotEqual(layout.titleRect)
|
||||||
unreadCountView.setFrameIfNotEqual(layout.unreadCountRect)
|
unreadCountView.setFrameIfNotEqual(layout.unreadCountRect)
|
||||||
|
|
|
@ -38,6 +38,7 @@ class MasterFeedViewController: ProgressTableViewController, UndoableCommandRunn
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(backingStoresDidRebuild(_:)), name: .BackingStoresDidRebuild, object: navState)
|
NotificationCenter.default.addObserver(self, selector: #selector(backingStoresDidRebuild(_:)), name: .BackingStoresDidRebuild, object: navState)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(masterSelectionDidChange(_:)), name: .MasterSelectionDidChange, object: navState)
|
NotificationCenter.default.addObserver(self, selector: #selector(masterSelectionDidChange(_:)), name: .MasterSelectionDidChange, object: navState)
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
||||||
|
|
||||||
refreshControl = UIRefreshControl()
|
refreshControl = UIRefreshControl()
|
||||||
refreshControl!.addTarget(self, action: #selector(refreshAccounts(_:)), for: .valueChanged)
|
refreshControl!.addTarget(self, action: #selector(refreshAccounts(_:)), for: .valueChanged)
|
||||||
|
@ -141,6 +142,10 @@ class MasterFeedViewController: ProgressTableViewController, UndoableCommandRunn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func contentSizeCategoryDidChange(_ note: Notification) {
|
||||||
|
tableView.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: Table View
|
// MARK: Table View
|
||||||
|
|
||||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||||
|
@ -152,7 +157,27 @@ class MasterFeedViewController: ProgressTableViewController, UndoableCommandRunn
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||||||
return CGFloat(integerLiteral: 44)
|
|
||||||
|
guard let nameProvider = navState.rootNode.childAtIndex(section)?.representedObject as? DisplayNameProvider else {
|
||||||
|
return 44
|
||||||
|
}
|
||||||
|
|
||||||
|
let headerView = MasterFeedTableViewSectionHeader()
|
||||||
|
headerView.name = nameProvider.nameForDisplay
|
||||||
|
|
||||||
|
guard let sectionNode = navState.rootNode.childAtIndex(section) else {
|
||||||
|
return 44
|
||||||
|
}
|
||||||
|
|
||||||
|
if let account = sectionNode.representedObject as? Account {
|
||||||
|
headerView.unreadCount = account.unreadCount
|
||||||
|
} else {
|
||||||
|
headerView.unreadCount = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
let size = headerView.sizeThatFits(CGSize.zero)
|
||||||
|
return size.height
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
||||||
|
|
|
@ -243,14 +243,3 @@ private extension MasterTimelineCellLayout {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension Array where Element == CGRect {
|
|
||||||
|
|
||||||
func maxY() -> CGFloat {
|
|
||||||
|
|
||||||
var y: CGFloat = 0.0
|
|
||||||
self.forEach { y = Swift.max(y, $0.maxY) }
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -98,9 +98,12 @@ private extension MultilineUILabelSizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
var height = MultilineUILabelSizer.calculateHeight(string, width, font)
|
var height = MultilineUILabelSizer.calculateHeight(string, width, font)
|
||||||
let maxHeight = singleLineHeightEstimate * numberOfLines
|
|
||||||
if height > maxHeight {
|
if numberOfLines != 0 {
|
||||||
height = maxHeight
|
let maxHeight = singleLineHeightEstimate * numberOfLines
|
||||||
|
if height > maxHeight {
|
||||||
|
height = maxHeight
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cache[string]![width] = height
|
cache[string]![width] = height
|
||||||
|
|
Loading…
Reference in New Issue