Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit cfb1dd3

Browse files
committed
Initial implementation of PR conversation view.
1 parent 50b04ac commit cfb1dd3

34 files changed

+793
-100
lines changed

src/GitHub.App/Models/PullRequestModel.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ public string Title
110110
}
111111
}
112112

113-
PullRequestStateEnum status;
114-
public PullRequestStateEnum State
113+
PullRequestState status;
114+
public PullRequestState State
115115
{
116116
get { return status; }
117117
set
@@ -126,8 +126,8 @@ public PullRequestStateEnum State
126126
}
127127

128128
// TODO: Remove these property once maintainer workflow has been merged to master.
129-
public bool IsOpen => State == PullRequestStateEnum.Open;
130-
public bool Merged => State == PullRequestStateEnum.Merged;
129+
public bool IsOpen => State == PullRequestState.Open;
130+
public bool Merged => State == PullRequestState.Merged;
131131

132132
int commentCount;
133133
public int CommentCount

src/GitHub.App/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
[assembly: XmlnsDefinition("https://github.com/github/VisualStudio", "GitHub.SampleData")]
44
[assembly: XmlnsDefinition("https://github.com/github/VisualStudio", "GitHub.SampleData.Dialog.Clone")]
5+
[assembly: XmlnsDefinition("https://github.com/github/VisualStudio", "GitHub.SampleData.Documents")]
56
[assembly: XmlnsDefinition("https://github.com/github/VisualStudio", "GitHub.ViewModels")]
67
[assembly: XmlnsDefinition("https://github.com/github/VisualStudio", "GitHub.ViewModels.Dialog")]
78
[assembly: XmlnsDefinition("https://github.com/github/VisualStudio", "GitHub.ViewModels.Dialog.Clone")]

src/GitHub.App/SampleData/CommentViewModelDesigner.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Diagnostics.CodeAnalysis;
33
using System.Reactive;
4+
using System.Threading.Tasks;
5+
using GitHub.Models;
46
using GitHub.ViewModels;
57
using ReactiveUI;
68

