diff --git a/src/GitHub.Exports/Settings/Guids.cs b/src/GitHub.Exports/Settings/Guids.cs
index 2e225c7038..81562cdaff 100644
--- a/src/GitHub.Exports/Settings/Guids.cs
+++ b/src/GitHub.Exports/Settings/Guids.cs
@@ -13,6 +13,7 @@ public static class Guids
public const string StartPagePackageId = "3b764d23-faf7-486f-94c7-b3accc44a70e";
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 TeamExplorerWelcomeMessage = "C529627F-8AA6-4FDB-82EB-4BFB7DB753C3";
public const string LoginManagerId = "7BA2071A-790A-4F95-BE4A-0EEAA5928AAF";
diff --git a/src/GitHub.InlineReviews/GitHub.InlineReviews.csproj b/src/GitHub.InlineReviews/GitHub.InlineReviews.csproj
index d7e0f3d91f..ced6cf829e 100644
--- a/src/GitHub.InlineReviews/GitHub.InlineReviews.csproj
+++ b/src/GitHub.InlineReviews/GitHub.InlineReviews.csproj
@@ -88,10 +88,13 @@
+
+
+
@@ -124,6 +127,7 @@
+
DiffCommentThreadView.xaml
@@ -161,6 +165,9 @@
CommentView.xaml
+
+ PullRequestStatusView.xaml
+
@@ -447,6 +454,10 @@
MSBuild:Compile
Designer
+
+ Designer
+ MSBuild:Compile
+
diff --git a/src/GitHub.InlineReviews/InlineReviewsPackage.cs b/src/GitHub.InlineReviews/InlineReviewsPackage.cs
index 9271fbd299..5d06a63d87 100644
--- a/src/GitHub.InlineReviews/InlineReviewsPackage.cs
+++ b/src/GitHub.InlineReviews/InlineReviewsPackage.cs
@@ -12,7 +12,7 @@ namespace GitHub.InlineReviews
[Guid(Guids.InlineReviewsPackageId)]
[ProvideAutoLoad(UIContextGuids80.SolutionExists)]
[ProvideMenuResource("Menus.ctmenu", 1)]
- [ProvideToolWindow(typeof(PullRequestCommentsPane), DocumentLikeTool=true)]
+ [ProvideToolWindow(typeof(PullRequestCommentsPane), DocumentLikeTool = true)]
public class InlineReviewsPackage : Package
{
protected override void Initialize()
diff --git a/src/GitHub.InlineReviews/PullRequestStatusPackage.cs b/src/GitHub.InlineReviews/PullRequestStatusPackage.cs
new file mode 100644
index 0000000000..bf9caf9075
--- /dev/null
+++ b/src/GitHub.InlineReviews/PullRequestStatusPackage.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Runtime.InteropServices;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.ComponentModelHost;
+using GitHub.VisualStudio;
+using GitHub.InlineReviews.Services;
+
+namespace GitHub.InlineReviews
+{
+ [PackageRegistration(UseManagedResourcesOnly = true)]
+ [Guid(Guids.PullRequestStatusPackageId)]
+ [ProvideAutoLoad(UIContextGuids80.SolutionExists)]
+ public class PullRequestStatusPackage : Package
+ {
+ protected override void Initialize()
+ {
+ var componentModel = (IComponentModel)GetService(typeof(SComponentModel));
+ var exportProvider = componentModel.DefaultExportProvider;
+ var pullRequestStatusManager = exportProvider.GetExportedValue();
+ pullRequestStatusManager.Initialize();
+ }
+ }
+}
diff --git a/src/GitHub.InlineReviews/Services/IPullRequestStatusManager.cs b/src/GitHub.InlineReviews/Services/IPullRequestStatusManager.cs
new file mode 100644
index 0000000000..d355b68312
--- /dev/null
+++ b/src/GitHub.InlineReviews/Services/IPullRequestStatusManager.cs
@@ -0,0 +1,7 @@
+namespace GitHub.InlineReviews.Services
+{
+ public interface IPullRequestStatusManager
+ {
+ void Initialize();
+ }
+}
diff --git a/src/GitHub.InlineReviews/Services/PullRequestStatusManager.cs b/src/GitHub.InlineReviews/Services/PullRequestStatusManager.cs
new file mode 100644
index 0000000000..d2d3f118a9
--- /dev/null
+++ b/src/GitHub.InlineReviews/Services/PullRequestStatusManager.cs
@@ -0,0 +1,149 @@
+using System;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.ComponentModel;
+using System.ComponentModel.Composition;
+using GitHub.InlineReviews.Views;
+using GitHub.InlineReviews.ViewModels;
+using GitHub.Services;
+using GitHub.VisualStudio;
+using Microsoft.VisualStudio.Shell;
+using GitHub.Models;
+using GitHub.Logging;
+using Serilog;
+
+namespace GitHub.InlineReviews.Services
+{
+ [Export(typeof(IPullRequestStatusManager))]
+ public class PullRequestStatusManager : IPullRequestStatusManager
+ {
+ static readonly ILogger log = LogManager.ForContext();
+ const string StatusBarPartName = "PART_SccStatusBarHost";
+
+ readonly SVsServiceProvider serviceProvider;
+ readonly Window mainWindow;
+ readonly IPullRequestSessionManager pullRequestSessionManager;
+
+ [ImportingConstructor]
+ public PullRequestStatusManager(SVsServiceProvider serviceProvider, IPullRequestSessionManager pullRequestSessionManager)
+ : this()
+ {
+ this.serviceProvider = serviceProvider;
+ this.pullRequestSessionManager = pullRequestSessionManager;
+ }
+
+ public PullRequestStatusManager()
+ {
+ mainWindow = Application.Current.MainWindow;
+ }
+
+ public void Initialize()
+ {
+ RefreshCurrentSession();
+ pullRequestSessionManager.PropertyChanged += PullRequestSessionManager_PropertyChanged;
+ }
+
+ void PullRequestSessionManager_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(PullRequestSessionManager.CurrentSession))
+ {
+ RefreshCurrentSession();
+ }
+ }
+
+ void RefreshCurrentSession()
+ {
+ var pullRequest = pullRequestSessionManager.CurrentSession?.PullRequest;
+ var viewModel = pullRequest != null ? CreatePullRequestStatusViewModel(serviceProvider, pullRequest) : null;
+ ShowStatus(viewModel);
+ }
+
+ static PullRequestStatusViewModel CreatePullRequestStatusViewModel(IServiceProvider serviceProvider, IPullRequestModel pullRequest)
+ {
+ var command = new RaiseVsCommand(serviceProvider, Guids.guidGitHubCmdSetString, PkgCmdIDList.showCurrentPullRequestCommand);
+ var pullRequestStatusViewModel = new PullRequestStatusViewModel(command);
+ pullRequestStatusViewModel.Number = pullRequest.Number;
+ pullRequestStatusViewModel.Title = pullRequest.Title;
+ return pullRequestStatusViewModel;
+ }
+
+ void ShowStatus(PullRequestStatusViewModel pullRequestStatusViewModel = null)
+ {
+ var statusBar = FindSccStatusBar();
+ if (statusBar != null)
+ {
+ var githubStatusBar = Find(statusBar);
+ if (githubStatusBar != null)
+ {
+ // Replace to ensure status shows up.
+ statusBar.Items.Remove(githubStatusBar);
+ }
+
+ if (pullRequestStatusViewModel != null)
+ {
+ githubStatusBar = new PullRequestStatusView { DataContext = pullRequestStatusViewModel };
+ statusBar.Items.Insert(0, githubStatusBar);
+ }
+ }
+ }
+
+ static T Find(StatusBar statusBar)
+ {
+ foreach (var item in statusBar.Items)
+ {
+ if (item is T)
+ {
+ return (T)item;
+ }
+ }
+
+ return default(T);
+ }
+
+ StatusBar FindSccStatusBar()
+ {
+ var contentControl = mainWindow?.Template?.FindName(StatusBarPartName, mainWindow) as ContentControl;
+ return contentControl?.Content as StatusBar;
+ }
+
+ class RaiseVsCommand : ICommand
+ {
+ readonly IServiceProvider serviceProvider;
+ readonly string guid;
+ readonly int id;
+
+ internal RaiseVsCommand(IServiceProvider serviceProvider, string guid, int id)
+ {
+ this.serviceProvider = serviceProvider;
+ this.guid = guid;
+ this.id = id;
+ }
+
+ public bool CanExecute(object parameter) => true;
+
+ public void Execute(object parameter)
+ {
+ try
+ {
+ var dte = serviceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
+ 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);
+ System.Diagnostics.Trace.WriteLine(e);
+ }
+ }
+
+ public event EventHandler CanExecuteChanged
+ {
+ add { }
+ remove { }
+ }
+ }
+ }
+}
diff --git a/src/GitHub.InlineReviews/ViewModels/PullRequestStatusViewModel.cs b/src/GitHub.InlineReviews/ViewModels/PullRequestStatusViewModel.cs
new file mode 100644
index 0000000000..ee7b1e285e
--- /dev/null
+++ b/src/GitHub.InlineReviews/ViewModels/PullRequestStatusViewModel.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Windows.Input;
+using System.ComponentModel;
+
+namespace GitHub.InlineReviews.ViewModels
+{
+ public class PullRequestStatusViewModel : INotifyPropertyChanged
+ {
+ int? number;
+ string title;
+
+ public PullRequestStatusViewModel(ICommand showCurrentPullRequestCommand)
+ {
+ ShowCurrentPullRequestCommand = showCurrentPullRequestCommand;
+ }
+
+ public int? Number
+ {
+ get { return number; }
+ set
+ {
+ if (number != value)
+ {
+ number = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Number)));
+ }
+ }
+ }
+
+ public string Title
+ {
+ get { return title; }
+ set
+ {
+ if (title != value)
+ {
+ title = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Title)));
+ }
+ }
+ }
+
+ public ICommand ShowCurrentPullRequestCommand { get; }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ }
+}
diff --git a/src/GitHub.InlineReviews/Views/PullRequestStatusView.xaml b/src/GitHub.InlineReviews/Views/PullRequestStatusView.xaml
new file mode 100644
index 0000000000..98d48646f0
--- /dev/null
+++ b/src/GitHub.InlineReviews/Views/PullRequestStatusView.xaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/GitHub.InlineReviews/Views/PullRequestStatusView.xaml.cs b/src/GitHub.InlineReviews/Views/PullRequestStatusView.xaml.cs
new file mode 100644
index 0000000000..535830924a
--- /dev/null
+++ b/src/GitHub.InlineReviews/Views/PullRequestStatusView.xaml.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Windows.Controls;
+
+namespace GitHub.InlineReviews.Views
+{
+ public partial class PullRequestStatusView : UserControl
+ {
+ public PullRequestStatusView()
+ {
+ InitializeComponent();
+ }
+ }
+}