diff --git a/Mac/AppDelegate.swift b/Mac/AppDelegate.swift index e38ee7bed..73519e152 100644 --- a/Mac/AppDelegate.swift +++ b/Mac/AppDelegate.swift @@ -57,7 +57,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, private var addFeedController: AddFeedController? private var addFolderWindowController: AddFolderWindowController? private var importOPMLController: ImportOPMLWindowController? - private var importNNW3Controller: ImportNNW3WindowController? private var exportOPMLController: ExportOPMLWindowController? private var keyboardShortcutsWindowController: WebViewWindowController? private var inspectorWindowController: InspectorWindowController? @@ -127,8 +126,13 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, logDebugMessage("Is first run.") } let localAccount = AccountManager.shared.defaultAccount - NNW3FeedsImporter.importIfNeeded(isFirstRun, account: localAccount) - DefaultFeedsImporter.importIfNeeded(isFirstRun, account: localAccount) + + if isFirstRun && !AccountManager.shared.anyAccountHasAtLeastOneFeed() { + // Import feeds. Either old NNW 3 feeds or the default feeds. + if !NNW3ImportController.importSubscriptionsIfFileExists(account: localAccount) { + DefaultFeedsImporter.importDefaultFeeds(account: localAccount) + } + } let tempDirectory = NSTemporaryDirectory() let bundleIdentifier = (Bundle.main.infoDictionary!["CFBundleIdentifier"]! as! String) @@ -425,9 +429,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, if mainWindowController!.isDisplayingSheet { return } - - importNNW3Controller = ImportNNW3WindowController() - importNNW3Controller?.runSheetOnWindow(mainWindowController!.window!) + NNW3ImportController.askUserToImportNNW3Subscriptions(window: mainWindowController!.window!) } @IBAction func exportOPML(_ sender: Any?) { diff --git a/Mac/Base.lproj/Main.storyboard b/Mac/Base.lproj/Main.storyboard index b2769eccb..e7944c841 100644 --- a/Mac/Base.lproj/Main.storyboard +++ b/Mac/Base.lproj/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -92,7 +92,7 @@ - + diff --git a/Mac/MainWindow/NNW3/ImportNNW3Sheet.xib b/Mac/MainWindow/NNW3/ImportNNW3Sheet.xib deleted file mode 100644 index 522ead006..000000000 --- a/Mac/MainWindow/NNW3/ImportNNW3Sheet.xib +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Mac/MainWindow/NNW3/ImportNNW3WindowController.swift b/Mac/MainWindow/NNW3/ImportNNW3WindowController.swift deleted file mode 100644 index 3488ecb03..000000000 --- a/Mac/MainWindow/NNW3/ImportNNW3WindowController.swift +++ /dev/null @@ -1,110 +0,0 @@ -// -// ImportNNW3WindowController.swift -// NetNewsWire -// -// Created by Maurice Parker on 10/14/19. -// Copyright © 2019 Ranchero Software. All rights reserved. -// - -import AppKit -import Account - -class ImportNNW3WindowController: NSWindowController { - - @IBOutlet weak var accountPopUpButton: NSPopUpButton! - private weak var hostWindow: NSWindow? - - convenience init() { - self.init(windowNibName: NSNib.Name("ImportNNW3Sheet")) - } - - override func windowDidLoad() { - accountPopUpButton.removeAllItems() - - let menu = NSMenu() - accountPopUpButton.menu = menu - - for oneAccount in AccountManager.shared.sortedActiveAccounts { - - let oneMenuItem = NSMenuItem() - oneMenuItem.title = oneAccount.nameForDisplay - oneMenuItem.representedObject = oneAccount - menu.addItem(oneMenuItem) - - if oneAccount.accountID == AppDefaults.importOPMLAccountID { - accountPopUpButton.select(oneMenuItem) - } - - } - } - - // MARK: API - - func runSheetOnWindow(_ hostWindow: NSWindow) { - - self.hostWindow = hostWindow - - if AccountManager.shared.activeAccounts.count == 1 { - let account = AccountManager.shared.activeAccounts.first! - importNNW3(account: account) - } else { - hostWindow.beginSheet(window!) - } - - } - - // MARK: Actions - - @IBAction func cancel(_ sender: Any) { - hostWindow!.endSheet(window!, returnCode: NSApplication.ModalResponse.cancel) - } - - @IBAction func importNNW3(_ sender: Any) { - - guard let menuItem = accountPopUpButton.selectedItem else { - return - } - - let account = menuItem.representedObject as! Account - AppDefaults.importOPMLAccountID = account.accountID - hostWindow!.endSheet(window!, returnCode: NSApplication.ModalResponse.OK) - importNNW3(account: account) - - } - - func importNNW3(account: Account) { - - let panel = NSOpenPanel() - panel.canDownloadUbiquitousContents = true - panel.canResolveUbiquitousConflicts = true - panel.canChooseFiles = true - panel.allowsMultipleSelection = false - panel.canChooseDirectories = false - panel.resolvesAliases = true - panel.directoryURL = URL(fileURLWithPath: NNW3PlistConverter.defaultFilePath) - panel.allowedFileTypes = ["plist"] - panel.allowsOtherFileTypes = false - - panel.beginSheetModal(for: hostWindow!) { modalResult in - if modalResult == NSApplication.ModalResponse.OK, let url = panel.url { - - guard let opmlURL = NNW3PlistConverter.convertToOPML(url: url) else { - return - } - - account.importOPML(opmlURL) { result in - try? FileManager.default.removeItem(at: opmlURL) - switch result { - case .success: - break - case .failure(let error): - NSApplication.shared.presentError(error) - } - } - - } - } - - } - -} diff --git a/Mac/MainWindow/NNW3/NNW3Document.swift b/Mac/MainWindow/NNW3/NNW3Document.swift index d5738631f..536f5500d 100644 --- a/Mac/MainWindow/NNW3/NNW3Document.swift +++ b/Mac/MainWindow/NNW3/NNW3Document.swift @@ -7,47 +7,138 @@ // import Foundation +import RSCore -class NNW3Document: NNW3Entry { - - init(plist: [[String: Any]]) { - super.init(title: "NNW3") - - for child in plist { - if child["isContainer"] as? Bool ?? false { - entries.append(NNW3Entry(plist: child, parent: self)) - } else { - entries.append(NNW3Feed(plist: child, parent: self)) - } - } - +struct NNW3Document { + + private let children: [OPMLRepresentable]? + + private init(plist: [[String: AnyObject]]) { + self.children = NNW3Folder.itemsWithPlist(plist: plist) } - - override func makeXML(indentLevel: Int) -> String { - + + init?(subscriptionsPlistURL url: URL) { + guard let data = try? Data(contentsOf: url) else { + return nil + } + guard let plist = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [[String: AnyObject]] else { + return nil + } + self.init(plist: plist) + } +} + +// MARK: OPMLRepresentable + +extension NNW3Document: OPMLRepresentable { + + func OPMLString(indentLevel: Int, strictConformance: Bool) -> String { var s = """ - \(title ?? "") + NetNewsWire 3 Subscriptions - + """ - - for entry in entries { - s += entry.makeXML(indentLevel: indentLevel + 1) + + if let children = children { + for child in children { + s += child.OPMLString(indentLevel: indentLevel + 1, strictConformance: true) + } } s += """ - - - """ - + + + """ + return s - } - } + +// MARK: - NNW3Folder + +private struct NNW3Folder { + + private let title: String? + private let children: [OPMLRepresentable]? + + init(plist: [String: Any]) { + self.title = plist["name"] as? String + guard let childrenArray = plist["childrenArray"] as? [[String: Any]] else { + self.children = nil + return + } + self.children = NNW3Folder.itemsWithPlist(plist: childrenArray) + } + + static func itemsWithPlist(plist: [[String: Any]]) -> [OPMLRepresentable]? { + // Also used by NNW3Document. + var items = [OPMLRepresentable]() + for child in plist { + if child["isContainer"] as? Bool ?? false { + items.append(NNW3Folder(plist: child)) + } else { + items.append(NNW3Feed(plist: child)) + } + } + return items.isEmpty ? nil : items + } +} + +// MARK: OPMLRepresentable + +extension NNW3Folder: OPMLRepresentable { + + func OPMLString(indentLevel: Int, strictConformance: Bool) -> String { + let t = title?.rs_stringByEscapingSpecialXMLCharacters() ?? "" + guard let children = children else { + // Empty folder. + return "\n".rs_string(byPrependingNumberOfTabs: indentLevel) + } + + var s = "\n".rs_string(byPrependingNumberOfTabs: indentLevel) + for child in children { + s += child.OPMLString(indentLevel: indentLevel + 1, strictConformance: true) + } + + s += "\n".rs_string(byPrependingNumberOfTabs: indentLevel) + return s + } +} + +// MARK: - NNW3Feed + +private struct NNW3Feed { + + private let title: String? + private let homePageURL: String? + private let feedURL: String? + + init(plist: [String: Any]) { + self.title = plist["name"] as? String + self.homePageURL = plist["home"] as? String + self.feedURL = plist["rss"] as? String + } +} + +// MARK: OPMLRepresentable + +extension NNW3Feed: OPMLRepresentable { + + func OPMLString(indentLevel: Int, strictConformance: Bool) -> String { + let t = title?.rs_stringByEscapingSpecialXMLCharacters() ?? "" + let p = homePageURL?.rs_stringByEscapingSpecialXMLCharacters() ?? "" + let f = feedURL?.rs_stringByEscapingSpecialXMLCharacters() ?? "" + + var s = "\n" + s = s.rs_string(byPrependingNumberOfTabs: indentLevel) + + return s + } +} + diff --git a/Mac/MainWindow/NNW3/NNW3Entry.swift b/Mac/MainWindow/NNW3/NNW3Entry.swift deleted file mode 100644 index 4cc19b911..000000000 --- a/Mac/MainWindow/NNW3/NNW3Entry.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// NNW3Entry.swift -// NetNewsWire -// -// Created by Maurice Parker on 10/14/19. -// Copyright © 2019 Ranchero Software. All rights reserved. -// - -import Foundation -import RSCore - -class NNW3Entry { - - var title: String? - var entries = [NNW3Entry]() - - weak var parent: NNW3Entry? - - var isFolder: Bool { - return type(of: self) == NNW3Entry.self - } - - init(title: String?, parent: NNW3Entry? = nil) { - self.title = title - self.parent = parent - } - - convenience init(plist: [String: Any], parent: NNW3Entry? = nil) { - let title = plist["name"] as? String - self.init(title: title, parent: parent) - - guard let childrenArray = plist["childrenArray"] as? [[String: AnyObject]] else { - return - } - - for child in childrenArray { - if child["isContainer"] as? Bool ?? false { - entries.append(NNW3Entry(plist: child, parent: self)) - } else { - entries.append(NNW3Feed(plist: child, parent: self)) - } - } - - } - - func makeXML(indentLevel: Int) -> String { - - let t = title?.rs_stringByEscapingSpecialXMLCharacters() ?? "" - var s = "\n".rs_string(byPrependingNumberOfTabs: indentLevel) - - for entry in entries { - s += entry.makeXML(indentLevel: indentLevel + 1) - } - - s += "\n".rs_string(byPrependingNumberOfTabs: indentLevel) - - return s - - } - -} diff --git a/Mac/MainWindow/NNW3/NNW3Feed.swift b/Mac/MainWindow/NNW3/NNW3Feed.swift deleted file mode 100644 index f6d54a480..000000000 --- a/Mac/MainWindow/NNW3/NNW3Feed.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// NNW3Feed.swift -// NetNewsWire -// -// Created by Maurice Parker on 10/14/19. -// Copyright © 2019 Ranchero Software. All rights reserved. -// - -import Foundation -import RSCore - -class NNW3Feed: NNW3Entry { - - var pageURL: String? - var feedURL: String? - - init(feedURL: String) { - super.init(title: nil) - self.feedURL = feedURL - } - - init(title: String?, pageURL: String?, feedURL: String?, parent: NNW3Entry? = nil) { - super.init(title: title, parent: parent) - self.pageURL = pageURL - self.feedURL = feedURL - } - - convenience init(plist: [String: Any], parent: NNW3Entry? = nil) { - let title = plist["name"] as? String - let pageURL = plist["home"] as? String - let feedURL = plist["rss"] as? String - self.init(title: title, pageURL: pageURL, feedURL: feedURL, parent: parent) - } - - override func makeXML(indentLevel: Int) -> String { - - let t = title?.rs_stringByEscapingSpecialXMLCharacters() ?? "" - let p = pageURL?.rs_stringByEscapingSpecialXMLCharacters() ?? "" - let f = feedURL?.rs_stringByEscapingSpecialXMLCharacters() ?? "" - - var s = "\n" - s = s.rs_string(byPrependingNumberOfTabs: indentLevel) - - return s - - } - -} diff --git a/Mac/MainWindow/NNW3/NNW3FeedsImporter.swift b/Mac/MainWindow/NNW3/NNW3FeedsImporter.swift deleted file mode 100644 index baaa14eba..000000000 --- a/Mac/MainWindow/NNW3/NNW3FeedsImporter.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// NNW3FeedsImporter.swift -// NetNewsWire -// -// Created by Maurice Parker on 10/14/19. -// Copyright © 2019 Ranchero Software. All rights reserved. -// - -import Foundation -import Account -import RSCore - -struct NNW3FeedsImporter { - - static func importIfNeeded(_ isFirstRun: Bool, account: Account) { - guard shouldImportDefaultFeeds(isFirstRun) else { - return - } - - if !FileManager.default.fileExists(atPath: NNW3PlistConverter.defaultFilePath) { - return - } - - appDelegate.logDebugMessage("Importing NNW3 feeds.") - - let url = URL(fileURLWithPath: NNW3PlistConverter.defaultFilePath) - guard let opmlURL = NNW3PlistConverter.convertToOPML(url: url) else { - return - } - - account.importOPML(opmlURL) { result in - try? FileManager.default.removeItem(at: opmlURL) - switch result { - case .success: - appDelegate.logDebugMessage("Importing NNW3 feeds succeeded.") - case .failure(let error): - appDelegate.logDebugMessage("Importing NNW3 feeds failed. \(error.localizedDescription)") - } - } - - } - - private static func shouldImportDefaultFeeds(_ isFirstRun: Bool) -> Bool { - if !isFirstRun || AccountManager.shared.anyAccountHasAtLeastOneFeed() { - return false - } - return true - } - -} diff --git a/Mac/MainWindow/NNW3/NNW3ImportController.swift b/Mac/MainWindow/NNW3/NNW3ImportController.swift new file mode 100644 index 000000000..f3103e1e1 --- /dev/null +++ b/Mac/MainWindow/NNW3/NNW3ImportController.swift @@ -0,0 +1,108 @@ +// +// NNW3ImportController.swift +// NetNewsWire +// +// Created by Brent Simmons on 10/14/19. +// Copyright © 2019 Ranchero Software. All rights reserved. +// + +import AppKit +import Account + +struct NNW3ImportController { + + /// Import NNW3 subscriptions if they exist. + /// Return true if Subscriptions.plist was found and subscriptions were imported. + static func importSubscriptionsIfFileExists(account: Account) -> Bool { + guard let subscriptionsPlistURL = defaultFileURL else { + return false + } + if !FileManager.default.fileExists(atPath: subscriptionsPlistURL.path) { + return false + } + NNW3ImportController.importSubscriptionsPlist(subscriptionsPlistURL, into: account) + return true + } + + /// Run an NSOpenPanel and import subscriptions (if the user chooses to). + static func askUserToImportNNW3Subscriptions(window: NSWindow) { + chooseFile(window) + } +} + +private extension NNW3ImportController { + + /// URL to ~/Library/Application Support/NetNewsWire/Subscriptions.plist + static var defaultFileURL: URL? { + guard let applicationSupportURL = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first else { + return nil + } + let folderURL = applicationSupportURL.appendingPathComponent("NetNewsWire", isDirectory: true) + return folderURL.appendingPathComponent("Subscriptions.plist", isDirectory: false) + } + + /// Import Subscriptions.plist file. Convert to OPML and then import into specified Account. + static func importSubscriptionsPlist(_ subscriptionsPlistURL: URL, into account: Account) { + guard let opmlURL = convertToOPMLFile(subscriptionsPlistURL: subscriptionsPlistURL) else { + return + } + account.importOPML(opmlURL) { result in + try? FileManager.default.removeItem(at: opmlURL) + switch result { + case .success: + break + case .failure(let error): + NSApplication.shared.presentError(error) + } + } + } + + /// Run the NSOpenPanel. On success, import subscriptions to the selected account. + static func chooseFile(_ window: NSWindow) { + let accessoryViewController = NNW3OpenPanelAccessoryViewController() + + let panel = NSOpenPanel() + panel.canDownloadUbiquitousContents = true + panel.canResolveUbiquitousConflicts = true + panel.canChooseFiles = true + panel.allowsMultipleSelection = false + panel.canChooseDirectories = false + panel.resolvesAliases = true + panel.directoryURL = NNW3ImportController.defaultFileURL + panel.allowedFileTypes = ["plist"] + panel.allowsOtherFileTypes = false + panel.accessoryView = accessoryViewController.view + panel.isAccessoryViewDisclosed = true + panel.title = NSLocalizedString("Choose a Subscriptions.plist file:", comment: "NNW3 Import") + + panel.beginSheetModal(for: window) { modalResult in + guard modalResult == .OK, let subscriptionsPlistURL = panel.url else { + return + } + guard let account = accessoryViewController.selectedAccount else { + return + } + AppDefaults.importOPMLAccountID = account.accountID + + NNW3ImportController.importSubscriptionsPlist(subscriptionsPlistURL, into: account) + } + } + + /// Convert Subscriptions.plist on disk to a temporary OPML file. + static func convertToOPMLFile(subscriptionsPlistURL url: URL) -> URL? { + guard let document = NNW3Document(subscriptionsPlistURL: url) else { + return nil + } + let opml = document.OPMLString(indentLevel: 0, strictConformance: true) + + let opmlURL = FileManager.default.temporaryDirectory.appendingPathComponent("NNW3.opml") + do { + try opml.write(to: opmlURL, atomically: true, encoding: .utf8) + } catch let error as NSError { + NSApplication.shared.presentError(error) + return nil + } + + return opmlURL + } +} diff --git a/Mac/MainWindow/NNW3/NNW3OpenPanelAccessoryView.xib b/Mac/MainWindow/NNW3/NNW3OpenPanelAccessoryView.xib new file mode 100644 index 000000000..bfed3618b --- /dev/null +++ b/Mac/MainWindow/NNW3/NNW3OpenPanelAccessoryView.xib @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Choose a NetNewsWire 3 “Subscriptions.plist” file. + +Then choose the account to receive your imported subscriptions. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mac/MainWindow/NNW3/NNW3OpenPanelAccessoryViewController.swift b/Mac/MainWindow/NNW3/NNW3OpenPanelAccessoryViewController.swift new file mode 100644 index 000000000..a7a05fc8f --- /dev/null +++ b/Mac/MainWindow/NNW3/NNW3OpenPanelAccessoryViewController.swift @@ -0,0 +1,47 @@ +// +// NNW3OpenPanelAccessoryViewController.swift +// NetNewsWire +// +// Created by Brent Simmons on 10/14/19. +// Copyright © 2019 Ranchero Software. All rights reserved. +// + +import AppKit +import Account + +final class NNW3OpenPanelAccessoryViewController: NSViewController { + + @IBOutlet weak var accountPopUpButton: NSPopUpButton! + + var selectedAccount: Account? { + accountPopUpButton.selectedItem?.representedObject as? Account + } + + init() { + super.init(nibName: "NNW3OpenPanelAccessoryView", bundle: nil) + } + + // MARK: - NSViewController + + required init?(coder: NSCoder) { + preconditionFailure("NNW3OpenPanelAccessoryViewController.init(coder) not implemented by design.") + } + + override func viewDidLoad() { + accountPopUpButton.removeAllItems() + + let menu = NSMenu() + accountPopUpButton.menu = menu + + for account in AccountManager.shared.sortedActiveAccounts { + let menuItem = NSMenuItem() + menuItem.title = account.nameForDisplay + menuItem.representedObject = account + menu.addItem(menuItem) + + if account.accountID == AppDefaults.importOPMLAccountID { + accountPopUpButton.select(menuItem) + } + } + } +} diff --git a/Mac/MainWindow/NNW3/NNW3PlistConverter.swift b/Mac/MainWindow/NNW3/NNW3PlistConverter.swift deleted file mode 100644 index 310a2d93d..000000000 --- a/Mac/MainWindow/NNW3/NNW3PlistConverter.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// NNW3Importer.swift -// NetNewsWire -// -// Created by Maurice Parker on 10/14/19. -// Copyright © 2019 Ranchero Software. All rights reserved. -// - -import Foundation - -class NNW3PlistConverter { - - static var defaultFilePath: String { - return ("~/Library/Application Support/NetNewsWire/Subscriptions.plist" as NSString).expandingTildeInPath - } - - static func convertToOPML(url: URL) -> URL? { - guard let data = try? Data(contentsOf: url) else { - return nil - } - - guard let nnw3plist = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [[String: AnyObject]] else { - return nil - } - - let opmlURL = FileManager.default.temporaryDirectory.appendingPathComponent("NNW3.opml") - let doc = NNW3Document(plist: nnw3plist) - let opml = doc.makeXML(indentLevel: 0) - do { - try opml.write(to: opmlURL, atomically: true, encoding: .utf8) - } catch let error as NSError { - NSApplication.shared.presentError(error) - return nil - } - - return opmlURL - } - -} diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 0f20efa2e..c24b1e5d4 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -35,8 +35,6 @@ 51554C25228B71910055115A /* SyncDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 51554C01228B6EB50055115A /* SyncDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 51554C30228B71A10055115A /* SyncDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51554C01228B6EB50055115A /* SyncDatabase.framework */; }; 51554C31228B71A10055115A /* SyncDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 51554C01228B6EB50055115A /* SyncDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 516CAC4C235521070038D354 /* ImportNNW3Sheet.xib in Resources */ = {isa = PBXBuildFile; fileRef = 516CAC42235521070038D354 /* ImportNNW3Sheet.xib */; }; - 516CAC4D235521070038D354 /* ImportNNW3WindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516CAC4B235521070038D354 /* ImportNNW3WindowController.swift */; }; 5183CCD0226E1E880010922C /* NonIntrinsicLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */; }; 5183CCDA226E31A50010922C /* NonIntrinsicImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */; }; 5183CCDD226F1F5C0010922C /* NavigationProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCDC226F1F5C0010922C /* NavigationProgressView.swift */; }; @@ -48,11 +46,7 @@ 5183CCE9226F68D90010922C /* AccountRefreshTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCE7226F68D90010922C /* AccountRefreshTimer.swift */; }; 5183CCED22711DCE0010922C /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5183CCEC22711DCE0010922C /* Settings.storyboard */; }; 5183CCEF227125970010922C /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCEE227125970010922C /* SettingsViewController.swift */; }; - 5186515223552E610078E021 /* NNW3PlistConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5186515123552E610078E021 /* NNW3PlistConverter.swift */; }; - 5186515E23552F040078E021 /* NNW3Feed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5186515B23552F040078E021 /* NNW3Feed.swift */; }; 5186515F23552F040078E021 /* NNW3Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5186515C23552F040078E021 /* NNW3Document.swift */; }; - 5186516023552F040078E021 /* NNW3Entry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5186515D23552F040078E021 /* NNW3Entry.swift */; }; - 51865167235556240078E021 /* NNW3FeedsImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51865166235556240078E021 /* NNW3FeedsImporter.swift */; }; 519B8D332143397200FA689C /* SharingServiceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519B8D322143397200FA689C /* SharingServiceDelegate.swift */; }; 51C451A9226377C200C03939 /* ArticlesDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; }; 51C451AA226377C200C03939 /* ArticlesDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -185,8 +179,11 @@ 844B5B651FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 844B5B641FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist */; }; 844B5B671FEA18E300C7C76A /* MainWIndowKeyboardHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844B5B661FEA18E300C7C76A /* MainWIndowKeyboardHandler.swift */; }; 844B5B691FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 844B5B681FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist */; }; + 844BA21923557D3C00ECF23E /* NNW3ImportController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BA21823557D3C00ECF23E /* NNW3ImportController.swift */; }; 845213231FCA5B11003B6E93 /* ImageDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845213221FCA5B10003B6E93 /* ImageDownloader.swift */; }; 845479881FEB77C000AD8B59 /* TimelineKeyboardShortcuts.plist in Resources */ = {isa = PBXBuildFile; fileRef = 845479871FEB77C000AD8B59 /* TimelineKeyboardShortcuts.plist */; }; + 8459D0F92355794C0050076F /* NNW3OpenPanelAccessoryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8459D0F82355794C0050076F /* NNW3OpenPanelAccessoryView.xib */; }; + 8459D10323557A460050076F /* NNW3OpenPanelAccessoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8459D10223557A460050076F /* NNW3OpenPanelAccessoryViewController.swift */; }; 845A29091FC74B8E007B49E3 /* SingleFaviconDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845A29081FC74B8E007B49E3 /* SingleFaviconDownloader.swift */; }; 845A29221FC9251E007B49E3 /* SidebarCellLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845A29211FC9251E007B49E3 /* SidebarCellLayout.swift */; }; 845A29241FC9255E007B49E3 /* SidebarCellAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845A29231FC9255E007B49E3 /* SidebarCellAppearance.swift */; }; @@ -697,8 +694,6 @@ 515436872291D75D005E1CDF /* AddLocalAccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddLocalAccountViewController.swift; sourceTree = ""; }; 515436892291FED9005E1CDF /* FeedbinAccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinAccountViewController.swift; sourceTree = ""; }; 51554BFC228B6EB50055115A /* SyncDatabase.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SyncDatabase.xcodeproj; path = Frameworks/SyncDatabase/SyncDatabase.xcodeproj; sourceTree = SOURCE_ROOT; }; - 516CAC42235521070038D354 /* ImportNNW3Sheet.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ImportNNW3Sheet.xib; sourceTree = ""; }; - 516CAC4B235521070038D354 /* ImportNNW3WindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportNNW3WindowController.swift; sourceTree = ""; }; 5183CCCF226E1E880010922C /* NonIntrinsicLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonIntrinsicLabel.swift; sourceTree = ""; }; 5183CCD9226E31A50010922C /* NonIntrinsicImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonIntrinsicImageView.swift; sourceTree = ""; }; 5183CCDC226F1F5C0010922C /* NavigationProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationProgressView.swift; sourceTree = ""; }; @@ -708,11 +703,7 @@ 5183CCE7226F68D90010922C /* AccountRefreshTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountRefreshTimer.swift; sourceTree = ""; }; 5183CCEC22711DCE0010922C /* Settings.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Settings.storyboard; sourceTree = ""; }; 5183CCEE227125970010922C /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; - 5186515123552E610078E021 /* NNW3PlistConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NNW3PlistConverter.swift; sourceTree = ""; }; - 5186515B23552F040078E021 /* NNW3Feed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NNW3Feed.swift; sourceTree = ""; }; 5186515C23552F040078E021 /* NNW3Document.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NNW3Document.swift; sourceTree = ""; }; - 5186515D23552F040078E021 /* NNW3Entry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NNW3Entry.swift; sourceTree = ""; }; - 51865166235556240078E021 /* NNW3FeedsImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NNW3FeedsImporter.swift; sourceTree = ""; }; 519B8D322143397200FA689C /* SharingServiceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingServiceDelegate.swift; sourceTree = ""; }; 51C4524E226506F400C03939 /* UIStoryboard-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIStoryboard-Extensions.swift"; sourceTree = ""; }; 51C45250226506F400C03939 /* String-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String-Extensions.swift"; sourceTree = ""; }; @@ -801,8 +792,11 @@ 844B5B641FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = GlobalKeyboardShortcuts.plist; sourceTree = ""; }; 844B5B661FEA18E300C7C76A /* MainWIndowKeyboardHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWIndowKeyboardHandler.swift; sourceTree = ""; }; 844B5B681FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = SidebarKeyboardShortcuts.plist; sourceTree = ""; }; + 844BA21823557D3C00ECF23E /* NNW3ImportController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NNW3ImportController.swift; sourceTree = ""; }; 845213221FCA5B10003B6E93 /* ImageDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageDownloader.swift; sourceTree = ""; }; 845479871FEB77C000AD8B59 /* TimelineKeyboardShortcuts.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = TimelineKeyboardShortcuts.plist; sourceTree = ""; }; + 8459D0F82355794C0050076F /* NNW3OpenPanelAccessoryView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NNW3OpenPanelAccessoryView.xib; sourceTree = ""; }; + 8459D10223557A460050076F /* NNW3OpenPanelAccessoryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NNW3OpenPanelAccessoryViewController.swift; sourceTree = ""; }; 845A29081FC74B8E007B49E3 /* SingleFaviconDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleFaviconDownloader.swift; sourceTree = ""; }; 845A29211FC9251E007B49E3 /* SidebarCellLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarCellLayout.swift; sourceTree = ""; }; 845A29231FC9255E007B49E3 /* SidebarCellAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarCellAppearance.swift; sourceTree = ""; }; @@ -1058,13 +1052,10 @@ 516CAC53235529180038D354 /* NNW3 */ = { isa = PBXGroup; children = ( - 516CAC42235521070038D354 /* ImportNNW3Sheet.xib */, - 516CAC4B235521070038D354 /* ImportNNW3WindowController.swift */, - 51865166235556240078E021 /* NNW3FeedsImporter.swift */, - 5186515123552E610078E021 /* NNW3PlistConverter.swift */, + 844BA21823557D3C00ECF23E /* NNW3ImportController.swift */, 5186515C23552F040078E021 /* NNW3Document.swift */, - 5186515D23552F040078E021 /* NNW3Entry.swift */, - 5186515B23552F040078E021 /* NNW3Feed.swift */, + 8459D0F82355794C0050076F /* NNW3OpenPanelAccessoryView.xib */, + 8459D10223557A460050076F /* NNW3OpenPanelAccessoryViewController.swift */, ); path = NNW3; sourceTree = ""; @@ -1998,12 +1989,12 @@ ORGANIZATIONNAME = "Ranchero Software"; TargetAttributes = { 6581C73220CED60000F4AD34 = { - DevelopmentTeam = SHJK2V3AJG; - ProvisioningStyle = Automatic; + DevelopmentTeam = M8L2WTLA8W; + ProvisioningStyle = Manual; }; 840D617B2029031C009BC708 = { CreatedOnToolsVersion = 9.3; - DevelopmentTeam = SHJK2V3AJG; + DevelopmentTeam = M8L2WTLA8W; ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.BackgroundModes = { @@ -2019,8 +2010,8 @@ }; 849C645F1ED37A5D003D8FC0 = { CreatedOnToolsVersion = 8.2.1; - DevelopmentTeam = SHJK2V3AJG; - ProvisioningStyle = Automatic; + DevelopmentTeam = M8L2WTLA8W; + ProvisioningStyle = Manual; SystemCapabilities = { com.apple.HardenedRuntime = { enabled = 1; @@ -2029,7 +2020,7 @@ }; 849C64701ED37A5D003D8FC0 = { CreatedOnToolsVersion = 8.2.1; - DevelopmentTeam = SHJK2V3AJG; + DevelopmentTeam = 9C84TZ7Q6Z; ProvisioningStyle = Automatic; TestTargetID = 849C645F1ED37A5D003D8FC0; }; @@ -2284,7 +2275,6 @@ files = ( 844B5B651FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist in Resources */, 5127B23A222B4849006D641D /* DetailKeyboardShortcuts.plist in Resources */, - 516CAC4C235521070038D354 /* ImportNNW3Sheet.xib in Resources */, 845479881FEB77C000AD8B59 /* TimelineKeyboardShortcuts.plist in Resources */, 848362FF2262A30E00DA1D35 /* template.html in Resources */, 848363082262A3DD00DA1D35 /* Main.storyboard in Resources */, @@ -2296,6 +2286,7 @@ 5144EA3B227A379E00D19003 /* ImportOPMLSheet.xib in Resources */, 844B5B691FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist in Resources */, 84A3EE5F223B667F00557320 /* DefaultFeeds.opml in Resources */, + 8459D0F92355794C0050076F /* NNW3OpenPanelAccessoryView.xib in Resources */, 84C9FC8222629E4800D921D6 /* Preferences.storyboard in Resources */, 5144EA3D227A37AF00D19003 /* ExportOPMLSheet.xib in Resources */, 849C64681ED37A5D003D8FC0 /* Assets.xcassets in Resources */, @@ -2477,6 +2468,7 @@ 841ABA4E20145E7300980E11 /* NothingInspectorViewController.swift in Sources */, 842E45CE1ED8C308000A8B52 /* AppNotifications.swift in Sources */, 844B5B5B1FEA00FB00C7C76A /* TimelineKeyboardDelegate.swift in Sources */, + 844BA21923557D3C00ECF23E /* NNW3ImportController.swift in Sources */, 842E45DD1ED8C54B000A8B52 /* Browser.swift in Sources */, 84216D0322128B9D0049B9B9 /* DetailWebViewController.swift in Sources */, 8444C8F21FED81840051386C /* OPMLExporter.swift in Sources */, @@ -2492,11 +2484,9 @@ D5A2678C20130ECF00A8D3C0 /* Author+Scriptability.swift in Sources */, 84F2D5371FC22FCC00998D64 /* PseudoFeed.swift in Sources */, 51EF0F902279C9500050506E /* AccountsAddViewController.swift in Sources */, - 5186515223552E610078E021 /* NNW3PlistConverter.swift in Sources */, D57BE6E0204CD35F00D11AAC /* NSScriptCommand+NetNewsWire.swift in Sources */, D553738B20186C20006D8857 /* Article+Scriptability.swift in Sources */, 845EE7C11FC2488C00854A1F /* SmartFeed.swift in Sources */, - 51865167235556240078E021 /* NNW3FeedsImporter.swift in Sources */, 84702AA41FA27AC0006B8943 /* MarkStatusCommand.swift in Sources */, D5907D7F2004AC00005947E5 /* NSApplication+Scriptability.swift in Sources */, 8405DD9C22153BD7008CE1BF /* NSView-Extensions.swift in Sources */, @@ -2535,7 +2525,6 @@ 5144EA51227B8E4500D19003 /* AccountsFeedbinWindowController.swift in Sources */, 84AD1EBC2032AF5C00BC20B7 /* SidebarOutlineDataSource.swift in Sources */, 845A29241FC9255E007B49E3 /* SidebarCellAppearance.swift in Sources */, - 5186515E23552F040078E021 /* NNW3Feed.swift in Sources */, 845EE7B11FC2366500854A1F /* StarredFeedDelegate.swift in Sources */, 848F6AE51FC29CFB002D422E /* FaviconDownloader.swift in Sources */, 84C9FC7722629E1200D921D6 /* AdvancedPreferencesViewController.swift in Sources */, @@ -2543,6 +2532,7 @@ 849A97981ED9EFAA007D329B /* Node-Extensions.swift in Sources */, 849EE70F203919360082A1EA /* AppAssets.swift in Sources */, 849A97531ED9EAC0007D329B /* AddFeedController.swift in Sources */, + 8459D10323557A460050076F /* NNW3OpenPanelAccessoryViewController.swift in Sources */, 5183CCE8226F68D90010922C /* AccountRefreshTimer.swift in Sources */, 849A97831ED9EC63007D329B /* SidebarStatusBarView.swift in Sources */, 84F2D5381FC22FCC00998D64 /* TodayFeedDelegate.swift in Sources */, @@ -2557,7 +2547,6 @@ 848D578E21543519005FFAD5 /* PasteboardFeed.swift in Sources */, 5144EA2F2279FAB600D19003 /* AccountsDetailViewController.swift in Sources */, 849A97801ED9EC42007D329B /* DetailViewController.swift in Sources */, - 5186516023552F040078E021 /* NNW3Entry.swift in Sources */, 84C9FC6722629B9000D921D6 /* AppDelegate.swift in Sources */, 84C9FC7A22629E1200D921D6 /* AccountsTableViewBackgroundView.swift in Sources */, 84CAFCAF22BC8C35007694F0 /* FetchRequestOperation.swift in Sources */, @@ -2579,7 +2568,6 @@ 5144EA40227A37EC00D19003 /* ImportOPMLWindowController.swift in Sources */, 849A976D1ED9EBC8007D329B /* TimelineTableView.swift in Sources */, 84D52E951FE588BB00D14F5B /* DetailStatusBarView.swift in Sources */, - 516CAC4D235521070038D354 /* ImportNNW3WindowController.swift in Sources */, D5E4CC64202C1AC1009B4FFC /* MainWindowController+Scriptability.swift in Sources */, 84C9FC7922629E1200D921D6 /* PreferencesWindowController.swift in Sources */, 84411E711FE5FBFA004B527F /* SmallIconProvider.swift in Sources */, diff --git a/Shared/Importers/DefaultFeedsImporter.swift b/Shared/Importers/DefaultFeedsImporter.swift index 63ec5aa71..b86d39e36 100644 --- a/Shared/Importers/DefaultFeedsImporter.swift +++ b/Shared/Importers/DefaultFeedsImporter.swift @@ -12,21 +12,10 @@ import RSCore struct DefaultFeedsImporter { - static func importIfNeeded(_ isFirstRun: Bool, account: Account) { - guard shouldImportDefaultFeeds(isFirstRun) else { - return - } - + static func importDefaultFeeds(account: Account) { appDelegate.logDebugMessage("Importing default feeds.") let defaultFeedsURL = Bundle.main.url(forResource: "DefaultFeeds", withExtension: "opml")! AccountManager.shared.defaultAccount.importOPML(defaultFeedsURL) { result in } } - - private static func shouldImportDefaultFeeds(_ isFirstRun: Bool) -> Bool { - if !isFirstRun || AccountManager.shared.anyAccountHasAtLeastOneFeed() { - return false - } - return true - } }