@@ -33,5 +35,10 @@ public CommentViewModelDesigner()
3335
public ReactiveCommand<Unit, Unit> CommitEdit { get; }
3436
public ReactiveCommand<Unit, Unit> OpenOnGitHub { get; }
3537
public ReactiveCommand<Unit, Unit> Delete { get; }
38+
39+
public Task InitializeAsync(ICommentThreadViewModel thread, ActorModel currentUser, CommentModel comment, CommentEditState state)
40+
{
41+
return Task.CompletedTask;
42+
}
3643
}
3744
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using GitHub.Models;
4+
using GitHub.ViewModels;
5+
using GitHub.ViewModels.Documents;
6+
using ReactiveUI;
7+
8+
namespace GitHub.SampleData.Documents
9+
{
10+
public class IssueishCommentThreadViewModelDesigner : ViewModelBase, IIssueishCommentThreadViewModel
11+
{
12+
public IReadOnlyReactiveList<ICommentViewModel> Comments { get; set; }
13+
public IActorViewModel CurrentUser { get; } = new ActorViewModelDesigner("grokys");
14+
public Task DeleteComment(int pullRequestId, int commentId) => Task.CompletedTask;
15+
public Task EditComment(string id, string body) => Task.CompletedTask;
16+
public Task InitializeAsync(ActorModel currentUser, IssueishDetailModel model, bool addPlaceholder) => Task.CompletedTask;
17+
public Task PostComment(string body) => Task.CompletedTask;
18+
}
19+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using System;
2+
using System.Reactive;
3+
using System.Threading.Tasks;
4+
using GitHub.Models;
5+
using GitHub.ViewModels;
6+
using GitHub.ViewModels.Documents;
7+
using ReactiveUI;
8+
9+
namespace GitHub.SampleData.Documents
10+
{
11+
public class PullRequestPageViewModelDesigner : ViewModelBase, IPullRequestPageViewModel
12+
{
13+
public PullRequestPageViewModelDesigner()
14+
{
15+
Body = @"Save drafts of inline comments, PR reviews and PRs.
16+
17+
> Note: This feature required a refactoring of the comment view models because they now need async initialization and to be available from GitHub.App. This part of the PR has been submitted separately as #1993 to ease review. The two PRs can alternatively be reviewed as one if that's more convenient.
18+
19+
As described in #1905, it is easy to lose a comment that you're working on if you close the diff view accidentally. This PR saves drafts of comments as they are being written to an SQLite database.
20+
21+
In addition to saving drafts of inline comments, it also saves comments to PR reviews and PRs themselves.
22+
23+
The comments are written to an SQLite database directly instead of going through Akavache because in the case of inline reviews, there can be many drafts in progress on a separate file. When a diff is opened we need to look for any comments present on that file and show the most recent. That use-case didn't fit well with Akavache (being a pure key/value store).
24+
25+
## Testing
26+
27+
### Inline Comments
28+
29+
- Open a PR
30+
- Open the diff of a file
31+
- Start adding a comment
32+
- Close the comment by closing the peek view, or the document tab
33+
- Reopen the diff
34+
- You should see the comment displayed in edit mode with the draft of the comment you were previously writing
35+
36+
### PR reviews
37+
38+
- Open a PR
39+
- Click ""Add your review""
40+
- Start adding a review
41+
- Click the ""Back"" button and navigate to a different PR
42+
- Click the ""Back"" button and navigate to the original PR
43+
- Click ""Add your review""
44+
- You should see the the draft of the review you were previously writing
45+
46+
### PRs
47+
48+
-Click ""Create new"" at the top of the PR list
49+
- Start adding a PR title/ description
50+
- Close VS
51+
- Restart VS and click ""Create new"" again
52+
- You should see the the draft of the PR you were previously writing
53+
54+
Depends on #1993
55+
Fixes #1905";
56+
}
57+
58+
public PullRequestState State { get; set; } = PullRequestState.Open;
59+
public IIssueishCommentThreadViewModel Thread { get; set; }
60+
public string SourceBranchDisplayName { get; set; } = "feature/save-drafts";
61+
public string TargetBranchDisplayName { get; set; } = "master";
62+
public IActorViewModel Author { get; set; } = new ActorViewModelDesigner("grokys");
63+
public string Body { get; set; }
64+
public int Number { get; set; } = 1994;
65+
public IRepositoryModel Repository { get; set; }
66+
public string Title { get; set; } = "Save drafts of comments";
67+
public Uri WebUrl { get; set; }
68+
public ReactiveCommand<Unit, Unit> OpenOnGitHub { get; }
69+
70+
public Task InitializeAsync(ActorModel currentUser, PullRequestDetailModel model) => Task.CompletedTask;
71+
}
72+
}

src/GitHub.App/Services/FromGraphQlExtensions.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@ public static class FromGraphQlExtensions
3333
}
3434
}
3535

36-
public static PullRequestStateEnum FromGraphQl(this PullRequestState value)
36+
public static Models.PullRequestState FromGraphQl(this Octokit.GraphQL.Model.PullRequestState value)
3737
{
3838
switch (value)
3939
{
40-
case PullRequestState.Open:
41-
return PullRequestStateEnum.Open;
42-
case PullRequestState.Closed:
43-
return PullRequestStateEnum.Closed;
44-
case PullRequestState.Merged:
45-
return PullRequestStateEnum.Merged;
40+
case Octokit.GraphQL.Model.PullRequestState.Open:
41+
return Models.PullRequestState.Open;
42+
case Octokit.GraphQL.Model.PullRequestState.Closed:
43+
return Models.PullRequestState.Closed;
44+
case Octokit.GraphQL.Model.PullRequestState.Merged:
45+
return Models.PullRequestState.Merged;
4646
default:
4747
throw new ArgumentOutOfRangeException(nameof(value), value, null);
4848
}

src/GitHub.App/Services/ModelService.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ IPullRequestModel Create(PullRequestCacheItem prCacheItem)
442442
Head = Create(prCacheItem.Head),
443443
State = prCacheItem.State.HasValue ?
444444
prCacheItem.State.Value :
445-
prCacheItem.IsOpen.Value ? PullRequestStateEnum.Open : PullRequestStateEnum.Closed,
445+
prCacheItem.IsOpen.Value ? PullRequestState.Open : PullRequestState.Closed,
446446
};
447447
}
448448

@@ -576,25 +576,25 @@ public PullRequestCacheItem(PullRequest pr)
576576
public string Body { get; set; }
577577

578578
// Nullable for compatibility with old caches.
579-
public PullRequestStateEnum? State { get; set; }
579+
public PullRequestState? State { get; set; }
580580

581581
// This fields exists only for compatibility with old caches. The State property should be used.
582582
public bool? IsOpen { get; set; }
583583
public bool? Merged { get; set; }
584584

585-
static PullRequestStateEnum GetState(PullRequest pullRequest)
585+
static PullRequestState GetState(PullRequest pullRequest)
586586
{
587587
if (pullRequest.State == ItemState.Open)
588588
{
589-
return PullRequestStateEnum.Open;
589+
return PullRequestState.Open;
590590
}
591591
else if (pullRequest.Merged)
592592
{
593-
return PullRequestStateEnum.Merged;
593+
return PullRequestState.Merged;
594594
}
595595
else
596596
{
597-
return PullRequestStateEnum.Closed;
597+
return PullRequestState.Closed;
598598
}
599599
}
600600
}

src/GitHub.App/Services/PullRequestService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public async Task<Page<PullRequestListItemModel>> ReadPullRequests(
8080
string owner,
8181
string name,
8282
string after,
83-
PullRequestStateEnum[] states)
83+
Models.PullRequestState[] states)
8484
{
8585

8686
ICompiledQuery<Page<PullRequestListItemModel>> query;
@@ -204,7 +204,7 @@ public async Task<Page<PullRequestListItemModel>> ReadPullRequests(
204204
{ nameof(owner), owner },
205205
{ nameof(name), name },
206206
{ nameof(after), after },
207-
{ nameof(states), states.Select(x => (PullRequestState)x).ToList() },
207+
{ nameof(states), states.Select(x => (Octokit.GraphQL.Model.PullRequestState)x).ToList() },
208208
};
209209

210210
var result = await graphql.Run(query, vars);

src/GitHub.App/ViewModels/CommentViewModel.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.ComponentModel.Composition;
23
using System.Linq;
34
using System.Reactive;
45
using System.Reactive.Linq;
@@ -13,9 +14,11 @@
1314
namespace GitHub.ViewModels
1415
{
1516
/// <summary>
16-
/// Base view model for an issue or pull request comment.
17+
/// An issue or pull request comment.
1718
/// </summary>
18-
public abstract class CommentViewModel : ReactiveObject, ICommentViewModel
19+
[Export(typeof(ICommentViewModel))]
20+
[PartCreationPolicy(CreationPolicy.NonShared)]
21+
public class CommentViewModel : ReactiveObject, ICommentViewModel
1922
{
2023
static readonly ILogger log = LogManager.ForContext<CommentViewModel>();
2124
readonly ICommentService commentService;
@@ -36,6 +39,7 @@ public abstract class CommentViewModel : ReactiveObject, ICommentViewModel
3639
/// Initializes a new instance of the <see cref="CommentViewModel"/> class.
3740
/// </summary>
3841
/// <param name="commentService">The comment service.</param>
42+
[ImportingConstructor]
3943
public CommentViewModel(ICommentService commentService)
4044
{
4145
Guard.ArgumentNotNull(commentService, nameof(commentService));
@@ -175,14 +179,8 @@ public ICommentThreadViewModel Thread
175179
/// <inheritdoc/>
176180
public ReactiveCommand<Unit, Unit> Delete { get; }
177181

178-
/// <summary>
179-
/// Initializes the view model with data.
180-
/// </summary>
181-
/// <param name="thread">The thread that the comment is a part of.</param>
182-
/// <param name="currentUser">The current user.</param>
183-
/// <param name="comment">The comment model. May be null.</param>
184-
/// <param name="state">The comment edit state.</param>
185-
protected Task InitializeAsync(
182+
/// <inheritdoc/>
183+
public Task InitializeAsync(
186184
ICommentThreadViewModel thread,
187185
ActorModel currentUser,
188186
CommentModel comment,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using GitHub.Models;
3+
using GitHub.ViewModels;
4+
5+
namespace GitHub.App.ViewModels.Documents
6+
{
7+
public class CommitSummaryViewModel : ViewModelBase
8+
{
9+
public CommitSummaryViewModel(CommitModel model)
10+
{
11+
AbbreviatedOid = model.AbbreviatedOid;
12+
Header = model.MessageHeadline;
13+
}
14+
15+
public string AbbreviatedOid { get; }
16+
public string Header { get; }
17+
}
18+
}

0 commit comments

Comments
 (0)