From 6f9d3953f1166d4c44909708baeb365856e1264d Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 23 Sep 2019 09:57:50 -0500 Subject: [PATCH 01/11] Ensure that account metadata gets propagated to delegates when it reloads --- Frameworks/Account/Account.swift | 6 +++++- Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift | 1 - Frameworks/Account/Feedly/FeedlyAccountDelegate.swift | 1 - Frameworks/Account/ReaderAPI/ReaderAPIAccountDelegate.swift | 1 - 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index bc10ad7ee..f3a2ed70e 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -174,7 +174,11 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, private lazy var opmlFile = OPMLFile(filename: (dataFolder as NSString).appendingPathComponent("Subscriptions.opml"), account: self) private lazy var metadataFile = AccountMetadataFile(filename: (dataFolder as NSString).appendingPathComponent("Settings.plist"), account: self) - var metadata = AccountMetadata() + var metadata = AccountMetadata() { + didSet { + delegate.accountMetadata = metadata + } + } private lazy var feedMetadataFile = FeedMetadataFile(filename: (dataFolder as NSString).appendingPathComponent("FeedMetadata.plist"), account: self) typealias FeedMetadataDictionary = [String: FeedMetadata] diff --git a/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift b/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift index 597a6db67..4eace99df 100644 --- a/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift @@ -524,7 +524,6 @@ final class FeedbinAccountDelegate: AccountDelegate { func accountDidInitialize(_ account: Account) { credentials = try? account.retrieveCredentials(type: .basic) - accountMetadata = account.metadata } static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL? = nil, completion: @escaping (Result) -> Void) { diff --git a/Frameworks/Account/Feedly/FeedlyAccountDelegate.swift b/Frameworks/Account/Feedly/FeedlyAccountDelegate.swift index f154438be..79bbef237 100644 --- a/Frameworks/Account/Feedly/FeedlyAccountDelegate.swift +++ b/Frameworks/Account/Feedly/FeedlyAccountDelegate.swift @@ -170,7 +170,6 @@ final class FeedlyAccountDelegate: AccountDelegate { } func accountDidInitialize(_ account: Account) { -// accountMetadata = account.metadata credentials = try? account.retrieveCredentials(type: .oauthAccessToken) syncStrategy = FeedlySyncStrategy(account: account, caller: caller, log: log) diff --git a/Frameworks/Account/ReaderAPI/ReaderAPIAccountDelegate.swift b/Frameworks/Account/ReaderAPI/ReaderAPIAccountDelegate.swift index 6ee8edc11..4b895b0ed 100644 --- a/Frameworks/Account/ReaderAPI/ReaderAPIAccountDelegate.swift +++ b/Frameworks/Account/ReaderAPI/ReaderAPIAccountDelegate.swift @@ -411,7 +411,6 @@ final class ReaderAPIAccountDelegate: AccountDelegate { } func accountDidInitialize(_ account: Account) { - accountMetadata = account.metadata credentials = try? account.retrieveCredentials(type: .readerAPIKey) } From 0424ba3bb778631aded4e0fed76645d336006feb Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 23 Sep 2019 10:27:17 -0500 Subject: [PATCH 02/11] Make unread counts show up for new feeds added by share extension --- Frameworks/Account/Account.swift | 5 +++-- Frameworks/Account/FeedMetadataFile.swift | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index f3a2ed70e..9f0a7f88e 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -184,7 +184,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, typealias FeedMetadataDictionary = [String: FeedMetadata] var feedMetadata = FeedMetadataDictionary() - private var startingUp = true + var startingUp = true public var unreadCount = 0 { didSet { @@ -406,10 +406,11 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, } - public func resetAllFeedMetadata() { + public func resetFeedMetadataAndUnreadCounts() { for feed in flattenedFeeds() { feed.metadata = feedMetadata(feedURL: feed.url, feedID: feed.feedID) } + fetchAllUnreadCounts() NotificationCenter.default.post(name: .FeedMetadataDidChange, object: self, userInfo: nil) } diff --git a/Frameworks/Account/FeedMetadataFile.swift b/Frameworks/Account/FeedMetadataFile.swift index e9314a4f0..d56f2a749 100644 --- a/Frameworks/Account/FeedMetadataFile.swift +++ b/Frameworks/Account/FeedMetadataFile.swift @@ -49,7 +49,9 @@ private extension FeedMetadataFile { let decoder = PropertyListDecoder() account.feedMetadata = (try? decoder.decode(Account.FeedMetadataDictionary.self, from: fileData)) ?? Account.FeedMetadataDictionary() account.feedMetadata.values.forEach { $0.delegate = account } - account.resetAllFeedMetadata() + if !account.startingUp { + account.resetFeedMetadataAndUnreadCounts() + } } }) From de994a305e9882efc274b3f24080699ea9796456 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 23 Sep 2019 10:35:48 -0500 Subject: [PATCH 03/11] Remove dead code. --- Frameworks/Account/Account.swift | 2 +- Frameworks/Account/AccountMetadataFile.swift | 4 ---- Frameworks/Account/FeedMetadataFile.swift | 4 ---- Frameworks/Account/OPMLFile.swift | 4 ---- 4 files changed, 1 insertion(+), 13 deletions(-) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 9f0a7f88e..ccd90f376 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -206,7 +206,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, } else { NotificationCenter.default.post(name: .AccountRefreshDidFinish, object: self) - opmlFile.queueSaveToDiskIfNeeded() + opmlFile.markAsDirty() } } } diff --git a/Frameworks/Account/AccountMetadataFile.swift b/Frameworks/Account/AccountMetadataFile.swift index 14457dc45..e38a49a1e 100644 --- a/Frameworks/Account/AccountMetadataFile.swift +++ b/Frameworks/Account/AccountMetadataFile.swift @@ -27,10 +27,6 @@ final class AccountMetadataFile { managedFile.markAsDirty() } - func queueSaveToDiskIfNeeded() { - managedFile.queueSaveToDiskIfNeeded() - } - func load() { managedFile.load() } diff --git a/Frameworks/Account/FeedMetadataFile.swift b/Frameworks/Account/FeedMetadataFile.swift index d56f2a749..bb3384fa1 100644 --- a/Frameworks/Account/FeedMetadataFile.swift +++ b/Frameworks/Account/FeedMetadataFile.swift @@ -27,10 +27,6 @@ final class FeedMetadataFile { managedFile.markAsDirty() } - func queueSaveToDiskIfNeeded() { - managedFile.queueSaveToDiskIfNeeded() - } - func load() { managedFile.load() } diff --git a/Frameworks/Account/OPMLFile.swift b/Frameworks/Account/OPMLFile.swift index c21d1f8d3..39ace29b8 100644 --- a/Frameworks/Account/OPMLFile.swift +++ b/Frameworks/Account/OPMLFile.swift @@ -28,10 +28,6 @@ final class OPMLFile { managedFile.markAsDirty() } - func queueSaveToDiskIfNeeded() { - managedFile.queueSaveToDiskIfNeeded() - } - func load() { managedFile.load() } From 59991d0478794d26f95be42ff2ea06b704789c95 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 23 Sep 2019 11:09:40 -0500 Subject: [PATCH 04/11] Save resource files immediately in the share extension --- Frameworks/Account/Account.swift | 6 ++++++ Frameworks/Account/AccountMetadataFile.swift | 4 ++++ Frameworks/Account/FeedMetadataFile.swift | 4 ++++ Frameworks/Account/OPMLFile.swift | 4 ++++ iOS/ShareExtension/ShareViewController.swift | 1 + submodules/RSCore | 2 +- 6 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index ccd90f376..c7ad1a617 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -368,6 +368,12 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, } + public func saveIfNecessary() { + metadataFile.saveIfNecessary() + feedMetadataFile.saveIfNecessary() + opmlFile.saveIfNecessary() + } + func loadOPMLItems(_ items: [RSOPMLItem], parentFolder: Folder?) { var feedsToAdd = Set() diff --git a/Frameworks/Account/AccountMetadataFile.swift b/Frameworks/Account/AccountMetadataFile.swift index e38a49a1e..cb1aaed5d 100644 --- a/Frameworks/Account/AccountMetadataFile.swift +++ b/Frameworks/Account/AccountMetadataFile.swift @@ -31,6 +31,10 @@ final class AccountMetadataFile { managedFile.load() } + func saveIfNecessary() { + managedFile.saveIfNecessary() + } + } private extension AccountMetadataFile { diff --git a/Frameworks/Account/FeedMetadataFile.swift b/Frameworks/Account/FeedMetadataFile.swift index bb3384fa1..a602819b6 100644 --- a/Frameworks/Account/FeedMetadataFile.swift +++ b/Frameworks/Account/FeedMetadataFile.swift @@ -31,6 +31,10 @@ final class FeedMetadataFile { managedFile.load() } + func saveIfNecessary() { + managedFile.saveIfNecessary() + } + } private extension FeedMetadataFile { diff --git a/Frameworks/Account/OPMLFile.swift b/Frameworks/Account/OPMLFile.swift index 39ace29b8..6cc06eeb2 100644 --- a/Frameworks/Account/OPMLFile.swift +++ b/Frameworks/Account/OPMLFile.swift @@ -32,6 +32,10 @@ final class OPMLFile { managedFile.load() } + func saveIfNecessary() { + managedFile.saveIfNecessary() + } + } private extension OPMLFile { diff --git a/iOS/ShareExtension/ShareViewController.swift b/iOS/ShareExtension/ShareViewController.swift index 19d42cb4e..1510ff04b 100644 --- a/iOS/ShareExtension/ShareViewController.swift +++ b/iOS/ShareExtension/ShareViewController.swift @@ -119,6 +119,7 @@ class ShareViewController: SLComposeServiceViewController, ShareFolderPickerCont switch result { case .success: + account!.saveIfNecessary() self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil) case .failure(let error): self.presentError(error) { diff --git a/submodules/RSCore b/submodules/RSCore index ced48ad15..55afb4585 160000 --- a/submodules/RSCore +++ b/submodules/RSCore @@ -1 +1 @@ -Subproject commit ced48ad15ebc762fea50beb618eed3cf10721148 +Subproject commit 55afb45853754e4a894035edc05fd4b5823472ca From f1819fb39cb87cf36e87c69298591d09cc84f445 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 23 Sep 2019 12:05:44 -0500 Subject: [PATCH 05/11] Use correct name for display --- iOS/MasterFeed/MasterFeedViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index 10006583b..bd4589151 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -223,7 +223,7 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { if let self = self { - let alert = UIAlertController(title: feed.name, message: nil, preferredStyle: .actionSheet) + let alert = UIAlertController(title: feed.nameForDisplay, message: nil, preferredStyle: .actionSheet) if let popoverController = alert.popoverPresentationController { popoverController.sourceView = view popoverController.sourceRect = CGRect(x: view.frame.size.width/2, y: view.frame.size.height/2, width: 1, height: 1) From eaf798991f1166c141dc39e38bdf4f79ad787a29 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 23 Sep 2019 12:29:48 -0500 Subject: [PATCH 06/11] Remove name from the feed metadata as we manage it using the OPML file instead --- Frameworks/Account/Feed.swift | 13 +------------ Frameworks/Account/FeedMetadata.swift | 9 --------- ...lyCreateFeedsForCollectionFoldersOperation.swift | 7 ++++++- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/Frameworks/Account/Feed.swift b/Frameworks/Account/Feed.swift index 5a7a4c3ec..114964430 100644 --- a/Frameworks/Account/Feed.swift +++ b/Frameworks/Account/Feed.swift @@ -65,18 +65,7 @@ public final class Feed: DisplayNameProvider, Renamable, UnreadCountProvider, Ha } } - public var name: String? { - get { - return metadata.name - } - set { - let oldNameForDisplay = nameForDisplay - metadata.name = newValue - if oldNameForDisplay != newValue { - postDisplayNameDidChangeNotification() - } - } - } + public var name: String? public var authors: Set? { get { diff --git a/Frameworks/Account/FeedMetadata.swift b/Frameworks/Account/FeedMetadata.swift index 2509b1e04..7da7ac9c0 100644 --- a/Frameworks/Account/FeedMetadata.swift +++ b/Frameworks/Account/FeedMetadata.swift @@ -21,7 +21,6 @@ final class FeedMetadata: Codable { case homePageURL case iconURL case faviconURL - case name case editedName case authors case contentHash @@ -63,14 +62,6 @@ final class FeedMetadata: Codable { } } - var name: String? { - didSet { - if name != oldValue { - valueDidChange(.name) - } - } - } - var editedName: String? { didSet { if editedName != oldValue { diff --git a/Frameworks/Account/Feedly/FeedlyCreateFeedsForCollectionFoldersOperation.swift b/Frameworks/Account/Feedly/FeedlyCreateFeedsForCollectionFoldersOperation.swift index 62c601535..5b22a2aa1 100644 --- a/Frameworks/Account/Feedly/FeedlyCreateFeedsForCollectionFoldersOperation.swift +++ b/Frameworks/Account/Feedly/FeedlyCreateFeedsForCollectionFoldersOperation.swift @@ -52,7 +52,12 @@ final class FeedlyCreateFeedsForCollectionFoldersOperation: FeedlySyncOperation let url = collectionFeed.id let metadata = FeedMetadata(feedID: url) // TODO: More metadata - metadata.name = collectionFeed.title + + // Kiel, I'm commenting this out as we shouldn't be storing the name + // in the feed metadata. It should be stored in the OPML file. + // You can just set the name directly on the feed itself. +// metadata.name = collectionFeed.title + let feed = Feed(account: account, url: url, metadata: metadata) // So the same feed isn't created more than once. From b8dd63b55310bcd4eca541454730e30781cacd3a Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 23 Sep 2019 17:56:10 -0500 Subject: [PATCH 07/11] Remove obsolete split view controller code --- iOS/SceneCoordinator.swift | 53 -------------------------------------- 1 file changed, 53 deletions(-) diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index ae8e43b85..baed463b2 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -852,60 +852,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { extension SceneCoordinator: UISplitViewControllerDelegate { func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool { - - // Check to see if the system is currently configured for three panel mode - if let subSplit = secondaryViewController as? UISplitViewController { - - // Take the timeline controller out of the subsplit and throw it on the master navigation stack - if let masterTimelineNav = subSplit.viewControllers.first as? UINavigationController, let masterTimeline = masterTimelineNav.topViewController { - masterNavigationController.pushViewController(masterTimeline, animated: false) - } - - // Take the detail view (ignoring system message controllers) and put it on the master navigation stack - if let detailNav = subSplit.viewControllers.last as? UINavigationController, let detail = detailNav.topViewController as? DetailViewController { - masterNavigationController.pushViewController(detail, animated: false) - } - - } else { - - // If the timeline controller has been initialized and only the feeds controller is on the stack, we add the timeline controller - if let timeline = masterTimelineViewController, masterNavigationController.viewControllers.count == 1 { - masterNavigationController.pushViewController(timeline, animated: false) - } - - // Take the detail view (ignoring system message controllers) and put it on the master navigation stack - if let detailNav = secondaryViewController as? UINavigationController, let detail = detailNav.topViewController as? DetailViewController { - // I have no idea why, I have to wire up the left bar button item for this, but not when I am transitioning from three panel mode - detail.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem - detail.navigationItem.leftItemsSupplementBackButton = true - masterNavigationController.pushViewController(detail, animated: false) - } - - } - return true - - } - - func splitViewController(_ splitViewController: UISplitViewController, separateSecondaryFrom primaryViewController: UIViewController) -> UIViewController? { - - if isThreePanelMode { - return transitionToThreePanelMode() - } - - if let detail = masterNavigationController.viewControllers.last as? DetailViewController { - - // If we have a detail controller on the stack, remove it and return it. - masterNavigationController.viewControllers.removeLast() - let detailNav = addNavControllerIfNecessary(detail, showButton: true) - return detailNav - - } else { - - // Display a no selection controller since we don't have any detail selected - return fullyWrappedSystemMesssageController(showButton: true) - - } } } From a9047105dbd0c685bdea3499516b1a687c4699d6 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 23 Sep 2019 19:23:23 -0500 Subject: [PATCH 08/11] Remove unnecessary system message controller --- NetNewsWire.xcodeproj/project.pbxproj | 4 -- iOS/Base.lproj/Main.storyboard | 34 +--------- iOS/Detail/DetailViewController.swift | 66 +++++++++++++++----- iOS/Detail/SystemMessageViewController.swift | 21 ------- iOS/SceneCoordinator.swift | 22 +++---- 5 files changed, 62 insertions(+), 85 deletions(-) delete mode 100644 iOS/Detail/SystemMessageViewController.swift 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 } }() From cb394a2a6143f7abacec688b67621a81189fd371 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 23 Sep 2019 19:56:16 -0500 Subject: [PATCH 09/11] add APPLICATION_EXTENSION_API_ONLY build setting --- Frameworks/Account/xcconfig/Account_target.xcconfig | 2 +- Frameworks/Articles/Articles.xcodeproj/project.pbxproj | 2 ++ Frameworks/Articles/xcconfig/Articles_target.xcconfig | 2 +- .../ArticlesDatabase/xcconfig/ArticlesDatabase_target.xcconfig | 2 +- Frameworks/SyncDatabase/xcconfig/SyncDatabase_target.xcconfig | 2 +- submodules/RSCore | 2 +- submodules/RSDatabase | 2 +- submodules/RSParser | 2 +- submodules/RSTree | 2 +- submodules/RSWeb | 2 +- 10 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Frameworks/Account/xcconfig/Account_target.xcconfig b/Frameworks/Account/xcconfig/Account_target.xcconfig index ce05ec71b..1861195ac 100644 --- a/Frameworks/Account/xcconfig/Account_target.xcconfig +++ b/Frameworks/Account/xcconfig/Account_target.xcconfig @@ -11,4 +11,4 @@ INFOPLIST_FILE = Info.plist PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.Account PRODUCT_NAME = $(TARGET_NAME:c99extidentifier) CLANG_ENABLE_MODULES = YES - +APPLICATION_EXTENSION_API_ONLY = YES diff --git a/Frameworks/Articles/Articles.xcodeproj/project.pbxproj b/Frameworks/Articles/Articles.xcodeproj/project.pbxproj index f501f687a..740c95eb7 100644 --- a/Frameworks/Articles/Articles.xcodeproj/project.pbxproj +++ b/Frameworks/Articles/Articles.xcodeproj/project.pbxproj @@ -345,6 +345,7 @@ 844BEE701F0AB3C9004AB7CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; MACOSX_DEPLOYMENT_TARGET = 10.13; @@ -357,6 +358,7 @@ 844BEE711F0AB3C9004AB7CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; MACOSX_DEPLOYMENT_TARGET = 10.13; diff --git a/Frameworks/Articles/xcconfig/Articles_target.xcconfig b/Frameworks/Articles/xcconfig/Articles_target.xcconfig index 65ad26d4b..d54abfddb 100644 --- a/Frameworks/Articles/xcconfig/Articles_target.xcconfig +++ b/Frameworks/Articles/xcconfig/Articles_target.xcconfig @@ -11,4 +11,4 @@ INFOPLIST_FILE = Info.plist PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.Articles PRODUCT_NAME = $(TARGET_NAME) CLANG_ENABLE_MODULES = YES - +APPLICATION_EXTENSION_API_ONLY = YES diff --git a/Frameworks/ArticlesDatabase/xcconfig/ArticlesDatabase_target.xcconfig b/Frameworks/ArticlesDatabase/xcconfig/ArticlesDatabase_target.xcconfig index 7152d0233..d23843946 100644 --- a/Frameworks/ArticlesDatabase/xcconfig/ArticlesDatabase_target.xcconfig +++ b/Frameworks/ArticlesDatabase/xcconfig/ArticlesDatabase_target.xcconfig @@ -13,4 +13,4 @@ INFOPLIST_FILE = Info.plist PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.ArticlesDatabase PRODUCT_NAME = $(TARGET_NAME) CLANG_ENABLE_MODULES = YES - +APPLICATION_EXTENSION_API_ONLY = YES diff --git a/Frameworks/SyncDatabase/xcconfig/SyncDatabase_target.xcconfig b/Frameworks/SyncDatabase/xcconfig/SyncDatabase_target.xcconfig index 3fbeffac5..d01ed698a 100644 --- a/Frameworks/SyncDatabase/xcconfig/SyncDatabase_target.xcconfig +++ b/Frameworks/SyncDatabase/xcconfig/SyncDatabase_target.xcconfig @@ -13,4 +13,4 @@ INFOPLIST_FILE = Info.plist PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.SyncDatabase PRODUCT_NAME = $(TARGET_NAME) CLANG_ENABLE_MODULES = YES - +APPLICATION_EXTENSION_API_ONLY = YES diff --git a/submodules/RSCore b/submodules/RSCore index 55afb4585..388b58e2f 160000 --- a/submodules/RSCore +++ b/submodules/RSCore @@ -1 +1 @@ -Subproject commit 55afb45853754e4a894035edc05fd4b5823472ca +Subproject commit 388b58e2fde1a93233767f4dba61d236838b6900 diff --git a/submodules/RSDatabase b/submodules/RSDatabase index 7b4476830..feb02ec73 160000 --- a/submodules/RSDatabase +++ b/submodules/RSDatabase @@ -1 +1 @@ -Subproject commit 7b44768308dc6970ee78470d0ea1e5287badc2bc +Subproject commit feb02ec73674fc572914f429e38428809c8d2281 diff --git a/submodules/RSParser b/submodules/RSParser index 9e86cf613..6d0b05ccd 160000 --- a/submodules/RSParser +++ b/submodules/RSParser @@ -1 +1 @@ -Subproject commit 9e86cf613b40b6a3389b6248be9427d90debbf9f +Subproject commit 6d0b05ccd661dac745dc4db402b5078e25c86b56 diff --git a/submodules/RSTree b/submodules/RSTree index d333739a7..1a856651f 160000 --- a/submodules/RSTree +++ b/submodules/RSTree @@ -1 +1 @@ -Subproject commit d333739a776236aae32b3868415729499021cec3 +Subproject commit 1a856651f1643abc5d52f4ef416077b9c41bf7e4 diff --git a/submodules/RSWeb b/submodules/RSWeb index b1230d5aa..c55f96018 160000 --- a/submodules/RSWeb +++ b/submodules/RSWeb @@ -1 +1 @@ -Subproject commit b1230d5aae49ee6c908fe694cd4f77b98d17cc42 +Subproject commit c55f96018ef1c81db35376065e1f094840162943 From cb1e8e393eaa6632e88c819d7837b1df36db33cd Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 23 Sep 2019 20:48:45 -0500 Subject: [PATCH 10/11] Fix controller collapsing behavior --- iOS/SceneCoordinator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/SceneCoordinator.swift b/iOS/SceneCoordinator.swift index ffb6f983f..65e2d8abd 100644 --- a/iOS/SceneCoordinator.swift +++ b/iOS/SceneCoordinator.swift @@ -854,7 +854,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { extension SceneCoordinator: UISplitViewControllerDelegate { func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool { - return true + return currentArticle == nil } } From 4e239a44e124bb915bffcd22acb0f83e4a8b6b69 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 23 Sep 2019 20:53:09 -0500 Subject: [PATCH 11/11] Reload the title view icon again after it becomes available --- iOS/MasterTimeline/MasterTimelineViewController.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/iOS/MasterTimeline/MasterTimelineViewController.swift b/iOS/MasterTimeline/MasterTimelineViewController.swift index a7bbe6645..ed13b926b 100644 --- a/iOS/MasterTimeline/MasterTimelineViewController.swift +++ b/iOS/MasterTimeline/MasterTimelineViewController.swift @@ -13,6 +13,7 @@ import Articles class MasterTimelineViewController: UITableViewController, UndoableCommandRunner { + private var titleView: MasterTimelineTitleView? private var numberOfTextLines = 0 @IBOutlet weak var markAllAsReadButton: UIBarButtonItem! @@ -342,6 +343,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner } @objc func faviconDidBecomeAvailable(_ note: Notification) { + titleView?.imageView.image = coordinator.timelineFavicon if coordinator.showAvatars { queueReloadAvailableCells() } @@ -455,6 +457,7 @@ private extension MasterTimelineViewController { title = coordinator.timelineName if let titleView = Bundle.main.loadNibNamed("MasterTimelineTitleView", owner: self, options: nil)?[0] as? MasterTimelineTitleView { + self.titleView = titleView titleView.imageView.image = coordinator.timelineFavicon titleView.label.text = coordinator.timelineName navigationItem.titleView = titleView