| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660 |
- /*
- * Copyright 2019 Google
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #import <objc/runtime.h>
- #import <FirebaseCore/FIRApp.h>
- #import <FirebaseCore/FIRAppInternal.h>
- #import "AppManager.h"
- #import "AuthCredentials.h"
- #import "FacebookAuthProvider.h"
- #import "FirebaseAuth.h"
- #import "GoogleAuthProvider.h"
- #import "MainViewController+App.h"
- #import "MainViewController+Auth.h"
- #import "MainViewController+AutoTests.h"
- #import "MainViewController+Custom.h"
- #import "MainViewController+Email.h"
- #import "MainViewController+Facebook.h"
- #import "MainViewController+GameCenter.h"
- #import "MainViewController+Google.h"
- #import "MainViewController+Internal.h"
- #import "MainViewController+MultiFactor.h"
- #import "MainViewController+OAuth.h"
- #import "MainViewController+OOB.h"
- #import "MainViewController+Phone.h"
- #import "MainViewController+User.h"
- #import "SettingsViewController.h"
- #import "StaticContentTableViewManager.h"
- #import "UIViewController+Alerts.h"
- #import "UserInfoViewController.h"
- #import "UserTableViewCell.h"
- NS_ASSUME_NONNULL_BEGIN
- static NSString *const kSectionTitleSettings = @"Settings";
- static NSString *const kSectionTitleUserDetails = @"User Defaults";
- static NSString *const kSwitchToInMemoryUserTitle = @"Switch to in memory user";
- static NSString *const kNewOrExistingUserToggleTitle = @"New or Existing User Toggle";
- extern NSString *const FIRAuthErrorUserInfoMultiFactorResolverKey;
- typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable error);
- @implementation MainViewController {
- NSMutableString *_consoleString;
- /** @var _userInMemory
- @brief Acts like the "memory" function of a calculator. An operation allows sample app users
- to assign this value based on @c FIRAuth.currentUser or clear this value.
- */
- FIRUser *_userInMemory;
- /** @var _useUserInMemory
- @brief Instructs the application to use _userInMemory instead of @c FIRAuth.currentUser for
- testing operations. This allows us to test if things still work with a user who is not
- the @c FIRAuth.currentUser, and also allows us to test those things while
- @c FIRAuth.currentUser remains nil (after a sign-out) and also when @c FIRAuth.currentUser
- is non-nil (do to a subsequent sign-in.)
- */
- BOOL _useUserInMemory;
- }
- - (id)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
- _actionCodeRequestType = ActionCodeRequestTypeInApp;
- _actionCodeContinueURL = [NSURL URLWithString:KCONTINUE_URL];
- _authStateDidChangeListeners = [NSMutableArray array];
- _IDTokenDidChangeListeners = [NSMutableArray array];
- _googleOAuthProvider = [FIROAuthProvider providerWithProviderID:FIRGoogleAuthProviderID];
- _microsoftOAuthProvider = [FIROAuthProvider providerWithProviderID:@"microsoft.com"];
- _twitterOAuthProvider = [FIROAuthProvider providerWithProviderID:@"twitter.com"];
- _linkedinOAuthProvider = [FIROAuthProvider providerWithProviderID:@"linkedin.com"];
- _yahooOAuthProvider = [FIROAuthProvider providerWithProviderID:@"yahoo.com"];
- _gitHubOAuthProvider = [FIROAuthProvider providerWithProviderID:@"github.com"];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(authStateChangedForAuth:)
- name:FIRAuthStateDidChangeNotification
- object:nil];
- self.useStatusBarSpinner = YES;
- }
- return self;
- }
- - (void)viewDidLoad {
- [super viewDidLoad];
- // Give us a circle for the image view:
- _userInfoTableViewCell.userInfoProfileURLImageView.layer.cornerRadius =
- _userInfoTableViewCell.userInfoProfileURLImageView.frame.size.width / 2.0f;
- _userInfoTableViewCell.userInfoProfileURLImageView.layer.masksToBounds = YES;
- _userInMemoryInfoTableViewCell.userInfoProfileURLImageView.layer.cornerRadius =
- _userInMemoryInfoTableViewCell.userInfoProfileURLImageView.frame.size.width / 2.0f;
- _userInMemoryInfoTableViewCell.userInfoProfileURLImageView.layer.masksToBounds = YES;
- }
- - (void)viewWillAppear:(BOOL)animated {
- [super viewWillAppear:animated];
- [self updateTable];
- [self updateUserInfo];
- }
- #pragma mark - Public
- - (BOOL)handleIncomingLinkWithURL:(NSURL *)URL {
- // Parse the query portion of the incoming URL.
- NSDictionary<NSString *, NSString *> *queryItems =
- parseURL([NSURLComponents componentsWithString:URL.absoluteString].query);
- // Check that all necessary query items are available.
- NSString *actionCode = queryItems[@"oobCode"];
- NSString *mode = queryItems[@"mode"];
- if (!actionCode || !mode) {
- return NO;
- }
- // Handle Password Reset action.
- if ([mode isEqualToString:kPasswordResetAction]) {
- [self showTextInputPromptWithMessage:@"New Password:"
- completionBlock:^(BOOL userPressedOK, NSString *_Nullable newPassword) {
- if (!userPressedOK || !newPassword.length) {
- [UIPasteboard generalPasteboard].string = actionCode;
- return;
- }
- [self showSpinner:^() {
- [[AppManager auth] confirmPasswordResetWithCode:actionCode
- newPassword:newPassword
- completion:^(NSError *_Nullable error) {
- [self hideSpinner:^{
- if (error) {
- [self logFailure:@"Password reset in app failed" error:error];
- [self showMessagePrompt:error.localizedDescription];
- return;
- }
- [self logSuccess:@"Password reset in app succeeded."];
- [self showMessagePrompt:@"Password reset in app succeeded."];
- }];
- }];
- }];
- }];
- return YES;
- }
- if ([mode isEqualToString:kVerifyEmailAction]) {
- [self showMessagePromptWithTitle:@"Tap OK to verify email"
- message:actionCode
- showCancelButton:YES
- completion:^(BOOL userPressedOK, NSString *_Nullable userInput) {
- if (!userPressedOK) {
- return;
- }
- [self showSpinner:^() {
- [[AppManager auth] applyActionCode:actionCode completion:^(NSError *_Nullable error) {
- [self hideSpinner:^{
- if (error) {
- [self logFailure:@"Verify email in app failed" error:error];
- [self showMessagePrompt:error.localizedDescription];
- return;
- }
- [self logSuccess:@"Verify email in app succeeded."];
- [self showMessagePrompt:@"Verify email in app succeeded."];
- }];
- }];
- }];
- }];
- return YES;
- }
- return NO;
- }
- static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
- NSString *linkURL = [NSURLComponents componentsWithString:urlString].query;
- NSArray<NSString *> *URLComponents = [linkURL componentsSeparatedByString:@"&"];
- NSMutableDictionary<NSString *, NSString *> *queryItems =
- [[NSMutableDictionary alloc] initWithCapacity:URLComponents.count];
- for (NSString *component in URLComponents) {
- NSRange equalRange = [component rangeOfString:@"="];
- if (equalRange.location != NSNotFound) {
- NSString *queryItemKey =
- [[component substringToIndex:equalRange.location] stringByRemovingPercentEncoding];
- NSString *queryItemValue =
- [[component substringFromIndex:equalRange.location + 1] stringByRemovingPercentEncoding];
- if (queryItemKey && queryItemValue) {
- queryItems[queryItemKey] = queryItemValue;
- }
- }
- }
- return queryItems;
- }
- - (void)updateTable {
- __weak typeof(self) weakSelf = self;
- _tableViewManager.contents =
- [StaticContentTableViewContent contentWithSections:@[
- // User Defaults
- [StaticContentTableViewSection sectionWithTitle:kSectionTitleUserDetails cells:@[
- [StaticContentTableViewCell cellWithCustomCell:_userInfoTableViewCell action:^{
- [weakSelf presentUserInfo];
- }],
- [StaticContentTableViewCell cellWithCustomCell:_userToUseCell],
- [StaticContentTableViewCell cellWithCustomCell:_userInMemoryInfoTableViewCell action:^{
- [weakSelf presentUserInMemoryInfo];
- }],
- ]],
- // Settings
- [StaticContentTableViewSection sectionWithTitle:kSectionTitleSettings cells:@[
- [StaticContentTableViewCell cellWithTitle:kSectionTitleSettings
- action:^{ [weakSelf presentSettings]; }],
- [StaticContentTableViewCell cellWithTitle:kNewOrExistingUserToggleTitle
- value:_isNewUserToggleOn ? @"Enabled" : @"Disabled"
- action:^{
- _isNewUserToggleOn = !_isNewUserToggleOn;
- [self updateTable]; }],
- [StaticContentTableViewCell cellWithTitle:kSwitchToInMemoryUserTitle
- action:^{ [weakSelf updateToSavedUser]; }],
- ]],
- // Auth
- [weakSelf authSection],
- // User
- [weakSelf userSection],
- // Multi Factor
- [weakSelf multiFactorSection],
- // Email Auth
- [weakSelf emailAuthSection],
- // Phone Auth
- [weakSelf phoneAuthSection],
- // Google Auth
- [weakSelf googleAuthSection],
- // Facebook Auth
- [weakSelf facebookAuthSection],
- // OAuth
- [weakSelf oAuthSection],
- // Custom Auth
- [weakSelf customAuthSection],
- // Game Center Auth
- [weakSelf gameCenterAuthSection],
- // App
- [weakSelf appSection],
- // OOB
- [weakSelf oobSection],
- // Auto Tests
- [weakSelf autoTestsSection],
- ]];
- }
- #pragma mark - Internal
- - (FIRUser *)user {
- return _useUserInMemory ? _userInMemory : [AppManager auth].currentUser;
- }
- - (void)signInWithProvider:(nonnull id<AuthProvider>)provider callback:(void(^)(void))callback {
- if (!provider) {
- [self logFailedTest:@"A valid auth provider was not provided to the signInWithProvider."];
- return;
- }
- [provider getAuthCredentialWithPresentingViewController:self
- callback:^(FIRAuthCredential *credential,
- NSError *error) {
- if (!credential) {
- [self logFailedTest:@"The test needs a valid credential to continue."];
- return;
- }
- [[AppManager auth] signInWithCredential:credential
- completion:^(FIRAuthDataResult *_Nullable result,
- NSError *_Nullable error) {
- if (error) {
- [self logFailure:@"sign-in with provider failed" error:error];
- [self logFailedTest:@"Sign-in should succeed"];
- return;
- } else {
- [self logSuccess:@"sign-in with provider succeeded."];
- callback();
- }
- }];
- }];
- }
- - (FIRActionCodeSettings *)actionCodeSettings {
- FIRActionCodeSettings *actionCodeSettings = [[FIRActionCodeSettings alloc] init];
- actionCodeSettings.URL = self.actionCodeContinueURL;
- actionCodeSettings.handleCodeInApp = self.actionCodeRequestType == ActionCodeRequestTypeInApp;
- return actionCodeSettings;
- }
- - (void)reauthenticate:(id<AuthProvider>)authProvider retrieveData:(BOOL)retrieveData {
- FIRUser *user = [self user];
- if (!user) {
- NSString *provider = @"Firebase";
- if ([authProvider isKindOfClass:[GoogleAuthProvider class]]) {
- provider = @"Google";
- } else if ([authProvider isKindOfClass:[FacebookAuthProvider class]]) {
- provider = @"Facebook";
- }
- NSString *title = @"Missing User";
- NSString *message =
- [NSString stringWithFormat:@"There is no signed-in %@ user.", provider];
- [self showMessagePromptWithTitle:title message:message showCancelButton:NO completion:nil];
- return;
- }
- [authProvider getAuthCredentialWithPresentingViewController:self
- callback:^(FIRAuthCredential *credential,
- NSError *error) {
- if (credential) {
- FIRAuthDataResultCallback completion = ^(FIRAuthDataResult *_Nullable authResult,
- NSError *_Nullable error) {
- if (error) {
- if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
- FIRMultiFactorResolver *resolver = error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
- NSMutableString *displayNameString = [NSMutableString string];
- for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
- [displayNameString appendString:tmpFactorInfo.displayName];
- [displayNameString appendString:@" "];
- }
- [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Select factor to reauthenticate\n%@", displayNameString]
- completionBlock:^(BOOL userPressedOK, NSString *_Nullable displayName) {
- FIRPhoneMultiFactorInfo* selectedHint;
- for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
- if ([displayName isEqualToString:tmpFactorInfo.displayName]) {
- selectedHint = (FIRPhoneMultiFactorInfo *)tmpFactorInfo;
- }
- }
- [FIRPhoneAuthProvider.provider
- verifyPhoneNumberWithMultiFactorInfo:selectedHint
- UIDelegate:nil
- multiFactorSession:resolver.session
- completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
- if (error) {
- [self logFailure:@"Multi factor start sign in failed." error:error];
- } else {
- [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Verification code for %@", selectedHint.displayName]
- completionBlock:^(BOOL userPressedOK, NSString *_Nullable verificationCode) {
- FIRPhoneAuthCredential *credential =
- [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
- verificationCode:verificationCode];
- FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
- [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
- if (error) {
- [self logFailure:@"Multi factor finalize sign in failed." error:error];
- } else {
- [self logSuccess:@"Multi factor finalize sign in succeeded."];
- }
- }];
- }];
- }
- }];
- }];
- } else {
- [self logFailure:@"reauthenticate operation failed." error:error];
- }
- } else {
- [self logSuccess:@"reauthenticate operation succeeded."];
- }
- if (authResult.additionalUserInfo) {
- [self logSuccess:[self stringWithAdditionalUserInfo:authResult.additionalUserInfo]];
- }
- };
- [user reauthenticateWithCredential:credential completion:completion];
- }
- }];
- }
- - (void)signinWithProvider:(id<AuthProvider>)authProvider retrieveData:(BOOL)retrieveData {
- FIRAuth *auth = [AppManager auth];
- if (!auth) {
- return;
- }
- [authProvider getAuthCredentialWithPresentingViewController:self
- callback:^(FIRAuthCredential *credential,
- NSError *error) {
- if (credential) {
- FIRAuthDataResultCallback completion = ^(FIRAuthDataResult *_Nullable authResult,
- NSError *_Nullable error) {
- if (error) {
- [self logFailure:@"sign-in with provider failed" error:error];
- } else {
- [self logSuccess:@"sign-in with provider succeeded."];
- }
- if (authResult.additionalUserInfo) {
- [self logSuccess:[self stringWithAdditionalUserInfo:authResult.additionalUserInfo]];
- if (_isNewUserToggleOn) {
- NSString *newUserString = authResult.additionalUserInfo.isNewUser ?
- @"New user" : @"Existing user";
- [self showMessagePromptWithTitle:@"New or Existing"
- message:newUserString
- showCancelButton:NO
- completion:nil];
- }
- }
- [self showTypicalUIForUserUpdateResultsWithTitle:@"Sign-In" error:error];
- };
- [auth signInWithCredential:credential completion:completion];
- }
- }];
- }
- - (void)linkWithAuthProvider:(id<AuthProvider>)authProvider retrieveData:(BOOL)retrieveData {
- FIRUser *user = [self user];
- if (!user) {
- return;
- }
- [authProvider getAuthCredentialWithPresentingViewController:self
- callback:^(FIRAuthCredential *credential,
- NSError *error) {
- if (credential) {
- FIRAuthDataResultCallback completion = ^(FIRAuthDataResult *_Nullable authResult,
- NSError *_Nullable error) {
- if (error) {
- if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
- FIRMultiFactorResolver *resolver = error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
- NSMutableString *displayNameString = [NSMutableString string];
- for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
- [displayNameString appendString:tmpFactorInfo.displayName];
- [displayNameString appendString:@" "];
- }
- [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Select factor to link\n%@", displayNameString]
- completionBlock:^(BOOL userPressedOK, NSString *_Nullable displayName) {
- FIRPhoneMultiFactorInfo* selectedHint;
- for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
- if ([displayName isEqualToString:tmpFactorInfo.displayName]) {
- selectedHint = (FIRPhoneMultiFactorInfo *)tmpFactorInfo;
- }
- }
- [FIRPhoneAuthProvider.provider
- verifyPhoneNumberWithMultiFactorInfo:selectedHint
- UIDelegate:nil
- multiFactorSession:resolver.session
- completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
- if (error) {
- [self logFailure:@"Multi factor start sign in failed." error:error];
- } else {
- [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Verification code for %@", selectedHint.displayName]
- completionBlock:^(BOOL userPressedOK, NSString *_Nullable verificationCode) {
- FIRPhoneAuthCredential *credential =
- [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
- verificationCode:verificationCode];
- FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
- [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
- if (error) {
- [self logFailure:@"Multi factor finalize sign in failed." error:error];
- } else {
- [self logSuccess:@"Multi factor finalize sign in succeeded."];
- }
- }];
- }];
- }
- }];
- }];
- } else {
- [self logFailure:@"link auth provider failed" error:error];
- }
- } else {
- [self logSuccess:@"link auth provider succeeded."];
- }
- if (authResult.additionalUserInfo) {
- [self logSuccess:[self stringWithAdditionalUserInfo:authResult.additionalUserInfo]];
- }
- };
- [user linkWithCredential:credential completion:completion];
- }
- }];
- }
- - (void)unlinkFromProvider:(NSString *)provider
- completion:(nullable TestAutomationCallback)completion {
- [[self user] unlinkFromProvider:provider
- completion:^(FIRUser *_Nullable user,
- NSError *_Nullable error) {
- if (error) {
- [self logFailure:@"unlink auth provider failed" error:error];
- if (completion) {
- completion(error);
- }
- return;
- }
- [self logSuccess:@"unlink auth provider succeeded."];
- if (completion) {
- completion(nil);
- }
- [self showTypicalUIForUserUpdateResultsWithTitle:@"Unlink from Provider" error:error];
- }];
- }
- - (void)updateToSavedUser {
- if(![AppManager auth].currentUser) {
- NSLog(@"You must be signed in to perform this action");
- return;
- }
- if (!_userInMemory) {
- [self showMessagePrompt:[NSString stringWithFormat:@"You need an in-memory user to perform this"
- "action, use the M+ button to save a user to memory.", nil]];
- return;
- }
- [[AppManager auth] updateCurrentUser:_userInMemory completion:^(NSError *_Nullable error) {
- if (error) {
- [self showMessagePrompt:
- [NSString stringWithFormat:@"An error Occurred: %@", error.localizedDescription]];
- return;
- }
- }];
- }
- #pragma mark - Private
- - (void)presentSettings {
- SettingsViewController *settingsViewController = [[SettingsViewController alloc]
- initWithNibName:NSStringFromClass([SettingsViewController class])
- bundle:nil];
- [self showViewController:settingsViewController sender:self];
- }
- - (void)presentUserInfo {
- UserInfoViewController *userInfoViewController =
- [[UserInfoViewController alloc] initWithUser:[AppManager auth].currentUser];
- [self showViewController:userInfoViewController sender:self];
- }
- - (void)presentUserInMemoryInfo {
- UserInfoViewController *userInfoViewController =
- [[UserInfoViewController alloc] initWithUser:_userInMemory];
- [self showViewController:userInfoViewController sender:self];
- }
- - (NSString *)stringWithAdditionalUserInfo:(nullable FIRAdditionalUserInfo *)additionalUserInfo {
- if (!additionalUserInfo) {
- return @"(no additional user info)";
- }
- NSString *newUserString = additionalUserInfo.isNewUser ? @"new user" : @"existing user";
- return [NSString stringWithFormat:@"%@: %@", newUserString, additionalUserInfo.profile];
- }
- - (void)showTypicalUIForUserUpdateResultsWithTitle:(NSString *)resultsTitle
- error:(NSError * _Nullable)error {
- if (error) {
- NSString *message = [NSString stringWithFormat:@"%@ (%ld)\n%@",
- error.domain,
- (long)error.code,
- error.localizedDescription];
- if (error.code == FIRAuthErrorCodeAccountExistsWithDifferentCredential) {
- NSString *errorEmail = error.userInfo[FIRAuthErrorUserInfoEmailKey];
- resultsTitle = [NSString stringWithFormat:@"Existing email : %@", errorEmail];
- }
- [self showMessagePromptWithTitle:resultsTitle
- message:message
- showCancelButton:NO
- completion:nil];
- return;
- }
- [self updateUserInfo];
- }
- - (void)showUIForAuthDataResultWithResult:(FIRAuthDataResult *)result
- error:(NSError * _Nullable)error {
- NSString *errorMessage = [NSString stringWithFormat:@"%@ (%ld)\n%@",
- error.domain ?: @"",
- (long)error.code,
- error.localizedDescription ?: @""];
- [self showMessagePromptWithTitle:@"Error"
- message:errorMessage
- showCancelButton:NO
- completion:^(BOOL userPressedOK,
- NSString *_Nullable userInput) {
- [self showMessagePromptWithTitle:@"Profile Info"
- message:[self stringWithAdditionalUserInfo:result.additionalUserInfo]
- showCancelButton:NO
- completion:nil];
- [self updateUserInfo];
- }];
- }
- - (void)updateUserInfo {
- [_userInfoTableViewCell updateContentsWithUser:[AppManager auth].currentUser];
- [_userInMemoryInfoTableViewCell updateContentsWithUser:_userInMemory];
- }
- - (void)authStateChangedForAuth:(NSNotification *)notification {
- [self updateUserInfo];
- if (notification) {
- [self log:[NSString stringWithFormat:
- @"received FIRAuthStateDidChange notification on user '%@'.",
- ((FIRAuth *)notification.object).currentUser.uid]];
- }
- }
- - (void)log:(NSString *)string {
- dispatch_async(dispatch_get_main_queue(), ^{
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
- dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
- NSString *date = [dateFormatter stringFromDate:[NSDate date]];
- if (!_consoleString) {
- _consoleString = [NSMutableString string];
- }
- [_consoleString appendString:[NSString stringWithFormat:@"%@ %@\n", date, string]];
- _consoleTextView.text = _consoleString;
- CGRect targetRect = CGRectMake(0, _consoleTextView.contentSize.height - 1, 1, 1);
- [_consoleTextView scrollRectToVisible:targetRect animated:YES];
- });
- }
- - (void)logSuccess:(NSString *)string {
- [self log:[NSString stringWithFormat:@"SUCCESS: %@", string]];
- }
- - (void)logFailure:(NSString *)string error:(NSError * _Nullable) error {
- NSString *message =
- [NSString stringWithFormat:@"FAILURE: %@ Error Description: %@.", string, error.description];
- [self log:message];
- }
- - (void)logFailedTest:( NSString *_Nonnull )reason {
- [self log:[NSString stringWithFormat:@"FAILIURE: TEST FAILED - %@", reason]];
- }
- #pragma mark - IBAction
- - (IBAction)userToUseDidChange:(UISegmentedControl *)sender {
- _useUserInMemory = (sender.selectedSegmentIndex == 1);
- }
- - (IBAction)memoryPlus {
- _userInMemory = [AppManager auth].currentUser;
- [self updateUserInfo];
- }
- - (IBAction)memoryClear {
- _userInMemory = nil;
- [self updateUserInfo];
- }
- - (IBAction)clearConsole:(id)sender {
- [_consoleString appendString:@"\n\n"];
- _consoleTextView.text = @"";
- }
- - (IBAction)copyConsole:(id)sender {
- UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
- pasteboard.string = _consoleString ?: @"";
- }
- @end
- NS_ASSUME_NONNULL_END
|