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); }