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

Commit 804f3b3

Browse files
authored
Merge pull request #1512 from github/fixes/1511-Git-UIContext
Use custom UIContext to load GitHubPackage / PullRequestStatusBarPackage in context of active repo
2 parents 6fe4bf1 + 2e45e33 commit 804f3b3

File tree

6 files changed

+64
-38
lines changed

6 files changed

+64
-38
lines changed

src/GitHub.Exports/Settings/Guids.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ public static class Guids
2121
public const string GitSccProviderId = "11B8E6D7-C08B-4385-B321-321078CDD1F8";
2222
public const string TeamExplorerInstall3rdPartyGitTools = "DF785C7C-8454-4836-9686-D1C4A01D0BB9";
2323

24+
// UIContexts
25+
public const string UIContext_Git = "565515AD-F4C1-4D59-BC14-AE77396DDDD7";
26+
2427
// Guids defined in GitHub.VisualStudio.vsct
2528
public const string guidGitHubPkgString = "c3d3dc68-c977-411f-b3e8-03b0dccf7dfc";
2629
public const string guidAssemblyResolverPkgString = "a6424dba-34cb-360d-a4de-1b0b0411e57d";

src/GitHub.InlineReviews/PullRequestStatusBarPackage.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Threading;
33
using System.Runtime.InteropServices;
4+
using GitHub.Helpers;
45
using GitHub.Services;
56
using GitHub.VisualStudio;
67
using GitHub.InlineReviews.Services;
@@ -11,7 +12,7 @@ namespace GitHub.InlineReviews
1112
{
1213
[Guid(Guids.PullRequestStatusPackageId)]
1314
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
14-
[ProvideAutoLoad(Guids.GitSccProviderId, PackageAutoLoadFlags.BackgroundLoad)]
15+
[ProvideAutoLoad(Guids.UIContext_Git, PackageAutoLoadFlags.BackgroundLoad)]
1516
public class PullRequestStatusBarPackage : AsyncPackage
1617
{
1718
/// <summary>
@@ -21,9 +22,11 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
2122
{
2223
var usageTracker = (IUsageTracker)await GetServiceAsync(typeof(IUsageTracker));
2324
var serviceProvider = (IGitHubServiceProvider)await GetServiceAsync(typeof(IGitHubServiceProvider));
24-
var gitExt = (IVSGitExt)await GetServiceAsync(typeof(IVSGitExt));
25+
var barManager = new PullRequestStatusBarManager(usageTracker, serviceProvider);
2526

26-
new PullRequestStatusBarManager(gitExt, usageTracker, serviceProvider);
27+
// await ThreadingHelper.SwitchToMainThreadAsync() won't return until after a solution
28+
// has been loaded. We're using the following instead as a workaround.
29+
await ThreadingHelper.MainThreadDispatcher.InvokeAsync(() => barManager.StartShowingStatus());
2730
}
2831
}
2932
}

src/GitHub.InlineReviews/Services/PullRequestStatusBarManager.cs

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Windows.Input;
44
using System.Windows.Controls;
55
using System.Windows.Controls.Primitives;
6-
using System.ComponentModel;
76
using System.ComponentModel.Composition;
87
using GitHub.InlineReviews.Views;
98
using GitHub.InlineReviews.ViewModels;
@@ -13,64 +12,50 @@
1312
using GitHub.Logging;
1413
using GitHub.Extensions;
1514
using Serilog;
15+
using ReactiveUI;
1616

