diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index c8c826ef4..79c28212a 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -63,6 +63,8 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, private let feedsPath: ODBPath private let feedsTable: ODBTable + private let opmlFilePath: String + private struct SettingsKey { static let unreadCount = "unreadCount" } @@ -115,6 +117,8 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, self.settingsFile = settingsFile self.dataFolder = dataFolder + self.opmlFilePath = (dataFolder as NSString).appendingPathComponent("Subscriptions.opml") + let databaseFilePath = (dataFolder as NSString).appendingPathComponent("DB.sqlite3") self.database = ArticlesDatabase(databaseFilePath: databaseFilePath, accountID: accountID) @@ -417,6 +421,32 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, flattenedFeeds().forEach { $0.unreadCount = 0 } } + public func opmlDocument() -> String { + let escapedTitle = nameForDisplay.rs_stringByEscapingSpecialXMLCharacters() + let openingText = + """ + + + + + \(escapedTitle) + + + + """ + + let middleText = OPMLString(indentLevel: 0) + + let closingText = + """ + + + """ + + let opml = openingText + middleText + closingText + return opml + } + // MARK: - Debug public func debugDropConditionalGetInfo() { @@ -585,6 +615,8 @@ private extension Account { func saveToDisk() { + dirty = false + let d = diskDictionary() do { try RSPlist.write(d, filePath: settingsFile) @@ -592,7 +624,15 @@ private extension Account { catch let error as NSError { NSApplication.shared.presentError(error) } - dirty = false + + let opmlDocumentString = opmlDocument() + do { + let url = URL(fileURLWithPath: opmlFilePath) + try opmlDocumentString.write(to: url, atomically: true, encoding: .utf8) + } + catch let error as NSError { + NSApplication.shared.presentError(error) + } } } diff --git a/Frameworks/Account/Feed.swift b/Frameworks/Account/Feed.swift index 78194e085..33741421d 100644 --- a/Frameworks/Account/Feed.swift +++ b/Frameworks/Account/Feed.swift @@ -116,7 +116,6 @@ public final class Feed: DisplayNameProvider, UnreadCountProvider, Hashable { self.faviconURL = dictionary[Key.faviconURL] as? String self.name = dictionary[Key.name] as? String self.editedName = dictionary[Key.editedName] as? String -// self.contentHash = dictionary[Key.contentHash] as? String if let conditionalGetInfoDictionary = dictionary[Key.conditionalGetInfo] as? [String: String] { self.conditionalGetInfo = HTTPConditionalGetInfo(dictionary: conditionalGetInfoDictionary) @@ -160,9 +159,6 @@ public final class Feed: DisplayNameProvider, UnreadCountProvider, Hashable { if let authorsArray = authors?.diskArray() { d[Key.authors] = authorsArray } -// if let contentHash = contentHash { -// d[Key.contentHash] = contentHash -// } if let conditionalGetInfo = conditionalGetInfo { d[Key.conditionalGetInfo] = conditionalGetInfo.dictionary } diff --git a/Frameworks/Account/LocalAccount/LocalAccountRefresher.swift b/Frameworks/Account/LocalAccount/LocalAccountRefresher.swift index 618093110..fbdf1d1e6 100644 --- a/Frameworks/Account/LocalAccount/LocalAccountRefresher.swift +++ b/Frameworks/Account/LocalAccount/LocalAccountRefresher.swift @@ -80,7 +80,6 @@ extension LocalAccountRefresher: DownloadSessionDelegate { } feed.contentHash = dataHash - feed.account?.dirty = true } } } diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 4e8bee760..029e361d3 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -8,6 +8,9 @@ /* Begin PBXBuildFile section */ 519B8D332143397200FA689C /* SharingServiceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519B8D322143397200FA689C /* SharingServiceDelegate.swift */; }; + 51EC114C2149FE3300B296E3 /* FolderTreeMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EC114B2149FE3300B296E3 /* FolderTreeMenu.swift */; }; + 51EC11A1214A94AD00B296E3 /* AddFeedFromListSheet.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51EC1193214A94AC00B296E3 /* AddFeedFromListSheet.xib */; }; + 51EC11A3214A990000B296E3 /* AddFeedFromListWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EC11A2214A990000B296E3 /* AddFeedFromListWindowController.swift */; }; 6581C73820CED60100F4AD34 /* SafariExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6581C73720CED60100F4AD34 /* SafariExtensionHandler.swift */; }; 6581C73A20CED60100F4AD34 /* SafariExtensionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6581C73920CED60100F4AD34 /* SafariExtensionViewController.swift */; }; 6581C73D20CED60100F4AD34 /* SafariExtensionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6581C73B20CED60100F4AD34 /* SafariExtensionViewController.xib */; }; @@ -480,6 +483,9 @@ /* Begin PBXFileReference section */ 519B8D322143397200FA689C /* SharingServiceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingServiceDelegate.swift; sourceTree = ""; }; + 51EC114B2149FE3300B296E3 /* FolderTreeMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FolderTreeMenu.swift; path = AddFeed/FolderTreeMenu.swift; sourceTree = ""; }; + 51EC1194214A94AC00B296E3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = NetNewsWire/Base.lproj/AddFeedFromListSheet.xib; sourceTree = SOURCE_ROOT; }; + 51EC11A2214A990000B296E3 /* AddFeedFromListWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AddFeedFromListWindowController.swift; path = AddFeed/AddFeedFromListWindowController.swift; sourceTree = ""; }; 6581C73320CED60000F4AD34 /* Subscribe to Feed.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Subscribe to Feed.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 6581C73420CED60100F4AD34 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 6581C73720CED60100F4AD34 /* SafariExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariExtensionHandler.swift; sourceTree = ""; }; @@ -948,10 +954,13 @@ 849A97551ED9EAC3007D329B /* Add Feed */ = { isa = PBXGroup; children = ( + 51EC1193214A94AC00B296E3 /* AddFeedFromListSheet.xib */, + 51EC11A2214A990000B296E3 /* AddFeedFromListWindowController.swift */, 849A97A71ED9F9AA007D329B /* AddFeedSheet.xib */, 849A97511ED9EAC0007D329B /* AddFeedController.swift */, 849A97521ED9EAC0007D329B /* AddFeedWindowController.swift */, 849A97A01ED9F180007D329B /* InitialFeedDownloader.swift */, + 51EC114B2149FE3300B296E3 /* FolderTreeMenu.swift */, 849A97A11ED9F180007D329B /* FolderTreeControllerDelegate.swift */, ); name = "Add Feed"; @@ -1528,8 +1537,8 @@ ORGANIZATIONNAME = "Ranchero Software"; TargetAttributes = { 6581C73220CED60000F4AD34 = { - DevelopmentTeam = M8L2WTLA8W; - ProvisioningStyle = Manual; + DevelopmentTeam = SHJK2V3AJG; + ProvisioningStyle = Automatic; }; 840D617B2029031C009BC708 = { CreatedOnToolsVersion = 9.3; @@ -1550,12 +1559,12 @@ }; 849C645F1ED37A5D003D8FC0 = { CreatedOnToolsVersion = 8.2.1; - DevelopmentTeam = M8L2WTLA8W; - ProvisioningStyle = Manual; + DevelopmentTeam = SHJK2V3AJG; + ProvisioningStyle = Automatic; }; 849C64701ED37A5D003D8FC0 = { CreatedOnToolsVersion = 8.2.1; - DevelopmentTeam = 9C84TZ7Q6Z; + DevelopmentTeam = SHJK2V3AJG; ProvisioningStyle = Automatic; TestTargetID = 849C645F1ED37A5D003D8FC0; }; @@ -1811,6 +1820,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 51EC11A1214A94AD00B296E3 /* AddFeedFromListSheet.xib in Resources */, 84EB381F1FBA8B9F000D2111 /* KeyboardShortcuts.html in Resources */, 849A97951ED9EF7A007D329B /* IndeterminateProgressWindow.xib in Resources */, 844B5B651FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist in Resources */, @@ -1940,6 +1950,7 @@ 8426118A1FCB67AA0086A189 /* FeedIconDownloader.swift in Sources */, 84162A152038C12C00035290 /* MarkCommandValidationStatus.swift in Sources */, 84E95D241FB1087500552D99 /* ArticlePasteboardWriter.swift in Sources */, + 51EC11A3214A990000B296E3 /* AddFeedFromListWindowController.swift in Sources */, 849A975B1ED9EB0D007D329B /* ArticleUtilities.swift in Sources */, 84DAEE301F86CAFE0058304B /* OPMLImporter.swift in Sources */, 849A975C1ED9EB0D007D329B /* DefaultFeedsImporter.swift in Sources */, @@ -2005,6 +2016,7 @@ 84B99C691FAE36B800ECDEDB /* FeedListFolder.swift in Sources */, 84411E711FE5FBFA004B527F /* SmallIconProvider.swift in Sources */, 844B5B591FE9FE4F00C7C76A /* SidebarKeyboardDelegate.swift in Sources */, + 51EC114C2149FE3300B296E3 /* FolderTreeMenu.swift in Sources */, 849A97A31ED9F180007D329B /* FolderTreeControllerDelegate.swift in Sources */, 84A1500320048D660046AD9A /* SendToCommand.swift in Sources */, 845A29091FC74B8E007B49E3 /* SingleFaviconDownloader.swift in Sources */, @@ -2113,6 +2125,14 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + 51EC1193214A94AC00B296E3 /* AddFeedFromListSheet.xib */ = { + isa = PBXVariantGroup; + children = ( + 51EC1194214A94AC00B296E3 /* Base */, + ); + name = AddFeedFromListSheet.xib; + sourceTree = ""; + }; 6581C73B20CED60100F4AD34 /* SafariExtensionViewController.xib */ = { isa = PBXVariantGroup; children = ( diff --git a/NetNewsWire/AppDelegate.swift b/NetNewsWire/AppDelegate.swift index a94d8405c..8e38abf8a 100644 --- a/NetNewsWire/AppDelegate.swift +++ b/NetNewsWire/AppDelegate.swift @@ -49,6 +49,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, private var readerWindows = [NSWindowController]() private var feedListWindowController: NSWindowController? private var addFeedController: AddFeedController? + private var addFeedFromListController: AddFeedFromListWindowController? private var addFolderWindowController: AddFolderWindowController? private var keyboardShortcutsWindowController: WebViewWindowController? private var inspectorWindowController: InspectorWindowController? @@ -101,6 +102,18 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, addFeedController = AddFeedController(hostWindow: window) addFeedController?.showAddFeedSheet(urlString, name) } + + func showAddFeedFromListOnMainWindow(_ feedListFeeds: [FeedListFeed]) { + + addFeedFromListController = AddFeedFromListWindowController(feedListFeeds) + + createAndShowMainWindow() + + let isDisplayingSheet = mainWindowController?.isDisplayingSheet ?? false + if !isDisplayingSheet, let mainWindow = mainWindowController?.window { + addFeedFromListController!.runSheetOnWindow(mainWindow) + } + } // MARK: - NSApplicationDelegate diff --git a/NetNewsWire/Base.lproj/AddFeedFromListSheet.xib b/NetNewsWire/Base.lproj/AddFeedFromListSheet.xib new file mode 100644 index 000000000..a622517e9 --- /dev/null +++ b/NetNewsWire/Base.lproj/AddFeedFromListSheet.xib @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NetNewsWire/Base.lproj/MainWindow.storyboard b/NetNewsWire/Base.lproj/MainWindow.storyboard index 76c995b0b..b44312305 100644 --- a/NetNewsWire/Base.lproj/MainWindow.storyboard +++ b/NetNewsWire/Base.lproj/MainWindow.storyboard @@ -1,8 +1,8 @@ - + - + @@ -120,7 +120,7 @@ - + @@ -349,11 +349,11 @@ -