Example #1
0
        async Task LoadSource(Uri fileUri)
        {
            var fontSize = (int)UIFont.PreferredSubheadline.PointSize;
            var content  = System.IO.File.ReadAllText(fileUri.LocalPath, System.Text.Encoding.UTF8);

            if (ViewModel.IsMarkdown)
            {
                var markdownContent = await Mvx.Resolve <IApplicationService>().Client.Markdown.GetMarkdown(content);

                var model       = new DescriptionModel(markdownContent, fontSize);
                var htmlContent = new MarkdownView {
                    Model = model
                };
                LoadContent(htmlContent.GenerateString());
            }
            else
            {
                var zoom        = UIDevice.CurrentDevice.UserInterfaceIdiom != UIUserInterfaceIdiom.Phone;
                var model       = new SourceBrowserModel(content, "idea", fontSize, zoom, fileUri.LocalPath);
                var contentView = new SyntaxHighlighterView {
                    Model = model
                };
                LoadContent(contentView.GenerateString());
            }
        }
Example #2
0
        protected virtual void LoadSource(Uri fileUri)
        {
            if (ViewModel.IsMarkdown)
            {
                var content     = System.IO.File.ReadAllText(fileUri.LocalPath, System.Text.Encoding.UTF8);
                var htmlContent = new MarkdownView {
                    Model = content
                };
                LoadContent(htmlContent.GenerateString());
            }
            else
            {
                var content    = System.IO.File.ReadAllText(fileUri.LocalPath, System.Text.Encoding.UTF8);
                var contentStr = new SyntaxHighlighterView
                {
                    Model = new SourceBrowserModel
                    {
                        Content = content,
                        Theme   = ViewModel.Theme ?? "idea"
                    }
                }.GenerateString();

                LoadContent(contentStr);
            }
        }
Example #3
0
        void SegmentValueChanged(object sender, EventArgs e)
        {
            if (_viewSegment.SelectedSegment == 0)
            {
                if (_previewView != null)
                {
                    _previewView.RemoveFromSuperview();
                    _previewView.Dispose();
                    _previewView = null;
                }

                Add(TextView);
                TextView.BecomeFirstResponder();
            }
            else
            {
                if (_previewView == null)
                {
                    _previewView = new UIWebView(this.View.Bounds);
                }

                TextView.RemoveFromSuperview();
                Add(_previewView);

                var markdownService = IoC.Resolve <IMarkdownService>();
                var markdownView    = new MarkdownView()
                {
                    Model = markdownService.Convert(TextView.Text)
                };
                _previewView.LoadHtmlString(markdownView.GenerateString(), null);
            }
        }
Example #4
0
 protected override void LoadSource(Uri fileUri)
 {
     if (ViewModel.IsMarkdown)
     {
         var content     = System.IO.File.ReadAllText(fileUri.LocalPath, System.Text.Encoding.UTF8);
         var htmlContent = new MarkdownView {
             Model = content
         };
         LoadContent(htmlContent.GenerateString());
     }
     else
     {
         base.LoadSource(fileUri);
     }
 }
Example #5
0
        protected MarkdownComposerView(IMarkdownService markdownService)
        {
            TextView.Font     = UIFont.SystemFontOfSize(16f);
            TextView.Changed += (sender, e) => ViewModel.Text = TextView.Text;

            this.WhenAnyValue(x => x.ViewModel.Text)
            .Subscribe(x => Text = x);


            this.WhenAnyValue(x => x.ViewModel.PostToImgurCommand)
            .Select(x => x == null ? null : new MarkdownAccessoryView(TextView, ViewModel.PostToImgurCommand))
            .Subscribe(x => TextView.InputAccessoryView = x);

            _viewSegment = new UISegmentedControl(new [] { "Compose", "Preview" });
            _viewSegment.SelectedSegment = 0;
            NavigationItem.TitleView     = _viewSegment;
            _viewSegment.ValueChanged   += (sender, e) =>
            {
                if (_viewSegment.SelectedSegment == 0)
                {
                    if (_previewView != null)
                    {
                        _previewView.RemoveFromSuperview();
                        _previewView.Dispose();
                        _previewView = null;
                    }

                    Add(TextView);
                    TextView.BecomeFirstResponder();
                }
                else
                {
                    if (_previewView == null)
                    {
                        _previewView = new UIWebView(this.View.Bounds);
                    }

                    TextView.RemoveFromSuperview();
                    Add(_previewView);

                    var markdownView = new MarkdownView {
                        Model = markdownService.Convert(TextView.Text)
                    };
                    _previewView.LoadHtmlString(markdownView.GenerateString(), null);
                }
            };
        }
