Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
1a17ec4
Display basic PR details.
grokys Sep 16, 2016
b281ce0
Allow PR details to be opened more than once.
grokys Sep 16, 2016
e71726c
Clicking PR number opens PR on GitHub.
grokys Sep 16, 2016
13df498
Add more stuff to PR details.
grokys Sep 16, 2016
e82016a
Merge branch 'master' into grokys/pr-detail
grokys Sep 16, 2016
d48f422
Filled out PR details form XAML.
grokys Sep 20, 2016
c4ba3f0
Display more PR detail information.
grokys Sep 20, 2016
2bbdd88
Rejigged PR detail view layout.
grokys Sep 20, 2016
5d1d177
Implement PR Open/Closed label.
grokys Sep 20, 2016
8ac5503
Shorten branch name if not from a fork.
grokys Sep 20, 2016
7669160
Added body right margin.
grokys Sep 20, 2016
7ad0d4b
Fix separator overflow.
grokys Sep 20, 2016
524c3e2
Skip ModelService for PR details.
grokys Sep 20, 2016
7d52f9c
Started adding changes tree to PR details.
grokys Sep 21, 2016
ff38e49
Use TeamExplorer's SectionControl.
grokys Sep 21, 2016
4efb5f6
Fix mouse wheel scrolling in PR details.
grokys Sep 21, 2016
45060f6
Merge branch 'master' into grokys/pr-detail
grokys Sep 22, 2016
9654986
Display spinner in PR details view.
grokys Sep 22, 2016
0b46eba
Display avatar.
grokys Sep 22, 2016
898b73f
Make "view on github" link work.
grokys Sep 22, 2016
25ead9e
Preparation for switchable changed files view.
grokys Sep 22, 2016
27807d4
Allow switching changes to list in PR details.
grokys Sep 22, 2016
0fac3a0
Make changes list look a bit nicer.
grokys Sep 23, 2016
2cd7f1c
Show options in dropdown menu in PR details.
grokys Sep 23, 2016
3e137fe
Implement toggling file open action in PR detail.
grokys Sep 23, 2016
04fa640
Added some documentation.
grokys Sep 23, 2016
6870a39
Tweaks for dark theme.
grokys Sep 23, 2016
d0d6f14
Adjust font size of PR title
donokuda Sep 26, 2016
028b60d
Update PR status text treatment
donokuda Sep 26, 2016
9908f33
Vertical align center pr status
donokuda Sep 26, 2016
9d13833
Thinner separators
donokuda Sep 26, 2016
00e99e5
Tweak PR title margins and alignment
donokuda Sep 27, 2016
73beacd
Nudge chevron arrow
donokuda Sep 27, 2016
7090ebd
Adjust margins and avatar size for author timestamp
donokuda Sep 27, 2016
0efa196
Omg I got the images to actually resize
donokuda Sep 27, 2016
c9aa5b4
This isn't needed
donokuda Sep 27, 2016
5cd711b
Merge pull request #564 from github/don/pr-header-polish
grokys Sep 28, 2016
4f85ef2
Merge pull request #565 from github/don/pr-description-polish
grokys Sep 28, 2016
a7ca7cd
Use RelativeSource in binding.
grokys Sep 28, 2016
89cde83
Implemented checking out PR branches.
grokys Sep 28, 2016
6b05fd3
Merge branch 'master' into grokys/maintainer-workflow
grokys Sep 28, 2016
0e2dc9d
Correctly convert config key to branch name.
grokys Sep 28, 2016
83cb4c9
Check how far behind PR current branch is.
grokys Sep 28, 2016
654027e
Fix typo.
grokys Sep 28, 2016
c541300
Added missing else.
grokys Sep 28, 2016
c0005a0
Update icon
donokuda Sep 28, 2016
55b731b
Fix a couple of CA errors.
grokys Sep 29, 2016
6e57be4
Avoid naming clashes in local PR branch names.
grokys Sep 29, 2016
ebdf9e9
Check for dirty repository state.
grokys Sep 29, 2016
1ae6a85
Detect local commits in PR branch.
grokys Sep 29, 2016
f864171
Display placeholder text if no PR body present.
grokys Sep 29, 2016
7f9b834
Implement updating local PR branch.
grokys Sep 29, 2016
c50cb5d
Use correct branch name in config.
grokys Sep 29, 2016
6934e3f
Trim trailing hypens from generated branch name.
grokys Sep 29, 2016
18535d5
Re-checkout PR branch when there are local changes.
grokys Sep 29, 2016
2167aff
Correctly handle PRs from local repo.
grokys Sep 29, 2016
c24604a
Fix expected test result.
grokys Sep 29, 2016
0e746fc
Added tests for PullRequestService.GetLocalBranches.
grokys Sep 29, 2016
683e795
Correctly check out branch from same repo.
grokys Sep 29, 2016
6d98cdd
Display a "local changes can be pushed" message.
grokys Sep 29, 2016
2c87346
Hide hyperlinks when disabled.
grokys Sep 30, 2016
4f2d950
Open changed file when double clicked.
grokys Sep 30, 2016
98a9696
Merge branch 'grokys/maintainer-workflow' of https://github.com/githu…
donokuda Sep 30, 2016
b0213fc
Remove alert icon from error message
donokuda Oct 3, 2016
1090baa
Add error message style
donokuda Oct 3, 2016
cf8e12d
Change folder icon to a folder
donokuda Oct 3, 2016
d9a0f03
Update directory icon color
donokuda Oct 3, 2016
c499948
Remove top margin from error message
donokuda Oct 3, 2016
78cf181
Merge pull request #574 from github/don/pr-details-polish
grokys Oct 4, 2016
f6c24db
Fix failing test.
Oct 4, 2016
e0fc71a
Couple of renames.
Oct 6, 2016
3baf00e
Do a FF-pull when updating PR from same repo.
Oct 6, 2016
84631f5
Replace ActivateItem with open/diff file ommands.
grokys Oct 14, 2016
ef300a4
Merge branch 'master' into grokys/maintainer-workflow
grokys Oct 14, 2016
f862a3d
Removed duplicate file.
grokys Oct 14, 2016
e5aecc9
Read pull request details view ModelService.
grokys Oct 18, 2016
c996266
Enable the cache for PRs in ModelService.
grokys Oct 18, 2016
a397f25
Expose the PR model from view model.
grokys Oct 18, 2016
c350de0
Tweaks to PR details view
grokys Oct 19, 2016
6587ddb
Renamed PR file/directory node classes.
grokys Oct 19, 2016
fa6f59c
Fix failing tests.
grokys Oct 19, 2016
73dd7e5
Merge branch 'master' into grokys/maintainer-workflow
grokys Oct 19, 2016
6fc5ff9
Account for DPI scaling when positioning menu.
grokys Oct 19, 2016
e22daa8
Raised missing notification of dependent value.
grokys Oct 21, 2016
d28c340
Use readonly collections where appropriate.
grokys Oct 21, 2016
47ee8e0
Make method static.
grokys Oct 21, 2016
4526845
PullRequest.Head can be null.
grokys Oct 21, 2016
b890f32
Make GitReferenceModel immutable.
grokys Oct 21, 2016
059a8db
Added an assert and handle something going wrong.
grokys Oct 21, 2016
4711503
Fix assertion error.
grokys Oct 24, 2016
5ad4d53
Merge branch 'master' into grokys/maintainer-workflow
haacked Oct 24, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/GitHub.App/Api/ApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,16 @@ public IObservable<Unit> DeleteApplicationAuthorization(int id, [AllowNull]strin
return gitHubClient.Authorization.Delete(id, twoFactorAuthorizationCode);
}

public IObservable<PullRequest> GetPullRequest(string owner, string name, int number)
{
return gitHubClient.PullRequest.Get(owner, name, number);
}

public IObservable<PullRequestFile> GetPullRequestFiles(string owner, string name, int number)
{
return gitHubClient.PullRequest.Files(owner, name, number);
}

public IObservable<PullRequest> GetPullRequestsForRepository(string owner, string name)
{
return gitHubClient.PullRequest.GetAllForRepository(owner, name,
Expand Down
4 changes: 4 additions & 0 deletions src/GitHub.App/GitHub.App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,15 @@
<Compile Include="Factories\UIFactory.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="Infrastructure\LoggingConfiguration.cs" />
<Compile Include="Models\PullRequestFileModel.cs" />
<Compile Include="Models\PullRequestModel.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="SampleData\AccountDesigner.cs" />
<Compile Include="SampleData\LocalRepositoryModelDesigner.cs" />
<Compile Include="SampleData\PullRequestCreationViewModelDesigner.cs" />
<Compile Include="SampleData\PullRequestDetailViewModelDesigner.cs" />
<Compile Include="SampleData\LoggedOutViewModelDesigner.cs" />
Expand Down Expand Up @@ -204,6 +206,8 @@
<Compile Include="ViewModels\LogoutRequiredViewModel.cs" />
<Compile Include="ViewModels\PullRequestCreationViewModel.cs" />
<Compile Include="ViewModels\PullRequestDetailViewModel.cs" />
<Compile Include="ViewModels\PullRequestDirectoryNode.cs" />
<Compile Include="ViewModels\PullRequestFileNode.cs" />
<Compile Include="ViewModels\PullRequestListViewModel.cs" />
<Compile Include="ViewModels\RepositoryCreationViewModel.cs" />
<Compile Include="ViewModels\RepositoryCloneViewModel.cs" />
Expand Down
7 changes: 7 additions & 0 deletions src/GitHub.App/Models/Account.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ public Account(Octokit.Account account)
HasMaximumPrivateRepositories = OwnedPrivateRepos >= PrivateReposInPlan;
}

public Account(Octokit.Account account, IObservable<BitmapSource> bitmapSource)
: this(account)
{
bitmapSource.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(x => Avatar = x);
}

public bool IsOnFreePlan { get; private set; }

public bool HasMaximumPrivateRepositories { get; private set; }
Expand Down
16 changes: 16 additions & 0 deletions src/GitHub.App/Models/PullRequestFileModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;

namespace GitHub.Models
{
public class PullRequestFileModel : IPullRequestFileModel
{
public PullRequestFileModel(string fileName, PullRequestFileStatus status)
{
FileName = fileName;
Status = status;
}

public string FileName { get; set; }
public PullRequestFileStatus Status { get; set; }
}
}
47 changes: 38 additions & 9 deletions src/GitHub.App/Models/PullRequestModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,22 @@
using GitHub.VisualStudio.Helpers;
using NullGuard;
using System.Diagnostics;
using GitHub.SampleData;
using System.Collections.Generic;

namespace GitHub.Models
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
[NullGuard(ValidationFlags.None)]
public sealed class PullRequestModel : NotificationAwareObject, IPullRequestModel,
IEquatable<PullRequestModel>,
IComparable<PullRequestModel>
{
public PullRequestModel(int number, string title,
IAccount author, [AllowNull]IAccount assignee,
public PullRequestModel(int number, string title, IAccount author,
DateTimeOffset createdAt, DateTimeOffset? updatedAt = null)
{
Number = number;
Title = title;
Author = author;
Assignee = assignee;
CreatedAt = createdAt;
UpdatedAt = updatedAt ?? CreatedAt;
}
Expand All @@ -30,10 +29,10 @@ public void CopyFrom(IPullRequestModel other)
if (!Equals(other))
throw new ArgumentException("Instance to copy from doesn't match this instance. this:(" + this + ") other:(" + other + ")", nameof(other));
Title = other.Title;
State = other.State;
UpdatedAt = other.UpdatedAt;
CommentCount = other.CommentCount;
HasNewComments = other.HasNewComments;
IsOpen = other.IsOpen;
Assignee = other.Assignee;
}

Expand Down Expand Up @@ -107,30 +106,60 @@ public string Title
set { title = value; this.RaisePropertyChange(); }
}

bool isOpen;
public bool IsOpen
PullRequestStateEnum status;
public PullRequestStateEnum State
{
get { return isOpen; }
set { isOpen = value; this.RaisePropertyChange(); }
get { return status; }
set
{
status = value;
this.RaisePropertyChange();

// TODO: These notifications will be removed once maintainer workflow has been merged to master.
this.RaisePropertyChange(nameof(IsOpen));
this.RaisePropertyChange(nameof(Merged));
}
}

// TODO: Remove these property once maintainer workflow has been merged to master.
public bool IsOpen => State == PullRequestStateEnum.Open;
public bool Merged => State == PullRequestStateEnum.Merged;

int commentCount;
public int CommentCount
{
get { return commentCount; }
set { commentCount = value; this.RaisePropertyChange(); }
}

int commitCount;
public int CommitCount
{
get { return commitCount; }
set { commitCount = value; this.RaisePropertyChange(); }
}

bool hasNewComments;
public bool HasNewComments
{
get { return hasNewComments; }
set { hasNewComments = value; this.RaisePropertyChange(); }
}

string body;
public string Body
{
get { return body; }
set { body = value; this.RaisePropertyChange(); }
}

public GitReferenceModel Base { get; set; }
[AllowNull]
public GitReferenceModel Head { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public DateTimeOffset UpdatedAt { get; set; }
public IAccount Author { get; set; }
public IReadOnlyCollection<IPullRequestFileModel> ChangedFiles { get; set; } = new IPullRequestFileModel[0];

IAccount assignee;
[AllowNull]
Expand Down
40 changes: 40 additions & 0 deletions src/GitHub.App/SampleData/LocalRepositoryModelDesigner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using GitHub.Models;
using GitHub.Primitives;
using GitHub.UI;
using NullGuard;

namespace GitHub.App.SampleData
{
[NullGuard(ValidationFlags.None)]
public class LocalRepositoryModelDesigner : ILocalRepositoryModel
{
public UriString CloneUrl { get; set; }
public IBranch CurrentBranch { get; set; }
public Octicon Icon { get; set; }
public string LocalPath { get; set; }
public string Name { get; set; }
public string Owner { get; set; }

#pragma warning disable CS0067
public event PropertyChangedEventHandler PropertyChanged;
#pragma warning restore CS0067

public Task<UriString> GenerateUrl(string path = null, int startLine = -1, int endLine = -1)
{
throw new NotImplementedException();
}

public void Refresh()
{
throw new NotImplementedException();
}

public void SetIcon(bool isPrivate, bool isFork)
{
throw new NotImplementedException();
}
}
}
65 changes: 65 additions & 0 deletions src/GitHub.App/SampleData/PullRequestDetailViewModelDesigner.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reactive;
using GitHub.Models;
using GitHub.ViewModels;
using ReactiveUI;

namespace GitHub.SampleData
{
Expand All @@ -8,7 +12,68 @@ public class PullRequestDetailViewModelDesigner : BaseViewModel, IPullRequestDet
{
public PullRequestDetailViewModelDesigner()
{
Model = new PullRequestModel(419,
"Error handling/bubbling from viewmodels to views to viewhosts",
new AccountDesigner { Login = "shana", IsUser = true },
DateTime.Now.Subtract(TimeSpan.FromDays(3)))
{
State = PullRequestStateEnum.Open,
CommitCount = 9,
};

SourceBranchDisplayName = "shana/error-handling";
TargetBranchDisplayName = "master";
Body = @"Adds a way to surface errors from the view model to the view so that view hosts can get to them.

ViewModels are responsible for handling the UI on the view they control, but they shouldn't be handling UI for things outside of the view. In this case, we're showing errors in VS outside the view, and that should be handled by the section that is hosting the view.

This requires that errors be propagated from the viewmodel to the view and from there to the host via the IView interface, since hosts don't usually know what they're hosting.

![An image](https://cloud.githubusercontent.com/assets/1174461/18882991/5dd35648-8496-11e6-8735-82c3a182e8b4.png)";

var gitHubDir = new PullRequestDirectoryNode("GitHub");
var modelsDir = new PullRequestDirectoryNode("Models");
var repositoriesDir = new PullRequestDirectoryNode("Repositories");
var itrackingBranch = new PullRequestFileNode(@"GitHub\Models\ITrackingBranch.cs", PullRequestFileStatus.Modified);
var oldBranchModel = new PullRequestFileNode(@"GitHub\Models\OldBranchModel.cs", PullRequestFileStatus.Removed);
var concurrentRepositoryConnection = new PullRequestFileNode(@"GitHub\Repositories\ConcurrentRepositoryConnection.cs", PullRequestFileStatus.Added);

repositoriesDir.Files.Add(concurrentRepositoryConnection);
modelsDir.Directories.Add(repositoriesDir);
modelsDir.Files.Add(itrackingBranch);
modelsDir.Files.Add(oldBranchModel);
gitHubDir.Directories.Add(modelsDir);

ChangedFilesTree = new ReactiveList<IPullRequestChangeNode>();
ChangedFilesTree.Add(gitHubDir);

ChangedFilesList = new ReactiveList<IPullRequestFileNode>();
ChangedFilesList.Add(concurrentRepositoryConnection);
ChangedFilesList.Add(itrackingBranch);
ChangedFilesList.Add(oldBranchModel);

CheckoutMode = CheckoutMode.Fetch;
}

public IPullRequestModel Model { get; }
public string SourceBranchDisplayName { get; }
public string TargetBranchDisplayName { get; }
public string Body { get; }
public ChangedFilesViewType ChangedFilesViewType { get; set; }
public OpenChangedFileAction OpenChangedFileAction { get; set; }
public IReactiveList<IPullRequestChangeNode> ChangedFilesTree { get; }
public IReactiveList<IPullRequestFileNode> ChangedFilesList { get; }
public CheckoutMode CheckoutMode { get; set; }
public string CheckoutError { get; set; }
public int CommitsBehind { get; set; }
public string CheckoutDisabledMessage { get; set; }

public ReactiveCommand<Unit> Checkout { get; }
public ReactiveCommand<object> OpenOnGitHub { get; }
public ReactiveCommand<object> ActivateItem { get; }
public ReactiveCommand<object> ToggleChangedFilesView { get; }
public ReactiveCommand<object> ToggleOpenChangedFileAction { get; }
public ReactiveCommand<object> OpenFile { get; }
public ReactiveCommand<object> DiffFile { get; }
}
}
24 changes: 17 additions & 7 deletions src/GitHub.App/SampleData/PullRequestListViewModelDesigner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,26 @@ public PullRequestListViewModelDesigner()
var prs = new TrackingCollection<IPullRequestModel>(Observable.Empty<IPullRequestModel>());
prs.Add(new PullRequestModel(399, "Let's try doing this differently",
new AccountDesigner { Login = "shana", IsUser = true },
new AccountDesigner { Login = "shana", IsUser = true },
DateTimeOffset.Now - TimeSpan.FromDays(1)));
DateTimeOffset.Now - TimeSpan.FromDays(1))
{
Assignee = new AccountDesigner { Login = "shana", IsUser = true },
});
prs.Add(new PullRequestModel(389, "Build system upgrade",
new AccountDesigner { Login = "haacked", IsUser = true },
new AccountDesigner { Login = "shana", IsUser = true },
DateTimeOffset.Now - TimeSpan.FromMinutes(2)) { CommentCount = 4, HasNewComments = false });
DateTimeOffset.Now - TimeSpan.FromMinutes(2))
{
CommentCount = 4,
HasNewComments = false,
Assignee = new AccountDesigner { Login = "haacked", IsUser = true },
});
prs.Add(new PullRequestModel(409, "Fix publish button style and a really, really long name for this thing... OMG look how long this name is yusssss",
new AccountDesigner { Login = "shana", IsUser = true },
new AccountDesigner { Login = "Haacked", IsUser = true },
DateTimeOffset.Now - TimeSpan.FromHours(5)) { CommentCount = 27, HasNewComments = true });
new AccountDesigner { Login = "shana", IsUser = true },
DateTimeOffset.Now - TimeSpan.FromHours(5))
{
CommentCount = 27,
HasNewComments = true,
Assignee = new AccountDesigner { Login = "Haacked", IsUser = true },
});
PullRequests = prs;

States = new List<PullRequestState> {
Expand Down
34 changes: 32 additions & 2 deletions src/GitHub.App/Services/GitClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Reactive;
Expand Down Expand Up @@ -61,13 +62,33 @@ public Task Fetch(IRepository repository, string remoteName, params string[] ref
});
}

public Task Checkout(IRepository repository, string branchName)
{
Guard.ArgumentNotEmptyString(branchName, nameof(branchName));

return Task.Factory.StartNew(() =>
{
repository.Checkout(branchName);
});
}

public Task SetConfig(IRepository repository, string key, string value)
{
Guard.ArgumentNotEmptyString(key, nameof(key));
Guard.ArgumentNotEmptyString(value, nameof(value));

return Task.Factory.StartNew(() =>
{
repository.Config.Set(key, value);
});
}

public Task SetRemote(IRepository repository, string remoteName, Uri url)
{
Guard.ArgumentNotEmptyString(remoteName, nameof(remoteName));

return Task.Factory.StartNew(() =>
{

repository.Config.Set("remote." + remoteName + ".url", url.ToString());
repository.Config.Set("remote." + remoteName + ".fetch", "+refs/heads/*:refs/remotes/" + remoteName + "/*");
});
Expand All @@ -92,11 +113,20 @@ public Task SetTrackingBranch(IRepository repository, string branchName, string
});
}

public Task<Remote> GetHttpRemote(IRepository repo, string remote)
public Task UnsetConfig(IRepository repository, string key)
{
Guard.ArgumentNotEmptyString(key, nameof(key));

return Task.Factory.StartNew(() =>
{
repository.Config.Unset(key);
});
}

public Task<Remote> GetHttpRemote(IRepository repo, string remote)
{
return Task.Factory.StartNew(() =>
{
var uri = GitService.GitServiceHelper.GetRemoteUri(repo, remote);
var remoteName = uri.IsHypertextTransferProtocol ? remote : remote + "-http";
var ret = repo.Network.Remotes[remoteName];
Expand Down
Loading