public async Task InitializeAsync(IConnection connection) { modelService = await modelServiceFactory.CreateAsync(connection); Title = string.Format(CultureInfo.CurrentCulture, Resources.CreateTitle, connection.HostAddress.Title); accounts = modelService.GetAccounts() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, vm => vm.Accounts, initialValue: new ReadOnlyCollection <IAccount>(new IAccount[] { })); this.WhenAny(x => x.Accounts, x => x.Value) .Select(accts => accts?.FirstOrDefault()) .WhereNotNull() .Subscribe(a => SelectedAccount = a); GitIgnoreTemplates = TrackingCollection.CreateListenerCollectionAndRun( modelService.GetGitIgnoreTemplates(), new[] { GitIgnoreItem.None }, OrderedComparer <GitIgnoreItem> .OrderByDescending(item => GitIgnoreItem.IsRecommended(item.Name)).Compare, x => { if (x.Name.Equals("VisualStudio", StringComparison.OrdinalIgnoreCase)) { SelectedGitIgnoreTemplate = x; } }); Licenses = TrackingCollection.CreateListenerCollectionAndRun( modelService.GetLicenses(), new[] { LicenseItem.None }, OrderedComparer <LicenseItem> .OrderByDescending(item => LicenseItem.IsRecommended(item.Name)).Compare); }
public async Task InitializeAsync(LocalRepositoryModel repository, IConnection connection) { modelService = await modelServiceFactory.CreateAsync(connection); activeLocalRepo = repository; SourceBranch = gitService.GetBranch(repository); var obs = modelService.ApiClient.GetRepository(repository.Owner, repository.Name) .Select(r => CreateRemoteRepositoryModel(r)) .PublishLast(); disposables.Add(obs.Connect()); var githubObs = obs; githubRepository = githubObs.ToProperty(this, x => x.GitHubRepository); this.WhenAnyValue(x => x.GitHubRepository) .WhereNotNull() .Subscribe(r => { TargetBranch = r.IsFork ? r.Parent.DefaultBranch : r.DefaultBranch; }); githubObs.SelectMany(r => { var b = Observable.Empty <BranchModel>(); if (r.IsFork) { b = modelService.GetBranches(r.Parent).Select(x => { return(x); }); } return(b.Concat(modelService.GetBranches(r))); }) .ToList() .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { Branches = x.ToList(); Initialized = true; }); var draftKey = GetDraftKey(); await LoadInitialState(draftKey).ConfigureAwait(true); this.WhenAnyValue( x => x.PRTitle, x => x.Description, (t, d) => new PullRequestDraft { Title = t, Body = d }) .Throttle(TimeSpan.FromSeconds(1), timerScheduler) .Subscribe(x => draftStore.UpdateDraft(draftKey, string.Empty, x)); Initialized = true; }
public async Task InitializeAsync(IConnection connection) { var modelService = await modelServiceFactory.CreateAsync(connection); apiClient = modelService.ApiClient; // This class is only instantiated after we are logged into to a github account, so we should be safe to grab the first one here as the defaut. account = modelService.GetAccounts() .FirstAsync() .Select(a => a.First()) .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, vm => vm.Account); }
public async Task InitializeAsync(IConnection connection) { modelService = await modelServiceFactory.CreateAsync(connection).ConfigureAwait(true); Title = string.Format(CultureInfo.CurrentCulture, Resources.CreateTitle, connection.HostAddress.Title); accounts = modelService.GetAccounts() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, vm => vm.Accounts, initialValue: new ReadOnlyCollection <IAccount>(Array.Empty <IAccount>())); this.WhenAny(x => x.Accounts, x => x.Value) .Select(accts => accts?.FirstOrDefault()) .WhereNotNull() .Subscribe(a => SelectedAccount = a); modelService.GetGitIgnoreTemplates() .Where(x => x != null) .ToList() .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { var sorted = x .Distinct() .OrderByDescending(item => item.Recommended) .ThenBy(item => item.Name); GitIgnoreTemplates = new[] { GitIgnoreItem.None }.Concat(sorted).ToList(); SelectedGitIgnoreTemplate = GitIgnoreTemplates .FirstOrDefault(i => i?.Name.Equals("VisualStudio", StringComparison.OrdinalIgnoreCase) == true); }); modelService.GetLicenses() .Where(x => x != null) .ToList() .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { var sorted = x .Distinct() .OrderByDescending(item => item.Recommended) .ThenBy(item => item.Key); Licenses = new[] { LicenseItem.None }.Concat(sorted).ToList(); }); }
public GistCreationViewModel( IConnection connection, IModelServiceFactory modelServiceFactory, ISelectedTextProvider selectedTextProvider, IGistPublishService gistPublishService, IUsageTracker usageTracker) { Guard.ArgumentNotNull(connection, nameof(connection)); Guard.ArgumentNotNull(selectedTextProvider, nameof(selectedTextProvider)); Guard.ArgumentNotNull(gistPublishService, nameof(gistPublishService)); Guard.ArgumentNotNull(usageTracker, nameof(usageTracker)); Title = Resources.CreateGistTitle; this.gistPublishService = gistPublishService; this.usageTracker = usageTracker; FileName = VisualStudio.Services.GetFileNameFromActiveDocument() ?? Resources.DefaultGistFileName; SelectedText = selectedTextProvider.GetSelectedText(); var modelService = modelServiceFactory.CreateBlocking(connection); apiClient = modelService.ApiClient; // This class is only instantiated after we are logged into to a github account, so we should be safe to grab the first one here as the defaut. account = modelService.GetAccounts() .FirstAsync() .Select(a => a.First()) .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, vm => vm.Account); var canCreateGist = this.WhenAny( x => x.FileName, fileName => !String.IsNullOrEmpty(fileName.Value)); CreateGist = ReactiveCommand.CreateAsyncObservable(canCreateGist, OnCreateGist); }
public RepositoryCreationViewModel( IConnection connection, IModelServiceFactory modelServiceFactory, IOperatingSystem operatingSystem, IRepositoryCreationService repositoryCreationService, IUsageTracker usageTracker) { Guard.ArgumentNotNull(connection, nameof(connection)); Guard.ArgumentNotNull(modelServiceFactory, nameof(modelServiceFactory)); Guard.ArgumentNotNull(operatingSystem, nameof(operatingSystem)); Guard.ArgumentNotNull(repositoryCreationService, nameof(repositoryCreationService)); Guard.ArgumentNotNull(usageTracker, nameof(usageTracker)); this.operatingSystem = operatingSystem; this.repositoryCreationService = repositoryCreationService; this.usageTracker = usageTracker; Title = string.Format(CultureInfo.CurrentCulture, Resources.CreateTitle, connection.HostAddress.Title); SelectedGitIgnoreTemplate = GitIgnoreItem.None; SelectedLicense = LicenseItem.None; modelService = modelServiceFactory.CreateBlocking(connection); accounts = modelService.GetAccounts() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, vm => vm.Accounts, initialValue: new ReadOnlyCollection <IAccount>(new IAccount[] {})); this.WhenAny(x => x.Accounts, x => x.Value) .Select(accts => accts?.FirstOrDefault()) .WhereNotNull() .Subscribe(a => SelectedAccount = a); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); BaseRepositoryPathValidator = ReactivePropertyValidator.ForObservable(this.WhenAny(x => x.BaseRepositoryPath, x => x.Value)) .IfNullOrEmpty(Resources.RepositoryCreationClonePathEmpty) .IfTrue(x => x.Length > 200, Resources.RepositoryCreationClonePathTooLong) .IfContainsInvalidPathChars(Resources.RepositoryCreationClonePathInvalidCharacters) .IfPathNotRooted(Resources.RepositoryCreationClonePathInvalid); var nonNullRepositoryName = this.WhenAny( x => x.RepositoryName, x => x.BaseRepositoryPath, (x, y) => x.Value) .WhereNotNull(); RepositoryNameValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName) .IfNullOrEmpty(Resources.RepositoryNameValidatorEmpty) .IfTrue(x => x.Length > 100, Resources.RepositoryNameValidatorTooLong) .IfTrue(IsAlreadyRepoAtPath, Resources.RepositoryNameValidatorAlreadyExists); SafeRepositoryNameWarningValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName) .Add(repoName => { var parsedReference = GetSafeRepositoryName(repoName); return(parsedReference != repoName ? String.Format(CultureInfo.CurrentCulture, Resources.SafeRepositoryNameWarning, parsedReference) : null); }); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); CreateRepository = InitializeCreateRepositoryCommand(); canKeepPrivate = CanKeepPrivateObservable.CombineLatest(CreateRepository.IsExecuting, (canKeep, publishing) => canKeep && !publishing) .ToProperty(this, x => x.CanKeepPrivate); isCreating = CreateRepository.IsExecuting .ToProperty(this, x => x.IsCreating); GitIgnoreTemplates = TrackingCollection.CreateListenerCollectionAndRun( modelService.GetGitIgnoreTemplates(), new[] { GitIgnoreItem.None }, OrderedComparer <GitIgnoreItem> .OrderByDescending(item => GitIgnoreItem.IsRecommended(item.Name)).Compare, x => { if (x.Name.Equals("VisualStudio", StringComparison.OrdinalIgnoreCase)) { SelectedGitIgnoreTemplate = x; } }); Licenses = TrackingCollection.CreateListenerCollectionAndRun( modelService.GetLicenses(), new[] { LicenseItem.None }, OrderedComparer <LicenseItem> .OrderByDescending(item => LicenseItem.IsRecommended(item.Name)).Compare); BaseRepositoryPath = repositoryCreationService.DefaultClonePath; }
public async Task InitializeAsync(ILocalRepositoryModel sourceRepository, IAccount destinationAccount, IConnection connection) { var modelService = await modelServiceFactory.CreateAsync(connection); apiClient = modelService.ApiClient; DestinationAccount = destinationAccount; SourceRepository = sourceRepository; DestinationRepository = new RemoteRepositoryModel( 0, sourceRepository.Name, CreateForkUri(sourceRepository.CloneUrl, destinationAccount.Login), false, true, destinationAccount, null); }
public PullRequestCreationViewModel( IConnection connection, IModelServiceFactory modelServiceFactory, ILocalRepositoryModel activeRepo, IPullRequestService service, INotificationService notifications) { Guard.ArgumentNotNull(connection, nameof(connection)); Guard.ArgumentNotNull(modelServiceFactory, nameof(modelServiceFactory)); Guard.ArgumentNotNull(activeRepo, nameof(activeRepo)); Guard.ArgumentNotNull(service, nameof(service)); Guard.ArgumentNotNull(notifications, nameof(notifications)); activeLocalRepo = activeRepo; modelService = modelServiceFactory.CreateBlocking(connection); var obs = modelService.ApiClient.GetRepository(activeRepo.Owner, activeRepo.Name) .Select(r => new RemoteRepositoryModel(r)) .PublishLast(); disposables.Add(obs.Connect()); githubObs = obs; githubRepository = githubObs.ToProperty(this, x => x.GitHubRepository); this.WhenAnyValue(x => x.GitHubRepository) .WhereNotNull() .Subscribe(r => { TargetBranch = r.IsFork ? r.Parent.DefaultBranch : r.DefaultBranch; }); SourceBranch = activeRepo.CurrentBranch; this.WhenAnyValue(x => x.Branches) .WhereNotNull() .Where(_ => TargetBranch != null) .Subscribe(x => { if (!x.Any(t => t.Equals(TargetBranch))) { TargetBranch = GitHubRepository.IsFork ? GitHubRepository.Parent.DefaultBranch : GitHubRepository.DefaultBranch; } }); SetupValidators(); var uniqueCommits = this.WhenAnyValue( x => x.SourceBranch, x => x.TargetBranch) .Where(x => x.Item1 != null && x.Item2 != null) .Select(branches => { var baseBranch = branches.Item1.Name; var compareBranch = branches.Item2.Name; // We only need to get max two commits for what we're trying to achieve here. // If there's no commits we want to block creation of the PR, if there's one commits // we wan't to use its commit message as the PR title/body and finally if there's more // than one we'll use the branch name for the title. return(service.GetMessagesForUniqueCommits(activeRepo, baseBranch, compareBranch, maxCommits: 2) .Catch <IReadOnlyList <CommitMessage>, Exception>(ex => { log.Warning(ex, "Could not load unique commits"); return Observable.Empty <IReadOnlyList <CommitMessage> >(); })); }) .Switch() .ObserveOn(RxApp.MainThreadScheduler) .Replay(1) .RefCount(); var whenAnyValidationResultChanges = this.WhenAny( x => x.TitleValidator.ValidationResult, x => x.BranchValidator.ValidationResult, x => x.IsBusy, (x, y, z) => (x.Value?.IsValid ?? false) && (y.Value?.IsValid ?? false) && !z.Value); this.WhenAny(x => x.BranchValidator.ValidationResult, x => x.GetValue()) .WhereNotNull() .Where(x => !x.IsValid && x.DisplayValidationError) .Subscribe(x => notifications.ShowError(BranchValidator.ValidationResult.Message)); CreatePullRequest = ReactiveCommand.CreateAsyncObservable(whenAnyValidationResultChanges, _ => service .CreatePullRequest(modelService, activeRepo, TargetBranch.Repository, SourceBranch, TargetBranch, PRTitle, Description ?? String.Empty) .Catch <IPullRequestModel, Exception>(ex => { log.Error(ex, "Error creating pull request"); //TODO:Will need a uniform solution to HTTP exception message handling var apiException = ex as ApiValidationException; var error = apiException?.ApiError?.Errors?.FirstOrDefault(); notifications.ShowError(error?.Message ?? ex.Message); return(Observable.Empty <IPullRequestModel>()); })) .OnExecuteCompleted(pr => { notifications.ShowMessage(String.Format(CultureInfo.CurrentCulture, Resources.PRCreatedUpstream, SourceBranch.DisplayName, TargetBranch.Repository.Owner + "/" + TargetBranch.Repository.Name + "#" + pr.Number, TargetBranch.Repository.CloneUrl.ToRepositoryUrl().Append("pull/" + pr.Number))); }); isExecuting = CreatePullRequest.IsExecuting.ToProperty(this, x => x.IsExecuting); this.WhenAnyValue(x => x.Initialized, x => x.GitHubRepository, x => x.Description, x => x.IsExecuting) .Select(x => !(x.Item1 && x.Item2 != null && x.Item3 != null && !x.Item4)) .Subscribe(x => IsBusy = x); Observable.CombineLatest( this.WhenAnyValue(x => x.SourceBranch), uniqueCommits, service.GetPullRequestTemplate(activeRepo).DefaultIfEmpty(string.Empty), (compare, commits, template) => new { compare, commits, template }) .Subscribe(x => { var prTitle = string.Empty; var prDescription = string.Empty; if (x.commits.Count == 1) { prTitle = x.commits[0].Summary; prDescription = x.commits[0].Details; } else { prTitle = x.compare.Name.Humanize(); } if (!string.IsNullOrWhiteSpace(x.template)) { if (!string.IsNullOrEmpty(prDescription)) { prDescription += "\n\n"; } prDescription += x.template; } PRTitle = prTitle; Description = prDescription; }); }
public Task InitializeAsync(LocalRepositoryModel sourceRepository, IAccount destinationAccount, IConnection connection) { return(Task.CompletedTask); }
public async Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection) { modelService = await modelServiceFactory.CreateAsync(connection); activeLocalRepo = repository; SourceBranch = repository.CurrentBranch; var obs = modelService.ApiClient.GetRepository(repository.Owner, repository.Name) .Select(r => new RemoteRepositoryModel(r)) .PublishLast(); disposables.Add(obs.Connect()); var githubObs = obs; githubRepository = githubObs.ToProperty(this, x => x.GitHubRepository); this.WhenAnyValue(x => x.GitHubRepository) .WhereNotNull() .Subscribe(r => { TargetBranch = r.IsFork ? r.Parent.DefaultBranch : r.DefaultBranch; }); githubObs.SelectMany(r => { var b = Observable.Empty <IBranch>(); if (r.IsFork) { b = modelService.GetBranches(r.Parent).Select(x => { return(x); }); } return(b.Concat(modelService.GetBranches(r))); }) .ToList() .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { Branches = x.ToList(); Initialized = true; }); SourceBranch = activeLocalRepo.CurrentBranch; var uniqueCommits = this.WhenAnyValue( x => x.SourceBranch, x => x.TargetBranch) .Where(x => x.Item1 != null && x.Item2 != null) .Select(branches => { var baseBranch = branches.Item1.Name; var compareBranch = branches.Item2.Name; // We only need to get max two commits for what we're trying to achieve here. // If there's no commits we want to block creation of the PR, if there's one commits // we wan't to use its commit message as the PR title/body and finally if there's more // than one we'll use the branch name for the title. return(service.GetMessagesForUniqueCommits(activeLocalRepo, baseBranch, compareBranch, maxCommits: 2) .Catch <IReadOnlyList <CommitMessage>, Exception>(ex => { log.Warning(ex, "Could not load unique commits"); return Observable.Empty <IReadOnlyList <CommitMessage> >(); })); }) .Switch() .ObserveOn(RxApp.MainThreadScheduler) .Replay(1) .RefCount(); Observable.CombineLatest( this.WhenAnyValue(x => x.SourceBranch), uniqueCommits, service.GetPullRequestTemplate(repository).DefaultIfEmpty(string.Empty), (compare, commits, template) => new { compare, commits, template }) .Subscribe(x => { var prTitle = string.Empty; var prDescription = string.Empty; if (x.commits.Count == 1) { prTitle = x.commits[0].Summary; prDescription = x.commits[0].Details; } else { prTitle = x.compare.Name.Humanize(); } if (!string.IsNullOrWhiteSpace(x.template)) { if (!string.IsNullOrEmpty(prDescription)) { prDescription += "\n\n"; } prDescription += x.template; } PRTitle = prTitle; Description = prDescription; }); Initialized = true; }