2018-08-19 20:14:04 +00:00
//
// O n b o a r d i n g V i e w C o n t r o l l e r . s w i f t
// T u s k e r
//
// C r e a t e d b y S h a d o w f a c t s o n 8 / 1 8 / 1 8 .
// C o p y r i g h t © 2 0 1 8 S h a d o w f a c t s . A l l r i g h t s r e s e r v e d .
//
import UIKit
import AuthenticationServices
2021-06-13 03:22:49 +00:00
import Pachyderm
2018-08-19 20:14:04 +00:00
protocol OnboardingViewControllerDelegate {
2020-01-08 02:29:15 +00:00
func didFinishOnboarding ( account : LocalData . UserAccountInfo )
2018-08-19 20:14:04 +00:00
}
2019-09-15 19:01:35 +00:00
class OnboardingViewController : UINavigationController {
2018-08-19 20:14:04 +00:00
2019-06-19 23:12:42 +00:00
static var blocks : [ NSRegularExpression ] = {
guard let path = Bundle . main . path ( forResource : " DomainBlocks " , ofType : " plist " ) ,
let array = NSArray ( contentsOfFile : path ) as ? [ String ] else { return [ ] }
return array . compactMap { try ? NSRegularExpression ( pattern : $0 , options : . caseInsensitive ) }
} ( )
2019-09-15 19:01:35 +00:00
var onboardingDelegate : OnboardingViewControllerDelegate ?
2018-08-19 20:14:04 +00:00
2019-09-15 19:01:35 +00:00
var instanceSelector = InstanceSelectorTableViewController ( )
2018-08-19 20:14:04 +00:00
var authenticationSession : ASWebAuthenticationSession ?
2018-10-20 16:03:18 +00:00
init ( ) {
2019-09-15 19:01:35 +00:00
super . init ( rootViewController : instanceSelector )
2018-10-20 16:03:18 +00:00
}
required init ? ( coder aDecoder : NSCoder ) {
fatalError ( " init(coder:) has not been implemented " )
}
2018-08-19 20:14:04 +00:00
override func viewDidLoad ( ) {
super . viewDidLoad ( )
2019-09-15 19:01:35 +00:00
instanceSelector . delegate = self
}
2021-06-13 03:22:49 +00:00
private func doAuthenticationSession ( url : URL ) async throws -> URL {
return try await withCheckedThrowingContinuation { continuation in
self . authenticationSession = ASWebAuthenticationSession ( url : url , callbackURLScheme : " tusker " ) { url , error in
defer {
DispatchQueue . main . async {
self . authenticationSession = nil
}
}
if let url = url {
continuation . resume ( returning : url )
} else {
continuation . resume ( throwing : error ! )
}
}
DispatchQueue . main . async {
// P r e f e r e p h e m e r a l s e s s i o n s t o m a k e i t e a s i e r t o s i g n i n t o m u l t i p l e a c c o u n t s o n t h e s a m e i n s t a n c e .
self . authenticationSession ! . prefersEphemeralWebBrowserSession = true
self . authenticationSession ! . presentationContextProvider = self
self . authenticationSession ! . start ( )
}
}
}
2019-09-15 19:01:35 +00:00
}
extension OnboardingViewController : InstanceSelectorTableViewControllerDelegate {
2020-01-08 02:29:15 +00:00
func didSelectInstance ( url instanceURL : URL ) {
2021-06-13 03:22:49 +00:00
async {
let mastodonController = MastodonController ( instanceURL : instanceURL )
let ( clientID , clientSecret ) = await mastodonController . registerApp ( )
2020-01-08 02:29:15 +00:00
var components = URLComponents ( url : instanceURL , resolvingAgainstBaseURL : false ) !
2018-08-19 20:14:04 +00:00
components . path = " /oauth/authorize "
components . queryItems = [
URLQueryItem ( name : " client_id " , value : clientID ) ,
URLQueryItem ( name : " response_type " , value : " code " ) ,
URLQueryItem ( name : " scope " , value : " read write follow " ) ,
2020-06-23 23:32:30 +00:00
URLQueryItem ( name : " redirect_uri " , value : " tusker://oauth " )
2018-08-19 20:14:04 +00:00
]
2021-06-13 03:22:49 +00:00
guard let url = try ? await self . doAuthenticationSession ( url : components . url ! ) ,
let components = URLComponents ( url : url , resolvingAgainstBaseURL : true ) ,
let item = components . queryItems ? . first ( where : { $0 . name = = " code " } ) ,
let authCode = item . value else {
return
2018-08-19 20:14:04 +00:00
}
2021-06-13 03:22:49 +00:00
let accessToken = await mastodonController . authorize ( authorizationCode : authCode )
// c o n s t r u c t a t e m p o r a r y U s e r A c c o u n t I n f o i n s t a n c e f o r t h e M a s t o d o n C o n t r o l l e r t o u s e t o f e t c h i t s o w n a c c o u n t
let tempAccountInfo = LocalData . UserAccountInfo ( id : " temp " , instanceURL : instanceURL , clientID : clientID , clientSecret : clientSecret , username : nil , accessToken : accessToken )
mastodonController . accountInfo = tempAccountInfo
let account : Account
do {
account = try await mastodonController . getOwnAccount ( )
} catch {
let alert = UIAlertController ( title : " Unable to Verify Credentials " , message : " Your account fcould not be fetcheda this time: \( error . localizedDescription ) " , preferredStyle : . alert )
alert . addAction ( UIAlertAction ( title : " Ok " , style : . default , handler : nil ) )
self . present ( alert , animated : true )
return
2019-07-27 22:31:55 +00:00
}
2021-06-13 03:22:49 +00:00
let accountInfo = LocalData . shared . addAccount ( instanceURL : instanceURL , clientID : clientID , clientSecret : clientSecret , username : account . username , accessToken : accessToken )
mastodonController . accountInfo = accountInfo
self . onboardingDelegate ? . didFinishOnboarding ( account : accountInfo )
2018-08-19 20:14:04 +00:00
}
}
}
2019-06-04 17:31:12 +00:00
extension OnboardingViewController : ASWebAuthenticationPresentationContextProviding {
func presentationAnchor ( for session : ASWebAuthenticationSession ) -> ASPresentationAnchor {
2019-06-11 17:21:22 +00:00
return view . window !
2019-06-04 17:31:12 +00:00
}
}