Made number of lines in timeline configurable.

This commit is contained in:
Maurice Parker 2019-04-29 15:29:00 -05:00
parent b4e2acb5ce
commit 0451ed9e70
9 changed files with 153 additions and 14 deletions

View File

@ -109,6 +109,7 @@
51EF0F77227716200050506E /* FaviconGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F76227716200050506E /* FaviconGenerator.swift */; };
51EF0F79227716380050506E /* ColorHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F78227716380050506E /* ColorHash.swift */; };
51EF0F7A22771B890050506E /* ColorHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F78227716380050506E /* ColorHash.swift */; };
51EF0F7C2277919E0050506E /* TimelineNumberOfLinesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F7B2277919E0050506E /* TimelineNumberOfLinesViewController.swift */; };
51F85BE5227217D000C787DC /* RefreshIntervalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BDB2272162F00C787DC /* RefreshIntervalViewController.swift */; };
51F85BE7227245FC00C787DC /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BE6227245FC00C787DC /* AboutViewController.swift */; };
51F85BEB22724CB600C787DC /* About.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 51F85BEA22724CB600C787DC /* About.rtf */; };
@ -667,6 +668,7 @@
51EC114B2149FE3300B296E3 /* FolderTreeMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FolderTreeMenu.swift; path = AddFeed/FolderTreeMenu.swift; sourceTree = "<group>"; };
51EF0F76227716200050506E /* FaviconGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FaviconGenerator.swift; sourceTree = "<group>"; };
51EF0F78227716380050506E /* ColorHash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorHash.swift; sourceTree = "<group>"; };
51EF0F7B2277919E0050506E /* TimelineNumberOfLinesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineNumberOfLinesViewController.swift; sourceTree = "<group>"; };
51F85BDB2272162F00C787DC /* RefreshIntervalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshIntervalViewController.swift; sourceTree = "<group>"; };
51F85BE6227245FC00C787DC /* AboutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = "<group>"; };
51F85BEA22724CB600C787DC /* About.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = About.rtf; sourceTree = "<group>"; };
@ -970,8 +972,9 @@
children = (
5183CCEC22711DCE0010922C /* Settings.storyboard */,
5183CCEE227125970010922C /* SettingsViewController.swift */,
51F85BDB2272162F00C787DC /* RefreshIntervalViewController.swift */,
51F85BE6227245FC00C787DC /* AboutViewController.swift */,
51F85BDB2272162F00C787DC /* RefreshIntervalViewController.swift */,
51EF0F7B2277919E0050506E /* TimelineNumberOfLinesViewController.swift */,
);
path = Settings;
sourceTree = "<group>";
@ -2272,6 +2275,7 @@
84F3EE1B20DEC97E003FADEB /* HTMLFeedFinder.swift in Sources */,
51C452A222650A1900C03939 /* RSHTMLMetadata+Extension.swift in Sources */,
5183CCE5226F4DFA0010922C /* RefreshInterval.swift in Sources */,
51EF0F7C2277919E0050506E /* TimelineNumberOfLinesViewController.swift in Sources */,
51C4529D22650A1000C03939 /* FaviconURLFinder.swift in Sources */,
51C45258226508CF00C03939 /* AppAssets.swift in Sources */,
51C4527C2265091600C03939 /* MasterTimelineCellLayout.swift in Sources */,

View File

@ -15,6 +15,7 @@ struct AppDefaults {
static let timelineSortDirection = "timelineSortDirection"
static let refreshInterval = "refreshInterval"
static let lastRefresh = "lastRefresh"
static let timelineNumberOfLines = "timelineNumberOfLines"
}
static let isFirstRun: Bool = {
@ -53,8 +54,17 @@ struct AppDefaults {
}
}
static var timelineNumberOfLines: Int {
get {
return int(for: Key.timelineNumberOfLines)
}
set {
setInt(for: Key.timelineNumberOfLines, newValue)
}
}
static func registerDefaults() {
let defaults: [String : Any] = [Key.timelineSortDirection: ComparisonResult.orderedDescending.rawValue, Key.refreshInterval: RefreshInterval.everyHour.rawValue]
let defaults: [String : Any] = [Key.timelineSortDirection: ComparisonResult.orderedDescending.rawValue, Key.refreshInterval: RefreshInterval.everyHour.rawValue, Key.timelineNumberOfLines: 2]
UserDefaults.standard.register(defaults: defaults)
}

