From 31af975174d29470f96c38dc8530afcdb333c479 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Thu, 24 Jun 2021 07:49:13 +0800 Subject: [PATCH 01/17] applies fullWidth to accounts --- Mac/Base.lproj/Preferences.storyboard | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mac/Base.lproj/Preferences.storyboard b/Mac/Base.lproj/Preferences.storyboard index ddd693d02..b9ad21c4b 100644 --- a/Mac/Base.lproj/Preferences.storyboard +++ b/Mac/Base.lproj/Preferences.storyboard @@ -412,7 +412,7 @@ - + From 1bda0c37346b87caa3facd18b74ffa0553fee2af Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Thu, 24 Jun 2021 07:50:23 +0800 Subject: [PATCH 02/17] adds full width to extensions --- Mac/Base.lproj/Preferences.storyboard | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mac/Base.lproj/Preferences.storyboard b/Mac/Base.lproj/Preferences.storyboard index b9ad21c4b..d22ee1785 100644 --- a/Mac/Base.lproj/Preferences.storyboard +++ b/Mac/Base.lproj/Preferences.storyboard @@ -583,7 +583,7 @@ - + From 83b349925faa53fdb2ef40cadab309be4a0f66ad Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 26 Jun 2021 14:23:40 -0500 Subject: [PATCH 03/17] 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 b5492931676c19d73c2b0eeb429b8c43f060df5d Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 26 Jun 2021 18:15:05 -0500 Subject: [PATCH 04/17] 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 100823e57ee49fb20785aa8ff1240326cc5dcafb Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 26 Jun 2021 20:54:17 -0500 Subject: [PATCH 05/17] 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 c10aa8412bd0e90eb4f47f8dc027cba8cb27e44b Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 5 Jul 2021 14:24:50 -0500 Subject: [PATCH 06/17] 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 e33d624dd8ee167be8409fbd696a4d0944f5ba71 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Tue, 6 Jul 2021 16:52:31 -0500 Subject: [PATCH 07/17] 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 26497e916..459305902 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 1b24140e1ab6b4982600a0a8618e9977d94242ea Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Wed, 7 Jul 2021 12:24:21 -0500 Subject: [PATCH 08/17] 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 459305902..b469a034e 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 f47e82f804d7e92bd1d988a883870a00378b77d9 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 8 Jul 2021 13:09:26 -0500 Subject: [PATCH 09/17] 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 b469a034e..ecffb9689 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 634d728ebed00fa2d3f0e3e382ebef69b6bfd8da Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 9 Jul 2021 11:56:05 -0500 Subject: [PATCH 10/17] 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 ecffb9689..6592ae7c1 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 8ae2f9583ce4df6ad2b31e18b8217cff3e8a4e19 Mon Sep 17 00:00:00 2001 From: Nate Weaver Date: Sun, 18 Jul 2021 17:01:59 -0500 Subject: [PATCH 11/17] 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 8080136bb8ab3c3757689d81a1b4d79c11d82acf Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Wed, 21 Jul 2021 17:01:57 -0500 Subject: [PATCH 12/17] 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 18ad76e7b9887ed961cdeb916f68d9418ed86bf7 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Tue, 27 Jul 2021 13:37:31 -0500 Subject: [PATCH 13/17] 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 acccc4f063935a847de1d6332f77a2935d14454b Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 29 Jul 2021 17:11:22 -0500 Subject: [PATCH 14/17] 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 418711849..418c1c81a 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 b38ee75ba24fa7e1b6b50eeea4ba0d0ebca101ce Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Tue, 10 Aug 2021 20:07:38 -0500 Subject: [PATCH 15/17] 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 4820d3eee65d959e8edbed9872e4d8fa5948e2a5 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Tue, 17 Aug 2021 17:40:00 -0500 Subject: [PATCH 16/17] 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 8634858249dec2b6f0665d510279d15a34b74633 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 21 Aug 2021 16:09:47 -0500 Subject: [PATCH 17/17] 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 16d333340..87db27815 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)) + } } }