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

Initialize GitHubPane and menus asynchronously #1569

Merged
merged 25 commits into from
Apr 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c20e618
Create MEF commands on background thread
jcansdale Mar 20, 2018
0527497
Allow menuService.AddCommands to be called from a b/g thread
jcansdale Mar 21, 2018
266ec58
Construct PullRequestStatusBarManager using MEF on b/g thread
jcansdale Mar 21, 2018
5730008
Factor b/g loading menu code into AsyncMenuPackage
jcansdale Mar 21, 2018
ec46954
Restore missing metrics
jcansdale Mar 21, 2018
48cb0cc
Allow MEF to refresh its cache on a background thread
jcansdale Mar 22, 2018
ca0a273
Use ContentPresenter instead of ContentControl
jcansdale Mar 27, 2018
f66afaf
Use package without MEF dependency for GitHubPane
jcansdale Mar 27, 2018
47d3753
Revert "Factor b/g loading menu code into AsyncMenuPackage"
jcansdale Mar 28, 2018
e9c8db9
Revert "Allow menuService.AddCommands to be called from a b/g thread"
jcansdale Mar 28, 2018
2fc764b
Add placeholder initializing and error views
jcansdale Mar 28, 2018
e6ee44d
Add GetViewModelAsync for GitHubPane
jcansdale Mar 29, 2018
ed0cb39
Remove redundant initialization code
jcansdale Mar 29, 2018
5dcf605
Fixed typo
jcansdale Apr 3, 2018
29508bb
Make error text box read only
jcansdale Apr 4, 2018
89ffd87
Show `Initializing...` while MEF is loading
jcansdale Apr 4, 2018
e3158d2
Make GitHubPane await initialization of IGitHubPaneViewModel
jcansdale Apr 4, 2018
255b007
Remove empty IncrementNumberOfShowCurrentPullRequest method
jcansdale Apr 4, 2018
4746859
Cast IMenuCommandService on Main thread
jcansdale Apr 4, 2018
a9c5c16
Use JoinableTask rather than TaskCompletionSource
jcansdale Apr 4, 2018
0504119
This page is intentionally left blank
jcansdale Apr 4, 2018
cb26608
Use JoinableTaskFactory from parent AsyncPackage
jcansdale Apr 6, 2018
7511113
Retrieve IGitHubServiceProvider asynchronously
jcansdale Apr 6, 2018
0983ef0
Moved NumberOfShowCurrentPullRequest tracking into command
jcansdale Apr 9, 2018
39d77aa
Keep CA happy
jcansdale Apr 9, 2018
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
1 change: 1 addition & 0 deletions src/GitHub.Exports/Settings/Guids.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public static class Guids
public const string CodeContainerProviderId = "6CE146CB-EF57-4F2C-A93F-5BA685317660";
public const string InlineReviewsPackageId = "248325BE-4A2D-4111-B122-E7D59BF73A35";
public const string PullRequestStatusPackageId = "5121BEC6-1088-4553-8453-0DDC7C8E2238";
public const string GitHubPanePackageId = "0A40459D-6B6D-4110-B6CE-EC83C0BC6A09";
public const string TeamExplorerWelcomeMessage = "C529627F-8AA6-4FDB-82EB-4BFB7DB753C3";
public const string LoginManagerId = "7BA2071A-790A-4F95-BE4A-0EEAA5928AAF";

