Example #1
0
        public SendFeedbackViewModel(
            INavigationService navigationService,
            IInteractorFactory interactorFactory,
            IDialogService dialogService,
            ISchedulerProvider schedulerProvider,
            IRxActionFactory rxActionFactory)
        {
            Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory));
            Ensure.Argument.IsNotNull(navigationService, nameof(navigationService));
            Ensure.Argument.IsNotNull(dialogService, nameof(dialogService));
            Ensure.Argument.IsNotNull(schedulerProvider, nameof(schedulerProvider));
            Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory));

            this.dialogService     = dialogService;
            this.interactorFactory = interactorFactory;
            this.navigationService = navigationService;

            IsFeedbackEmpty = isEmptyObservable.DistinctUntilChanged().AsDriver(schedulerProvider);
            SendEnabled     = sendingIsEnabledObservable.DistinctUntilChanged().AsDriver(schedulerProvider);

            Close        = rxActionFactory.FromObservable(cancel);
            DismissError = rxActionFactory.FromAction(dismissError);
            Send         = rxActionFactory.FromObservable(sendFeedback, sendingIsEnabledObservable);

            IsLoading = isLoadingSubject.AsDriver(false, schedulerProvider);
            Error     = currentErrorSubject.AsDriver(default(Exception), schedulerProvider);
        }
        public ForgotPasswordViewModel(
            ITimeService timeService,
            IUserAccessManager userAccessManager,
            IAnalyticsService analyticsService,
            INavigationService navigationService,
            IRxActionFactory rxActionFactory)
            : base(navigationService)
        {
            Ensure.Argument.IsNotNull(timeService, nameof(timeService));
            Ensure.Argument.IsNotNull(userAccessManager, nameof(userAccessManager));
            Ensure.Argument.IsNotNull(analyticsService, nameof(analyticsService));
            Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory));

            this.timeService       = timeService;
            this.userAccessManager = userAccessManager;
            this.analyticsService  = analyticsService;
            this.rxActionFactory   = rxActionFactory;

            Reset = rxActionFactory.FromObservable(reset, Email.Select(email => email.IsValid));

            var resetActionStartedObservable = Reset
                                               .Executing
                                               .Where(executing => executing)
                                               .Select(_ => (Exception)null);

            ErrorMessage = Reset.Errors
                           .Merge(resetActionStartedObservable)
                           .Select(toErrorString)
                           .StartWith("")
                           .DistinctUntilChanged();

            PasswordResetSuccessful = Reset.Elements
                                      .Select(_ => true)
                                      .StartWith(false);
        }
Example #3
0
        public NoWorkspaceViewModel(
            ISyncManager syncManager,
            IInteractorFactory interactorFactory,
            INavigationService navigationService,
            IAccessRestrictionStorage accessRestrictionStorage,
            ISchedulerProvider schedulerProvider,
            IRxActionFactory rxActionFactory)
            : base(navigationService)
        {
            Ensure.Argument.IsNotNull(syncManager, nameof(syncManager));
            Ensure.Argument.IsNotNull(accessRestrictionStorage, nameof(accessRestrictionStorage));
            Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory));
            Ensure.Argument.IsNotNull(schedulerProvider, nameof(schedulerProvider));
            Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory));

            this.syncManager = syncManager;
            this.accessRestrictionStorage = accessRestrictionStorage;
            this.interactorFactory        = interactorFactory;
            this.rxActionFactory          = rxActionFactory;

            CreateWorkspaceWithDefaultName = rxActionFactory.FromObservable(createWorkspaceWithDefaultName);
            TryAgain  = rxActionFactory.FromAsync(tryAgain);
            IsLoading = Observable.CombineLatest(
                CreateWorkspaceWithDefaultName.Executing,
                TryAgain.Executing,
                CommonFunctions.Or);
        }
