// // AuthorizationProgressViewController.m // HotPocket (macOS) // // Created by Tomek Wójcik on 20/09/2025. // #import "AuthorizationProgressViewController.h" #import "AppDelegate.h" #import "AuthorizationViewController.h" #import "HPAuthFlow.h" #import "HPCredentialsHelper.h" #import "MainViewController.h" #import "NSBundle+HotPocketExtensions.h" #import "ReplaceAnimator.h" @interface AuthorizationProgressViewController (AuthorizationProgressViewControllerPrivate) #pragma mark - Private interface -(void)presentAuthorizationError; @end @implementation AuthorizationProgressViewController #pragma mark - View lifecycle -(instancetype)initWithCoder:(NSCoder *)coder { if (self = [super initWithCoder:coder]) { self.authorizationURL = nil; self.webAuthenticationSession = nil; self.userCancelledSession = NO; } return self; } -(void)viewDidLoad { [super viewDidLoad]; self.progressLabelTitle = NSLocalizedString(@"Continue to sign in in your browser...", @"Continue to sign in in your browser..."); } -(void)viewWillAppear { AppDelegate *appDelegate = [[NSApplication sharedApplication] delegate]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAuthFlowDidFinish:) name:@"AuthFlowDidFinish" object:appDelegate.authFlow]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAuthFlowDidReceiveAuthParams:) name:@"AuthFlowDidReceiveAuthParams" object:appDelegate.authFlow]; [self.progressIndicator startAnimation:self]; } -(void)viewDidAppear { [super viewDidAppear]; AppDelegate *appDelegate = [[NSApplication sharedApplication] delegate]; ASWebAuthenticationSessionCompletionHandler completionHandler = ^(NSURL *url, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ if (error != nil) { #ifdef DEBUG NSLog(@"[AuthorizationViewController.session completionHandler] error=`%@`", error); #endif if (error.code == ASWebAuthenticationSessionErrorCodeCanceledLogin) { self.userCancelledSession = YES; } [self presentAuthorizationError]; } else { HPAuthParams *receivedAuthParams = [appDelegate.authFlow handlePostAuthenticateURL:url]; if (receivedAuthParams != nil) { [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; [appDelegate.authFlow handleAuthParams:receivedAuthParams]; } else { [self presentAuthorizationError]; } } self.webAuthenticationSession = nil; }); }; ASWebAuthenticationSessionCallback *callback = [ASWebAuthenticationSessionCallback callbackWithCustomScheme:[NSBundle postAuthenticateURLScheme]]; self.webAuthenticationSession = [[ASWebAuthenticationSession alloc] initWithURL:self.authorizationURL callback:callback completionHandler:completionHandler]; self.webAuthenticationSession.presentationContextProvider = self; #ifdef DEBUG self.webAuthenticationSession.prefersEphemeralWebBrowserSession = YES; #endif if (self.webAuthenticationSession.canStart == NO) { [self presentAuthorizationError]; return; } [self.webAuthenticationSession start]; } -(void)viewDidDisappear { [super viewDidDisappear]; self.webAuthenticationSession = nil; [self.progressIndicator stopAnimation:self]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - Actions -(IBAction)doCancel:(id)sender { [self.webAuthenticationSession cancel]; } #pragma mark - Private interface -(void)presentAuthorizationError { if (self.userCancelledSession == NO) { NSAlert *alert = [[NSAlert alloc] init]; alert.alertStyle = NSAlertStyleCritical; alert.messageText = NSLocalizedString(@"Oops!", @"Oops!"); alert.informativeText = NSLocalizedString(@"HotPocket couldn't complete this operation.", @"HotPocket couldn't complete this operation."); [alert beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse response) { AuthorizationViewController *authorizationViewController = [self.storyboard instantiateControllerWithIdentifier:@"AuthorizationViewController"]; [self presentViewController:authorizationViewController animator:[[ReplaceAnimator alloc] init]]; }]; } else { AuthorizationViewController *authorizationViewController = [self.storyboard instantiateControllerWithIdentifier:@"AuthorizationViewController"]; [self presentViewController:authorizationViewController animator:[[ReplaceAnimator alloc] init]]; } } #pragma mark - Notification handlers -(void)onAuthFlowDidFinish:(NSNotification *)notification { dispatch_async(dispatch_get_main_queue(), ^{ HPCredentials *credentials = [[HPCredentialsHelper sharedHelper] getCredentials]; [[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest]; [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; if (credentials.usable == NO) { [self presentAuthorizationError]; } else { MainViewController *mainViewController = [self.storyboard instantiateControllerWithIdentifier:@"MainViewController"]; [self presentViewController:mainViewController animator:[[ReplaceAnimator alloc] init]]; } }); } -(void)onAuthFlowDidReceiveAuthParams:(NSNotification *)notification { self.progressLabelTitle = NSLocalizedString(@"Processing authorization...", @"Processing authorization..."); } # pragma mark - ASWebAuthenticationPresentationContextProviding implementation -(ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session { return self.view.window; } @end