public override void ViewDidLoad() { base.ViewDidLoad(); var commitsElement = new ButtonElement("Commits", Octicon.GitCommit.ToImage()); var filesElement = new ButtonElement("Files Changed", Octicon.Diff.ToImage()); var mergeButton = new StringElement("Merge", Octicon.GitMerge.ToImage()); var pullRequestSection = new Section { commitsElement, filesElement, mergeButton }; OnActivation(d => { var commitsObs = this.WhenAnyValue(x => x.ViewModel.PullRequest.Commits); d(commitsElement.BindValue(commitsObs)); d(commitsElement.BindCommand(ViewModel.GoToCommitsCommand)); d(commitsElement.BindDisclosure(commitsObs.Select(x => x > 0))); var filesObs = this.WhenAnyValue(x => x.ViewModel.PullRequest.ChangedFiles); d(filesElement.BindValue(filesObs)); d(filesElement.BindCommand(ViewModel.GoToFilesCommand)); d(filesElement.BindDisclosure(filesObs.Select(x => x > 0))); d(mergeButton.Clicked.SubscribeSafe(_ => { if (!ViewModel.PullRequest.Merged && ViewModel.CanMerge && ViewModel.PullRequest.State == Octokit.ItemState.Open) { PromptForCommitMessage(); } })); d(this.WhenAnyValue(x => x.ViewModel.PullRequest.Merged, x => x.ViewModel.CanMerge, x => x.ViewModel.PullRequest.State) .Subscribe(x => { if (x.Item1) { mergeButton.Caption = "Merged"; mergeButton.SelectionStyle = UITableViewCellSelectionStyle.None; mergeButton.Accessory = UITableViewCellAccessory.Checkmark; } else if (!x.Item1 && x.Item2 && x.Item3 == Octokit.ItemState.Open) { mergeButton.Caption = "Merge"; mergeButton.SelectionStyle = UITableViewCellSelectionStyle.Blue; mergeButton.Accessory = UITableViewCellAccessory.DisclosureIndicator; } else { mergeButton.Caption = "Not Merged"; mergeButton.SelectionStyle = UITableViewCellSelectionStyle.None; mergeButton.Accessory = UITableViewCellAccessory.None; } })); }); Root.Insert(Root.Count - 1, pullRequestSection); }
protected BaseIssueViewController() { CommentsElement = new HtmlElement("comments"); DescriptionElement = new HtmlElement("description"); 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 ButtonElement("Milestone", Octicon.Milestone.ToImage()); this.WhenAnyValue(x => x.ViewModel.AssignedMilestone) .Select(x => x == null ? "No Milestone" : x.Title) .Subscribe(x => MilestoneElement.Value = x); AssigneeElement = new ButtonElement("Assigned", Octicon.Person.ToImage()); this.WhenAnyValue(x => x.ViewModel.AssignedUser) .Select(x => x == null ? "Unassigned" : x.Login) .Subscribe(x => AssigneeElement.Value = x); LabelsElement = new ButtonElement("Labels", Octicon.Tag.ToImage()); 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); 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); } } }); var footerButton = new TableFooterButton("Add Comment"); CommentsSection.FooterView = footerButton; 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()); this.WhenAnyObservable(x => x.ViewModel.CommentAdded) .Select(_ => Appeared.Take(1)) .Switch() .Delay(TimeSpan.FromMilliseconds(50), RxApp.MainThreadScheduler) .SubscribeSafe(_ => TableView.SetContentOffset(new CoreGraphics.CGPoint(0, TableView.ContentSize.Height - TableView.Bounds.Height), true)); OnActivation(d => { d(MilestoneElement.BindCommand(ViewModel.GoToMilestonesCommand)); d(AssigneeElement.BindCommand(ViewModel.GoToAssigneesCommand)); d(LabelsElement.BindCommand(ViewModel.GoToLabelsCommand)); var canModify = this.WhenAnyValue(x => x.ViewModel.CanModify); d(MilestoneElement.BindDisclosure(canModify)); d(AssigneeElement.BindDisclosure(canModify)); d(LabelsElement.BindDisclosure(canModify)); d(footerButton.Clicked.InvokeCommand(ViewModel.AddCommentCommand)); d(HeaderView.Clicked.InvokeCommand(ViewModel.GoToOwnerCommand)); d(this.WhenAnyValue(x => x.ViewModel.ShowMenuCommand) .ToBarButtonItem(UIBarButtonSystemItem.Action, x => NavigationItem.RightBarButtonItem = x)); d(CommentsElement.UrlRequested.InvokeCommand(ViewModel.GoToUrlCommand)); d(DescriptionElement.UrlRequested.InvokeCommand(ViewModel.GoToUrlCommand)); d(this.WhenAnyObservable(x => x.ViewModel.GoToAssigneesCommand) .Subscribe(_ => IssueAssigneeViewController.Show(this, ViewModel.CreateAssigneeViewModel()))); d(this.WhenAnyObservable(x => x.ViewModel.GoToMilestonesCommand) .Subscribe(_ => IssueMilestonesViewController.Show(this, ViewModel.CreateMilestonesViewModel()))); d(this.WhenAnyObservable(x => x.ViewModel.GoToLabelsCommand) .Subscribe(_ => IssueLabelsViewController.Show(this, ViewModel.CreateLabelsViewModel()))); }); }
public override void ViewDidLoad() { base.ViewDidLoad(); HeaderView.SetImage(null, Images.Avatar); var compose = new UIBarButtonItem(UIBarButtonSystemItem.Compose); var more = new UIBarButtonItem(UIBarButtonSystemItem.Action); NavigationItem.RightBarButtonItems = new[] { more, compose }; var split = new SplitButtonElement(); var commentCount = split.AddButton("Comments", "-"); var watchers = split.AddButton("Watchers", "-"); ICollection <Section> root = new LinkedList <Section>(); root.Add(new Section { split }); var secDetails = new Section(); root.Add(secDetails); this.WhenAnyValue(x => x.ViewModel.ShowDescription) .DistinctUntilChanged() .Subscribe(x => { if (x) { secDetails.Insert(0, UITableViewRowAnimation.None, _descriptionElement); } else { secDetails.Remove(_descriptionElement); } }); this.WhenAnyValue(x => x.ViewModel.Description) .Where(x => !string.IsNullOrWhiteSpace(x)) .Select(x => new DescriptionModel(x, (int)UIFont.PreferredSubheadline.PointSize, true)) .Select(x => new MarkdownView { Model = x }.GenerateString()) .Subscribe(_descriptionElement.SetValue); var split1 = new SplitViewElement(AtlassianIcon.Configure.ToImage(), AtlassianIcon.Error.ToImage()); var split2 = new SplitViewElement(AtlassianIcon.Flag.ToImage(), AtlassianIcon.Spacedefault.ToImage()); var split3 = new SplitViewElement(AtlassianIcon.Copyclipboard.ToImage(), AtlassianIcon.Calendar.ToImage()); secDetails.Add(split1); secDetails.Add(split2); secDetails.Add(split3); var assigneeElement = new ButtonElement("Assigned", string.Empty, UITableViewCellStyle.Value1) { Image = AtlassianIcon.User.ToImage(), }; secDetails.Add(assigneeElement); var commentsSection = new Section("Comments"); root.Add(commentsSection); var addComment = new ButtonElement("Add Comment") { Image = AtlassianIcon.Addcomment.ToImage() }; commentsSection.Reset(new[] { addComment }); ViewModel .Comments .ChangedObservable() .Subscribe(x => { if (x.Count > 0) { var comments = x.Select(y => new Comment(y.Avatar.ToUrl(), y.Name, y.Content, y.CreatedOn)).ToList(); var commentModel = new CommentModel(comments, (int)UIFont.PreferredSubheadline.PointSize); var content = new CommentsView { Model = commentModel }.GenerateString(); _commentsElement.SetValue(content); commentsSection.Insert(0, UITableViewRowAnimation.None, _commentsElement); } else { commentsSection.Remove(_commentsElement); } }); Root.Reset(root); OnActivation(d => { this.WhenAnyValue(x => x.ViewModel.Issue) .Where(x => x != null) .Subscribe(x => { var avatarUrl = x.ReportedBy?.Avatar; HeaderView.Text = x.Title; HeaderView.SubText = "Updated " + ViewModel.Issue.UtcLastUpdated.Humanize(); HeaderView.SetImage(new Avatar(avatarUrl).ToUrl(128), Images.Avatar); TableView.TableHeaderView = HeaderView; }) .AddTo(d); this.WhenAnyObservable(x => x.ViewModel.DismissCommand) .Subscribe(_ => NavigationController.PopViewController(true)) .AddTo(d); this.WhenAnyValue(x => x.ViewModel.Issue) .Subscribe(x => { split1.Button1.Text = x?.Status; split1.Button2.Text = x?.Priority; split2.Button1.Text = x?.Metadata?.Kind; split2.Button2.Text = x?.Metadata?.Component ?? "No Component"; split3.Button1.Text = x?.Metadata?.Version ?? "No Version"; split3.Button2.Text = x?.Metadata?.Milestone ?? "No Milestone"; }) .AddTo(d); HeaderView .Clicked .BindCommand(this, x => x.ViewModel.GoToReporterCommand) .AddTo(d); compose .GetClickedObservable() .SelectUnit() .BindCommand(ViewModel.GoToEditCommand) .AddTo(d); addComment .Clicked .Subscribe(_ => NewCommentViewController.Present(this, ViewModel.AddComment)) .AddTo(d); assigneeElement .BindValue(this.WhenAnyValue(x => x.ViewModel.Assigned)) .AddTo(d); assigneeElement .BindDisclosure( this.WhenAnyValue(x => x.ViewModel.Assigned) .Select(x => !string.Equals(x, "Unassigned", StringComparison.OrdinalIgnoreCase))) .AddTo(d); assigneeElement .Clicked .SelectUnit() .BindCommand(ViewModel.GoToAssigneeCommand) .AddTo(d); more.Bind(ViewModel.ShowMenuCommand) .AddTo(d); this.WhenAnyValue(x => x.ViewModel.Issue) .Select(x => x != null) .Subscribe(x => compose.Enabled = x) .AddTo(d); this.WhenAnyObservable(x => x.ViewModel.Comments.CountChanged) .StartWith(ViewModel.Comments.Count) .Subscribe(x => commentCount.Text = x.ToString()) .AddTo(d); this.WhenAnyValue(x => x.ViewModel.Issue.FollowerCount) .Subscribe(x => watchers.Text = x.ToString()) .AddTo(d); }); }
public override void ViewDidLoad() { base.ViewDidLoad(); HeaderView.SetImage(null, Images.Avatar); var detailsSection = new Section(); var diffButton = new ButtonElement(AtlassianIcon.ListAdd.ToImage()); var removedButton = new ButtonElement(AtlassianIcon.ListRemove.ToImage()); var modifiedButton = new ButtonElement(AtlassianIcon.Edit.ToImage()); var allChangesButton = new ButtonElement("All Changes", AtlassianIcon.Devtoolssidediff.ToImage()); detailsSection.Add(new [] { diffButton, removedButton, modifiedButton, allChangesButton }); var additions = ViewModel.WhenAnyValue(x => x.DiffAdditions); diffButton.BindClick(ViewModel.GoToAddedFiles); diffButton.BindDisclosure(additions.Select(x => x > 0)); diffButton.BindCaption(additions.Select(x => $"{x} Added")); var deletions = ViewModel.WhenAnyValue(x => x.DiffDeletions); removedButton.BindClick(ViewModel.GoToRemovedFiles); removedButton.BindDisclosure(deletions.Select(x => x > 0)); removedButton.BindCaption(deletions.Select(x => $"{x} Removed")); var modifications = ViewModel.WhenAnyValue(x => x.DiffModifications); modifiedButton.BindClick(ViewModel.GoToModifiedFiles); modifiedButton.BindDisclosure(modifications.Select(x => x > 0)); modifiedButton.BindCaption(modifications.Select(x => $"{x} Modified")); allChangesButton.BindClick(ViewModel.GoToAllFiles); var split = new SplitButtonElement(); var commentCount = split.AddButton("Comments", "-"); var participants = split.AddButton("Participants", "-"); var approvals = split.AddButton("Approvals", "-"); var headerSection = new Section { split }; var actionButton = new UIBarButtonItem(UIBarButtonSystemItem.Action); NavigationItem.RightBarButtonItem = actionButton; var detailSection = new Section(); var detailsElement = new MultilinedElement(); detailSection.Add(detailsElement); var approvalSection = new Section("Approvals"); var approveElement = new LoaderButtonElement("Approve", AtlassianIcon.Approve.ToImage()); approveElement.Accessory = UITableViewCellAccessory.None; approveElement.BindLoader(ViewModel.ToggleApproveButton); approveElement.BindCaption(ViewModel.WhenAnyValue(x => x.Approved).Select(x => x ? "Unapprove" : "Approve")); var commentsSection = new Section("Comments"); var addCommentElement = new ButtonElement("Add Comment", AtlassianIcon.Addcomment.ToImage()); commentsSection.Add(addCommentElement); if (ViewModel.ShowRepository) { var repo = new ButtonElement(ViewModel.Repository) { TextColor = StringElement.DefaultDetailColor, Image = AtlassianIcon.Devtoolsrepository.ToImage() }; detailSection.Add(repo); repo.Clicked.SelectUnit().BindCommand(ViewModel.GoToRepositoryCommand); } ViewModel.WhenAnyValue(x => x.Commit).Where(x => x != null).Subscribe(x => { participants.Text = x?.Participants?.Count.ToString() ?? "-"; approvals.Text = x?.Participants?.Count(y => y.Approved).ToString() ?? "-"; var titleMsg = (ViewModel.Commit.Message ?? string.Empty).Split(new [] { '\n' }, 2).FirstOrDefault(); var avatarUrl = ViewModel.Commit.Author?.User?.Links?.Avatar?.Href; HeaderView.SubText = titleMsg ?? "Commited " + (ViewModel.Commit.Date).Humanize(); HeaderView.SetImage(new Avatar(avatarUrl).ToUrl(128), Images.Avatar); RefreshHeaderView(); var user = x.Author?.User?.DisplayName ?? x.Author?.Raw ?? "Unknown"; detailsElement.Caption = user; detailsElement.Details = x.Message; }); this.WhenAnyValue(x => x.ViewModel.Approvals) .Select(x => x.Select(y => new UserElement(y)).OfType <Element>()) .Subscribe(x => approvalSection.Reset(x.Concat(new[] { approveElement }))); ViewModel.Comments .CountChanged .Select(x => x.ToString()) .StartWith("-") .Subscribe(x => commentCount.Text = x); ViewModel .Comments .ChangedObservable() .Subscribe(x => { if (x.Count > 0) { var comments = x.Select(y => new Comment(y.Avatar.ToUrl(), y.Name, y.Content, y.CreatedOn)).ToList(); var commentModel = new Views.CommentModel(comments, (int)UIFont.PreferredSubheadline.PointSize); var content = new CommentsView { Model = commentModel }.GenerateString(); _commentsElement.SetValue(content); commentsSection.Insert(0, UITableViewRowAnimation.None, _commentsElement); } else { commentsSection.Remove(_commentsElement); } }); ViewModel.WhenAnyValue(x => x.Commit) .Where(x => x != null) .Take(1) .Subscribe(_ => Root.Reset(headerSection, detailsSection, approvalSection, commentsSection)); ViewModel.GoToAddedFiles.Select(_ => CommitFileType.Added).Subscribe(GoToFiles); ViewModel.GoToRemovedFiles.Select(_ => CommitFileType.Removed).Subscribe(GoToFiles); ViewModel.GoToModifiedFiles.Select(_ => CommitFileType.Modified).Subscribe(GoToFiles); ViewModel.GoToAllFiles.Subscribe(_ => GoToAllFiles()); OnActivation(d => { actionButton .GetClickedObservable() .Select(x => (object)x) .BindCommand(ViewModel.ShowMenuCommand) .AddTo(d); addCommentElement .Clicked .SelectUnit() .BindCommand(ViewModel.AddCommentCommand) .AddTo(d); this.WhenAnyObservable(x => x.ViewModel.AddCommentCommand) .Subscribe(_ => NewCommentViewController.Present(this, ViewModel.AddComment)) .AddTo(d); }); }