Merge remote-tracking branch 'upstream/master'
# Conflicts: # iOS/AppAssets.swift
This commit is contained in:
commit
7d226c46a4
|
@ -33,7 +33,7 @@ public enum AccountType: Int {
|
||||||
case feedbin = 17
|
case feedbin = 17
|
||||||
case feedWrangler = 18
|
case feedWrangler = 18
|
||||||
case newsBlur = 19
|
case newsBlur = 19
|
||||||
case readerAPI = 20
|
case freshRSS = 20
|
||||||
// TODO: more
|
// TODO: more
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||||
self.delegate = LocalAccountDelegate()
|
self.delegate = LocalAccountDelegate()
|
||||||
case .feedbin:
|
case .feedbin:
|
||||||
self.delegate = FeedbinAccountDelegate(dataFolder: dataFolder, transport: transport)
|
self.delegate = FeedbinAccountDelegate(dataFolder: dataFolder, transport: transport)
|
||||||
case .readerAPI:
|
case .freshRSS:
|
||||||
self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport)
|
self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport)
|
||||||
default:
|
default:
|
||||||
fatalError("Only Local and Feedbin accounts are supported")
|
fatalError("Only Local and Feedbin accounts are supported")
|
||||||
|
@ -250,8 +250,8 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||||
defaultName = "FeedWrangler"
|
defaultName = "FeedWrangler"
|
||||||
case .newsBlur:
|
case .newsBlur:
|
||||||
defaultName = "NewsBlur"
|
defaultName = "NewsBlur"
|
||||||
case .readerAPI:
|
case .freshRSS:
|
||||||
defaultName = "Reader API"
|
defaultName = "FreshRSS"
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(downloadProgressDidChange(_:)), name: .DownloadProgressDidChange, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(downloadProgressDidChange(_:)), name: .DownloadProgressDidChange, object: nil)
|
||||||
|
@ -295,34 +295,40 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func retrieveBasicCredentials() throws -> Credentials? {
|
public func retrieveCredentials() throws -> Credentials? {
|
||||||
guard let username = self.username, let server = delegate.server else {
|
switch type {
|
||||||
|
case .feedbin:
|
||||||
|
guard let username = self.username, let server = delegate.server else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return try CredentialsManager.retrieveBasicCredentials(server: server, username: username)
|
||||||
|
case .freshRSS:
|
||||||
|
guard let username = self.username, let server = delegate.server else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return try CredentialsManager.retrieveReaderAPIAuthCredentials(server: server, username: username)
|
||||||
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return try CredentialsManager.retrieveBasicCredentials(server: server, username: username)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func removeBasicCredentials() throws {
|
public func removeCredentials() throws {
|
||||||
guard let username = self.username, let server = delegate.server else {
|
switch type {
|
||||||
return
|
case .feedbin:
|
||||||
|
guard let username = self.username, let server = delegate.server else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try CredentialsManager.removeBasicCredentials(server: server, username: username)
|
||||||
|
self.username = nil
|
||||||
|
case .freshRSS:
|
||||||
|
guard let username = self.username, let server = delegate.server else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try CredentialsManager.removeReaderAPIAuthCredentials(server: server, username: username)
|
||||||
|
self.username = nil
|
||||||
|
default:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
try CredentialsManager.removeBasicCredentials(server: server, username: username)
|
|
||||||
self.username = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
public func retrieveReaderAPIAuthCredentials() throws -> Credentials? {
|
|
||||||
guard let username = self.username, let server = delegate.server else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return try CredentialsManager.retrieveReaderAPIAuthCredentials(server: server, username: username)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func removeReaderAPIAuthCredentials() throws {
|
|
||||||
guard let username = self.username, let server = delegate.server else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
try CredentialsManager.removeReaderAPIAuthCredentials(server: server, username: username)
|
|
||||||
self.username = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func validateCredentials(transport: Transport = URLSession.webserviceTransport(), type: AccountType, credentials: Credentials, endpoint: URL? = nil, completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
public static func validateCredentials(transport: Transport = URLSession.webserviceTransport(), type: AccountType, credentials: Credentials, endpoint: URL? = nil, completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
||||||
|
@ -331,7 +337,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||||
LocalAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion)
|
LocalAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion)
|
||||||
case .feedbin:
|
case .feedbin:
|
||||||
FeedbinAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion)
|
FeedbinAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion)
|
||||||
case .readerAPI:
|
case .freshRSS:
|
||||||
ReaderAPIAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint, completion: completion)
|
ReaderAPIAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint, completion: completion)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
|
|
@ -55,7 +55,7 @@ final class FeedbinAPICaller: NSObject {
|
||||||
switch error {
|
switch error {
|
||||||
case TransportError.httpError(let status):
|
case TransportError.httpError(let status):
|
||||||
if status == 401 {
|
if status == 401 {
|
||||||
completion(.success(self.credentials))
|
completion(.success(nil))
|
||||||
} else {
|
} else {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
|
|
@ -510,7 +510,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
func accountDidInitialize(_ account: Account) {
|
func accountDidInitialize(_ account: Account) {
|
||||||
credentials = try? account.retrieveBasicCredentials()
|
credentials = try? account.retrieveCredentials()
|
||||||
accountMetadata = account.metadata
|
accountMetadata = account.metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -411,7 +411,7 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
|
||||||
|
|
||||||
func accountDidInitialize(_ account: Account) {
|
func accountDidInitialize(_ account: Account) {
|
||||||
accountMetadata = account.metadata
|
accountMetadata = account.metadata
|
||||||
credentials = try? account.retrieveReaderAPIAuthCredentials()
|
credentials = try? account.retrieveCredentials()
|
||||||
}
|
}
|
||||||
|
|
||||||
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, completion: @escaping (Result<Credentials?, Error>) -> Void) {
|
||||||
|
|
|
@ -34,8 +34,8 @@ struct AppAssets {
|
||||||
return RSImage(named: "accountFeedbin")
|
return RSImage(named: "accountFeedbin")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var accountReader: RSImage! = {
|
static var accountFreshRSS: RSImage! = {
|
||||||
return RSImage(named: "accountReader")
|
return RSImage(named: "accountFreshRSS")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var faviconTemplateImage: RSImage = {
|
static var faviconTemplateImage: RSImage = {
|
||||||
|
|
|
@ -64,8 +64,8 @@ extension AccountsAddViewController: NSTableViewDelegate {
|
||||||
cell.accountNameLabel?.stringValue = NSLocalizedString("Feedbin", comment: "Feedbin")
|
cell.accountNameLabel?.stringValue = NSLocalizedString("Feedbin", comment: "Feedbin")
|
||||||
cell.accountImageView?.image = AppAssets.accountFeedbin
|
cell.accountImageView?.image = AppAssets.accountFeedbin
|
||||||
case 2:
|
case 2:
|
||||||
cell.accountNameLabel?.stringValue = NSLocalizedString("Reader API", comment: "Reader API")
|
cell.accountNameLabel?.stringValue = NSLocalizedString("FreshRSS", comment: "FreshRSS")
|
||||||
cell.accountImageView?.image = AppAssets.accountReader
|
cell.accountImageView?.image = AppAssets.accountFreshRSS
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ extension AccountsAddViewController: NSTableViewDelegate {
|
||||||
accountsAddWindowController = accountsFeedbinWindowController
|
accountsAddWindowController = accountsFeedbinWindowController
|
||||||
case 2:
|
case 2:
|
||||||
let accountsReaderAPIWindowController = AccountsReaderAPIWindowController()
|
let accountsReaderAPIWindowController = AccountsReaderAPIWindowController()
|
||||||
|
accountsReaderAPIWindowController.accountType = .freshRSS
|
||||||
accountsReaderAPIWindowController.runSheetOnWindow(self.view.window!)
|
accountsReaderAPIWindowController.runSheetOnWindow(self.view.window!)
|
||||||
accountsAddWindowController = accountsReaderAPIWindowController
|
accountsAddWindowController = accountsReaderAPIWindowController
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -27,10 +27,9 @@ class AccountsFeedbinWindowController: NSWindowController {
|
||||||
}
|
}
|
||||||
|
|
||||||
override func windowDidLoad() {
|
override func windowDidLoad() {
|
||||||
if let account = account, let credentials = try? account.retrieveBasicCredentials() {
|
if let account = account, let credentials = try? account.retrieveCredentials() {
|
||||||
if case .basic(let username, let password) = credentials {
|
if case .basic(let username, _) = credentials {
|
||||||
usernameTextField.stringValue = username
|
usernameTextField.stringValue = username
|
||||||
passwordTextField.stringValue = password
|
|
||||||
}
|
}
|
||||||
actionButton.title = NSLocalizedString("Update", comment: "Update")
|
actionButton.title = NSLocalizedString("Update", comment: "Update")
|
||||||
} else {
|
} else {
|
||||||
|
@ -87,7 +86,7 @@ class AccountsFeedbinWindowController: NSWindowController {
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try self.account?.removeBasicCredentials()
|
try self.account?.removeCredentials()
|
||||||
try self.account?.storeCredentials(validatedCredentials)
|
try self.account?.storeCredentials(validatedCredentials)
|
||||||
if newAccount {
|
if newAccount {
|
||||||
self.account?.refreshAll() { result in
|
self.account?.refreshAll() { result in
|
||||||
|
|
|
@ -107,8 +107,8 @@ extension AccountsPreferencesViewController: NSTableViewDelegate {
|
||||||
cell.imageView?.image = AppAssets.accountLocal
|
cell.imageView?.image = AppAssets.accountLocal
|
||||||
case .feedbin:
|
case .feedbin:
|
||||||
cell.imageView?.image = NSImage(named: "accountFeedbin")
|
cell.imageView?.image = NSImage(named: "accountFeedbin")
|
||||||
case .readerAPI:
|
case .freshRSS:
|
||||||
cell.imageView?.image = AppAssets.accountReader
|
cell.imageView?.image = AppAssets.accountFreshRSS
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
<outlet property="errorMessageLabel" destination="byK-Sd-r7F" id="8zt-9d-dWQ"/>
|
<outlet property="errorMessageLabel" destination="byK-Sd-r7F" id="8zt-9d-dWQ"/>
|
||||||
<outlet property="passwordTextField" destination="JSa-LY-zNQ" id="E9W-0F-69m"/>
|
<outlet property="passwordTextField" destination="JSa-LY-zNQ" id="E9W-0F-69m"/>
|
||||||
<outlet property="progressIndicator" destination="B0W-bh-Evv" id="Tiq-gx-s3F"/>
|
<outlet property="progressIndicator" destination="B0W-bh-Evv" id="Tiq-gx-s3F"/>
|
||||||
|
<outlet property="titleImageView" destination="Ssh-Dh-xbg" id="8Iy-jf-EYR"/>
|
||||||
|
<outlet property="titleLabel" destination="lti-yM-8LV" id="AP0-ds-6tS"/>
|
||||||
<outlet property="usernameTextField" destination="78p-Cf-f55" id="RWd-0q-oAL"/>
|
<outlet property="usernameTextField" destination="78p-Cf-f55" id="RWd-0q-oAL"/>
|
||||||
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
@ -37,7 +39,7 @@
|
||||||
<constraint firstAttribute="height" constant="36" id="Ern-Kk-8LX"/>
|
<constraint firstAttribute="height" constant="36" id="Ern-Kk-8LX"/>
|
||||||
<constraint firstAttribute="width" constant="36" id="PLS-68-NMc"/>
|
<constraint firstAttribute="width" constant="36" id="PLS-68-NMc"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="accountReader" id="y38-YL-woC"/>
|
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="y38-YL-woC"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lti-yM-8LV">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lti-yM-8LV">
|
||||||
<rect key="frame" x="53" y="0.0" width="156" height="38"/>
|
<rect key="frame" x="53" y="0.0" width="156" height="38"/>
|
||||||
|
@ -205,7 +207,4 @@ Gw
|
||||||
<point key="canvasLocation" x="116.5" y="136.5"/>
|
<point key="canvasLocation" x="116.5" y="136.5"/>
|
||||||
</window>
|
</window>
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
|
||||||
<image name="accountReader" width="73" height="73"/>
|
|
||||||
</resources>
|
|
||||||
</document>
|
</document>
|
||||||
|
|
|
@ -12,6 +12,9 @@ import RSWeb
|
||||||
|
|
||||||
class AccountsReaderAPIWindowController: NSWindowController {
|
class AccountsReaderAPIWindowController: NSWindowController {
|
||||||
|
|
||||||
|
@IBOutlet weak var titleImageView: NSImageView!
|
||||||
|
@IBOutlet weak var titleLabel: NSTextField!
|
||||||
|
|
||||||
@IBOutlet weak var progressIndicator: NSProgressIndicator!
|
@IBOutlet weak var progressIndicator: NSProgressIndicator!
|
||||||
@IBOutlet weak var usernameTextField: NSTextField!
|
@IBOutlet weak var usernameTextField: NSTextField!
|
||||||
@IBOutlet weak var apiURLTextField: NSTextField!
|
@IBOutlet weak var apiURLTextField: NSTextField!
|
||||||
|
@ -20,6 +23,7 @@ class AccountsReaderAPIWindowController: NSWindowController {
|
||||||
@IBOutlet weak var actionButton: NSButton!
|
@IBOutlet weak var actionButton: NSButton!
|
||||||
|
|
||||||
var account: Account?
|
var account: Account?
|
||||||
|
var accountType: AccountType?
|
||||||
|
|
||||||
private weak var hostWindow: NSWindow?
|
private weak var hostWindow: NSWindow?
|
||||||
|
|
||||||
|
@ -28,10 +32,19 @@ class AccountsReaderAPIWindowController: NSWindowController {
|
||||||
}
|
}
|
||||||
|
|
||||||
override func windowDidLoad() {
|
override func windowDidLoad() {
|
||||||
if let account = account, let credentials = try? account.retrieveBasicCredentials() {
|
if let accountType = accountType {
|
||||||
if case .basic(let username, let password) = credentials {
|
switch accountType {
|
||||||
|
case .freshRSS:
|
||||||
|
titleImageView.image = AppAssets.accountFreshRSS
|
||||||
|
titleLabel.stringValue = NSLocalizedString("FreshRSS", comment: "FreshRSS")
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let account = account, let credentials = try? account.retrieveCredentials() {
|
||||||
|
if case .basic(let username, _) = credentials {
|
||||||
usernameTextField.stringValue = username
|
usernameTextField.stringValue = username
|
||||||
passwordTextField.stringValue = password
|
|
||||||
}
|
}
|
||||||
actionButton.title = NSLocalizedString("Update", comment: "Update")
|
actionButton.title = NSLocalizedString("Update", comment: "Update")
|
||||||
} else {
|
} else {
|
||||||
|
@ -71,7 +84,7 @@ class AccountsReaderAPIWindowController: NSWindowController {
|
||||||
}
|
}
|
||||||
|
|
||||||
let credentials = Credentials.readerAPIBasicLogin(username: usernameTextField.stringValue, password: passwordTextField.stringValue)
|
let credentials = Credentials.readerAPIBasicLogin(username: usernameTextField.stringValue, password: passwordTextField.stringValue)
|
||||||
Account.validateCredentials(type: .readerAPI, credentials: credentials, endpoint: apiURL) { [weak self] result in
|
Account.validateCredentials(type: accountType!, credentials: credentials, endpoint: apiURL) { [weak self] result in
|
||||||
|
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
@ -89,14 +102,14 @@ class AccountsReaderAPIWindowController: NSWindowController {
|
||||||
|
|
||||||
var newAccount = false
|
var newAccount = false
|
||||||
if self.account == nil {
|
if self.account == nil {
|
||||||
self.account = AccountManager.shared.createAccount(type: .readerAPI)
|
self.account = AccountManager.shared.createAccount(type: self.accountType!)
|
||||||
newAccount = true
|
newAccount = true
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
self.account?.endpointURL = apiURL
|
self.account?.endpointURL = apiURL
|
||||||
|
|
||||||
try self.account?.removeReaderAPIAuthCredentials()
|
try self.account?.removeCredentials()
|
||||||
try self.account?.storeCredentials(validatedCredentials)
|
try self.account?.storeCredentials(validatedCredentials)
|
||||||
|
|
||||||
if newAccount {
|
if newAccount {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"filename" : "accountReader.pdf"
|
"filename" : "accountFreshRSS.pdf"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
Binary file not shown.
|
@ -142,8 +142,8 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta
|
||||||
osType = "FWrg"
|
osType = "FWrg"
|
||||||
case .newsBlur:
|
case .newsBlur:
|
||||||
osType = "NBlr"
|
osType = "NBlr"
|
||||||
case .readerAPI:
|
case .freshRSS:
|
||||||
osType = "Grdr"
|
osType = "Frsh"
|
||||||
}
|
}
|
||||||
return osType.fourCharCode()
|
return osType.fourCharCode()
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ private extension RSImage {
|
||||||
let rect = CGRect(x: 0, y: 0, width: avatarSize, height: avatarSize)
|
let rect = CGRect(x: 0, y: 0, width: avatarSize, height: avatarSize)
|
||||||
UIGraphicsBeginImageContext(rect.size)
|
UIGraphicsBeginImageContext(rect.size)
|
||||||
if let context = UIGraphicsGetCurrentContext() {
|
if let context = UIGraphicsGetCurrentContext() {
|
||||||
context.setFillColor(AppAssets.avatarLightBackgroundColor.cgColor)
|
context.setFillColor(AppAssets.avatarBackgroundColor.cgColor)
|
||||||
context.fill(rect)
|
context.fill(rect)
|
||||||
context.translateBy(x: 0.0, y: CGFloat(integerLiteral: avatarSize));
|
context.translateBy(x: 0.0, y: CGFloat(integerLiteral: avatarSize));
|
||||||
context.scaleBy(x: 1.0, y: -1.0)
|
context.scaleBy(x: 1.0, y: -1.0)
|
||||||
|
|
|
@ -10,34 +10,30 @@ import RSCore
|
||||||
|
|
||||||
struct AppAssets {
|
struct AppAssets {
|
||||||
|
|
||||||
static var avatarDarkBackgroundColor: UIColor {
|
static var avatarBackgroundColor: UIColor = {
|
||||||
return UIColor(named: "avatarDarkBackgroundColor")!
|
return UIColor(named: "avatarBackgroundColor")!
|
||||||
}
|
}()
|
||||||
|
|
||||||
static var avatarLightBackgroundColor: UIColor {
|
static var circleClosedImage: RSImage = {
|
||||||
return UIColor(named: "avatarLightBackgroundColor")!
|
return RSImage(named: "circleClosedImage")!
|
||||||
}
|
|
||||||
|
|
||||||
static var circleClosedImage: UIImage = {
|
|
||||||
return UIImage(systemName: "circle.fill")!
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var circleOpenImage: UIImage = {
|
static var circleOpenImage: RSImage = {
|
||||||
return UIImage(systemName: "circle")!
|
return RSImage(named: "circleOpenImage")!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var chevronDisclosureColor: UIColor = {
|
static var chevronDisclosureColor: UIColor = {
|
||||||
return UIColor(named: "chevronDisclosureColor")!
|
return UIColor(named: "chevronDisclosureColor")!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var chevronDownImage: UIImage = {
|
static var chevronDownImage: RSImage = {
|
||||||
let image = UIImage(systemName: "chevron.down")!
|
let image = RSImage(named: "chevronDownImage")!
|
||||||
return image.withTintColor(AppAssets.chevronDisclosureColor, renderingMode: .alwaysOriginal)
|
return image.maskWithColor(color: AppAssets.chevronDisclosureColor.cgColor)!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var chevronRightImage: UIImage = {
|
static var chevronRightImage: RSImage = {
|
||||||
let image = UIImage(systemName: "chevron.right")!
|
let image = RSImage(named: "chevronRightImage")!
|
||||||
return image.withTintColor(AppAssets.chevronDisclosureColor, renderingMode: .alwaysOriginal)
|
return image.maskWithColor(color: AppAssets.chevronDisclosureColor.cgColor)!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var faviconTemplateImage: RSImage = {
|
static var faviconTemplateImage: RSImage = {
|
||||||
|
@ -52,9 +48,9 @@ struct AppAssets {
|
||||||
return UIColor(named: "masterFolderColor")!
|
return UIColor(named: "masterFolderColor")!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var masterFolderImage: UIImage = {
|
static var masterFolderImage: RSImage = {
|
||||||
let image = UIImage(systemName: "folder.fill")!
|
let image = RSImage(systemName: "folder.fill")!
|
||||||
return image.withTintColor(AppAssets.masterFolderColor, renderingMode: .alwaysOriginal)
|
return image.maskWithColor(color: AppAssets.masterFolderColor.cgColor)!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var netNewsWireBlueColor: UIColor = {
|
static var netNewsWireBlueColor: UIColor = {
|
||||||
|
@ -65,26 +61,26 @@ struct AppAssets {
|
||||||
return UIColor(named: "smartFeedColor")!
|
return UIColor(named: "smartFeedColor")!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var smartFeedImage: UIImage = {
|
static var smartFeedImage: RSImage = {
|
||||||
let image = UIImage(systemName: "gear")!
|
let image = RSImage(named: "smartFeedImage")!
|
||||||
return image.withTintColor(AppAssets.smartFeedColor, renderingMode: .alwaysOriginal)
|
return image.maskWithColor(color: AppAssets.smartFeedColor.cgColor)!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var starColor: UIColor = {
|
static var starColor: UIColor = {
|
||||||
return UIColor(named: "starColor")!
|
return UIColor(named: "starColor")!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var starClosedImage: UIImage = {
|
static var starClosedImage: RSImage = {
|
||||||
return UIImage(systemName: "star.fill")!
|
return RSImage(named: "starClosedImage")!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var starOpenImage: UIImage = {
|
static var starOpenImage: RSImage = {
|
||||||
return UIImage(systemName: "star")!
|
return RSImage(named: "starOpenImage")!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var timelineStarImage: UIImage = {
|
static var timelineStarImage: RSImage = {
|
||||||
let image = UIImage(systemName: "star.fill")!
|
let image = RSImage(named: "starClosedImage")!
|
||||||
return image.withTintColor(AppAssets.starColor, renderingMode: .alwaysOriginal)
|
return image.maskWithColor(color: AppAssets.starColor.cgColor)!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var timelineUnreadCircleColor: UIColor = {
|
static var timelineUnreadCircleColor: UIColor = {
|
||||||
|
|
|
@ -73,6 +73,19 @@ class MasterTimelineViewController: ProgressTableViewController, UndoableCommand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||||
|
super.traitCollectionDidChange(previousTraitCollection)
|
||||||
|
|
||||||
|
if traitCollection.userInterfaceStyle != previousTraitCollection?.userInterfaceStyle {
|
||||||
|
appDelegate.authorAvatarDownloader.resetCache()
|
||||||
|
appDelegate.feedIconDownloader.resetCache()
|
||||||
|
appDelegate.faviconDownloader.resetCache()
|
||||||
|
performBlockAndRestoreSelection {
|
||||||
|
tableView.reloadData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK Actions
|
// MARK Actions
|
||||||
|
|
||||||
@IBAction func markAllAsRead(_ sender: Any) {
|
@IBAction func markAllAsRead(_ sender: Any) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ public final class NavigationProgressView: UIView {
|
||||||
|
|
||||||
internal let bar = UIView()
|
internal let bar = UIView()
|
||||||
|
|
||||||
@objc public dynamic var progressTintColor: UIColor? = UIColor(red: 0, green: 122/255, blue: 1, alpha: 1) {
|
@objc public dynamic var progressTintColor: UIColor? = AppAssets.netNewsWireBlueColor {
|
||||||
didSet {
|
didSet {
|
||||||
bar.backgroundColor = progressTintColor
|
bar.backgroundColor = progressTintColor
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "accountFreshRSS.pdf"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"template-rendering-intent" : "template"
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
},
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"red" : "242",
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "242",
|
||||||
|
"green" : "242"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"red" : "56",
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "56",
|
||||||
|
"green" : "56"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"info" : {
|
|
||||||
"version" : 1,
|
|
||||||
"author" : "xcode"
|
|
||||||
},
|
|
||||||
"colors" : [
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"color" : {
|
|
||||||
"color-space" : "srgb",
|
|
||||||
"components" : {
|
|
||||||
"red" : "56",
|
|
||||||
"alpha" : "1.000",
|
|
||||||
"blue" : "56",
|
|
||||||
"green" : "56"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"info" : {
|
|
||||||
"version" : 1,
|
|
||||||
"author" : "xcode"
|
|
||||||
},
|
|
||||||
"colors" : [
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"color" : {
|
|
||||||
"color-space" : "srgb",
|
|
||||||
"components" : {
|
|
||||||
"red" : "242",
|
|
||||||
"alpha" : "1.000",
|
|
||||||
"blue" : "242",
|
|
||||||
"green" : "242"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -93,7 +93,7 @@ struct SettingsFeedbinAccountView : View {
|
||||||
do {
|
do {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try workAccount.removeBasicCredentials()
|
try workAccount.removeCredentials()
|
||||||
} catch {}
|
} catch {}
|
||||||
try workAccount.storeCredentials(credentials)
|
try workAccount.storeCredentials(credentials)
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ struct SettingsFeedbinAccountView : View {
|
||||||
|
|
||||||
init(account: Account) {
|
init(account: Account) {
|
||||||
self.account = account
|
self.account = account
|
||||||
if case .basic(let username, let password) = try? account.retrieveBasicCredentials() {
|
if case .basic(let username, let password) = try? account.retrieveCredentials() {
|
||||||
self.email = username
|
self.email = username
|
||||||
self.password = password
|
self.password = password
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ struct SettingsReaderAPIAccountView : View {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
List {
|
List {
|
||||||
Section(header:
|
Section(header:
|
||||||
SettingsAccountLabelView(accountImage: "accountLocal", accountLabel: "Google Reader Compatible").padding()
|
SettingsAccountLabelView(accountImage: "accountFreshRSS", accountLabel: "FreshRSS").padding()
|
||||||
) {
|
) {
|
||||||
HStack {
|
HStack {
|
||||||
Text("Email:")
|
Text("Email:")
|
||||||
|
@ -83,7 +83,7 @@ struct SettingsReaderAPIAccountView : View {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Account.validateCredentials(type: .readerAPI, credentials: credentials, endpoint: apiURL) { result in
|
Account.validateCredentials(type: viewModel.accountType, credentials: credentials, endpoint: apiURL) { result in
|
||||||
|
|
||||||
self.busy = false
|
self.busy = false
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ struct SettingsReaderAPIAccountView : View {
|
||||||
var newAccount = false
|
var newAccount = false
|
||||||
let workAccount: Account
|
let workAccount: Account
|
||||||
if self.viewModel.account == nil {
|
if self.viewModel.account == nil {
|
||||||
workAccount = AccountManager.shared.createAccount(type: .readerAPI)
|
workAccount = AccountManager.shared.createAccount(type: self.viewModel.accountType)
|
||||||
newAccount = true
|
newAccount = true
|
||||||
} else {
|
} else {
|
||||||
workAccount = self.viewModel.account!
|
workAccount = self.viewModel.account!
|
||||||
|
@ -104,7 +104,7 @@ struct SettingsReaderAPIAccountView : View {
|
||||||
do {
|
do {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try workAccount.removeBasicCredentials()
|
try workAccount.removeCredentials()
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
workAccount.endpointURL = apiURL
|
workAccount.endpointURL = apiURL
|
||||||
|
@ -139,14 +139,17 @@ struct SettingsReaderAPIAccountView : View {
|
||||||
|
|
||||||
class ViewModel: BindableObject {
|
class ViewModel: BindableObject {
|
||||||
let didChange = PassthroughSubject<ViewModel, Never>()
|
let didChange = PassthroughSubject<ViewModel, Never>()
|
||||||
|
var accountType: AccountType
|
||||||
var account: Account? = nil
|
var account: Account? = nil
|
||||||
|
|
||||||
init() {
|
init(accountType: AccountType) {
|
||||||
|
self.accountType = accountType
|
||||||
}
|
}
|
||||||
|
|
||||||
init(account: Account) {
|
init(accountType: AccountType, account: Account) {
|
||||||
self.account = account
|
self.account = account
|
||||||
if case .basic(let username, let password) = try? account.retrieveBasicCredentials() {
|
self.accountType = accountType
|
||||||
|
if case .basic(let username, let password) = try? account.retrieveCredentials() {
|
||||||
self.email = username
|
self.email = username
|
||||||
self.password = password
|
self.password = password
|
||||||
}
|
}
|
||||||
|
@ -181,7 +184,7 @@ struct SettingsReaderAPIAccountView : View {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
struct SettingsReaderAPIAccountView_Previews : PreviewProvider {
|
struct SettingsReaderAPIAccountView_Previews : PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
SettingsReaderAPIAccountView(viewModel: SettingsReaderAPIAccountView.ViewModel())
|
SettingsReaderAPIAccountView(viewModel: SettingsReaderAPIAccountView.ViewModel(accountType: .freshRSS))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,7 +30,7 @@ class FeedbinAccountViewController: UIViewController {
|
||||||
emailTextField.delegate = self
|
emailTextField.delegate = self
|
||||||
passwordTextField.delegate = self
|
passwordTextField.delegate = self
|
||||||
|
|
||||||
if let account = account, let credentials = try? account.retrieveBasicCredentials() {
|
if let account = account, let credentials = try? account.retrieveCredentials() {
|
||||||
actionButton.setTitle(NSLocalizedString("Update Credentials", comment: "Update Credentials"), for: .normal)
|
actionButton.setTitle(NSLocalizedString("Update Credentials", comment: "Update Credentials"), for: .normal)
|
||||||
if case .basic(let username, let password) = credentials {
|
if case .basic(let username, let password) = credentials {
|
||||||
emailTextField.text = username
|
emailTextField.text = username
|
||||||
|
@ -77,7 +77,7 @@ class FeedbinAccountViewController: UIViewController {
|
||||||
do {
|
do {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try self.account?.removeBasicCredentials()
|
try self.account?.removeCredentials()
|
||||||
} catch {}
|
} catch {}
|
||||||
try self.account?.storeCredentials(credentials)
|
try self.account?.storeCredentials(credentials)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue