public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            AddProjectBubbleLabel.Text = Resources.AddProjectBubbleText;

            prepareViews();
            prepareOnboarding();

            var source = new StartTimeEntryTableViewSource(SuggestionsTableView);

            SuggestionsTableView.Source = source;

            source.Rx().ModelSelected()
            .Subscribe(ViewModel.SelectSuggestion.Inputs)
            .DisposedBy(DisposeBag);

            ViewModel.Suggestions
            .Subscribe(SuggestionsTableView.Rx().ReloadSections(source))
            .DisposedBy(DisposeBag);

            source.ToggleTasks
            .Subscribe(ViewModel.ToggleTasks.Inputs)
            .DisposedBy(DisposeBag);

            TimeInput.Rx().Duration()
            .Subscribe(ViewModel.SetRunningTime.Inputs)
            .DisposedBy(DisposeBag);

            //Text

            ViewModel.DisplayedTime
            .Subscribe(TimeLabel.Rx().Text())
            .DisposedBy(DisposeBag);

            Placeholder.Text = ViewModel.PlaceholderText;

            // Buttons
            UIColor booleanToColor(bool b) => b
                ? Colors.StartTimeEntry.ActiveButton.ToNativeColor()
                : Colors.StartTimeEntry.InactiveButton.ToNativeColor();

            ViewModel.IsBillable
            .Select(booleanToColor)
            .Subscribe(BillableButton.Rx().TintColor())
            .DisposedBy(DisposeBag);

            ViewModel.IsSuggestingTags
            .Select(booleanToColor)
            .Subscribe(TagsButton.Rx().TintColor())
            .DisposedBy(DisposeBag);

            ViewModel.IsSuggestingProjects
            .Select(booleanToColor)
            .Subscribe(ProjectsButton.Rx().TintColor())
            .DisposedBy(DisposeBag);

            //Visibility
            ViewModel.IsBillableAvailable
            .Select(b => b ? (nfloat)42 : 0)
            .Subscribe(BillableButtonWidthConstraint.Rx().Constant())
            .DisposedBy(DisposeBag);

            // Actions
            CloseButton.Rx().Tap()
            .Subscribe(ViewModel.CloseWithDefaultResult)
            .DisposedBy(DisposeBag);

            DoneButton.Rx()
            .BindAction(ViewModel.Done)
            .DisposedBy(DisposeBag);

            ViewModel.Done.Elements
            .Subscribe(IosDependencyContainer.Instance.IntentDonationService.DonateStartTimeEntry)
            .DisposedBy(DisposeBag);

            BillableButton.Rx()
            .BindAction(ViewModel.ToggleBillable)
            .DisposedBy(DisposeBag);

            StartDateButton.Rx()
            .BindAction(ViewModel.SetStartDate)
            .DisposedBy(DisposeBag);

            DateTimeButton.Rx()
            .BindAction(ViewModel.ChangeTime)
            .DisposedBy(DisposeBag);

            TagsButton.Rx()
            .BindAction(ViewModel.ToggleTagSuggestions)
            .DisposedBy(DisposeBag);

            ProjectsButton.Rx()
            .BindAction(ViewModel.ToggleProjectSuggestions)
            .DisposedBy(DisposeBag);

            // Reactive
            ViewModel.TextFieldInfo
            .DistinctUntilChanged()
            .Subscribe(onTextFieldInfo)
            .DisposedBy(DisposeBag);

            DescriptionTextView.Rx().AttributedText()
            .Select(attributedString => attributedString.Length == 0)
            .Subscribe(isDescriptionEmptySubject)
            .DisposedBy(DisposeBag);

            Observable.CombineLatest(
                DescriptionTextView.Rx().AttributedText().SelectUnit(),
                DescriptionTextView.Rx().CursorPosition().SelectUnit()
                )
            .Select(_ => DescriptionTextView.AttributedText)     // Programatically changing the text doesn't send an event, that's why we do this, to get the last version of the text
            .Do(updatePlaceholder)
            .Select(text => text.AsSpans((int)DescriptionTextView.SelectedRange.Location).ToIImmutableList())
            .Subscribe(ViewModel.SetTextSpans.Inputs)
            .DisposedBy(DisposeBag);
        }
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            prepareViews();
            prepareSiriButton();
            localizeLabels();

            BillableSwitch.Rx().Changed()
            .Select(_ => BillableSwitch.On)
            .Subscribe(ViewModel.IsBillable.Accept)
            .DisposedBy(DisposeBag);

            TagsTextView.Rx()
            .BindAction(ViewModel.SelectTags)
            .DisposedBy(DisposeBag);

            ViewModel.HasTags
            .Invert()
            .Subscribe(AddTagsView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.HasTags
            .Subscribe(TagsTextView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.TagNames
            .Select(tagsListToAttributedString.Convert)
            .Subscribe(TagsTextView.Rx().AttributedTextObserver())
            .DisposedBy(DisposeBag);

            SelectTagsView.Rx()
            .BindAction(ViewModel.SelectTags)
            .DisposedBy(DisposeBag);

            SelectProjectView.Rx()
            .BindAction(ViewModel.SelectProject)
            .DisposedBy(DisposeBag);

            ViewModel.ProjectClientTask
            .Select(info => projectTaskClientToAttributedString.Convert(
                        info.Project,
                        info.Task,
                        info.Client,
                        new Color(info.ProjectColor).ToNativeColor()))
            .Subscribe(ProjectTaskClientLabel.Rx().AttributedText())
            .DisposedBy(DisposeBag);

            ViewModel.ProjectClientTask
            .Select(info => info.HasProject)
            .Subscribe(ProjectTaskClientLabel.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.ProjectClientTask
            .Select(info => !info.HasProject)
            .Subscribe(AddProjectAndTaskView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.IsBillable
            .Subscribe(BillableSwitch.Rx().CheckedObserver())
            .DisposedBy(DisposeBag);

            ViewModel.IsBillableAvailable
            .Subscribe(BillableView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.PasteFromClipboard
            .Invert()
            .Subscribe(DescriptionTextView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.PasteFromClipboard
            .Subscribe(DescriptionUsingClipboardWrapperView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.PasteFromClipboard
            .Subscribe(PasteFromClipboardHintView.Rx().IsVisible())
            .DisposedBy(DisposeBag);

            ViewModel.PasteFromClipboard
            .Select(enabled => enabled ? pasteFromClipboardButtonImageEnabled : pasteFromClipboardButtonImage)
            .Subscribe(image =>
            {
                PasteFromClipboardButton.SetImage(image, UIControlState.Normal);
            })
            .DisposedBy(DisposeBag);

            ViewModel.PasteFromClipboard
            .Subscribe(enabled =>
            {
                if (enabled)
                {
                    DescriptionTextView.ResignFirstResponder();
                }
                else
                {
                    DescriptionTextView.BecomeFirstResponder();
                }
            })
            .DisposedBy(DisposeBag);

            DescriptionTextView.TextObservable
            .Subscribe(ViewModel.Description.Accept)
            .DisposedBy(DisposeBag);

            PasteFromClipboardButton.Rx()
            .BindAction(ViewModel.SelectClipboard)
            .DisposedBy(DisposeBag);
        }
Example #3
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            AddProjectBubbleLabel.Text = Resources.AddProjectBubbleText;

            prepareViews();
            prepareOnboarding();

            var source = new StartTimeEntryTableViewSource(SuggestionsTableView);

            SuggestionsTableView.Source = source;
            source.ToggleTasksCommand   = new MvxCommand <ProjectSuggestion>(toggleTaskSuggestions);

            var invertedVisibilityConverter = new MvxInvertedVisibilityValueConverter();
            var invertedBoolConverter       = new BoolToConstantValueConverter <bool>(false, true);
            var buttonColorConverter        = new BoolToConstantValueConverter <UIColor>(
                Color.StartTimeEntry.ActiveButton.ToNativeColor(),
                Color.StartTimeEntry.InactiveButton.ToNativeColor()
                );
            var durationCombiner = new DurationValueCombiner();

            var bindingSet = this.CreateBindingSet <StartTimeEntryViewController, StartTimeEntryViewModel>();

            //TableView
            bindingSet.Bind(source)
            .For(v => v.ObservableCollection)
            .To(vm => vm.Suggestions);

            bindingSet.Bind(source)
            .For(v => v.UseGrouping)
            .To(vm => vm.UseGrouping);

            bindingSet.Bind(source)
            .For(v => v.SelectSuggestionCommand)
            .To(vm => vm.SelectSuggestionCommand);

            bindingSet.Bind(source)
            .For(v => v.CreateCommand)
            .To(vm => vm.CreateCommand);

            bindingSet.Bind(source)
            .For(v => v.IsSuggestingProjects)
            .To(vm => vm.IsSuggestingProjects);

            bindingSet.Bind(source)
            .For(v => v.Text)
            .To(vm => vm.CurrentQuery);

            bindingSet.Bind(source)
            .For(v => v.SuggestCreation)
            .To(vm => vm.SuggestCreation);

            bindingSet.Bind(source)
            .For(v => v.ShouldShowNoTagsInfoMessage)
            .To(vm => vm.ShouldShowNoTagsInfoMessage);

            bindingSet.Bind(source)
            .For(v => v.ShouldShowNoProjectsInfoMessage)
            .To(vm => vm.ShouldShowNoProjectsInfoMessage);

            //Text
            bindingSet.Bind(TimeInput)
            .For(v => v.Duration)
            .To(vm => vm.DisplayedTime)
            .Mode(MvxBindingMode.OneWayToSource);

            bindingSet.Bind(TimeLabel)
            .For(v => v.Text)
            .ByCombining(durationCombiner,
                         vm => vm.DisplayedTime,
                         vm => vm.DisplayedTimeFormat);

            bindingSet.Bind(Placeholder)
            .To(vm => vm.PlaceholderText);

            //Buttons
            bindingSet.Bind(TagsButton)
            .For(v => v.TintColor)
            .To(vm => vm.IsSuggestingTags)
            .WithConversion(buttonColorConverter);

            bindingSet.Bind(BillableButton)
            .For(v => v.TintColor)
            .To(vm => vm.IsBillable)
            .WithConversion(buttonColorConverter);

            bindingSet.Bind(ProjectsButton)
            .For(v => v.TintColor)
            .To(vm => vm.IsSuggestingProjects)
            .WithConversion(buttonColorConverter);

            //Visibility
            bindingSet.Bind(BillableButtonWidthConstraint)
            .For(v => v.Constant)
            .To(vm => vm.IsBillableAvailable)
            .WithConversion(new BoolToConstantValueConverter <nfloat>(42, 0));

            //Commands
            bindingSet.Bind(DoneButton).To(vm => vm.DoneCommand);
            bindingSet.Bind(CloseButton).To(vm => vm.BackCommand);
            bindingSet.Bind(BillableButton).To(vm => vm.ToggleBillableCommand);
            bindingSet.Bind(StartDateButton).To(vm => vm.SetStartDateCommand);
            bindingSet.Bind(DateTimeButton).To(vm => vm.ChangeTimeCommand);
            bindingSet.Bind(TagsButton).To(vm => vm.ToggleTagSuggestionsCommand);
            bindingSet.Bind(ProjectsButton).To(vm => vm.ToggleProjectSuggestionsCommand);

            bindingSet.Apply();

            // Reactive
            ViewModel.TextFieldInfoObservable
            .Subscribe(onTextFieldInfo)
            .DisposedBy(DisposeBag);

            DescriptionTextView.Rx().AttributedText()
            .Select(attributedString => attributedString.Length == 0)
            .Subscribe(isDescriptionEmptySubject)
            .DisposedBy(DisposeBag);

            DescriptionTextView.Rx().AttributedText()
            .CombineLatest(DescriptionTextView.Rx().CursorPosition(), (text, _) => text)
            .Where(_ => !isUpdatingDescriptionField)
            .SubscribeOn(ThreadPoolScheduler.Instance)
            .Do(updatePlaceholder)
            .Select(text => text.AsImmutableSpans((int)DescriptionTextView.SelectedRange.Location))
            .ObserveOn(SynchronizationContext.Current)
            .Subscribe(async info => await ViewModel.OnTextFieldInfoFromView(info))
            .DisposedBy(DisposeBag);

            source.TableRenderCallback = () =>
            {
                ViewModel.StopSuggestionsRenderingStopwatch();
            };
        }