Merge pull request #3079 from babbage/bugfix/3069

Handle links with unencoded spaces. Fixes #3069
This commit is contained in:
Brent Simmons 2021-04-28 21:55:46 -07:00 committed by GitHub
commit 790218501b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 24 additions and 33 deletions

View File

@ -38,7 +38,7 @@ extension Article: PasteboardWriterOwner {
func writableTypes(for pasteboard: NSPasteboard) -> [NSPasteboard.PasteboardType] { func writableTypes(for pasteboard: NSPasteboard) -> [NSPasteboard.PasteboardType] {
var types = [ArticlePasteboardWriter.articleUTIType] var types = [ArticlePasteboardWriter.articleUTIType]
if let link = article.preferredLink, let _ = URL(string: link) { if let _ = article.preferredURL {
types += [.URL] types += [.URL]
} }
types += [.string, .html, ArticlePasteboardWriter.articleUTIInternalType] types += [.string, .html, ArticlePasteboardWriter.articleUTIInternalType]

View File

@ -107,7 +107,7 @@ struct ArticleToolbarModifier: ViewModifier {
.disabled(sceneModel.shareButtonState == nil) .disabled(sceneModel.shareButtonState == nil)
.help("Share") .help("Share")
.sheet(isPresented: $showActivityView) { .sheet(isPresented: $showActivityView) {
if let article = sceneModel.selectedArticles.first, let link = article.preferredLink, let url = URL(string: link) { if let article = sceneModel.selectedArticles.first, let url = article.preferredURL {
ActivityViewController(title: article.title, url: url) ActivityViewController(title: article.title, url: url)
} }
} }

View File

@ -249,12 +249,11 @@ class TimelineModel: ObservableObject, UndoableCommandRunner {
} }
func openIndicatedArticleInBrowser(_ article: Article) { func openIndicatedArticleInBrowser(_ article: Article) {
guard let link = article.preferredLink else { return }
#if os(macOS) #if os(macOS)
guard let link = article.preferredLink else { return }
Browser.open(link, invertPreference: NSApp.currentEvent?.modifierFlags.contains(.shift) ?? false) Browser.open(link, invertPreference: NSApp.currentEvent?.modifierFlags.contains(.shift) ?? false)
#else #else
guard let url = URL(string: link) else { return } guard let url = article.preferredURL else { return }
UIApplication.shared.open(url, options: [:]) UIApplication.shared.open(url, options: [:])
#endif #endif
} }

View File

@ -56,6 +56,18 @@ extension Article {
return nil return nil
} }
var preferredURL: URL? {
guard let link = preferredLink else { return nil }
// If required, we replace any space characters to handle malformed links that are otherwise percent
// encoded but contain spaces. For performance reasons, only try this if initial URL init fails.
if let url = URL(string: link) {
return url
} else if let url = URL(string: link.replacingOccurrences(of: " ", with: "%20")) {
return url
}
return nil
}
var body: String? { var body: String? {
return contentHTML ?? contentText ?? summary return contentHTML ?? contentText ?? summary
} }

View File

@ -235,20 +235,14 @@ class WebViewController: UIViewController {
} }
func showActivityDialog(popOverBarButtonItem: UIBarButtonItem? = nil) { func showActivityDialog(popOverBarButtonItem: UIBarButtonItem? = nil) {
guard let preferredLink = article?.preferredLink, let url = URL(string: preferredLink) else { guard let url = article?.preferredURL else { return }
return
}
let activityViewController = UIActivityViewController(url: url, title: article?.title, applicationActivities: [FindInArticleActivity(), OpenInBrowserActivity()]) let activityViewController = UIActivityViewController(url: url, title: article?.title, applicationActivities: [FindInArticleActivity(), OpenInBrowserActivity()])
activityViewController.popoverPresentationController?.barButtonItem = popOverBarButtonItem activityViewController.popoverPresentationController?.barButtonItem = popOverBarButtonItem
present(activityViewController, animated: true) present(activityViewController, animated: true)
} }
func openInAppBrowser() { func openInAppBrowser() {
guard let preferredLink = article?.preferredLink, let url = URL(string: preferredLink) else { guard let url = article?.preferredURL else { return }
return
}
let vc = SFSafariViewController(url: url) let vc = SFSafariViewController(url: url)
present(vc, animated: true) present(vc, animated: true)
} }

View File

@ -889,9 +889,7 @@ private extension MasterTimelineViewController {
} }
func openInBrowserAction(_ article: Article) -> UIAction? { func openInBrowserAction(_ article: Article) -> UIAction? {
guard let preferredLink = article.preferredLink, let _ = URL(string: preferredLink) else { guard let _ = article.preferredURL else { return nil }
return nil
}
let title = NSLocalizedString("Open in Browser", comment: "Open in Browser") let title = NSLocalizedString("Open in Browser", comment: "Open in Browser")
let action = UIAction(title: title, image: AppAssets.safariImage) { [weak self] action in let action = UIAction(title: title, image: AppAssets.safariImage) { [weak self] action in
self?.coordinator.showBrowserForArticle(article) self?.coordinator.showBrowserForArticle(article)
@ -900,9 +898,7 @@ private extension MasterTimelineViewController {
} }
func openInBrowserAlertAction(_ article: Article, completion: @escaping (Bool) -> Void) -> UIAlertAction? { func openInBrowserAlertAction(_ article: Article, completion: @escaping (Bool) -> Void) -> UIAlertAction? {
guard let preferredLink = article.preferredLink, let _ = URL(string: preferredLink) else { guard let _ = article.preferredURL else { return nil }
return nil
}
let title = NSLocalizedString("Open in Browser", comment: "Open in Browser") let title = NSLocalizedString("Open in Browser", comment: "Open in Browser")
let action = UIAlertAction(title: title, style: .default) { [weak self] action in let action = UIAlertAction(title: title, style: .default) { [weak self] action in
self?.coordinator.showBrowserForArticle(article) self?.coordinator.showBrowserForArticle(article)
@ -923,10 +919,7 @@ private extension MasterTimelineViewController {
} }
func shareAction(_ article: Article, indexPath: IndexPath) -> UIAction? { func shareAction(_ article: Article, indexPath: IndexPath) -> UIAction? {
guard let preferredLink = article.preferredLink, let url = URL(string: preferredLink) else { guard let url = article.preferredURL else { return nil }
return nil
}
let title = NSLocalizedString("Share", comment: "Share") let title = NSLocalizedString("Share", comment: "Share")
let action = UIAction(title: title, image: AppAssets.shareImage) { [weak self] action in let action = UIAction(title: title, image: AppAssets.shareImage) { [weak self] action in
self?.shareDialogForTableCell(indexPath: indexPath, url: url, title: article.title) self?.shareDialogForTableCell(indexPath: indexPath, url: url, title: article.title)
@ -935,10 +928,7 @@ private extension MasterTimelineViewController {
} }
func shareAlertAction(_ article: Article, indexPath: IndexPath, completion: @escaping (Bool) -> Void) -> UIAlertAction? { func shareAlertAction(_ article: Article, indexPath: IndexPath, completion: @escaping (Bool) -> Void) -> UIAlertAction? {
guard let preferredLink = article.preferredLink, let url = URL(string: preferredLink) else { guard let url = article.preferredURL else { return nil }
return nil
}
let title = NSLocalizedString("Share", comment: "Share") let title = NSLocalizedString("Share", comment: "Share")
let action = UIAlertAction(title: title, style: .default) { [weak self] action in let action = UIAlertAction(title: title, style: .default) { [weak self] action in
completion(true) completion(true)

View File

@ -1238,16 +1238,12 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
} }
func showBrowserForArticle(_ article: Article) { func showBrowserForArticle(_ article: Article) {
guard let preferredLink = article.preferredLink, let url = URL(string: preferredLink) else { guard let url = article.preferredURL else { return }
return
}
UIApplication.shared.open(url, options: [:]) UIApplication.shared.open(url, options: [:])
} }
func showBrowserForCurrentArticle() { func showBrowserForCurrentArticle() {
guard let preferredLink = currentArticle?.preferredLink, let url = URL(string: preferredLink) else { guard let url = currentArticle?.preferredURL else { return }
return
}
UIApplication.shared.open(url, options: [:]) UIApplication.shared.open(url, options: [:])
} }