Expand Down
11 changes: 7 additions & 4 deletions src/GitHub.InlineReviews/InlineReviewsPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,17 @@ protected override async Task InitializeAsync(

async Task InitializeMenus()
{
var menuService = (IMenuCommandService)(await GetServiceAsync(typeof(IMenuCommandService)));
var componentModel = (IComponentModel)(await GetServiceAsync(typeof(SComponentModel)));
var exports = componentModel.DefaultExportProvider;
var commands = new IVsCommandBase[]
{
exports.GetExportedValue<INextInlineCommentCommand>(),
exports.GetExportedValue<IPreviousInlineCommentCommand>()
};

await JoinableTaskFactory.SwitchToMainThreadAsync();
menuService.AddCommands(
exports.GetExportedValue<INextInlineCommentCommand>(),
exports.GetExportedValue<IPreviousInlineCommentCommand>());
var menuService = (IMenuCommandService)(await GetServiceAsync(typeof(IMenuCommandService)));
menuService.AddCommands(commands);
}
}
}
8 changes: 4 additions & 4 deletions src/GitHub.InlineReviews/PullRequestStatusBarPackage.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using System;
using System.Threading;
using System.Runtime.InteropServices;
using GitHub.Services;
using GitHub.VisualStudio;
using GitHub.InlineReviews.Services;
using Microsoft.VisualStudio.Shell;
using Task = System.Threading.Tasks.Task;
using Microsoft.VisualStudio.Threading;
using Microsoft.VisualStudio.ComponentModelHost;

