Skip to content

Commit

Permalink
New pull request (#185)
Browse files Browse the repository at this point in the history
* Made GitHub New Pull Request a category.

This allows the user to select the compare branch from the app.

* Localization.
  • Loading branch information
pvginkel authored Dec 19, 2023
1 parent c6846fa commit c4e5190
Show file tree
Hide file tree
Showing 16 changed files with 190 additions and 21 deletions.
3 changes: 1 addition & 2 deletions src/Tql.Plugins.GitHub/Categories/IssueMatch.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Octokit;
using Tql.Abstractions;
using Tql.Abstractions;

namespace Tql.Plugins.GitHub.Categories;

Expand Down
1 change: 0 additions & 1 deletion src/Tql.Plugins.GitHub/Categories/IssueMatchBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Windows.Forms;
using Microsoft.Extensions.DependencyInjection;
using Octokit;
using Tql.Abstractions;
using Tql.Utilities;

Expand Down
1 change: 0 additions & 1 deletion src/Tql.Plugins.GitHub/Categories/IssueType.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Tql.Abstractions;
using Tql.Plugins.GitHub.Services;
using Tql.Utilities;

namespace Tql.Plugins.GitHub.Categories;

Expand Down
20 changes: 11 additions & 9 deletions src/Tql.Plugins.GitHub/Categories/NewMatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ namespace Tql.Plugins.GitHub.Categories;
internal class NewMatch(NewMatchDto dto) : IRunnableMatch, ISerializableMatch, ICopyableMatch
{
public string Text =>
dto.Type switch
Dto.Type switch
{
NewMatchType.Issue
=> MatchText.Path($"{dto.Owner}/{dto.Repository}", Labels.NewMatch_NewIssue),
=> MatchText.Path($"{Dto.Owner}/{Dto.Repository}", Labels.NewMatch_NewIssue),
NewMatchType.PullRequest
=> MatchText.Path($"{dto.Owner}/{dto.Repository}", Labels.NewMatch_NewPullRequest),
=> MatchText.Path($"{Dto.Owner}/{Dto.Repository}", Labels.NewMatch_NewPullRequest),
NewMatchType.Repository => Labels.NewMatch_NewRepository,
NewMatchType.Gist => Labels.NewMatch_NewGist,
NewMatchType.Organization => Labels.NewMatch_NewOrganization,
Expand All @@ -23,7 +23,7 @@ internal class NewMatch(NewMatchDto dto) : IRunnableMatch, ISerializableMatch, I
};

public ImageSource Icon =>
dto.Type switch
Dto.Type switch
{
NewMatchType.Issue => Images.Issue,
NewMatchType.PullRequest => Images.PullRequest,
Expand All @@ -35,7 +35,9 @@ internal class NewMatch(NewMatchDto dto) : IRunnableMatch, ISerializableMatch, I
_ => throw new ArgumentOutOfRangeException()
};

public MatchTypeId TypeId => TypeIds.New;
public virtual MatchTypeId TypeId => TypeIds.New;

protected NewMatchDto Dto { get; } = dto;

public Task Run(IServiceProvider serviceProvider, IWin32Window owner)
{
Expand All @@ -46,7 +48,7 @@ public Task Run(IServiceProvider serviceProvider, IWin32Window owner)

public string Serialize()
{
return JsonSerializer.Serialize(dto);
return JsonSerializer.Serialize(Dto);
}

public Task Copy(IServiceProvider serviceProvider)
Expand All @@ -57,11 +59,11 @@ public Task Copy(IServiceProvider serviceProvider)
}

private string GetUrl() =>
dto.Type switch
Dto.Type switch
{
NewMatchType.Issue
=> $"https://github.com/{dto.Owner}/{dto.Repository}/issues/new/choose",
NewMatchType.PullRequest => $"https://github.com/{dto.Owner}/{dto.Repository}/compare",
=> $"https://github.com/{Dto.Owner}/{Dto.Repository}/issues/new/choose",
NewMatchType.PullRequest => $"https://github.com/{Dto.Owner}/{Dto.Repository}/compare",
NewMatchType.Repository => "https://github.com/new",
NewMatchType.Gist => "https://gist.github.com/",
NewMatchType.Organization => "https://github.com/account/organizations/new",
Expand Down
38 changes: 38 additions & 0 deletions src/Tql.Plugins.GitHub/Categories/NewPullRequestMatch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Windows.Forms;
using Microsoft.Extensions.DependencyInjection;
using Tql.Abstractions;
using Tql.Utilities;

namespace Tql.Plugins.GitHub.Categories;

// This class is not serializable because instances of this class
// are transient by definition. The moment the user creates the pull
// request, the instance in the history becomes invalid. Because of
// this, there also isn't a MatchType class for this match. We do
// still need the TypeId though!
internal class NewPullRequestMatch(NewPullRequestDto dto) : IRunnableMatch, ICopyableMatch
{
public string Text => dto.CompareBranch;
public ImageSource Icon => Images.PullRequest;
public MatchTypeId TypeId => TypeIds.NewPullRequest;

public Task Run(IServiceProvider serviceProvider, IWin32Window owner)
{
serviceProvider.GetRequiredService<IUI>().OpenUrl(dto.GetUrl());

return Task.CompletedTask;
}

public Task Copy(IServiceProvider serviceProvider)
{
serviceProvider.GetRequiredService<IClipboard>().CopyUri(Text, dto.GetUrl());

return Task.CompletedTask;
}
}

internal record NewPullRequestDto(Guid Id, string Owner, string Repository, string CompareBranch)
{
public string GetUrl() =>
$"https://github.com/{Uri.EscapeDataString(Owner)}/{Uri.EscapeDataString(Repository)}/compare/{Uri.EscapeDataString(CompareBranch)}?expand=1";
}
94 changes: 94 additions & 0 deletions src/Tql.Plugins.GitHub/Categories/NewPullRequestsMatch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using Octokit.GraphQL;
using Octokit.GraphQL.Model;
using Tql.Abstractions;
using Tql.Plugins.GitHub.Services;
using Tql.Utilities;

namespace Tql.Plugins.GitHub.Categories;

internal class NewPullRequestsMatch(
NewMatchDto dto,
GitHubApi api,
IMatchFactory<NewPullRequestMatch, NewPullRequestDto> factory
) : NewMatch(dto), ISearchableMatch
{
public override MatchTypeId TypeId => TypeIds.NewPullRequests;
public string SearchHint => Labels.NewPullRequestsMatch_SearchHint;

public async Task<IEnumerable<IMatch>> Search(
ISearchContext context,
string text,
CancellationToken cancellationToken
)
{
var task = context.GetDataCached($"{GetType()}|{Dto.Id}", _ => GetMatches());

if (!task.IsCompleted)
await context.DebounceDelay(cancellationToken);

return context.Filter(await task);
}

private async Task<ImmutableArray<NewPullRequestMatch>> GetMatches()
{
var graphQlConnection = await api.GetConnection(Dto.Id!.Value);

var query = new Query()
.Repository(Dto.Repository, Dto.Owner)
.Refs("refs/heads/", first: 100)
.Edges.Select(
refEdge =>
new
{
Refs = refEdge
.Node.Select(
@ref =>
new
{
@ref.Name,
AssociatedPullRequests = @ref.AssociatedPullRequests(
1,
null,
null,
null,
null,
null,
null,
null,
new[] { PullRequestState.Open }
)
.Edges.Select(
pullRequest =>
new
{
Id = pullRequest
.Select(p4 => p4.Node.Id)
.SingleOrDefault()
}
)
.ToList()
}
)
.SingleOrDefault()
}
)
.Compile();

var items = await graphQlConnection.Run(query);

return items
.Where(p => p.Refs.AssociatedPullRequests.Count == 0)
.Select(
p =>
factory.Create(
new NewPullRequestDto(
Dto.Id!.Value,
Dto.Owner!,
Dto.Repository!,
p.Refs.Name
)
)
)
.ToImmutableArray();
}
}
16 changes: 16 additions & 0 deletions src/Tql.Plugins.GitHub/Categories/NewPullRequestsType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Tql.Abstractions;
using Tql.Plugins.GitHub.Services;
using Tql.Utilities;

namespace Tql.Plugins.GitHub.Categories;

internal class NewPullRequestsType(
IMatchFactory<NewPullRequestsMatch, NewMatchDto> factory,
ConfigurationManager configurationManager
) : MatchType<NewPullRequestsMatch, NewMatchDto>(factory)
{
public override Guid Id => TypeIds.NewPullRequests.Id;

protected override bool IsValid(NewMatchDto dto) =>
!dto.Id.HasValue || configurationManager.Configuration.HasConnection(dto.Id.Value);
}
5 changes: 3 additions & 2 deletions src/Tql.Plugins.GitHub/Categories/NewsMatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ internal class NewsMatch(
RootItemDto dto,
ICache<GitHubData> cache,
ConfigurationManager configurationManager,
IMatchFactory<NewMatch, NewMatchDto> factory
IMatchFactory<NewMatch, NewMatchDto> factory,
IMatchFactory<NewPullRequestsMatch, NewMatchDto> newPullRequestsFactory
) : CachedMatch<GitHubData>(cache), ISerializableMatch
{
public override string Text =>
Expand All @@ -35,7 +36,7 @@ protected override IEnumerable<IMatch> Create(GitHubData data)
yield return factory.Create(
new NewMatchDto(dto.Id, repository.Owner, repository.Name, NewMatchType.Issue)
);
yield return factory.Create(
yield return newPullRequestsFactory.Create(
new NewMatchDto(dto.Id, repository.Owner, repository.Name, NewMatchType.PullRequest)
);
}
Expand Down
3 changes: 1 addition & 2 deletions src/Tql.Plugins.GitHub/Categories/PullRequestMatch.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Octokit;
using Tql.Abstractions;
using Tql.Abstractions;

namespace Tql.Plugins.GitHub.Categories;

Expand Down
1 change: 0 additions & 1 deletion src/Tql.Plugins.GitHub/Categories/PullRequestType.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Tql.Abstractions;
using Tql.Plugins.GitHub.Services;
using Tql.Utilities;

namespace Tql.Plugins.GitHub.Categories;

Expand Down
3 changes: 2 additions & 1 deletion src/Tql.Plugins.GitHub/Categories/RepositoryMatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,6 @@ string Url

internal record RepositoryItemMatchDto(Guid ConnectionId, string Owner, string RepositoryName)
{
public string GetUrl() => $"https://github.com/{Owner}/{RepositoryName}";
public string GetUrl() =>
$"https://github.com/{Uri.EscapeDataString(Owner)}/{Uri.EscapeDataString(RepositoryName)}";
}
7 changes: 7 additions & 0 deletions src/Tql.Plugins.GitHub/Categories/TypeIds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ internal static class TypeIds
public static readonly MatchTypeId News = CreateId("d5561f08-6bbf-4133-8ab4-d55cd1c97d57");
public static readonly MatchTypeId New = CreateId("0141215a-4947-4d12-9e45-ba929314178d");

public static readonly MatchTypeId NewPullRequests = CreateId(
"c2d7c46f-d37c-4b34-85f3-509584998e90"
);
public static readonly MatchTypeId NewPullRequest = CreateId(
"919c0586-f40d-45c6-8789-5237fd36ee83"
);

public static readonly MatchTypeId Projects = CreateId("0c3b2a6c-123b-49c9-a3dd-cee663deda7c");
public static readonly MatchTypeId Project = CreateId("b3e3f65c-b264-438b-a6d7-49b460acb1af");
public static readonly MatchTypeId ProjectItem = CreateId(
Expand Down
9 changes: 9 additions & 0 deletions src/Tql.Plugins.GitHub/Labels.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/Tql.Plugins.GitHub/Labels.nl.resx
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,8 @@
<value>Authenticatie is afgerond. Je kunt nu terug naar de app.</value>
<comment>Original: Authentication completed. You can now go back to the app.</comment>
</data>
<data name="NewPullRequestsMatch_SearchHint" xml:space="preserve">
<value>Vind compare branch</value>
<comment>Original: Find compare branch</comment>
</data>
</root>
3 changes: 3 additions & 0 deletions src/Tql.Plugins.GitHub/Labels.resx
Original file line number Diff line number Diff line change
Expand Up @@ -255,4 +255,7 @@
<data name="GitHubOAuthWorkflow_AuthenticationComplete" xml:space="preserve">
<value>Authentication completed. You can now go back to the app.</value>
</data>
<data name="NewPullRequestsMatch_SearchHint" xml:space="preserve">
<value>Find compare branch</value>
</data>
</root>
3 changes: 1 addition & 2 deletions src/Tql.Utilities/MatchType.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using Tql.Abstractions;
using Tql.Abstractions;

namespace Tql.Utilities;

Expand Down

0 comments on commit c4e5190

Please sign in to comment.