2019-06-06 14:46:23 -07:00
//
2019-09-05 11:59:10 -07:00
// S e t t i n g s V i e w C o n t r o l l e r . s w i f t
2019-06-06 14:46:23 -07:00
// A l t S t o r e
//
2019-09-05 11:59:10 -07:00
// C r e a t e d b y R i l e y T e s t u t o n 8 / 3 1 / 1 9 .
2019-06-06 14:46:23 -07:00
// C o p y r i g h t © 2 0 1 9 R i l e y T e s t u t . A l l r i g h t s r e s e r v e d .
//
import UIKit
2019-09-07 15:34:07 -07:00
import SafariServices
2019-09-12 13:23:21 -07:00
import MessageUI
2019-06-06 14:46:23 -07:00
2019-09-05 11:59:10 -07:00
extension SettingsViewController
{
fileprivate enum Section : Int , CaseIterable
{
case signIn
case account
case patreon
case backgroundRefresh
2019-09-07 15:34:07 -07:00
case instructions
case credits
2019-09-05 11:59:10 -07:00
case debug
}
2019-09-07 15:34:07 -07:00
fileprivate enum CreditsRow : Int , CaseIterable
{
case developer
case designer
case softwareLicenses
}
2019-09-12 13:23:21 -07:00
fileprivate enum DebugRow : Int , CaseIterable
{
case sendFeedback
case refreshAttempts
}
2019-09-05 11:59:10 -07:00
}
2019-06-06 14:46:23 -07:00
2019-07-31 11:46:26 -07:00
class SettingsViewController : UITableViewController
2019-06-06 14:46:23 -07:00
{
2019-09-05 11:59:10 -07:00
private var activeTeam : Team ?
2019-06-06 14:46:23 -07:00
2019-09-05 11:59:10 -07:00
private var prototypeHeaderFooterView : SettingsHeaderFooterView !
2019-06-06 14:46:23 -07:00
2019-09-05 11:59:10 -07:00
@IBOutlet private var accountNameLabel : UILabel !
@IBOutlet private var accountEmailLabel : UILabel !
@IBOutlet private var accountTypeLabel : UILabel !
2019-06-06 14:46:23 -07:00
2019-09-05 11:59:10 -07:00
@IBOutlet private var backgroundRefreshSwitch : UISwitch !
2019-06-06 14:46:23 -07:00
override func viewDidLoad ( )
{
super . viewDidLoad ( )
2019-09-05 11:59:10 -07:00
let nib = UINib ( nibName : " SettingsHeaderFooterView " , bundle : nil )
self . prototypeHeaderFooterView = nib . instantiate ( withOwner : nil , options : nil ) [ 0 ] as ? SettingsHeaderFooterView
self . tableView . register ( nib , forHeaderFooterViewReuseIdentifier : " HeaderFooterView " )
2019-06-06 14:46:23 -07:00
self . update ( )
}
2019-09-07 15:34:07 -07:00
override func viewWillAppear ( _ animated : Bool )
{
super . viewWillAppear ( animated )
self . update ( )
}
2019-06-06 14:46:23 -07:00
}
2019-07-31 11:46:26 -07:00
private extension SettingsViewController
2019-06-06 14:46:23 -07:00
{
func update ( )
{
if let team = DatabaseManager . shared . activeTeam ( )
{
2019-09-05 11:59:10 -07:00
self . accountNameLabel . text = team . name
2019-06-06 14:46:23 -07:00
self . accountEmailLabel . text = team . account . appleID
2019-09-05 11:59:10 -07:00
self . accountTypeLabel . text = team . type . localizedDescription
2019-06-06 14:46:23 -07:00
2019-09-05 11:59:10 -07:00
self . activeTeam = team
2019-06-06 14:46:23 -07:00
}
else
{
2019-09-05 11:59:10 -07:00
self . activeTeam = nil
2019-06-06 14:46:23 -07:00
}
2019-09-05 11:59:10 -07:00
self . backgroundRefreshSwitch . isOn = UserDefaults . standard . isBackgroundRefreshEnabled
2019-06-06 14:46:23 -07:00
if self . isViewLoaded
{
self . tableView . reloadData ( )
}
}
2019-09-05 11:59:10 -07:00
func prepare ( _ settingsHeaderFooterView : SettingsHeaderFooterView , for section : Section , isHeader : Bool )
{
settingsHeaderFooterView . primaryLabel . isHidden = ! isHeader
settingsHeaderFooterView . secondaryLabel . isHidden = isHeader
settingsHeaderFooterView . button . isHidden = true
settingsHeaderFooterView . layoutMargins . bottom = isHeader ? 0 : 8
switch section
{
case . signIn :
if isHeader
{
settingsHeaderFooterView . primaryLabel . text = NSLocalizedString ( " ACCOUNT " , comment : " " )
}
else
{
settingsHeaderFooterView . secondaryLabel . text = NSLocalizedString ( " Sign in with your Apple ID to download apps from AltStore. " , comment : " " )
}
case . patreon :
2019-09-10 12:33:14 -07:00
settingsHeaderFooterView . secondaryLabel . text = NSLocalizedString ( " Receive access to beta versions of AltStore, Delta, and more by becoming a patron. " , comment : " " )
2019-09-05 11:59:10 -07:00
case . account :
settingsHeaderFooterView . primaryLabel . text = NSLocalizedString ( " ACCOUNT " , comment : " " )
settingsHeaderFooterView . button . setTitle ( NSLocalizedString ( " SIGN OUT " , comment : " " ) , for : . normal )
settingsHeaderFooterView . button . addTarget ( self , action : #selector ( SettingsViewController . signOut ( _ : ) ) , for : . primaryActionTriggered )
settingsHeaderFooterView . button . isHidden = false
case . backgroundRefresh :
settingsHeaderFooterView . secondaryLabel . text = NSLocalizedString ( " Automatically refresh apps in the background when connected to the same WiFi as AltServer. " , comment : " " )
2019-09-07 15:34:07 -07:00
case . instructions :
break
case . credits :
settingsHeaderFooterView . primaryLabel . text = NSLocalizedString ( " CREDITS " , comment : " " )
2019-09-05 11:59:10 -07:00
case . debug :
settingsHeaderFooterView . primaryLabel . text = NSLocalizedString ( " DEBUG " , comment : " " )
}
}
func preferredHeight ( for settingsHeaderFooterView : SettingsHeaderFooterView , in section : Section , isHeader : Bool ) -> CGFloat
{
let widthConstraint = settingsHeaderFooterView . contentView . widthAnchor . constraint ( equalToConstant : tableView . bounds . width )
NSLayoutConstraint . activate ( [ widthConstraint ] )
defer { NSLayoutConstraint . deactivate ( [ widthConstraint ] ) }
self . prepare ( settingsHeaderFooterView , for : section , isHeader : isHeader )
let size = settingsHeaderFooterView . contentView . systemLayoutSizeFitting ( UIView . layoutFittingCompressedSize )
return size . height
}
2019-06-06 14:46:23 -07:00
}
2019-07-31 11:46:26 -07:00
private extension SettingsViewController
2019-06-06 14:46:23 -07:00
{
2019-09-05 11:59:10 -07:00
func signIn ( )
2019-06-06 14:46:23 -07:00
{
AppManager . shared . authenticate ( presentingViewController : self ) { ( result ) in
DispatchQueue . main . async {
self . update ( )
}
}
}
2019-09-05 11:59:10 -07:00
@objc func signOut ( _ sender : UIBarButtonItem )
2019-06-06 14:46:23 -07:00
{
func signOut ( )
{
DatabaseManager . shared . signOut { ( error ) in
DispatchQueue . main . async {
if let error = error
{
2019-09-05 11:59:10 -07:00
let toastView = ToastView ( text : error . localizedDescription , detailText : nil )
2019-06-06 14:46:23 -07:00
toastView . show ( in : self . navigationController ? . view ? ? self . view , duration : 2.0 )
}
self . update ( )
}
}
}
let alertController = UIAlertController ( title : NSLocalizedString ( " Are you sure you want to sign out? " , comment : " " ) , message : NSLocalizedString ( " You will no longer be able to install or refresh apps once you sign out. " , comment : " " ) , preferredStyle : . actionSheet )
alertController . addAction ( UIAlertAction ( title : NSLocalizedString ( " Sign Out " , comment : " " ) , style : . destructive ) { _ in signOut ( ) } )
alertController . addAction ( . cancel )
self . present ( alertController , animated : true , completion : nil )
}
2019-09-05 11:59:10 -07:00
@IBAction func toggleIsBackgroundRefreshEnabled ( _ sender : UISwitch )
{
UserDefaults . standard . isBackgroundRefreshEnabled = sender . isOn
}
2019-06-06 14:46:23 -07:00
}
2019-07-31 11:46:26 -07:00
extension SettingsViewController
2019-06-06 14:46:23 -07:00
{
2019-09-05 11:59:10 -07:00
override func tableView ( _ tableView : UITableView , numberOfRowsInSection section : Int ) -> Int
2019-06-06 14:46:23 -07:00
{
2019-09-05 11:59:10 -07:00
let section = Section . allCases [ section ]
switch section
{
case . signIn : return ( self . activeTeam = = nil ) ? 1 : 0
case . account : return ( self . activeTeam = = nil ) ? 0 : 3
default : return super . tableView ( tableView , numberOfRowsInSection : section . rawValue )
}
}
override func tableView ( _ tableView : UITableView , viewForHeaderInSection section : Int ) -> UIView ?
{
let section = Section . allCases [ section ]
switch section
{
case . signIn where self . activeTeam != nil : return nil
case . account where self . activeTeam = = nil : return nil
2019-09-07 15:34:07 -07:00
case . signIn , . account , . credits , . debug :
2019-09-05 11:59:10 -07:00
let headerView = tableView . dequeueReusableHeaderFooterView ( withIdentifier : " HeaderFooterView " ) as ! SettingsHeaderFooterView
self . prepare ( headerView , for : section , isHeader : true )
return headerView
2019-09-07 15:34:07 -07:00
case . patreon , . backgroundRefresh , . instructions : return nil
2019-09-05 11:59:10 -07:00
}
}
override func tableView ( _ tableView : UITableView , viewForFooterInSection section : Int ) -> UIView ?
{
let section = Section . allCases [ section ]
switch section
{
case . signIn where self . activeTeam != nil : return nil
case . signIn , . patreon , . backgroundRefresh :
let footerView = tableView . dequeueReusableHeaderFooterView ( withIdentifier : " HeaderFooterView " ) as ! SettingsHeaderFooterView
self . prepare ( footerView , for : section , isHeader : false )
return footerView
2019-09-07 15:34:07 -07:00
case . account , . credits , . debug , . instructions : return nil
2019-09-05 11:59:10 -07:00
}
2019-06-06 14:46:23 -07:00
}
2019-09-05 11:59:10 -07:00
override func tableView ( _ tableView : UITableView , heightForHeaderInSection section : Int ) -> CGFloat
{
let section = Section . allCases [ section ]
switch section
{
case . signIn where self . activeTeam != nil : return 1.0
case . account where self . activeTeam = = nil : return 1.0
2019-09-07 15:34:07 -07:00
case . signIn , . account , . credits , . debug :
2019-09-05 11:59:10 -07:00
let height = self . preferredHeight ( for : self . prototypeHeaderFooterView , in : section , isHeader : true )
return height
2019-09-07 15:34:07 -07:00
case . patreon , . backgroundRefresh , . instructions : return 0.0
2019-09-05 11:59:10 -07:00
}
}
override func tableView ( _ tableView : UITableView , heightForFooterInSection section : Int ) -> CGFloat
{
let section = Section . allCases [ section ]
switch section
{
case . signIn where self . activeTeam != nil : return 1.0
case . account where self . activeTeam = = nil : return 1.0
case . signIn , . patreon , . backgroundRefresh :
let height = self . preferredHeight ( for : self . prototypeHeaderFooterView , in : section , isHeader : false )
return height
2019-09-07 15:34:07 -07:00
case . account , . credits , . debug , . instructions : return 0.0
2019-09-05 11:59:10 -07:00
}
}
}
2019-06-06 14:46:23 -07:00
2019-09-05 11:59:10 -07:00
extension SettingsViewController
{
override func tableView ( _ tableView : UITableView , didSelectRowAt indexPath : IndexPath )
{
let section = Section . allCases [ indexPath . section ]
switch section
{
case . signIn : self . signIn ( )
2019-09-07 15:34:07 -07:00
case . instructions : break
case . credits :
let row = CreditsRow . allCases [ indexPath . row ]
switch row
{
case . developer :
let safariViewController = SFSafariViewController ( url : URL ( string : " https://twitter.com/rileytestut " ) ! )
2019-09-19 11:29:10 -07:00
safariViewController . preferredControlTintColor = . altPrimary
2019-09-07 15:34:07 -07:00
self . present ( safariViewController , animated : true , completion : nil )
case . designer :
let safariViewController = SFSafariViewController ( url : URL ( string : " https://twitter.com/1carolinemoore " ) ! )
2019-09-19 11:29:10 -07:00
safariViewController . preferredControlTintColor = . altPrimary
2019-09-07 15:34:07 -07:00
self . present ( safariViewController , animated : true , completion : nil )
case . softwareLicenses :
break
}
2019-09-12 13:23:21 -07:00
case . debug :
let row = DebugRow . allCases [ indexPath . row ]
switch row
{
case . sendFeedback :
if MFMailComposeViewController . canSendMail ( )
{
let mailViewController = MFMailComposeViewController ( )
mailViewController . mailComposeDelegate = self
mailViewController . setToRecipients ( [ " riley@rileytestut.com " ] )
if let version = Bundle . main . object ( forInfoDictionaryKey : " CFBundleShortVersionString " ) as ? String
{
mailViewController . setSubject ( " AltStore Beta \( version ) Feedback " )
}
else
{
mailViewController . setSubject ( " AltStore Beta Feedback " )
}
self . present ( mailViewController , animated : true , completion : nil )
}
else
{
let toastView = ToastView ( text : NSLocalizedString ( " Cannot Send Mail " , comment : " " ) , detailText : nil )
toastView . show ( in : self . navigationController ? . view ? ? self . view , duration : 2.0 )
}
case . refreshAttempts : break
}
2019-09-05 11:59:10 -07:00
default : break
}
}
}
2019-09-12 13:23:21 -07:00
extension SettingsViewController : MFMailComposeViewControllerDelegate
{
func mailComposeController ( _ controller : MFMailComposeViewController , didFinishWith result : MFMailComposeResult , error : Error ? )
{
if let error = error
{
let toastView = ToastView ( text : error . localizedDescription , detailText : " " )
toastView . show ( in : self . navigationController ? . view ? ? self . view , duration : 2.0 )
}
controller . dismiss ( animated : true , completion : nil )
}
}