public CommitViewModel( string username, string repository, string node, bool showRepository = false, IApplicationService applicationService = null, IActionMenuService actionMenuService = null, IAlertDialogService alertDialogService = null) { _applicationService = applicationService = applicationService ?? Locator.Current.GetService <IApplicationService>(); actionMenuService = actionMenuService ?? Locator.Current.GetService <IActionMenuService>(); alertDialogService = alertDialogService ?? Locator.Current.GetService <IAlertDialogService>(); Username = username; Repository = repository; Node = node; ShowRepository = showRepository; var shortNode = node.Substring(0, node.Length > 7 ? 7 : node.Length); Title = $"Commit {shortNode}"; var changesetFiles = this.WhenAnyValue(x => x.Changeset) .Where(x => x != null) .Select(x => x.Files ?? Enumerable.Empty <Client.V1.ChangesetFile>()); changesetFiles .Select(x => x.Count(y => y.Type == "added")) .ToProperty(this, x => x.DiffAdditions, out _diffAdditions); changesetFiles .Select(x => x.Count(y => y.Type == "removed")) .ToProperty(this, x => x.DiffDeletions, out _diffDeletions); changesetFiles .Select(x => x.Count(y => y.Type != "added" && y.Type != "removed")) .ToProperty(this, x => x.DiffModifications, out _diffModifications); Comments = _comments.CreateDerivedCollection(comment => { var name = comment.User.DisplayName ?? comment.User.Username; var avatar = new Avatar(comment.User.Links?.Avatar?.Href); return(new CommentItemViewModel(name, avatar, comment.CreatedOn.Humanize(), comment.Content.Raw)); }, x => x.Inline == null); GoToUserCommand = ReactiveCommand.Create <string>(user => NavigateTo(new UserViewModel(user))); GoToRepositoryCommand .Select(_ => new RepositoryViewModel(username, repository)) .Subscribe(NavigateTo); GoToAddedFiles = ReactiveCommand.Create( () => { }, this.WhenAnyValue(x => x.DiffAdditions).Select(x => x > 0)); GoToRemovedFiles = ReactiveCommand.Create( () => { }, this.WhenAnyValue(x => x.DiffDeletions).Select(x => x > 0)); GoToModifiedFiles = ReactiveCommand.Create( () => { }, this.WhenAnyValue(x => x.DiffModifications).Select(x => x > 0)); var canShowMenu = this.WhenAnyValue(x => x.Commit).Select(x => x != null); ShowMenuCommand = ReactiveCommand.Create <object>(sender => { var uri = new Uri($"https://bitbucket.org/{username}/{repository}/commits/{node}"); var menu = actionMenuService.Create(); menu.AddButton("Add Comment", _ => AddCommentCommand.ExecuteNow()); menu.AddButton("Copy SHA", _ => actionMenuService.SendToPasteBoard(node)); menu.AddButton("Share", x => actionMenuService.ShareUrl(x, uri)); menu.AddButton("Show In Bitbucket", _ => NavigateTo(new WebBrowserViewModel(uri.AbsoluteUri))); menu.Show(sender); }, canShowMenu); ToggleApproveButton = ReactiveCommand.CreateFromTask(async _ => { if (Approved) { await applicationService.Client.Commits.Unapprove(username, repository, node); } else { await applicationService.Client.Commits.Approve(username, repository, node); } var shouldBe = !Approved; var commit = await applicationService.Client.Commits.Get(username, repository, node); var currentUsername = applicationService.Account.Username; var me = commit.Participants.FirstOrDefault( y => string.Equals(currentUsername, y?.User?.Username, StringComparison.OrdinalIgnoreCase)); if (me != null) { me.Approved = shouldBe; } Commit = commit; }); ToggleApproveButton .ThrownExceptions .Subscribe(x => alertDialogService.Alert("Error", "Unable to approve commit: " + x.Message).ToBackground()); var commitFiles = new ReactiveList <Client.V1.ChangesetFile>(); CommitFiles = commitFiles.CreateDerivedCollection(x => { var vm = new CommitFileItemViewModel(username, repository, node, Changeset.Parents.FirstOrDefault(), x); vm.GoToCommand .Select(_ => new ChangesetDiffViewModel(username, repository, node, x)) .Subscribe(NavigateTo); return(vm); }); this.WhenAnyValue(x => x.Commit.Participants) .Select(participants => { return((participants ?? Enumerable.Empty <CommitParticipant>()) .Where(x => x.Approved) .Select(x => { var avatar = new Avatar(x.User?.Links?.Avatar?.Href); var vm = new UserItemViewModel(x.User?.Username, x.User?.DisplayName, avatar); vm.GoToCommand .Select(_ => new UserViewModel(x.User)) .Subscribe(NavigateTo); return vm; })); }) .Select(x => x.ToArray()) .ToProperty(this, x => x.Approvals, out _approvals, new UserItemViewModel[0]); this.WhenAnyValue(x => x.Changeset) .Subscribe(x => commitFiles.Reset(x?.Files ?? Enumerable.Empty <Client.V1.ChangesetFile>())); this.WhenAnyValue(x => x.Commit) .Subscribe(x => { var currentUsername = applicationService.Account.Username; Approved = x?.Participants ?.FirstOrDefault(y => string.Equals(currentUsername, y?.User?.Username, StringComparison.OrdinalIgnoreCase)) ?.Approved ?? false; }); LoadCommand = ReactiveCommand.CreateFromTask(_ => { var commit = applicationService.Client.Commits.Get(username, repository, node) .OnSuccess(x => Commit = x); var changeset = applicationService.Client.Commits.GetChangeset(username, repository, node) .OnSuccess(x => Changeset = x); applicationService.Client.AllItems(x => x.Commits.GetComments(username, repository, node)) .ToBackground(_comments.Reset); return(Task.WhenAll(commit, changeset)); }); }
public ChangesetViewModel(IApplicationService applicationService, IActionMenuService actionMenuService) { _applicationService = applicationService; Title = "Commit"; GoToUrlCommand = this.CreateUrlCommand(); Comments = new ReactiveList <CommentModel>(); var goToUrlCommand = this.CreateUrlCommand(); GoToHtmlUrlCommand = ReactiveCommand.Create(this.WhenAnyValue(x => x.Commit).Select(x => x != null)); GoToHtmlUrlCommand.Select(x => Commit.HtmlUrl).Subscribe(goToUrlCommand.ExecuteIfCan); GoToRepositoryCommand = ReactiveCommand.Create(); GoToRepositoryCommand.Subscribe(_ => { var vm = CreateViewModel <RepositoryViewModel>(); vm.RepositoryOwner = RepositoryOwner; vm.RepositoryName = RepositoryName; ShowViewModel(vm); }); GoToCommentCommand = ReactiveCommand.Create().WithSubscription(_ => { var vm = CreateViewModel <CommitCommentViewModel>(); vm.RepositoryOwner = RepositoryOwner; vm.RepositoryName = RepositoryName; vm.Node = Node; vm.CommentAdded.Subscribe(Comments.Add); ShowViewModel(vm); }); GoToFileCommand = ReactiveCommand.Create(); GoToFileCommand.OfType <CommitModel.CommitFileModel>().Subscribe(x => { if (x.Patch == null) { var vm = CreateViewModel <SourceViewModel>(); vm.Branch = Commit.Sha; vm.RepositoryOwner = RepositoryOwner; vm.RepositoryName = RepositoryName; // vm.Items = new [] // { // new SourceViewModel.SourceItemModel // { // ForceBinary = true, // GitUrl = x.BlobUrl, // Name = x.Filename, // Path = x.Filename, // HtmlUrl = x.BlobUrl // } // }; // vm.CurrentItemIndex = 0; ShowViewModel(vm); } else { var vm = CreateViewModel <ChangesetDiffViewModel>(); vm.Username = RepositoryOwner; vm.Repository = RepositoryName; vm.Branch = Commit.Sha; vm.Filename = x.Filename; ShowViewModel(vm); } }); var copyShaCommand = ReactiveCommand.Create(this.WhenAnyValue(x => x.Commit).Select(x => x != null)) .WithSubscription(x => actionMenuService.SendToPasteBoard(this.Commit.Sha)); var shareCommand = ReactiveCommand.Create(this.WhenAnyValue(x => x.Commit).Select(x => x != null)) .WithSubscription(x => actionMenuService.ShareUrl(this.Commit.HtmlUrl)); ShowMenuCommand = ReactiveCommand.CreateAsyncTask(_ => { var menu = actionMenuService.Create(Title); menu.AddButton("Add Comment", GoToCommentCommand); menu.AddButton("Copy SHA", copyShaCommand); menu.AddButton("Share", shareCommand); menu.AddButton("Show in GitHub", GoToHtmlUrlCommand); return(menu.Show()); }); LoadCommand = ReactiveCommand.CreateAsyncTask(t => { var forceCacheInvalidation = t as bool?; var t1 = this.RequestModel(_applicationService.Client.Users[RepositoryOwner].Repositories[RepositoryName].Commits[Node].Get(), forceCacheInvalidation, response => Commit = response.Data); Comments.SimpleCollectionLoad(_applicationService.Client.Users[RepositoryOwner].Repositories[RepositoryName].Commits[Node].Comments.GetAll(), forceCacheInvalidation).FireAndForget(); return(t1); }); }