Add externalID to Folder and persist it to OPML file. Issue #1060

This commit is contained in:
Maurice Parker 2019-09-25 17:01:09 -05:00
parent 08a8b8f6c2
commit c4ee1edb69
8 changed files with 25 additions and 14 deletions

View File

@ -542,7 +542,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
""" """
let middleText = OPMLString(indentLevel: 0) let middleText = OPMLString(indentLevel: 0, strictConformance: false)
let closingText = let closingText =
""" """
@ -1079,6 +1079,7 @@ private extension Account {
} }
if let folder = ensureFolder(with: folderName) { if let folder = ensureFolder(with: folderName) {
folder.externalID = item.attributes?["nnw_externalID"] as? String
if let itemChildren = item.children { if let itemChildren = item.children {
loadOPMLItems(itemChildren, parentFolder: folder) loadOPMLItems(itemChildren, parentFolder: folder)
} }
@ -1160,13 +1161,13 @@ extension Account {
extension Account: OPMLRepresentable { extension Account: OPMLRepresentable {
public func OPMLString(indentLevel: Int) -> String { public func OPMLString(indentLevel: Int, strictConformance: Bool) -> String {
var s = "" var s = ""
for feed in topLevelFeeds { for feed in topLevelFeeds {
s += feed.OPMLString(indentLevel: indentLevel + 1) s += feed.OPMLString(indentLevel: indentLevel + 1, strictConformance: strictConformance)
} }
for folder in folders! { for folder in folders! {
s += folder.OPMLString(indentLevel: indentLevel + 1) s += folder.OPMLString(indentLevel: indentLevel + 1, strictConformance: strictConformance)
} }
return s return s
} }

View File

@ -226,7 +226,7 @@ public final class Feed: DisplayNameProvider, Renamable, UnreadCountProvider, Ha
extension Feed: OPMLRepresentable { extension Feed: OPMLRepresentable {
public func OPMLString(indentLevel: Int) -> String { public func OPMLString(indentLevel: Int, strictConformance: Bool) -> String {
// https://github.com/brentsimmons/NetNewsWire/issues/527 // https://github.com/brentsimmons/NetNewsWire/issues/527
// Dont use nameForDisplay because that can result in a feed name "Untitled" written to disk, // Dont use nameForDisplay because that can result in a feed name "Untitled" written to disk,
// which NetNewsWire may take later to be the actual name. // which NetNewsWire may take later to be the actual name.

View File

@ -24,6 +24,7 @@ public final class Folder: DisplayNameProvider, Renamable, Container, UnreadCoun
static let untitledName = NSLocalizedString("Untitled ƒ", comment: "Folder name") static let untitledName = NSLocalizedString("Untitled ƒ", comment: "Folder name")
public let folderID: Int // not saved: per-run only public let folderID: Int // not saved: per-run only
public var externalID: String? = nil
static var incrementingID = 0 static var incrementingID = 0
// MARK: - DisplayNameProvider // MARK: - DisplayNameProvider
@ -136,20 +137,29 @@ private extension Folder {
extension Folder: OPMLRepresentable { extension Folder: OPMLRepresentable {
public func OPMLString(indentLevel: Int) -> String { public func OPMLString(indentLevel: Int, strictConformance: Bool) -> String {
let attrExternalID: String = {
if !strictConformance, let externalID = externalID {
return " nnw_externalID=\"\(externalID)\""
} else {
return ""
}
}()
let escapedTitle = nameForDisplay.rs_stringByEscapingSpecialXMLCharacters() let escapedTitle = nameForDisplay.rs_stringByEscapingSpecialXMLCharacters()
var s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\">\n" var s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\"\(attrExternalID)>\n"
s = s.rs_string(byPrependingNumberOfTabs: indentLevel) s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
var hasAtLeastOneChild = false var hasAtLeastOneChild = false
for feed in topLevelFeeds { for feed in topLevelFeeds {
s += feed.OPMLString(indentLevel: indentLevel + 1) s += feed.OPMLString(indentLevel: indentLevel + 1, strictConformance: strictConformance)
hasAtLeastOneChild = true hasAtLeastOneChild = true
} }
if !hasAtLeastOneChild { if !hasAtLeastOneChild {
s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\"/>\n" s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\"\(attrExternalID)/>\n"
s = s.rs_string(byPrependingNumberOfTabs: indentLevel) s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
return s return s
} }

View File

@ -150,7 +150,7 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta
@objc(opmlRepresentation) @objc(opmlRepresentation)
var opmlRepresentation:String { var opmlRepresentation:String {
return self.account.OPMLString(indentLevel:0) return self.account.OPMLString(indentLevel:0, strictConformance: true)
} }
@objc(accountType) @objc(accountType)

View File

@ -146,7 +146,7 @@ class ScriptableFeed: NSObject, UniqueIdScriptingObject, ScriptingObjectContaine
@objc(opmlRepresentation) @objc(opmlRepresentation)
var opmlRepresentation:String { var opmlRepresentation:String {
return self.feed.OPMLString(indentLevel:0) return self.feed.OPMLString(indentLevel:0, strictConformance: true)
} }
// MARK: --- scriptable elements --- // MARK: --- scriptable elements ---

View File

@ -101,7 +101,7 @@ class ScriptableFolder: NSObject, UniqueIdScriptingObject, ScriptingObjectContai
@objc(opmlRepresentation) @objc(opmlRepresentation)
var opmlRepresentation:String { var opmlRepresentation:String {
return self.folder.OPMLString(indentLevel:0) return self.folder.OPMLString(indentLevel:0, strictConformance: true)
} }
} }

View File

@ -27,7 +27,7 @@ struct OPMLExporter {
""" """
let middleText = account.OPMLString(indentLevel: 0) let middleText = account.OPMLString(indentLevel: 0, strictConformance: true)
let closingText = let closingText =
""" """

@ -1 +1 @@
Subproject commit b3a3178b00810c9e2c668a8c3b17080501cf1f33 Subproject commit d70c24feb4bdad8fdbe7e0beb6edd12d3383c7dc