Example #6
0
        protected MarkdownComposerViewController(IMarkdownService markdownService)
        {
            TextView.Font               = UIFont.PreferredBody;
            TextView.Changed           += (sender, e) => ViewModel.Text = TextView.Text;
            TextView.InputAccessoryView = new MarkdownAccessoryView(TextView);

            this.WhenAnyValue(x => x.ViewModel.Text)
            .Subscribe(x => Text = x);

            var viewSegment = new UISegmentedControl(new [] { "Compose", "Preview" });

            viewSegment.SelectedSegment = 0;
            NavigationItem.TitleView    = viewSegment;
            viewSegment.ValueChanged   += (sender, e) =>
            {
                if (viewSegment.SelectedSegment == 0)
                {
                    if (_previewView != null)
                    {
                        _previewView.RemoveFromSuperview();
                        _previewView.Dispose();
                        _previewView = null;
                    }

                    Add(TextView);
                    TextView.BecomeFirstResponder();
                }
                else
                {
                    if (_previewView == null)
                    {
                        _previewView = new UIWebView(this.View.Bounds);
                    }

                    TextView.RemoveFromSuperview();
                    Add(_previewView);

                    var markdown     = markdownService.Convert(TextView.Text);
                    var model        = new DescriptionModel(markdown, (int)UIFont.PreferredSubheadline.PointSize);
                    var markdownView = new MarkdownView {
                        Model = model
                    };
                    _previewView.LoadHtmlString(markdownView.GenerateString(), null);
                }
            };
        }
Example #7
0
        async Task LoadSource(Uri fileUri)
        {
            var fontSize = (int)UIFont.PreferredSubheadline.PointSize;
            var content = System.IO.File.ReadAllText(fileUri.LocalPath, System.Text.Encoding.UTF8);

            if (ViewModel.IsMarkdown)
            {
                var markdownContent = await Mvx.Resolve<IApplicationService>().Client.Markdown.GetMarkdown(content);
                var model = new DescriptionModel(markdownContent, fontSize);
                var htmlContent = new MarkdownView { Model = model };
                LoadContent(htmlContent.GenerateString());
            }
            else
            {
                var zoom = UIDevice.CurrentDevice.UserInterfaceIdiom != UIUserInterfaceIdiom.Phone;
                var model = new SourceBrowserModel(content, "idea", fontSize, zoom, fileUri.LocalPath);
                var contentView = new SyntaxHighlighterView { Model = model };
                LoadContent(contentView.GenerateString());
            }
        }
Example #8
0
        private void Load(string path)
        {
            if (path == _loadedPath)
            {
                return;
            }

            _loadedPath = path;

            if (ViewModel.IsText)
            {
                if (ViewModel.IsMarkdown)
                {
                    var converter       = Locator.Current.GetService <IMarkdownService>();
                    var content         = System.IO.File.ReadAllText(path, System.Text.Encoding.UTF8);
                    var fontSize        = (int)UIFont.PreferredSubheadline.PointSize;
                    var markdownContent = converter.ConvertMarkdown(content);
                    var model           = new DescriptionModel(markdownContent, fontSize);
                    var v = new MarkdownView {
                        Model = model
                    };
                    LoadContent(v.GenerateString());
                }
                else
                {
                    var content  = System.IO.File.ReadAllText(path, System.Text.Encoding.UTF8);
                    var fontSize = (int)UIFont.PreferredSubheadline.PointSize;
                    var zoom     = UIDevice.CurrentDevice.UserInterfaceIdiom != UIUserInterfaceIdiom.Phone;
                    var model    = new SourceBrowserModel(content, "idea", fontSize, zoom, path);
                    var v        = new SyntaxHighlighterView {
                        Model = model
                    };
                    LoadContent(v.GenerateString());
                }
            }
            else
            {
                LoadFile(path);
            }
        }
Example #9
0
        protected virtual void LoadSource(Uri fileUri)
        {
            var fontSize = (int)UIFont.PreferredSubheadline.PointSize;
            var content  = System.IO.File.ReadAllText(fileUri.LocalPath, System.Text.Encoding.UTF8);

            if (ViewModel.IsMarkdown)
            {
                var model       = new DescriptionModel(content, fontSize);
                var htmlContent = new MarkdownView {
                    Model = model
                };
                LoadContent(htmlContent.GenerateString());
            }
            else
            {
                var model       = new SourceBrowserModel(content, ViewModel.Theme ?? "idea", fontSize, fileUri.LocalPath);
                var contentView = new SyntaxHighlighterView {
                    Model = model
                };
                LoadContent(contentView.GenerateString());
            }
        }
Example #10
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            _splitButton1 = _split.AddButton("Comments", "-");
            _splitButton2 = _split.AddButton("Participants", "-");

            Title = "Issue #" + ViewModel.Id;
            HeaderView.SetImage(null, Images.Avatar);
            HeaderView.Text = Title;

            Appeared.Take(1)
                .Select(_ => Observable.Timer(TimeSpan.FromSeconds(0.2f)))
                .Switch()
                .ObserveOn(RxApp.MainThreadScheduler)
                .Select(_ => ViewModel.Bind(x => x.IsClosed, true).Where(x => x.HasValue).Select(x => x.Value))
                .Switch()
                .Subscribe(x => 
                {
                    HeaderView.SubImageView.TintColor = x ? UIColor.FromRGB(0xbd, 0x2c, 0) : UIColor.FromRGB(0x6c, 0xc6, 0x44);
                    HeaderView.SetSubImage((x ? Octicon.IssueClosed :Octicon.IssueOpened).ToImage());
                });

            _milestoneElement = new StringElement("Milestone", "No Milestone", UITableViewCellStyle.Value1) {Image = Octicon.Milestone.ToImage() };
            _assigneeElement = new StringElement("Assigned", "Unassigned", UITableViewCellStyle.Value1) {Image = Octicon.Person.ToImage() };
            _labelsElement = new StringElement("Labels", "None", UITableViewCellStyle.Value1) {Image = Octicon.Tag.ToImage() };
            _addCommentElement = new StringElement("Add Comment") { Image = Octicon.Pencil.ToImage() };

            var actionButton = new UIBarButtonItem(UIBarButtonSystemItem.Action) { Enabled = false };
            NavigationItem.RightBarButtonItem = actionButton;

            ViewModel.Bind(x => x.IsModifying).SubscribeStatus("Loading...");

            ViewModel.Bind(x => x.Issue).Subscribe(x =>
            {
                _assigneeElement.Value = x.Assignee != null ? x.Assignee.Login : "******";
                _milestoneElement.Value = x.Milestone != null ? x.Milestone.Title : "No Milestone";
                _labelsElement.Value = x.Labels.Count == 0 ? "None" : string.Join(", ", x.Labels.Select(i => i.Name));

                var model = new DescriptionModel(ViewModel.MarkdownDescription, (int)UIFont.PreferredSubheadline.PointSize, true);
                var markdown = new MarkdownView { Model = model };
                var html = markdown.GenerateString();
                _descriptionElement.SetValue(string.IsNullOrEmpty(ViewModel.MarkdownDescription) ? null : html);

                HeaderView.Text = x.Title;
                HeaderView.SubText = "Updated " + x.UpdatedAt.Humanize();
                HeaderView.SetImage(x.User?.AvatarUrl, Images.Avatar);
                RefreshHeaderView();

                Render();
            });

            ViewModel.BindCollection(x => x.Comments).Subscribe(_ => RenderComments());
            ViewModel.BindCollection(x => x.Events).Subscribe(_ => RenderComments());
            ViewModel.Bind(x => x.ShouldShowPro).Subscribe(x => {
                if (x) this.ShowPrivateView(); 
            });

            OnActivation(d =>
            {
                d(_milestoneElement.Clicked.BindCommand(ViewModel.GoToMilestoneCommand));
                d(_assigneeElement.Clicked.BindCommand(ViewModel.GoToAssigneeCommand));
                d(_labelsElement.Clicked.BindCommand(ViewModel.GoToLabelsCommand));
                d(_addCommentElement.Clicked.Subscribe(_ => AddCommentTapped()));
                d(_descriptionElement.UrlRequested.BindCommand(ViewModel.GoToUrlCommand));
                d(_commentsElement.UrlRequested.BindCommand(ViewModel.GoToUrlCommand));
                d(actionButton.GetClickedObservable().Subscribe(ShowExtraMenu));
                d(HeaderView.Clicked.BindCommand(ViewModel.GoToOwner));

                d(ViewModel.Bind(x => x.IsCollaborator, true).Subscribe(x => {
                    foreach (var i in new [] { _assigneeElement, _milestoneElement, _labelsElement })
                        i.Accessory = x ? UITableViewCellAccessory.DisclosureIndicator : UITableViewCellAccessory.None;
                }));

                d(ViewModel.Bind(x => x.IsLoading).Subscribe(x => actionButton.Enabled = !x));
            });
        }
Example #11
0
        protected BaseIssueViewController()
        {
            CommentsElement = new HtmlElement("comments");
            this.WhenAnyValue(x => x.ViewModel.GoToUrlCommand)
            .Subscribe(x => CommentsElement.UrlRequested = x.ExecuteIfCan);

            DescriptionElement = new HtmlElement("description");
            this.WhenAnyValue(x => x.ViewModel.GoToUrlCommand)
            .Subscribe(x => DescriptionElement.UrlRequested = x.ExecuteIfCan);

            this.WhenAnyValue(x => x.ViewModel.ShowMenuCommand)
            .Select(x => x.ToBarButtonItem(UIBarButtonSystemItem.Action))
            .Subscribe(x => NavigationItem.RightBarButtonItem = x);

            this.WhenAnyObservable(x => x.ViewModel.GoToAssigneesCommand)
            .Subscribe(_ => IssueAssigneeViewController.Show(this, ViewModel.CreateAssigneeViewModel()));

            this.WhenAnyObservable(x => x.ViewModel.GoToMilestonesCommand)
            .Subscribe(_ => IssueMilestonesViewController.Show(this, ViewModel.CreateMilestonesViewModel()));

            this.WhenAnyObservable(x => x.ViewModel.GoToLabelsCommand)
            .Subscribe(_ => IssueLabelsViewController.Show(this, ViewModel.CreateLabelsViewModel()));

            this.WhenAnyValue(x => x.ViewModel.GoToOwnerCommand)
            .Subscribe(x => HeaderView.ImageButtonAction = x != null ? new Action(() => ViewModel.GoToOwnerCommand.ExecuteIfCan()) : null);

            Appeared.Take(1)
            .Select(_ => Observable.Timer(TimeSpan.FromSeconds(0.2f)))
            .Switch()
            .ObserveOn(RxApp.MainThreadScheduler)
            .Select(_ => this.WhenAnyValue(x => x.ViewModel.IsClosed))
            .Switch()
            .Subscribe(x =>
            {
                HeaderView.SubImageView.TintColor = x ? UIColor.FromRGB(0xbd, 0x2c, 0) : UIColor.FromRGB(0x6c, 0xc6, 0x44);
                HeaderView.SetSubImage((x ? Octicon.IssueClosed :Octicon.IssueOpened).ToImage());
            });

            MilestoneElement = new StringElement("Milestone", string.Empty, UITableViewCellStyle.Value1)
            {
                Image = Octicon.Milestone.ToImage()
            };
            MilestoneElement.Tapped = () => ViewModel.GoToMilestonesCommand.ExecuteIfCan();
            this.WhenAnyValue(x => x.ViewModel.AssignedMilestone)
            .Select(x => x == null ? "No Milestone" : x.Title)
            .Subscribe(x => MilestoneElement.Value = x);

            AssigneeElement = new StringElement("Assigned", string.Empty, UITableViewCellStyle.Value1)
            {
                Image = Octicon.Person.ToImage()
            };
            AssigneeElement.Tapped = () => ViewModel.GoToAssigneesCommand.ExecuteIfCan();
            this.WhenAnyValue(x => x.ViewModel.AssignedUser)
            .Select(x => x == null ? "Unassigned" : x.Login)
            .Subscribe(x => AssigneeElement.Value = x);

            LabelsElement = new StringElement("Labels", string.Empty, UITableViewCellStyle.Value1)
            {
                Image = Octicon.Tag.ToImage()
            };
            LabelsElement.Tapped = () => ViewModel.GoToLabelsCommand.ExecuteIfCan();
            this.WhenAnyValue(x => x.ViewModel.AssignedLabels)
            .Select(x => (x == null || x.Count == 0) ? "None" : string.Join(",", x.Select(y => y.Name)))
            .Subscribe(x => LabelsElement.Value = x);

            this.WhenAnyValue(x => x.ViewModel.CanModify)
            .Select(x => x ? UITableViewCellAccessory.DisclosureIndicator : UITableViewCellAccessory.None)
            .Subscribe(x => MilestoneElement.Accessory = AssigneeElement.Accessory = LabelsElement.Accessory = x);

            DetailsSection.Add(MilestoneElement);
            DetailsSection.Add(AssigneeElement);
            DetailsSection.Add(LabelsElement);

            this.WhenAnyValue(x => x.ViewModel.Avatar)
            .SubscribeSafe(x => HeaderView.SetImage(x?.ToUri(128), Images.LoginUserUnknown));

            this.WhenAnyValue(x => x.ViewModel.Issue)
            .IsNotNull()
            .Subscribe(x => {
                HeaderView.Text    = x.Title;
                HeaderView.SubText = x.UpdatedAt.HasValue ?
                                     ("Updated " + x.UpdatedAt.Value.UtcDateTime.Humanize()) :
                                     ("Created " + x.CreatedAt.UtcDateTime.Humanize());
                RefreshHeaderView();
            });

            this.WhenAnyValue(x => x.ViewModel.MarkdownDescription)
            .Subscribe(x =>
            {
                if (string.IsNullOrEmpty(x))
                {
                    DetailsSection.Remove(DescriptionElement);
                }
                else
                {
                    var model    = new DescriptionModel(x, (int)UIFont.PreferredSubheadline.PointSize);
                    var markdown = new MarkdownView {
                        Model = model
                    };
                    var html = markdown.GenerateString();
                    DescriptionElement.Value = html;

                    if (!DetailsSection.Contains(DescriptionElement))
                    {
                        DetailsSection.Insert(0, UITableViewRowAnimation.Fade, DescriptionElement);
                    }
                }
            });

            CommentsSection.FooterView = new TableFooterButton("Add Comment", () => ViewModel.AddCommentCommand.ExecuteIfCan());

            this.WhenAnyValue(x => x.ViewModel.Events)
            .Select(x => x.Changed)
            .Switch()
            .Select(x => ViewModel.Events)
            .Subscribe(events =>
            {
                var comments = events.Select(x =>
                {
                    var body    = string.Empty;
                    var comment = x as IssueCommentItemViewModel;
                    var @event  = x as IssueEventItemViewModel;

                    if (comment != null)
                    {
                        body = comment.Comment;
                    }
                    else if (@event != null)
                    {
                        body = CreateEventBody(@event.EventInfo, @event.Commit);
                    }

                    return(new Comment(x.AvatarUrl.ToUri(), x.Actor, body, x.CreatedAt.Humanize()));
                })
                               .Where(x => !string.IsNullOrEmpty(x.Body))
                               .ToList();

                if (comments.Count > 0)
                {
                    var commentModel = new CommentModel(comments, (int)UIFont.PreferredSubheadline.PointSize);
                    var razorView    = new CommentsView {
                        Model = commentModel
                    };
                    var html = razorView.GenerateString();
                    CommentsElement.Value = html;

                    if (!CommentsSection.Contains(CommentsElement))
                    {
                        CommentsSection.Insert(0, UITableViewRowAnimation.Fade, CommentsElement);
                    }
                }
                else
                {
                    CommentsSection.Remove(CommentsElement);
                }
            });

            var commentsButton     = SplitButton.AddButton("Comments", "-");
            var participantsButton = SplitButton.AddButton("Participants", "-");

            this.WhenAnyValue(x => x.ViewModel.CommentCount)
            .Subscribe(x => commentsButton.Text = x.ToString());

            this.WhenAnyValue(x => x.ViewModel.Participants)
            .Subscribe(x => participantsButton.Text = x.ToString());
        }