Example #4
0
        public ForgotPasswordViewModel(
            ITimeService timeService,
            IUserAccessManager userAccessManager,
            IAnalyticsService analyticsService,
            IMvxNavigationService navigationService,
            IRxActionFactory rxActionFactory)
        {
            Ensure.Argument.IsNotNull(timeService, nameof(timeService));
            Ensure.Argument.IsNotNull(userAccessManager, nameof(userAccessManager));
            Ensure.Argument.IsNotNull(analyticsService, nameof(analyticsService));
            Ensure.Argument.IsNotNull(navigationService, nameof(navigationService));
            Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory));

            this.timeService       = timeService;
            this.userAccessManager = userAccessManager;
            this.analyticsService  = analyticsService;
            this.navigationService = navigationService;
            this.rxActionFactory   = rxActionFactory;

            Reset = rxActionFactory.FromObservable(reset, Email.Select(email => email.IsValid));
            Close = rxActionFactory.FromAction(returnEmail, Reset.Executing.Invert());

            ErrorMessage = Reset.Errors
                           .Select(toErrorString)
                           .StartWith("");

            PasswordResetSuccessful = Reset.Elements
                                      .Select(_ => true)
                                      .StartWith(false);
        }
Example #5
0
        public TokenResetViewModel(
            IUserAccessManager userAccessManager,
            ITogglDataSource dataSource,
            IDialogService dialogService,
            IMvxNavigationService navigationService,
            IUserPreferences userPreferences,
            IAnalyticsService analyticsService,
            ISchedulerProvider schedulerProvider,
            IRxActionFactory rxActionFactory,
            IInteractorFactory interactorFactory
            )
        {
            Ensure.Argument.IsNotNull(dataSource, nameof(dataSource));
            Ensure.Argument.IsNotNull(userAccessManager, nameof(userAccessManager));
            Ensure.Argument.IsNotNull(dialogService, nameof(dialogService));
            Ensure.Argument.IsNotNull(navigationService, nameof(navigationService));
            Ensure.Argument.IsNotNull(userPreferences, nameof(userPreferences));
            Ensure.Argument.IsNotNull(analyticsService, nameof(analyticsService));
            Ensure.Argument.IsNotNull(schedulerProvider, nameof(schedulerProvider));
            Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory));
            Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory));

            this.dataSource        = dataSource;
            this.userAccessManager = userAccessManager;
            this.dialogService     = dialogService;
            this.navigationService = navigationService;
            this.userPreferences   = userPreferences;
            this.analyticsService  = analyticsService;
            this.schedulerProvider = schedulerProvider;
            this.rxActionFactory   = rxActionFactory;
            this.interactorFactory = interactorFactory;

            Email = emailSubject
                    .DistinctUntilChanged()
                    .AsDriver(schedulerProvider);

            IsPasswordMasked = isPasswordMaskedSubject
                               .DistinctUntilChanged()
                               .AsDriver(schedulerProvider);

            TogglePasswordVisibility = rxActionFactory.FromAction(togglePasswordVisibility);

            Done    = rxActionFactory.FromObservable(done);
            SignOut = rxActionFactory.FromAsync(signout);

            Error = Done.Errors
                    .Select(transformException);

            HasError = Error
                       .Select(error => !string.IsNullOrEmpty(error))
                       .DistinctUntilChanged()
                       .AsDriver(schedulerProvider);

            NextIsEnabled = Password
                            .Select(Multivac.Password.From)
                            .CombineLatest(Done.Executing, (password, isExecuting) => password.IsValid && !isExecuting)
                            .DistinctUntilChanged()
                            .AsDriver(schedulerProvider);
        }
        protected SelectUserCalendarsViewModelBase(
            IUserPreferences userPreferences,
            IInteractorFactory interactorFactory,
            IRxActionFactory rxActionFactory)
        {
            Ensure.Argument.IsNotNull(userPreferences, nameof(userPreferences));
            Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory));
            Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory));

            this.userPreferences = userPreferences;
            InteractorFactory    = interactorFactory;
            this.rxActionFactory = rxActionFactory;

            SelectCalendar = rxActionFactory.FromObservable <SelectableUserCalendarViewModel>(selectCalendar);
        }
        public SelectDefaultWorkspaceViewModel(
            ITogglDataSource dataSource,
            IInteractorFactory interactorFactory,
            INavigationService navigationService,
            IAccessRestrictionStorage accessRestrictionStorage,
            IRxActionFactory rxActionFactory)
        {
            Ensure.Argument.IsNotNull(dataSource, nameof(dataSource));
            Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory));
            Ensure.Argument.IsNotNull(navigationService, nameof(navigationService));
            Ensure.Argument.IsNotNull(accessRestrictionStorage, nameof(accessRestrictionStorage));
            Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory));

            this.dataSource               = dataSource;
            this.interactorFactory        = interactorFactory;
            this.navigationService        = navigationService;
            this.accessRestrictionStorage = accessRestrictionStorage;
            this.rxActionFactory          = rxActionFactory;

            SelectWorkspace = rxActionFactory.FromObservable <SelectableWorkspaceViewModel>(selectWorkspace);
        }
Example #8
0
        public TokenResetViewModel(
            IUserAccessManager userAccessManager,
            ITogglDataSource dataSource,
            INavigationService navigationService,
            IUserPreferences userPreferences,
            IAnalyticsService analyticsService,
            ISchedulerProvider schedulerProvider,
            IRxActionFactory rxActionFactory,
            IInteractorFactory interactorFactory)
            : base(navigationService)
        {
            Ensure.Argument.IsNotNull(dataSource, nameof(dataSource));
            Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory));
            Ensure.Argument.IsNotNull(userPreferences, nameof(userPreferences));
            Ensure.Argument.IsNotNull(analyticsService, nameof(analyticsService));
            Ensure.Argument.IsNotNull(userAccessManager, nameof(userAccessManager));
            Ensure.Argument.IsNotNull(schedulerProvider, nameof(schedulerProvider));
            Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory));

            this.dataSource        = dataSource;
            this.userAccessManager = userAccessManager;
            this.interactorFactory = interactorFactory;

            Done    = rxActionFactory.FromObservable(done);
            SignOut = rxActionFactory.FromAsync(signout);

            Error = Done.Errors
                    .Select(transformException);

            HasError = Error
                       .Select(error => !string.IsNullOrEmpty(error))
                       .DistinctUntilChanged()
                       .AsDriver(schedulerProvider);

            NextIsEnabled = Password
                            .Select(Shared.Password.From)
                            .CombineLatest(Done.Executing, (password, isExecuting) => password.IsValid && !isExecuting)
                            .DistinctUntilChanged()
                            .AsDriver(schedulerProvider);
        }
        public override Task Initialize()
        {
            base.Initialize();

            StartTimeEntry = rxActionFactory.FromObservable <Suggestion, IThreadSafeTimeEntry>(startTimeEntry);

            var appResumedFromBackground = backgroundService
                                           .AppResumedFromBackground
                                           .SelectUnit()
                                           .Skip(1);

            var userCalendarPreferencesChanged = userPreferences
                                                 .EnabledCalendars
                                                 .SelectUnit()
                                                 .Skip(1);

            Suggestions = syncManager.ProgressObservable
                          .Where(progress => progress != SyncProgress.Syncing && progress != SyncProgress.Unknown && !backgroundService.AppIsInBackground)
                          .Throttle(recalculationThrottleDuration, schedulerProvider.DefaultScheduler)
                          .SelectUnit()
                          .StartWith(Unit.Default)
                          .Merge(recalculationRequested)
                          .Merge(appResumedFromBackground)
                          .Merge(userCalendarPreferencesChanged)
                          .SelectMany(_ => getSuggestions())
                          .WithLatestFrom(permissionsChecker.CalendarPermissionGranted, (suggestions, isCalendarAuthorized) => (suggestions, isCalendarAuthorized))
                          .Do(item => trackPresentedSuggestions(item.suggestions, item.isCalendarAuthorized))
                          .Select(item => item.suggestions)
                          .AsDriver(onErrorJustReturn: ImmutableList.Create <Suggestion>(), schedulerProvider: schedulerProvider);

            IsEmpty = Suggestions
                      .Select(suggestions => suggestions.None())
                      .StartWith(true)
                      .AsDriver(onErrorJustReturn: true, schedulerProvider: schedulerProvider);

            return(base.Initialize());
        }
        public EditProjectViewModel(
            ITogglDataSource dataSource,
            IRxActionFactory rxActionFactory,
            IInteractorFactory interactorFactory,
            ISchedulerProvider schedulerProvider,
            INavigationService navigationService)
            : base(navigationService)
        {
            Ensure.Argument.IsNotNull(dataSource, nameof(dataSource));
            Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory));
            Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory));
            Ensure.Argument.IsNotNull(schedulerProvider, nameof(schedulerProvider));

            this.dataSource        = dataSource;
            this.interactorFactory = interactorFactory;

            Name      = new BehaviorRelay <string>("");
            IsPrivate = new BehaviorRelay <bool>(true);

            PickColor     = rxActionFactory.FromObservable <Color>(pickColor);
            PickClient    = rxActionFactory.FromObservable <IThreadSafeClient>(pickClient);
            PickWorkspace = rxActionFactory.FromObservable <IThreadSafeWorkspace>(pickWorkspace);

            var initialWorkspaceObservable = interactorFactory
                                             .GetDefaultWorkspace()
                                             .TrackException <InvalidOperationException, IThreadSafeWorkspace>("EditProjectViewModel.Initialize")
                                             .Execute()
                                             .SelectMany(defaultWorkspaceOrWorkspaceEligibleForProjectCreation)
                                             .Do(initialWorkspace => initialWorkspaceId = initialWorkspace.Id);

            currentWorkspace = initialWorkspaceObservable
                               .Merge(PickWorkspace.Elements)
                               .ShareReplay(1);

            currentClient = currentWorkspace
                            .SelectValue((IThreadSafeClient)null)
                            .Merge(PickClient.Elements)
                            .ShareReplay(1);

            WorkspaceName = currentWorkspace
                            .Select(w => w.Name)
                            .DistinctUntilChanged()
                            .AsDriver(schedulerProvider);

            CanCreatePublicProjects = currentWorkspace
                                      .Select(w => w.Admin)
                                      .DoIf(isAdmin => !isAdmin, _ => IsPrivate.Accept(true))
                                      .DistinctUntilChanged()
                                      .AsDriver(schedulerProvider);

            var clientName = currentClient
                             .Select(client => client?.Name ?? "")
                             .DistinctUntilChanged();

            ClientName = clientName
                         .AsDriver(schedulerProvider);

            Color = PickColor.Elements
                    .StartWith(getRandomColor())
                    .Merge(currentWorkspace
                           .SelectMany(customColorIsEnabled)
                           .SelectMany(customColorsAreAvailable => customColorsAreAvailable
                        ? Observable.Empty <Color>()
                        : Color.FirstAsync().Select(randomColorIfNotDefault)))
                    .DistinctUntilChanged()
                    .AsDriver(schedulerProvider);

            var saveEnabledObservable = Name.Select(checkNameValidity);

            var projectOrClientNameChanged = Observable
                                             .Merge(clientName.SelectUnit(), Name.SelectUnit());

            Save            = rxActionFactory.FromObservable(done, saveEnabledObservable);
            ToggleIsPrivate = rxActionFactory.FromAction(toggleIsPrivate);

            Error = Save.Errors
                    .Select(e => e.Message)
                    .Merge(projectOrClientNameChanged.SelectValue(string.Empty))
                    .AsDriver(schedulerProvider);

            IObservable <IThreadSafeWorkspace> defaultWorkspaceOrWorkspaceEligibleForProjectCreation(IThreadSafeWorkspace defaultWorkspace)
            => defaultWorkspace.IsEligibleForProjectCreation()
                    ? Observable.Return(defaultWorkspace)
                    : interactorFactory.GetAllWorkspaces().Execute()
            .Select(allWorkspaces => allWorkspaces.First(ws => ws.IsEligibleForProjectCreation()));

            IObservable <bool> customColorIsEnabled(IThreadSafeWorkspace workspace)
            => interactorFactory
            .AreCustomColorsEnabledForWorkspace(workspace.Id)
            .Execute();

            Color getRandomColor()
            {
                var randomColorIndex = random.Next(0, Helper.Colors.DefaultProjectColors.Length);

                return(Helper.Colors.DefaultProjectColors[randomColorIndex]);
            }

            Color randomColorIfNotDefault(Color lastColor)
            {
                var hex = lastColor.ToHexString();

                if (DefaultProjectColors.Any(defaultColor => defaultColor == hex))
                {
                    return(lastColor);
                }

                return(getRandomColor());
            }

            bool checkNameValidity(string name)
            => !string.IsNullOrWhiteSpace(name) &&
            name.LengthInBytes() <= Constants.MaxProjectNameLengthInBytes;
        }
        public StartTimeEntryViewModel(
            ITimeService timeService,
            ITogglDataSource dataSource,
            IUserPreferences userPreferences,
            IOnboardingStorage onboardingStorage,
            IInteractorFactory interactorFactory,
            INavigationService navigationService,
            IAnalyticsService analyticsService,
            ISchedulerProvider schedulerProvider,
            IRxActionFactory rxActionFactory)
            : base(navigationService)
        {
            Ensure.Argument.IsNotNull(dataSource, nameof(dataSource));
            Ensure.Argument.IsNotNull(timeService, nameof(timeService));
            Ensure.Argument.IsNotNull(userPreferences, nameof(userPreferences));
            Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory));
            Ensure.Argument.IsNotNull(onboardingStorage, nameof(onboardingStorage));
            Ensure.Argument.IsNotNull(analyticsService, nameof(analyticsService));
            Ensure.Argument.IsNotNull(schedulerProvider, nameof(schedulerProvider));
            Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory));

            this.timeService       = timeService;
            this.userPreferences   = userPreferences;
            this.interactorFactory = interactorFactory;
            this.analyticsService  = analyticsService;
            this.schedulerProvider = schedulerProvider;

            DataSource        = dataSource;
            OnboardingStorage = onboardingStorage;

            TextFieldInfo        = textFieldInfo.AsDriver(schedulerProvider);
            IsBillable           = isBillable.AsDriver(schedulerProvider);
            IsSuggestingTags     = isSuggestingTags.AsDriver(schedulerProvider);
            IsSuggestingProjects = isSuggestingProjects.AsDriver(schedulerProvider);
            IsBillableAvailable  = isBillableAvailable.AsDriver(schedulerProvider);
            DisplayedTime        = displayedTime
                                   .Select(time => time.ToFormattedString(DurationFormat.Improved))
                                   .AsDriver(schedulerProvider);

            Done                     = rxActionFactory.FromObservable <IThreadSafeTimeEntry>(done);
            DurationTapped           = rxActionFactory.FromAction(durationTapped);
            ToggleBillable           = rxActionFactory.FromAction(toggleBillable);
            SetStartDate             = rxActionFactory.FromAsync(setStartDate);
            ChangeTime               = rxActionFactory.FromAsync(changeTime);
            ToggleTagSuggestions     = rxActionFactory.FromAction(toggleTagSuggestions);
            ToggleProjectSuggestions = rxActionFactory.FromAction(toggleProjectSuggestions);
            SelectSuggestion         = rxActionFactory.FromAsync <AutocompleteSuggestion>(selectSuggestion);
            SetRunningTime           = rxActionFactory.FromAction <TimeSpan>(setRunningTime);
            ToggleTasks              = rxActionFactory.FromAction <ProjectSuggestion>(toggleTasks);
            SetTextSpans             = rxActionFactory.FromAction <IImmutableList <ISpan> >(setTextSpans);

            var queryByType = queryByTypeSubject
                              .AsObservable()
                              .SelectMany(type => interactorFactory.GetAutocompleteSuggestions(new QueryInfo("", type)).Execute());

            var queryByText = textFieldInfo
                              .SelectMany(setBillableValues)
                              .Select(QueryInfo.ParseFieldInfo)
                              .Do(onParsedQuery)
                              .ObserveOn(schedulerProvider.BackgroundScheduler)
                              .SelectMany(query => interactorFactory.GetAutocompleteSuggestions(query).Execute());

            Suggestions = Observable.Merge(queryByText, queryByType)
                          .Select(filter)
                          .Select(group)
                          .CombineLatest(expandedProjects, (groups, _) => groups)
                          .Select(toCollections)
                          .Select(addStaticElements)
                          .AsDriver(schedulerProvider);
        }
Example #12
0
        public override async Task Initialize()
        {
            await base.Initialize();

            await TimeEntriesViewModel.Initialize();

            await SuggestionsViewModel.Initialize();

            await RatingViewModel.Initialize();

            SyncProgressState = dataSource
                                .SyncManager
                                .ProgressObservable
                                .AsDriver(SchedulerProvider);

            var isWelcome = onboardingStorage.IsNewUser;

            var noTimeEntries = Observable
                                .CombineLatest(TimeEntriesViewModel.Empty, SuggestionsViewModel.IsEmpty,
                                               (isTimeEntryEmpty, isSuggestionEmpty) => isTimeEntryEmpty && isSuggestionEmpty)
                                .DistinctUntilChanged();

            ShouldShowEmptyState = ObservableAddons.CombineLatestAll(
                isWelcome,
                noTimeEntries
                )
                                   .DistinctUntilChanged()
                                   .AsDriver(SchedulerProvider);

            ShouldShowWelcomeBack = ObservableAddons.CombineLatestAll(
                isWelcome.Select(b => !b),
                noTimeEntries
                )
                                    .StartWith(false)
                                    .DistinctUntilChanged()
                                    .AsDriver(SchedulerProvider);

            IsInManualMode = userPreferences
                             .IsManualModeEnabledObservable
                             .AsDriver(SchedulerProvider);

            ShouldShowRunningTimeEntryNotification = userPreferences.AreRunningTimerNotificationsEnabledObservable;
            ShouldShowStoppedTimeEntryNotification = userPreferences.AreStoppedTimerNotificationsEnabledObservable;

            CurrentRunningTimeEntry = dataSource
                                      .TimeEntries
                                      .CurrentlyRunningTimeEntry
                                      .AsDriver(SchedulerProvider);

            IsTimeEntryRunning = CurrentRunningTimeEntry
                                 .Select(te => te != null)
                                 .DistinctUntilChanged()
                                 .AsDriver(SchedulerProvider);

            var durationObservable = dataSource
                                     .Preferences
                                     .Current
                                     .Select(preferences => preferences.DurationFormat);

            ElapsedTime = TimeService
                          .CurrentDateTimeObservable
                          .CombineLatest(CurrentRunningTimeEntry, (now, te) => (now - te?.Start) ?? TimeSpan.Zero)
                          .CombineLatest(durationObservable, (duration, format) => duration.ToFormattedString(format))
                          .AsDriver(SchedulerProvider);

            NumberOfSyncFailures = interactorFactory
                                   .GetItemsThatFailedToSync()
                                   .Execute()
                                   .Select(i => i.Count())
                                   .AsDriver(SchedulerProvider);

            ShouldReloadTimeEntryLog = Observable.Merge(
                TimeService.MidnightObservable.SelectUnit(),
                TimeService.SignificantTimeChangeObservable.SelectUnit())
                                       .AsDriver(SchedulerProvider);

            Refresh           = rxActionFactory.FromAsync(refresh);
            OpenReports       = rxActionFactory.FromAsync(openReports);
            OpenSettings      = rxActionFactory.FromAsync(openSettings);
            OpenSyncFailures  = rxActionFactory.FromAsync(openSyncFailures);
            SelectTimeEntry   = rxActionFactory.FromAsync <long>(timeEntrySelected);
            DeleteTimeEntry   = rxActionFactory.FromObservable <TimeEntryViewModel>(deleteTimeEntry);
            ContinueTimeEntry = rxActionFactory.FromObservable <TimeEntryViewModel>(continueTimeEntry);
            StartTimeEntry    = rxActionFactory.FromAsync <bool>(startTimeEntry, IsTimeEntryRunning.Invert());
            StopTimeEntry     = rxActionFactory.FromAsync <TimeEntryStopOrigin>(stopTimeEntry, IsTimeEntryRunning);

            switch (urlNavigationAction)
            {
            case ApplicationUrls.Main.Action.Continue:
                await continueMostRecentEntry();

                break;

            case ApplicationUrls.Main.Action.Stop:
                await stopTimeEntry(TimeEntryStopOrigin.Deeplink);

                break;
            }

            ratingViewExperiment
            .RatingViewShouldBeVisible
            .Subscribe(presentRatingViewIfNeeded)
            .DisposedBy(disposeBag);

            onboardingStorage.StopButtonWasTappedBefore
            .Subscribe(hasBeen => hasStopButtonEverBeenUsed = hasBeen)
            .DisposedBy(disposeBag);

            interactorFactory.GetDefaultWorkspace()
            .TrackException <InvalidOperationException, IThreadSafeWorkspace>("MainViewModel.Initialize")
            .Execute()
            .Subscribe(intentDonationService.SetDefaultShortcutSuggestions)
            .DisposedBy(disposeBag);

            dataSource
            .Workspaces
            .Created
            .Subscribe(_ => onWorkspaceCreated())
            .DisposedBy(disposeBag);

            dataSource
            .Workspaces
            .Updated
            .Subscribe(onWorkspaceUpdated)
            .DisposedBy(disposeBag);
        }
