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

Commit 7598d20

Browse files
committed
Added context menu to PR list.
1 parent a6200b3 commit 7598d20

File tree

7 files changed

+108
-7
lines changed

7 files changed

+108
-7
lines changed

src/GitHub.App/SampleData/PullRequestListViewModelDesigner.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public PullRequestListViewModelDesigner()
6363
public Uri WebUrl => null;
6464
public ReactiveCommand<object> CreatePullRequest { get; }
6565
public ReactiveCommand<Unit> OpenItem { get; }
66+
public ReactiveCommand<object> OpenItemInBrowser { get; }
6667

6768
public Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection) => Task.CompletedTask;
6869
}

src/GitHub.App/ViewModels/GitHubPane/PullRequestListViewModel.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public PullRequestListViewModel(
5151
.Select(x => x?.CloneUrl?.ToRepositoryUrl().Append("pulls"))
5252
.ToProperty(this, x => x.WebUrl);
5353
CreatePullRequest = ReactiveCommand.Create().OnExecuteCompleted(_ => NavigateTo("pull/new"));
54+
OpenItemInBrowser = ReactiveCommand.Create();
5455
}
5556

5657
/// <inheritdoc/>
@@ -62,6 +63,9 @@ public PullRequestListViewModel(
6263
/// <inheritdoc/>
6364
public ReactiveCommand<object> CreatePullRequest { get; }
6465

66+
/// <inheritdoc/>
67+
public ReactiveCommand<object> OpenItemInBrowser { get; }
68+
6569
/// <inheritdoc/>
6670
protected override IVirtualizingListSource<IIssueListItemViewModelBase> CreateItemSource()
6771
{

src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestListViewModel.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,10 @@ public interface IPullRequestListViewModel : IIssueListViewModelBase, IOpenInBro
1212
/// Gets a command which navigates to the "Create Pull Request" view.
1313
/// </summary>
1414
ReactiveCommand<object> CreatePullRequest { get; }
15+
16+
/// <summary>
17+
/// Gets a command that opens pull request item on GitHub.
18+
/// </summary>
19+
ReactiveCommand<object> OpenItemInBrowser { get; }
1520
}
1621
}

src/GitHub.VisualStudio.UI/Resources.Designer.cs

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/GitHub.VisualStudio.UI/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,4 +434,7 @@
434434
<data name="UpdateComment" xml:space="preserve">
435435
<value>Update comment</value>
436436
</data>
437+
<data name="Open" xml:space="preserve">
438+
<value>Open</value>
439+
</data>
437440
</root>

src/GitHub.VisualStudio/Views/GitHubPane/PullRequestListView.xaml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<UserControl x:Class="GitHub.VisualStudio.Views.GitHubPane.PullRequestListView"
2+
Name="root"
23
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
34
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
45
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
56
xmlns:ghfvs="https://github.com/github/VisualStudio"
67
xmlns:local="clr-namespace:GitHub.VisualStudio.Views.GitHubPane"
78
xmlns:v="clr-namespace:GitHub.VisualStudio.Views"
89
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
10+
xmlns:prop="clr-namespace:GitHub.VisualStudio.UI;assembly=GitHub.VisualStudio.UI"
911
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"
1012
AutomationProperties.AutomationId="{x:Static ghfvs:AutomationIDs.PullRequestListViewCustom}">
1113
<d:DesignProperties.DataContext>
@@ -107,7 +109,14 @@
107109
<ListBox ItemsSource="{Binding ItemsView}"
108110
BorderThickness="0"
109111
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
110-
Visibility="{Binding Message, Converter={ghfvs:EqualsToVisibilityConverter None}}">
112+
Visibility="{Binding Message, Converter={ghfvs:EqualsToVisibilityConverter None}}"
113+
ContextMenuOpening="ListBox_ContextMenuOpening">
114+
<ListBox.ContextMenu>
115+
<ContextMenu>
116+
<MenuItem Header="{x:Static prop:Resources.Open}" Command="{Binding OpenItem}"/>
117+
<MenuItem Header="{x:Static prop:Resources.openInBrowser}" Command="{Binding OpenItemInBrowser}"/>
118+
</ContextMenu>
119+
</ListBox.ContextMenu>
111120
<ListBox.ItemContainerStyle>
112121
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
113122
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>

