From ccd0385220b79b29c5c1e6f30b25035266a9b5b8 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Tue, 30 Jul 2019 13:08:58 -0500 Subject: [PATCH 01/44] Prevent flicker when selected feed's unread count changes. --- 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 9d1234d63..7f2a1120b 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -104,7 +104,7 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { } performBlockAndRestoreSelection { - tableView.reloadRows(at: [indexPath], with: .automatic) + tableView.reloadRows(at: [indexPath], with: .none) } } From badd7862b9d07d5624390f1d4717581b5610540c Mon Sep 17 00:00:00 2001 From: Olof Hellman Date: Tue, 30 Jul 2019 21:05:30 -0700 Subject: [PATCH 02/44] fix failing tests Disable the test that requires permissions to send keystrokes via SystemEvents.app Add PRODUCT_NAME back to the .pbxproj files to work around Xcode 11 beta 4 bug --- NetNewsWire.xcodeproj/project.pbxproj | 6 +++++- .../xcshareddata/xcschemes/NetNewsWire.xcscheme | 8 ++++---- .../ScriptingTests/ScriptingTests.swift | 10 +++++++++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 98ead857b..706e0bdaa 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -845,7 +845,7 @@ 849A97971ED9EFAA007D329B /* Node-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Node-Extensions.swift"; sourceTree = ""; }; 849A979E1ED9F130007D329B /* SidebarCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SidebarCell.swift; sourceTree = ""; }; 849A97A11ED9F180007D329B /* FolderTreeControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FolderTreeControllerDelegate.swift; sourceTree = ""; }; - 849C64601ED37A5D003D8FC0 /* NetNewsWire.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; name = NetNewsWire.app; path = .app; sourceTree = BUILT_PRODUCTS_DIR; }; + 849C64601ED37A5D003D8FC0 /* NetNewsWire.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetNewsWire.app; sourceTree = BUILT_PRODUCTS_DIR; }; 849C64671ED37A5D003D8FC0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 849C64711ED37A5D003D8FC0 /* NetNewsWireTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NetNewsWireTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 849EE70E203919360082A1EA /* AppAssets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAssets.swift; sourceTree = ""; }; @@ -2801,6 +2801,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 51121AA12265430A00BC0EC1 /* NetNewsWire_iOSapp_target.xcconfig */; buildSettings = { + PRODUCT_NAME = NetNewsWire; }; name = Debug; }; @@ -2808,6 +2809,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 51121AA12265430A00BC0EC1 /* NetNewsWire_iOSapp_target.xcconfig */; buildSettings = { + PRODUCT_NAME = NetNewsWire; }; name = Release; }; @@ -2829,6 +2831,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = D5907CE02002F0FA005947E5 /* NetNewsWire_macapp_target.xcconfig */; buildSettings = { + PRODUCT_NAME = NetNewsWire; }; name = Debug; }; @@ -2836,6 +2839,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = D5907CE02002F0FA005947E5 /* NetNewsWire_macapp_target.xcconfig */; buildSettings = { + PRODUCT_NAME = NetNewsWire; }; name = Release; }; diff --git a/NetNewsWire.xcodeproj/xcshareddata/xcschemes/NetNewsWire.xcscheme b/NetNewsWire.xcodeproj/xcshareddata/xcschemes/NetNewsWire.xcscheme index 07e988391..230b6714a 100644 --- a/NetNewsWire.xcodeproj/xcshareddata/xcschemes/NetNewsWire.xcscheme +++ b/NetNewsWire.xcodeproj/xcshareddata/xcschemes/NetNewsWire.xcscheme @@ -15,7 +15,7 @@ @@ -31,7 +31,7 @@ @@ -69,7 +69,7 @@ @@ -86,7 +86,7 @@ diff --git a/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift b/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift index 663e9b101..e89fb2381 100644 --- a/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift +++ b/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift @@ -81,8 +81,16 @@ class ScriptingTests: AppleScriptXCTestCase { actions and the keystrokes aren't delivered to the app right away, so the ui isn't updated in time for 'current article' to be set. But, breaking them up in this way seems to work. + + July 30, 2019: There's an issue where in order for a script to send keystrokes, + The app has to be allowed to interact with the SystemEvents.app in + System Preferences -> Security & Privacy -> Privacy -> Accessibility + and this premission needs to be renewed every time the app is recompiled unless + the app is codesigned. Until we figure out how to get around this limitation, + this test is disabled. */ - func testCurrentArticleScripts() { + func disabledTestCurrentArticleScripts() { + doIndividualScriptWithExpectation(filename: "uiScriptingTestSetup") doIndividualScriptWithExpectation(filename: "establishMainWindowStartingState") doIndividualScriptWithExpectation(filename: "selectAFeed") From f837caba69f04ef20369d25d2a5390fc888ced6a Mon Sep 17 00:00:00 2001 From: Olof Hellman Date: Tue, 30 Jul 2019 22:43:54 -0700 Subject: [PATCH 03/44] fix failing Applescript test by disabling it --- .../ScriptingTests/ScriptingTests.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift b/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift index 663e9b101..e89fb2381 100644 --- a/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift +++ b/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift @@ -81,8 +81,16 @@ class ScriptingTests: AppleScriptXCTestCase { actions and the keystrokes aren't delivered to the app right away, so the ui isn't updated in time for 'current article' to be set. But, breaking them up in this way seems to work. + + July 30, 2019: There's an issue where in order for a script to send keystrokes, + The app has to be allowed to interact with the SystemEvents.app in + System Preferences -> Security & Privacy -> Privacy -> Accessibility + and this premission needs to be renewed every time the app is recompiled unless + the app is codesigned. Until we figure out how to get around this limitation, + this test is disabled. */ - func testCurrentArticleScripts() { + func disabledTestCurrentArticleScripts() { + doIndividualScriptWithExpectation(filename: "uiScriptingTestSetup") doIndividualScriptWithExpectation(filename: "establishMainWindowStartingState") doIndividualScriptWithExpectation(filename: "selectAFeed") From 88c6f2274bdb4547d85ef3fddcf68483ca637f96 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 1 Aug 2019 06:53:34 -0500 Subject: [PATCH 04/44] Refactor how the No Selection message is displayed --- iOS/AppCoordinator.swift | 42 +++++++++++++++------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 1b35fe087..6c3614a83 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -210,7 +210,6 @@ class AppCoordinator: NSObject, UndoableCommandRunner { rootSplitViewController.delegate = self masterNavigationController = (rootSplitViewController.viewControllers.first as! UINavigationController) - masterNavigationController.delegate = self masterFeedViewController = UIStoryboard.main.instantiateController(ofType: MasterFeedViewController.self) masterFeedViewController.coordinator = self masterNavigationController.pushViewController(masterFeedViewController, animated: false) @@ -453,18 +452,24 @@ class AppCoordinator: NSObject, UndoableCommandRunner { navControllerForTimeline().pushViewController(masterTimelineViewController!, animated: true) } - if isThreePanelMode { - let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) - let targetSplitController = targetSplitForDetail() - let controller = addNavControllerIfNecessary(systemMessageViewController, split: targetSplitController, showBackButton: false) - targetSplitController.showDetailViewController(controller, sender: self) - } + selectArticle(nil) } - func selectArticle(_ indexPath: IndexPath) { - if detailViewController != nil { - currentArticleIndexPath = indexPath - } else { + func selectArticle(_ indexPath: IndexPath?) { + currentArticleIndexPath = indexPath + + if indexPath == nil { + if !rootSplitViewController.isCollapsed { + let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) + let showBackButton = rootSplitViewController.displayMode != .allVisible + let targetSplit = targetSplitForDetail() + let controller = addNavControllerIfNecessary(systemMessageViewController, split: targetSplit, showBackButton: showBackButton) + targetSplit.showDetailViewController(controller, sender: self) + } + return + } + + if detailViewController == nil { let targetSplit = targetSplitForDetail() let detailViewController = UIStoryboard.main.instantiateController(ofType: DetailViewController.self) @@ -593,21 +598,6 @@ class AppCoordinator: NSObject, UndoableCommandRunner { } -// MARK: UINavigationControllerDelegate - -extension AppCoordinator: UINavigationControllerDelegate { - - func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) { - if rootSplitViewController.isCollapsed != true && navigationController.viewControllers.count == 1 { - let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) - let showBackButton = rootSplitViewController.displayMode != .allVisible - let controller = addNavControllerIfNecessary(systemMessageViewController, split: rootSplitViewController, showBackButton: showBackButton) - rootSplitViewController.showDetailViewController(controller, sender: self) - } - } - -} - // MARK: UISplitViewControllerDelegate extension AppCoordinator: UISplitViewControllerDelegate { From 2ab3ff76fb3e758be682a6d0b878c55ebe7767c1 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 1 Aug 2019 07:10:02 -0500 Subject: [PATCH 05/44] Make settings button work second split controller is installed --- iOS/AppCoordinator.swift | 4 ++-- iOS/Base.lproj/Main.storyboard | 22 +++++++++++++------ iOS/MasterFeed/MasterFeedViewController.swift | 5 ----- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 6c3614a83..8b5a60fbc 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -560,8 +560,8 @@ class AppCoordinator: NSObject, UndoableCommandRunner { let settingsNavViewController = UIStoryboard.settings.instantiateInitialViewController() as! UINavigationController settingsNavViewController.modalPresentationStyle = .formSheet let settingsViewController = settingsNavViewController.topViewController as! SettingsViewController - settingsViewController.presentingParentController = masterFeedViewController - masterFeedViewController.present(settingsNavViewController, animated: true) + settingsViewController.presentingParentController = rootSplitViewController + rootSplitViewController.present(settingsNavViewController, animated: true) // let settings = UIHostingController(rootView: SettingsView(viewModel: SettingsView.ViewModel())) // self.present(settings, animated: true) diff --git a/iOS/Base.lproj/Main.storyboard b/iOS/Base.lproj/Main.storyboard index d1120fc2b..e183c169d 100644 --- a/iOS/Base.lproj/Main.storyboard +++ b/iOS/Base.lproj/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -24,7 +24,7 @@ - + @@ -122,7 +122,6 @@ - @@ -135,7 +134,7 @@ - + @@ -148,6 +147,7 @@ + @@ -158,7 +158,7 @@ - + @@ -238,7 +238,14 @@ - + + + + + + + + @@ -256,6 +263,7 @@ + diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index 7f2a1120b..126e2611f 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -29,11 +29,6 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { super.viewDidLoad() - let settingsButton = UIBarButtonItem() - settingsButton.image = AppAssets.settingsImage - settingsButton.action = #selector(settings(_:)) - navigationItem.leftBarButtonItem = settingsButton - navigationItem.rightBarButtonItem = editButtonItem tableView.register(MasterFeedTableViewSectionHeader.self, forHeaderFooterViewReuseIdentifier: "SectionHeader") From d16386d205bf53ca46bf91e6bbd6833eb6f76ce3 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 1 Aug 2019 16:14:34 -0500 Subject: [PATCH 06/44] Add transitioning for three panel mode --- iOS/AppCoordinator.swift | 83 +++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 8b5a60fbc..1ac1f6810 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -62,7 +62,7 @@ class AppCoordinator: NSObject, UndoableCommandRunner { }() var isThreePanelMode: Bool { - return !rootSplitViewController.isCollapsed && rootSplitViewController.displayMode == .allVisible + return rootSplitViewController.traitCollection.userInterfaceIdiom == .pad && rootSplitViewController.displayMode == .allVisible } var rootNode: Node { @@ -602,14 +602,26 @@ class AppCoordinator: NSObject, UndoableCommandRunner { extension AppCoordinator: UISplitViewControllerDelegate { - func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool { - if currentArticle == nil { - // Return true to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded. - return true - } - return false - } + func splitViewController(_ svc: UISplitViewController, willChangeTo displayMode: UISplitViewController.DisplayMode) { + guard rootSplitViewController.traitCollection.userInterfaceIdiom == .pad else { + return + } + + if rootSplitViewController.displayMode != .allVisible && displayMode == .allVisible { + transitionToThreePanelMode() + } + + if rootSplitViewController.displayMode == .allVisible && displayMode != .allVisible { + transitionFromThreePanelMode() + } + + } + + func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool { + return currentArticle == nil + } + } // MARK: Private @@ -856,7 +868,6 @@ private extension AppCoordinator { rootSplitViewController.preferredPrimaryColumnWidthFraction = 0.33 let subSplit = UISplitViewController.template() - subSplit.delegate = self subSplit.preferredDisplayMode = .allVisible subSplit.preferredPrimaryColumnWidthFraction = 0.5 rootSplitViewController.showDetailViewController(subSplit, sender: self) @@ -880,4 +891,58 @@ private extension AppCoordinator { } } + func transitionToThreePanelMode() { + defer { + masterNavigationController.viewControllers = [masterFeedViewController] + } + + if masterNavigationController.viewControllers.count == 1 { + + let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) + let navController = UINavigationController(rootViewController: systemMessageViewController) + navController.isToolbarHidden = false + rootSplitViewController.showDetailViewController(navController, sender: self) + + } else { + + let detailController: UIViewController = { + if let detailNavController = rootSplitViewController.viewControllers.last as? UINavigationController, + let detailController = detailNavController.topViewController as? DetailViewController { + return detailController + } else { + return UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) + } + }() + + masterTimelineViewController!.navigationItem.leftBarButtonItem = nil + + let subSplit = ensureDoubleSplit() + let masterTimelineNavController = subSplit.viewControllers.first as! UINavigationController + masterTimelineNavController.viewControllers = [masterTimelineViewController!] + let detailNavController = addNavControllerIfNecessary(detailController, split: subSplit, showBackButton: false) + subSplit.showDetailViewController(detailNavController, sender: false) + + } + + } + + func transitionFromThreePanelMode() { + + rootSplitViewController.preferredPrimaryColumnWidthFraction = UISplitViewController.automaticDimension + + if let secondarySplit = rootSplitViewController.viewControllers.last as? UISplitViewController { + + if let masterTimelineNav = secondarySplit.viewControllers.first as? UINavigationController, + let masterTimeline = masterTimelineNav.topViewController { + masterNavigationController.pushViewController(masterTimeline, animated: false) + } + + if let detailNav = secondarySplit.viewControllers.last as? UINavigationController, let topController = detailNav.topViewController { + let newNav = addNavControllerIfNecessary(topController, split: rootSplitViewController, showBackButton: true) + rootSplitViewController.showDetailViewController(newNav, sender: self) + } + + } + } + } From 47025e3e1601db5482024bdef538f25a7a33d689 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 1 Aug 2019 17:16:08 -0500 Subject: [PATCH 07/44] Remove duplicate AppCoordinator in Sources that was causing an warning --- NetNewsWire.xcodeproj/project.pbxproj | 1 - 1 file changed, 1 deletion(-) diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 706e0bdaa..06bcc022b 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -2383,7 +2383,6 @@ 51C452852265093600C03939 /* AddFeedFolderPickerData.swift in Sources */, 51C4526B226508F600C03939 /* MasterFeedViewController.swift in Sources */, 5126EE97226CB48A00C22AFC /* AppCoordinator.swift in Sources */, - 5126EE97226CB48A00C22AFC /* AppCoordinator.swift in Sources */, 84CAFCB022BC8C35007694F0 /* FetchRequestOperation.swift in Sources */, 51EF0F77227716200050506E /* FaviconGenerator.swift in Sources */, 51C4525A226508D600C03939 /* UIStoryboard-Extensions.swift in Sources */, From e22088b2842f4ef37bc569e533bd2ce83c82ae4b Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 1 Aug 2019 19:59:56 -0500 Subject: [PATCH 08/44] Implemented Shim Controller so that we can change out the secondary split view controller when the display mode changes --- iOS/AppCoordinator.swift | 89 ++++++++++++++++++++-------------------- submodules/RSCore | 2 +- 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 1ac1f6810..0df3dcf8b 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -34,10 +34,11 @@ class AppCoordinator: NSObject, UndoableCommandRunner { private var masterTimelineViewController: MasterTimelineViewController? private var detailViewController: DetailViewController? { - if let detailNavController = targetSplitForDetail().viewControllers.last as? UINavigationController { - return detailNavController.topViewController as? DetailViewController + if let subSplit = rootSplitViewController.viewControllers.last?.children.first as? UISplitViewController { + return subSplit.viewControllers.last as? DetailViewController + } else { + return rootSplitViewController.viewControllers.last?.children.first as? DetailViewController } - return nil } private let fetchAndMergeArticlesQueue = CoalescingQueue(name: "Fetch and Merge Articles", interval: 0.5) @@ -215,8 +216,10 @@ class AppCoordinator: NSObject, UndoableCommandRunner { masterNavigationController.pushViewController(masterFeedViewController, animated: false) let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) - let controller = addNavControllerIfNecessary(systemMessageViewController, split: rootSplitViewController, showBackButton: true) - rootSplitViewController.showDetailViewController(controller, sender: self) + let detailNavController = addNavControllerIfNecessary(systemMessageViewController, showButton: true) + let shimController = UIViewController() + shimController.replaceChildAndPinView(detailNavController) + rootSplitViewController.showDetailViewController(shimController, sender: self) return rootSplitViewController } @@ -461,25 +464,15 @@ class AppCoordinator: NSObject, UndoableCommandRunner { if indexPath == nil { if !rootSplitViewController.isCollapsed { let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) - let showBackButton = rootSplitViewController.displayMode != .allVisible - let targetSplit = targetSplitForDetail() - let controller = addNavControllerIfNecessary(systemMessageViewController, split: targetSplit, showBackButton: showBackButton) - targetSplit.showDetailViewController(controller, sender: self) + installDetailController(systemMessageViewController) } return } if detailViewController == nil { - let targetSplit = targetSplitForDetail() - let detailViewController = UIStoryboard.main.instantiateController(ofType: DetailViewController.self) detailViewController.coordinator = self - - let showBackButton = rootSplitViewController.displayMode != .allVisible - let controller = addNavControllerIfNecessary(detailViewController, split: targetSplit, showBackButton: showBackButton) - currentArticleIndexPath = indexPath - - targetSplit.showDetailViewController(controller, sender: self) + installDetailController(detailViewController) } // Automatically hide the overlay @@ -846,14 +839,28 @@ private extension AppCoordinator { // MARK: Double Split - func addNavControllerIfNecessary(_ controller: UIViewController, split: UISplitViewController, showBackButton: Bool) -> UIViewController { - if split.isCollapsed { + func installDetailController(_ detailController: UIViewController) { + let showButton = rootSplitViewController.displayMode != .allVisible + let controller = addNavControllerIfNecessary(detailController, showButton: showButton) + + if isThreePanelMode { + let targetSplit = ensureDoubleSplit() + targetSplit.showDetailViewController(controller, sender: self) + } else { + if let shimController = rootSplitViewController.viewControllers.last { + shimController.replaceChildAndPinView(controller) + } + } + } + + func addNavControllerIfNecessary(_ controller: UIViewController, showButton: Bool) -> UIViewController { + if rootSplitViewController.isCollapsed { return controller } else { let navController = UINavigationController(rootViewController: controller) navController.isToolbarHidden = false - if showBackButton { - controller.navigationItem.leftBarButtonItem = split.displayModeButtonItem + if showButton { + controller.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem controller.navigationItem.leftItemsSupplementBackButton = true } return navController @@ -861,7 +868,7 @@ private extension AppCoordinator { } func ensureDoubleSplit() -> UISplitViewController { - if let subSplit = rootSplitViewController.viewControllers.last as? UISplitViewController { + if let shimController = rootSplitViewController.viewControllers.last, let subSplit = shimController.children.first as? UISplitViewController { return subSplit } @@ -870,7 +877,11 @@ private extension AppCoordinator { let subSplit = UISplitViewController.template() subSplit.preferredDisplayMode = .allVisible subSplit.preferredPrimaryColumnWidthFraction = 0.5 - rootSplitViewController.showDetailViewController(subSplit, sender: self) + + let shimController = UIViewController() + shimController.addChildAndPinView(subSplit) + + rootSplitViewController.showDetailViewController(shimController, sender: self) return subSplit } @@ -883,14 +894,6 @@ private extension AppCoordinator { } } - func targetSplitForDetail() -> UISplitViewController { - if isThreePanelMode { - return ensureDoubleSplit() - } else { - return rootSplitViewController - } - } - func transitionToThreePanelMode() { defer { masterNavigationController.viewControllers = [masterFeedViewController] @@ -905,10 +908,9 @@ private extension AppCoordinator { } else { - let detailController: UIViewController = { - if let detailNavController = rootSplitViewController.viewControllers.last as? UINavigationController, - let detailController = detailNavController.topViewController as? DetailViewController { - return detailController + let controller: UIViewController = { + if let result = detailViewController { + return result } else { return UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) } @@ -919,30 +921,29 @@ private extension AppCoordinator { let subSplit = ensureDoubleSplit() let masterTimelineNavController = subSplit.viewControllers.first as! UINavigationController masterTimelineNavController.viewControllers = [masterTimelineViewController!] - let detailNavController = addNavControllerIfNecessary(detailController, split: subSplit, showBackButton: false) - subSplit.showDetailViewController(detailNavController, sender: false) - + + installDetailController(controller) } - } func transitionFromThreePanelMode() { rootSplitViewController.preferredPrimaryColumnWidthFraction = UISplitViewController.automaticDimension - if let secondarySplit = rootSplitViewController.viewControllers.last as? UISplitViewController { + if let shimController = rootSplitViewController.viewControllers.last, let subSplit = shimController.children.first as? UISplitViewController { - if let masterTimelineNav = secondarySplit.viewControllers.first as? UINavigationController, + if let masterTimelineNav = subSplit.viewControllers.first as? UINavigationController, let masterTimeline = masterTimelineNav.topViewController { masterNavigationController.pushViewController(masterTimeline, animated: false) } - if let detailNav = secondarySplit.viewControllers.last as? UINavigationController, let topController = detailNav.topViewController { - let newNav = addNavControllerIfNecessary(topController, split: rootSplitViewController, showBackButton: true) - rootSplitViewController.showDetailViewController(newNav, sender: self) + if let detailNav = subSplit.viewControllers.last as? UINavigationController, let topController = detailNav.topViewController { + let newNav = addNavControllerIfNecessary(topController, showButton: true) + shimController.replaceChildAndPinView(newNav) } } + } } diff --git a/submodules/RSCore b/submodules/RSCore index 277c64868..b8656655f 160000 --- a/submodules/RSCore +++ b/submodules/RSCore @@ -1 +1 @@ -Subproject commit 277c64868a4a7464f32bbd2b063af3b7736904a3 +Subproject commit b8656655f68f207bf9d14e9fda2c928c1bcbe0cf From 9e0a4aed00bb7dbb4ecda934c523e10274efb7bd Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 1 Aug 2019 20:06:55 -0500 Subject: [PATCH 09/44] Correctly handle showing the detail view when the root view controller is collapsed --- iOS/AppCoordinator.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 0df3dcf8b..77a685214 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -846,6 +846,8 @@ private extension AppCoordinator { if isThreePanelMode { let targetSplit = ensureDoubleSplit() targetSplit.showDetailViewController(controller, sender: self) + } else if rootSplitViewController.isCollapsed { + rootSplitViewController.showDetailViewController(controller, sender: self) } else { if let shimController = rootSplitViewController.viewControllers.last { shimController.replaceChildAndPinView(controller) From 7b7fb7ef2a306e4ad20ff9f199050f7f760e9682 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 1 Aug 2019 20:24:54 -0500 Subject: [PATCH 10/44] Adjust font to silence dynamic type warning --- iOS/Base.lproj/Main.storyboard | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/Base.lproj/Main.storyboard b/iOS/Base.lproj/Main.storyboard index e183c169d..4c40e5500 100644 --- a/iOS/Base.lproj/Main.storyboard +++ b/iOS/Base.lproj/Main.storyboard @@ -129,7 +129,7 @@ From eb4d61dc2c93914e40b3aa9b00175100607432b6 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 1 Aug 2019 20:47:46 -0500 Subject: [PATCH 11/44] Correct LD_RUNPATH_SEARCH_PATHS so that we can run on devices without crashing --- xcconfig/NetNewsWire_iOSapp_target.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcconfig/NetNewsWire_iOSapp_target.xcconfig b/xcconfig/NetNewsWire_iOSapp_target.xcconfig index e76a5b046..534d890ed 100644 --- a/xcconfig/NetNewsWire_iOSapp_target.xcconfig +++ b/xcconfig/NetNewsWire_iOSapp_target.xcconfig @@ -39,7 +39,7 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) $(PROJECT_DIR)/Frameworks/Vendor GCC_C_LANGUAGE_STANDARD = gnu11; IPHONEOS_DEPLOYMENT_TARGET = 13.0 -LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks +LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks INFOPLIST_FILE = iOS/Resources/Info.plist PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.NetNewsWire-Evergreen.iOS PRODUCT_NAME = NetNewsWire From e800b13f01a4b3bcf820e09d8de214dac888a97e Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Thu, 1 Aug 2019 21:52:12 -0700 Subject: [PATCH 12/44] The accounts property returns all accounts. --- Mac/Scriptability/NSApplication+Scriptability.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mac/Scriptability/NSApplication+Scriptability.swift b/Mac/Scriptability/NSApplication+Scriptability.swift index c6d140688..a7e181009 100644 --- a/Mac/Scriptability/NSApplication+Scriptability.swift +++ b/Mac/Scriptability/NSApplication+Scriptability.swift @@ -56,7 +56,7 @@ extension NSApplication : ScriptingObjectContainer { @objc(accounts) func accounts() -> NSArray { - let accounts = AccountManager.shared.activeAccounts + let accounts = AccountManager.shared.accounts return accounts.map { ScriptableAccount($0) } as NSArray } From 5d97e89e91cdbf33944f037b28a45405730dd02a Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Thu, 1 Aug 2019 22:51:03 -0700 Subject: [PATCH 13/44] =?UTF-8?q?Replace=20the=20contents=20property=20wit?= =?UTF-8?q?h=20allFeeds=20=E2=80=94=20which=20returns=20all=20the=20feeds,?= =?UTF-8?q?=20including=20those=20inside=20folders.=20This=20is=20distinct?= =?UTF-8?q?=20from=20the=20feeds=20element,=20which=20returns=20just=20top?= =?UTF-8?q?-level=20feeds.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Mac/Resources/NetNewsWire.sdef | 13 +++++-------- Mac/Scriptability/Account+Scriptability.swift | 15 +++++++++------ .../ScriptingTests/ScriptingTests.swift | 14 +++++++------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Mac/Resources/NetNewsWire.sdef b/Mac/Resources/NetNewsWire.sdef index 5a754f993..982719b4b 100644 --- a/Mac/Resources/NetNewsWire.sdef +++ b/Mac/Resources/NetNewsWire.sdef @@ -87,9 +87,9 @@ - - - + + + @@ -102,10 +102,7 @@ - - - - + @@ -154,7 +151,7 @@ - + diff --git a/Mac/Scriptability/Account+Scriptability.swift b/Mac/Scriptability/Account+Scriptability.swift index 9513e3fab..486a9c7c8 100644 --- a/Mac/Scriptability/Account+Scriptability.swift +++ b/Mac/Scriptability/Account+Scriptability.swift @@ -121,18 +121,21 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta // MARK: --- Scriptable properties --- - @objc(contents) - var contents:NSArray { - var contentsArray:[AnyObject] = [] + @objc(allFeeds) + var allFeeds: NSArray { + var feeds = [ScriptableFeed]() for feed in account.topLevelFeeds { - contentsArray.append(ScriptableFeed(feed, container: self)) + feeds.append(ScriptableFeed(feed, container: self)) } if let folders = account.folders { for folder in folders { - contentsArray.append(ScriptableFolder(folder, container:self)) + let scriptableFolder = ScriptableFolder(folder, container: self) + for feed in folder.topLevelFeeds { + feeds.append(ScriptableFeed(feed, container: scriptableFolder)) + } } } - return contentsArray as NSArray + return feeds as NSArray } @objc(opmlRepresentation) diff --git a/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift b/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift index e89fb2381..0dec11b94 100644 --- a/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift +++ b/Tests/NetNewsWireTests/ScriptingTests/ScriptingTests.swift @@ -56,13 +56,13 @@ class ScriptingTests: AppleScriptXCTestCase { _ = doIndividualScript(filename: "testFeedOPML") } - func testTitleOfArticlesWhoseScript() { - _ = doIndividualScript(filename: "testTitleOfArticlesWhose") - } - - func testIterativeCreateAndDeleteScript() { - _ = doIndividualScriptWithExpectation(filename: "testIterativeCreateAndDeleteFeed") - } +// func testTitleOfArticlesWhoseScript() { +// _ = doIndividualScript(filename: "testTitleOfArticlesWhose") +// } +// +// func testIterativeCreateAndDeleteScript() { +// _ = doIndividualScriptWithExpectation(filename: "testIterativeCreateAndDeleteFeed") +// } func doIndividualScriptWithExpectation(filename:String) { let queue = DispatchQueue(label:"testQueue") From 7da1aacf28b1deaaa64e37f29a588f52e75c2f84 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 2 Aug 2019 04:22:47 -0500 Subject: [PATCH 14/44] Fix transition to three panel mode --- iOS/AppCoordinator.swift | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 77a685214..d5c48ad13 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -35,10 +35,15 @@ class AppCoordinator: NSObject, UndoableCommandRunner { private var detailViewController: DetailViewController? { if let subSplit = rootSplitViewController.viewControllers.last?.children.first as? UISplitViewController { - return subSplit.viewControllers.last as? DetailViewController + if let navController = subSplit.viewControllers.last as? UINavigationController { + return navController.topViewController as? DetailViewController + } } else { - return rootSplitViewController.viewControllers.last?.children.first as? DetailViewController + if let navController = rootSplitViewController.viewControllers.last?.children.first as? UINavigationController { + return navController.topViewController as? DetailViewController + } } + return nil } private let fetchAndMergeArticlesQueue = CoalescingQueue(name: "Fetch and Merge Articles", interval: 0.5) @@ -901,11 +906,10 @@ private extension AppCoordinator { masterNavigationController.viewControllers = [masterFeedViewController] } - if masterNavigationController.viewControllers.count == 1 { + if currentArticle == nil { let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) - let navController = UINavigationController(rootViewController: systemMessageViewController) - navController.isToolbarHidden = false + let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: false) rootSplitViewController.showDetailViewController(navController, sender: self) } else { @@ -917,14 +921,18 @@ private extension AppCoordinator { return UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) } }() + + let navController = addNavControllerIfNecessary(controller, showButton: false) masterTimelineViewController!.navigationItem.leftBarButtonItem = nil let subSplit = ensureDoubleSplit() + let masterTimelineNavController = subSplit.viewControllers.first as! UINavigationController masterTimelineNavController.viewControllers = [masterTimelineViewController!] - installDetailController(controller) + subSplit.showDetailViewController(navController, sender: self) + } } From 4f49a4bcf63a60a69bbc6f8fdb44925e1ee46ae9 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 2 Aug 2019 04:23:41 -0500 Subject: [PATCH 15/44] Fix code formatting --- iOS/AppCoordinator.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index d5c48ad13..4781bbd77 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -601,19 +601,15 @@ class AppCoordinator: NSObject, UndoableCommandRunner { extension AppCoordinator: UISplitViewControllerDelegate { func splitViewController(_ svc: UISplitViewController, willChangeTo displayMode: UISplitViewController.DisplayMode) { - guard rootSplitViewController.traitCollection.userInterfaceIdiom == .pad else { return } - if rootSplitViewController.displayMode != .allVisible && displayMode == .allVisible { transitionToThreePanelMode() } - if rootSplitViewController.displayMode == .allVisible && displayMode != .allVisible { transitionFromThreePanelMode() } - } func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool { From e0832260b866b7412d9f1050b69129e0b5c7fda8 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 2 Aug 2019 04:29:42 -0500 Subject: [PATCH 16/44] Fix timeline selected transition to three panel mode --- iOS/AppCoordinator.swift | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 4781bbd77..9e0ab0cc5 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -902,7 +902,7 @@ private extension AppCoordinator { masterNavigationController.viewControllers = [masterFeedViewController] } - if currentArticle == nil { + if currentMasterIndexPath == nil && currentArticleIndexPath == nil { let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: false) @@ -910,6 +910,12 @@ private extension AppCoordinator { } else { + masterTimelineViewController!.navigationItem.leftBarButtonItem = nil + + let subSplit = ensureDoubleSplit() + let masterTimelineNavController = subSplit.viewControllers.first as! UINavigationController + masterTimelineNavController.viewControllers = [masterTimelineViewController!] + let controller: UIViewController = { if let result = detailViewController { return result @@ -919,14 +925,6 @@ private extension AppCoordinator { }() let navController = addNavControllerIfNecessary(controller, showButton: false) - - masterTimelineViewController!.navigationItem.leftBarButtonItem = nil - - let subSplit = ensureDoubleSplit() - - let masterTimelineNavController = subSplit.viewControllers.first as! UINavigationController - masterTimelineNavController.viewControllers = [masterTimelineViewController!] - subSplit.showDetailViewController(navController, sender: self) } From d7afc30ed38a098a29d30ba7ae44c9a9598baa76 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 2 Aug 2019 04:42:48 -0500 Subject: [PATCH 17/44] Remove dead code --- iOS/AppCoordinator.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 9e0ab0cc5..b72ea3300 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -864,7 +864,6 @@ private extension AppCoordinator { navController.isToolbarHidden = false if showButton { controller.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem - controller.navigationItem.leftItemsSupplementBackButton = true } return navController } From 52055d83f5780e8d4f44406636b14ec58eddf655 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 2 Aug 2019 09:12:15 -0500 Subject: [PATCH 18/44] Made the detail panel slightly larger than the others in three panel mode --- iOS/AppCoordinator.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index b72ea3300..3eb4d5fd0 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -874,11 +874,11 @@ private extension AppCoordinator { return subSplit } - rootSplitViewController.preferredPrimaryColumnWidthFraction = 0.33 + rootSplitViewController.preferredPrimaryColumnWidthFraction = 0.30 let subSplit = UISplitViewController.template() subSplit.preferredDisplayMode = .allVisible - subSplit.preferredPrimaryColumnWidthFraction = 0.5 + subSplit.preferredPrimaryColumnWidthFraction = 0.4285 let shimController = UIViewController() shimController.addChildAndPinView(subSplit) From 54f660762127b71001446e02e8ffa6d7bb8ac364 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 2 Aug 2019 10:25:47 -0500 Subject: [PATCH 19/44] Keep table selections when root split isn't collapsed --- iOS/AppCoordinator.swift | 4 ++++ iOS/MasterFeed/MasterFeedViewController.swift | 2 +- iOS/MasterTimeline/MasterTimelineViewController.swift | 5 +++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 3eb4d5fd0..69526a668 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -67,6 +67,10 @@ class AppCoordinator: NSObject, UndoableCommandRunner { return TreeController(delegate: treeControllerDelegate) }() + var isRootSplitCollapsed: Bool { + return rootSplitViewController.isCollapsed + } + var isThreePanelMode: Bool { return rootSplitViewController.traitCollection.userInterfaceIdiom == .pad && rootSplitViewController.displayMode == .allVisible } diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index 126e2611f..e3b906da1 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -53,8 +53,8 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { } override func viewWillAppear(_ animated: Bool) { - clearsSelectionOnViewWillAppear = true navigationController?.title = NSLocalizedString("Feeds", comment: "Feeds") + clearsSelectionOnViewWillAppear = coordinator.isRootSplitCollapsed super.viewWillAppear(animated) } diff --git a/iOS/MasterTimeline/MasterTimelineViewController.swift b/iOS/MasterTimeline/MasterTimelineViewController.swift index 2cc6bbd52..5e55c2cb0 100644 --- a/iOS/MasterTimeline/MasterTimelineViewController.swift +++ b/iOS/MasterTimeline/MasterTimelineViewController.swift @@ -54,6 +54,11 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner } + override func viewWillAppear(_ animated: Bool) { + clearsSelectionOnViewWillAppear = coordinator.isRootSplitCollapsed + super.viewWillAppear(animated) + } + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) becomeFirstResponder() From 8753790a192e772f460af4ce3d115c7ae78b5bc2 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 2 Aug 2019 10:34:32 -0500 Subject: [PATCH 20/44] Fix bug that lost detail view when transitioning to three panel mode --- iOS/AppCoordinator.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 69526a668..be2af07e1 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -913,12 +913,6 @@ private extension AppCoordinator { } else { - masterTimelineViewController!.navigationItem.leftBarButtonItem = nil - - let subSplit = ensureDoubleSplit() - let masterTimelineNavController = subSplit.viewControllers.first as! UINavigationController - masterTimelineNavController.viewControllers = [masterTimelineViewController!] - let controller: UIViewController = { if let result = detailViewController { return result @@ -927,6 +921,12 @@ private extension AppCoordinator { } }() + masterTimelineViewController!.navigationItem.leftBarButtonItem = nil + + let subSplit = ensureDoubleSplit() + let masterTimelineNavController = subSplit.viewControllers.first as! UINavigationController + masterTimelineNavController.viewControllers = [masterTimelineViewController!] + let navController = addNavControllerIfNecessary(controller, showButton: false) subSplit.showDetailViewController(navController, sender: self) From ccd1d4bdc1d02a021bc26166e7a56fa1bbc955b9 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Fri, 2 Aug 2019 12:44:24 -0700 Subject: [PATCH 21/44] Wire up the account name for scripting. --- Mac/Resources/NetNewsWire.sdef | 2 +- Mac/Scriptability/Account+Scriptability.swift | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Mac/Resources/NetNewsWire.sdef b/Mac/Resources/NetNewsWire.sdef index 982719b4b..d9facd1da 100644 --- a/Mac/Resources/NetNewsWire.sdef +++ b/Mac/Resources/NetNewsWire.sdef @@ -76,7 +76,7 @@ - + diff --git a/Mac/Scriptability/Account+Scriptability.swift b/Mac/Scriptability/Account+Scriptability.swift index 486a9c7c8..520c3d298 100644 --- a/Mac/Scriptability/Account+Scriptability.swift +++ b/Mac/Scriptability/Account+Scriptability.swift @@ -35,7 +35,17 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta account.isActive = newValue } } - + + @objc(scriptingName) + var scriptingName: NSString { + get { + return account.nameForDisplay as NSString + } + set { + account.name = newValue as String + } + } + // MARK: --- ScriptingObject protocol --- var scriptingKey: String { From 4b5dd7cd179d0f7dbdd14c68ce9add067f277ae6 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Fri, 2 Aug 2019 14:03:04 -0700 Subject: [PATCH 22/44] Fix some AppleScript terminology conflicts. Change account.type too account.accountType. Change local account to onmymac. --- Mac/Resources/NetNewsWire.sdef | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mac/Resources/NetNewsWire.sdef b/Mac/Resources/NetNewsWire.sdef index d9facd1da..aa7fb9974 100644 --- a/Mac/Resources/NetNewsWire.sdef +++ b/Mac/Resources/NetNewsWire.sdef @@ -66,7 +66,7 @@ - + @@ -81,7 +81,7 @@ - + From 7acf77f5725e0c49373fe168e957c060d8431ed9 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 2 Aug 2019 16:46:55 -0500 Subject: [PATCH 23/44] Enable collapsing and splitting of root split view controller --- iOS/AppCoordinator.swift | 81 +++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index be2af07e1..25b19cc1b 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -34,6 +34,9 @@ class AppCoordinator: NSObject, UndoableCommandRunner { private var masterTimelineViewController: MasterTimelineViewController? private var detailViewController: DetailViewController? { + if let detail = masterNavigationController.viewControllers.last as? DetailViewController { + return detail + } if let subSplit = rootSplitViewController.viewControllers.last?.children.first as? UISplitViewController { if let navController = subSplit.viewControllers.last as? UINavigationController { return navController.topViewController as? DetailViewController @@ -72,7 +75,7 @@ class AppCoordinator: NSObject, UndoableCommandRunner { } var isThreePanelMode: Bool { - return rootSplitViewController.traitCollection.userInterfaceIdiom == .pad && rootSplitViewController.displayMode == .allVisible + return rootSplitViewController.traitCollection.userInterfaceIdiom == .pad && !rootSplitViewController.isCollapsed && rootSplitViewController.displayMode == .allVisible } var rootNode: Node { @@ -617,9 +620,63 @@ extension AppCoordinator: UISplitViewControllerDelegate { } func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool { + + if let shimController = rootSplitViewController.viewControllers.last, + let detailNav = shimController.children.first as? UINavigationController, + let detail = detailNav.topViewController as? DetailViewController { + masterNavigationController.pushViewController(detail, animated: false) + return true + } + + if let subSplit = secondaryViewController.children.first as? UISplitViewController { + + if let masterTimelineNav = subSplit.viewControllers.first as? UINavigationController, + let masterTimeline = masterTimelineNav.topViewController { + masterNavigationController.pushViewController(masterTimeline, animated: false) + } + + if let detailNav = subSplit.viewControllers.last as? UINavigationController, let detail = detailNav.topViewController { + masterNavigationController.pushViewController(detail, animated: false) + } + + return true + + } + return currentArticle == nil } + func splitViewController(_ splitViewController: UISplitViewController, separateSecondaryFrom primaryViewController: UIViewController) -> UIViewController? { + + if isThreePanelMode { + return transitionToThreePanelMode() + } + + if let detail = masterNavigationController.viewControllers.last as? DetailViewController { + + masterNavigationController.viewControllers.removeLast() + let detailNav = addNavControllerIfNecessary(detail, showButton: true) + let shimController = UIViewController() + shimController.addChildAndPinView(detailNav) + return shimController + + } + +// +// } else { +// +// let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) +// let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: true) +// let shimController = UIViewController() +// shimController.addChildAndPinView(navController) +// return shimController +// +// } +// + return nil + + } + } // MARK: Private @@ -849,7 +906,7 @@ private extension AppCoordinator { let controller = addNavControllerIfNecessary(detailController, showButton: showButton) if isThreePanelMode { - let targetSplit = ensureDoubleSplit() + let targetSplit = ensureDoubleSplit().children.first as! UISplitViewController targetSplit.showDetailViewController(controller, sender: self) } else if rootSplitViewController.isCollapsed { rootSplitViewController.showDetailViewController(controller, sender: self) @@ -873,9 +930,9 @@ private extension AppCoordinator { } } - func ensureDoubleSplit() -> UISplitViewController { - if let shimController = rootSplitViewController.viewControllers.last, let subSplit = shimController.children.first as? UISplitViewController { - return subSplit + func ensureDoubleSplit() -> UIViewController { + if let shimController = rootSplitViewController.viewControllers.last, shimController.children.first is UISplitViewController { + return shimController } rootSplitViewController.preferredPrimaryColumnWidthFraction = 0.30 @@ -888,19 +945,20 @@ private extension AppCoordinator { shimController.addChildAndPinView(subSplit) rootSplitViewController.showDetailViewController(shimController, sender: self) - return subSplit + return shimController } func navControllerForTimeline() -> UINavigationController { if isThreePanelMode { - let subSplit = ensureDoubleSplit() + let subSplit = ensureDoubleSplit().children.first as! UISplitViewController return subSplit.viewControllers.first as! UINavigationController } else { return masterNavigationController } } - func transitionToThreePanelMode() { + @discardableResult + func transitionToThreePanelMode() -> UIViewController { defer { masterNavigationController.viewControllers = [masterFeedViewController] } @@ -910,7 +968,8 @@ private extension AppCoordinator { let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: false) rootSplitViewController.showDetailViewController(navController, sender: self) - + return navController + } else { let controller: UIViewController = { @@ -923,13 +982,15 @@ private extension AppCoordinator { masterTimelineViewController!.navigationItem.leftBarButtonItem = nil - let subSplit = ensureDoubleSplit() + let shimController = ensureDoubleSplit() + let subSplit = shimController.children.first as! UISplitViewController let masterTimelineNavController = subSplit.viewControllers.first as! UINavigationController masterTimelineNavController.viewControllers = [masterTimelineViewController!] let navController = addNavControllerIfNecessary(controller, showButton: false) subSplit.showDetailViewController(navController, sender: self) + return shimController } } From e52b3531d90da69b692bef1dd4d670616be2e01c Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 2 Aug 2019 18:14:49 -0500 Subject: [PATCH 24/44] Add missing shim controller --- iOS/AppCoordinator.swift | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 25b19cc1b..fcb96fb44 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -621,11 +621,10 @@ extension AppCoordinator: UISplitViewControllerDelegate { func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool { - if let shimController = rootSplitViewController.viewControllers.last, - let detailNav = shimController.children.first as? UINavigationController, - let detail = detailNav.topViewController as? DetailViewController { - masterNavigationController.pushViewController(detail, animated: false) - return true + if let detailNav = secondaryViewController.children.first as? UINavigationController, let detail = detailNav.topViewController { + masterNavigationController.pushViewController(detail, animated: false) + detail.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem + return true } if let subSplit = secondaryViewController.children.first as? UISplitViewController { @@ -967,7 +966,9 @@ private extension AppCoordinator { let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: false) - rootSplitViewController.showDetailViewController(navController, sender: self) + let shimController = UIViewController() + shimController.addChildAndPinView(navController) + rootSplitViewController.showDetailViewController(shimController, sender: self) return navController } else { From 0baf15b58882f8fe536f6f6a044f016f4219b2dd Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 3 Aug 2019 10:55:46 -0500 Subject: [PATCH 25/44] Fix root split view controller collapsing and splitting when no in all visible mode --- iOS/AppCoordinator.swift | 48 ++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index fcb96fb44..758e7721d 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -608,7 +608,7 @@ class AppCoordinator: NSObject, UndoableCommandRunner { extension AppCoordinator: UISplitViewControllerDelegate { func splitViewController(_ svc: UISplitViewController, willChangeTo displayMode: UISplitViewController.DisplayMode) { - guard rootSplitViewController.traitCollection.userInterfaceIdiom == .pad else { + guard rootSplitViewController.traitCollection.userInterfaceIdiom == .pad && !rootSplitViewController.isCollapsed else { return } if rootSplitViewController.displayMode != .allVisible && displayMode == .allVisible { @@ -620,13 +620,7 @@ extension AppCoordinator: UISplitViewControllerDelegate { } func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool { - - if let detailNav = secondaryViewController.children.first as? UINavigationController, let detail = detailNav.topViewController { - masterNavigationController.pushViewController(detail, animated: false) - detail.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem - return true - } - + if let subSplit = secondaryViewController.children.first as? UISplitViewController { if let masterTimelineNav = subSplit.viewControllers.first as? UINavigationController, @@ -634,19 +628,27 @@ extension AppCoordinator: UISplitViewControllerDelegate { masterNavigationController.pushViewController(masterTimeline, animated: false) } - if let detailNav = subSplit.viewControllers.last as? UINavigationController, let detail = detailNav.topViewController { + if let detailNav = subSplit.viewControllers.last as? UINavigationController, let detail = detailNav.topViewController as? DetailViewController { masterNavigationController.pushViewController(detail, animated: false) } - return true + } else { + if let timeline = masterTimelineViewController, masterNavigationController.viewControllers.count == 1 { + masterNavigationController.pushViewController(timeline, animated: false) + } + + if let detailNav = secondaryViewController.children.first as? UINavigationController, let detail = detailNav.topViewController as? DetailViewController { + masterNavigationController.pushViewController(detail, animated: false) + } + } - return currentArticle == nil + return true + } func splitViewController(_ splitViewController: UISplitViewController, separateSecondaryFrom primaryViewController: UIViewController) -> UIViewController? { - if isThreePanelMode { return transitionToThreePanelMode() } @@ -659,21 +661,15 @@ extension AppCoordinator: UISplitViewControllerDelegate { shimController.addChildAndPinView(detailNav) return shimController - } - -// -// } else { -// -// let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) -// let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: true) -// let shimController = UIViewController() -// shimController.addChildAndPinView(navController) -// return shimController -// -// } -// - return nil + } else { + let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) + let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: true) + let shimController = UIViewController() + shimController.addChildAndPinView(navController) + return shimController + + } } } From d5094dd103d95289b4b55fc28e75ee4e82932a16 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 3 Aug 2019 11:06:55 -0500 Subject: [PATCH 26/44] Deleted obsolete code --- iOS/AppCoordinator.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 758e7721d..8eae8dfc1 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -977,8 +977,6 @@ private extension AppCoordinator { } }() - masterTimelineViewController!.navigationItem.leftBarButtonItem = nil - let shimController = ensureDoubleSplit() let subSplit = shimController.children.first as! UISplitViewController let masterTimelineNavController = subSplit.viewControllers.first as! UINavigationController From e4c3590111dcf26efee9c219a0509420db9c9d99 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 3 Aug 2019 11:09:12 -0500 Subject: [PATCH 27/44] Made code formatting more consistent --- iOS/AppCoordinator.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 8eae8dfc1..85a3e46b9 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -623,8 +623,7 @@ extension AppCoordinator: UISplitViewControllerDelegate { if let subSplit = secondaryViewController.children.first as? UISplitViewController { - if let masterTimelineNav = subSplit.viewControllers.first as? UINavigationController, - let masterTimeline = masterTimelineNav.topViewController { + if let masterTimelineNav = subSplit.viewControllers.first as? UINavigationController, let masterTimeline = masterTimelineNav.topViewController { masterNavigationController.pushViewController(masterTimeline, animated: false) } From a30b03bcea1b88438e818b4e6c736cea3f0b2360 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 3 Aug 2019 11:43:21 -0500 Subject: [PATCH 28/44] Remove obsolete code --- iOS/Detail/DetailViewController.swift | 7 ------- 1 file changed, 7 deletions(-) diff --git a/iOS/Detail/DetailViewController.swift b/iOS/Detail/DetailViewController.swift index 2f5e85c71..3261a397e 100644 --- a/iOS/Detail/DetailViewController.swift +++ b/iOS/Detail/DetailViewController.swift @@ -80,13 +80,6 @@ class DetailViewController: UIViewController { let starImage = article.status.starred ? AppAssets.starClosedImage : AppAssets.starOpenImage starBarButtonItem.image = starImage - if let timelineName = coordinator.timelineName { - if navigationController?.navigationItem.backBarButtonItem?.title != timelineName { - let backItem = UIBarButtonItem(title: timelineName, style: .plain, target: nil, action: nil) - navigationController?.navigationItem.backBarButtonItem = backItem - } - } - } func reloadHTML() { From 9768d8ca55c4aac736c728574c3029b576b4be05 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 3 Aug 2019 11:44:05 -0500 Subject: [PATCH 29/44] Fix bugs in detail back button when transitioning from collapsed mode --- iOS/AppCoordinator.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 85a3e46b9..687f594d5 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -638,6 +638,8 @@ extension AppCoordinator: UISplitViewControllerDelegate { } if let detailNav = secondaryViewController.children.first as? UINavigationController, let detail = detailNav.topViewController as? DetailViewController { + detail.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem + detail.navigationItem.leftItemsSupplementBackButton = true masterNavigationController.pushViewController(detail, animated: false) } @@ -919,6 +921,7 @@ private extension AppCoordinator { navController.isToolbarHidden = false if showButton { controller.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem + controller.navigationItem.leftItemsSupplementBackButton = true } return navController } From 536ac205a0750f88a3fdd94f107b16271b57bd72 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 3 Aug 2019 11:04:52 -0700 Subject: [PATCH 30/44] Fix crash when making a feed via AppleScript and the feed already exists. --- Mac/Scriptability/Feed+Scriptability.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Mac/Scriptability/Feed+Scriptability.swift b/Mac/Scriptability/Feed+Scriptability.swift index 42fefde87..27a1aa791 100644 --- a/Mac/Scriptability/Feed+Scriptability.swift +++ b/Mac/Scriptability/Feed+Scriptability.swift @@ -89,17 +89,17 @@ class ScriptableFeed: NSObject, UniqueIdScriptingObject, ScriptingObjectContaine guard let url = self.urlForNewFeed(arguments:arguments) else {return nil} if let existingFeed = account.existingFeed(withURL:url) { - return self.scriptableFeed(existingFeed, account:account, folder:folder) + return scriptableFeed(existingFeed, account:account, folder:folder).objectSpecifier } let container: Container = folder != nil ? folder! : account - // at this point, we need to download the feed and parse it. - // RS Parser does the callback for the download on the main thread (which it probably shouldn't?) - // because we can't wait here (on the main thread, maybe) for the callback, we have to return from this function - // Generally, returning from an AppleEvent handler function means that handling the appleEvent is over, - // but we don't yet have the result of the event yet, so we prevent the AppleEvent from returning by calling - // suspendExecution(). When we get the callback, we can supply the event result and call resumeExecution() + // We need to download the feed and parse it. + // RSParser does the callback for the download on the main thread. + // Because we can't wait here (on the main thread) for the callback, we have to return from this function. + // Generally, returning from an AppleEvent handler function means that handling the Apple event is over, + // but we don’t yet have the result of the event yet, so we prevent the Apple event from returning by calling + // suspendExecution(). When we get the callback, we supply the event result and call resumeExecution(). command.suspendExecution() account.createFeed(url: url, name: titleFromArgs, container: container) { result in From 43d0d0c8894ca81720150acc242fa7336b5e6106 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 3 Aug 2019 13:24:51 -0500 Subject: [PATCH 31/44] Reformat statement --- iOS/AppCoordinator.swift | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 687f594d5..9f6ee86d8 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -75,7 +75,9 @@ class AppCoordinator: NSObject, UndoableCommandRunner { } var isThreePanelMode: Bool { - return rootSplitViewController.traitCollection.userInterfaceIdiom == .pad && !rootSplitViewController.isCollapsed && rootSplitViewController.displayMode == .allVisible + return rootSplitViewController.traitCollection.userInterfaceIdiom == .pad && + !rootSplitViewController.isCollapsed && + rootSplitViewController.displayMode == .allVisible } var rootNode: Node { @@ -607,14 +609,14 @@ class AppCoordinator: NSObject, UndoableCommandRunner { extension AppCoordinator: UISplitViewControllerDelegate { - func splitViewController(_ svc: UISplitViewController, willChangeTo displayMode: UISplitViewController.DisplayMode) { - guard rootSplitViewController.traitCollection.userInterfaceIdiom == .pad && !rootSplitViewController.isCollapsed else { + func splitViewController(_ splitViewController: UISplitViewController, willChangeTo displayMode: UISplitViewController.DisplayMode) { + guard splitViewController.traitCollection.userInterfaceIdiom == .pad && !splitViewController.isCollapsed else { return } - if rootSplitViewController.displayMode != .allVisible && displayMode == .allVisible { + if splitViewController.displayMode != .allVisible && displayMode == .allVisible { transitionToThreePanelMode() } - if rootSplitViewController.displayMode == .allVisible && displayMode != .allVisible { + if splitViewController.displayMode == .allVisible && displayMode != .allVisible { transitionFromThreePanelMode() } } From 9aa8ea7dc9e51a0ceb61c89a9abbbf34d4d8797b Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 3 Aug 2019 13:53:30 -0500 Subject: [PATCH 32/44] Refactor some common code and wrote copious comments --- iOS/AppCoordinator.swift | 49 +++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 9f6ee86d8..50b1e338a 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -623,23 +623,29 @@ extension AppCoordinator: 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.children.first 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.children.first 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) @@ -652,12 +658,15 @@ extension AppCoordinator: UISplitViewControllerDelegate { } func splitViewController(_ splitViewController: UISplitViewController, separateSecondaryFrom primaryViewController: UIViewController) -> UIViewController? { + + // If we are in three panel mode, return back the new shim controller that contains a new sub split controller if isThreePanelMode { return transitionToThreePanelMode() } if let detail = masterNavigationController.viewControllers.last as? DetailViewController { + // If we have a detail controller on the stack, remove it, wrap it in a shim, and return it. masterNavigationController.viewControllers.removeLast() let detailNav = addNavControllerIfNecessary(detail, showButton: true) let shimController = UIViewController() @@ -666,11 +675,8 @@ extension AppCoordinator: UISplitViewControllerDelegate { } else { - let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) - let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: true) - let shimController = UIViewController() - shimController.addChildAndPinView(navController) - return shimController + // Display a no selection controller since we don't have any detail selected + return fullyWrappedSystemMesssageController() } } @@ -899,6 +905,13 @@ private extension AppCoordinator { // MARK: Double Split + // Note about the Shim Controller + // In the root split view controller's secondary (or detail) position we use a view controller that + // only acts as a shim (or wrapper) for the actaully desired contents of the second position. This + // is because we normally can't change the root split view controllers second position contents + // during the display mode change callback (in the split view controller delegate). To fool the + // system, we leave the same controller, the shim, in place and change its child controllers instead. + func installDetailController(_ detailController: UIViewController) { let showButton = rootSplitViewController.displayMode != .allVisible let controller = addNavControllerIfNecessary(detailController, showButton: showButton) @@ -956,6 +969,14 @@ private extension AppCoordinator { } } + func fullyWrappedSystemMesssageController() -> UIViewController { + let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) + let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: false) + let shimController = UIViewController() + shimController.addChildAndPinView(navController) + return shimController + } + @discardableResult func transitionToThreePanelMode() -> UIViewController { defer { @@ -964,12 +985,9 @@ private extension AppCoordinator { if currentMasterIndexPath == nil && currentArticleIndexPath == nil { - let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) - let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: false) - let shimController = UIViewController() - shimController.addChildAndPinView(navController) - rootSplitViewController.showDetailViewController(shimController, sender: self) - return navController + let wrappedSystemMessageController = fullyWrappedSystemMesssageController() + rootSplitViewController.showDetailViewController(wrappedSystemMessageController, sender: self) + return wrappedSystemMessageController } else { @@ -981,11 +999,13 @@ private extension AppCoordinator { } }() + // Create the new sub split controller (wrapped in the shim of course) and add the timeline in the primary position let shimController = ensureDoubleSplit() let subSplit = shimController.children.first as! UISplitViewController let masterTimelineNavController = subSplit.viewControllers.first as! UINavigationController masterTimelineNavController.viewControllers = [masterTimelineViewController!] + // Put the detail or no selection controller in the secondary (or detail) position of the sub split let navController = addNavControllerIfNecessary(controller, showButton: false) subSplit.showDetailViewController(navController, sender: self) @@ -999,11 +1019,14 @@ private extension AppCoordinator { if let shimController = rootSplitViewController.viewControllers.last, let subSplit = shimController.children.first as? UISplitViewController { - if let masterTimelineNav = subSplit.viewControllers.first as? UINavigationController, - let masterTimeline = masterTimelineNav.topViewController { + // Push the timeline on to the master navigation controller. This should always be true if we have installed + // the sub split controller because we only install the sub split controller if a timeline needs to be displayed. + if let masterTimelineNav = subSplit.viewControllers.first as? UINavigationController, let masterTimeline = masterTimelineNav.topViewController { masterNavigationController.pushViewController(masterTimeline, animated: false) } + // Pull the detail or no selection controller out of the sub split second position and move it to the root split controller + // secondary (detail) position, by replacing the contents of the shim controller in the second position. if let detailNav = subSplit.viewControllers.last as? UINavigationController, let topController = detailNav.topViewController { let newNav = addNavControllerIfNecessary(topController, showButton: true) shimController.replaceChildAndPinView(newNav) From 4ece4173baf6ef57ecfbb679916a4bf419f668d6 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 3 Aug 2019 13:56:18 -0500 Subject: [PATCH 33/44] Fix show back bar button bug introduced in last refactoring --- iOS/AppCoordinator.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 50b1e338a..d105695cd 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -676,7 +676,7 @@ extension AppCoordinator: UISplitViewControllerDelegate { } else { // Display a no selection controller since we don't have any detail selected - return fullyWrappedSystemMesssageController() + return fullyWrappedSystemMesssageController(showButton: true) } } @@ -969,9 +969,9 @@ private extension AppCoordinator { } } - func fullyWrappedSystemMesssageController() -> UIViewController { + func fullyWrappedSystemMesssageController(showButton: Bool) -> UIViewController { let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) - let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: false) + let navController = addNavControllerIfNecessary(systemMessageViewController, showButton: showButton) let shimController = UIViewController() shimController.addChildAndPinView(navController) return shimController @@ -985,7 +985,7 @@ private extension AppCoordinator { if currentMasterIndexPath == nil && currentArticleIndexPath == nil { - let wrappedSystemMessageController = fullyWrappedSystemMesssageController() + let wrappedSystemMessageController = fullyWrappedSystemMesssageController(showButton: false) rootSplitViewController.showDetailViewController(wrappedSystemMessageController, sender: self) return wrappedSystemMessageController From 02575c31fed7d5d915dec77eddd1fbacae5f95d5 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 3 Aug 2019 16:25:35 -0500 Subject: [PATCH 34/44] Change selected table row text to be white. Issue #693 --- iOS/AppAssets.swift | 4 ++++ .../Cell/MasterFeedTableViewCell.swift | 6 ++++++ .../Cell/MasterTimelineTableViewCell.swift | 11 ++++++++++ .../Cell/MasterUnreadIndicatorView.swift | 12 ++++++++++- .../selectedTextColor.colorset/Contents.json | 20 +++++++++++++++++++ 5 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 iOS/Resources/Assets.xcassets/selectedTextColor.colorset/Contents.json diff --git a/iOS/AppAssets.swift b/iOS/AppAssets.swift index 352ece4b1..7477f223f 100644 --- a/iOS/AppAssets.swift +++ b/iOS/AppAssets.swift @@ -60,6 +60,10 @@ struct AppAssets { return UIColor(named: "netNewsWireBlueColor")! }() + static var selectedTextColor: UIColor = { + return UIColor(named: "selectedTextColor")! + }() + static var settingsImage: UIImage = { return UIImage(named: "settingsImage")! }() diff --git a/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift b/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift index 7f34a65cc..5d13b52aa 100644 --- a/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift +++ b/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift @@ -105,6 +105,12 @@ class MasterFeedTableViewCell : UITableViewCell { commonInit() } + override func setSelected(_ selected: Bool, animated: Bool) { + titleView.textColor = selected ? AppAssets.selectedTextColor : UIColor.label + faviconImageView.tintColor = selected ? AppAssets.selectedTextColor : tintColor + super.setSelected(selected, animated: animated) + } + override func willTransition(to state: UITableViewCell.StateMask) { super.willTransition(to: state) showingEditControl = state.contains(.showingEditControl) diff --git a/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift b/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift index adfe89aea..5cf316e5b 100644 --- a/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift +++ b/iOS/MasterTimeline/Cell/MasterTimelineTableViewCell.swift @@ -44,6 +44,17 @@ class MasterTimelineTableViewCell: UITableViewCell { } } + override func setSelected(_ selected: Bool, animated: Bool) { + let selectedTextColor = selected ? AppAssets.selectedTextColor : UIColor.label + titleView.textColor = selectedTextColor + summaryView.textColor = selectedTextColor + dateView.textColor = selectedTextColor + feedNameView.textColor = selectedTextColor + unreadIndicatorView.isSelected = selected + + super.setSelected(selected, animated: animated) + } + override func sizeThatFits(_ size: CGSize) -> CGSize { let layout = updatedLayout(width: size.width) return CGSize(width: size.width, height: layout.height) diff --git a/iOS/MasterTimeline/Cell/MasterUnreadIndicatorView.swift b/iOS/MasterTimeline/Cell/MasterUnreadIndicatorView.swift index d7e90469a..d09cd8f34 100644 --- a/iOS/MasterTimeline/Cell/MasterUnreadIndicatorView.swift +++ b/iOS/MasterTimeline/Cell/MasterUnreadIndicatorView.swift @@ -10,6 +10,12 @@ import UIKit class MasterUnreadIndicatorView: UIView { + var isSelected = false { + didSet { + setNeedsDisplay() + } + } + override init(frame: CGRect) { super.init(frame: frame) self.isOpaque = false @@ -26,7 +32,11 @@ class MasterUnreadIndicatorView: UIView { }() override func draw(_ dirtyRect: CGRect) { - AppAssets.timelineUnreadCircleColor.setFill() + if isSelected { + AppAssets.selectedTextColor.setFill() + } else { + AppAssets.timelineUnreadCircleColor.setFill() + } MasterUnreadIndicatorView.bezierPath.fill() } diff --git a/iOS/Resources/Assets.xcassets/selectedTextColor.colorset/Contents.json b/iOS/Resources/Assets.xcassets/selectedTextColor.colorset/Contents.json new file mode 100644 index 000000000..c6e5d3d43 --- /dev/null +++ b/iOS/Resources/Assets.xcassets/selectedTextColor.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "1.000", + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000" + } + } + } + ] +} \ No newline at end of file From 0269683b16b17bed431fca90e9a2e9e984671d7a Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 3 Aug 2019 16:34:35 -0500 Subject: [PATCH 35/44] Reenable tinting now that at the beta OS releases don't crash when using them --- iOS/AppAssets.swift | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/iOS/AppAssets.swift b/iOS/AppAssets.swift index 7477f223f..20dd186d4 100644 --- a/iOS/AppAssets.swift +++ b/iOS/AppAssets.swift @@ -28,14 +28,12 @@ struct AppAssets { static var chevronDownImage: UIImage = { let image = UIImage(systemName: "chevron.down")! - return image -// return image.withTintColor(AppAssets.chevronDisclosureColor, renderingMode: .alwaysOriginal) + return image.withTintColor(AppAssets.chevronDisclosureColor, renderingMode: .alwaysOriginal) }() static var chevronRightImage: UIImage = { let image = UIImage(systemName: "chevron.right")! - return image -// return image.withTintColor(AppAssets.chevronDisclosureColor, renderingMode: .alwaysOriginal) + return image.withTintColor(AppAssets.chevronDisclosureColor, renderingMode: .alwaysOriginal) }() static var faviconTemplateImage: RSImage = { @@ -51,9 +49,7 @@ struct AppAssets { }() static var masterFolderImage: UIImage = { - let image = UIImage(systemName: "folder.fill")! - return image -// return image.withTintColor(AppAssets.masterFolderColor, renderingMode: .alwaysOriginal) + return UIImage(systemName: "folder.fill")! }() static var netNewsWireBlueColor: UIColor = { @@ -73,9 +69,7 @@ struct AppAssets { }() static var smartFeedImage: UIImage = { - let image = UIImage(systemName: "gear")! - return image -// return image.withTintColor(AppAssets.smartFeedColor, renderingMode: .alwaysOriginal) + return UIImage(systemName: "gear")! }() static var starColor: UIColor = { @@ -92,8 +86,7 @@ struct AppAssets { static var timelineStarImage: UIImage = { let image = UIImage(systemName: "star.fill")! - return image -// return image.withTintColor(AppAssets.starColor, renderingMode: .alwaysOriginal) + return image.withTintColor(AppAssets.starColor, renderingMode: .alwaysOriginal) }() static var timelineUnreadCircleColor: UIColor = { From e39972bd64d9cfe6c591b5379e5538f7c7ce4ee2 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 3 Aug 2019 17:07:43 -0500 Subject: [PATCH 36/44] Correct First Unread button to select the first unread in the timeline and show article in detail view. Issue #695 --- iOS/AppCoordinator.swift | 17 +++++++++++++++-- .../MasterTimelineViewController.swift | 4 +--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index d105695cd..2cf8872b3 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -510,6 +510,10 @@ class AppCoordinator: NSObject, UndoableCommandRunner { } } + func selectFirstUnread() { + selectFirstUnreadArticleInTimeline() + } + func selectNextUnread() { // This should never happen, but I don't want to risk throwing us @@ -718,9 +722,13 @@ private extension AppCoordinator { // MARK: Select Next Unread + @discardableResult + func selectFirstUnreadArticleInTimeline() -> Bool { + return selectArticleInTimeline(startingRow: 0) + } + @discardableResult func selectNextUnreadArticleInTimeline() -> Bool { - let startingRow: Int = { if let indexPath = currentArticleIndexPath { return indexPath.row @@ -729,10 +737,15 @@ private extension AppCoordinator { } }() + return selectArticleInTimeline(startingRow: startingRow) + } + + func selectArticleInTimeline(startingRow: Int) -> Bool { + for i in startingRow.. Date: Sat, 3 Aug 2019 17:28:45 -0500 Subject: [PATCH 37/44] Removed unused color for folders. This has been replaced with the tint color. --- iOS/AppAssets.swift | 4 ---- .../masterFolderColor.colorset/Contents.json | 20 ------------------- 2 files changed, 24 deletions(-) delete mode 100644 iOS/Resources/Assets.xcassets/masterFolderColor.colorset/Contents.json diff --git a/iOS/AppAssets.swift b/iOS/AppAssets.swift index 20dd186d4..d6646cfe2 100644 --- a/iOS/AppAssets.swift +++ b/iOS/AppAssets.swift @@ -44,10 +44,6 @@ struct AppAssets { return RSImage(named: "feedImage")! }() - static var masterFolderColor: UIColor = { - return UIColor(named: "masterFolderColor")! - }() - static var masterFolderImage: UIImage = { return UIImage(systemName: "folder.fill")! }() diff --git a/iOS/Resources/Assets.xcassets/masterFolderColor.colorset/Contents.json b/iOS/Resources/Assets.xcassets/masterFolderColor.colorset/Contents.json deleted file mode 100644 index 728894ebe..000000000 --- a/iOS/Resources/Assets.xcassets/masterFolderColor.colorset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - }, - "colors" : [ - { - "idiom" : "universal", - "color" : { - "color-space" : "srgb", - "components" : { - "red" : "111", - "alpha" : "1.000", - "blue" : "250", - "green" : "175" - } - } - } - ] -} \ No newline at end of file From 55da3185035567ad737b8ebab1b6607a2e5b0b61 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sun, 4 Aug 2019 13:20:37 -0500 Subject: [PATCH 38/44] Fix bug that was causing new feeds to be created with and empty string name --- iOS/Add/UIKit/AddFeedViewController.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/iOS/Add/UIKit/AddFeedViewController.swift b/iOS/Add/UIKit/AddFeedViewController.swift index a0495d8f9..73210a40a 100644 --- a/iOS/Add/UIKit/AddFeedViewController.swift +++ b/iOS/Add/UIKit/AddFeedViewController.swift @@ -91,9 +91,12 @@ class AddFeedViewController: UITableViewController, AddContainerViewControllerCh } delegate?.processingDidBegin() + + let feedName = (nameTextField.text?.isEmpty ?? true) ? nil : nameTextField.text + BatchUpdate.shared.start() - account!.createFeed(url: url.absoluteString, name: nameTextField.text, container: container) { result in + account!.createFeed(url: url.absoluteString, name: feedName, container: container) { result in BatchUpdate.shared.end() From f8eb750d56e1b5eb8d6c06c55c5d5eb1361e34a7 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sun, 4 Aug 2019 13:23:34 -0500 Subject: [PATCH 39/44] Fix background color to respect dark mode --- iOS/Add/UIKit/Add.storyboard | 61 +++++++++++++++++------------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/iOS/Add/UIKit/Add.storyboard b/iOS/Add/UIKit/Add.storyboard index 12745974f..a422fd8f3 100644 --- a/iOS/Add/UIKit/Add.storyboard +++ b/iOS/Add/UIKit/Add.storyboard @@ -1,11 +1,8 @@ - - - - + + - - + @@ -22,14 +19,14 @@ - + - + - + @@ -44,14 +41,14 @@ - + - + - + @@ -70,20 +67,20 @@ - + - + - + - + - + @@ -171,7 +168,7 @@ - + @@ -184,10 +181,10 @@ - + - + @@ -249,14 +246,14 @@ - + - + - + @@ -275,20 +272,20 @@ - + - + - + - + - + From 659597e5e4717b84ee6a33c8aa451ca707d9595d Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sun, 4 Aug 2019 13:43:35 -0500 Subject: [PATCH 40/44] Fix about box for dark mode --- iOS/Settings/UIKit/AboutViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/iOS/Settings/UIKit/AboutViewController.swift b/iOS/Settings/UIKit/AboutViewController.swift index 31da63e9e..9c52e9611 100644 --- a/iOS/Settings/UIKit/AboutViewController.swift +++ b/iOS/Settings/UIKit/AboutViewController.swift @@ -51,6 +51,7 @@ private extension AboutViewController { textView.attributedText = string textView.adjustsFontForContentSizeCategory = true textView.font = .preferredFont(forTextStyle: .body) + textView.textColor = UIColor.label } } From 5a594fd3cb2411903d87fca9cb3c5007ab680891 Mon Sep 17 00:00:00 2001 From: Ryan Dotson Date: Mon, 5 Aug 2019 07:55:50 +0900 Subject: [PATCH 41/44] Helpbook: organised index, updating NetNewsWire, user data, privacy Organised index a bit Added pages: - user data location - privacy summary - updating the app Minor formatting adjustments --- Technotes/HelpBook/5.0/en/index.markdown | 77 ++++++++++++------- Technotes/HelpBook/5.0/en/privacy.markdown | 15 ++++ .../HelpBook/5.0/en/safari-extension.markdown | 6 +- Technotes/HelpBook/5.0/en/updating.markdown | 25 ++++++ .../5.0/en/userdata-location.markdown | 42 ++++++++++ 5 files changed, 135 insertions(+), 30 deletions(-) create mode 100644 Technotes/HelpBook/5.0/en/privacy.markdown create mode 100644 Technotes/HelpBook/5.0/en/updating.markdown create mode 100644 Technotes/HelpBook/5.0/en/userdata-location.markdown diff --git a/Technotes/HelpBook/5.0/en/index.markdown b/Technotes/HelpBook/5.0/en/index.markdown index e975f5b62..e92538630 100644 --- a/Technotes/HelpBook/5.0/en/index.markdown +++ b/Technotes/HelpBook/5.0/en/index.markdown @@ -1,52 +1,75 @@ @title NetNewsWire 5 Help +## Getting Started [What is RSS? What are feeds?](what-is-rss.html) -More topics to do… + + +## Reading Feeds + +[How to go through your articles](reading-articles.html) + +How to sort the timeline + +Tour of the built-in smart feeds: Today, All Unread, Starred + +Keyboard shortcuts (see Help menu command) + +Sharing to other apps, including MarsEdit and Micro.blog + + + +## Managing Feeds [How to add a feed](adding-feeds.html) [Installing and using the Safari Extension to add feeds](safari-extension.html) -[How to import OPML](import-opml.html) - -[How to export OPML](export-opml.html) - -[How to go through your articles](reading-articles.html) - -Sharing to other apps, including MarsEdit and Micro.blog - [How to delete feeds and folders](deleting-feeds-folders.html) -How to add a syncing account - -[How to contribute](contributing.html) - -[How to get NetNewsWire news](netnewswire-news.html) - -Keyboard shortcuts (see Help menu command) - -[About the On My Mac account](on-my-mac.html) - -Privacy (including link to privacy policy) - How to add special Micro.blog feeds How to rename feeds and folders How to get and copy feed information -Where NetNewsWire data is stored -How to update NetNewsWire -How to sort the timeline +## Accounts -Tour of the built-in smart feeds: Today, All Unread, Starred +Accounts overview -Other ideas? Add them here. +[About the On My Mac account](on-my-mac.html) + +How to add a syncing account + + + +## NetNewsWire Data + +[Where NetNewsWire data is stored](userdata-location.html) + +[How to import OPML](import-opml.html) + +[How to export OPML](export-opml.html) + + + +## The NetNewsWire Project + +[How to Update NetNewsWire](updating.html) + +[How to get NetNewsWire news](netnewswire-news.html) + +[NetNewsWire and your privacy](privacy.html) + +[How to contribute to NetNewsWire](contributing.html) + + + +## Other ideas? Add them here. --- -Credits: The Help book was written [Brent Simmons](https://inessential.com/), your name here, etc. +Credits: The Help book was written by [Brent Simmons](https://inessential.com/), [Ryan Dotson](https://nostodnayr.net), your name here, etc. diff --git a/Technotes/HelpBook/5.0/en/privacy.markdown b/Technotes/HelpBook/5.0/en/privacy.markdown new file mode 100644 index 000000000..50eac92fe --- /dev/null +++ b/Technotes/HelpBook/5.0/en/privacy.markdown @@ -0,0 +1,15 @@ +@title NetNewsWire and your privacy + +# NetNewsWire and your privacy + +[The NetNewsWire Privacy Policy](https://github.com/brentsimmons/NetNewsWire/blob/master/Technotes/privacypolicy.markdown) + +NetNewsWire has a very strict privacy policy – we don’t want any private information about you. + +The only data we collect about how you use NetNewsWire, *only if you agree and opt in*, is crash logs. + + + +## Changes to the Privacy Policy + +The [full privacy policy](https://github.com/brentsimmons/NetNewsWire/blob/master/Technotes/privacypolicy.markdown) is stored in the NetNewsWire GitHub repository, where you can track any changes we might make. \ No newline at end of file diff --git a/Technotes/HelpBook/5.0/en/safari-extension.markdown b/Technotes/HelpBook/5.0/en/safari-extension.markdown index 251582c78..c064d0a6d 100644 --- a/Technotes/HelpBook/5.0/en/safari-extension.markdown +++ b/Technotes/HelpBook/5.0/en/safari-extension.markdown @@ -2,7 +2,7 @@ # Installing and using the Safari Extension to add feeds -NetNewsWire provides a Safari Extension which adds a ‘Subscribe to Feed’ button to your Safari toolbar. This allows you to quickly add a site’s feed without entering an address manually into NetNewsWire. +NetNewsWire provides a Safari Extension which adds a *Subscribe to Feed* button to your Safari toolbar. This allows you to quickly add a site’s feed without entering an address manually into NetNewsWire. ## Installing the NetNewsWire Safari Extension @@ -17,7 +17,7 @@ You will enable the extension in Safari: 4. From the list, click the checkbox beside **Subscribe to Feed** to enable the extension 5. Close the Preferences window -Once this is done, the ‘Subscribe to Feed’ button will be added to your Safari toolbar. +Once this is done, the *Subscribe to Feed* button will be added to your Safari toolbar. ## Adding a feed using the Safari Extension @@ -27,6 +27,6 @@ For any site that advertises its feeds, you can use the ‘Subscribe to Feed’ ### What to do if the ‘Subscribe to Feed’ button is greyed out and disabled -The ‘Subscribe in NetNewsWire’ button will only be enabled for sites that advertise their feeds in their code. If the button is disabled, NetNewsWire wasn’t able to find any feeds automatically. +The *Subscribe to Feed* button will only be enabled for sites that advertise their feeds in their code. If the button is disabled, NetNewsWire wasn’t able to find any feeds automatically. You may be able to find a feed manually by visiting the site. There, look for a link to an RSS, Atom or JSON feed. If one exists, you can [add this URL to NetNewsWire directly](adding-feeds.html). Right-click on the link and copy the URL to paste into NetNewsWire. \ No newline at end of file diff --git a/Technotes/HelpBook/5.0/en/updating.markdown b/Technotes/HelpBook/5.0/en/updating.markdown new file mode 100644 index 000000000..3245ae88d --- /dev/null +++ b/Technotes/HelpBook/5.0/en/updating.markdown @@ -0,0 +1,25 @@ +@title How to Update NetNewsWire + +# How to Update NetNewsWire + +NetNewsWire can check for and install updated versions of itself. This can be done for you automatically in the background or you can check for updates manually. + + + +## Automatic checks for updates + +When you first launch NetNewsWire you’ll be asked whether it should periodically check for updates. You will be notified of any new updates and can choose to update when you’re ready. + + + +## Manually checking for updates + +You may have declined automatic checks for updates or just [read about a great new update](netnewswire-news.html) and want to download it now. You can always check for updates manually by selecting **NetNewsWire → Check for Updates…** from the menu bar. + +If a new update is found, NetNewsWire can download and install it for you. + + + +## Privacy + +When checking for updates, whether automatically or manually, no personally-identifiable information is collected – not even an anonymous system profile. For more information about your privacy and NetNewsWire, please see the NetNewsWire Privacy Policy. \ No newline at end of file diff --git a/Technotes/HelpBook/5.0/en/userdata-location.markdown b/Technotes/HelpBook/5.0/en/userdata-location.markdown new file mode 100644 index 000000000..ff86593fd --- /dev/null +++ b/Technotes/HelpBook/5.0/en/userdata-location.markdown @@ -0,0 +1,42 @@ +@title Where NetNewsWire data is stored + +# Where NetNewsWire data is stored + +NetNewsWire remembers your feeds and article read status, as well as your account information and preferences. This information is stored in two different locations on your Mac, but separately from the NetNewsWire app. + + + +## Preferences file + +Your NetNewsWire preferences file is called `com.ranchero.NetNewsWire-Evergreen.plist`. It’s stored in your account’s Preferences folder, which can be found in the Finder by navigating to: + +*Your home folder* › Library › Preferences + + +### Preferences caching + +The contents in the preferences `plist` file are cached by macOS. If you make any changes or delete the file, log out and log back in before relaunching NetNewsWire to make sure the old settings are fully cleared. (Alternatively, if you prefer, you can also run `killall cfprefsd` from Terminal to reload the preferences cache.) + + + +## Feeds and accounts data + +Information about your subscribed feeds, article read status and accounts (On my Mac and Feedbin) are stored in your account’s Application Support folder. This can be found in the Finder by navigating to: + +*Your home folder* › Library › Application Support › NetNewsWire + + +### Exporting your feeds + +If you just want to export your list of subscribed feeds, NetNewsWire [can export an OPML for you](export-opml.html). + + + +## Resetting or removing NetNewsWire + +If you are encountering problems while using NetNewsWire, by removing the files and folders above you can set up NetNewsWire again from scratch. You may also want to delete these files if you want to completely remove NetNewsWire from your Mac. + + +### Can’t find the Library folder? + +If you can’t see the Library folder in the Finder, you can open it by holding down the Option (⌥) key and clicking **Go → Library**. For more information, see the [Library folder](https://support.apple.com/en-gb/guide/mac-help/aside/mh35934/10.14/mac/10.14) note in the macOS Documentation. \ No newline at end of file From 13797c66934945d2a9579032cb55d6c8d2eaba3d Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sun, 4 Aug 2019 23:02:09 -0700 Subject: [PATCH 42/44] Remove no-longer-needed removal of that weird character Six Colors uses in some of their headlines. --- Shared/Timeline/TimelineStringFormatter.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Shared/Timeline/TimelineStringFormatter.swift b/Shared/Timeline/TimelineStringFormatter.swift index c066ab0d1..067d5542c 100644 --- a/Shared/Timeline/TimelineStringFormatter.swift +++ b/Shared/Timeline/TimelineStringFormatter.swift @@ -65,7 +65,6 @@ struct TimelineStringFormatter { s = s.replacingOccurrences(of: "\r", with: "") s = s.replacingOccurrences(of: "\t", with: "") s = s.rsparser_stringByDecodingHTMLEntities() - s = s.replacingOccurrences(of: "↦", with: "") s = s.rs_stringByTrimmingWhitespace() s = s.rs_stringWithCollapsedWhitespace() From 7c5c02407aa7e427015f828d07e2611d07f13333 Mon Sep 17 00:00:00 2001 From: Ryan Dotson Date: Tue, 6 Aug 2019 22:24:04 +0900 Subject: [PATCH 43/44] Help Book: Added sorting, syncing, keyboard shortcuts Added pages: - Sorting the timeline - Syncing accounts - Keyboard shortcuts Updated pages: - On My Mac: added hiding/disabling - On My Mac: added syncing note - Adding Feeds: added links - Various pages, adjusting formatting Many files touched to make minor content and formatting changes --- .../HelpBook/5.0/en/adding-feeds.markdown | 26 +++++---- .../HelpBook/5.0/en/contributing.markdown | 10 +++- .../5.0/en/deleting-feeds-folders.markdown | 5 +- Technotes/HelpBook/5.0/en/index.markdown | 8 ++- .../5.0/en/keyboard-shortcuts.markdown | 55 +++++++++++++++++++ .../HelpBook/5.0/en/netnewswire-news.markdown | 5 +- Technotes/HelpBook/5.0/en/on-my-mac.markdown | 34 ++++++++++-- Technotes/HelpBook/5.0/en/privacy.markdown | 3 +- .../HelpBook/5.0/en/reading-articles.markdown | 16 ++++-- .../HelpBook/5.0/en/safari-extension.markdown | 8 ++- .../5.0/en/sorting-the-timeline.markdown | 13 +++++ Technotes/HelpBook/5.0/en/updating.markdown | 9 ++- .../5.0/en/userdata-location.markdown | 13 +++-- .../HelpBook/5.0/en/what-is-rss.markdown | 2 +- 14 files changed, 170 insertions(+), 37 deletions(-) create mode 100644 Technotes/HelpBook/5.0/en/keyboard-shortcuts.markdown create mode 100644 Technotes/HelpBook/5.0/en/sorting-the-timeline.markdown diff --git a/Technotes/HelpBook/5.0/en/adding-feeds.markdown b/Technotes/HelpBook/5.0/en/adding-feeds.markdown index 46a93f964..8c3f42486 100644 --- a/Technotes/HelpBook/5.0/en/adding-feeds.markdown +++ b/Technotes/HelpBook/5.0/en/adding-feeds.markdown @@ -15,33 +15,37 @@ Before you finish, you can choose an alternative name for the feed and where it Click ‘Add’ and NetNewsWire will fetch the URL you entered. If you entered an address that’s not a feed, NetNewsWire will search the page and add the feed it finds. -## Choosing an alternative name for a feed + +Choosing an alternative name for a feed +--------------------------------------- Feeds specify their own name, but you may want to change it to something easier to remember. ‘Brent’ rather than ‘inessential’, for example. You also change this later in the [feed inspector]. -## Choosing a feed’s folder + +Choosing a feed’s folder +------------------------ Before you add a feed, you can choose the account and folder where it will be saved. -This option is especially important if you’re using multiple accounts. You can choose whether to save the subscription to your [On My Mac](on-my-mac.html) account or [Feedbin] account. +This option is especially important if you’re using multiple accounts. You can choose whether to save the subscription to your [On My Mac](on-my-mac.html) account or [Feedbin](syncing-accounts.html) account. In either case, if you use folders, you can also choose which one keep the feed in. -## What to do when NetNewsWire can’t find a feed -Sometimes NetNewsWire won’t be able to find a feed for a site. Either the site doesn’t offer a feed, or the feed isn’t advertised in a way that NetNewsWire can find it. +What to do when NetNewsWire can’t find a feed +--------------------------------------------- + +Sometimes NetNewsWire won’t be able to find a feed for a site. Either the site doesn’t offer a feed, or the feed isn’t advertised in a way that NetNewsWire can find it. You may be able to find a feed manually by visiting the site. There, look for a link to an RSS, Atom or JSON feed. If one exists, you can add this direct URL to NetNewsWire using the process above. Right-click on the link and copy the URL to paste into NetNewsWire. -## Other ways to add feeds -### Safari Extension +Other ways to add feeds +----------------------- -You can also add a feed from Safari using the [NetNewsWire Safari Extension](safari-extension.html). +Adding feeds in the NetNewsWire app isn’t the only way. You can also add feeds from Safari using the [NetNewsWire Safari Extension](safari-extension.html). -### Importing an OPML list of feeds - -If you have an existing subscription list in OPML format, you can [import those feeds into NetNewsWire](import-opml.html). \ No newline at end of file +If you have an existing OPML subscription list from another app or service, you can [import those feeds into NetNewsWire](import-opml.html), too. \ No newline at end of file diff --git a/Technotes/HelpBook/5.0/en/contributing.markdown b/Technotes/HelpBook/5.0/en/contributing.markdown index 9396299ea..67bb8db61 100644 --- a/Technotes/HelpBook/5.0/en/contributing.markdown +++ b/Technotes/HelpBook/5.0/en/contributing.markdown @@ -6,10 +6,16 @@ NetNewsWire is open-source and contributions from the community are welcomed. There are two channels for contributing. There is a Slack group for conducting discussions. For filing tickets, and contributing code or documentation, we use GitHub. -## Slack + + +Slack +----- [Join the Slack group](https://join.slack.com/t/netnewswire/shared_invite/enQtNjM4MDA1MjQzMDkzLTNlNjBhOWVhYzdhYjA4ZWFhMzQ1MTUxYjU0NTE5ZGY0YzYwZWJhNjYwNTNmNTg2NjIwYWY4YzhlYzk5NmU3ZTc) to talk with other NetNewsWire users — and to help out, if you’d like to, by testing, coding, writing, providing feedback, or just helping us think things through. Everybody is welcome and encouraged to join. -## GitHub + + +GitHub +------ The [NetNewsWire project on GitHub](https://github.com/brentsimmons/NetNewsWire) is the place to raise formal issues like bugs and feature requests. If you want to make contributions to NetNewsWire’s code or documentation, please refer to our [contribution guidelines](https://github.com/brentsimmons/NetNewsWire/blob/master/CONTRIBUTING.md) page on GitHub. \ No newline at end of file diff --git a/Technotes/HelpBook/5.0/en/deleting-feeds-folders.markdown b/Technotes/HelpBook/5.0/en/deleting-feeds-folders.markdown index 2679a5a24..5a920c0de 100644 --- a/Technotes/HelpBook/5.0/en/deleting-feeds-folders.markdown +++ b/Technotes/HelpBook/5.0/en/deleting-feeds-folders.markdown @@ -4,6 +4,9 @@ To delete a feed or folder, select it from the subscription list and choose **Edit → Delete** from the menu bar. Alternatively, select the feed and press the **delete** key. -## Undo deleting a feed or folder + + +Undo deleting a feed or folder +------------------------------ If you change your mind, you can undo the deletion by selecting **Edit → Undo** in the menu bar or pressing ⌘-Z. \ No newline at end of file diff --git a/Technotes/HelpBook/5.0/en/index.markdown b/Technotes/HelpBook/5.0/en/index.markdown index e92538630..25a61e109 100644 --- a/Technotes/HelpBook/5.0/en/index.markdown +++ b/Technotes/HelpBook/5.0/en/index.markdown @@ -10,11 +10,11 @@ [How to go through your articles](reading-articles.html) -How to sort the timeline +[How to sort the timeline](sorting-the-timeline.html) Tour of the built-in smart feeds: Today, All Unread, Starred -Keyboard shortcuts (see Help menu command) +[Keyboard shortcuts](keyboard-shortcuts.html) Sharing to other apps, including MarsEdit and Micro.blog @@ -42,7 +42,7 @@ Accounts overview [About the On My Mac account](on-my-mac.html) -How to add a syncing account +[How to add a syncing account](syncing-accounts.html) @@ -70,6 +70,8 @@ How to add a syncing account ## Other ideas? Add them here. + + --- Credits: The Help book was written by [Brent Simmons](https://inessential.com/), [Ryan Dotson](https://nostodnayr.net), your name here, etc. diff --git a/Technotes/HelpBook/5.0/en/keyboard-shortcuts.markdown b/Technotes/HelpBook/5.0/en/keyboard-shortcuts.markdown new file mode 100644 index 000000000..dc6b9b224 --- /dev/null +++ b/Technotes/HelpBook/5.0/en/keyboard-shortcuts.markdown @@ -0,0 +1,55 @@ +@title Keyboard shortcuts + +# Keyboard shortcuts + +NetNewsWire’s interface is easily navigable using keyboard shortcuts. + +The most useful shortcuts are for reading articles: **space** to scroll articles and jump to the next unread one, or **n** to jump immediately to the next unread article. There’s also **b** to open the article in your browser (the **Return** or **Enter** keys work too). + + + +In-app list of keyboard shortcuts +--------------------------------- + +A comprehensive list of NetNewsWire’s keyboard shortcuts is always accessible to you in NetNewsWire. Just click on **Help → Keyboard Shortcuts** in the menu bar. + +The list opens in a separate window which you can leave open to remind you of the keys to press. *You’ll be a NetNewsWire keyboard magician in no time.* + + +### Do I need to use the Command key? + +No, the Command (⌘) key isn’t required for these advanced keyboard shortcuts – just press the key by itself. + + + +NetNewsWire’s keyboard shortcuts +-------------------------------- + +Many of NetNewsWire’s shortcuts work from anywhere in the app. Others only work when a certain pane is active and highlighted. + + + + + + + + + + + + + + + + + + + + + + + + + + +
Everywhere in NetNewsWire
Scroll or go to next unread space
Go to next unread n or +
Mark as read r
Mark all as read k
Mark older articles as read o
Mark all as read, go to next unread l
Mark as unread, go to next unread m
Mark as unread u
Open in browser b or ⏎ or Enter
Previous subscription a
Next subscription z
Feed list (left pane)
Collapse , or ⌥+←
Expand . or ⌥+→
Collapse All (except for group items) ; or ⌥+⌘+←
Expand All ' or ⌥+⌘+→
Move focus to headlines
Article list timeline (centre pane)
Move focus to subscriptions
Move focus to detail
Article reader (right pane)
Move focus to headlines
\ No newline at end of file diff --git a/Technotes/HelpBook/5.0/en/netnewswire-news.markdown b/Technotes/HelpBook/5.0/en/netnewswire-news.markdown index 647a4d54a..345972de0 100644 --- a/Technotes/HelpBook/5.0/en/netnewswire-news.markdown +++ b/Technotes/HelpBook/5.0/en/netnewswire-news.markdown @@ -4,7 +4,10 @@ The very best way to get news about NetNewsWire is with NetNewsWire itself, using the *NetNewsWire News Feed*. Important and notable news about NetNewsWire will appear there: new version announcements, critical bug notices, tech notes and important project announcements. -## Add the NetNewsWire News Feed + + +Add the NetNewsWire News Feed +----------------------------- The NetNewsWire News Feed is part of the default subscription list installed the first time you launched NetNewsWire. If it’s no longer in your list, it’s easy to add it back. diff --git a/Technotes/HelpBook/5.0/en/on-my-mac.markdown b/Technotes/HelpBook/5.0/en/on-my-mac.markdown index e7b06c034..be9dda07d 100644 --- a/Technotes/HelpBook/5.0/en/on-my-mac.markdown +++ b/Technotes/HelpBook/5.0/en/on-my-mac.markdown @@ -1,6 +1,6 @@ -@title About the On My Mac account +@title The On My Mac account -# About the On My Mac account +# The On My Mac account The On My Mac account is the simplest way to use NetNewsWire. Using it requires no additional service or software. It’s just you, your subscriptions and NetNewsWire. @@ -8,7 +8,33 @@ On My Mac subscriptions are wholly managed by NetNewsWire. It keeps your subscri The On My Mac account does not sync this data to any other location. It works best for those people who only read NetNewsWire feeds on one Mac and nowhere else. +*NetNewsWire can also be used with a [syncing account](syncing-accounts.html) service like Feedbin.* -## Refreshing On My Mac feeds -The feeds in the On My Mac account will be refreshed automatically whenever you open NetNewsWire. If left open, NetNewsWire will refresh your feeds every hour, or according to the schedule you set in Preferences. You can also disable all automatic refreshing from there. \ No newline at end of file +Refreshing On My Mac feeds +-------------------------- + +The feeds in the On My Mac account will be refreshed automatically whenever you open NetNewsWire. If left open, NetNewsWire will refresh your feeds every hour, or according to the schedule you set in Preferences. + + + +If you don’t use the On My Mac account +-------------------------------------- + +If you only use a syncing account with NetNewsWire, you may want to hide or disable the On My Mac account. + + +### Hide the On My Mac account + +To hide the On My Mac account, place the mouse over the **On My Mac** listing in the sidebar and click on **Hide**. + + +### Disable the On My Mac account + +Disabling the On My Mac account can be done in NetNewsWire’s preferences. + +1. Open the NetNewsWire preferences from **NetNewsWire → Preferences…** (⌘-,) +2. Click on **Accounts** and select *On My Mac* +3. Deselect the *Active* tick box + +You’ll no longer see the On My Mac account in the NetNewsWire sidebar. \ No newline at end of file diff --git a/Technotes/HelpBook/5.0/en/privacy.markdown b/Technotes/HelpBook/5.0/en/privacy.markdown index 50eac92fe..e4cbc6162 100644 --- a/Technotes/HelpBook/5.0/en/privacy.markdown +++ b/Technotes/HelpBook/5.0/en/privacy.markdown @@ -10,6 +10,7 @@ The only data we collect about how you use NetNewsWire, *only if you agree and o -## Changes to the Privacy Policy +Changes to the Privacy Policy +----------------------------- The [full privacy policy](https://github.com/brentsimmons/NetNewsWire/blob/master/Technotes/privacypolicy.markdown) is stored in the NetNewsWire GitHub repository, where you can track any changes we might make. \ No newline at end of file diff --git a/Technotes/HelpBook/5.0/en/reading-articles.markdown b/Technotes/HelpBook/5.0/en/reading-articles.markdown index 687f241f8..b4d8c4daa 100644 --- a/Technotes/HelpBook/5.0/en/reading-articles.markdown +++ b/Technotes/HelpBook/5.0/en/reading-articles.markdown @@ -9,21 +9,27 @@ One-handed reading is accomplished with keyboard shortcuts. NetNewsWire’s shor (For a full list of keyboard shortcuts, including Command (⌘) key alternatives, see the [Keyboard Shortcuts](keyboard-shortcuts.html) help page, or use **Help → Keyboard Shortcuts** in NetNewsWire.) -## Use the Space bar + +Use the Space bar +----------------- The easiest way to read articles in NetNewsWire is using the **space bar**. If you’re reading an article that can be scrolled, pressing **space bar** will scroll it – just like it would in Safari. If you’re at the end of the article, **space bar** will take you to the next unread article. -## Go to Next Unread + +Go to Next Unread +----------------- Sometimes you may want to skip reading an article entirely – that’s totally fine! Rather than press space bar multiple times, you can jump directly to the next unread item by pressing ⌘-/ or just press **n** or **+**. If you want to skip the article for now, but plan to come back to it later, the **m** key is for you. Pressing it will mark the current article as unread and then go to the *next unread* item. -## Moving around lists + +Moving around lists +------------------- You may not always want to read linearly – imagine there’s a new article on [Julia Evans’](https://jvns.ca) site you want to read first. You still don’t need to leave the keyboard. @@ -32,7 +38,9 @@ Pressing the left and right arrow keys will move you between the three panes in In the subscription and article lists, the up and down arrow keys will change the currently selected item. -## Marking as read or unread + +Marking as read or unread +------------------------- As you zip through the NetNewsWire interface, you may want to mark an article as read or unread. The easiest way to do this is use the **r** and **u** keys, respectively. diff --git a/Technotes/HelpBook/5.0/en/safari-extension.markdown b/Technotes/HelpBook/5.0/en/safari-extension.markdown index c064d0a6d..98024045f 100644 --- a/Technotes/HelpBook/5.0/en/safari-extension.markdown +++ b/Technotes/HelpBook/5.0/en/safari-extension.markdown @@ -5,7 +5,9 @@ NetNewsWire provides a Safari Extension which adds a *Subscribe to Feed* button to your Safari toolbar. This allows you to quickly add a site’s feed without entering an address manually into NetNewsWire. -## Installing the NetNewsWire Safari Extension + +Installing the NetNewsWire Safari Extension +------------------------------------------- The Safari Extension is installed automatically with NetNewsWire. However, it must be *enabled* before you can use it. @@ -20,7 +22,9 @@ You will enable the extension in Safari: Once this is done, the *Subscribe to Feed* button will be added to your Safari toolbar. -## Adding a feed using the Safari Extension + +Adding a feed using the Safari Extension +---------------------------------------- For any site that advertises its feeds, you can use the ‘Subscribe to Feed’ button. Clicking it send the feed’s address to NetNewsWire where you can set options like an alternative feed name, and the account and folder where it will be stored. diff --git a/Technotes/HelpBook/5.0/en/sorting-the-timeline.markdown b/Technotes/HelpBook/5.0/en/sorting-the-timeline.markdown new file mode 100644 index 000000000..bc1b10ef7 --- /dev/null +++ b/Technotes/HelpBook/5.0/en/sorting-the-timeline.markdown @@ -0,0 +1,13 @@ +@title Sorting the NetNewsWire timeline + +# Sorting the NetNewsWire timeline + +The NetNewsWire timeline is the list of articles shown in the centre pane. + +« Screenshot » + +By default, this list displays newer articles at the top. + +You can change the sorting for the timeline in the View menu: **View → Sort by → Newest Article on Top** or **Oldest Article on Top**. + +This setting applies to all feeds and can be changed anytime. \ No newline at end of file diff --git a/Technotes/HelpBook/5.0/en/updating.markdown b/Technotes/HelpBook/5.0/en/updating.markdown index 3245ae88d..3d1c4c4a6 100644 --- a/Technotes/HelpBook/5.0/en/updating.markdown +++ b/Technotes/HelpBook/5.0/en/updating.markdown @@ -6,13 +6,15 @@ NetNewsWire can check for and install updated versions of itself. This can be do -## Automatic checks for updates +Automatic checks for updates +---------------------------- When you first launch NetNewsWire you’ll be asked whether it should periodically check for updates. You will be notified of any new updates and can choose to update when you’re ready. -## Manually checking for updates +Manually checking for updates +----------------------------- You may have declined automatic checks for updates or just [read about a great new update](netnewswire-news.html) and want to download it now. You can always check for updates manually by selecting **NetNewsWire → Check for Updates…** from the menu bar. @@ -20,6 +22,7 @@ If a new update is found, NetNewsWire can download and install it for you. -## Privacy +Privacy +------- When checking for updates, whether automatically or manually, no personally-identifiable information is collected – not even an anonymous system profile. For more information about your privacy and NetNewsWire, please see the NetNewsWire Privacy Policy. \ No newline at end of file diff --git a/Technotes/HelpBook/5.0/en/userdata-location.markdown b/Technotes/HelpBook/5.0/en/userdata-location.markdown index ff86593fd..138c95a72 100644 --- a/Technotes/HelpBook/5.0/en/userdata-location.markdown +++ b/Technotes/HelpBook/5.0/en/userdata-location.markdown @@ -6,7 +6,8 @@ NetNewsWire remembers your feeds and article read status, as well as your accoun -## Preferences file +Preferences file +---------------- Your NetNewsWire preferences file is called `com.ranchero.NetNewsWire-Evergreen.plist`. It’s stored in your account’s Preferences folder, which can be found in the Finder by navigating to: @@ -19,7 +20,8 @@ The contents in the preferences `plist` file are cached by macOS. If you make an -## Feeds and accounts data +Feeds and accounts data +----------------------- Information about your subscribed feeds, article read status and accounts (On my Mac and Feedbin) are stored in your account’s Application Support folder. This can be found in the Finder by navigating to: @@ -32,9 +34,12 @@ If you just want to export your list of subscribed feeds, NetNewsWire [can expor -## Resetting or removing NetNewsWire +Resetting or removing NetNewsWire +--------------------------------- -If you are encountering problems while using NetNewsWire, by removing the files and folders above you can set up NetNewsWire again from scratch. You may also want to delete these files if you want to completely remove NetNewsWire from your Mac. +If you are running into problems while using NetNewsWire, you may want to reset your settings. By removing the files and folders above you can start over again from scratch. + +You may also want to delete these files if you want to completely remove NetNewsWire from your Mac. ### Can’t find the Library folder? diff --git a/Technotes/HelpBook/5.0/en/what-is-rss.markdown b/Technotes/HelpBook/5.0/en/what-is-rss.markdown index a611fad9c..4dba0366c 100644 --- a/Technotes/HelpBook/5.0/en/what-is-rss.markdown +++ b/Technotes/HelpBook/5.0/en/what-is-rss.markdown @@ -12,7 +12,7 @@ Like this imaginary squished-down web page: The good part is the part in the middle — that’s the part with the news. That’s the part that you read. That’s the part you’re interested in. -

And that’s what RSS is — it’s just that part, minus the rest of the stuff. +And that’s what RSS is — it’s just that part, minus the rest of the stuff. #### Details From 40369eaca0a2c78e439330db4d0a7f02a310af9d Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 10 Aug 2019 14:26:51 -0700 Subject: [PATCH 44/44] Change the URL of the Help book to include a /mac/ directory, so we can have separate help books for Mac and iOS. --- Mac/AppDelegate.swift | 2 +- Technotes/HelpBook/5.0/en/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Mac/AppDelegate.swift b/Mac/AppDelegate.swift index f78cae77e..3c1dd932c 100644 --- a/Mac/AppDelegate.swift +++ b/Mac/AppDelegate.swift @@ -444,7 +444,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, @IBAction func showHelp(_ sender: Any?) { - Browser.open("https://ranchero.com/netnewswire/help/5.0/en/", inBackground: false) + Browser.open("https://ranchero.com/netnewswire/help/mac/5.0/en/", inBackground: false) } @IBAction func donateToAppCampForGirls(_ sender: Any?) { diff --git a/Technotes/HelpBook/5.0/en/README.md b/Technotes/HelpBook/5.0/en/README.md index b31aced68..25c2297c8 100644 --- a/Technotes/HelpBook/5.0/en/README.md +++ b/Technotes/HelpBook/5.0/en/README.md @@ -2,7 +2,7 @@ The Help book goes here. Text files go at the top level, and images go in the images directory. -Text files are markdown files. A script ([wildcat](https://github.com/brentsimmons/wildcat)) will turn this into a web site that will appear at [https://ranchero.com/netnewswire/help/5.0/en/](https://ranchero.com/netnewswire/help/5.0/en/). (The /en/ directory because we hope to have localized versions.) +Text files are markdown files. A script ([wildcat](https://github.com/brentsimmons/wildcat)) will turn this into a web site that will appear at [https://ranchero.com/netnewswire/help/mac/5.0/en/](https://ranchero.com/netnewswire/help/mac/5.0/en/). (The /en/ directory because we hope to have localized versions.) If you’d like to write or edit the Help book, or help with screenshots, please bring it up on the [NetNewsWire Slack](https://netnewswire.slack.com/join/shared_invite/enQtNjM4MDA1MjQzMDkzLTNlNjBhOWVhYzdhYjA4ZWFhMzQ1MTUxYjU0NTE5ZGY0YzYwZWJhNjYwNTNmNTg2NjIwYWY4YzhlYzk5NmU3ZTc) group. We’ll coordinate there.