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

Commit abb4661

Browse files
committed
Refactored comment views.
Use a different view for comments in the conversation view and inline comments.
1 parent 72fb28b commit abb4661

File tree

10 files changed

+321
-63
lines changed

10 files changed

+321
-63
lines changed

src/GitHub.App/ViewModels/CommentViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace GitHub.ViewModels
1818
/// </summary>
1919
[Export(typeof(ICommentViewModel))]
2020
[PartCreationPolicy(CreationPolicy.NonShared)]
21-
public class CommentViewModel : ReactiveObject, ICommentViewModel
21+
public class CommentViewModel : ViewModelBase, ICommentViewModel
2222
{
2323
static readonly ILogger log = LogManager.ForContext<CommentViewModel>();
2424
readonly ICommentService commentService;

src/GitHub.App/ViewModels/Documents/CommitListViewModel.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.ComponentModel.Composition;
34
using System.Linq;
45
using System.Text;
56

@@ -8,6 +9,7 @@ namespace GitHub.ViewModels.Documents
89
/// <summary>
910
/// Displays a list of commit summaries in a pull request timeline.
1011
/// </summary>
12+
[Export(typeof(ICommitListViewModel))]
1113
public class CommitListViewModel : ViewModelBase, ICommitListViewModel
1214
{
1315
/// <summary>

src/GitHub.App/ViewModels/Documents/IssueishCommentViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ await base.InitializeAsync(
7474
}
7575
}
7676

77-
public void Dispose() => closeOrReopenCaption.Dispose();
77+
public void Dispose() => closeOrReopenCaption?.Dispose();
7878

7979
async Task DoCloseOrReopen()
8080
{

src/GitHub.VisualStudio.UI/GitHub.VisualStudio.UI.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
</ItemGroup>
3131

3232
<ItemGroup>
33+
<Compile Update="Views\Documents\IssueishCommentView.xaml.cs">
34+
<DependentUpon>IssueishCommentView.xaml</DependentUpon>
35+
</Compile>
3336
<Compile Update="Views\GitHubPane\NoRemoteOriginView.xaml.cs">
3437
<DependentUpon>NoRemoteOriginView.xaml</DependentUpon>
3538
</Compile>

src/GitHub.VisualStudio.UI/Views/CommentThreadView.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<ItemsControl ItemsSource="{Binding Comments}">
1414
<ItemsControl.ItemTemplate>
1515
<DataTemplate>
16-
<local:CommentView />
16+
<local:PullRequestReviewCommentView />
1717
</DataTemplate>
1818
</ItemsControl.ItemTemplate>
1919
</ItemsControl>
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
<UserControl x:Class="GitHub.VisualStudio.Views.Documents.IssueishCommentView"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:ghfvs="https://github.com/github/VisualStudio"
7+
xmlns:cache="clr-namespace:GitHub.UI.Helpers;assembly=GitHub.UI"
8+
xmlns:ui="clr-namespace:GitHub.UI;assembly=GitHub.UI"
9+
xmlns:markdig="clr-namespace:Markdig.Wpf;assembly=Markdig.Wpf"
10+
xmlns:views="clr-namespace:GitHub.VisualStudio.Views"
11+
mc:Ignorable="d" d:DesignWidth="300">
12+
<d:DesignProperties.DataContext>
13+
<ghfvs:CommentViewModelDesigner EditState="Editing">
14+
<ghfvs:CommentViewModelDesigner.Body>
15+
You can use a `CompositeDisposable` type here, it's designed to handle disposables in an optimal way (you can just call `Dispose()` on it and it will handle disposing everything it holds).
16+
</ghfvs:CommentViewModelDesigner.Body>
17+
</ghfvs:CommentViewModelDesigner>
18+
</d:DesignProperties.DataContext>
19+
20+
<FrameworkElement.Resources>
21+
<ResourceDictionary>
22+
<ResourceDictionary.MergedDictionaries>
23+
<cache:SharedDictionaryManager Source="pack://application:,,,/GitHub.UI;component/SharedDictionary.xaml" />
24+
<cache:SharedDictionaryManager Source="pack://application:,,,/GitHub.UI.Reactive;component/SharedDictionary.xaml" />
25+
<cache:SharedDictionaryManager Source="pack://application:,,,/GitHub.VisualStudio.UI;component/SharedDictionary.xaml" />
26+
<cache:SharedDictionaryManager Source="pack://application:,,,/GitHub.UI;component/Assets/Markdown.xaml" />
27+
</ResourceDictionary.MergedDictionaries>
28+
29+
<Style TargetType="Button" BasedOn="{StaticResource GitHubVsButton}"/>
30+
</ResourceDictionary>
31+
</FrameworkElement.Resources>
32+
33+
<FrameworkElement.CommandBindings>
34+
<CommandBinding Command="{x:Static markdig:Commands.Hyperlink}" Executed="OpenHyperlink" />
35+
</FrameworkElement.CommandBindings>
36+
37+
<Grid>
38+
<!-- Displays an existing comment-->
39+
<Grid Margin="0 16">
40+
<Grid.ColumnDefinitions>
41+
<ColumnDefinition Width="40" />
42+
<ColumnDefinition Width="*" />
43+
</Grid.ColumnDefinitions>
44+
<Grid.RowDefinitions>
45+
<RowDefinition Height="Auto"/>
46+
<RowDefinition Height="Auto"/>
47+
</Grid.RowDefinitions>
48+
49+
<Grid.Style>
50+
<!-- Hides the grid unless EditState == None -->
51+
<Style TargetType="FrameworkElement">
52+
<Setter Property="Visibility" Value="Collapsed"/>
53+
<Style.Triggers>
54+
<DataTrigger Binding="{Binding EditState}" Value="None">
55+
<Setter Property="Visibility" Value="Visible"/>
56+
</DataTrigger>
57+
</Style.Triggers>
58+
</Style>
59+
</Grid.Style>
60+
61+
<views:ActorAvatarView Width="35"
62+
Height="35"
63+
VerticalAlignment="Top"
64+
Margin="0 0 5 0"
65+
ViewModel="{Binding Author}" />
66+
67+
<Border BorderBrush="{DynamicResource GitHubHeaderSeparatorBrush}" BorderThickness="1"
68+
Grid.Column="1" VerticalAlignment="Top">
69+
<StackPanel Orientation="Vertical">
70+
<Border Padding="6" Background="{DynamicResource GitHubBranchNameBackgroundBrush}" BorderBrush="{DynamicResource GitHubHeaderSeparatorBrush}" BorderThickness="0 0 0 1">
71+
<StackPanel Orientation="Horizontal" DockPanel.Dock="Left" >
72+
<TextBlock Foreground="{DynamicResource GitHubVsToolWindowText}" Margin="4">
73+
<Run FontWeight="SemiBold" Text="{Binding Author.Login}" />
74+
<Run Text="commented" />
75+
</TextBlock>
76+
77+
<ui:GitHubActionLink Content="{Binding CreatedAt, Converter={ui:DurationToStringConverter}}"
78+
Command="{Binding OpenOnGitHub}"
79+
Foreground="{DynamicResource GitHubVsToolWindowText}"
80+
VerticalAlignment="Center"
81+
Opacity="0.75" />
82+
<Border Background="{DynamicResource VsBrush.InfoBackground}"
83+
BorderBrush="{DynamicResource VsBrush.AccentPale}"
84+
BorderThickness="1"
85+
CornerRadius="3"
86+
Padding="2 1"
87+
VerticalAlignment="Center"
88+
Visibility="{Binding IsPending, Converter={ui:BooleanToVisibilityConverter}, FallbackValue=Collapsed}">
89+
<TextBlock FontSize="10" Text="{x:Static ghfvs:Resources.Pending}" />
90+
</Border>
91+
</StackPanel>
92+
</Border>
93+
94+
<markdig:MarkdownViewer Name="bodyMarkdown" Margin="8" Foreground="{DynamicResource VsBrush.WindowText}" Markdown="{Binding Body}"/>
95+
</StackPanel>
96+
</Border>
97+
</Grid>
98+
99+
<!-- Displays edit view or a reply placeholder-->
100+
<Grid>
101+
<Grid.Style>
102+
<Style TargetType="FrameworkElement">
103+
<Setter Property="Visibility" Value="Collapsed"/>
104+
<Style.Triggers>
105+
<DataTrigger Binding="{Binding EditState}" Value="Placeholder">
106+
<Setter Property="Visibility" Value="Visible"/>
107+
</DataTrigger>
108+
<DataTrigger Binding="{Binding EditState}" Value="Editing">
109+
<Setter Property="Visibility" Value="Visible"/>
110+
</DataTrigger>
111+
</Style.Triggers>
112+
</Style>
113+
</Grid.Style>
114+
115+
<Grid.ColumnDefinitions>
116+
<ColumnDefinition Width="40" />
117+
<ColumnDefinition Width="Auto"/>
118+
<ColumnDefinition Width="*"/>
119+
</Grid.ColumnDefinitions>
120+
121+
<Grid.RowDefinitions>
122+
<RowDefinition Height="Auto"/>
123+
<RowDefinition Height="*"/>
124+
<RowDefinition Height="Auto"/>
125+
<RowDefinition Height="Auto"/>
126+
</Grid.RowDefinitions>
127+
128+
<Separator Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="0" Margin="0 0 0 4"
129+
Background="{DynamicResource GitHubButtonBorderBrush}"/>
130+
131+
<ui:PromptTextBox Name="body"
132+
Grid.Column="2"
133+
Grid.Row="1"
134+
AcceptsReturn="True"
135+
AcceptsTab="True"
136+
IsReadOnly="{Binding IsReadOnly}"
137+
Margin="4 0 4 4"
138+
Text="{Binding Body, UpdateSourceTrigger=PropertyChanged}"
139+
TextWrapping="Wrap"
140+
VerticalAlignment="Center"
141+
GotFocus="ReplyPlaceholder_GotFocus"
142+
Loaded="body_Loaded"
143+
SpellCheck.IsEnabled="True">
144+
<ui:PromptTextBox.Style>
145+
<Style TargetType="ui:PromptTextBox" BasedOn="{StaticResource RoundedPromptTextBox}">
146+
<Setter Property="Foreground" Value="{DynamicResource GitHubVsToolWindowText}" />
147+
<Setter Property="Background" Value="{DynamicResource VsBrush.SearchBoxBackground}" />
148+
<Setter Property="Height" Value="28"/>
149+
<Setter Property="PromptText" Value="Reply..."/>
150+
<Setter Property="BorderBrush" Value="{DynamicResource GitHubVsBrandedUIBorder}" />
151+
152+
<Style.Triggers>
153+
<DataTrigger Binding="{Binding EditState}" Value="Editing">
154+
<Setter Property="MinHeight" Value="100"/>
155+
<Setter Property="PromptText" Value="Leave a comment"/>
156+
</DataTrigger>
157+
</Style.Triggers>
158+
159+
<Style.Resources>
160+
<Style TargetType="TextBlock">
161+
<Setter Property="Foreground" Value="{DynamicResource GitHubVsToolWindowText}" />
162+
</Style>
163+
</Style.Resources>
164+
</Style>
165+
</ui:PromptTextBox.Style>
166+
</ui:PromptTextBox>
167+
168+
<DockPanel Grid.Column="2" Grid.Row="2"
169+
Margin="0 4"
170+
HorizontalAlignment="Left"
171+
TextBlock.Foreground="Red">
172+
<DockPanel.Style>
173+
<Style TargetType="FrameworkElement">
174+
<Style.Triggers>
175+
<DataTrigger Binding="{Binding ErrorMessage}" Value="{x:Null}">
176+
<Setter Property="Visibility" Value="Collapsed"/>
177+
</DataTrigger>
178+
</Style.Triggers>
179+
</Style>
180+
</DockPanel.Style>
181+
<ui:OcticonImage DockPanel.Dock="Left" Icon="alert" Margin="0 0 4 0"/>
182+
<TextBlock Text="{Binding ErrorMessage}" TextWrapping="Wrap"/>
183+
</DockPanel>
184+
185+
<StackPanel Name="buttonPanel"
186+
Grid.Column="2" Grid.Row="3"
187+
Margin="4 8"
188+
HorizontalAlignment="Left"
189+
Orientation="Horizontal"
190+
IsVisibleChanged="buttonPanel_IsVisibleChanged">
191+
<StackPanel.Style>
192+
<Style TargetType="FrameworkElement">
193+
<Setter Property="Visibility" Value="Collapsed"/>
194+
<Style.Triggers>
195+
<DataTrigger Binding="{Binding EditState}" Value="Editing">
196+
<Setter Property="Visibility" Value="Visible"/>
197+
</DataTrigger>
198+
</Style.Triggers>
199+
</Style>
200+
</StackPanel.Style>
201+
<Button Command="{Binding CommitEdit}" Content="{Binding CommitCaption}"/>
202+
</StackPanel>
203+
</Grid>
204+
</Grid>
205+
</UserControl>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using System;
2+
using System.ComponentModel.Composition;
3+
using System.Windows;
4+
using System.Windows.Controls;
5+
using System.Windows.Input;
6+
using GitHub.Exports;
7+
using GitHub.Services;
8+
using GitHub.UI;
9+
using GitHub.ViewModels;
10+
using GitHub.ViewModels.Documents;
11+
using GitHub.VisualStudio.UI.Helpers;
12+
using Microsoft.VisualStudio.Shell;
13+
14+
namespace GitHub.VisualStudio.Views.Documents
15+
{
16+
[ExportViewFor(typeof(IIssueishCommentViewModel))]
17+
[PartCreationPolicy(CreationPolicy.NonShared)]
18+
public partial class IssueishCommentView : UserControl
19+
{
20+
private IDisposable subscription;
21+
22+
public IssueishCommentView()
23+
{
24+
InitializeComponent();
25+
this.Loaded += CommentView_Loaded;
26+
bodyMarkdown.PreviewMouseWheel += ScrollViewerUtilities.FixMouseWheelScroll;
27+
DataContextChanged += HandleDataContextChanged;
28+
}
29+
30+
static IVisualStudioBrowser GetBrowser()
31+
{
32+
var serviceProvider = (IGitHubServiceProvider)Package.GetGlobalService(typeof(IGitHubServiceProvider));
33+
return serviceProvider.GetService<IVisualStudioBrowser>();
34+
}
35+
36+
void DoOpenOnGitHub()
37+
{
38+
if (DataContext is IIssueishCommentViewModel vm)
39+
{
40+
GetBrowser().OpenUrl(vm.WebUrl);
41+
}
42+
}
43+
44+
private void CommentView_Loaded(object sender, System.Windows.RoutedEventArgs e)
45+
{
46+
if (buttonPanel.IsVisible)
47+
{
48+
BringIntoView();
49+
body.Focus();
50+
}
51+
}
52+
53+
private void HandleDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
54+
{
55+
subscription?.Dispose();
56+
57+
if (e.NewValue is IIssueishCommentViewModel newValue)
58+
{
59+
subscription = newValue.OpenOnGitHub.Subscribe(_ => DoOpenOnGitHub());
60+
}
61+
else
62+
{
63+
subscription = null;
64+
}
65+
}
66+
67+
private void ReplyPlaceholder_GotFocus(object sender, System.Windows.RoutedEventArgs e)
68+
{
69+
var command = (ICommand)((ICommentViewModel)DataContext)?.BeginEdit;
70+
71+
if (command?.CanExecute(null) == true)
72+
{
73+
command.Execute(null);
74+
}
75+
}
76+
77+
private void buttonPanel_IsVisibleChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
78+
{
79+
if (buttonPanel.IsVisible)
80+
{
81+
BringIntoView();
82+
}
83+
}
84+
85+
void OpenHyperlink(object sender, ExecutedRoutedEventArgs e)
86+
{
87+
Uri uri;
88+
89+
if (Uri.TryCreate(e.Parameter?.ToString(), UriKind.Absolute, out uri))
90+
{
91+
GetBrowser().OpenUrl(uri);
92+
}
93+
}
94+
95+
private void body_Loaded(object sender, System.Windows.RoutedEventArgs e)
96+
{
97+
var textBox = (PromptTextBox)sender;
98+
textBox.SelectAll();
99+
}
100+
}
101+
}

0 commit comments

Comments
 (0)