diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 604a4b9fc..3752177c8 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -72,7 +72,6 @@ 51554C25228B71910055115A /* SyncDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 51554C01228B6EB50055115A /* SyncDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 51554C30228B71A10055115A /* SyncDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51554C01228B6EB50055115A /* SyncDatabase.framework */; }; 51554C31228B71A10055115A /* SyncDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 51554C01228B6EB50055115A /* SyncDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 515ADE4022E11FAE006B2460 /* SystemMessageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 515ADE3F22E11FAE006B2460 /* SystemMessageViewController.swift */; }; 515D4FC123257A3200EE1167 /* FolderTreeControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97A11ED9F180007D329B /* FolderTreeControllerDelegate.swift */; }; 515D4FCA23257CB500EE1167 /* Node-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97971ED9EFAA007D329B /* Node-Extensions.swift */; }; 515D4FCC2325815A00EE1167 /* SafariExt.js in Resources */ = {isa = PBXBuildFile; fileRef = 515D4FCB2325815A00EE1167 /* SafariExt.js */; }; @@ -812,7 +811,6 @@ 514B7C8223205EFB00BAC947 /* RootSplitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootSplitViewController.swift; sourceTree = ""; }; 514B7D1E23219F3C00BAC947 /* AddControllerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddControllerType.swift; sourceTree = ""; }; 51554BFC228B6EB50055115A /* SyncDatabase.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SyncDatabase.xcodeproj; path = Frameworks/SyncDatabase/SyncDatabase.xcodeproj; sourceTree = SOURCE_ROOT; }; - 515ADE3F22E11FAE006B2460 /* SystemMessageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemMessageViewController.swift; sourceTree = ""; }; 515D4FCB2325815A00EE1167 /* SafariExt.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = SafariExt.js; sourceTree = ""; }; 515D4FCD2325909200EE1167 /* NetNewsWire_iOS_ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NetNewsWire_iOS_ShareExtension.entitlements; sourceTree = ""; }; 515D4FCE2325B3D000EE1167 /* NetNewsWire_iOSshareextension_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_iOSshareextension_target.xcconfig; sourceTree = ""; }; @@ -1379,7 +1377,6 @@ children = ( 51C4527E2265092C00C03939 /* DetailViewController.swift */, 517630222336657E00E15FFF /* DetailViewControllerWebViewProvider.swift */, - 515ADE3F22E11FAE006B2460 /* SystemMessageViewController.swift */, ); path = Detail; sourceTree = ""; @@ -2704,7 +2701,6 @@ 51EAED96231363EF00A9EEE3 /* NonIntrinsicButton.swift in Sources */, 51C4527B2265091600C03939 /* MasterUnreadIndicatorView.swift in Sources */, 5152E1022324900D00E5C7AD /* SettingsAddAccountView.swift in Sources */, - 515ADE4022E11FAE006B2460 /* SystemMessageViewController.swift in Sources */, 51F85BF92274AA7B00C787DC /* UIBarButtonItem-Extensions.swift in Sources */, 51B62E68233186730085F949 /* MasterTimelineAvatarView.swift in Sources */, 51C45296226509D300C03939 /* OPMLExporter.swift in Sources */, diff --git a/iOS/Base.lproj/Main.storyboard b/iOS/Base.lproj/Main.storyboard index e58263b3e..ef1fd9be4 100644 --- a/iOS/Base.lproj/Main.storyboard +++ b/iOS/Base.lproj/Main.storyboard @@ -113,39 +113,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/iOS/Detail/DetailViewController.swift b/iOS/Detail/DetailViewController.swift index 9878be601..bf2e35ad7 100644 --- a/iOS/Detail/DetailViewController.swift +++ b/iOS/Detail/DetailViewController.swift @@ -12,6 +12,14 @@ import Account import Articles import SafariServices +enum DetailViewState: Equatable { + case noSelection + case multipleSelection + case loading + case article(Article) + case extracted(Article, ExtractedArticle) +} + class DetailViewController: UIViewController { @IBOutlet private weak var nextUnreadBarButtonItem: UIBarButtonItem! @@ -26,6 +34,26 @@ class DetailViewController: UIViewController { weak var coordinator: SceneCoordinator! + var state: DetailViewState = .noSelection { + didSet { + if state != oldValue { + updateUI() + reloadHTML() + } + } + } + + var currentArticle: Article? { + switch state { + case .article(let article): + return article + case .extracted(let article, _): + return article + default: + return nil + } + } + private let keyboardManager = KeyboardManager(type: .detail) override var keyCommands: [UIKeyCommand]? { return keyboardManager.keyCommands @@ -66,7 +94,7 @@ class DetailViewController: UIViewController { func updateUI() { - guard let article = coordinator.currentArticle else { + guard let article = currentArticle else { nextUnreadBarButtonItem.isEnabled = false prevArticleBarButtonItem.isEnabled = false nextArticleBarButtonItem.isEnabled = false @@ -95,12 +123,22 @@ class DetailViewController: UIViewController { } func reloadHTML() { - guard let article = coordinator.currentArticle, let webView = webView else { - return - } - + let style = ArticleStylesManager.shared.currentStyle - let rendering = ArticleRenderer.articleHTML(article: article, style: style) + let rendering: ArticleRenderer.Rendering + + switch state { + case .noSelection: + rendering = ArticleRenderer.noSelectionHTML(style: style) + case .multipleSelection: + rendering = ArticleRenderer.multipleSelectionHTML(style: style) + case .loading: + rendering = ArticleRenderer.loadingHTML(style: style) + case .article(let article): + rendering = ArticleRenderer.articleHTML(article: article, style: style) + case .extracted(let article, let extractedArticle): + rendering = ArticleRenderer.articleHTML(article: article, extractedArticle: extractedArticle, style: style) + } let templateData = TemplateData(style: rendering.style, body: rendering.html) @@ -111,7 +149,8 @@ class DetailViewController: UIViewController { render = "render(\(json));" } - webView.evaluateJavaScript(render) + webView?.evaluateJavaScript(render) + } // MARK: Notifications @@ -124,7 +163,7 @@ class DetailViewController: UIViewController { guard let articles = note.userInfo?[Account.UserInfoKey.articles] as? Set
else { return } - if articles.count == 1 && articles.first?.articleID == coordinator.currentArticle?.articleID { + if articles.count == 1 && articles.first?.articleID == currentArticle?.articleID { updateUI() } } @@ -164,11 +203,11 @@ class DetailViewController: UIViewController { } @IBAction func showActivityDialog(_ sender: Any) { - guard let currentArticle = coordinator.currentArticle, let preferredLink = currentArticle.preferredLink, let url = URL(string: preferredLink) else { + guard let preferredLink = currentArticle?.preferredLink, let url = URL(string: preferredLink) else { return } - let itemSource = ArticleActivityItemSource(url: url, subject: currentArticle.title) + let itemSource = ArticleActivityItemSource(url: url, subject: currentArticle!.title) let activityViewController = UIActivityViewController(activityItems: [itemSource], applicationActivities: nil) activityViewController.popoverPresentationController?.barButtonItem = actionBarButtonItem present(activityViewController, animated: true) @@ -180,10 +219,6 @@ class DetailViewController: UIViewController { } // MARK: API - func updateArticleSelection() { - updateUI() - reloadHTML() - } func focus() { webView.becomeFirstResponder() @@ -241,7 +276,8 @@ extension DetailViewController: WKNavigationDelegate { } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { - self.updateArticleSelection() + self.updateUI() + self.reloadHTML() } } diff --git a/iOS/Detail/SystemMessageViewController.swift b/iOS/Detail/SystemMessageViewController.swift deleted file mode 100644 index cafd2397e..000000000 --- a/iOS/Detail/SystemMessageViewController.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// SystemMessageViewController.swift -// NetNewsWire-iOS -// -// Created by Maurice Parker on 7/18/19. -// Copyright © 2019 Ranchero Software. All rights reserved. -// - -import UIKit - -class SystemMessageViewController: UIViewController { - - @IBOutlet weak var messageLabel: UILabel! - var message: String = NSLocalizedString("No Selection", comment: "No Selection") - - override func viewDidLoad() { - super.viewDidLoad() - messageLabel.text = message - } - -} diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index baed463b2..ffb6f983f 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -289,8 +289,10 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { masterFeedViewController.coordinator = self masterNavigationController.pushViewController(masterFeedViewController, animated: false) - let noSelectionController = fullyWrappedSystemMesssageController(showButton: true) - rootSplitViewController.showDetailViewController(noSelectionController, sender: self) + let detailViewController = UIStoryboard.main.instantiateController(ofType: DetailViewController.self) + detailViewController.coordinator = self + let detailNavigationController = addNavControllerIfNecessary(detailViewController, showButton: false) + rootSplitViewController.showDetailViewController(detailNavigationController, sender: self) configureThreePanelMode(for: size) @@ -560,8 +562,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { masterNavigationController.popViewController(animated: !automated) } } else { - let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) - installDetailController(systemMessageViewController, automated: automated) + detailViewController?.state = .noSelection } masterTimelineViewController?.updateArticleSelection(animate: !automated) return @@ -577,11 +578,12 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { masterTimelineViewController?.updateArticleSelection(animate: false) } - detailViewController?.updateArticleSelection() + detailViewController?.state = .article(article!) if let article = currentArticle { markArticles(Set([article]), statusKey: .read, flag: true) } + } func beginSearching() { @@ -1396,12 +1398,6 @@ private extension SceneCoordinator { } } - func fullyWrappedSystemMesssageController(showButton: Bool) -> UIViewController { - let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) - let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: showButton) - return navController - } - @discardableResult func transitionToThreePanelMode() -> UIViewController { @@ -1413,7 +1409,9 @@ private extension SceneCoordinator { if let result = detailViewController { return result } else { - return UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) + let detailController = UIStoryboard.main.instantiateController(ofType: DetailViewController.self) + detailController.coordinator = self + return detailController } }()