public SignupPageViewModel(
            INavigationService navigationService,
            IContainerRegistry containerRegistry,
            IUserDataStore userDataStore,
            IUserDialogs dialogService,
            IFirebaseAuthService firebaseAuthService) : base(navigationService)
        {
            Title = "Sign Up";
            _containerRegistry = containerRegistry;
            _userDataStore     = userDataStore;

            // we want to disable all commands when any one is running. We'll do that by using a
            // behavior subject to play all of the command events through
            BehaviorSubject <bool> canExecute = new BehaviorSubject <bool>(true);

            SignInWithGoogle = ReactiveCommand.CreateFromTask(async() =>
            {
                if (!AgreeWithTermsAndConditions)
                {
                    await ShowTermsAndConditionsValidationMessage(dialogService).ConfigureAwait(false);
                    return;
                }

                if (await firebaseAuthService.SignInWithGoogle())
                {
                    var userId  = firebaseAuthService.GetCurrentUserId();
                    var account = await new FakeUserDataStore().GetUserById(userId);

                    if (account != null)
                    {
                        // if the account is not null, the user is already registered. Just log them
                        // in and head to the home screen
                        _containerRegistry.RegisterInstance <IUserService>(new UserService(account));

                        await NavigationService.NavigateHomeAsync().ConfigureAwait(false);
                    }
                    else
                    {
                        // The account does not yet exist. Go through the registration process
                        await NavigationService
                        .NavigateAsync(
                            nameof(RegistrationTypeSelectionPage),
                            new NavigationParameters
                        {
                            { "user_id", userId }
                        }).ConfigureAwait(false);
                    }
                }
            },
                                                              canExecute);

            SignInWithFacebook = ReactiveCommand.CreateFromTask(async() =>
            {
                if (!AgreeWithTermsAndConditions)
                {
                    await ShowTermsAndConditionsValidationMessage(dialogService).ConfigureAwait(false);
                    return;
                }

                await dialogService.AlertAsync("Coming Soon!").ConfigureAwait(false);
            },
                                                                canExecute);

            SignInWithTwitter = ReactiveCommand.CreateFromTask(async() =>
            {
                if (!AgreeWithTermsAndConditions)
                {
                    await ShowTermsAndConditionsValidationMessage(dialogService).ConfigureAwait(false);
                    return;
                }

                await dialogService.AlertAsync("Coming Soon!").ConfigureAwait(false);
            },
                                                               canExecute);

            var commandsExecuting = Observable.CombineLatest(
                SignInWithGoogle.IsExecuting,
                SignInWithFacebook.IsExecuting,
                SignInWithTwitter.IsExecuting,
                (googleExecuting, facebookExecuting, twitterExecuting) => googleExecuting || facebookExecuting || twitterExecuting)
                                    .DistinctUntilChanged()
                                    .Publish()
                                    .RefCount();

            // when any of the commands are executing, update the busy state
            commandsExecuting
            .StartWith(false)
            .ToProperty(this, x => x.IsBusy, out _isBusy, scheduler: RxApp.MainThreadScheduler);

            // when any of the commands are executing, update the "can execute" state
            commandsExecuting
            .Select(isExecuting => !isExecuting)
            .Subscribe(canExecute);

            // When an exception is thrown from a command, log the error and let the user handle the exception
            SignInWithGoogle.ThrownExceptions
            .Merge(SignInWithFacebook.ThrownExceptions)
            .Merge(SignInWithTwitter.ThrownExceptions)
            .SelectMany(exception =>
            {
                this.Log().ErrorException("Error signing up", exception);

                //return SharedInteractions.Error.Handle(exception);
                return(Observable.Return(Unit.Default));
            })
            .Subscribe();
        }
        public ExtendedSplashPageViewModel(
            INavigationService navigationService,
            IContainerRegistry containerRegistry,
            IUserDataStore userDataStore,
            IFirebaseAuthService firebaseAuthService) : base(navigationService)
        {
            const int Home  = 1;
            const int Login = 2;

            Initialize = ReactiveCommand.CreateFromTask(async() =>
            {
                // make sure we're running this on a background thread
                this.Log().Debug($"Loading projects on thread: {Thread.CurrentThread.ManagedThreadId}, IsBackground = {Thread.CurrentThread.IsBackground}");
                AssertRunningOnBackgroundThread();

                if (firebaseAuthService.IsUserSigned())
                {
                    var currentUserId = firebaseAuthService.GetCurrentUserId();
                    if (string.IsNullOrWhiteSpace(currentUserId))
                    {
                        await firebaseAuthService.Logout();
                        return(Login);
                    }

                    // try to get the user from our database
                    var user = await userDataStore.GetUserById(currentUserId);
                    if (user == null)
                    {
                        await firebaseAuthService.Logout();
                        return(Login);
                    }

                    containerRegistry.RegisterInstance <IUserService>(new UserService(user));
                    return(Home);
                }

                return(Login);
            });

            Initialize
            .SubscribeOn(RxApp.MainThreadScheduler)
            .SelectMany(async nextPage =>
            {
                if (nextPage == Home)
                {
                    await NavigationService.NavigateHomeAsync().ConfigureAwait(false);
                }
                else
                {
                    await NavigationService.NavigateToLoginPageAsync().ConfigureAwait(false);
                }

                return(Observable.Return(Unit.Default));
            })
            .Subscribe();

            // when the command is executing, update the busy state
            Initialize.IsExecuting
            .StartWith(false)
            .ToProperty(this, x => x.IsBusy, out _isBusy);

            Initialize.ThrownExceptions
            .Subscribe(exception => System.Diagnostics.Debug.WriteLine($"Error: {exception}"));
        }
