From 86ca3972211635de8d883327b52424dedf4fc98e Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Wed, 23 Jun 2021 02:44:34 -0500 Subject: [PATCH 01/23] Ignore key commands when the web view has focus. Fixes #3179 --- iOS/MasterFeed/MasterFeedViewController.swift | 6 ++++++ iOS/MasterTimeline/MasterTimelineViewController.swift | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index 6233bf2b6..807d9c955 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -35,6 +35,12 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { private let keyboardManager = KeyboardManager(type: .sidebar) override var keyCommands: [UIKeyCommand]? { + + // If the first responder is the WKWebView (PreloadedWebView) we don't want to supply any keyboard + // commands that the system is looking for by going up the responder chain. They will interfere with + // the WKWebViews built in hardware keyboard shortcuts, specifically the up and down arrow keys. + guard let current = UIResponder.currentFirstResponder, !(current is PreloadedWebView) else { return nil } + return keyboardManager.keyCommands } diff --git a/iOS/MasterTimeline/MasterTimelineViewController.swift b/iOS/MasterTimeline/MasterTimelineViewController.swift index 1a99608bd..9cc5a6152 100644 --- a/iOS/MasterTimeline/MasterTimelineViewController.swift +++ b/iOS/MasterTimeline/MasterTimelineViewController.swift @@ -33,6 +33,12 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner private let keyboardManager = KeyboardManager(type: .timeline) override var keyCommands: [UIKeyCommand]? { + + // If the first responder is the WKWebView (PreloadedWebView) we don't want to supply any keyboard + // commands that the system is looking for by going up the responder chain. They will interfere with + // the WKWebViews built in hardware keyboard shortcuts, specifically the up and down arrow keys. + guard let current = UIResponder.currentFirstResponder, !(current is PreloadedWebView) else { return nil } + return keyboardManager.keyCommands } From c2413cda37d56655a7cb9bf4b31bb9b2da811ba2 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Wed, 23 Jun 2021 03:24:23 -0500 Subject: [PATCH 02/23] Restore alpha of the indicators to 1 incase the animation completion handler doesn't get called. Fixes #3156 --- iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift b/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift index 49b9f9ae8..2ec879473 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift @@ -229,12 +229,13 @@ private extension MasterTimelineTableViewCell { } unreadIndicatorPropertyAnimator?.startAnimation() } else { + unreadIndicatorView.alpha = 1 showOrHideView(unreadIndicatorView, cellData.read || cellData.starred) } } func updateStarView() { - if !starView.isHidden && cellData.read && !cellData.starred { + if !starView.isHidden && cellData.read && !cellData.starred { starViewPropertyAnimator = UIViewPropertyAnimator(duration: 0.66, curve: .easeInOut) { [weak self] in self?.starView.alpha = 0 } @@ -245,6 +246,7 @@ private extension MasterTimelineTableViewCell { } starViewPropertyAnimator?.startAnimation() } else { + starView.alpha = 1 showOrHideView(starView, !cellData.starred) } } From 534016bf800dbae71d843c1508d64befafb7fba0 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 26 Jun 2021 14:22:04 -0500 Subject: [PATCH 03/23] Update to latest RSCore. Fixes #3199 --- .../xcshareddata/swiftpm/Package.resolved | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/NetNewsWire.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/NetNewsWire.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index b58a85312..62d557ca1 100644 --- a/NetNewsWire.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/NetNewsWire.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/Thomvis/BrightFutures.git", "state": { "branch": null, - "revision": "9279defa6bdc21501ce740266e5a14d0119ddc63", - "version": "8.0.1" + "revision": "939858b811026f85e87847a808f0bea2f187e5c4", + "version": "8.1.0" } }, { @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/microsoft/plcrashreporter.git", "state": { "branch": null, - "revision": "de6b8f9db4b2a0aa859a5507550a70548e4da936", - "version": "1.8.1" + "revision": "d747ab5de269cd44022bbe96ff9609d8626694ab", + "version": "1.9.0" } }, { @@ -60,8 +60,8 @@ "repositoryURL": "https://github.com/Ranchero-Software/RSCore.git", "state": { "branch": null, - "revision": "2a13519b4d91843faa6aff4245b0e387dc64eafe", - "version": "1.0.6" + "revision": "060b12a3d3b6d27d57b2fae84160bfec91ec7118", + "version": "1.0.7" } }, { From 2862d4066333b7d3b2ba466d6748e81128dde5e1 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 26 Jun 2021 18:15:37 -0500 Subject: [PATCH 04/23] Upgrade to latest RSWeb. Fixes #3202 --- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NetNewsWire.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/NetNewsWire.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 62d557ca1..79c1e198c 100644 --- a/NetNewsWire.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/NetNewsWire.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -96,8 +96,8 @@ "repositoryURL": "https://github.com/Ranchero-Software/RSWeb.git", "state": { "branch": null, - "revision": "2f9ad98736c5c17dfb2be0b3cc06e71a49b061fa", - "version": "1.0.1" + "revision": "b27837aaa7163a8ed002fed52965a350aa868013", + "version": "1.0.2" } }, { From 17cc23364d0730acdf4dc84e9efdb63bfdd90155 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 26 Jun 2021 20:54:17 -0500 Subject: [PATCH 05/23] Make sure we don't use negative oftsets when finding an index. Fixes #3204 --- .../Sources/Account/FeedProvider/Twitter/TwitterStatus.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift b/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift index 149814667..0e86168fb 100644 --- a/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift +++ b/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift @@ -91,8 +91,8 @@ private extension TwitterStatus { } } - let offsetStartIndex = entity.startIndex - unicodeScalarOffset - let offsetEndIndex = entity.endIndex - unicodeScalarOffset + let offsetStartIndex = unicodeScalarOffset < entity.startIndex ? entity.startIndex - unicodeScalarOffset : entity.startIndex + let offsetEndIndex = unicodeScalarOffset < entity.endIndex ? entity.endIndex - unicodeScalarOffset : entity.endIndex let entityStartIndex = text.index(text.startIndex, offsetBy: offsetStartIndex, limitedBy: text.endIndex) ?? text.startIndex let entityEndIndex = text.index(text.startIndex, offsetBy: offsetEndIndex, limitedBy: text.endIndex) ?? text.endIndex From c279f92f7987ef6e67952b2abd12eac6c894d523 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 5 Jul 2021 14:24:50 -0500 Subject: [PATCH 06/23] Changed how images are placed in Twitter articles so that you can better see who Tweeted the image. --- .../FeedProvider/Twitter/TwitterStatus.swift | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift b/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift index 0e86168fb..275d4b354 100644 --- a/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift +++ b/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift @@ -48,7 +48,7 @@ final class TwitterStatus: Codable { func renderAsHTML(topLevel: Bool = true) -> String { if let retweetedStatus = retweetedStatus { - return renderAsRetweetHTML(retweetedStatus, topLevel: topLevel) + return renderAsRetweetHTML(retweetedStatus) } if let quotedStatus = quotedStatus { return renderAsQuoteHTML(quotedStatus, topLevel: topLevel) @@ -139,26 +139,17 @@ private extension TwitterStatus { func renderAsOriginalHTML(topLevel: Bool) -> String { var html = renderAsTweetHTML(self, topLevel: topLevel) - if topLevel { - html += extendedEntities?.renderAsHTML() ?? "" - html += retweetedStatus?.extendedEntities?.renderAsHTML() ?? "" - html += quotedStatus?.extendedEntities?.renderAsHTML() ?? "" - } + html += extendedEntities?.renderAsHTML() ?? "" return html } - func renderAsRetweetHTML(_ status: TwitterStatus, topLevel: Bool) -> String { + func renderAsRetweetHTML(_ status: TwitterStatus) -> String { var html = "
" if let userHTML = status.user?.renderAsHTML() { html += userHTML } html += status.renderAsHTML(topLevel: false) html += "
" - if topLevel { - html += status.extendedEntities?.renderAsHTML() ?? "" - html += status.retweetedStatus?.extendedEntities?.renderAsHTML() ?? "" - html += status.quotedStatus?.extendedEntities?.renderAsHTML() ?? "" - } return html } @@ -171,11 +162,6 @@ private extension TwitterStatus { } html += quotedStatus.renderAsHTML(topLevel: false) html += "" - if topLevel { - html += quotedStatus.extendedEntities?.renderAsHTML() ?? "" - html += quotedStatus.retweetedStatus?.extendedEntities?.renderAsHTML() ?? "" - html += quotedStatus.quotedStatus?.extendedEntities?.renderAsHTML() ?? "" - } return html } From fd4fd5174ee9377d6a5b44018eea206c1af8aee8 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Tue, 6 Jul 2021 16:52:31 -0500 Subject: [PATCH 07/23] Continue processing if we don't find any articles. Fixes #3213 --- .../CloudKit/CloudKitSendStatusOperation.swift | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift index 30c983ef2..1979880a4 100644 --- a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift +++ b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift @@ -74,11 +74,13 @@ private extension CloudKitSendStatusOperation { case .success(let syncStatuses): func stopProcessing() { - if self.showProgress { - self.refreshProgress?.completeTask() + self.database.resetAllSelectedForProcessing { _ in + if self.showProgress { + self.refreshProgress?.completeTask() + } + os_log(.debug, log: self.log, "Done sending article statuses.") + self.operationDelegate?.operationDidComplete(self) } - os_log(.debug, log: self.log, "Done sending article statuses.") - self.operationDelegate?.operationDidComplete(self) } guard syncStatuses.count > 0 else { @@ -130,10 +132,10 @@ private extension CloudKitSendStatusOperation { } // If this happens, we have somehow gotten into a state where we have new status records - // but the articles didn't come back in the fetch. Rather than crashing, we stop processing + // but the articles didn't come back in the fetch. Rather than crashing, we continue processing // and hope that it gets cleared up later. guard !statusUpdates.isEmpty else { - done(true) + done(false) return } From 3ea427bd2dd62a1946e9a60def3173983f5a8a25 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Tue, 6 Jul 2021 18:50:48 -0500 Subject: [PATCH 08/23] Fix open in browser when the article is selected. Fixes #3215 --- iOS/MasterTimeline/MasterTimelineViewController.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/iOS/MasterTimeline/MasterTimelineViewController.swift b/iOS/MasterTimeline/MasterTimelineViewController.swift index 9cc5a6152..ed966c783 100644 --- a/iOS/MasterTimeline/MasterTimelineViewController.swift +++ b/iOS/MasterTimeline/MasterTimelineViewController.swift @@ -129,6 +129,15 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner } // MARK: Actions + + @objc func openInBrowser(_ sender: Any?) { + coordinator.showBrowserForCurrentArticle() + } + + @objc func openInAppBrowser(_ sender: Any?) { + coordinator.showInAppBrowser() + } + @IBAction func toggleFilter(_ sender: Any) { coordinator.toggleReadArticlesFilter() } From 1096e341d536938909ab916cc53f20135c35ad84 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Wed, 7 Jul 2021 12:24:21 -0500 Subject: [PATCH 09/23] Remove reset for processing as it was causing an infinite loop in some scenarios. --- .../Account/CloudKit/CloudKitSendStatusOperation.swift | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift index 1979880a4..b8cf00866 100644 --- a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift +++ b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift @@ -74,13 +74,11 @@ private extension CloudKitSendStatusOperation { case .success(let syncStatuses): func stopProcessing() { - self.database.resetAllSelectedForProcessing { _ in - if self.showProgress { - self.refreshProgress?.completeTask() - } - os_log(.debug, log: self.log, "Done sending article statuses.") - self.operationDelegate?.operationDidComplete(self) + if self.showProgress { + self.refreshProgress?.completeTask() } + os_log(.debug, log: self.log, "Done sending article statuses.") + self.operationDelegate?.operationDidComplete(self) } guard syncStatuses.count > 0 else { From f446a7e2ead1ebd1c103a93b44a227c50a604e3e Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 8 Jul 2021 13:09:26 -0500 Subject: [PATCH 10/23] Delete orphaned sync status records. --- .../CloudKitSendStatusOperation.swift | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift index b8cf00866..a1a1f1070 100644 --- a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift +++ b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift @@ -130,24 +130,26 @@ private extension CloudKitSendStatusOperation { } // If this happens, we have somehow gotten into a state where we have new status records - // but the articles didn't come back in the fetch. Rather than crashing, we continue processing - // and hope that it gets cleared up later. - guard !statusUpdates.isEmpty else { - done(false) - return - } - - articlesZone.modifyArticles(statusUpdates) { result in - switch result { - case .success: - self.database.deleteSelectedForProcessing(statusUpdates.map({ $0.articleID })) { _ in - done(false) - } - case .failure(let error): - self.database.resetSelectedForProcessing(syncStatuses.map({ $0.articleID })) { _ in - self.processAccountError(account, error) - os_log(.error, log: self.log, "Send article status modify articles error: %@.", error.localizedDescription) - completion(true) + // but the articles didn't come back in the fetch. We need to clean up those sync records + // and continue processing. + if statusUpdates.isEmpty { + self.database.deleteSelectedForProcessing(articleIDs) { _ in + done(false) + return + } + } else { + articlesZone.modifyArticles(statusUpdates) { result in + switch result { + case .success: + self.database.deleteSelectedForProcessing(statusUpdates.map({ $0.articleID })) { _ in + done(false) + } + case .failure(let error): + self.database.resetSelectedForProcessing(syncStatuses.map({ $0.articleID })) { _ in + self.processAccountError(account, error) + os_log(.error, log: self.log, "Send article status modify articles error: %@.", error.localizedDescription) + completion(true) + } } } } From 33ecf4ec5bee0ef65ba040ad43bfb0ffffe66992 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 9 Jul 2021 11:56:05 -0500 Subject: [PATCH 11/23] Stop processing when we don't return status records. --- .../Account/CloudKit/CloudKitSendStatusOperation.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift index a1a1f1070..41f42bc4d 100644 --- a/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift +++ b/Account/Sources/Account/CloudKit/CloudKitSendStatusOperation.swift @@ -131,10 +131,10 @@ private extension CloudKitSendStatusOperation { // If this happens, we have somehow gotten into a state where we have new status records // but the articles didn't come back in the fetch. We need to clean up those sync records - // and continue processing. + // and stop processing. if statusUpdates.isEmpty { self.database.deleteSelectedForProcessing(articleIDs) { _ in - done(false) + done(true) return } } else { From 9d6bfc87b01760732755280a5065feb43ecff5e9 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 16 Jul 2021 14:28:56 -0500 Subject: [PATCH 12/23] Fix crash on iOS 15 --- iOS/UIKit Extensions/CroppingPreviewParameters.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/iOS/UIKit Extensions/CroppingPreviewParameters.swift b/iOS/UIKit Extensions/CroppingPreviewParameters.swift index 58a19dfbf..330ade196 100644 --- a/iOS/UIKit Extensions/CroppingPreviewParameters.swift +++ b/iOS/UIKit Extensions/CroppingPreviewParameters.swift @@ -10,6 +10,10 @@ import UIKit class CroppingPreviewParameters: UIPreviewParameters { + override init() { + super.init() + } + init(view: UIView) { super.init() let newBounds = CGRect(x: 1, y: 1, width: view.bounds.width - 2, height: view.bounds.height - 2) From 8bac72e5c08e7c9fec2158aac8f451de315c6582 Mon Sep 17 00:00:00 2001 From: Nate Weaver Date: Sun, 18 Jul 2021 17:01:59 -0500 Subject: [PATCH 13/23] Fix favicons when a feed's homepage URL has non-ASCII in its path --- Shared/Favicons/FaviconDownloader.swift | 2 +- Shared/Favicons/FaviconURLFinder.swift | 2 +- Shared/HTMLMetadata/HTMLMetadataDownloader.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Shared/Favicons/FaviconDownloader.swift b/Shared/Favicons/FaviconDownloader.swift index 99d8dd2e6..bda684e43 100644 --- a/Shared/Favicons/FaviconDownloader.swift +++ b/Shared/Favicons/FaviconDownloader.swift @@ -200,7 +200,7 @@ private extension FaviconDownloader { func findFaviconURLs(with homePageURL: String, _ completion: @escaping ([String]?) -> Void) { - guard let url = URL(string: homePageURL) else { + guard let url = URL(unicodeString: homePageURL) else { completion(nil) return } diff --git a/Shared/Favicons/FaviconURLFinder.swift b/Shared/Favicons/FaviconURLFinder.swift index cc429e4c6..dd51da4a5 100644 --- a/Shared/Favicons/FaviconURLFinder.swift +++ b/Shared/Favicons/FaviconURLFinder.swift @@ -42,7 +42,7 @@ struct FaviconURLFinder { /// - urls: An array of favicon URLs as strings. static func findFaviconURLs(with homePageURL: String, _ completion: @escaping (_ urls: [String]?) -> Void) { - guard let _ = URL(string: homePageURL) else { + guard let _ = URL(unicodeString: homePageURL) else { completion(nil) return } diff --git a/Shared/HTMLMetadata/HTMLMetadataDownloader.swift b/Shared/HTMLMetadata/HTMLMetadataDownloader.swift index 40651d420..4f2404868 100644 --- a/Shared/HTMLMetadata/HTMLMetadataDownloader.swift +++ b/Shared/HTMLMetadata/HTMLMetadataDownloader.swift @@ -15,7 +15,7 @@ struct HTMLMetadataDownloader { static let serialDispatchQueue = DispatchQueue(label: "HTMLMetadataDownloader") static func downloadMetadata(for url: String, _ completion: @escaping (RSHTMLMetadata?) -> Void) { - guard let actualURL = URL(string: url) else { + guard let actualURL = URL(unicodeString: url) else { completion(nil) return } From 63e4d2c54e9ab940267c5862f0532eb91c6ee2e6 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Wed, 21 Jul 2021 17:01:57 -0500 Subject: [PATCH 14/23] Make external links span the full width of the article area --- Shared/Article Rendering/ArticleRenderer.swift | 5 +---- Shared/Article Rendering/shared.css | 4 ++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Shared/Article Rendering/ArticleRenderer.swift b/Shared/Article Rendering/ArticleRenderer.swift index a8f8c4e4b..85fc0db30 100644 --- a/Shared/Article Rendering/ArticleRenderer.swift +++ b/Shared/Article Rendering/ArticleRenderer.swift @@ -154,10 +154,7 @@ private extension ArticleRenderer { d["title"] = title if let externalLink = article.externalURL, externalLink != article.preferredLink { - var displayLink = externalLink.strippingHTTPOrHTTPSScheme - if displayLink.count > 27 { - displayLink = displayLink.prefix(27).appending("...") - } + let displayLink = externalLink.strippingHTTPOrHTTPSScheme let regarding = NSLocalizedString("Link", comment: "Link") let externalLinkString = "\(regarding): \(displayLink)" d["external_link"] = externalLinkString diff --git a/Shared/Article Rendering/shared.css b/Shared/Article Rendering/shared.css index 9019d6aee..d14237442 100644 --- a/Shared/Article Rendering/shared.css +++ b/Shared/Article Rendering/shared.css @@ -118,6 +118,10 @@ body > .systemMessage { .externalLink { margin-bottom: 5px; font-style: italic; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .articleBody { From 25370cc0af2cb5b6241c9d99ac89159954c9d694 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Tue, 27 Jul 2021 13:37:31 -0500 Subject: [PATCH 15/23] Hide Daring Fireball's external link --- Shared/Article Rendering/shared.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Shared/Article Rendering/shared.css b/Shared/Article Rendering/shared.css index d14237442..b0626b7c9 100644 --- a/Shared/Article Rendering/shared.css +++ b/Shared/Article Rendering/shared.css @@ -266,6 +266,14 @@ blockquote { border-top: 1px solid var(--header-table-border-color); } +/* Hide the external link at the bottom of Daring Fireball posts */ + +.x-netnewswire-hide { + display: none; +} + +/* see removeWpSmiley; this rule is kept in case a wp-smiley is encountered without alt text */ + .wp-smiley { height: 1em; max-height: 1em; From 3512646261d04fb61d6a02bedf189e1ef66844d8 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 29 Jul 2021 17:11:22 -0500 Subject: [PATCH 16/23] Add Feedbin external url handling. Fixes #3239 --- .../Sources/Account/Feedbin/FeedbinAccountDelegate.swift | 2 +- Account/Sources/Account/Feedbin/FeedbinEntry.swift | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift index cbb44d837..e46b52885 100644 --- a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift @@ -1259,7 +1259,7 @@ private extension FeedbinAccountDelegate { let parsedItems: [ParsedItem] = entries.map { entry in let authors = Set([ParsedAuthor(name: entry.authorName, url: entry.jsonFeed?.jsonFeedAuthor?.url, avatarURL: entry.jsonFeed?.jsonFeedAuthor?.avatarURL, emailAddress: nil)]) - return ParsedItem(syncServiceID: String(entry.articleID), uniqueID: String(entry.articleID), feedURL: String(entry.feedID), url: entry.url, externalURL: nil, title: entry.title, language: nil, contentHTML: entry.contentHTML, contentText: nil, summary: entry.summary, imageURL: nil, bannerImageURL: nil, datePublished: entry.parsedDatePublished, dateModified: nil, authors: authors, tags: nil, attachments: nil) + return ParsedItem(syncServiceID: String(entry.articleID), uniqueID: String(entry.articleID), feedURL: String(entry.feedID), url: entry.url, externalURL: entry.jsonFeed?.jsonFeedExternalURL, title: entry.title, language: nil, contentHTML: entry.contentHTML, contentText: nil, summary: entry.summary, imageURL: nil, bannerImageURL: nil, datePublished: entry.parsedDatePublished, dateModified: nil, authors: authors, tags: nil, attachments: nil) } return Set(parsedItems) diff --git a/Account/Sources/Account/Feedbin/FeedbinEntry.swift b/Account/Sources/Account/Feedbin/FeedbinEntry.swift index 741d6abfc..27e23a140 100644 --- a/Account/Sources/Account/Feedbin/FeedbinEntry.swift +++ b/Account/Sources/Account/Feedbin/FeedbinEntry.swift @@ -52,9 +52,11 @@ final class FeedbinEntry: Decodable { struct FeedbinEntryJSONFeed: Decodable { let jsonFeedAuthor: FeedbinEntryJSONFeedAuthor? - + let jsonFeedExternalURL: String? + enum CodingKeys: String, CodingKey { case jsonFeedAuthor = "author" + case jsonFeedExternalURL = "external_url" } public init(from decoder: Decoder) throws { @@ -64,6 +66,11 @@ struct FeedbinEntryJSONFeed: Decodable { } catch { jsonFeedAuthor = nil } + do { + jsonFeedExternalURL = try container.decode(String.self, forKey: .jsonFeedExternalURL) + } catch { + jsonFeedExternalURL = nil + } } } From 15bf35ce28ee68396b570da3dbe3b816f720fdae Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Tue, 10 Aug 2021 20:07:38 -0500 Subject: [PATCH 17/23] Fix bug that was incorrectly parsing Twitter Symbols. Fixes #3248 --- .../Account/FeedProvider/Twitter/TwitterSymbol.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Account/Sources/Account/FeedProvider/Twitter/TwitterSymbol.swift b/Account/Sources/Account/FeedProvider/Twitter/TwitterSymbol.swift index 525a1a595..9b1119743 100644 --- a/Account/Sources/Account/FeedProvider/Twitter/TwitterSymbol.swift +++ b/Account/Sources/Account/FeedProvider/Twitter/TwitterSymbol.swift @@ -10,18 +10,18 @@ import Foundation struct TwitterSymbol: Codable, TwitterEntity { - let name: String? + let text: String? let indices: [Int]? enum CodingKeys: String, CodingKey { - case name = "name" + case text = "text" case indices = "indices" } func renderAsHTML() -> String { var html = String() - if let name = name { - html += "$\(name)" + if let text = text { + html += "$\(text)" } return html } From 05e3ff9fd20c4a972be70b8236a977ecd3fde6d4 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Tue, 17 Aug 2021 17:40:00 -0500 Subject: [PATCH 18/23] Replace newlines with line breaks. Fixes #3258 --- .../Sources/Account/FeedProvider/Twitter/TwitterStatus.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift b/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift index 275d4b354..eeef28076 100644 --- a/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift +++ b/Account/Sources/Account/FeedProvider/Twitter/TwitterStatus.swift @@ -115,7 +115,7 @@ private extension TwitterStatus { } if prevIndex < displayEndIndex { - html += String(text[prevIndex..") } return html From 8828c0eaaada5afa528b97b26632c3dc985f7860 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 21 Aug 2021 16:09:47 -0500 Subject: [PATCH 19/23] Revalidate the API keys if they are expired. Fixes #3210 --- .../ReaderAPI/ReaderAPIAccountDelegate.swift | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift index 7d36cb5be..85f6235e7 100644 --- a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift +++ b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift @@ -136,8 +136,35 @@ final class ReaderAPIAccountDelegate: AccountDelegate { case .failure(let error): DispatchQueue.main.async { self.refreshProgress.clear() + let wrappedError = AccountError.wrappedError(error: error, account: account) - completion(.failure(wrappedError)) + if wrappedError.isCredentialsError, let basicCredentials = try? account.retrieveCredentials(type: .readerBasic), let endpoint = account.endpointURL { + self.caller.credentials = basicCredentials + + self.caller.validateCredentials(endpoint: endpoint) { result in + switch result { + case .success(let apiCredentials): + if let apiCredentials = apiCredentials { + DispatchQueue.main.async { + try? account.storeCredentials(apiCredentials) + self.caller.credentials = apiCredentials + self.refreshAll(for: account, completion: completion) + } + } else { + DispatchQueue.main.async { + completion(.failure(wrappedError)) + } + } + case .failure: + DispatchQueue.main.async { + completion(.failure(wrappedError)) + } + } + } + + } else { + completion(.failure(wrappedError)) + } } } From 7773e31e17860fc81530bf65e0e846a2fe427093 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 21 Aug 2021 18:08:29 -0700 Subject: [PATCH 20/23] Release notes for 6.0.1 first TestFlight build. --- Technotes/ReleaseNotes-iOS.markdown | 16 ++++++++++++++++ .../NetNewsWire_ios_target_common.xcconfig | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Technotes/ReleaseNotes-iOS.markdown b/Technotes/ReleaseNotes-iOS.markdown index 8102b5fd3..7f4de89e5 100644 --- a/Technotes/ReleaseNotes-iOS.markdown +++ b/Technotes/ReleaseNotes-iOS.markdown @@ -1,5 +1,21 @@ # iOS Release Notes +### 6.0.1 TestFlight build 607 - 21 Aug 2021 + +Fixed bug where BazQux-synced feeds might stop updating +Fixed bug where words prepended with $ wouldn’t appear in Twitter feeds +Fixed bug where newlines would be just a space in Twitter feeds +Fixed a crashing bug in Twitter rendering +Fixed bug where hitting b key to open in browser wouldn’t always work +Fixed a crashing bug due to running code off the main thread that needed to be on the main thread +Fixed bug where article unread indicator could have wrong alpha in specific circumstances +Fixed bug using right arrow key to move focus to Article view +Fixed bug where long press could trigger a crash +Fixed bug where external URLs in Feedbin feeds might be lost +Fixed bug where favicons wouldn’t be found when a home page URL has non-ASCII characters +Fixed bug where iCloud syncing could stop prematurely when the sync database has records not in the local database + + ### 6.0 TestFlight build 604 - 31 May 2021 This is a final candidate diff --git a/xcconfig/common/NetNewsWire_ios_target_common.xcconfig b/xcconfig/common/NetNewsWire_ios_target_common.xcconfig index ef5675d42..f51679314 100644 --- a/xcconfig/common/NetNewsWire_ios_target_common.xcconfig +++ b/xcconfig/common/NetNewsWire_ios_target_common.xcconfig @@ -1,7 +1,7 @@ // High Level Settings common to both the iOS application and any extensions we bundle with it -MARKETING_VERSION = 6.0 -CURRENT_PROJECT_VERSION = 606 +MARKETING_VERSION = 6.0.1 +CURRENT_PROJECT_VERSION = 607 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon From 7c6ddb5d95dca4fdbcb747585e881809b939a0dc Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 21 Aug 2021 18:10:29 -0700 Subject: [PATCH 21/23] Update release notes for 607 --- Technotes/ReleaseNotes-iOS.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/Technotes/ReleaseNotes-iOS.markdown b/Technotes/ReleaseNotes-iOS.markdown index 7f4de89e5..76ba1e0ef 100644 --- a/Technotes/ReleaseNotes-iOS.markdown +++ b/Technotes/ReleaseNotes-iOS.markdown @@ -14,6 +14,7 @@ Fixed bug where long press could trigger a crash Fixed bug where external URLs in Feedbin feeds might be lost Fixed bug where favicons wouldn’t be found when a home page URL has non-ASCII characters Fixed bug where iCloud syncing could stop prematurely when the sync database has records not in the local database +Fixed bug where creating a new folder in iCloud and moving feeds to it wouldn’t sync correctly ### 6.0 TestFlight build 604 - 31 May 2021 From 799bd9aeb85a99312f6f4a83d18ba1001b95e75b Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 26 Aug 2021 15:54:22 -0500 Subject: [PATCH 22/23] Remove custom Hashable implementation. Fixes #3201 --- Account/Sources/Account/FeedIdentifier.swift | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/Account/Sources/Account/FeedIdentifier.swift b/Account/Sources/Account/FeedIdentifier.swift index 842963e74..05d3d7f23 100644 --- a/Account/Sources/Account/FeedIdentifier.swift +++ b/Account/Sources/Account/FeedIdentifier.swift @@ -12,7 +12,7 @@ public protocol FeedIdentifiable { var feedID: FeedIdentifier? { get } } -public enum FeedIdentifier: CustomStringConvertible, Hashable { +public enum FeedIdentifier: CustomStringConvertible, Hashable, Equatable { case smartFeed(String) // String is a unique identifier case script(String) // String is a unique identifier @@ -80,22 +80,4 @@ public enum FeedIdentifier: CustomStringConvertible, Hashable { } } - // MARK: - Hashable - - public func hash(into hasher: inout Hasher) { - switch self { - case .smartFeed(let id): - hasher.combine("smartFeed") - hasher.combine(id) - case .script(let id): - hasher.combine("smartFeed") - hasher.combine(id) - case .webFeed(_, let webFeedID): - hasher.combine("webFeed") - hasher.combine(webFeedID) - case .folder(_, let folderName): - hasher.combine("folder") - hasher.combine(folderName) - } - } } From fe080b8ddcdb8a3197acf760a788b641025bfa9c Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 28 Aug 2021 14:26:23 -0700 Subject: [PATCH 23/23] Bump build number to 608. Write release notes. --- Technotes/ReleaseNotes-iOS.markdown | 4 ++++ xcconfig/common/NetNewsWire_ios_target_common.xcconfig | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Technotes/ReleaseNotes-iOS.markdown b/Technotes/ReleaseNotes-iOS.markdown index 76ba1e0ef..4150dfb6c 100644 --- a/Technotes/ReleaseNotes-iOS.markdown +++ b/Technotes/ReleaseNotes-iOS.markdown @@ -1,5 +1,9 @@ # iOS Release Notes +### 6.0.1 TestFlight build 608 - 28 Aug 2021 + +Fixed our top crashing bug — it could happen when updating a table view + ### 6.0.1 TestFlight build 607 - 21 Aug 2021 Fixed bug where BazQux-synced feeds might stop updating diff --git a/xcconfig/common/NetNewsWire_ios_target_common.xcconfig b/xcconfig/common/NetNewsWire_ios_target_common.xcconfig index f51679314..af737cd42 100644 --- a/xcconfig/common/NetNewsWire_ios_target_common.xcconfig +++ b/xcconfig/common/NetNewsWire_ios_target_common.xcconfig @@ -1,7 +1,7 @@ // High Level Settings common to both the iOS application and any extensions we bundle with it MARKETING_VERSION = 6.0.1 -CURRENT_PROJECT_VERSION = 607 +CURRENT_PROJECT_VERSION = 608 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon