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()));
        }
Exemple #2
0
        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);
            }
        }
Exemple #6
0
        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));
        }
Exemple #10
0
        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()));
        }
Exemple #11
0
 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);
        }
Exemple #14
0
        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()));
        }
Exemple #15
0
        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));
        }
Exemple #17
0
        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));
        }
Exemple #18
0
 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);
         }
     });
 }
Exemple #19
0
        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()));
        }
Exemple #21
0
        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());
	    }
Exemple #23
0
        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);
            }
        }
Exemple #24
0
        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());
        }
Exemple #25
0
        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();
            });
        }
Exemple #26
0
        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;
                }
            });
        }
Exemple #27
0
        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);
        }