diff --git a/Frameworks/Account/Account.xcodeproj/project.pbxproj b/Frameworks/Account/Account.xcodeproj/project.pbxproj index 3c1de4b7c..b51ae8086 100644 --- a/Frameworks/Account/Account.xcodeproj/project.pbxproj +++ b/Frameworks/Account/Account.xcodeproj/project.pbxproj @@ -61,6 +61,7 @@ 5165D73122837F3400D9D53D /* InitialFeedDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5165D73022837F3400D9D53D /* InitialFeedDownloader.swift */; }; 516896352448EBEA00185AC5 /* FeedProviderManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 516896342448EBEA00185AC5 /* FeedProviderManager.swift */; }; 5170743C232AEDB500A461A3 /* OPMLFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5170743B232AEDB500A461A3 /* OPMLFile.swift */; }; + 5193CD54245E3F7A0092735E /* RedditFeedProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5193CD53245E3F7A0092735E /* RedditFeedProvider.swift */; }; 519E84A62433D49000D238B0 /* OPMLNormalizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84A52433D49000D238B0 /* OPMLNormalizer.swift */; }; 519E84A82434C5EF00D238B0 /* CloudKitArticlesZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */; }; 519E84AC2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */; }; @@ -315,6 +316,7 @@ 5165D73022837F3400D9D53D /* InitialFeedDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InitialFeedDownloader.swift; sourceTree = ""; }; 516896342448EBEA00185AC5 /* FeedProviderManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedProviderManager.swift; sourceTree = ""; }; 5170743B232AEDB500A461A3 /* OPMLFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLFile.swift; sourceTree = ""; }; + 5193CD53245E3F7A0092735E /* RedditFeedProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedditFeedProvider.swift; sourceTree = ""; }; 519E84A52433D49000D238B0 /* OPMLNormalizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLNormalizer.swift; sourceTree = ""; }; 519E84A72434C5EF00D238B0 /* CloudKitArticlesZone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitArticlesZone.swift; sourceTree = ""; }; 519E84AB2435019100D238B0 /* CloudKitArticlesZoneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CloudKitArticlesZoneDelegate.swift; sourceTree = ""; }; @@ -590,6 +592,7 @@ 5132AAC12448BAD90077840A /* FeedProvider.swift */, 516896342448EBEA00185AC5 /* FeedProviderManager.swift */, 5132AAC22448BAD90077840A /* Twitter */, + 5193CD52245E3F520092735E /* Reddit */, ); path = FeedProvider; sourceTree = ""; @@ -624,6 +627,14 @@ path = FeedFinder; sourceTree = ""; }; + 5193CD52245E3F520092735E /* Reddit */ = { + isa = PBXGroup; + children = ( + 5193CD53245E3F7A0092735E /* RedditFeedProvider.swift */, + ); + path = Reddit; + sourceTree = ""; + }; 51D58756227F62E300900287 /* JSON */ = { isa = PBXGroup; children = ( @@ -1180,6 +1191,7 @@ 841974251F6DDCE4006346C4 /* AccountDelegate.swift in Sources */, 510BD113232C3E9D002692E4 /* WebFeedMetadataFile.swift in Sources */, 51B36309244B62A5000DEF2A /* TwitterURL.swift in Sources */, + 5193CD54245E3F7A0092735E /* RedditFeedProvider.swift in Sources */, 5103A9D92422546800410853 /* CloudKitAccountDelegate.swift in Sources */, 5165D73122837F3400D9D53D /* InitialFeedDownloader.swift in Sources */, 9E784EBE237E890600099B1B /* FeedlyLogoutOperation.swift in Sources */, diff --git a/Frameworks/Account/FeedProvider/Reddit/RedditFeedProvider.swift b/Frameworks/Account/FeedProvider/Reddit/RedditFeedProvider.swift new file mode 100644 index 000000000..5fae04115 --- /dev/null +++ b/Frameworks/Account/FeedProvider/Reddit/RedditFeedProvider.swift @@ -0,0 +1,138 @@ +// +// RedditFeedProvider.swift +// Account +// +// Created by Maurice Parker on 5/2/20. +// Copyright © 2020 Ranchero Software, LLC. All rights reserved. +// + +import Foundation +import OAuthSwift +import Secrets +import RSParser + +public enum RedditFeedProviderError: LocalizedError { + case unknown + + public var localizedDescription: String { + switch self { + case .unknown: + return NSLocalizedString("An Reddit Twitter Feed Provider error has occurred.", comment: "Unknown error") + } + } +} + +public struct RedditFeedProvider: FeedProvider { + + private static let server = "api.twitter.com" + private static let apiBase = "https://api.twitter.com/1.1/" + private static let dateFormat = "EEE MMM dd HH:mm:ss Z yyyy" + + private static let userPaths = ["/home", "/notifications"] + private static let reservedPaths = ["/search", "/explore", "/messages", "/i", "/compose"] + + public var username: String + + private var oauthToken: String + private var oauthTokenSecret: String + + private var client: OAuthSwiftClient + + public init?(tokenSuccess: OAuthSwift.TokenSuccess) { + guard let username = tokenSuccess.parameters["screen_name"] as? String else { + return nil + } + + self.username = username + self.oauthToken = tokenSuccess.credential.oauthToken + self.oauthTokenSecret = tokenSuccess.credential.oauthTokenSecret + + let tokenCredentials = Credentials(type: .oauthAccessToken, username: username, secret: oauthToken) + try? CredentialsManager.storeCredentials(tokenCredentials, server: Self.server) + + let tokenSecretCredentials = Credentials(type: .oauthAccessTokenSecret, username: username, secret: oauthTokenSecret) + try? CredentialsManager.storeCredentials(tokenSecretCredentials, server: Self.server) + + client = OAuthSwiftClient(consumerKey: Secrets.twitterConsumerKey, + consumerSecret: Secrets.twitterConsumerSecret, + oauthToken: oauthToken, + oauthTokenSecret: oauthTokenSecret, + version: .oauth1) + } + + public init?(username: String) { + self.username = username + + guard let tokenCredentials = try? CredentialsManager.retrieveCredentials(type: .oauthAccessToken, server: Self.server, username: username), + let tokenSecretCredentials = try? CredentialsManager.retrieveCredentials(type: .oauthAccessTokenSecret, server: Self.server, username: username) else { + return nil + } + + self.oauthToken = tokenCredentials.secret + self.oauthTokenSecret = tokenSecretCredentials.secret + + client = OAuthSwiftClient(consumerKey: Secrets.twitterConsumerKey, + consumerSecret: Secrets.twitterConsumerSecret, + oauthToken: oauthToken, + oauthTokenSecret: oauthTokenSecret, + version: .oauth1) + } + + public func ability(_ urlComponents: URLComponents) -> FeedProviderAbility { + guard urlComponents.host?.hasSuffix("reddit.com") ?? false else { + return .none + } + + if let username = urlComponents.user { + if username == username { + return .owner + } else { + return .none + } + } + + return .available + } + + public func iconURL(_ urlComponents: URLComponents, completion: @escaping (Result) -> Void) { + completion(.failure(TwitterFeedProviderError.screenNameNotFound)) + } + + public func assignName(_ urlComponents: URLComponents, completion: @escaping (Result) -> Void) { + let path = urlComponents.path + + switch path { + case "", "/": + let name = NSLocalizedString("Reddit Timeline", comment: "Reddit Timeline") + completion(.success(name)) + case "/r", "/u": + let path = String(path.suffix(from: path.index(path.startIndex, offsetBy: 2))) + completion(.success(path)) + case "/user": + let path = String(path.suffix(from: path.index(path.startIndex, offsetBy: 5))) + completion(.success(path)) + default: + completion(.failure(TwitterFeedProviderError.unknown)) + } + } + + public func refresh(_ webFeed: WebFeed, completion: @escaping (Result, Error>) -> Void) { +// guard let urlComponents = URLComponents(string: webFeed.url) else { +// completion(.failure(TwitterFeedProviderError.unknown)) +// return +// } + + completion(.success(Set())) + } + +} + +// MARK: OAuth1SwiftProvider + +extension RedditFeedProvider: OAuth2SwiftProvider { + + public static var oauth2Swift: OAuth2Swift { + return OAuth2Swift(consumerKey: "", consumerSecret: "", authorizeUrl: "", accessTokenUrl: "", responseType: "") + } + +} diff --git a/Frameworks/Secrets/OAuth2SwiftProvider.swift b/Frameworks/Secrets/OAuth2SwiftProvider.swift new file mode 100644 index 000000000..5509dfeea --- /dev/null +++ b/Frameworks/Secrets/OAuth2SwiftProvider.swift @@ -0,0 +1,17 @@ +// +// OAuth2SwiftProvider.swift +// Secrets +// +// Created by Maurice Parker on 5/2/20. +// Copyright © 2020 Ranchero Software, LLC. All rights reserved. +// + +import Foundation + +import OAuthSwift + +public protocol OAuth2SwiftProvider { + + static var oauth2Swift: OAuth2Swift { get } + +} diff --git a/Frameworks/Secrets/Secrets.xcodeproj/project.pbxproj b/Frameworks/Secrets/Secrets.xcodeproj/project.pbxproj index 489bf569f..5cc15d12b 100644 --- a/Frameworks/Secrets/Secrets.xcodeproj/project.pbxproj +++ b/Frameworks/Secrets/Secrets.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 514BB43B243FFBFF0023B621 /* CredentialsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514BB439243FFBFF0023B621 /* CredentialsManager.swift */; }; 514BB43C243FFBFF0023B621 /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514BB43A243FFBFF0023B621 /* Credentials.swift */; }; 5152BEF2244633FA00138380 /* OAuth1SwiftProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5152BEF1244633FA00138380 /* OAuth1SwiftProvider.swift */; }; + 5193CD56245E40B70092735E /* OAuth2SwiftProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5193CD55245E40B70092735E /* OAuth2SwiftProvider.swift */; }; 51C99ABD2447DD730027D5F6 /* OAuthSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51C99ABC2447DD730027D5F6 /* OAuthSwift.framework */; }; /* End PBXBuildFile section */ @@ -29,6 +30,7 @@ 514BB439243FFBFF0023B621 /* CredentialsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CredentialsManager.swift; sourceTree = ""; }; 514BB43A243FFBFF0023B621 /* Credentials.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Credentials.swift; sourceTree = ""; }; 5152BEF1244633FA00138380 /* OAuth1SwiftProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuth1SwiftProvider.swift; sourceTree = ""; }; + 5193CD55245E40B70092735E /* OAuth2SwiftProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuth2SwiftProvider.swift; sourceTree = ""; }; 51C99ABC2447DD730027D5F6 /* OAuthSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OAuthSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -50,6 +52,7 @@ 514BB43A243FFBFF0023B621 /* Credentials.swift */, 514BB439243FFBFF0023B621 /* CredentialsManager.swift */, 5152BEF1244633FA00138380 /* OAuth1SwiftProvider.swift */, + 5193CD55245E40B70092735E /* OAuth2SwiftProvider.swift */, 514BB41E243FFA640023B621 /* Info.plist */, 514BB41B243FFA640023B621 /* Products */, 514446EC2440030900EE752D /* Secrets.swift */, @@ -192,6 +195,7 @@ 514BB43C243FFBFF0023B621 /* Credentials.swift in Sources */, 514446ED2440030900EE752D /* Secrets.swift in Sources */, 5152BEF2244633FA00138380 /* OAuth1SwiftProvider.swift in Sources */, + 5193CD56245E40B70092735E /* OAuth2SwiftProvider.swift in Sources */, 514BB43B243FFBFF0023B621 /* CredentialsManager.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Mac/AppAssets.swift b/Mac/AppAssets.swift index b7dca8f1f..5e4699fa1 100644 --- a/Mac/AppAssets.swift +++ b/Mac/AppAssets.swift @@ -85,6 +85,10 @@ struct AppAssets { return RSImage(named: "extensionPointMicroblog")! }() + static var extensionPointReddit: RSImage = { + return RSImage(named: "extensionPointReddit")! + }() + static var extensionPointTwitter: RSImage = { return RSImage(named: "extensionPointTwitter")! }() diff --git a/Mac/Resources/Assets.xcassets/extensionPointReddit.imageset/Contents.json b/Mac/Resources/Assets.xcassets/extensionPointReddit.imageset/Contents.json new file mode 100644 index 000000000..08e567354 --- /dev/null +++ b/Mac/Resources/Assets.xcassets/extensionPointReddit.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "reddit-logo.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Mac/Resources/Assets.xcassets/extensionPointReddit.imageset/reddit-logo.pdf b/Mac/Resources/Assets.xcassets/extensionPointReddit.imageset/reddit-logo.pdf new file mode 100644 index 000000000..b4b6d7419 Binary files /dev/null and b/Mac/Resources/Assets.xcassets/extensionPointReddit.imageset/reddit-logo.pdf differ diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 761a47d7b..55d921e13 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -191,6 +191,9 @@ 51934CCE2310792F006127BE /* ActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CCD2310792F006127BE /* ActivityManager.swift */; }; 51938DF2231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */; }; 51938DF3231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */; }; + 5193CD58245E44A90092735E /* RedditFeedProvider-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5193CD57245E44A90092735E /* RedditFeedProvider-Extensions.swift */; }; + 5193CD59245E44A90092735E /* RedditFeedProvider-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5193CD57245E44A90092735E /* RedditFeedProvider-Extensions.swift */; }; + 5193CD5A245E44A90092735E /* RedditFeedProvider-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5193CD57245E44A90092735E /* RedditFeedProvider-Extensions.swift */; }; 519B8D332143397200FA689C /* SharingServiceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519B8D322143397200FA689C /* SharingServiceDelegate.swift */; }; 519E743D22C663F900A78E47 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E743422C663F900A78E47 /* SceneDelegate.swift */; }; 519ED456244828C3007F8E94 /* AddExtensionPointViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519ED455244828C3007F8E94 /* AddExtensionPointViewController.swift */; }; @@ -1502,6 +1505,7 @@ 51934CC1230F5963006127BE /* InteractiveNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractiveNavigationController.swift; sourceTree = ""; }; 51934CCD2310792F006127BE /* ActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityManager.swift; sourceTree = ""; }; 51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchTimelineFeedDelegate.swift; sourceTree = ""; }; + 5193CD57245E44A90092735E /* RedditFeedProvider-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RedditFeedProvider-Extensions.swift"; sourceTree = ""; }; 519B8D322143397200FA689C /* SharingServiceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingServiceDelegate.swift; sourceTree = ""; }; 519E743422C663F900A78E47 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 519ED455244828C3007F8E94 /* AddExtensionPointViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddExtensionPointViewController.swift; sourceTree = ""; }; @@ -1968,6 +1972,7 @@ 84A1500420048DDF0046AD9A /* SendToMarsEditCommand.swift */, 84A14FF220048CA70046AD9A /* SendToMicroBlogCommand.swift */, 515A5106243D0CCD0089E588 /* TwitterFeedProvider-Extensions.swift */, + 5193CD57245E44A90092735E /* RedditFeedProvider-Extensions.swift */, ); path = ExtensionPoints; sourceTree = ""; @@ -4141,6 +4146,7 @@ 65ED3FE3235DEF6C0081F399 /* ArticleUtilities.swift in Sources */, 65ED3FE4235DEF6C0081F399 /* NNW3OpenPanelAccessoryViewController.swift in Sources */, 65ED3FE5235DEF6C0081F399 /* DefaultFeedsImporter.swift in Sources */, + 5193CD59245E44A90092735E /* RedditFeedProvider-Extensions.swift in Sources */, 65ED3FE6235DEF6C0081F399 /* RenameWindowController.swift in Sources */, 65ED3FE7235DEF6C0081F399 /* SendToMicroBlogCommand.swift in Sources */, 65ED3FE8235DEF6C0081F399 /* ArticleStyle.swift in Sources */, @@ -4308,6 +4314,7 @@ 51C4526B226508F600C03939 /* MasterFeedViewController.swift in Sources */, 5126EE97226CB48A00C22AFC /* SceneCoordinator.swift in Sources */, 84CAFCB022BC8C35007694F0 /* FetchRequestOperation.swift in Sources */, + 5193CD5A245E44A90092735E /* RedditFeedProvider-Extensions.swift in Sources */, 51EF0F77227716200050506E /* FaviconGenerator.swift in Sources */, 51938DF3231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */, 51C4525A226508D600C03939 /* UIStoryboard-Extensions.swift in Sources */, @@ -4527,6 +4534,7 @@ 849A97531ED9EAC0007D329B /* AddFeedController.swift in Sources */, 5183CCE8226F68D90010922C /* AccountRefreshTimer.swift in Sources */, 849A97831ED9EC63007D329B /* SidebarStatusBarView.swift in Sources */, + 5193CD58245E44A90092735E /* RedditFeedProvider-Extensions.swift in Sources */, 51938DF2231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */, 84F2D5381FC22FCC00998D64 /* TodayFeedDelegate.swift in Sources */, 841ABA5E20145E9200980E11 /* FolderInspectorViewController.swift in Sources */, diff --git a/Shared/ExtensionPoints/ExtensionPointIdentifer.swift b/Shared/ExtensionPoints/ExtensionPointIdentifer.swift index a23328a48..434ee817c 100644 --- a/Shared/ExtensionPoints/ExtensionPointIdentifer.swift +++ b/Shared/ExtensionPoints/ExtensionPointIdentifer.swift @@ -16,7 +16,8 @@ enum ExtensionPointIdentifer: Hashable { case microblog #endif case twitter(String) - + case reddit(String) + var extensionPointType: ExtensionPoint.Type { switch self { #if os(macOS) @@ -27,6 +28,8 @@ enum ExtensionPointIdentifer: Hashable { #endif case .twitter: return TwitterFeedProvider.self + case .reddit: + return RedditFeedProvider.self } } @@ -47,6 +50,11 @@ enum ExtensionPointIdentifer: Hashable { "type": "twitter", "screenName": screenName ] + case .reddit(let username): + return [ + "type": "reddit", + "screenName": username + ] } } @@ -63,6 +71,9 @@ enum ExtensionPointIdentifer: Hashable { case "twitter": guard let screenName = userInfo["screenName"] as? String else { return nil } self = ExtensionPointIdentifer.twitter(screenName) + case "reddit": + guard let username = userInfo["username"] as? String else { return nil } + self = ExtensionPointIdentifer.twitter(username) default: return nil } @@ -79,6 +90,9 @@ enum ExtensionPointIdentifer: Hashable { case .twitter(let screenName): hasher.combine("twitter") hasher.combine(screenName) + case .reddit(let username): + hasher.combine("reddit") + hasher.combine(username) } } diff --git a/Shared/ExtensionPoints/ExtensionPointManager.swift b/Shared/ExtensionPoints/ExtensionPointManager.swift index 423cad4eb..4d51b8a4b 100644 --- a/Shared/ExtensionPoints/ExtensionPointManager.swift +++ b/Shared/ExtensionPoints/ExtensionPointManager.swift @@ -53,18 +53,22 @@ final class ExtensionPointManager: FeedProviderManagerDelegate { return activeExtensionPoints.values.contains(where: { $0 is TwitterFeedProvider }) } + var isRedditEnabled: Bool { + return activeExtensionPoints.values.contains(where: { $0 is RedditFeedProvider }) + } + init() { #if os(macOS) #if DEBUG - possibleExtensionPointTypes = [SendToMarsEditCommand.self, SendToMicroBlogCommand.self, TwitterFeedProvider.self] + possibleExtensionPointTypes = [SendToMarsEditCommand.self, SendToMicroBlogCommand.self, TwitterFeedProvider.self, RedditFeedProvider.self] #else - possibleExtensionPointTypes = [SendToMarsEditCommand.self, SendToMicroBlogCommand.self, TwitterFeedProvider.self] + possibleExtensionPointTypes = [SendToMarsEditCommand.self, SendToMicroBlogCommand.self, TwitterFeedProvider.self, RedditFeedProvider.self] #endif #else #if DEBUG - possibleExtensionPointTypes = [TwitterFeedProvider.self] + possibleExtensionPointTypes = [TwitterFeedProvider.self, RedditFeedProvider.self] #else - possibleExtensionPointTypes = [TwitterFeedProvider.self] + possibleExtensionPointTypes = [TwitterFeedProvider.self, RedditFeedProvider.self] #endif #endif loadExtensionPoints() @@ -115,6 +119,12 @@ private extension ExtensionPointManager { } else { return nil } + case is RedditFeedProvider.Type: + if let tokenSuccess = tokenSuccess { + return RedditFeedProvider(tokenSuccess: tokenSuccess) + } else { + return nil + } default: assertionFailure("Unrecognized Extension Point Type.") } @@ -131,6 +141,8 @@ private extension ExtensionPointManager { #endif case .twitter(let screenName): return TwitterFeedProvider(screenName: screenName) + case .reddit(let username): + return RedditFeedProvider(username: username) } } diff --git a/Shared/ExtensionPoints/RedditFeedProvider-Extensions.swift b/Shared/ExtensionPoints/RedditFeedProvider-Extensions.swift new file mode 100644 index 000000000..a2f3839b6 --- /dev/null +++ b/Shared/ExtensionPoints/RedditFeedProvider-Extensions.swift @@ -0,0 +1,30 @@ +// +// RedditFeedProvider-Extensions.swift +// NetNewsWire +// +// Created by Maurice Parker on 5/2/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import Foundation +import Account + +extension RedditFeedProvider: ExtensionPoint { + + static var isSinglton = false + static var isDeveloperBuildRestricted = true + static var title = NSLocalizedString("Reddit", comment: "Reddit") + static var templateImage = AppAssets.extensionPointReddit + static var description: NSAttributedString = { + return RedditFeedProvider.makeAttrString("This extension enables you to subscribe to Reddit URL's as if they were RSS feeds. It only works with \(Account.defaultLocalAccountName) or iCloud accounts.") + }() + + var extensionPointID: ExtensionPointIdentifer { + return ExtensionPointIdentifer.reddit(username) + } + + var title: String { + return "/u/\(username)" + } + +} diff --git a/iOS/AppAssets.swift b/iOS/AppAssets.swift index ffb89d13e..4cf633fb4 100644 --- a/iOS/AppAssets.swift +++ b/iOS/AppAssets.swift @@ -101,6 +101,10 @@ struct AppAssets { UIImage(systemName: "square.and.pencil")! }() + static var extensionPointReddit: RSImage = { + return RSImage(named: "extensionPointReddit")! + }() + static var extensionPointTwitter: UIImage = { return UIImage(named: "extensionPointTwitter")! }() diff --git a/iOS/Resources/Assets.xcassets/extensionPointReddit.imageset/Contents.json b/iOS/Resources/Assets.xcassets/extensionPointReddit.imageset/Contents.json new file mode 100644 index 000000000..08e567354 --- /dev/null +++ b/iOS/Resources/Assets.xcassets/extensionPointReddit.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "reddit-logo.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/iOS/Resources/Assets.xcassets/extensionPointReddit.imageset/reddit-logo.pdf b/iOS/Resources/Assets.xcassets/extensionPointReddit.imageset/reddit-logo.pdf new file mode 100644 index 000000000..b4b6d7419 Binary files /dev/null and b/iOS/Resources/Assets.xcassets/extensionPointReddit.imageset/reddit-logo.pdf differ