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

Commit 7cfc202

Browse files
author
Steven Kirk
committed
Merge branch 'feature/sso' of https://github.com/github/VisualStudio into feature/sso
2 parents cc9f341 + 428edf4 commit 7cfc202

File tree

308 files changed

+6584
-7507
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

308 files changed

+6584
-7507
lines changed

.gitmodules

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,4 @@
1212
url = https://github.com/editor-tools/Akavache
1313
[submodule "script"]
1414
path = script
15-
url = [email protected]:github/VisualStudioBuildScripts
16-
[submodule "submodules/Rothko"]
17-
path = submodules/Rothko
18-
url = https://github.com/editor-tools/Rothko.git
15+
url = [email protected]:github/VisualStudioBuildScripts

GitHubVS.sln

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHub.Api", "src\GitHub.Ap
5858
EndProject
5959
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHub.Exports.Reactive", "src\GitHub.Exports.Reactive\GitHub.Exports.Reactive.csproj", "{E4ED0537-D1D9-44B6-9212-3096D7C3F7A1}"
6060
EndProject
61-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesignTimeStyleHelper", "src\DesignTimeStyleHelper\DesignTimeStyleHelper.csproj", "{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}"
62-
EndProject
6361
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Octokit", "Octokit", "{1E7F7253-A6AF-43C4-A955-37BEDDA01AC0}"
6462
EndProject
6563
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Octokit", "submodules\octokit.net\Octokit\Octokit.csproj", "{08DD4305-7787-4823-A53F-4D0F725A07F3}"
@@ -106,10 +104,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHub.InlineReviews.UnitTe
106104
EndProject
107105
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHub.Logging", "src\GitHub.Logging\GitHub.Logging.csproj", "{8D73575A-A89F-47CC-B153-B47DD06837F0}"
108106
EndProject
109-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Rothko", "Rothko", "{8B9A34C6-0D62-4D49-9606-1AB838923A74}"
110-
EndProject
111-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rothko", "submodules\Rothko\src\Rothko.csproj", "{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}"
112-
EndProject
113107
Global
114108
GlobalSection(SolutionConfigurationPlatforms) = preSolution
115109
Debug|Any CPU = Debug|Any CPU
@@ -219,16 +213,6 @@ Global
219213
{E4ED0537-D1D9-44B6-9212-3096D7C3F7A1}.Release|Any CPU.Build.0 = Release|Any CPU
220214
{E4ED0537-D1D9-44B6-9212-3096D7C3F7A1}.ReleaseWithoutVsix|Any CPU.ActiveCfg = Release|Any CPU
221215
{E4ED0537-D1D9-44B6-9212-3096D7C3F7A1}.ReleaseWithoutVsix|Any CPU.Build.0 = Release|Any CPU
222-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
223-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
224-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.DebugCodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU
225-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.DebugCodeAnalysis|Any CPU.Build.0 = Debug|Any CPU
226-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.DebugWithoutVsix|Any CPU.ActiveCfg = Debug|Any CPU
227-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.DebugWithoutVsix|Any CPU.Build.0 = Debug|Any CPU
228-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
229-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.Release|Any CPU.Build.0 = Release|Any CPU
230-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.ReleaseWithoutVsix|Any CPU.ActiveCfg = Release|Any CPU
231-
{B1F5C227-456F-437D-BD5F-4C11B7A8D1A0}.ReleaseWithoutVsix|Any CPU.Build.0 = Release|Any CPU
232216
{08DD4305-7787-4823-A53F-4D0F725A07F3}.Debug|Any CPU.ActiveCfg = Release|Any CPU
233217
{08DD4305-7787-4823-A53F-4D0F725A07F3}.Debug|Any CPU.Build.0 = Release|Any CPU
234218
{08DD4305-7787-4823-A53F-4D0F725A07F3}.DebugCodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
@@ -419,16 +403,6 @@ Global
419403
{8D73575A-A89F-47CC-B153-B47DD06837F0}.Release|Any CPU.Build.0 = Release|Any CPU
420404
{8D73575A-A89F-47CC-B153-B47DD06837F0}.ReleaseWithoutVsix|Any CPU.ActiveCfg = Release|Any CPU
421405
{8D73575A-A89F-47CC-B153-B47DD06837F0}.ReleaseWithoutVsix|Any CPU.Build.0 = Release|Any CPU
422-
{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
423-
{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
424-
{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}.DebugCodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU
425-
{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}.DebugCodeAnalysis|Any CPU.Build.0 = Debug|Any CPU
426-
{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}.DebugWithoutVsix|Any CPU.ActiveCfg = Debug|Any CPU
427-
{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}.DebugWithoutVsix|Any CPU.Build.0 = Debug|Any CPU
428-
{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
429-
{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}.Release|Any CPU.Build.0 = Release|Any CPU
430-
{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}.ReleaseWithoutVsix|Any CPU.ActiveCfg = Release|Any CPU
431-
{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}.ReleaseWithoutVsix|Any CPU.Build.0 = Release|Any CPU
432406
EndGlobalSection
433407
GlobalSection(SolutionProperties) = preSolution
434408
HideSolutionNode = FALSE
@@ -452,7 +426,5 @@ Global
452426
{7B835A7D-CF94-45E8-B191-96F5A4FE26A8} = {8A7DA2E7-262B-4581-807A-1C45CE79CDFD}
453427
{110B206F-8554-4B51-BF86-94DAA32F5E26} = {8A7DA2E7-262B-4581-807A-1C45CE79CDFD}
454428
{17EB676B-BB91-48B5-AA59-C67695C647C2} = {8A7DA2E7-262B-4581-807A-1C45CE79CDFD}
455-
{8B9A34C6-0D62-4D49-9606-1AB838923A74} = {1E7F7253-A6AF-43C4-A955-37BEDDA01AB8}
456-
{4A84E568-CA86-4510-8CD0-90D3EF9B65F9} = {8B9A34C6-0D62-4D49-9606-1AB838923A74}
457429
EndGlobalSection
458430
EndGlobal

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: '2.3.5.{build}'
1+
version: '2.3.7.{build}'
22
skip_tags: true
33
install:
44
- ps: |

build.cmd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
powershell -ExecutionPolicy Unrestricted scripts\build.ps1 %1
1+
@if "%1" == "" echo Please specify Debug or Release && EXIT /B
2+
powershell -ExecutionPolicy Unrestricted scripts\build.ps1 -Package:$true -Config:%1

docs/contributing/creating-an-empty-repository-from-visual-studio.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Creating an empty repository from Visual Studio
22

3-
1. [Sign in](authenticating-to-github) to GitHub.
3+
1. [Sign in](../getting-started/authenticating-to-github.md) to GitHub.
44

55
2. Open **Team Explorer** by clicking on its tab next to *Solution Explorer*, or via the *View* menu.
66

docs/contributing/creating-gists.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
GitHub for Visual Studio enables easy creation of gists directly from the Visual Studio Editor.
44

5-
1. [Sign in](authenticating-to-github) to GitHub.
5+
1. [Sign in](../getting-started/authenticating-to-github.md) to GitHub.
66

77
2. Open a file in the Visual Studio text editor.
88

docs/contributing/viewing-the-pull-requests-for-a-repository.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
GitHub for Visual Studio exposes the pull requests for the current repository and lets you create new pull requests and review pull requests from other contributors.
44

5-
1. [Sign in](authenticating-to-github) to GitHub.
5+
1. [Sign in](../getting-started/authenticating-to-github.md) to GitHub.
66
2. Open a solution in a GitHub repository.
77
3. Open **Team Explorer** and click the **Pull Requests** button to open the **GitHub** pane.
88
![Pull Requests button in the Team Explorer pane](images/pull-requests-button2.png)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Dialog Views with Connections
2+
3+
Some dialog views need a connection to operate - if there is no connection, a login dialog should be shown: for example, clicking Create Gist without a connection will first prompt the user to log in.
4+
5+
Achieving this is simple, first make your view model interface implement `IConnectionInitializedViewModel` and do any initialization that requires a connection in the `InitializeAsync` method in your view model:
6+
7+
```csharp
8+
public Task InitializeAsync(IConnection connection)
9+
{
10+
// .. at this point, you're guaranteed to have a connection.
11+
}
12+
```
13+
14+
To show the dialog, call `IShowDialogService.ShowWithFirstConnection` instead of `Show`:
15+
16+
```csharp
17+
public async Task ShowExampleDialog()
18+
{
19+
var viewModel = serviceProvider.ExportProvider.GetExportedValue<IExampleDialogViewModel>();
20+
await showDialog.ShowWithFirstConnection(viewModel);
21+
}
22+
```
23+
24+
`ShowFirstConnection` first checks if there are any logged in connections. If there are, the first logged in connection will be passed to `InitializeAsync` and the view shown immediately. If there are no logged in connections, the login view will first be shown. Once the user has successfully logged in, the new connection will be passed to `InitalizeAsync` and the view shown.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# How ViewModels are Turned into Views
2+
3+
We make use of the [MVVM pattern](https://msdn.microsoft.com/en-us/library/ff798384.aspx), in which application level code is not aware of the view level. MVVM takes advantage of the fact that `DataTemplate`s can be used to create views from view models.
4+
5+
## DataTemplates
6+
7+
[`DataTemplate`](https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/data-templating-overview)s are a WPF feature that allow you to define the presentation of your data. Consider a simple view model:
8+
9+
```csharp
10+
public class ViewModel
11+
{
12+
public string Greeting => "Hello World!";
13+
}
14+
```
15+
16+
And a window:
17+
18+
```csharp
19+
public class MainWindow : Window
20+
{
21+
public MainWindow()
22+
{
23+
DataContext = new ViewModel();
24+
InitializeComponent();
25+
}
26+
}
27+
```
28+
29+
```xml
30+
<Window x:Class="MyApp.MainWindow"
31+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
32+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33+
xmlns:local="clr-namespace:MyApp"
34+
Content="{Binding}">
35+
<Window>
36+
37+
```
38+
39+
Here we're binding the `Content` of the `Window` to the `Window.DataContext`, which we're setting in the constructor to be an instance of `ViewModel`.
40+
41+
One can choose to display the `ViewModel` instance in any way we want by using a `DataTemplate`:
42+
43+
```xml
44+
<Window x:Class="MyApp.MainWindow"
45+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
46+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
47+
xmlns:local="clr-namespace:MyApp"
48+
Content="{Binding}">
49+
<Window.Resources>
50+
<DataTemplate DataType="{x:Type local:ViewModel}">
51+
52+
<!-- Display ViewModel.Greeting in a red border with rounded corners -->
53+
<Border Background="Red" CornerRadius="8">
54+
<TextBlock Binding="{Binding Greeting}"/>
55+
</Border>
56+
57+
</DataTemplate>
58+
</Window.Resources>
59+
</Window>
60+
```
61+
62+
This is the basis for converting view models to views.
63+
64+
## ViewLocator
65+
66+
There are currently two top-level controls for our UI:
67+
68+
- [GitHubDialogWindow](../src/GitHub.VisualStudio/Views/Dialog/GitHubDialogWindow.xaml) for the dialog which shows the login, clone, etc views
69+
- [GitHubPaneView](../src/GitHub.VisualStudio/Views/GitHubPane/GitHubPaneView.xaml) for the GitHub pane
70+
71+
In the resources for each of these top-level controls we define a `DataTemplate` like so:
72+
73+
```xml
74+
<views:ViewLocator x:Key="viewLocator"/>
75+
<DataTemplate DataType="{x:Type vm:ViewModelBase}">
76+
<ContentControl Content="{Binding Converter={StaticResource viewLocator}}"/>
77+
</DataTemplate>
78+
```
79+
80+
The `DataTemplate.DataType` here applies the template to all classes inherited from [`GitHub.ViewModels.ViewModelBase`](../src/GitHub.Exports.Reactive/ViewModels/ViewModelBase.cs) [1]. The template defines a single `ContentControl` whose contents are created by a `ViewLocator`.
81+
82+
The [`ViewLocator`](../src/GitHub.VisualStudio/Views/ViewLocator.cs) class is an `IValueConverter` which then creates an instance of the appropriate view for the view model using MEF.
83+
84+
And thus a view model becomes a view.
85+
86+
[1]: it would be nice to make it apply to all classes that inherit `IViewModel` but unfortunately WPF's `DataTemplate`s don't work with interfaces.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Implementing a Dialog View
2+
3+
GitHub for Visual Studio has a common dialog which is used to show the login, clone, create repository etc. operations. To add a new view to the dialog and show the dialog with this view, you need to do the following:
4+
5+
## Create a View Model and Interface
6+
7+
- Create an interface for the view model that implements `IDialogContentViewModel` in `GitHub.Exports.Reactive\ViewModels\Dialog`
8+
- Create a view model that inherits from `NewViewModelBase` and implements the interface in `GitHub.App\ViewModels\Dialog`
9+
- Export the view model with the interface as the contract and add a `[PartCreationPolicy(CreationPolicy.NonShared)]` attribute
10+
11+
A minimal example that just exposes a command that will dismiss the dialog:
12+
13+
```csharp
14+
using System;
15+
using ReactiveUI;
16+
17+
namespace GitHub.ViewModels.Dialog
18+
{
19+
public interface IExampleDialogViewModel : IDialogContentViewModel
20+
{
21+
ReactiveCommand<object> Dismiss { get; }
22+
}
23+
}
24+
```
25+
26+
```csharp
27+
using System;
28+
using System.ComponentModel.Composition;
29+
using ReactiveUI;
30+
31+
namespace GitHub.ViewModels.Dialog
32+
{
33+
[Export(typeof(IExampleDialogViewModel))]
34+
[PartCreationPolicy(CreationPolicy.NonShared)]
35+
public class ExampleDialogViewModel : ViewModelBase, IExampleDialogViewModel
36+
{
37+
[ImportingConstructor]
38+
public ExampleDialogViewModel()
39+
{
40+
Dismiss = ReactiveCommand.Create();
41+
}
42+
43+
public string Title => "Example Dialog";
44+
45+
public ReactiveCommand<object> Dismiss { get; }
46+
47+
public IObservable<object> Done => Dismiss;
48+
}
49+
}
50+
```
51+
52+
## Create a View
53+
54+
- Create a WPF `UserControl` under `GitHub.VisualStudio\Views\Dialog`
55+
- Add an `ExportViewFor` attribute with the type of the view model interface
56+
- Add a `PartCreationPolicy(CreationPolicy.NonShared)]` attribute
57+
58+
Continuing the example above:
59+
60+
```xml
61+
<UserControl x:Class="GitHub.VisualStudio.Views.Dialog.ExampleDialogView"
62+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
63+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
64+
<Button Command="{Binding Dismiss}" HorizontalAlignment="Center" VerticalAlignment="Center">
65+
Dismiss
66+
</Button>
67+
</UserControl>
68+
```
69+
70+
```csharp
71+
using System.ComponentModel.Composition;
72+
using System.Windows.Controls;
73+
using GitHub.Exports;
74+
using GitHub.ViewModels.Dialog;
75+
76+
namespace GitHub.VisualStudio.Views.Dialog
77+
{
78+
[ExportViewFor(typeof(IExampleDialogViewModel))]
79+
[PartCreationPolicy(CreationPolicy.NonShared)]
80+
public partial class ExampleDialogView : UserControl
81+
{
82+
public ExampleDialogView()
83+
{
84+
InitializeComponent();
85+
}
86+
}
87+
}
88+
```
89+
90+
## Show the Dialog!
91+
92+
To show the dialog you will need an instance of the `IShowDialogService` service. Once you have that, simply call the `Show` method with an instance of your view model.
93+
94+
```csharp
95+
var viewModel = new ExampleDialogViewModel();
96+
showDialog.Show(viewModel)
97+
```
98+
99+
## Optional: Add a method to `DialogService`
100+
101+
Creating a view model like this may be the right thing to do, but it's not very reusable or testable. If you want your dialog to be easy reusable, add a method to `DialogService`:
102+
103+
```csharp
104+
public async Task ShowExampleDialog()
105+
{
106+
var viewModel = factory.CreateViewModel<IExampleDialogViewModel>();
107+
await showDialog.Show(viewModel);
108+
}
109+
```
110+
111+
Obviously, add this method to `IDialogService` too.
112+
113+
Note that these methods are `async` - this means that if you need to do asynchronous initialization of your view model, you can do it here before calling `showDialog`.

0 commit comments

Comments
 (0)