1717
namespace GitHub.InlineReviews.Services
1818
{
19+
/// <summary>
20+
/// Manage the UI that shows the PR for the current branch.
21+
/// </summary>
1922
public class PullRequestStatusBarManager
2023
{
2124
static readonly ILogger log = LogManager.ForContext<PullRequestStatusBarManager>();
2225
const string StatusBarPartName = "PART_SccStatusBarHost";
2326

24-
readonly IVSGitExt gitExt;
2527
readonly IUsageTracker usageTracker;
2628
readonly IGitHubServiceProvider serviceProvider;
2729

2830
IPullRequestSessionManager pullRequestSessionManager;
2931

3032
[ImportingConstructor]
31-
public PullRequestStatusBarManager(IVSGitExt gitExt, IUsageTracker usageTracker, IGitHubServiceProvider serviceProvider)
33+
public PullRequestStatusBarManager(IUsageTracker usageTracker, IGitHubServiceProvider serviceProvider)
3234
{
33-
this.gitExt = gitExt;
3435
this.usageTracker = usageTracker;
3536
this.serviceProvider = serviceProvider;
36-
37-
OnActiveRepositoriesChanged();
38-
gitExt.ActiveRepositoriesChanged += OnActiveRepositoriesChanged;
39-
}
40-
41-
void OnActiveRepositoriesChanged()
42-
{
43-
if (gitExt.ActiveRepositories.Count > 0)
44-
{
45-
gitExt.ActiveRepositoriesChanged -= OnActiveRepositoriesChanged;
46-
Application.Current.Dispatcher.Invoke(() => StartShowingStatus());
47-
}
4837
}
4938

50-
void StartShowingStatus()
39+
/// <summary>
40+
/// Start showing the PR for the active branch on the status bar.
41+
/// </summary>
42+
/// <remarks>
43+
/// This must be called from the Main thread.
44+
/// </remarks>
45+
public void StartShowingStatus()
5146
{
5247
try
5348
{
54-
// Create just in time on Main thread.
5549
pullRequestSessionManager = serviceProvider.GetService<IPullRequestSessionManager>();
56-
57-
RefreshCurrentSession();
58-
pullRequestSessionManager.PropertyChanged += PullRequestSessionManager_PropertyChanged;
50+
pullRequestSessionManager.WhenAnyValue(x => x.CurrentSession)
51+
.Subscribe(x => RefreshCurrentSession());
5952
}
6053
catch (Exception e)
6154
{
6255
log.Error(e, "Error initializing");
6356
}
6457
}
6558

66-
void PullRequestSessionManager_PropertyChanged(object sender, PropertyChangedEventArgs e)
67-
{
68-
if (e.PropertyName == nameof(PullRequestSessionManager.CurrentSession))
69-
{
70-
RefreshCurrentSession();
71-
}
72-
}
73-
7459
void RefreshCurrentSession()
7560
{
7661
var pullRequest = pullRequestSessionManager.CurrentSession?.PullRequest;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
using System.Threading;
3+
using System.Runtime.InteropServices;
4+
using Microsoft.VisualStudio.Shell;
5+
using GitHub.Services;
6+
using Task = System.Threading.Tasks.Task;
7+
8+
namespace GitHub.VisualStudio
9+
{
10+
/// <summary>
11+
/// This package creates a custom UIContext <see cref="Guids.UIContext_Git"/> that is activated when a
12+
/// repository is active in <see cref="IVSGitExt"/>.
13+
/// </summary>
14+
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
15+
[Guid(Guids.UIContext_Git)]
16+
// this is the Git service GUID, so we load whenever it loads
17+
[ProvideAutoLoad(Guids.GitSccProviderId, PackageAutoLoadFlags.BackgroundLoad)]
18+
public class GitContextPackage : AsyncPackage
19+
{
20+
protected async override Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
21+
{
22+
var gitExt = (IVSGitExt)await GetServiceAsync(typeof(IVSGitExt));
23+
var context = UIContext.FromUIContextGuid(new Guid(Guids.UIContext_Git));
24+
RefreshContext(context, gitExt);
25+
gitExt.ActiveRepositoriesChanged += () =>
26+
{
27+
RefreshContext(context, gitExt);
28+
};
29+
}
30+
31+
static void RefreshContext(UIContext context, IVSGitExt gitExt)
32+
{
33+
context.IsActive = gitExt.ActiveRepositories.Count > 0;
34+
}
35+
}
36+
}

src/GitHub.VisualStudio/GitHub.VisualStudio.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@
306306
<Link>Properties\SolutionInfo.cs</Link>
307307
</Compile>
308308
<Compile Include="AssemblyResolverPackage.cs" />
309+
<Compile Include="GitContextPackage.cs" />
309310
<Compile Include="IServiceProviderPackage.cs" />
310311
<Compile Include="Menus\BlameLink.cs" />
311312
<Compile Include="Menus\MenuBase.cs" />

src/GitHub.VisualStudio/GitHubPackage.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using System.Windows;
88
using GitHub.Api;
99
using GitHub.Extensions;
10-
using GitHub.Helpers;
1110
using GitHub.Info;
1211
using GitHub.Logging;
1312
using GitHub.Models;
@@ -28,8 +27,8 @@ namespace GitHub.VisualStudio
2827
[InstalledProductRegistration("#110", "#112", System.AssemblyVersionInformation.Version, IconResourceID = 400)]
2928
[Guid(Guids.guidGitHubPkgString)]
3029
[ProvideMenuResource("Menus.ctmenu", 1)]
31-
// this is the Git service GUID, so we load whenever it loads
32-
[ProvideAutoLoad(Guids.GitSccProviderId)]
30+
// Only initialize when we're in the context of a Git repository.
31+
[ProvideAutoLoad(Guids.UIContext_Git, PackageAutoLoadFlags.BackgroundLoad)]
3332
[ProvideToolWindow(typeof(GitHubPane), Orientation = ToolWindowOrientation.Right, Style = VsDockStyle.Tabbed, Window = EnvDTE.Constants.vsWindowKindSolutionExplorer)]
3433
[ProvideOptionPage(typeof(OptionsPage), "GitHub for Visual Studio", "General", 0, 0, supportsAutomation: true)]
3534
public class GitHubPackage : AsyncPackage
@@ -56,7 +55,8 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
5655

5756
await GetServiceAsync(typeof(IUsageTracker));
5857

59-
InitializeMenus().Forget();
58+
// This package might be loaded on demand so we must await initialization of menus.
59+
await InitializeMenus();
6060
}
6161

6262
void LogVersionInformation()
@@ -76,8 +76,6 @@ async Task InitializeMenus()
7676
return;
7777
}
7878

79-
await ThreadingHelper.SwitchToMainThreadAsync();
80-
8179
foreach (var menu in menus.Menus)
8280
serviceProvider.AddCommandHandler(menu.Guid, menu.CmdId, (s, e) => menu.Activate());
8381

0 commit comments

Comments
 (0)