src/GitHub.VisualStudio/Views/GitHubPane/PullRequestListView.xaml.cs

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
using System;
22
using System.ComponentModel.Composition;
3+
using System.Linq;
4+
using System.Reactive.Disposables;
35
using System.Reactive.Linq;
6+
using System.Windows;
47
using System.Windows.Controls;
8+
using System.Windows.Documents;
59
using System.Windows.Input;
10+
using System.Windows.Media;
611
using GitHub.Exports;
12+
using GitHub.Extensions;
13+
using GitHub.Services;
14+
using GitHub.UI.Helpers;
715
using GitHub.ViewModels.GitHubPane;
816
using ReactiveUI;
917

@@ -23,13 +31,34 @@ public PullRequestListView()
2331
{
2432
var vm = DataContext as IPullRequestListViewModel;
2533
subscription?.Dispose();
26-
subscription = vm.AuthorFilter.WhenAnyValue(x => x.Selected)
27-
.Skip(1)
28-
.Subscribe(_ => authorFilterDropDown.IsOpen = false);
34+
subscription = null;
35+
36+
if (vm != null)
37+
{
38+
subscription = new CompositeDisposable(
39+
vm.AuthorFilter.WhenAnyValue(x => x.Selected)
40+
.Skip(1)
41+
.Subscribe(_ => authorFilterDropDown.IsOpen = false),
42+
vm.OpenItemInBrowser.Subscribe(x => OpenInBrowser((IPullRequestListItemViewModel)x)));
43+
}
2944
};
3045
}
3146

32-
private void ListBoxItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
47+
[Import]
48+
IVisualStudioBrowser VisualStudioBrowser { get; set; }
49+
50+
void OpenInBrowser(IPullRequestListItemViewModel item)
51+
{
52+
var vm = DataContext as IPullRequestListViewModel;
53+
54+
if (vm != null)
55+
{
56+
var uri = vm.RemoteRepository.CloneUrl.ToRepositoryUrl().Append("pull/" + item.Number);
57+
VisualStudioBrowser.OpenUrl(uri);
58+
}
59+
}
60+
61+
void ListBoxItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
3362
{
3463
var control = sender as ListBoxItem;
3564
var pr = control?.DataContext as IPullRequestListItemViewModel;
@@ -41,9 +70,50 @@ private void ListBoxItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
4170
}
4271
}
4372

44-
private void authorFilterDropDown_PopupOpened(object sender, EventArgs e)
73+
void authorFilterDropDown_PopupOpened(object sender, EventArgs e)
4574
{
4675
authorFilter.FocusSearchBox();
4776
}
77+
78+
void ListBox_ContextMenuOpening(object sender, ContextMenuEventArgs e)
79+
{
80+
ApplyContextMenuBinding<ListBoxItem>(sender, e);
81+
}
82+
83+
void ApplyContextMenuBinding<TItem>(object sender, ContextMenuEventArgs e) where TItem : Control
84+
{
85+
var container = (Control)sender;
86+
var item = GetVisual(e.OriginalSource)?.GetSelfAndVisualAncestors().OfType<TItem>().FirstOrDefault();
87+
88+
e.Handled = true;
89+
90+
if (item?.DataContext is IPullRequestListItemViewModel listItem)
91+
{
92+
container.ContextMenu.DataContext = this.DataContext;
93+
94+
foreach (var menuItem in container.ContextMenu.Items.OfType<MenuItem>())
95+
{
96+
menuItem.CommandParameter = listItem;
97+
}
98+
99+
e.Handled = false;
100+
}
101+
}
102+
103+
private Visual GetVisual(object element)
104+
{
105+
if (element is Visual v)
106+
{
107+
return v;
108+
}
109+
else if (element is TextElement e)
110+
{
111+
return e.Parent as Visual;
112+
}
113+
else
114+
{
115+
return null;
116+
}
117+
}
48118
}
49119
}

0 commit comments

Comments
 (0)