Example #3
0
        public LoginPageViewModel(
            INavigationService navigationService,
            IContainerRegistry containerRegistry,
            IUserDataStore userDataStore,
            IUserDialogs dialogs,
            IFirebaseAuthService firebaseAuthService) : base(navigationService)
        {
            Title = "Login";
            _containerRegistry = containerRegistry;

            // we want to disable all commands when any one is running. We'll do that by using a
            // behavior subject to play all of the command events through
            BehaviorSubject <bool> canExecute = new BehaviorSubject <bool>(true);

            SignInWithGoogle = ReactiveCommand.CreateFromTask(async() =>
            {
                if (await firebaseAuthService.SignInWithGoogle())
                {
                    var userId  = firebaseAuthService.GetCurrentUserId();
                    var account = await new FakeUserDataStore().GetUserById(userId);
                    account     = null; // TODO: Remove this

                    if (account == null)
                    {
                        // if the account doesn't exist, prompt the user to register
                        var shouldSignUp = await dialogs.ConfirmAsync(
                            new ConfirmConfig
                        {
                            Message = "The account does not appear to exist.  Would you like to sign up?",
                            OkText  = "Sign Up!"
                        });
                        if (shouldSignUp)
                        {
                            await NavigationService
                            .NavigateAsync(
                                nameof(RegistrationTypeSelectionPage),
                                new NavigationParameters
                            {
                                { "user_id", userId }
                            }).ConfigureAwait(false);
                        }
                    }
                    else
                    {
                        // the account exists. Head to the home page
                        _containerRegistry.RegisterInstance <IUserService>(new UserService(account));

                        await NavigationService.NavigateHomeAsync().ConfigureAwait(false);
                    }
                }
                else
                {
                    await dialogs.AlertAsync(
                        new AlertConfig
                    {
                        Title   = "Error",
                        Message = "Login failed"
                    }).ConfigureAwait(false);

                    // TODO: Should call log out just to be safe?
                }
            },
                                                              canExecute);

            SignInWithFacebook = ReactiveCommand.CreateFromTask(async() =>
            {
                await dialogs.AlertAsync("Coming Soon!").ConfigureAwait(false);
            },
                                                                canExecute);

            SignInWithTwitter = ReactiveCommand.CreateFromTask(async() =>
            {
                await dialogs.AlertAsync("Coming Soon!").ConfigureAwait(false);
            },
                                                               canExecute);

            var commandsExecuting = Observable.CombineLatest(
                SignInWithGoogle.IsExecuting,
                SignInWithFacebook.IsExecuting,
                SignInWithTwitter.IsExecuting,
                (googleExecuting, facebookExecuting, twitterExecuting) => googleExecuting || facebookExecuting || twitterExecuting)
                                    .DistinctUntilChanged()
                                    .Publish()
                                    .RefCount();

            // when any of the commands are executing, update the busy state
            commandsExecuting
            .StartWith(false)
            .ToProperty(this, x => x.IsBusy, out _isBusy, scheduler: RxApp.MainThreadScheduler);

            // when any of the commands are executing, update the "can execute" state
            commandsExecuting
            .Select(isExecuting => !isExecuting)
            .Subscribe(canExecute);

            // When an exception is thrown from a command, log the error and let the user handle the exception
            SignInWithGoogle.ThrownExceptions
            .Merge(SignInWithFacebook.ThrownExceptions)
            .Merge(SignInWithTwitter.ThrownExceptions)
            .SelectMany(exception =>
            {
                this.Log().ErrorException("Error logging in", exception);

                //return SharedInteractions.Error.Handle(exception);
                return(Observable.Return(Unit.Default));
            })
            .Subscribe();
        }