From af0d6c9022f2296c09f1c46e717430e20bd215be Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 20 Sep 2019 11:34:31 -0500 Subject: [PATCH] Implement AccountBehaviors so that we don't have to keep adding boolean flags to account --- Frameworks/Account/Account.swift | 12 +----- .../Account/Account.xcodeproj/project.pbxproj | 4 ++ Frameworks/Account/AccountBehaviors.swift | 38 +++++++++++++++++++ Frameworks/Account/AccountDelegate.swift | 6 +-- .../Feedbin/FeedbinAccountDelegate.swift | 4 +- .../Feedly/FeedlyAccountDelegate.swift | 11 ++---- .../LocalAccount/LocalAccountDelegate.swift | 4 +- .../ReaderAPI/ReaderAPIAccountDelegate.swift | 4 +- .../OPML/ImportOPMLWindowController.swift | 2 +- .../Sidebar/SidebarOutlineDataSource.swift | 12 +++--- iOS/Settings/SettingsView.swift | 2 +- 11 files changed, 61 insertions(+), 38 deletions(-) create mode 100644 Frameworks/Account/AccountBehaviors.swift diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 7bce13e01..7d2912261 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -189,12 +189,8 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, } } - public var isTagBasedSystem: Bool { - return delegate.isTagBasedSystem - } - - public var isOPMLImportSupported: Bool { - return delegate.isOPMLImportSupported + public var behaviors: AccountBehaviors { + return delegate.behaviors } var refreshInProgress = false { @@ -215,10 +211,6 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, return delegate.refreshProgress } - var isSubfoldersSupported: Bool { - return delegate.isSubfoldersSupported - } - init?(dataFolder: String, type: AccountType, accountID: String, transport: Transport? = nil) { switch type { case .onMyMac: diff --git a/Frameworks/Account/Account.xcodeproj/project.pbxproj b/Frameworks/Account/Account.xcodeproj/project.pbxproj index b457b5924..0718a94ff 100644 --- a/Frameworks/Account/Account.xcodeproj/project.pbxproj +++ b/Frameworks/Account/Account.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 5165D72A22835F7D00D9D53D /* HTMLFeedFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5165D71E22835E9800D9D53D /* HTMLFeedFinder.swift */; }; 5165D73122837F3400D9D53D /* InitialFeedDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5165D73022837F3400D9D53D /* InitialFeedDownloader.swift */; }; 5170743C232AEDB500A461A3 /* OPMLFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5170743B232AEDB500A461A3 /* OPMLFile.swift */; }; + 51BB7B84233531BC008E8144 /* AccountBehaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */; }; 51D58755227F53BE00900287 /* FeedbinTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51D58754227F53BE00900287 /* FeedbinTag.swift */; }; 51D5875A227F630B00900287 /* tags_delete.json in Resources */ = {isa = PBXBuildFile; fileRef = 51D58757227F630B00900287 /* tags_delete.json */; }; 51D5875B227F630B00900287 /* tags_add.json in Resources */ = {isa = PBXBuildFile; fileRef = 51D58758227F630B00900287 /* tags_add.json */; }; @@ -166,6 +167,7 @@ 5165D71E22835E9800D9D53D /* HTMLFeedFinder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLFeedFinder.swift; sourceTree = ""; }; 5165D73022837F3400D9D53D /* InitialFeedDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InitialFeedDownloader.swift; sourceTree = ""; }; 5170743B232AEDB500A461A3 /* OPMLFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLFile.swift; sourceTree = ""; }; + 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountBehaviors.swift; sourceTree = ""; }; 51D58754227F53BE00900287 /* FeedbinTag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbinTag.swift; sourceTree = ""; }; 51D58757227F630B00900287 /* tags_delete.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = tags_delete.json; sourceTree = ""; }; 51D58758227F630B00900287 /* tags_add.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = tags_add.json; sourceTree = ""; }; @@ -377,6 +379,7 @@ children = ( 848935101F62486800CEBD24 /* Account.swift */, 841974241F6DDCE4006346C4 /* AccountDelegate.swift */, + 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */, 51E3EB40229AF61B00645299 /* AccountError.swift */, 846E77531F6F00E300A165E2 /* AccountManager.swift */, 5170743B232AEDB500A461A3 /* OPMLFile.swift */, @@ -687,6 +690,7 @@ 9E1D155B2334423300F4944C /* FeedlyOrganiseParsedItemsByFeedOperation.swift in Sources */, 552032FE229D5D5A009559E0 /* ReaderAPIAccountDelegate.swift in Sources */, 5170743C232AEDB500A461A3 /* OPMLFile.swift in Sources */, + 51BB7B84233531BC008E8144 /* AccountBehaviors.swift in Sources */, 552032FC229D5D5A009559E0 /* ReaderAPIUnreadEntry.swift in Sources */, 9EC688EA232B973C00A8D0A2 /* FeedlyAPICaller.swift in Sources */, 9EAEC62823331C350085D7C9 /* FeedlyCategory.swift in Sources */, diff --git a/Frameworks/Account/AccountBehaviors.swift b/Frameworks/Account/AccountBehaviors.swift new file mode 100644 index 000000000..058e94b5d --- /dev/null +++ b/Frameworks/Account/AccountBehaviors.swift @@ -0,0 +1,38 @@ +// +// AccountBehaviors.swift +// Account +// +// Created by Maurice Parker on 9/20/19. +// Copyright © 2019 Ranchero Software, LLC. All rights reserved. +// + +import Foundation + +/** + Account specific behaviors are used to support different sync services. These sync + services don't all act the same and we need to reflect their differences in the + user interface as much as possible. For example some sync services don't allow + feeds to be in the root folder of the account. +*/ +public struct AccountBehaviors: OptionSet { + + /** + Account doesn't support copies of a feed that are in a folder to be made to the root folder. + */ + public static let disallowFeedCopyInRootFolder = AccountBehaviors(rawValue: 1) + + /** + Account doesn't support feeds in the root folder. + */ + public static let disallowFeedInRootFolder = AccountBehaviors(rawValue: 2) + + /** + Account doesn't support OPML imports + */ + public static let disallowOPMLImports = AccountBehaviors(rawValue: 3) + + public let rawValue: Int + public init(rawValue: Int) { + self.rawValue = rawValue + } +} diff --git a/Frameworks/Account/AccountDelegate.swift b/Frameworks/Account/AccountDelegate.swift index 5be29ebe6..4a3978f10 100644 --- a/Frameworks/Account/AccountDelegate.swift +++ b/Frameworks/Account/AccountDelegate.swift @@ -12,10 +12,8 @@ import RSWeb protocol AccountDelegate { - // Local account does not; some synced accounts might. - var isSubfoldersSupported: Bool { get } - var isTagBasedSystem: Bool { get } - var isOPMLImportSupported: Bool { get } + var behaviors: AccountBehaviors { get } + var isOPMLImportInProgress: Bool { get } var server: String? { get } diff --git a/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift b/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift index cc9020df3..597a6db67 100644 --- a/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift @@ -24,9 +24,7 @@ final class FeedbinAccountDelegate: AccountDelegate { private let caller: FeedbinAPICaller private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Feedbin") - let isSubfoldersSupported = false - let isTagBasedSystem = true - let isOPMLImportSupported = true + let behaviors: AccountBehaviors = [.disallowFeedCopyInRootFolder] let server: String? = "api.feedbin.com" var isOPMLImportInProgress = false diff --git a/Frameworks/Account/Feedly/FeedlyAccountDelegate.swift b/Frameworks/Account/Feedly/FeedlyAccountDelegate.swift index 09158aff4..f154438be 100644 --- a/Frameworks/Account/Feedly/FeedlyAccountDelegate.swift +++ b/Frameworks/Account/Feedly/FeedlyAccountDelegate.swift @@ -14,14 +14,11 @@ import SyncDatabase import os.log final class FeedlyAccountDelegate: AccountDelegate { + + // TODO: Kiel, if you decide not to support OPML import you will have to disallow it in the behaviors + // See https://developer.feedly.com/v3/opml/ + var behaviors: AccountBehaviors = [.disallowFeedInRootFolder] - // Collections are one-level deep. - let isSubfoldersSupported = false - - // Feedly uses collections and streams. But it does have tags? - let isTagBasedSystem = false - - // Could be true. See https://developer.feedly.com/v3/opml/ let isOPMLImportSupported = false var isOPMLImportInProgress = false diff --git a/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift b/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift index d1c1820c9..5ebd94551 100644 --- a/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift +++ b/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift @@ -18,9 +18,7 @@ public enum LocalAccountDelegateError: String, Error { final class LocalAccountDelegate: AccountDelegate { - let isSubfoldersSupported = false - let isTagBasedSystem = false - let isOPMLImportSupported = true + let behaviors: AccountBehaviors = [] let isOPMLImportInProgress = false let server: String? = nil diff --git a/Frameworks/Account/ReaderAPI/ReaderAPIAccountDelegate.swift b/Frameworks/Account/ReaderAPI/ReaderAPIAccountDelegate.swift index ca6631b20..6ee8edc11 100644 --- a/Frameworks/Account/ReaderAPI/ReaderAPIAccountDelegate.swift +++ b/Frameworks/Account/ReaderAPI/ReaderAPIAccountDelegate.swift @@ -25,8 +25,7 @@ final class ReaderAPIAccountDelegate: AccountDelegate { private let caller: ReaderAPICaller private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "ReaderAPI") - let isSubfoldersSupported = false - let isTagBasedSystem = true + var behaviors: AccountBehaviors = [.disallowFeedInRootFolder, .disallowOPMLImports] var server: String? { get { @@ -34,7 +33,6 @@ final class ReaderAPIAccountDelegate: AccountDelegate { } } - let isOPMLImportSupported = false var isOPMLImportInProgress = false var credentials: Credentials? { diff --git a/Mac/MainWindow/OPML/ImportOPMLWindowController.swift b/Mac/MainWindow/OPML/ImportOPMLWindowController.swift index 074419f02..252bcac43 100644 --- a/Mac/MainWindow/OPML/ImportOPMLWindowController.swift +++ b/Mac/MainWindow/OPML/ImportOPMLWindowController.swift @@ -26,7 +26,7 @@ class ImportOPMLWindowController: NSWindowController { for oneAccount in AccountManager.shared.sortedActiveAccounts { - if !oneAccount.isOPMLImportSupported { + if oneAccount.behaviors.contains(.disallowOPMLImports) { continue } diff --git a/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift b/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift index c993ac343..b438d540a 100644 --- a/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift +++ b/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift @@ -199,7 +199,7 @@ private extension SidebarOutlineDataSource { if nodeHasChildRepresentingDraggedFeed(dropTargetNode, draggedFeed) { return SidebarOutlineDataSource.dragOperationNone } - if violatesTagSpecificBehavior(dropTargetNode, draggedFeed) { + if violatesAccountSpecificBehavior(dropTargetNode, draggedFeed) { return SidebarOutlineDataSource.dragOperationNone } if parentNode == dropTargetNode && index == NSOutlineViewDropOnItemIndex { @@ -220,7 +220,7 @@ private extension SidebarOutlineDataSource { if nodeHasChildRepresentingAnyDraggedFeed(dropTargetNode, draggedFeeds) { return SidebarOutlineDataSource.dragOperationNone } - if violatesTagSpecificBehavior(dropTargetNode, draggedFeeds) { + if violatesAccountSpecificBehavior(dropTargetNode, draggedFeeds) { return SidebarOutlineDataSource.dragOperationNone } if parentNode !== dropTargetNode || index != NSOutlineViewDropOnItemIndex { @@ -631,12 +631,12 @@ private extension SidebarOutlineDataSource { return false } - func violatesTagSpecificBehavior(_ parentNode: Node, _ draggedFeed: PasteboardFeed) -> Bool { - return violatesTagSpecificBehavior(parentNode, Set([draggedFeed])) + func violatesAccountSpecificBehavior(_ parentNode: Node, _ draggedFeed: PasteboardFeed) -> Bool { + return violatesAccountSpecificBehavior(parentNode, Set([draggedFeed])) } - func violatesTagSpecificBehavior(_ parentNode: Node, _ draggedFeeds: Set) -> Bool { - guard let parentAccount = nodeAccount(parentNode), parentAccount.isTagBasedSystem else { + func violatesAccountSpecificBehavior(_ parentNode: Node, _ draggedFeeds: Set) -> Bool { + guard let parentAccount = nodeAccount(parentNode), parentAccount.behaviors.contains(.disallowFeedCopyInRootFolder) else { return false } diff --git a/iOS/Settings/SettingsView.swift b/iOS/Settings/SettingsView.swift index 83b4c847d..54066bba4 100644 --- a/iOS/Settings/SettingsView.swift +++ b/iOS/Settings/SettingsView.swift @@ -184,7 +184,7 @@ struct SettingsView : View { var buttons = [ActionSheet.Button]() for account in viewModel.activeAccounts { - if !account.isOPMLImportSupported { + if account.behaviors.contains(.disallowOPMLImports) { continue }