From f513741ddb06320c687bec2aff4d482f24a7e137 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 21 Aug 2019 13:23:46 -0700 Subject: [PATCH 1/6] Start work on filtering timeline so that articles from deleted feeds never show up. --- Frameworks/Account/Account.swift | 6 +++++- .../Timeline/TimelineViewController.swift | 19 +++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 869e4b198..d42e093c9 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -614,7 +614,11 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, database.ensureStatuses(articleIDs, statusKey, flag) } } - + + public func has(_ feed: Feed) -> Bool { + return flattenedFeeds().contains(feed) + } + // MARK: - Container public func flattenedFeeds() -> Set { diff --git a/Mac/MainWindow/Timeline/TimelineViewController.swift b/Mac/MainWindow/Timeline/TimelineViewController.swift index 26750287d..b01ba2873 100644 --- a/Mac/MainWindow/Timeline/TimelineViewController.swift +++ b/Mac/MainWindow/Timeline/TimelineViewController.swift @@ -67,6 +67,9 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr var articles = ArticleArray() { didSet { + defer { + updateUnreadCount() + } if articles == oldValue { return } @@ -76,13 +79,11 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr // Just reload visible cells in this case: don’t call reloadData. articleRowMap = [String: Int]() reloadVisibleCells() - updateUnreadCount() return } updateShowAvatars() articleRowMap = [String: Int]() tableView.reloadData() - updateUnreadCount() } } @@ -982,13 +983,23 @@ private extension TimelineViewController { } func replaceArticles(with unsortedArticles: Set
) { - - let sortedArticles = Array(unsortedArticles).sortedByDate(sortDirection) + // Since there may be transients in a smart feed, + // make sure each article is in a feed that’s still + // subscribed-to. + let filteredArticles = unsortedArticles.filter(articleIsInSubscribedToFeed) + let sortedArticles = Array(filteredArticles).sortedByDate(sortDirection) if articles != sortedArticles { articles = sortedArticles } } + func articleIsInSubscribedToFeed(_ article: Article) -> Bool { + guard let account = article.account, let feed = article.feed else { + return false + } + return account.has(feed) + } + func fetchUnsortedArticlesSync(for representedObjects: [Any]) -> Set
{ cancelPendingAsyncFetches() let articleFetchers = representedObjects.compactMap{ $0 as? ArticleFetcher } From edd9b1cc9141ea78ddfa8c3b14ba6e936407621d Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 21 Aug 2019 20:56:53 -0700 Subject: [PATCH 2/6] Remove HelpBook folder, since the help book now has a separate repo. --- Technotes/HelpBook.opml | 51 ----------------- Technotes/HelpBook/5.0/en/README.md | 9 --- .../HelpBook/5.0/en/images/websitediagram.png | Bin 1719 -> 0 bytes Technotes/HelpBook/5.0/en/index.markdown | 52 ------------------ .../HelpBook/5.0/en/what-is-rss.markdown | 29 ---------- 5 files changed, 141 deletions(-) delete mode 100644 Technotes/HelpBook.opml delete mode 100644 Technotes/HelpBook/5.0/en/README.md delete mode 100644 Technotes/HelpBook/5.0/en/images/websitediagram.png delete mode 100644 Technotes/HelpBook/5.0/en/index.markdown delete mode 100644 Technotes/HelpBook/5.0/en/what-is-rss.markdown diff --git a/Technotes/HelpBook.opml b/Technotes/HelpBook.opml deleted file mode 100644 index b26f00e3a..000000000 --- a/Technotes/HelpBook.opml +++ /dev/null @@ -1,51 +0,0 @@ - - - - HelpBook - Sun, 17 Feb 2019 22:26:12 GMT - 24,27 - 10 - 207 - 46 - 983 - 910 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Technotes/HelpBook/5.0/en/README.md b/Technotes/HelpBook/5.0/en/README.md deleted file mode 100644 index 25c2297c8..000000000 --- a/Technotes/HelpBook/5.0/en/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# About the NetNewsWire 5 Help Book - -The Help book goes here. Text files go at the top level, and images go in the images directory. - -Text files are markdown files. A script ([wildcat](https://github.com/brentsimmons/wildcat)) will turn this into a web site that will appear at [https://ranchero.com/netnewswire/help/mac/5.0/en/](https://ranchero.com/netnewswire/help/mac/5.0/en/). (The /en/ directory because we hope to have localized versions.) - -If you’d like to write or edit the Help book, or help with screenshots, please bring it up on the [NetNewsWire Slack](https://netnewswire.slack.com/join/shared_invite/enQtNjM4MDA1MjQzMDkzLTNlNjBhOWVhYzdhYjA4ZWFhMzQ1MTUxYjU0NTE5ZGY0YzYwZWJhNjYwNTNmNTg2NjIwYWY4YzhlYzk5NmU3ZTc) group. We’ll coordinate there. - -**NOTE:** It’s not a good idea to take screenshots yet! The UI is still subject to change. That won’t be true for too much longer, but it’s true for now. diff --git a/Technotes/HelpBook/5.0/en/images/websitediagram.png b/Technotes/HelpBook/5.0/en/images/websitediagram.png deleted file mode 100644 index 70496c1df53f3777a51462e79c1f796cd6d10087..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1719 zcmZuyeN{-Tc>g2Op{92Fj#m_M$ShkmvtX;a7IV!l?mA+EM|by(@W`5<9b&)UG(Kgn%h zp>`EUyM$*vx|_YGaWqpq6;xfmI&P%9GJvi^K#!!v8_6uaY>uuSzPh|D<*&S#cn%$u z#kjrR($dztyJF>70#WT~D71tk*TGFy>KGKx6tEB@tUTdH_&oRd@qO=Y+@Y6n2za2o z2CZ)e4I0ftGW^`DUy%o0VefuQ-p>l*CBfEc-Lunr)k5%m*`+sUc?#Qi4Y1c?Pf7HN zE)ypn&7BDRG-1d$y2O&6G0geLSsbwj7{+5EgL+7&YQ0j=|K_`D1rxC7$@1KS^ZAYCKZ>$%* z3X6Mbh4_iaHKG4M1234$px4yrvKWhxd(K0WEZK-ca67w8=2f|$?9$V^)4wPAiu|gJ zvTdhJ#G<@M`uS23v)Rc2+^`zwxHjv})D8UB8ozPswxpD6jXyW;AirgFJ2cE@Pi&bg z9MP>$yJgd@AM+KF&ZKzo25z^d8)0u#Ar}-nh&$-E4pyQKw$C zgHSxtNq%|~A_bZe3gqPcvklQ6W{VBY8^aKm4hdXtQ!6;^t;QtuxC7hgSzbd9!4!J- zOLyLh?T3qWA4OUN_zv>6KKjz!S5Mcd9rN0A0TD-(de?lwL7YhV#_Su`?7fW8h}Q~ z4%sy{zbfkpds^X)7|+$o@x_sW*x4wPM(_s&KtIS3x1(j-zuKE^q!=fx4RGNY@p=Q@ zL<-I_+{uk*UdVbn_h){9r?)ld)dPjLsA0e+3Kc~k&)&QsRg}zMw_Or{ea_fK*O!V1 zBq?5_)DM5!Z7yi)#_iB z3Vgp`=?Y&Psd^l-xK0%>8&kcOi3Ovo2F+51eU2rUPqr-`7B4I5kfQ)CU*C5Hmh8vg z|HHaM>xgBV4h2{{waxH^b;Qf=9Yb!pfVDgsRc{oV7O=G6H8UT-b}!GjxL{Cizn6ox zP8@O6TCJ;o&>f@;;wz%-d8zhv595tsUc0Vf0Q9y7zZF%fFJ=s8Vm(hIBm;boMd`(U zQ4~gZ2FDWYT@k~t9jE!PT<|a5GSxUz#WmAXWg72Gx0Q+26;IfEh^y}WYCF3t^Zayr z`Z6iMq(U|)8cJsG1BIrjA7_uCuz>!9R9VnorzsH0Te zg4BA!P>Gte++6YJ@%nJ - -The good part is the part in the middle — that’s the part with the news. That’s the part that you read. That’s the part you’re interested in. - -

And that’s what RSS is — it’s just that part, minus the rest of the stuff. - -#### Details - -That “good part” is actually made available as a *feed.* A feed is just a specially-formatted text file that readers like NetNewsWire can read. The files look weird — they kind of look like the source behind web pages, with angle brackets and everything. - -The important thing is: it’s NetNewsWire’s job to know how to read the feed. And it’s NetNewsWire’s job to show you what articles you haven’t read yet. - -By doing this — by running NetNewsWire — you can let NetNewsWire find out when there’s something new. You don’t have to go to the websites and check to see if there’s something new. You can save time, and not have to rely on your memory. - -#### Types of feeds - -People often talk or write about RSS — but sometimes they mention Atom, too. Atom does the same thing as RSS. Sometimes they mention the JSON Feed format, which does the same thing as RSS too. - -If you see RSS or Atom or JSON Feed, just know that NetNewsWire handles all these, no problem. \ No newline at end of file From fe2d329301d03b73ca1eebf1ac93a612def027cc Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 21 Aug 2019 21:05:47 -0700 Subject: [PATCH 3/6] Make has(feed) a Container protocol method. --- Frameworks/Account/Account.swift | 8 ++++---- Frameworks/Account/Container.swift | 1 + Frameworks/Account/Folder.swift | 6 +++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index d42e093c9..1a6acf1c6 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -615,10 +615,6 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, } } - public func has(_ feed: Feed) -> Bool { - return flattenedFeeds().contains(feed) - } - // MARK: - Container public func flattenedFeeds() -> Set { @@ -653,6 +649,10 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, postChildrenDidChangeNotification() } + public func has(_ feed: Feed) -> Bool { + return flattenedFeeds().contains(feed) + } + // MARK: - Debug public func debugDropConditionalGetInfo() { diff --git a/Frameworks/Account/Container.swift b/Frameworks/Account/Container.swift index c37cf2bfe..8d337ebe6 100644 --- a/Frameworks/Account/Container.swift +++ b/Frameworks/Account/Container.swift @@ -33,6 +33,7 @@ public protocol Container: class { //Recursive — checks subfolders func flattenedFeeds() -> Set + func has(_ feed: Feed) -> Bool func hasFeed(with feedID: String) -> Bool func hasFeed(withURL url: String) -> Bool func existingFeed(with feedID: String) -> Feed? diff --git a/Frameworks/Account/Folder.swift b/Frameworks/Account/Folder.swift index 6d164a28c..f47f07c02 100644 --- a/Frameworks/Account/Folder.swift +++ b/Frameworks/Account/Folder.swift @@ -101,7 +101,11 @@ public final class Folder: DisplayNameProvider, Renamable, Container, UnreadCoun topLevelFeeds.remove(feed) postChildrenDidChangeNotification() } - + + public func has(_ feed: Feed) -> Bool { + return flattenedFeeds().contains(feed) + } + // MARK: - Hashable public func hash(into hasher: inout Hasher) { From bffda93700ca25f20240a46f3215548e6dd5fd8e Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 21 Aug 2019 21:07:40 -0700 Subject: [PATCH 4/6] Give has(feed) a default implementation in Container.swift. --- Frameworks/Account/Account.swift | 4 ---- Frameworks/Account/Container.swift | 4 ++++ Frameworks/Account/Folder.swift | 4 ---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 1a6acf1c6..6a94bf4e4 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -649,10 +649,6 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, postChildrenDidChangeNotification() } - public func has(_ feed: Feed) -> Bool { - return flattenedFeeds().contains(feed) - } - // MARK: - Debug public func debugDropConditionalGetInfo() { diff --git a/Frameworks/Account/Container.swift b/Frameworks/Account/Container.swift index 8d337ebe6..610ee69b8 100644 --- a/Frameworks/Account/Container.swift +++ b/Frameworks/Account/Container.swift @@ -95,6 +95,10 @@ public extension Container { return existingFeed(withURL: url) != nil } + func has(_ feed: Feed) -> Bool { + return flattenedFeeds().contains(feed) + } + func existingFeed(with feedID: String) -> Feed? { for feed in flattenedFeeds() { if feed.feedID == feedID { diff --git a/Frameworks/Account/Folder.swift b/Frameworks/Account/Folder.swift index f47f07c02..bdfe13118 100644 --- a/Frameworks/Account/Folder.swift +++ b/Frameworks/Account/Folder.swift @@ -102,10 +102,6 @@ public final class Folder: DisplayNameProvider, Renamable, Container, UnreadCoun postChildrenDidChangeNotification() } - public func has(_ feed: Feed) -> Bool { - return flattenedFeeds().contains(feed) - } - // MARK: - Hashable public func hash(into hasher: inout Hasher) { From 849830f494015243a92320c7d53f504e3721c7ec Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 21 Aug 2019 21:41:56 -0700 Subject: [PATCH 5/6] Refetch articles for smart feeds and folders, if selected, when a feed or folder is deleted. Fix #838. --- .../Timeline/TimelineViewController.swift | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Mac/MainWindow/Timeline/TimelineViewController.swift b/Mac/MainWindow/Timeline/TimelineViewController.swift index b01ba2873..913d7c0b2 100644 --- a/Mac/MainWindow/Timeline/TimelineViewController.swift +++ b/Mac/MainWindow/Timeline/TimelineViewController.swift @@ -169,6 +169,7 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr NotificationCenter.default.addObserver(self, selector: #selector(accountDidDownloadArticles(_:)), name: .AccountDidDownloadArticles, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(accountStateDidChange(_:)), name: .AccountStateDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(accountsDidChange(_:)), name: .AccountsDidChange, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(containerChildrenDidChange(_:)), name: .ChildrenDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil) DistributedNotificationCenter.default.addObserver(self, selector: #selector(appleInterfaceThemeChanged), name: .AppleInterfaceThemeChangedNotification, object: nil) @@ -541,6 +542,12 @@ final class TimelineViewController: NSViewController, UndoableCommandRunner, Unr } } + @objc func containerChildrenDidChange(_ note: Notification) { + if representedObjectsContainsAnyPseudoFeed() || representedObjectsContainAnyFolder() { + fetchAndReplaceArticlesAsync() + } + } + @objc func userDefaultsDidChange(_ note: Notification) { self.fontSize = AppDefaults.timelineFontSize @@ -983,23 +990,12 @@ private extension TimelineViewController { } func replaceArticles(with unsortedArticles: Set

) { - // Since there may be transients in a smart feed, - // make sure each article is in a feed that’s still - // subscribed-to. - let filteredArticles = unsortedArticles.filter(articleIsInSubscribedToFeed) - let sortedArticles = Array(filteredArticles).sortedByDate(sortDirection) + let sortedArticles = Array(unsortedArticles).sortedByDate(sortDirection) if articles != sortedArticles { articles = sortedArticles } } - func articleIsInSubscribedToFeed(_ article: Article) -> Bool { - guard let account = article.account, let feed = article.feed else { - return false - } - return account.has(feed) - } - func fetchUnsortedArticlesSync(for representedObjects: [Any]) -> Set
{ cancelPendingAsyncFetches() let articleFetchers = representedObjects.compactMap{ $0 as? ArticleFetcher } @@ -1073,7 +1069,11 @@ private extension TimelineViewController { func representedObjectsContainsTodayFeed() -> Bool { return representedObjects?.contains(where: { $0 === SmartFeedsController.shared.todayFeed }) ?? false } - + + func representedObjectsContainAnyFolder() -> Bool { + return representedObjects?.contains(where: { $0 is Folder }) ?? false + } + func representedObjectsContainsAnyFeed(_ feeds: Set) -> Bool { // Return true if there’s a match or if a folder contains (recursively) one of feeds From e140d51e4ba468f71d9481c9613b7b4cd34aca40 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 21 Aug 2019 21:42:48 -0700 Subject: [PATCH 6/6] Bump version and build number. --- Mac/Resources/Info.plist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mac/Resources/Info.plist b/Mac/Resources/Info.plist index 6f5769077..230c42b35 100644 --- a/Mac/Resources/Info.plist +++ b/Mac/Resources/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 5.0b4 + 5.0b5 CFBundleURLTypes @@ -33,7 +33,7 @@ CFBundleVersion - 2606 + 2607 LSApplicationCategoryType public.app-category.news LSMinimumSystemVersion