Example #13
0
        public override async Task Initialize()
        {
            await base.Initialize();

            interactorFactory.GetCurrentUser().Execute()
            .Select(u => u.Id)
            .Subscribe(analyticsService.SetAppCenterUserId);

            await SuggestionsViewModel.Initialize();

            await RatingViewModel.Initialize();

            widgetsService.Start();

            SyncProgressState = syncManager.ProgressObservable
                                .AsDriver(schedulerProvider);

            var isWelcome = OnboardingStorage.IsNewUser;

            var noTimeEntries = Observable
                                .CombineLatest(TimeEntriesViewModel.Empty, SuggestionsViewModel.IsEmpty,
                                               (isTimeEntryEmpty, isSuggestionEmpty) => isTimeEntryEmpty && isSuggestionEmpty)
                                .DistinctUntilChanged();

            ShouldShowEmptyState = ObservableAddons.CombineLatestAll(
                isWelcome,
                noTimeEntries
                )
                                   .DistinctUntilChanged()
                                   .AsDriver(schedulerProvider);

            ShouldShowWelcomeBack = ObservableAddons.CombineLatestAll(
                isWelcome.Select(b => !b),
                noTimeEntries
                )
                                    .StartWith(false)
                                    .DistinctUntilChanged()
                                    .AsDriver(schedulerProvider);

            IsInManualMode = userPreferences
                             .IsManualModeEnabledObservable
                             .AsDriver(schedulerProvider);

            ShouldShowRunningTimeEntryNotification = userPreferences.AreRunningTimerNotificationsEnabledObservable;
            ShouldShowStoppedTimeEntryNotification = userPreferences.AreStoppedTimerNotificationsEnabledObservable;

            CurrentRunningTimeEntry = dataSource.TimeEntries
                                      .CurrentlyRunningTimeEntry
                                      .AsDriver(schedulerProvider);

            IsTimeEntryRunning = dataSource.TimeEntries
                                 .CurrentlyRunningTimeEntry
                                 .Select(te => te != null)
                                 .DistinctUntilChanged()
                                 .AsDriver(schedulerProvider);

            var durationObservable = dataSource
                                     .Preferences
                                     .Current
                                     .Select(preferences => preferences.DurationFormat);

            ElapsedTime = TimeService
                          .CurrentDateTimeObservable
                          .CombineLatest(CurrentRunningTimeEntry, (now, te) => (now - te?.Start) ?? TimeSpan.Zero)
                          .CombineLatest(durationObservable, (duration, format) => duration.ToFormattedString(format))
                          .AsDriver(schedulerProvider);

            NumberOfSyncFailures = interactorFactory
                                   .GetItemsThatFailedToSync()
                                   .Execute()
                                   .Select(i => i.Count())
                                   .AsDriver(schedulerProvider);

            ShouldReloadTimeEntryLog = Observable.Merge(
                TimeService.MidnightObservable.SelectUnit(),
                TimeService.SignificantTimeChangeObservable.SelectUnit())
                                       .AsDriver(schedulerProvider);

            Refresh           = rxActionFactory.FromAsync(refresh);
            OpenSettings      = rxActionFactory.FromAsync(openSettings);
            OpenSyncFailures  = rxActionFactory.FromAsync(openSyncFailures);
            SelectTimeEntry   = rxActionFactory.FromAsync <EditTimeEntryInfo>(timeEntrySelected);
            ContinueTimeEntry = rxActionFactory.FromObservable <ContinueTimeEntryInfo, IThreadSafeTimeEntry>(continueTimeEntry);
            StartTimeEntry    = rxActionFactory.FromAsync <bool>(startTimeEntry, IsTimeEntryRunning.Invert());
            StopTimeEntry     = rxActionFactory.FromObservable <TimeEntryStopOrigin>(stopTimeEntry, IsTimeEntryRunning);

            ShouldShowRatingView = Observable.Merge(
                ratingViewExperiment.RatingViewShouldBeVisible,
                RatingViewModel.HideRatingView.SelectValue(false),
                hideRatingView.AsObservable().SelectValue(false)
                )
                                   .Select(canPresentRating)
                                   .DistinctUntilChanged()
                                   .Do(trackRatingViewPresentation)
                                   .AsDriver(schedulerProvider);

            OnboardingStorage.StopButtonWasTappedBefore
            .Subscribe(hasBeen => hasStopButtonEverBeenUsed = hasBeen)
            .DisposedBy(disposeBag);

            if (platformInfo.Platform == Platform.Giskard)
            {
                analyticsService.ApplicationInstallLocation.Track(platformInfo.InstallLocation);
            }

            SyncProgressState
            .Subscribe(postAccessibilityAnnouncementAboutSync)
            .DisposedBy(disposeBag);
        }