View File

@ -21,8 +21,9 @@ struct MasterTimelineCellData {
let featuredImage: UIImage? // image from within the article
let read: Bool
let starred: Bool
let numberOfLines: Int
init(article: Article, showFeedName: Bool, feedName: String?, avatar: UIImage?, showAvatar: Bool, featuredImage: UIImage?) {
init(article: Article, showFeedName: Bool, feedName: String?, avatar: UIImage?, showAvatar: Bool, featuredImage: UIImage?, numberOfLines: Int) {
self.title = TimelineStringFormatter.truncatedTitle(article)
self.summary = TimelineStringFormatter.truncatedSummary(article)
@ -44,6 +45,8 @@ struct MasterTimelineCellData {
self.read = article.status.read
self.starred = article.status.starred
self.numberOfLines = numberOfLines
}
init() { //Empty
@ -57,6 +60,7 @@ struct MasterTimelineCellData {
self.featuredImage = nil
self.read = true
self.starred = false
self.numberOfLines = 0
}
}

View File

@ -11,7 +11,6 @@ import RSCore
struct MasterTimelineCellLayout {
static let maxNumberOfLines = 2
static let cellPadding = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)
static let unreadCircleMarginLeft = CGFloat(integerLiteral: 8)
@ -154,7 +153,7 @@ private extension MasterTimelineCellLayout {
r.origin = point
let sizeInfo = MultilineUILabelSizer.size(for: cellData.title, font: MasterTimelineCellLayout.titleFont, numberOfLines: MasterTimelineCellLayout.maxNumberOfLines, width: Int(textAreaWidth))
let sizeInfo = MultilineUILabelSizer.size(for: cellData.title, font: MasterTimelineCellLayout.titleFont, numberOfLines: cellData.numberOfLines, width: Int(textAreaWidth))
r.size.width = textAreaWidth
r.size.height = sizeInfo.size.height
@ -168,7 +167,7 @@ private extension MasterTimelineCellLayout {
static func rectForSummary(_ cellData: MasterTimelineCellData, _ point: CGPoint, _ textAreaWidth: CGFloat, _ linesUsed: Int) -> CGRect {
let linesLeft = MasterTimelineCellLayout.maxNumberOfLines - linesUsed
let linesLeft = cellData.numberOfLines - linesUsed
var r = CGRect.zero
if cellData.summary.isEmpty || linesLeft < 1 {

View File

@ -14,6 +14,7 @@ import Articles
class MasterTimelineViewController: ProgressTableViewController, UndoableCommandRunner {
private static var minAvatarDimension: CGFloat = 20.0
private var numberOfTextLines = 0
@IBOutlet weak var markAllAsReadButton: UIBarButtonItem!
@IBOutlet weak var firstUnreadButton: UIBarButtonItem!
@ -35,6 +36,7 @@ class MasterTimelineViewController: ProgressTableViewController, UndoableCommand
NotificationCenter.default.addObserver(self, selector: #selector(avatarDidBecomeAvailable(_:)), name: .AvatarDidBecomeAvailable, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(imageDidBecomeAvailable(_:)), name: .ImageDidBecomeAvailable, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(imageDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(articlesReinitialized(_:)), name: .ArticlesReinitialized, object: navState)
NotificationCenter.default.addObserver(self, selector: #selector(articleDataDidChange(_:)), name: .ArticleDataDidChange, object: navState)
@ -45,6 +47,8 @@ class MasterTimelineViewController: ProgressTableViewController, UndoableCommand
refreshControl = UIRefreshControl()
refreshControl!.addTarget(self, action: #selector(refreshAccounts(_:)), for: .valueChanged)
numberOfTextLines = AppDefaults.timelineNumberOfLines
resetUI()
}
@ -243,6 +247,13 @@ class MasterTimelineViewController: ProgressTableViewController, UndoableCommand
}
}
@objc func userDefaultsDidChange(_ note: Notification) {
if numberOfTextLines != AppDefaults.timelineNumberOfLines {
numberOfTextLines = AppDefaults.timelineNumberOfLines
tableView.reloadData()
}
}
@objc func articlesReinitialized(_ note: Notification) {
resetUI()
}
@ -346,7 +357,7 @@ private extension MasterTimelineViewController {
let showFeedNames = navState?.showFeedNames ?? false
let showAvatar = navState?.showAvatars ?? false && avatar != nil
cell.cellData = MasterTimelineCellData(article: article, showFeedName: showFeedNames, feedName: article.feed?.nameForDisplay, avatar: avatar, showAvatar: showAvatar, featuredImage: featuredImage)
cell.cellData = MasterTimelineCellData(article: article, showFeedName: showFeedNames, feedName: article.feed?.nameForDisplay, avatar: avatar, showAvatar: showAvatar, featuredImage: featuredImage, numberOfLines: numberOfTextLines)
}

View File

@ -11,7 +11,6 @@ import UIKit
class RefreshIntervalViewController: UITableViewController {
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}

View File

@ -181,12 +181,36 @@
</constraints>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="B5l-Qp-6Gm" detailTextLabel="u7B-tj-cw8" style="IBUITableViewCellStyleValue1" id="air-4O-D7p">
<rect key="frame" x="0.0" y="515" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="air-4O-D7p" id="76S-R5-xwM">
<rect key="frame" x="0.0" y="0.0" width="376" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Number of Text Lines" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="B5l-Qp-6Gm">
<rect key="frame" x="20" y="12" width="163" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="u7B-tj-cw8">
<rect key="frame" x="332" y="12" width="44" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="DATABASE" id="hAC-uA-RbS">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="qur-cL-wrM" detailTextLabel="qIl-N6-6wQ" style="IBUITableViewCellStyleValue1" id="z1J-VF-St0">
<rect key="frame" x="0.0" y="571" width="414" height="44"/>
<rect key="frame" x="0.0" y="615" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="z1J-VF-St0" id="Y8U-Ka-GeZ">
<rect key="frame" x="0.0" y="0.0" width="376" height="43.5"/>
@ -210,7 +234,7 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="dXN-Mw-yf2" style="IBUITableViewCellStyleDefault" id="F0L-Ut-reX">
<rect key="frame" x="0.0" y="615" width="414" height="44"/>
<rect key="frame" x="0.0" y="659" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="F0L-Ut-reX" id="5SX-M2-2jR">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -227,7 +251,7 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="4Hg-B3-zAE" style="IBUITableViewCellStyleDefault" id="glf-Pg-s3P">
<rect key="frame" x="0.0" y="659" width="414" height="44"/>
<rect key="frame" x="0.0" y="703" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="glf-Pg-s3P" id="bPA-43-Oqh">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -244,7 +268,7 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="25J-iX-3at" style="IBUITableViewCellStyleDefault" id="qke-Ha-PXl">
<rect key="frame" x="0.0" y="703" width="414" height="44"/>
<rect key="frame" x="0.0" y="747" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="qke-Ha-PXl" id="pZi-ck-RV5">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -277,6 +301,7 @@
</navigationItem>
<connections>
<outlet property="refreshIntervalLabel" destination="qIl-N6-6wQ" id="2gQ-Yn-FP8"/>
<outlet property="timelineNumberOfLinesLabel" destination="u7B-tj-cw8" id="9nM-oU-VIN"/>
<outlet property="timelineSortOrderSwitch" destination="Keq-Np-l9O" id="Zm7-HG-r5h"/>
</connections>
</tableViewController>
@ -284,6 +309,35 @@
</objects>
<point key="canvasLocation" x="465" y="152"/>
</scene>
<!--TImeline Text Lines-->
<scene sceneID="07z-Vb-4Fm">
<objects>
<tableViewController storyboardIdentifier="TimelineNumberOfLinesViewController" title="TImeline Text Lines" id="1uv-PS-Xco" customClass="TimelineNumberOfLinesViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="SJH-ze-loA">
<rect key="frame" x="0.0" y="0.0" width="414" height="808"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" id="Ebv-d0-yty">
<rect key="frame" x="0.0" y="55.5" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Ebv-d0-yty" id="OVc-0q-4qT">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="1uv-PS-Xco" id="DKg-ah-4so"/>
<outlet property="delegate" destination="1uv-PS-Xco" id="yji-a1-i5U"/>
</connections>
</tableView>
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" translucent="NO" prompted="NO"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="OQI-Vn-yUz" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1162" y="151"/>
</scene>
<!--Refresh Interval-->
<scene sceneID="5WY-bu-OPU">
<objects>
@ -312,7 +366,7 @@
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="PkF-Up-3qC" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1310" y="151"/>
<point key="canvasLocation" x="1872" y="151"/>
</scene>
<!--About-->
<scene sceneID="pWd-ql-XAA">
@ -492,7 +546,7 @@
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="kRt-nH-nOf" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2092.753623188406" y="150.66964285714286"/>
<point key="canvasLocation" x="2509" y="151"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="Ezn-Ny-zye">

View File

@ -13,6 +13,7 @@ class SettingsViewController: UITableViewController {
@IBOutlet weak var refreshIntervalLabel: UILabel!
@IBOutlet weak var timelineSortOrderSwitch: UISwitch!
@IBOutlet weak var timelineNumberOfLinesLabel: UILabel!
weak var presentingParentController: UIViewController?
@ -33,6 +34,9 @@ class SettingsViewController: UITableViewController {
refreshIntervalLabel.text = AppDefaults.refreshInterval.description()
let numberOfLinesText = NSLocalizedString(" lines", comment: "Lines")
timelineNumberOfLinesLabel.text = "\(AppDefaults.timelineNumberOfLines)" + numberOfLinesText
let buildLabel = UILabel(frame: CGRect(x: 20.0, y: 0.0, width: 0.0, height: 0.0))
buildLabel.font = UIFont.systemFont(ofSize: 11.0)
buildLabel.textColor = UIColor.gray
@ -70,6 +74,11 @@ class SettingsViewController: UITableViewController {
}
case 2:
UIApplication.shared.open(URL(string: "https://appcamp4girls.com/contribute/")!, options: [:])
case 3:
if indexPath.row == 1 {
let timeline = UIStoryboard.settings.instantiateController(ofType: TimelineNumberOfLinesViewController.self)
self.navigationController?.pushViewController(timeline, animated: true)
}
case 4:
switch indexPath.row {
case 0:

View File

@ -0,0 +1,49 @@
//
// TimelineNumberOfLinesViewController.swift
// NetNewsWire-iOS
//
// Created by Maurice Parker on 4/29/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
import UIKit
class TimelineNumberOfLinesViewController: UITableViewController {
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.adjustsFontForContentSizeCategory = true
let bgView = UIView()
bgView.backgroundColor = AppAssets.selectionBackgroundColor
cell.selectedBackgroundView = bgView
cell.textLabel?.text = "\(2 + indexPath.row)" + NSLocalizedString(" lines", comment: "Lines")
let numberOfLines = AppDefaults.timelineNumberOfLines
if indexPath.row + 2 == numberOfLines {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
AppDefaults.timelineNumberOfLines = indexPath.row + 2
self.navigationController?.popViewController(animated: true)
}
}