2019-11-25 06:26:03 +01:00
//
// F e e d W r a n g l e r 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
// N e t N e w s W i r e
//
// C r e a t e d b y J o n a t h a n B e n n e t t o n 2 0 1 9 - 1 1 - 2 4 .
// 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
import RSWeb
2020-04-16 15:25:40 +02:00
import Secrets
2020-11-09 14:31:29 +01:00
import SafariServices
2019-11-25 06:26:03 +01:00
class FeedWranglerAccountViewController : UITableViewController {
@IBOutlet weak var activityIndicator : UIActivityIndicatorView !
@IBOutlet weak var cancelBarButtonItem : UIBarButtonItem !
@IBOutlet weak var emailTextField : UITextField !
@IBOutlet weak var passwordTextField : UITextField !
@IBOutlet weak var showHideButton : UIButton !
@IBOutlet weak var actionButton : UIButton !
2020-11-09 14:41:05 +01:00
@IBOutlet weak var footerLabel : UILabel !
2019-11-25 06:26:03 +01:00
weak var account : Account ?
weak var delegate : AddAccountDismissDelegate ?
override func viewDidLoad ( ) {
super . viewDidLoad ( )
2020-11-09 14:41:05 +01:00
setupFooter ( )
2019-11-25 06:26:03 +01:00
activityIndicator . isHidden = true
emailTextField . delegate = self
passwordTextField . delegate = self
if let account = account , let credentials = try ? account . retrieveCredentials ( type : . feedWranglerBasic ) {
actionButton . setTitle ( NSLocalizedString ( " Update Credentials " , comment : " Update Credentials " ) , for : . normal )
emailTextField . text = credentials . username
passwordTextField . text = credentials . secret
} else {
actionButton . setTitle ( NSLocalizedString ( " Add Account " , comment : " Update Credentials " ) , for : . normal )
}
NotificationCenter . default . addObserver ( self , selector : #selector ( textDidChange ( _ : ) ) , name : UITextField . textDidChangeNotification , object : emailTextField )
NotificationCenter . default . addObserver ( self , selector : #selector ( textDidChange ( _ : ) ) , name : UITextField . textDidChangeNotification , object : passwordTextField )
tableView . register ( ImageHeaderView . self , forHeaderFooterViewReuseIdentifier : " SectionHeader " )
}
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 Feed Wrangler 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 Feed Wrangler account? " , comment : " Feed Wrangler " )
2020-11-09 14:41:05 +01:00
}
2019-11-25 06:26:03 +01:00
override func tableView ( _ tableView : UITableView , heightForHeaderInSection section : Int ) -> CGFloat {
return section = = 0 ? ImageHeaderView . rowHeight : super . tableView ( tableView , heightForHeaderInSection : section )
}
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 : . feedWrangler )
return headerView
} else {
return super . tableView ( tableView , viewForHeaderInSection : section )
}
}
@IBAction func cancel ( _ sender : Any ) {
dismiss ( animated : true , completion : nil )
}
@IBAction func showHidePassword ( _ sender : Any ) {
if passwordTextField . isSecureTextEntry {
passwordTextField . isSecureTextEntry = false
2019-11-25 11:16:20 +01:00
showHideButton . setTitle ( NSLocalizedString ( " Hide " , comment : " Button Label " ) , for : . normal )
2019-11-25 06:26:03 +01:00
} else {
passwordTextField . isSecureTextEntry = true
2019-11-25 11:16:20 +01:00
showHideButton . setTitle ( NSLocalizedString ( " Show " , comment : " Button Label " ) , for : . normal )
2019-11-25 06:26:03 +01:00
}
}
@IBAction func action ( _ sender : Any ) {
guard let email = emailTextField . text , let password = passwordTextField . text else {
showError ( NSLocalizedString ( " Username & password required. " , comment : " Credentials Error " ) )
return
}
2020-09-25 01:02:12 +02:00
// 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
let trimmedEmail = email . trimmingCharacters ( in : . whitespaces )
2020-10-29 20:05:55 +01:00
guard account != nil || ! AccountManager . shared . duplicateServiceAccount ( type : . feedWrangler , username : trimmedEmail ) else {
2020-09-25 01:02:12 +02:00
showError ( NSLocalizedString ( " There is already a FeedWrangler account with that username created. " , comment : " Duplicate Error " ) )
return
}
2020-03-11 13:42:25 +01:00
resignFirstResponder ( )
toggleActivityIndicatorAnimation ( visible : true )
setNavigationEnabled ( to : false )
2019-11-25 06:26:03 +01:00
let credentials = Credentials ( type : . feedWranglerBasic , username : trimmedEmail , secret : password )
Account . validateCredentials ( type : . feedWrangler , credentials : credentials ) { result in
2020-03-11 13:42:25 +01:00
self . toggleActivityIndicatorAnimation ( visible : false )
self . setNavigationEnabled ( to : true )
2019-11-25 06:26:03 +01:00
switch result {
case . success ( let validatedCredentials ) :
guard let validatedCredentials = validatedCredentials else {
self . showError ( NSLocalizedString ( " Invalid email/password combination. " , comment : " Credentials Error " ) )
return
}
if self . account = = nil {
self . account = AccountManager . shared . createAccount ( type : . feedWrangler )
}
do {
try self . account ? . removeCredentials ( type : . feedWranglerBasic )
try self . account ? . removeCredentials ( type : . feedWranglerToken )
try self . account ? . storeCredentials ( credentials )
try self . account ? . storeCredentials ( validatedCredentials )
2021-01-09 22:15:14 +01:00
self . account ? . refreshAll { result in
switch result {
case . success :
break
case . failure ( let error ) :
self . presentError ( error )
2019-11-25 06:26:03 +01:00
}
}
self . dismiss ( animated : true , completion : nil )
self . delegate ? . dismiss ( )
} catch {
self . showError ( NSLocalizedString ( " Keychain error while storing credentials. " , comment : " Credentials Error " ) )
}
case . failure :
self . showError ( NSLocalizedString ( " Network error. Try again later. " , comment : " Credentials Error " ) )
}
}
}
2020-11-09 14:31:29 +01:00
@IBAction func signUpWithProvider ( _ sender : Any ) {
let url = URL ( string : " https://feedwrangler.net/users/new " ) !
let safari = SFSafariViewController ( url : url )
safari . modalPresentationStyle = . currentContext
self . present ( safari , animated : true , completion : nil )
}
2019-11-25 06:26:03 +01:00
@objc func textDidChange ( _ note : Notification ) {
actionButton . isEnabled = ! ( emailTextField . text ? . isEmpty ? ? false ) && ! ( passwordTextField . text ? . isEmpty ? ? false )
}
2021-06-16 08:41:51 +02:00
2019-11-25 06:26:03 +01:00
private func showError ( _ message : String ) {
2020-03-11 13:42:25 +01:00
presentError ( title : NSLocalizedString ( " Error " , comment : " Credentials Error " ) , message : message )
2019-11-25 06:26:03 +01:00
}
2020-03-11 13:42:25 +01:00
private func setNavigationEnabled ( to value : Bool ) {
cancelBarButtonItem . isEnabled = value
actionButton . isEnabled = value
2019-11-25 06:26:03 +01: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-11-25 06:26:03 +01:00
}
}
extension FeedWranglerAccountViewController : 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-11-25 06:26:03 +01:00
return true
}
}