diff --git a/src/GitHub.App/ViewModels/GitHubPane/GitHubPaneViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/GitHubPaneViewModel.cs index 1125b6c211..9dd364c0ac 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/GitHubPaneViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/GitHubPaneViewModel.cs @@ -46,6 +46,8 @@ public sealed class GitHubPaneViewModel : ViewModelBase, IGitHubPaneViewModel, I readonly ReactiveCommand refresh; readonly ReactiveCommand showPullRequests; readonly ReactiveCommand openInBrowser; + readonly SemaphoreSlim initializing = new SemaphoreSlim(1); + bool initialized; IViewModel content; ILocalRepositoryModel localRepository; string searchQuery; @@ -198,26 +200,37 @@ public void Dispose() /// public async Task InitializeAsync(IServiceProvider paneServiceProvider) { - await UpdateContent(teamExplorerContext.ActiveRepository); - teamExplorerContext.WhenAnyValue(x => x.ActiveRepository) - .Skip(1) - .ObserveOn(RxApp.MainThreadScheduler) - .Subscribe(x => UpdateContent(x).Forget()); - - connectionManager.Connections.CollectionChanged += (_, __) => UpdateContent(LocalRepository).Forget(); - - BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.pullRequestCommand, showPullRequests); - BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.backCommand, navigator.NavigateBack); - BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.forwardCommand, navigator.NavigateForward); - BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.refreshCommand, refresh); - BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.githubCommand, openInBrowser); - - paneServiceProvider.AddCommandHandler(Guids.guidGitHubToolbarCmdSet, PkgCmdIDList.helpCommand, - (_, __) => - { - browser.OpenUrl(new Uri(GitHubUrls.Documentation)); - usageTracker.IncrementCounter(x => x.NumberOfGitHubPaneHelpClicks).Forget(); - }); + await initializing.WaitAsync(); + if (initialized) return; + + try + { + await UpdateContent(teamExplorerContext.ActiveRepository); + teamExplorerContext.WhenAnyValue(x => x.ActiveRepository) + .Skip(1) + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(x => UpdateContent(x).Forget()); + + connectionManager.Connections.CollectionChanged += (_, __) => UpdateContent(LocalRepository).Forget(); + + BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.pullRequestCommand, showPullRequests); + BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.backCommand, navigator.NavigateBack); + BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.forwardCommand, navigator.NavigateForward); + BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.refreshCommand, refresh); + BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.githubCommand, openInBrowser); + + paneServiceProvider.AddCommandHandler(Guids.guidGitHubToolbarCmdSet, PkgCmdIDList.helpCommand, + (_, __) => + { + browser.OpenUrl(new Uri(GitHubUrls.Documentation)); + usageTracker.IncrementCounter(x => x.NumberOfGitHubPaneHelpClicks).Forget(); + }); + } + finally + { + initialized = true; + initializing.Release(); + } } /// diff --git a/src/GitHub.Exports.Reactive/Services/IPullRequestSessionManager.cs b/src/GitHub.Exports.Reactive/Services/IPullRequestSessionManager.cs index 1069418a65..2d58852145 100644 --- a/src/GitHub.Exports.Reactive/Services/IPullRequestSessionManager.cs +++ b/src/GitHub.Exports.Reactive/Services/IPullRequestSessionManager.cs @@ -31,6 +31,18 @@ public interface IPullRequestSessionManager : INotifyPropertyChanged /// IPullRequestSession CurrentSession { get; } + /// + /// Ensures that the service is initialized. + /// + /// A task that when completed indicates that the service is initialized. + /// + /// If you are simply monitoring changes to the then you + /// don't need to call this method: will be updated on + /// initialization. If however, you want to be sure that is + /// initialized, you can await the task returned from this method. + /// + Task EnsureInitialized(); + /// /// Gets an that tracks the live state of a document. /// diff --git a/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs b/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs index 9025893bc1..70975c5884 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestSessionManager.cs @@ -36,6 +36,7 @@ public class PullRequestSessionManager : ReactiveObject, IPullRequestSessionMana readonly IModelServiceFactory modelServiceFactory; readonly Dictionary, WeakReference> sessions = new Dictionary, WeakReference>(); + TaskCompletionSource initialized; IPullRequestSession currentSession; ILocalRepositoryModel repository; @@ -65,6 +66,7 @@ public PullRequestSessionManager( this.sessionService = sessionService; this.connectionManager = connectionManager; this.modelServiceFactory = modelServiceFactory; + initialized = new TaskCompletionSource(null); Observable.FromEventPattern(teamExplorerContext, nameof(teamExplorerContext.StatusChanged)) .ObserveOn(RxApp.MainThreadScheduler) @@ -82,6 +84,10 @@ public IPullRequestSession CurrentSession private set { this.RaiseAndSetIfChanged(ref currentSession, value); } } + /// + public Task EnsureInitialized() => initialized.Task; + + /// public async Task GetLiveFile( string relativePath, ITextView textView, @@ -230,6 +236,7 @@ async Task StatusChanged() } CurrentSession = session; + initialized.SetResult(null); } catch (Exception e) { diff --git a/src/GitHub.VisualStudio/GitHubPackage.cs b/src/GitHub.VisualStudio/GitHubPackage.cs index 78a0626cba..bcd3c2271a 100644 --- a/src/GitHub.VisualStudio/GitHubPackage.cs +++ b/src/GitHub.VisualStudio/GitHubPackage.cs @@ -158,7 +158,7 @@ protected override Task InitializeAsync(CancellationToken cancellationToken, IPr return Task.CompletedTask; } - public IGitHubPaneViewModel ShowHomePane() + public async Task ShowGitHubPane() { var pane = ShowToolWindow(new Guid(GitHubPane.GitHubPaneGuid)); if (pane == null) @@ -168,7 +168,10 @@ public IGitHubPaneViewModel ShowHomePane() { ErrorHandler.Failed(frame.Show()); } - return (IGitHubPaneViewModel)((FrameworkElement)pane.Content).DataContext; + + var viewModel = (IGitHubPaneViewModel)((FrameworkElement)pane.Content).DataContext; + await viewModel.InitializeAsync(pane); + return viewModel; } static ToolWindowPane ShowToolWindow(Guid windowGuid) diff --git a/src/GitHub.VisualStudio/IServiceProviderPackage.cs b/src/GitHub.VisualStudio/IServiceProviderPackage.cs index 60b0da8b22..447301ca1f 100644 --- a/src/GitHub.VisualStudio/IServiceProviderPackage.cs +++ b/src/GitHub.VisualStudio/IServiceProviderPackage.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using System.Threading.Tasks; using GitHub.ViewModels.GitHubPane; namespace GitHub.VisualStudio @@ -12,6 +13,6 @@ public interface IServiceProviderPackage : IServiceProvider, Microsoft.VisualStu [ComVisible(true)] public interface IGitHubToolWindowManager { - IGitHubPaneViewModel ShowHomePane(); + Task ShowGitHubPane(); } } diff --git a/src/GitHub.VisualStudio/Menus/OpenPullRequests.cs b/src/GitHub.VisualStudio/Menus/OpenPullRequests.cs index f37f29f551..134be287ce 100644 --- a/src/GitHub.VisualStudio/Menus/OpenPullRequests.cs +++ b/src/GitHub.VisualStudio/Menus/OpenPullRequests.cs @@ -1,15 +1,17 @@ -using GitHub.Exports; -using GitHub.UI; -using GitHub.VisualStudio.UI; -using System; -using GitHub.Services; +using System; +using GitHub.Exports; using GitHub.Extensions; +using GitHub.Logging; +using GitHub.Services; +using Serilog; namespace GitHub.VisualStudio.Menus { [ExportMenu(MenuType = MenuType.OpenPullRequests)] public class OpenPullRequests : MenuBase, IMenuHandler { + static readonly ILogger log = LogManager.ForContext(); + public OpenPullRequests(IGitHubServiceProvider serviceProvider) : base(serviceProvider) { @@ -19,10 +21,17 @@ public OpenPullRequests(IGitHubServiceProvider serviceProvider) public Guid Guid => Guids.guidGitHubCmdSet; public int CmdId => PkgCmdIDList.openPullRequestsCommand; - public void Activate(object data = null) + public async void Activate(object data = null) { - var host = ServiceProvider.TryGetService().ShowHomePane(); - host.ShowPullRequests().Forget(); + try + { + var host = await ServiceProvider.TryGetService().ShowGitHubPane(); + await host.ShowPullRequests(); + } + catch (Exception ex) + { + log.Error(ex, "Error showing opening pull requests"); + } } } } diff --git a/src/GitHub.VisualStudio/Menus/ShowCurrentPullRequest.cs b/src/GitHub.VisualStudio/Menus/ShowCurrentPullRequest.cs index 267530efd5..8e4aa9fd24 100644 --- a/src/GitHub.VisualStudio/Menus/ShowCurrentPullRequest.cs +++ b/src/GitHub.VisualStudio/Menus/ShowCurrentPullRequest.cs @@ -1,15 +1,17 @@ using System; using GitHub.Exports; -using GitHub.UI; -using GitHub.Services; using GitHub.Extensions; -using GitHub.Models; +using GitHub.Logging; +using GitHub.Services; +using Serilog; namespace GitHub.VisualStudio.Menus { [ExportMenu(MenuType = MenuType.OpenPullRequests)] public class ShowCurrentPullRequest : MenuBase, IMenuHandler { + static readonly ILogger log = LogManager.ForContext(); + public ShowCurrentPullRequest(IGitHubServiceProvider serviceProvider) : base(serviceProvider) { @@ -19,19 +21,28 @@ public ShowCurrentPullRequest(IGitHubServiceProvider serviceProvider) public Guid Guid => Guids.guidGitHubCmdSet; public int CmdId => PkgCmdIDList.showCurrentPullRequestCommand; - public void Activate(object data = null) + public async void Activate(object data = null) { - var pullRequestSessionManager = ServiceProvider.ExportProvider.GetExportedValueOrDefault(); - var session = pullRequestSessionManager?.CurrentSession; - if (session == null) + try { - return; // No active PR session. - } + var pullRequestSessionManager = ServiceProvider.ExportProvider.GetExportedValueOrDefault(); + await pullRequestSessionManager.EnsureInitialized(); - var pullRequest = session.PullRequest; - var manager = ServiceProvider.TryGetService(); - var host = manager.ShowHomePane(); - host.ShowPullRequest(session.RepositoryOwner, host.LocalRepository.Name, pullRequest.Number); + var session = pullRequestSessionManager?.CurrentSession; + if (session == null) + { + return; // No active PR session. + } + + var pullRequest = session.PullRequest; + var manager = ServiceProvider.TryGetService(); + var host = await manager.ShowGitHubPane(); + await host.ShowPullRequest(session.RepositoryOwner, host.LocalRepository.Name, pullRequest.Number); + } + catch (Exception ex) + { + log.Error(ex, "Error showing current pull request"); + } } } } diff --git a/src/GitHub.VisualStudio/Menus/ShowGitHubPane.cs b/src/GitHub.VisualStudio/Menus/ShowGitHubPane.cs index f693106d52..d967c471a1 100644 --- a/src/GitHub.VisualStudio/Menus/ShowGitHubPane.cs +++ b/src/GitHub.VisualStudio/Menus/ShowGitHubPane.cs @@ -17,7 +17,7 @@ public ShowGitHubPane(IGitHubServiceProvider serviceProvider) public void Activate(object data = null) { - ServiceProvider.TryGetService()?.ShowHomePane(); + ServiceProvider.TryGetService()?.ShowGitHubPane(); } } }