public SourceViewModel( string username, string repository, string branch, string path, IApplicationService applicationService = null, IActionMenuService actionMenuService = null) { applicationService = applicationService ?? Locator.Current.GetService <IApplicationService>(); actionMenuService = actionMenuService ?? Locator.Current.GetService <IActionMenuService>(); GoToHtmlUrlCommand = ReactiveCommand.Create( () => NavigateTo(new WebBrowserViewModel(HtmlUrl)), this.WhenAnyValue(x => x.HtmlUrl).Select(x => !string.IsNullOrEmpty(x))); //Create the filename var fileName = Path.GetFileName(path); if (fileName == null) { fileName = path.Substring(path.LastIndexOf('/') + 1); } //Create the temp file path Title = fileName; var extension = Path.GetExtension(path); IsMarkdown = MarkdownExtensions.Any(x => x == extension); var canExecute = this.WhenAnyValue(x => x.HtmlUrl).Select(x => x != null); var canOpen = this.WhenAnyValue(x => x.FilePath).Select(x => x != null); var canShow = Observable.CombineLatest(canExecute, canOpen, (x, y) => x && y); ShowMenuCommand = ReactiveCommand.CreateFromTask <object>(sender => { var menu = actionMenuService.Create(); menu.AddButton("Open In", x => actionMenuService.OpenIn(x, FilePath)); menu.AddButton("Share", x => actionMenuService.ShareUrl(x, HtmlUrl)); menu.AddButton("Show in Bitbucket", _ => GoToHtmlUrlCommand.ExecuteNow()); return(menu.Show(sender)); }, canShow); LoadCommand = ReactiveCommand.CreateFromTask(async _ => { var filePath = Path.Combine(Path.GetTempPath(), Path.GetFileName(fileName)); using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { await applicationService.Client.Repositories.GetRawFile(username, repository, branch, path, stream); } using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { var buffer = new byte[1024]; var read = stream.Read(buffer, 0, 1024); IsText = !buffer.Take(read).Any(x => x == 0); } FilePath = filePath; HtmlUrl = $"https://bitbucket.org/{username}/{repository}/raw/{branch}/{path.TrimStart('/')}"; }); }
public ReadmeViewModel( string username, string repository, string filename, IApplicationService applicationService = null, IMarkdownService markdownService = null, IActionMenuService actionMenuService = null) { applicationService = applicationService ?? Locator.Current.GetService <IApplicationService>(); markdownService = markdownService ?? Locator.Current.GetService <IMarkdownService>(); actionMenuService = actionMenuService ?? Locator.Current.GetService <IActionMenuService>(); var canShowMenu = this.WhenAnyValue(x => x.ContentModel).Select(x => x != null); ShowMenuCommand = ReactiveCommand.CreateFromTask(sender => { var menu = actionMenuService.Create(); menu.AddButton("Share", x => actionMenuService.ShareUrl(x, new Uri(_htmlUrl))); menu.AddButton("Show in Bitbucket", _ => NavigateTo(new WebBrowserViewModel(_htmlUrl))); return(menu.Show(sender)); }, canShowMenu); Title = "Readme"; LoadCommand = ReactiveCommand.CreateFromTask(async t => { var filepath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), filename); var mainBranch = (await applicationService.Client.Repositories.GetPrimaryBranch(username, repository)).Name; ContentModel = await applicationService.Client.Repositories.GetFile(username, repository, mainBranch, filename); var readme = ContentModel.Data; _htmlUrl = "http://bitbucket.org/" + username + "/" + repository + "/src/" + mainBranch + "/" + filename; if (filepath.EndsWith("textile", StringComparison.Ordinal)) { ContentText = markdownService.ConvertTextile(readme); } else { ContentText = markdownService.ConvertMarkdown(readme); } }); }
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 static void ShareUrl(this IActionMenuService @this, object sender, string uri) { @this.ShareUrl(sender, new Uri(uri)); }
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); }); }