diff --git a/Mac/AppAssets.swift b/Mac/AppAssets.swift
index c537ee21b..a9d62921f 100644
--- a/Mac/AppAssets.swift
+++ b/Mac/AppAssets.swift
@@ -40,6 +40,10 @@ struct AppAssets {
static var accountFreshRSS: RSImage! = {
return RSImage(named: "accountFreshRSS")
}()
+
+ static var accountNewsBlur: RSImage! = {
+ return RSImage(named: "accountNewsBlur")
+ }()
static var articleExtractor: RSImage! = {
return RSImage(named: "articleExtractor")
@@ -151,6 +155,8 @@ struct AppAssets {
return AppAssets.accountFeedWrangler
case .freshRSS:
return AppAssets.accountFreshRSS
+ case .newsBlur:
+ return AppAssets.accountNewsBlur
default:
return nil
}
diff --git a/Mac/Preferences/Accounts/AccountsAddViewController.swift b/Mac/Preferences/Accounts/AccountsAddViewController.swift
index 4923272be..1207852ce 100644
--- a/Mac/Preferences/Accounts/AccountsAddViewController.swift
+++ b/Mac/Preferences/Accounts/AccountsAddViewController.swift
@@ -17,7 +17,7 @@ class AccountsAddViewController: NSViewController {
private var accountsAddWindowController: NSWindowController?
#if DEBUG
- private var addableAccountTypes: [AccountType] = [.onMyMac, .cloudKit, .feedbin, .feedly, .feedWrangler, .freshRSS]
+ private var addableAccountTypes: [AccountType] = [.onMyMac, .cloudKit, .feedbin, .feedly, .feedWrangler, .freshRSS, .newsBlur]
#else
private var addableAccountTypes: [AccountType] = [.onMyMac, .feedbin, .feedly]
#endif
@@ -80,6 +80,9 @@ extension AccountsAddViewController: NSTableViewDelegate {
case .feedly:
cell.accountNameLabel?.stringValue = NSLocalizedString("Feedly", comment: "Feedly")
cell.accountImageView?.image = AppAssets.accountFeedly
+ case .newsBlur:
+ cell.accountNameLabel?.stringValue = NSLocalizedString("NewsBlur", comment: "NewsBlur")
+ cell.accountImageView?.image = AppAssets.accountNewsBlur
default:
break
}
@@ -127,6 +130,10 @@ extension AccountsAddViewController: NSTableViewDelegate {
addAccount.delegate = self
addAccount.presentationAnchor = self.view.window!
MainThreadOperationQueue.shared.add(addAccount)
+ case .newsBlur:
+ let accountsNewsBlurWindowController = AccountsNewsBlurWindowController()
+ accountsNewsBlurWindowController.runSheetOnWindow(self.view.window!)
+ accountsAddWindowController = accountsNewsBlurWindowController
default:
break
}
diff --git a/Mac/Preferences/Accounts/AccountsNewsBlur.xib b/Mac/Preferences/Accounts/AccountsNewsBlur.xib
new file mode 100644
index 000000000..3b6027ed8
--- /dev/null
+++ b/Mac/Preferences/Accounts/AccountsNewsBlur.xib
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NSAllRomanInputSourcesLocaleIdentifier
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Mac/Preferences/Accounts/AccountsNewsBlurWindowController.swift b/Mac/Preferences/Accounts/AccountsNewsBlurWindowController.swift
new file mode 100644
index 000000000..cae19a31a
--- /dev/null
+++ b/Mac/Preferences/Accounts/AccountsNewsBlurWindowController.swift
@@ -0,0 +1,110 @@
+//
+// AccountsNewsBlurWindowController.swift
+// NetNewsWire
+//
+// Created by Anh Quang Do on 2020-03-22.
+// Copyright (c) 2020 Ranchero Software. All rights reserved.
+//
+
+import AppKit
+import Account
+import RSWeb
+
+class AccountsNewsBlurWindowController: NSWindowController {
+ @IBOutlet weak var progressIndicator: NSProgressIndicator!
+ @IBOutlet weak var usernameTextField: NSTextField!
+ @IBOutlet weak var passwordTextField: NSSecureTextField!
+ @IBOutlet weak var errorMessageLabel: NSTextField!
+ @IBOutlet weak var actionButton: NSButton!
+
+ var account: Account?
+
+ private weak var hostWindow: NSWindow?
+
+ convenience init() {
+ self.init(windowNibName: NSNib.Name("AccountsNewsBlur"))
+ }
+
+ override func windowDidLoad() {
+ if let account = account, let credentials = try? account.retrieveCredentials(type: .newsBlurBasic) {
+ usernameTextField.stringValue = credentials.username
+ actionButton.title = NSLocalizedString("Update", comment: "Update")
+ } else {
+ actionButton.title = NSLocalizedString("Create", comment: "Create")
+ }
+ }
+
+ // MARK: API
+
+ func runSheetOnWindow(_ hostWindow: NSWindow, completion: ((NSApplication.ModalResponse) -> Void)? = nil) {
+ self.hostWindow = hostWindow
+ hostWindow.beginSheet(window!, completionHandler: completion)
+ }
+
+ // MARK: Actions
+
+ @IBAction func cancel(_ sender: Any) {
+ hostWindow!.endSheet(window!, returnCode: NSApplication.ModalResponse.cancel)
+ }
+
+ @IBAction func action(_ sender: Any) {
+ self.errorMessageLabel.stringValue = ""
+
+ guard !usernameTextField.stringValue.isEmpty else {
+ self.errorMessageLabel.stringValue = NSLocalizedString("Username required.", comment: "Credentials Error")
+ return
+ }
+
+ actionButton.isEnabled = false
+ progressIndicator.isHidden = false
+ progressIndicator.startAnimation(self)
+
+ let credentials = Credentials(type: .newsBlurBasic, username: usernameTextField.stringValue, secret: passwordTextField.stringValue)
+ Account.validateCredentials(type: .newsBlur, credentials: credentials) { [weak self] result in
+
+ guard let self = self else { return }
+
+ self.actionButton.isEnabled = true
+ self.progressIndicator.isHidden = true
+ self.progressIndicator.stopAnimation(self)
+
+ switch result {
+ case .success(let validatedCredentials):
+ guard let validatedCredentials = validatedCredentials else {
+ self.errorMessageLabel.stringValue = NSLocalizedString("Invalid email/password combination.", comment: "Credentials Error")
+ return
+ }
+ var newAccount = false
+ if self.account == nil {
+ self.account = AccountManager.shared.createAccount(type: .newsBlur)
+ newAccount = true
+ }
+
+ do {
+ try self.account?.removeCredentials(type: .newsBlurBasic)
+ try self.account?.removeCredentials(type: .newsBlurSessionId)
+ try self.account?.storeCredentials(credentials)
+ try self.account?.storeCredentials(validatedCredentials)
+ if newAccount {
+ self.account?.refreshAll() { result in
+ switch result {
+ case .success:
+ break
+ case .failure(let error):
+ NSApplication.shared.presentError(error)
+ }
+ }
+ }
+ self.hostWindow?.endSheet(self.window!, returnCode: NSApplication.ModalResponse.OK)
+ } catch {
+ self.errorMessageLabel.stringValue = NSLocalizedString("Keychain error while storing credentials.", comment: "Credentials Error")
+ }
+
+ case .failure:
+
+ self.errorMessageLabel.stringValue = NSLocalizedString("Network error. Try again later.", comment: "Credentials Error")
+
+ }
+ }
+ }
+}
diff --git a/Mac/Resources/Assets.xcassets/accountNewsBlur.imageset/Contents.json b/Mac/Resources/Assets.xcassets/accountNewsBlur.imageset/Contents.json
new file mode 100644
index 000000000..99f78349c
--- /dev/null
+++ b/Mac/Resources/Assets.xcassets/accountNewsBlur.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "newsblur-512.png"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+}
\ No newline at end of file
diff --git a/Mac/Resources/Assets.xcassets/accountNewsBlur.imageset/newsblur-512.png b/Mac/Resources/Assets.xcassets/accountNewsBlur.imageset/newsblur-512.png
new file mode 100644
index 000000000..5fab67691
Binary files /dev/null and b/Mac/Resources/Assets.xcassets/accountNewsBlur.imageset/newsblur-512.png differ
diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj
index 4cdb13a9d..9cc10115d 100644
--- a/NetNewsWire.xcodeproj/project.pbxproj
+++ b/NetNewsWire.xcodeproj/project.pbxproj
@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
+ 179DB1DFBCF9177104B12E0F /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; };
+ 179DB3CE822BFCC2D774D9F4 /* AccountsNewsBlurWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */; };
3B3A32A5238B820900314204 /* FeedWranglerAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */; };
3B826DCB2385C84800FC1ADB /* AccountsFeedWrangler.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */; };
3B826DCC2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */; };
@@ -665,6 +667,8 @@
B2B80778239C4C7000F191E0 /* RSImage-AppIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B8075D239C49D300F191E0 /* RSImage-AppIcons.swift */; };
B2B80779239C4C7300F191E0 /* RSImage-AppIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B8075D239C49D300F191E0 /* RSImage-AppIcons.swift */; };
B528F81E23333C7E00E735DD /* page.html in Resources */ = {isa = PBXBuildFile; fileRef = B528F81D23333C7E00E735DD /* page.html */; };
+ BDCB516724282C8A00102A80 /* AccountsNewsBlur.xib in Resources */ = {isa = PBXBuildFile; fileRef = BDCB514D24282C8A00102A80 /* AccountsNewsBlur.xib */; };
+ BDCB516824282C8A00102A80 /* AccountsNewsBlur.xib in Resources */ = {isa = PBXBuildFile; fileRef = BDCB514D24282C8A00102A80 /* AccountsNewsBlur.xib */; };
C5A6ED5223C9AF4300AB6BE2 /* TitleActivityItemSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5A6ED5123C9AF4300AB6BE2 /* TitleActivityItemSource.swift */; };
C5A6ED6D23C9B0C800AB6BE2 /* UIActivityViewController-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5A6ED6C23C9B0C800AB6BE2 /* UIActivityViewController-Extensions.swift */; };
D553738B20186C20006D8857 /* Article+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D553737C20186C1F006D8857 /* Article+Scriptability.swift */; };
@@ -1255,6 +1259,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsNewsBlurWindowController.swift; sourceTree = ""; };
3B3A328B238B820900314204 /* FeedWranglerAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerAccountViewController.swift; sourceTree = ""; };
3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsFeedWrangler.xib; sourceTree = ""; };
3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsFeedWranglerWindowController.swift; sourceTree = ""; };
@@ -1626,6 +1631,7 @@
B24EFD5923310109006C6242 /* WKPreferencesPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKPreferencesPrivate.h; sourceTree = ""; };
B2B8075D239C49D300F191E0 /* RSImage-AppIcons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RSImage-AppIcons.swift"; sourceTree = ""; };
B528F81D23333C7E00E735DD /* page.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = page.html; sourceTree = ""; };
+ BDCB514D24282C8A00102A80 /* AccountsNewsBlur.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsNewsBlur.xib; sourceTree = ""; };
C5A6ED5123C9AF4300AB6BE2 /* TitleActivityItemSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleActivityItemSource.swift; sourceTree = ""; };
C5A6ED6C23C9B0C800AB6BE2 /* UIActivityViewController-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIActivityViewController-Extensions.swift"; sourceTree = ""; };
D519E74722EE553300923F27 /* NetNewsWire_safariextension_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_safariextension_target.xcconfig; sourceTree = ""; };
@@ -2630,6 +2636,8 @@
5144EA4F227B8E4500D19003 /* AccountsFeedbinWindowController.swift */,
3B826DB02385C84800FC1ADB /* AccountsFeedWrangler.xib */,
3B826DCA2385C84800FC1ADB /* AccountsFeedWranglerWindowController.swift */,
+ BDCB514D24282C8A00102A80 /* AccountsNewsBlur.xib */,
+ 179DBBA2B22A659F81EED6F9 /* AccountsNewsBlurWindowController.swift */,
55E15BC1229D65A900D6602A /* AccountsReaderAPI.xib */,
55E15BCA229D65A900D6602A /* AccountsReaderAPIWindowController.swift */,
5144EA352279FC3D00D19003 /* AccountsAddLocal.xib */,
@@ -3501,6 +3509,7 @@
65ED4066235DEF6C0081F399 /* TimelineTableView.xib in Resources */,
65ED4067235DEF6C0081F399 /* page.html in Resources */,
65ED4068235DEF6C0081F399 /* MainWindow.storyboard in Resources */,
+ BDCB516824282C8A00102A80 /* AccountsNewsBlur.xib in Resources */,
3B826DCD2385C89600FC1ADB /* AccountsFeedWrangler.xib in Resources */,
65ED4069235DEF6C0081F399 /* AccountsReaderAPI.xib in Resources */,
65ED406A235DEF6C0081F399 /* newsfoot.js in Resources */,
@@ -3593,6 +3602,7 @@
3B826DCB2385C84800FC1ADB /* AccountsFeedWrangler.xib in Resources */,
55E15BCB229D65A900D6602A /* AccountsReaderAPI.xib in Resources */,
49F40DF82335B71000552BF4 /* newsfoot.js in Resources */,
+ BDCB516724282C8A00102A80 /* AccountsNewsBlur.xib in Resources */,
5103A9982421643300410853 /* blank.html in Resources */,
84BAE64921CEDAF20046DB56 /* CrashReporterWindow.xib in Resources */,
84C9FC8E22629E8F00D921D6 /* Credits.rtf in Resources */,
@@ -3909,6 +3919,7 @@
65ED403E235DEF6C0081F399 /* TimelineCellAppearance.swift in Sources */,
65ED403F235DEF6C0081F399 /* ArticleRenderer.swift in Sources */,
65ED4040235DEF6C0081F399 /* GeneralPrefencesViewController.swift in Sources */,
+ 179DB1DFBCF9177104B12E0F /* AccountsNewsBlurWindowController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -4226,6 +4237,7 @@
849A97761ED9EC04007D329B /* TimelineCellAppearance.swift in Sources */,
849A977F1ED9EC42007D329B /* ArticleRenderer.swift in Sources */,
84C9FC7822629E1200D921D6 /* GeneralPrefencesViewController.swift in Sources */,
+ 179DB3CE822BFCC2D774D9F4 /* AccountsNewsBlurWindowController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/iOS/Account/NewsBlurAccountViewController.swift b/iOS/Account/NewsBlurAccountViewController.swift
index 8a5cb2ddf..9810f8196 100644
--- a/iOS/Account/NewsBlurAccountViewController.swift
+++ b/iOS/Account/NewsBlurAccountViewController.swift
@@ -29,7 +29,7 @@ class NewsBlurAccountViewController: UITableViewController {
usernameTextField.delegate = self
passwordTextField.delegate = self
- if let account = account, let credentials = try? account.retrieveCredentials(type: .basic) {
+ if let account = account, let credentials = try? account.retrieveCredentials(type: .newsBlurBasic) {
actionButton.setTitle(NSLocalizedString("Update Credentials", comment: "Update Credentials"), for: .normal)
actionButton.isEnabled = true
usernameTextField.text = credentials.username
@@ -90,7 +90,7 @@ class NewsBlurAccountViewController: UITableViewController {
let credentials = Credentials(type: .newsBlurBasic, username: trimmedUsername, secret: password)
Account.validateCredentials(type: .newsBlur, credentials: credentials) { result in
- self.stopAnimtatingActivityIndicator()
+ self.stopAnimatingActivityIndicator()
self.enableNavigation()
switch result {
@@ -105,7 +105,7 @@ class NewsBlurAccountViewController: UITableViewController {
do {
do {
- try self.account?.removeCredentials(type: .basic)
+ try self.account?.removeCredentials(type: .newsBlurBasic)
} catch {}
try self.account?.storeCredentials(credentials)
@@ -158,7 +158,7 @@ class NewsBlurAccountViewController: UITableViewController {
activityIndicator.startAnimating()
}
- private func stopAnimtatingActivityIndicator() {
+ private func stopAnimatingActivityIndicator() {
self.activityIndicator.isHidden = true
self.activityIndicator.stopAnimating()
}