public override void Prepare(DateTimePickerParameters parameter)
 {
     Mode            = parameter.Mode;
     MinDate         = parameter.MinDate;
     MaxDate         = parameter.MaxDate;
     CurrentDateTime = new BehaviorRelay <DateTimeOffset>(parameter.CurrentDate, sanitizeBasedOnMode);
 }
        public override Task Initialize(DateTimePickerParameters dateTimePicker)
        {
            defaultResult = dateTimePicker.CurrentDate;

            Mode            = dateTimePicker.Mode;
            MinDate         = dateTimePicker.MinDate;
            MaxDate         = dateTimePicker.MaxDate;
            CurrentDateTime = new BehaviorRelay <DateTimeOffset>(dateTimePicker.CurrentDate, sanitizeBasedOnMode);

            return(base.Initialize(dateTimePicker));
        }
Exemple #3
0
        public EditTimeEntryViewModel(
            ITimeService timeService,
            ITogglDataSource dataSource,
            ISyncManager syncManager,
            IInteractorFactory interactorFactory,
            IMvxNavigationService navigationService,
            IOnboardingStorage onboardingStorage,
            IDialogService dialogService,
            IAnalyticsService analyticsService,
            IStopwatchProvider stopwatchProvider,
            IRxActionFactory actionFactory,
            ISchedulerProvider schedulerProvider)
        {
            Ensure.Argument.IsNotNull(dataSource, nameof(dataSource));
            Ensure.Argument.IsNotNull(syncManager, nameof(syncManager));
            Ensure.Argument.IsNotNull(timeService, nameof(timeService));
            Ensure.Argument.IsNotNull(dialogService, nameof(dialogService));
            Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory));
            Ensure.Argument.IsNotNull(onboardingStorage, nameof(onboardingStorage));
            Ensure.Argument.IsNotNull(navigationService, nameof(navigationService));
            Ensure.Argument.IsNotNull(analyticsService, nameof(analyticsService));
            Ensure.Argument.IsNotNull(stopwatchProvider, nameof(stopwatchProvider));
            Ensure.Argument.IsNotNull(schedulerProvider, nameof(schedulerProvider));
            Ensure.Argument.IsNotNull(actionFactory, nameof(actionFactory));

            this.dataSource        = dataSource;
            this.syncManager       = syncManager;
            this.timeService       = timeService;
            this.dialogService     = dialogService;
            this.interactorFactory = interactorFactory;
            this.navigationService = navigationService;
            this.analyticsService  = analyticsService;
            this.stopwatchProvider = stopwatchProvider;
            this.schedulerProvider = schedulerProvider;
            this.actionFactory     = actionFactory;
            OnboardingStorage      = onboardingStorage;

            workspaceIdSubject
            .Where(id => id.HasValue)
            .Subscribe(id => workspaceId = id.Value)
            .DisposedBy(disposeBag);

            isEditingDescriptionSubject = new BehaviorSubject <bool>(false);
            Description = new BehaviorRelay <string>(string.Empty, CommonFunctions.Trim);

            projectClientTaskSubject = new BehaviorSubject <ProjectClientTaskInfo>(ProjectClientTaskInfo.Empty);
            ProjectClientTask        = projectClientTaskSubject
                                       .AsDriver(ProjectClientTaskInfo.Empty, schedulerProvider);

            IsBillableAvailable = workspaceIdSubject
                                  .Where(id => id.HasValue)
                                  .SelectMany(workspaceId => interactorFactory.IsBillableAvailableForWorkspace(workspaceId.Value).Execute())
                                  .DistinctUntilChanged()
                                  .AsDriver(false, schedulerProvider);

            isBillableSubject = new BehaviorSubject <bool>(false);
            IsBillable        = isBillableSubject
                                .DistinctUntilChanged()
                                .AsDriver(false, schedulerProvider);

            startTimeSubject = new BehaviorSubject <DateTimeOffset>(DateTimeOffset.UtcNow);
            var startTimeObservable = startTimeSubject.DistinctUntilChanged();

            StartTime = startTimeObservable
                        .AsDriver(default(DateTimeOffset), schedulerProvider);

            var now = timeService.CurrentDateTimeObservable.StartWith(timeService.CurrentDateTime);

            durationSubject = new ReplaySubject <TimeSpan?>(bufferSize: 1);
            Duration        =
                durationSubject
                .Select(duration
                        => duration.HasValue
                            ? Observable.Return(duration.Value)
                            : now.CombineLatest(
                            startTimeObservable,
                            (currentTime, startTime) => currentTime - startTime))
                .Switch()
                .DistinctUntilChanged()
                .AsDriver(TimeSpan.Zero, schedulerProvider);

            var stopTimeObservable = Observable.CombineLatest(startTimeObservable, durationSubject, calculateStopTime)
                                     .DistinctUntilChanged();

            StopTime = stopTimeObservable
                       .AsDriver(null, schedulerProvider);

            var isTimeEntryRunningObservable = stopTimeObservable
                                               .Select(stopTime => !stopTime.HasValue)
                                               .Do(value => isRunning = value)
                                               .DistinctUntilChanged();

            IsTimeEntryRunning = isTimeEntryRunningObservable
                                 .AsDriver(false, schedulerProvider);

            tagsSubject = new BehaviorSubject <IEnumerable <IThreadSafeTag> >(Enumerable.Empty <IThreadSafeTag>());
            Tags        = tagsSubject
                          .Select(tags => tags.Select(ellipsize).ToImmutableList())
                          .AsDriver(ImmutableList <string> .Empty, schedulerProvider);

            isInaccessibleSubject = new BehaviorSubject <bool>(false);
            IsInaccessible        = isInaccessibleSubject
                                    .DistinctUntilChanged()
                                    .AsDriver(false, schedulerProvider);

            syncErrorMessageSubject = new BehaviorSubject <string>(string.Empty);
            SyncErrorMessage        = syncErrorMessageSubject
                                      .Select(error => error ?? string.Empty)
                                      .DistinctUntilChanged()
                                      .AsDriver(string.Empty, schedulerProvider);

            IsSyncErrorMessageVisible = syncErrorMessageSubject
                                        .Select(error => !string.IsNullOrEmpty(error))
                                        .DistinctUntilChanged()
                                        .AsDriver(false, schedulerProvider);

            Preferences = interactorFactory.GetPreferences().Execute()
                          .AsDriver(null, schedulerProvider);

            // Actions
            Close                   = actionFactory.FromAsync(closeWithConfirmation);
            SelectProject           = actionFactory.FromAsync(selectProject);
            SelectTags              = actionFactory.FromAsync(selectTags);
            ToggleBillable          = actionFactory.FromAction(toggleBillable);
            EditTimes               = actionFactory.FromAsync <EditViewTapSource>(editTimes);
            SelectStartDate         = actionFactory.FromAsync(selectStartDate);
            StopTimeEntry           = actionFactory.FromAction(stopTimeEntry, isTimeEntryRunningObservable);
            DismissSyncErrorMessage = actionFactory.FromAction(dismissSyncErrorMessage);
            Save   = actionFactory.FromAsync(save);
            Delete = actionFactory.FromAsync(delete);
        }
        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;
        }