Example #12
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            _splitButton1 = _split.AddButton("Comments", "-");
            _splitButton2 = _split.AddButton("Participants", "-");

            Title = "Issue #" + ViewModel.Id;
            HeaderView.SetImage(null, Images.Avatar);
            HeaderView.Text = Title;

            Appeared.Take(1)
            .Select(_ => Observable.Timer(TimeSpan.FromSeconds(0.2f)))
            .Switch()
            .ObserveOn(RxApp.MainThreadScheduler)
            .Select(_ => ViewModel.Bind(x => x.IsClosed, true).Where(x => x.HasValue).Select(x => x.Value))
            .Switch()
            .Subscribe(x =>
            {
                HeaderView.SubImageView.TintColor = x ? UIColor.FromRGB(0xbd, 0x2c, 0) : UIColor.FromRGB(0x6c, 0xc6, 0x44);
                HeaderView.SetSubImage((x ? Octicon.IssueClosed :Octicon.IssueOpened).ToImage());
            });

            _milestoneElement = new StringElement("Milestone", "No Milestone", UITableViewCellStyle.Value1)
            {
                Image = Octicon.Milestone.ToImage()
            };
            _assigneeElement = new StringElement("Assigned", "Unassigned", UITableViewCellStyle.Value1)
            {
                Image = Octicon.Person.ToImage()
            };
            _labelsElement = new StringElement("Labels", "None", UITableViewCellStyle.Value1)
            {
                Image = Octicon.Tag.ToImage()
            };
            _addCommentElement = new StringElement("Add Comment")
            {
                Image = Octicon.Pencil.ToImage()
            };

            var actionButton = new UIBarButtonItem(UIBarButtonSystemItem.Action)
            {
                Enabled = false
            };

            NavigationItem.RightBarButtonItem = actionButton;

            ViewModel.Bind(x => x.IsModifying).SubscribeStatus("Loading...");

            ViewModel.Bind(x => x.Issue).Subscribe(x =>
            {
                _assigneeElement.Value  = x.Assignee != null ? x.Assignee.Login : "******";
                _milestoneElement.Value = x.Milestone != null ? x.Milestone.Title : "No Milestone";
                _labelsElement.Value    = x.Labels.Count == 0 ? "None" : string.Join(", ", x.Labels.Select(i => i.Name));

                var model    = new DescriptionModel(ViewModel.MarkdownDescription, (int)UIFont.PreferredSubheadline.PointSize, true);
                var markdown = new MarkdownView {
                    Model = model
                };
                var html = markdown.GenerateString();
                _descriptionElement.SetValue(string.IsNullOrEmpty(ViewModel.MarkdownDescription) ? null : html);

                HeaderView.Text    = x.Title;
                HeaderView.SubText = "Updated " + x.UpdatedAt.Humanize();
                HeaderView.SetImage(x.User?.AvatarUrl, Images.Avatar);
                RefreshHeaderView();

                Render();
            });

            ViewModel.BindCollection(x => x.Comments).Subscribe(_ => RenderComments());
            ViewModel.BindCollection(x => x.Events).Subscribe(_ => RenderComments());
            ViewModel.Bind(x => x.ShouldShowPro).Subscribe(x => {
                if (x)
                {
                    this.ShowPrivateView();
                }
            });

            OnActivation(d =>
            {
                d(_milestoneElement.Clicked.BindCommand(ViewModel.GoToMilestoneCommand));
                d(_assigneeElement.Clicked.BindCommand(ViewModel.GoToAssigneeCommand));
                d(_labelsElement.Clicked.BindCommand(ViewModel.GoToLabelsCommand));
                d(_addCommentElement.Clicked.Subscribe(_ => AddCommentTapped()));
                d(_descriptionElement.UrlRequested.BindCommand(ViewModel.GoToUrlCommand));
                d(_commentsElement.UrlRequested.BindCommand(ViewModel.GoToUrlCommand));
                d(actionButton.GetClickedObservable().Subscribe(ShowExtraMenu));
                d(HeaderView.Clicked.BindCommand(ViewModel.GoToOwner));

                d(ViewModel.Bind(x => x.IsCollaborator, true).Subscribe(x => {
                    foreach (var i in new [] { _assigneeElement, _milestoneElement, _labelsElement })
                    {
                        i.Accessory = x ? UITableViewCellAccessory.DisclosureIndicator : UITableViewCellAccessory.None;
                    }
                }));

                d(ViewModel.Bind(x => x.IsLoading).Subscribe(x => actionButton.Enabled = !x));
            });
        }