2019-10-21 18:51:33 +02:00
//
2019-10-21 20:44:47 +02:00
// F e e d b i n A c c o u n t V i e w C o n t r o l l e r . s w i f t
2019-10-21 18:51:33 +02:00
// N e t N e w s W i r e - i O S
//
// C r e a t e d b y M a u r i c e P a r k e r o n 5 / 1 9 / 1 9 .
// C o p y r i g h t © 2 0 1 9 R a n c h e r o S o f t w a r e . A l l r i g h t s r e s e r v e d .
//
import UIKit
import Account
2020-04-16 15:25:40 +02:00
import Secrets
2024-04-02 04:31:57 +02:00
import Web
2020-11-09 14:31:29 +01:00
import SafariServices
2019-10-21 18:51:33 +02:00
2019-10-22 03:28:50 +02:00
class FeedbinAccountViewController : UITableViewController {
2019-10-21 18:51:33 +02:00
@IBOutlet weak var activityIndicator : UIActivityIndicatorView !
@IBOutlet weak var cancelBarButtonItem : UIBarButtonItem !
@IBOutlet weak var emailTextField : UITextField !
@IBOutlet weak var passwordTextField : UITextField !
2019-10-21 20:44:47 +02:00
@IBOutlet weak var showHideButton : UIButton !
2019-10-21 18:51:33 +02:00
@IBOutlet weak var actionButton : UIButton !
2020-11-09 14:41:05 +01:00
@IBOutlet weak var footerLabel : UILabel !
2021-06-16 08:41:51 +02:00
@IBOutlet weak var onepasswordButton : UIBarButtonItem ! {
didSet {
onepasswordButton . image ? . withTintColor ( AppAssets . primaryAccentColor )
}
}
2019-10-21 18:51:33 +02:00
weak var account : Account ?
weak var delegate : AddAccountDismissDelegate ?
2024-03-11 06:22:41 +01:00
var secretsProvider : SecretsProvider !
2019-10-21 18:51:33 +02:00
override func viewDidLoad ( ) {
super . viewDidLoad ( )
2020-11-09 14:41:05 +01:00
setupFooter ( )
2019-10-21 18:51:33 +02:00
activityIndicator . isHidden = true
emailTextField . delegate = self
passwordTextField . delegate = self
if let account = account , let credentials = try ? account . retrieveCredentials ( type : . basic ) {
actionButton . setTitle ( NSLocalizedString ( " Update Credentials " , comment : " Update Credentials " ) , for : . normal )
2020-01-16 20:04:40 +01:00
actionButton . isEnabled = true
2019-10-21 18:51:33 +02:00
emailTextField . text = credentials . username
passwordTextField . text = credentials . secret
} else {
2020-01-16 20:04:40 +01:00
actionButton . setTitle ( NSLocalizedString ( " Add Account " , comment : " Add Account " ) , for : . normal )
2019-10-21 18:51:33 +02:00
}
2019-10-22 16:06:35 +02:00
NotificationCenter . default . addObserver ( self , selector : #selector ( textDidChange ( _ : ) ) , name : UITextField . textDidChangeNotification , object : emailTextField )
NotificationCenter . default . addObserver ( self , selector : #selector ( textDidChange ( _ : ) ) , name : UITextField . textDidChangeNotification , object : passwordTextField )
2019-11-16 22:47:12 +01:00
tableView . register ( ImageHeaderView . self , forHeaderFooterViewReuseIdentifier : " SectionHeader " )
2021-06-16 08:41:51 +02:00
if ! OnePasswordExtension . shared ( ) . isAppExtensionAvailable ( ) {
onepasswordButton . isEnabled = false
onepasswordButton . image ? . withTintColor ( . clear )
}
2019-11-16 22:47:12 +01:00
}
2020-11-09 14:41:05 +01:00
private func setupFooter ( ) {
2021-06-01 01:01:01 +02:00
footerLabel . text = NSLocalizedString ( " Sign in to your Feedbin account and sync your feeds across your devices. Your username and password will be encrypted and stored in Keychain. \n \n Don’ t have a Feedbin account? " , comment : " Feedbin " )
2020-11-09 14:41:05 +01:00
}
2019-11-16 22:47:12 +01:00
override func tableView ( _ tableView : UITableView , heightForHeaderInSection section : Int ) -> CGFloat {
2019-11-22 22:11:15 +01:00
return section = = 0 ? ImageHeaderView . rowHeight : super . tableView ( tableView , heightForHeaderInSection : section )
2019-10-21 18:51:33 +02:00
}
2019-11-16 22:47:12 +01:00
override func tableView ( _ tableView : UITableView , viewForHeaderInSection section : Int ) -> UIView ? {
if section = = 0 {
let headerView = tableView . dequeueReusableHeaderFooterView ( withIdentifier : " SectionHeader " ) as ! ImageHeaderView
headerView . imageView . image = AppAssets . image ( for : . feedbin )
return headerView
} else {
return super . tableView ( tableView , viewForHeaderInSection : section )
}
}
2019-10-21 18:51:33 +02:00
@IBAction func cancel ( _ sender : Any ) {
dismiss ( animated : true , completion : nil )
}
2021-06-16 08:41:51 +02:00
@IBAction func retrievePasswordDetailsFrom1Password ( _ sender : Any ) {
2021-06-17 06:38:53 +02:00
OnePasswordExtension . shared ( ) . findLogin ( forURLString : " feedbin.com " , for : self , sender : self ) { [ self ] loginDictionary , error in
2021-06-16 08:41:51 +02:00
if let loginDictionary = loginDictionary {
emailTextField . text = loginDictionary [ AppExtensionUsernameKey ] as ? String
passwordTextField . text = loginDictionary [ AppExtensionPasswordKey ] as ? String
actionButton . isEnabled = ! ( emailTextField . text ? . isEmpty ? ? false ) && ! ( passwordTextField . text ? . isEmpty ? ? false )
}
}
}
2019-10-21 20:44:47 +02:00
@IBAction func showHidePassword ( _ sender : Any ) {
if passwordTextField . isSecureTextEntry {
passwordTextField . isSecureTextEntry = false
showHideButton . setTitle ( " Hide " , for : . normal )
} else {
passwordTextField . isSecureTextEntry = true
showHideButton . setTitle ( " Show " , for : . normal )
}
}
2019-10-21 18:51:33 +02:00
@IBAction func action ( _ sender : Any ) {
2019-10-21 20:44:47 +02:00
guard let email = emailTextField . text , let password = passwordTextField . text else {
2019-10-22 03:28:50 +02:00
showError ( NSLocalizedString ( " Username & password required. " , comment : " Credentials Error " ) )
2019-10-21 18:51:33 +02:00
return
}
// W h e n y o u f i l l i n t h e e m a i l a d d r e s s v i a a u t o - c o m p l e t e i t a d d s e x t r a w h i t e s p a c e
2019-10-21 20:44:47 +02:00
let trimmedEmail = email . trimmingCharacters ( in : . whitespaces )
2020-09-25 01:02:12 +02:00
2020-10-29 18:01:27 +01:00
guard account != nil || ! AccountManager . shared . duplicateServiceAccount ( type : . feedbin , username : trimmedEmail ) else {
2020-09-25 01:02:12 +02:00
showError ( NSLocalizedString ( " There is already a Feedbin account with that username created. " , comment : " Duplicate Error " ) )
return
}
resignFirstResponder ( )
toggleActivityIndicatorAnimation ( visible : true )
setNavigationEnabled ( to : false )
2019-10-21 20:44:47 +02:00
let credentials = Credentials ( type : . basic , username : trimmedEmail , secret : password )
2024-03-11 06:22:41 +01:00
Account . validateCredentials ( type : . feedbin , credentials : credentials , secretsProvider : secretsProvider ) { result in
2020-03-11 13:42:25 +01:00
self . toggleActivityIndicatorAnimation ( visible : false )
self . setNavigationEnabled ( to : true )
2019-10-21 18:51:33 +02:00
switch result {
case . success ( let credentials ) :
if let credentials = credentials {
if self . account = = nil {
self . account = AccountManager . shared . createAccount ( type : . feedbin )
}
do {
do {
try self . account ? . removeCredentials ( type : . basic )
} catch { }
try self . account ? . storeCredentials ( credentials )
2024-03-27 01:31:46 +01:00
Task { @ MainActor in
do {
try await self . account ? . refreshAll ( )
} catch {
2021-01-09 22:15:14 +01:00
self . presentError ( error )
2019-10-21 18:51:33 +02:00
}
}
2024-03-27 01:31:46 +01:00
2019-10-21 18:51:33 +02:00
self . dismiss ( animated : true , completion : nil )
self . delegate ? . dismiss ( )
} catch {
2019-10-22 03:28:50 +02:00
self . showError ( NSLocalizedString ( " Keychain error while storing credentials. " , comment : " Credentials Error " ) )
2019-10-21 18:51:33 +02:00
}
} else {
2019-10-22 03:28:50 +02:00
self . showError ( NSLocalizedString ( " Invalid email/password combination. " , comment : " Credentials Error " ) )
2019-10-21 18:51:33 +02:00
}
case . failure :
2019-10-22 03:28:50 +02:00
self . showError ( NSLocalizedString ( " Network error. Try again later. " , comment : " Credentials Error " ) )
2019-10-21 18:51:33 +02:00
}
}
}
2020-11-09 14:31:29 +01:00
@IBAction func signUpWithProvider ( _ sender : Any ) {
let url = URL ( string : " https://feedbin.com/signup " ) !
let safari = SFSafariViewController ( url : url )
safari . modalPresentationStyle = . currentContext
self . present ( safari , animated : true , completion : nil )
}
2019-10-22 16:06:35 +02:00
@objc func textDidChange ( _ note : Notification ) {
actionButton . isEnabled = ! ( emailTextField . text ? . isEmpty ? ? false ) && ! ( passwordTextField . text ? . isEmpty ? ? false )
}
2019-10-22 03:28:50 +02:00
private func showError ( _ message : String ) {
2020-03-11 13:42:25 +01:00
presentError ( title : NSLocalizedString ( " Error " , comment : " Credentials Error " ) , message : message )
2019-10-21 18:51:33 +02:00
}
2020-03-11 13:42:25 +01:00
private func setNavigationEnabled ( to value : Bool ) {
cancelBarButtonItem . isEnabled = value
actionButton . isEnabled = value
2019-10-21 18:51:33 +02:00
}
2020-03-11 13:42:25 +01:00
private func toggleActivityIndicatorAnimation ( visible value : Bool ) {
activityIndicator . isHidden = ! value
if value {
activityIndicator . startAnimating ( )
} else {
activityIndicator . stopAnimating ( )
}
2019-10-21 18:51:33 +02:00
}
}
extension FeedbinAccountViewController : UITextFieldDelegate {
func textFieldShouldReturn ( _ textField : UITextField ) -> Bool {
2020-03-09 20:15:04 +01:00
if textField = = emailTextField {
passwordTextField . becomeFirstResponder ( )
} else {
textField . resignFirstResponder ( )
2020-03-11 14:02:06 +01:00
action ( self )
2020-03-09 20:15:04 +01:00
}
2019-10-21 18:51:33 +02:00
return true
}
}