public OAuthTokenLoginViewModel( ILoginService loginFactory, IAccountsRepository accountsRepository, IAlertDialogFactory alertDialogFactory) { Title = "Login"; var canLogin = this.WhenAnyValue(y => y.Token, (x) => !string.IsNullOrEmpty(x)); LoginCommand = ReactiveCommand.CreateAsyncTask(canLogin, async _ => { try { using (alertDialogFactory.Activate("Logging in...")) { var account = await loginFactory.Authenticate(ApiDomain, WebDomain, Token, false); await accountsRepository.SetDefault(account); return(account); } } catch (UnauthorizedException) { throw new Exception("The provided token is invalid! Please try again or " + "create a new token as this one might have been revoked."); } }); LoginCommand.Subscribe(x => MessageBus.Current.SendMessage(new LogoutMessage())); }
protected override async System.Threading.Tasks.Task <Gist> SaveGist() { if (Gist == null) { throw new InvalidOperationException("Missing Gist context to update!"); } var gistUpdate = new GistUpdate { Description = Description ?? string.Empty }; foreach (var file in Gist.Files) { gistUpdate.Files[file.Key] = null; } foreach (var file in Files) { gistUpdate.Files[file.Name] = new GistFileUpdate { Content = file.Content } } ; using (_alertDialogFactory.Activate("Updating Gist...")) return(await _sessionService.GitHubClient.Gist.Edit(Gist.Id, gistUpdate)); }
public OAuthTokenLoginViewModel( ILoginService loginFactory, IAccountsRepository accountsRepository, IAlertDialogFactory alertDialogFactory) { Title = "Login"; var canLogin = this.WhenAnyValue(y => y.Token, (x) => !string.IsNullOrEmpty(x)); LoginCommand = ReactiveCommand.CreateAsyncTask(canLogin, async _ => { try { using (alertDialogFactory.Activate("Logging in...")) { var account = await loginFactory.Authenticate(ApiDomain, WebDomain, Token, false); await accountsRepository.SetDefault(account); return account; } } catch (UnauthorizedException) { throw new Exception("The provided token is invalid! Please try again or " + "create a new token as this one might have been revoked."); } }); LoginCommand.Subscribe(x => MessageBus.Current.SendMessage(new LogoutMessage())); }
public CreateFileViewModel(ISessionService sessionService, IAlertDialogFactory alertDialogFactory) { Title = "Create File"; this.WhenAnyValue(x => x.Name) .Subscribe(x => CommitMessage = "Created " + x); GoToCommitMessageCommand = ReactiveCommand.Create( this.WhenAnyValue(x => x.Name, x => !string.IsNullOrEmpty(x))); SaveCommand = ReactiveCommand.CreateAsyncTask( this.WhenAnyValue(x => x.Name).Select(x => !string.IsNullOrEmpty(x)), async _ => { var content = Content ?? string.Empty; var path = System.IO.Path.Combine(Path ?? string.Empty, Name); var request = new Octokit.CreateFileRequest(CommitMessage, content) { Branch = Branch }; using (alertDialogFactory.Activate("Commiting...")) return await sessionService.GitHubClient.Repository.Content.CreateFile(RepositoryOwner, RepositoryName, path, request); }); SaveCommand.Subscribe(x => Dismiss()); DismissCommand = ReactiveCommand.CreateAsyncTask(async t => { if (string.IsNullOrEmpty(Name) && string.IsNullOrEmpty(Content)) return true; return await alertDialogFactory.PromptYesNo("Discard File?", "Are you sure you want to discard this file?"); }); DismissCommand.Where(x => x).Subscribe(_ => Dismiss()); }
private async Task <GitHubAccount> Login(string code) { using (_alertDialogService.Activate("Logging in...")) { var token = await Client.RequestAccessToken(ClientId, ClientSecret, code, RedirectUri, WebDomain); var client = Client.BasicOAuth(token.AccessToken); var info = (await client.ExecuteAsync(client.AuthenticatedUser.GetInfo())).Data; client.Username = info.Login; var account = (await _accountsRepository.Find(Client.DefaultApi, info.Login)) ?? new GitHubAccount(); account.Username = info.Login; account.OAuth = token.AccessToken; account.AvatarUrl = info.AvatarUrl; account.Name = info.Name; account.Email = info.Email; account.Domain = Client.DefaultApi; account.WebDomain = WebDomain; account.IsEnterprise = false; await _accountsRepository.Insert(account); await _accountsRepository.SetDefault(account); return(account); } }
public CreateFileViewModel(ISessionService sessionService, IAlertDialogFactory alertDialogFactory) { Title = "Create File"; this.WhenAnyValue(x => x.Name) .Subscribe(x => CommitMessage = "Created " + x); _canCommit = this.WhenAnyValue(x => x.Name) .Select(x => !string.IsNullOrEmpty(x)) .ToProperty(this, x => x.CanCommit); SaveCommand = ReactiveCommand.CreateAsyncTask( this.WhenAnyValue(x => x.Name).Select(x => !string.IsNullOrEmpty(x)), async _ => { var content = Content ?? string.Empty; var path = System.IO.Path.Combine(Path ?? string.Empty, Name); var request = new Octokit.CreateFileRequest(CommitMessage, content) { Branch = Branch }; using (alertDialogFactory.Activate("Commiting...")) return(await sessionService.GitHubClient.Repository.Content.CreateFile(RepositoryOwner, RepositoryName, path, request)); }); SaveCommand.Subscribe(x => Dismiss()); DismissCommand = ReactiveCommand.CreateAsyncTask(async t => { if (string.IsNullOrEmpty(Name) && string.IsNullOrEmpty(Content)) { return(true); } return(await alertDialogFactory.PromptYesNo("Discard File?", "Are you sure you want to discard this file?")); }); DismissCommand.Where(x => x).Subscribe(_ => Dismiss()); }
protected AddAccountViewModel(IAlertDialogFactory alertDialogFactory) { _alertDialogFactory = alertDialogFactory; Title = "Login"; this.WhenAnyValue(x => x.AttemptedAccount).Where(x => x != null).Subscribe(x => { Username = x.Username; Domain = x.Domain; }); LoginCommand = ReactiveCommand.CreateAsyncTask(async _ => { if (string.IsNullOrEmpty(Username)) throw new ArgumentException("Must have a valid username!"); if (string.IsNullOrEmpty(Password)) throw new ArgumentException("Must have a valid password!"); if (string.IsNullOrEmpty(Domain)) throw new ArgumentException("Must have a valid GitHub domain!"); using (alertDialogFactory.Activate("Logging in...")) return await Login(); }); LoginCommand.ThrownExceptions.Subscribe(x => { if (x is LoginService.TwoFactorRequiredException) PromptForTwoFactor().ToBackground(); else _alertDialogFactory.Alert("Error", x.Message).ToBackground(); }); LoginCommand.Subscribe(x => MessageBus.Current.SendMessage(new LogoutMessage())); }
public MarkdownAccessoryViewModel( IImgurService imgurService, IMediaPickerFactory mediaPicker, IAlertDialogFactory alertDialogFactory, IDefaultValueService defaultValueService) { PostToImgurCommand = ReactiveCommand.CreateAsyncTask(async _ => { if (!defaultValueService.GetOrDefault(IMGUR_UPLOAD_WARN, false)) { defaultValueService.Set(IMGUR_UPLOAD_WARN, true); await alertDialogFactory.Alert("Please Read!", IMGUR_UPLOAD_WARN_MESSAGE); } var photo = await mediaPicker.PickPhoto(); var memoryStream = new MemoryStream(); await photo.Save(Splat.CompressedBitmapFormat.Jpeg, 0.8f, memoryStream); using (alertDialogFactory.Activate("Uploading...")) { var model = await imgurService.SendImage(memoryStream.ToArray()); if (model == null || model.Data == null || model.Data.Link == null) { throw new InvalidOperationException("Unable to upload to Imgur. Please try again later."); } return(model.Data.Link); } }); PostToImgurCommand.ThrownExceptions .Where(x => !(x is TaskCanceledException)) .Subscribe(x => alertDialogFactory.Alert("Upload Error", x.Message)); }
public MarkdownAccessoryViewModel( IImgurService imgurService, IMediaPickerFactory mediaPicker, IAlertDialogFactory alertDialogFactory, IDefaultValueService defaultValueService) { PostToImgurCommand = ReactiveCommand.CreateAsyncTask(async _ => { if (!defaultValueService.GetOrDefault(IMGUR_UPLOAD_WARN, false)) { defaultValueService.Set(IMGUR_UPLOAD_WARN, true); await alertDialogFactory.Alert("Please Read!", IMGUR_UPLOAD_WARN_MESSAGE); } var photo = await mediaPicker.PickPhoto(); var memoryStream = new MemoryStream(); await photo.Save(Splat.CompressedBitmapFormat.Jpeg, 0.8f, memoryStream); using (alertDialogFactory.Activate("Uploading...")) { var model = await imgurService.SendImage(memoryStream.ToArray()); if (model == null || model.Data == null || model.Data.Link == null) throw new InvalidOperationException("Unable to upload to Imgur. Please try again later."); return model.Data.Link; } }); PostToImgurCommand.ThrownExceptions .Where(x => !(x is TaskCanceledException)) .Subscribe(x => alertDialogFactory.Alert("Upload Error", x.Message)); }
protected AddAccountViewModel(IAlertDialogFactory alertDialogFactory) { _alertDialogFactory = alertDialogFactory; Title = "Login"; this.WhenAnyValue(x => x.AttemptedAccount).Where(x => x != null).Subscribe(x => { Username = x.Username; Domain = x.Domain; }); var canLogin = this.WhenAnyValue(x => x.Username, y => y.Password, z => z.Domain, (x, y, z) => !string.IsNullOrEmpty(x) && !string.IsNullOrEmpty(y) && !string.IsNullOrEmpty(z)); LoginCommand = ReactiveCommand.CreateAsyncTask(canLogin, async _ => { using (alertDialogFactory.Activate("Logging in...")) return await Login(); }); LoginCommand.ThrownExceptions.Subscribe(x => { if (x is LoginService.TwoFactorRequiredException) PromptForTwoFactor().ToBackground(); else _alertDialogFactory.Alert("Error", x.Message).ToBackground(); }); LoginCommand.Subscribe(x => MessageBus.Current.SendMessage(new LogoutMessage())); }
protected IssueModifyViewModel(IAlertDialogFactory alertDialogFactory) { SaveCommand = ReactiveCommand.CreateAsyncTask(async _ => { using (alertDialogFactory.Activate("Saving...")) await Save(); Dismiss(); }); }
public GistCreateViewModel(IApplicationService applicationService, IAlertDialogFactory alertDialogFactory) { _applicationService = applicationService; CurrentAccount = applicationService.Account; Title = "Create Gist"; IsPublic = true; var files = new ReactiveList <Tuple <string, string> >(); Files = files.CreateDerivedCollection(x => { var item = new GistFileItemViewModel(x.Item1, x.Item2); item.EditCommand.Subscribe(_ => NavigateTo(new GistFileEditViewModel(y => { var i = files.IndexOf(x); files.Remove(x); files.Insert(i, y); return(Task.FromResult(0)); }) { Filename = x.Item1, Description = x.Item2 })); item.DeleteCommand.Subscribe(_ => files.Remove(x)); return(item); }); SaveCommand = ReactiveCommand.CreateAsyncTask(Files.CountChanged.Select(x => x > 0), async t => { var createGist = new GistCreateModel { Description = Description, Public = IsPublic, Files = Files.ToDictionary(x => x.Name, x => new GistCreateModel.File { Content = x.Content }) }; var request = _applicationService.Client.AuthenticatedUser.Gists.CreateGist(createGist); using (alertDialogFactory.Activate("Creating Gist...")) return((await _applicationService.Client.ExecuteAsync(request)).Data); }); SaveCommand.Subscribe(_ => Dismiss()); AddGistFileCommand = ReactiveCommand.Create() .WithSubscription(_ => NavigateTo(new GistFileAddViewModel(x => { if (Files.Any(y => y.Name == x.Item1)) { throw new Exception("Gist already contains a file with that name!"); } files.Add(x); return(Task.FromResult(0)); }))); }
public PullRequestViewModel( ISessionService applicationService, IMarkdownService markdownService, IActionMenuFactory actionMenuService, IAlertDialogFactory alertDialogFactory) : base(applicationService, markdownService, actionMenuService, alertDialogFactory) { this.WhenAnyValue(x => x.Id) .Subscribe(x => Title = "Pull Request #" + x); this.WhenAnyValue(x => x.PullRequest.HtmlUrl) .ToProperty(this, x => x.HtmlUrl, out _htmlUrl); var canMergeObservable = this.WhenAnyValue(x => x.PullRequest) .Select(x => x != null && !x.Merged && x.Mergeable.HasValue && x.Mergeable.Value); _canMerge = canMergeObservable.CombineLatest( this.WhenAnyValue(x => x.PushAccess), (x, y) => x && y) .ToProperty(this, x => x.CanMerge); _commentsCount = this.WhenAnyValue(x => x.Issue.Comments, x => x.Comments.Count, (x, y) => x + y) .ToProperty(this, x => x.CommentCount); MergeCommand = ReactiveCommand.CreateAsyncTask(canMergeObservable, async t => { using (alertDialogFactory.Activate("Merging...")) { var req = new MergePullRequest { Message = MergeComment }; var response = await applicationService.GitHubClient.PullRequest.Merge(RepositoryOwner, RepositoryName, Id, req); if (!response.Merged) { throw new Exception(string.Format("Unable to merge pull request: {0}", response.Message)); } await LoadCommand.ExecuteAsync(); } }); var canGoToCommits = this.WhenAnyValue(x => x.PullRequest.Commits).Select(x => x > 0); GoToCommitsCommand = ReactiveCommand.Create(canGoToCommits); GoToCommitsCommand .Select(x => this.CreateViewModel <PullRequestCommitsViewModel>()) .Select(x => x.Init(RepositoryOwner, RepositoryName, Id)) .Subscribe(NavigateTo); var canGoToFiles = this.WhenAnyValue(x => x.PullRequest.ChangedFiles).Select(x => x > 0); GoToFilesCommand = ReactiveCommand.Create(canGoToFiles); GoToFilesCommand .Select(x => this.CreateViewModel <PullRequestFilesViewModel>()) .Select(x => x.Init(RepositoryOwner, RepositoryName, Id, PullRequest.Head.Sha)) .Do(x => x.CommentCreated.Subscribe(AddComment)) .Subscribe(NavigateTo); }
public EnterpriseOAuthTokenLoginViewModel( ILoginService loginFactory, IAccountsRepository accountsRepository, IAlertDialogFactory alertDialogFactory) { Title = "Login"; LoginCommand = ReactiveCommand.CreateAsyncTask(async _ => { if (string.IsNullOrEmpty(Domain)) { throw new ArgumentException("Must have a valid GitHub domain"); } if (string.IsNullOrEmpty(Token)) { throw new ArgumentException("Must have a valid Token"); } Uri domainUri; if (!Uri.TryCreate(Domain, UriKind.Absolute, out domainUri)) { throw new Exception("The provided domain is not a valid URL."); } var apiUrl = Domain; if (apiUrl != null) { if (!apiUrl.EndsWith("/", StringComparison.Ordinal)) { apiUrl += "/"; } if (!apiUrl.Contains("/api/")) { apiUrl += "api/v3/"; } } try { using (alertDialogFactory.Activate("Logging in...")) { var account = await loginFactory.Authenticate(apiUrl, Domain, Token, true); await accountsRepository.SetDefault(account); return(account); } } catch (UnauthorizedException) { throw new Exception("The provided token is invalid! Please try again or " + "create a new token as this one might have been revoked."); } }); LoginCommand.Subscribe(x => MessageBus.Current.SendMessage(new LogoutMessage())); }
public EditFileViewModel(ISessionService sessionService, IAlertDialogFactory alertDialogFactory) { Title = "Edit"; this.WhenAnyValue(x => x.Path) .IsNotNull() .Subscribe(x => CommitMessage = "Updated " + x.Substring(x.LastIndexOf('/') + 1)); this.WhenAnyValue(x => x.Text) .Subscribe(x => _lastEdit = DateTime.Now); LoadCommand = ReactiveCommand.CreateAsyncTask(async t => { var path = Path; if (!path.StartsWith("/", StringComparison.Ordinal)) { path = "/" + path; } var request = sessionService.Client.Users[RepositoryOwner].Repositories[RepositoryName].GetContentFile(path, Branch ?? "master"); request.UseCache = false; var data = await sessionService.Client.ExecuteAsync(request); BlobSha = data.Data.Sha; var content = Convert.FromBase64String(data.Data.Content); Text = System.Text.Encoding.UTF8.GetString(content, 0, content.Length) ?? string.Empty; _lastLoad = DateTime.Now; }); GoToCommitMessageCommand = ReactiveCommand.Create(); SaveCommand = ReactiveCommand.CreateAsyncTask( this.WhenAnyValue(x => x.CommitMessage).Select(x => !string.IsNullOrEmpty(x)), async _ => { var path = Path.TrimStart('/'); var request = new Octokit.UpdateFileRequest(CommitMessage, Text, BlobSha) { Branch = Branch }; using (alertDialogFactory.Activate("Commiting...")) return(await sessionService.GitHubClient.Repository.Content.UpdateFile(RepositoryOwner, RepositoryName, path, request)); }); SaveCommand.Subscribe(x => Dismiss()); DismissCommand = ReactiveCommand.CreateAsyncTask(async t => { if (string.IsNullOrEmpty(Text)) { return(true); } if (_lastEdit <= _lastLoad) { return(true); } return(await alertDialogFactory.PromptYesNo("Discard Edit?", "Are you sure you want to discard these changes?")); }); DismissCommand.Where(x => x).Subscribe(_ => Dismiss()); }
public FeedbackComposerViewModel( IApplicationService applicationService, IImgurService imgurService, IMediaPickerFactory mediaPicker, IAlertDialogFactory alertDialogService) { this.WhenAnyValue(x => x.IsFeature).Subscribe(x => Title = x ? "New Feature" : "Bug Report"); SubmitCommand = ReactiveCommand.CreateAsyncTask( this.WhenAnyValue(x => x.Subject).Select(x => !string.IsNullOrEmpty(x)), async _ => { if (string.IsNullOrEmpty(Subject)) { throw new ArgumentException(string.Format("You must provide a title for this {0}!", IsFeature ? "feature" : "bug")); } var labels = await applicationService.GitHubClient.Issue.Labels.GetForRepository(CodeHubOwner, CodeHubName); var createLabels = labels.Where(x => string.Equals(x.Name, IsFeature ? "feature request" : "bug", StringComparison.OrdinalIgnoreCase)).Select(x => x.Name).Distinct(); var createIssueRequest = new Octokit.NewIssue(Subject) { Body = Description }; foreach (var label in createLabels) { createIssueRequest.Labels.Add(label); } var createdIssue = await applicationService.GitHubClient.Issue.Create(CodeHubOwner, CodeHubName, createIssueRequest); _createdIssueSubject.OnNext(createdIssue); Dismiss(); }); PostToImgurCommand = ReactiveCommand.CreateAsyncTask(async _ => { var photo = await mediaPicker.PickPhoto(); var memoryStream = new MemoryStream(); await photo.Save(Splat.CompressedBitmapFormat.Jpeg, 0.8f, memoryStream); using (alertDialogService.Activate("Uploading...")) { var model = await imgurService.SendImage(memoryStream.ToArray()); if (model == null || model.Data == null || model.Data.Link == null) { throw new InvalidOperationException("Unable to upload to Imgur. Please try again later."); } return(model.Data.Link); } }); PostToImgurCommand.ThrownExceptions .Where(x => !(x is TaskCanceledException)) .Subscribe(x => alertDialogService.Alert("Upload Error", x.Message)); }
protected override async System.Threading.Tasks.Task <Gist> SaveGist() { var newGist = new NewGist { Description = Description ?? string.Empty, Public = IsPublic }; foreach (var file in Files) { newGist.Files[file.Name.Trim()] = file.Content; } using (_alertDialogFactory.Activate("Creating Gist...")) return(await _sessionService.GitHubClient.Gist.Create(newGist)); }
protected MarkdownComposerViewModel(IImgurService imgurService, IMediaPickerFactory mediaPicker, IAlertDialogFactory alertDialogFactory) { PostToImgurCommand = ReactiveCommand.CreateAsyncTask(async _ => { var photo = await mediaPicker.PickPhoto(); var memoryStream = new MemoryStream(); await photo.Save(Splat.CompressedBitmapFormat.Jpeg, 0.8f, memoryStream); using (alertDialogFactory.Activate("Uploading...")) { var model = await imgurService.SendImage(memoryStream.ToArray()); if (model == null || model.Data == null || model.Data.Link == null) { throw new InvalidOperationException("Unable to upload to Imgur. Please try again later."); } return(model.Data.Link); } }); }
protected AddAccountViewModel(IAlertDialogFactory alertDialogFactory) { _alertDialogFactory = alertDialogFactory; Title = "Login"; this.WhenAnyValue(x => x.AttemptedAccount).Where(x => x != null).Subscribe(x => { Username = x.Username; Domain = x.Domain; }); LoginCommand = ReactiveCommand.CreateAsyncTask(async _ => { if (string.IsNullOrEmpty(Username)) { throw new ArgumentException("Must have a valid username!"); } if (string.IsNullOrEmpty(Password)) { throw new ArgumentException("Must have a valid password!"); } if (string.IsNullOrEmpty(Domain)) { throw new ArgumentException("Must have a valid GitHub domain!"); } using (alertDialogFactory.Activate("Logging in...")) return(await Login()); }); LoginCommand.ThrownExceptions.Subscribe(x => { if (x is LoginService.TwoFactorRequiredException) { PromptForTwoFactor().ToBackground(); } else { _alertDialogFactory.Alert("Error", x.Message).ToBackground(); } }); LoginCommand.Subscribe(x => MessageBus.Current.SendMessage(new LogoutMessage())); }
public EnterpriseOAuthTokenLoginViewModel( ILoginService loginFactory, IAccountsRepository accountsRepository, IAlertDialogFactory alertDialogFactory) { Title = "Login"; LoginCommand = ReactiveCommand.CreateAsyncTask(async _ => { if (string.IsNullOrEmpty(Domain)) throw new ArgumentException("Must have a valid GitHub domain"); if (string.IsNullOrEmpty(Token)) throw new ArgumentException("Must have a valid Token"); Uri domainUri; if (!Uri.TryCreate(Domain, UriKind.Absolute, out domainUri)) throw new Exception("The provided domain is not a valid URL."); var apiUrl = Domain; if (apiUrl != null) { if (!apiUrl.EndsWith("/", StringComparison.Ordinal)) apiUrl += "/"; if (!apiUrl.Contains("/api/")) apiUrl += "api/v3/"; } try { using (alertDialogFactory.Activate("Logging in...")) { var account = await loginFactory.Authenticate(apiUrl, Domain, Token, true); await accountsRepository.SetDefault(account); return account; } } catch (UnauthorizedException) { throw new Exception("The provided token is invalid! Please try again or " + "create a new token as this one might have been revoked."); } }); LoginCommand.Subscribe(x => MessageBus.Current.SendMessage(new LogoutMessage())); }
public EditFileViewModel(ISessionService sessionService, IAlertDialogFactory alertDialogFactory) { Title = "Edit"; this.WhenAnyValue(x => x.Path) .IsNotNull() .Subscribe(x => CommitMessage = "Updated " + x.Substring(x.LastIndexOf('/') + 1)); this.WhenAnyValue(x => x.Text) .Subscribe(x => _lastEdit = DateTime.Now); LoadCommand = ReactiveCommand.CreateAsyncTask(async t => { var path = Path; if (!path.StartsWith("/", StringComparison.Ordinal)) path = "/" + path; var request = sessionService.Client.Users[RepositoryOwner].Repositories[RepositoryName].GetContentFile(path, Branch ?? "master"); request.UseCache = false; var data = await sessionService.Client.ExecuteAsync(request); BlobSha = data.Data.Sha; var content = Convert.FromBase64String(data.Data.Content); Text = System.Text.Encoding.UTF8.GetString(content, 0, content.Length) ?? string.Empty; _lastLoad = DateTime.Now; }); GoToCommitMessageCommand = ReactiveCommand.Create(); SaveCommand = ReactiveCommand.CreateAsyncTask( this.WhenAnyValue(x => x.CommitMessage).Select(x => !string.IsNullOrEmpty(x)), async _ => { var path = Path.TrimStart('/'); var request = new Octokit.UpdateFileRequest(CommitMessage, Text, BlobSha) { Branch = Branch }; using (alertDialogFactory.Activate("Commiting...")) return await sessionService.GitHubClient.Repository.Content.UpdateFile(RepositoryOwner, RepositoryName, path, request); }); SaveCommand.Subscribe(x => Dismiss()); DismissCommand = ReactiveCommand.CreateAsyncTask(async t => { if (string.IsNullOrEmpty(Text)) return true; if (_lastEdit <= _lastLoad) return true; return await alertDialogFactory.PromptYesNo("Discard Edit?", "Are you sure you want to discard these changes?"); }); DismissCommand.Where(x => x).Subscribe(_ => Dismiss()); }
protected IssueModifyViewModel( ISessionService applicationService, IAlertDialogFactory alertDialogFactory) { GoToAssigneesCommand = ReactiveCommand.Create(); GoToLabelsCommand = ReactiveCommand.Create(); GoToMilestonesCommand = ReactiveCommand.Create(); // Make sure repeated access is cached with Lazy var getAssignees = new Lazy<Task<IReadOnlyList<User>>>(() => applicationService.GitHubClient.Issue.Assignee.GetAllForRepository(RepositoryOwner, RepositoryName)); var getMilestones = new Lazy<Task<IReadOnlyList<Milestone>>>(() => applicationService.GitHubClient.Issue.Milestone.GetAllForRepository(RepositoryOwner, RepositoryName)); var getLables = new Lazy<Task<IReadOnlyList<Label>>>(() => applicationService.GitHubClient.Issue.Labels.GetAllForRepository(RepositoryOwner, RepositoryName)); Assignees = new IssueAssigneeViewModel(() => getAssignees.Value); Milestones = new IssueMilestonesViewModel(() => getMilestones.Value); Labels = new IssueLabelsViewModel(() => getLables.Value); var canSave = this.WhenAnyValue(x => x.Subject).Select(x => !string.IsNullOrEmpty(x)); SaveCommand = ReactiveCommand.CreateAsyncTask(canSave, _ => { using (alertDialogFactory.Activate("Saving...")) return Save(); }); // This is because the stupid ReactiveUI issue with the tableview :( SaveCommand.Subscribe(_ => Dismiss()); LoadCommand = ReactiveCommand.CreateAsyncTask(async t => { try { IsCollaborator = await applicationService.GitHubClient.Repository.RepoCollaborators .IsCollaborator(RepositoryOwner, RepositoryName, applicationService.Account.Username); } catch { IsCollaborator = false; } }); DismissCommand = ReactiveCommand.CreateAsyncTask(t => Discard()); DismissCommand.Where(x => x).Subscribe(_ => Dismiss()); }
private async Task <Octokit.Issue> UpdateIssue(Octokit.User assignee, Octokit.Milestone milestone, IEnumerable <Octokit.Label> labels) { var update = new Octokit.IssueUpdate { Assignee = assignee?.Login, Milestone = milestone?.Number }; update.ClearLabels(); foreach (var l in (labels ?? Enumerable.Empty <Octokit.Label>())) { update.AddLabel(l.Name); } using (_alertDialogFactory.Activate("Updating...")) { Issue = await _applicationService.GitHubClient.Issue.Update(RepositoryOwner, RepositoryName, Id, update); InternalEvents.Reset(await RetrieveEvents()); return(Issue); } }
protected IssueModifyViewModel( ISessionService sessionService, IAlertDialogFactory alertDialogFactory) { GoToAssigneesCommand = ReactiveCommand.Create(); GoToLabelsCommand = ReactiveCommand.Create(); GoToMilestonesCommand = ReactiveCommand.Create(); _assigneesCache = new Lazy <Task <IReadOnlyList <User> > >(() => sessionService.GitHubClient.Issue.Assignee.GetAllForRepository(RepositoryOwner, RepositoryName)); _milestonesCache = new Lazy <Task <IReadOnlyList <Milestone> > >(() => sessionService.GitHubClient.Issue.Milestone.GetAllForRepository(RepositoryOwner, RepositoryName)); _labelsCache = new Lazy <Task <IReadOnlyList <Label> > >(() => sessionService.GitHubClient.Issue.Labels.GetAllForRepository(RepositoryOwner, RepositoryName)); var canSave = this.WhenAnyValue(x => x.Subject).Select(x => !string.IsNullOrEmpty(x)); SaveCommand = ReactiveCommand.CreateAsyncTask(canSave, _ => { using (alertDialogFactory.Activate("Saving...")) return(Save()); }); // This is because the stupid ReactiveUI issue with the tableview :( SaveCommand.Subscribe(_ => Dismiss()); LoadCommand = ReactiveCommand.CreateAsyncTask(async t => { try { IsCollaborator = await sessionService.GitHubClient.Repository.RepoCollaborators .IsCollaborator(RepositoryOwner, RepositoryName, sessionService.Account.Username); } catch { IsCollaborator = false; } }); DismissCommand = ReactiveCommand.CreateAsyncTask(t => Discard()); DismissCommand.Where(x => x).Subscribe(_ => Dismiss()); }
public EditFileViewModel(IApplicationService applicationService, IAlertDialogFactory alertDialogFactory) { Title = "Edit"; this.WhenAnyValue(x => x.Path) .IsNotNull() .Subscribe(x => CommitMessage = "Updated " + x.Substring(x.LastIndexOf('/') + 1)); LoadCommand = ReactiveCommand.CreateAsyncTask(async t => { var path = Path; if (!path.StartsWith("/", StringComparison.Ordinal)) { path = "/" + path; } var request = applicationService.Client.Users[RepositoryOwner].Repositories[RepositoryName].GetContentFile(path, Branch ?? "master"); request.UseCache = false; var data = await applicationService.Client.ExecuteAsync(request); BlobSha = data.Data.Sha; var content = Convert.FromBase64String(data.Data.Content); Text = System.Text.Encoding.UTF8.GetString(content, 0, content.Length) ?? string.Empty; }); SaveCommand = ReactiveCommand.CreateAsyncTask( this.WhenAnyValue(x => x.CommitMessage).Select(x => !string.IsNullOrEmpty(x)), async _ => { var path = Path.StartsWith("/", StringComparison.Ordinal) ? Path : string.Concat("/", Path); var request = applicationService.Client.Users[RepositoryOwner].Repositories[RepositoryName] .UpdateContentFile(path, CommitMessage, Text, BlobSha, Branch); using (alertDialogFactory.Activate("Commiting...")) { var response = await applicationService.Client.ExecuteAsync(request); _sourceChangedSubject.OnNext(response.Data); } Dismiss(); }); }
protected IssueModifyViewModel( IApplicationService applicationService, IAlertDialogFactory alertDialogFactory) { GoToAssigneesCommand = ReactiveCommand.Create(); GoToLabelsCommand = ReactiveCommand.Create(); GoToMilestonesCommand = ReactiveCommand.Create(); Assignees = new IssueAssigneeViewModel( () => applicationService.GitHubClient.Issue.Assignee.GetForRepository(RepositoryOwner, RepositoryName), () => Task.FromResult(AssignedUser), x => Task.FromResult(AssignedUser = x)); Milestones = new IssueMilestonesViewModel( () => applicationService.GitHubClient.Issue.Milestone.GetForRepository(RepositoryOwner, RepositoryName), () => Task.FromResult(AssignedMilestone), x => Task.FromResult(AssignedMilestone = x)); var assignedLabels = new ReactiveList <Octokit.Label>(); AssignedLabels = assignedLabels.CreateDerivedCollection(y => y); Labels = new IssueLabelsViewModel( () => applicationService.GitHubClient.Issue.Labels.GetForRepository(RepositoryOwner, RepositoryName), () => Task.FromResult(new ReadOnlyCollection <Octokit.Label>(AssignedLabels.ToList()) as IReadOnlyList <Octokit.Label>), x => { assignedLabels.Reset(x); return(Task.FromResult(0)); }); Labels.SelectedLabels.Changed .Select(_ => new ReadOnlyCollection <Octokit.Label>(Labels.SelectedLabels.ToList())) .Subscribe(x => assignedLabels.Reset(x)); var canSave = this.WhenAnyValue(x => x.Subject).Select(x => !string.IsNullOrEmpty(x)); SaveCommand = ReactiveCommand.CreateAsyncTask(canSave, async _ => { using (alertDialogFactory.Activate("Saving...")) { await Save(); // This is because the stupid ReactiveUI issue with the tableview :( await Task.Delay(400); } Dismiss(); }); LoadCommand = ReactiveCommand.CreateAsyncTask(async t => { try { IsCollaborator = await applicationService.GitHubClient.Repository.RepoCollaborators .IsCollaborator(RepositoryOwner, RepositoryName, applicationService.Account.Username); } catch { IsCollaborator = false; } }); }
public GistCreateViewModel(IApplicationService applicationService, IAlertDialogFactory alertDialogFactory) { _applicationService = applicationService; CurrentAccount = applicationService.Account; Title = "Create Gist"; Files = new Dictionary <string, string>(); IsPublic = true; SaveCommand = ReactiveCommand.CreateAsyncTask( this.WhenAnyValue(x => x.Files).Select(x => x.Count > 0), async t => { var createGist = new GistCreateModel { Description = Description, Public = IsPublic, Files = Files.ToDictionary(x => x.Key, x => new GistCreateModel.File { Content = x.Value }) }; var request = _applicationService.Client.AuthenticatedUser.Gists.CreateGist(createGist); using (alertDialogFactory.Activate("Creating Gist...")) _createdGistSubject.OnNext((await _applicationService.Client.ExecuteAsync(request)).Data); Dismiss(); }); AddGistFileCommand = ReactiveCommand.Create().WithSubscription(_ => { var vm = this.CreateViewModel <ModifyGistViewModel>(); vm.Title = "New File"; vm.SaveCommand.Subscribe(__ => { if (Files.ContainsKey(vm.Filename)) { alertDialogFactory.Alert("File already exists!", "Gist already contains a file with that name!"); } else { Files.Add(vm.Filename, vm.Description); Files = new Dictionary <string, string>(Files); vm.Dismiss(); } }); NavigateTo(vm); }); ModifyGistFileCommand = ReactiveCommand.Create(); // Analysis disable once ConvertClosureToMethodGroup // Don't remove the lambda below. It doesn't actually seem to work correctly ModifyGistFileCommand.OfType <string>().Where(x => Files.ContainsKey(x)).Subscribe(x => { var vm = this.CreateViewModel <ModifyGistViewModel>(); vm.Title = vm.Filename = x; vm.Description = Files[x]; vm.SaveCommand.Subscribe(__ => { Files.Remove(x); Files[vm.Filename] = vm.Description; Files = new Dictionary <string, string>(Files); vm.Dismiss(); }); NavigateTo(vm); }); }
public PullRequestViewModel( ISessionService applicationService, IMarkdownService markdownService, IActionMenuFactory actionMenuService, IAlertDialogFactory alertDialogFactory) : base(applicationService, markdownService, actionMenuService, alertDialogFactory) { this.WhenAnyValue(x => x.Id) .Subscribe(x => Title = "Pull Request #" + x); this.WhenAnyValue(x => x.PullRequest.HtmlUrl) .ToProperty(this, x => x.HtmlUrl, out _htmlUrl); var canMergeObservable = this.WhenAnyValue(x => x.PullRequest) .Select(x => x != null && !x.Merged && x.Mergeable.HasValue && x.Mergeable.Value); _canMerge = canMergeObservable.CombineLatest( this.WhenAnyValue(x => x.PushAccess), (x, y) => x && y) .ToProperty(this, x => x.CanMerge); _commentsCount = this.WhenAnyValue(x => x.Issue.Comments, x => x.Comments.Count, (x, y) => x + y) .ToProperty(this, x => x.CommentCount); MergeCommand = ReactiveCommand.CreateAsyncTask(canMergeObservable, async t => { using (alertDialogFactory.Activate("Merging...")) { var req = new MergePullRequest { Message = MergeComment }; var response = await applicationService.GitHubClient.PullRequest.Merge(RepositoryOwner, RepositoryName, Id, req); if (!response.Merged) throw new Exception(string.Format("Unable to merge pull request: {0}", response.Message)); await LoadCommand.ExecuteAsync(); } }); GoToCommitsCommand = ReactiveCommand.Create(); GoToCommitsCommand .Select(x => this.CreateViewModel<PullRequestCommitsViewModel>()) .Select(x => x.Init(RepositoryOwner, RepositoryName, Id)) .Subscribe(NavigateTo); var canGoToFiles = this.WhenAnyValue(x => x.PullRequest).Select(x => x != null); GoToFilesCommand = ReactiveCommand.Create(canGoToFiles); GoToFilesCommand .Select(x => this.CreateViewModel<PullRequestFilesViewModel>()) .Select(x => x.Init(RepositoryOwner, RepositoryName, Id, PullRequest.Head.Sha)) .Do(x => x.CommentCreated.Subscribe(AddComment)) .Subscribe(NavigateTo); }