namespace GitHub.InlineReviews
{
Expand All @@ -27,9 +27,9 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke

async Task InitializeStatusBar()
{
var usageTracker = (IUsageTracker)await GetServiceAsync(typeof(IUsageTracker));
var serviceProvider = (IGitHubServiceProvider)await GetServiceAsync(typeof(IGitHubServiceProvider));
var barManager = new PullRequestStatusBarManager(usageTracker, serviceProvider);
var componentModel = (IComponentModel)(await GetServiceAsync(typeof(SComponentModel)));
var exports = componentModel.DefaultExportProvider;
var barManager = exports.GetExportedValue<PullRequestStatusBarManager>();

await JoinableTaskFactory.SwitchToMainThreadAsync();
barManager.StartShowingStatus();
Expand Down
68 changes: 14 additions & 54 deletions src/GitHub.InlineReviews/Services/PullRequestStatusBarManager.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.ComponentModel.Composition;
using GitHub.Commands;
using GitHub.InlineReviews.Views;
using GitHub.InlineReviews.ViewModels;
using GitHub.Services;
using GitHub.VisualStudio;
using GitHub.Models;
using GitHub.Logging;
using GitHub.Extensions;
using Serilog;
using ReactiveUI;

Expand All @@ -19,21 +17,25 @@ namespace GitHub.InlineReviews.Services
/// <summary>
/// Manage the UI that shows the PR for the current branch.
/// </summary>
[Export(typeof(PullRequestStatusBarManager))]
public class PullRequestStatusBarManager
{
static readonly ILogger log = LogManager.ForContext<PullRequestStatusBarManager>();
const string StatusBarPartName = "PART_SccStatusBarHost";

readonly IUsageTracker usageTracker;
readonly IGitHubServiceProvider serviceProvider;
readonly IShowCurrentPullRequestCommand showCurrentPullRequestCommand;

IPullRequestSessionManager pullRequestSessionManager;
// At the moment this must be constructed on the main thread.
// TeamExplorerContext needs to retrieve DTE using GetService.
readonly Lazy<IPullRequestSessionManager> pullRequestSessionManager;

[ImportingConstructor]
public PullRequestStatusBarManager(IUsageTracker usageTracker, IGitHubServiceProvider serviceProvider)
public PullRequestStatusBarManager(
IShowCurrentPullRequestCommand showCurrentPullRequestCommand,
Lazy<IPullRequestSessionManager> pullRequestSessionManager)
{
this.usageTracker = usageTracker;
this.serviceProvider = serviceProvider;
this.showCurrentPullRequestCommand = showCurrentPullRequestCommand;
this.pullRequestSessionManager = pullRequestSessionManager;
}

/// <summary>
Expand All @@ -46,8 +48,7 @@ public void StartShowingStatus()
{
try
{
pullRequestSessionManager = serviceProvider.GetService<IPullRequestSessionManager>();
pullRequestSessionManager.WhenAnyValue(x => x.CurrentSession)
pullRequestSessionManager.Value.WhenAnyValue(x => x.CurrentSession)
.Subscribe(x => RefreshCurrentSession());
}
catch (Exception e)
Expand All @@ -58,16 +59,14 @@ public void StartShowingStatus()

void RefreshCurrentSession()
{
var pullRequest = pullRequestSessionManager.CurrentSession?.PullRequest;
var pullRequest = pullRequestSessionManager.Value.CurrentSession?.PullRequest;
var viewModel = pullRequest != null ? CreatePullRequestStatusViewModel(pullRequest) : null;
ShowStatus(viewModel);
}

PullRequestStatusViewModel CreatePullRequestStatusViewModel(IPullRequestModel pullRequest)
{
var dte = serviceProvider.TryGetService<EnvDTE.DTE>();
var command = new RaisePullRequestCommand(dte, usageTracker);
var pullRequestStatusViewModel = new PullRequestStatusViewModel(command);
var pullRequestStatusViewModel = new PullRequestStatusViewModel(showCurrentPullRequestCommand);
pullRequestStatusViewModel.Number = pullRequest.Number;
pullRequestStatusViewModel.Title = pullRequest.Title;
return pullRequestStatusViewModel;
Expand Down Expand Up @@ -111,44 +110,5 @@ StatusBar FindSccStatusBar(Window mainWindow)
var contentControl = mainWindow?.Template?.FindName(StatusBarPartName, mainWindow) as ContentControl;
return contentControl?.Content as StatusBar;
}

class RaisePullRequestCommand : ICommand
{
readonly string guid = Guids.guidGitHubCmdSetString;
readonly int id = PkgCmdIDList.showCurrentPullRequestCommand;

readonly EnvDTE.DTE dte;
readonly IUsageTracker usageTracker;

internal RaisePullRequestCommand(EnvDTE.DTE dte, IUsageTracker usageTracker)
{
this.dte = dte;
this.usageTracker = usageTracker;
}

public bool CanExecute(object parameter) => true;

public void Execute(object parameter)
{
try
{
object customIn = null;
object customOut = null;
dte?.Commands.Raise(guid, id, ref customIn, ref customOut);
}
catch (Exception e)
{
log.Error(e, "Couldn't raise {Guid}:{ID}", guid, id);
}

usageTracker.IncrementCounter(x => x.NumberOfShowCurrentPullRequest).Forget();
}

public event EventHandler CanExecuteChanged
{
add { }
remove { }
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using GitHub.Commands;
using GitHub.Logging;
using GitHub.Services;
using GitHub.Extensions;
using GitHub.Services.Vssdk.Commands;
using Serilog;

Expand All @@ -20,12 +21,14 @@ public class ShowCurrentPullRequestCommand : VsCommand, IShowCurrentPullRequestC
{
static readonly ILogger log = LogManager.ForContext<ShowCurrentPullRequestCommand>();
readonly IGitHubServiceProvider serviceProvider;
readonly Lazy<IUsageTracker> usageTracker;

[ImportingConstructor]
protected ShowCurrentPullRequestCommand(IGitHubServiceProvider serviceProvider)
protected ShowCurrentPullRequestCommand(IGitHubServiceProvider serviceProvider, Lazy<IUsageTracker> usageTracker)
: base(CommandSet, CommandId)
{
this.serviceProvider = serviceProvider;
this.usageTracker = usageTracker;
}

/// <summary>
Expand Down Expand Up @@ -58,6 +61,8 @@ public override async Task Execute()
var manager = serviceProvider.TryGetService<IGitHubToolWindowManager>();
var host = await manager.ShowGitHubPane();
await host.ShowPullRequest(session.RepositoryOwner, host.LocalRepository.Name, pullRequest.Number);

usageTracker.Value.IncrementCounter(x => x.NumberOfShowCurrentPullRequest).Forget();
}
catch (Exception ex)
{
Expand Down
1 change: 1 addition & 0 deletions src/GitHub.VisualStudio/GitHub.VisualStudio.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@
<Compile Include="Commands\ShowGitHubPaneCommand.cs" />
<Compile Include="Commands\OpenPullRequestsCommand.cs" />
<Compile Include="GitContextPackage.cs" />
<Compile Include="GitHubPanePackage.cs" />
<Compile Include="IServiceProviderPackage.cs" />
<Compile Include="Helpers\ActiveDocumentSnapshot.cs" />
<Compile Include="Commands\AddConnectionCommand.cs" />
Expand Down
20 changes: 10 additions & 10 deletions src/GitHub.VisualStudio/GitHubPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.Runtime.InteropServices;
using GitHub.Api;
using GitHub.Commands;
using GitHub.Helpers;
using GitHub.Info;
using GitHub.Exports;
using GitHub.Logging;
Expand All @@ -29,7 +28,6 @@ namespace GitHub.VisualStudio
[Guid(Guids.guidGitHubPkgString)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[ProvideAutoLoad(Guids.UIContext_Git, PackageAutoLoadFlags.BackgroundLoad)]
[ProvideToolWindow(typeof(GitHubPane), Orientation = ToolWindowOrientation.Right, Style = VsDockStyle.Tabbed, Window = EnvDTE.Constants.vsWindowKindSolutionExplorer)]
[ProvideOptionPage(typeof(OptionsPage), "GitHub for Visual Studio", "General", 0, 0, supportsAutomation: true)]
public class GitHubPackage : AsyncPackage
{
Expand All @@ -56,20 +54,23 @@ void LogVersionInformation()

async Task InitializeMenus()
{
var menuService = (IMenuCommandService)(await GetServiceAsync(typeof(IMenuCommandService)));
var componentModel = (IComponentModel)(await GetServiceAsync(typeof(SComponentModel)));
var exports = componentModel.DefaultExportProvider;

await JoinableTaskFactory.SwitchToMainThreadAsync();
menuService.AddCommands(
var commands = new IVsCommandBase[]
{
exports.GetExportedValue<IAddConnectionCommand>(),
exports.GetExportedValue<IBlameLinkCommand>(),
exports.GetExportedValue<ICopyLinkCommand>(),
exports.GetExportedValue<ICreateGistCommand>(),
exports.GetExportedValue<IOpenLinkCommand>(),
exports.GetExportedValue<IOpenPullRequestsCommand>(),
exports.GetExportedValue<IShowCurrentPullRequestCommand>(),
exports.GetExportedValue<IShowGitHubPaneCommand>());
exports.GetExportedValue<IShowGitHubPaneCommand>()
};

await JoinableTaskFactory.SwitchToMainThreadAsync();
var menuService = (IMenuCommandService)(await GetServiceAsync(typeof(IMenuCommandService)));
menuService.AddCommands(commands);
}

async Task EnsurePackageLoaded(Guid packageGuid)
Expand Down Expand Up @@ -147,9 +148,8 @@ public async Task<IGitHubPaneViewModel> ShowGitHubPane()
ErrorHandler.Failed(frame.Show());
}

var viewModel = (IGitHubPaneViewModel)((FrameworkElement)pane.Content).DataContext;
await viewModel.InitializeAsync(pane);
return viewModel;
var gitHubPane = (GitHubPane)pane;
return await gitHubPane.GetViewModelAsync();
}

static ToolWindowPane ShowToolWindow(Guid windowGuid)
Expand Down
22 changes: 22 additions & 0 deletions src/GitHub.VisualStudio/GitHubPanePackage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.Runtime.InteropServices;
using GitHub.VisualStudio.UI;
using Microsoft.VisualStudio.Shell;

namespace GitHub.VisualStudio
{
/// <summary>
/// This is the host package for the <see cref="GitHubPane"/> tool window.
/// </summary>
/// <remarks>
/// This package mustn't use MEF.
/// See: https://github.com/github/VisualStudio/issues/1550
/// </remarks>
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[Guid(Guids.GitHubPanePackageId)]
[ProvideToolWindow(typeof(GitHubPane), Orientation = ToolWindowOrientation.Right,
Style = VsDockStyle.Tabbed, Window = EnvDTE.Constants.vsWindowKindSolutionExplorer)]
public sealed class GitHubPanePackage : AsyncPackage
{
}
}
Loading