Skip to content

Commit e09b656

Browse files
committed
gitlab: add WPF-based UI helper on Windows
Implement a WPF-based UI helper for GitLab and include this in the Windows installers.
1 parent c7d5faa commit e09b656

File tree

12 files changed

+407
-0
lines changed

12 files changed

+407
-0
lines changed

Git-Credential-Manager.sln

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitLab.UI", "src\shared\Git
6767
EndProject
6868
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitLab.UI.Avalonia", "src\shared\GitLab.UI.Avalonia\GitLab.UI.Avalonia.csproj", "{47186A50-8889-4FC7-8A05-F9FCE7F8F4AE}"
6969
EndProject
70+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitLab.UI.Windows", "src\windows\GitLab.UI.Windows\GitLab.UI.Windows.csproj", "{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E}"
71+
EndProject
7072
Global
7173
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7274
Debug|Any CPU = Debug|Any CPU
@@ -469,6 +471,16 @@ Global
469471
{47186A50-8889-4FC7-8A05-F9FCE7F8F4AE}.MacRelease|Any CPU.Build.0 = Release|Any CPU
470472
{47186A50-8889-4FC7-8A05-F9FCE7F8F4AE}.WindowsRelease|Any CPU.ActiveCfg = Release|Any CPU
471473
{47186A50-8889-4FC7-8A05-F9FCE7F8F4AE}.WindowsRelease|Any CPU.Build.0 = Release|Any CPU
474+
{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
475+
{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E}.MacDebug|Any CPU.ActiveCfg = Debug|Any CPU
476+
{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E}.Release|Any CPU.ActiveCfg = Release|Any CPU
477+
{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E}.WindowsDebug|Any CPU.ActiveCfg = Debug|Any CPU
478+
{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E}.WindowsDebug|Any CPU.Build.0 = Debug|Any CPU
479+
{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E}.LinuxDebug|Any CPU.ActiveCfg = Debug|Any CPU
480+
{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E}.LinuxRelease|Any CPU.ActiveCfg = Release|Any CPU
481+
{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E}.MacRelease|Any CPU.ActiveCfg = Release|Any CPU
482+
{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E}.WindowsRelease|Any CPU.ActiveCfg = Release|Any CPU
483+
{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E}.WindowsRelease|Any CPU.Build.0 = Release|Any CPU
472484
EndGlobalSection
473485
GlobalSection(SolutionProperties) = preSolution
474486
HideSolutionNode = FALSE
@@ -505,6 +517,7 @@ Global
505517
{1AF9F7C5-FA2E-48F1-B216-4D5E9A27F393} = {D5277A0E-997E-453A-8CB9-4EFCC8B16A29}
506518
{9AFD88E2-7E2C-46DA-9D38-4342086426D3} = {D5277A0E-997E-453A-8CB9-4EFCC8B16A29}
507519
{47186A50-8889-4FC7-8A05-F9FCE7F8F4AE} = {D5277A0E-997E-453A-8CB9-4EFCC8B16A29}
520+
{83EAC1F9-8E1F-41FC-8FC9-2C452452D64E} = {66722747-1B61-40E4-A89B-1AC8E6D62EA9}
508521
EndGlobalSection
509522
GlobalSection(ExtensibilityGlobals) = postSolution
510523
SolutionGuid = {0EF9FC65-E6BA-45D4-A455-262A9EA4366B}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
3+
<ResourceDictionary.MergedDictionaries>
4+
<ResourceDictionary Source="pack://application:,,,/gcmcoreuiwpf;component/Assets/Styles.xaml"/>
5+
</ResourceDictionary.MergedDictionaries>
6+
</ResourceDictionary>
41.4 KB
Loading
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using GitLab.UI.ViewModels;
4+
using GitLab.UI.Views;
5+
using GitCredentialManager;
6+
using GitCredentialManager.UI;
7+
8+
namespace GitLab.UI.Commands
9+
{
10+
public class CredentialsCommandImpl : CredentialsCommand
11+
{
12+
public CredentialsCommandImpl(ICommandContext context) : base(context) { }
13+
14+
protected override Task ShowAsync(CredentialsViewModel viewModel, CancellationToken ct)
15+
{
16+
return Gui.ShowDialogWindow(viewModel, () => new CredentialsView(), GetParentHandle());
17+
}
18+
}
19+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<Window x:Class="GitLab.UI.Controls.TesterWindow"
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+
mc:Ignorable="d"
7+
ResizeMode="NoResize" Width="550" SizeToContent="Height"
8+
Title="GitLab Authentication Dialog Tester">
9+
<TabControl Margin="5,10">
10+
<TabItem Header="Credentials">
11+
<StackPanel>
12+
<Grid>
13+
<Grid.RowDefinitions>
14+
<RowDefinition Height="Auto"/>
15+
<RowDefinition Height="Auto"/>
16+
<RowDefinition Height="Auto"/>
17+
</Grid.RowDefinitions>
18+
<Grid.ColumnDefinitions>
19+
<ColumnDefinition Width="Auto"/>
20+
<ColumnDefinition Width="*"/>
21+
</Grid.ColumnDefinitions>
22+
<Label Grid.Row="0" Grid.Column="0"
23+
Content="Auth Modes" />
24+
<StackPanel Grid.Row="0" Grid.Column="1"
25+
Orientation="Horizontal" VerticalAlignment="Center">
26+
<CheckBox Content="Browser" x:Name="useBrowser" MinWidth="90" IsChecked="True" />
27+
<CheckBox Content="PAT" x:Name="usePat" MinWidth="80" IsChecked="True" />
28+
<CheckBox Content="Basic" x:Name="useBasic" MinWidth="80" />
29+
</StackPanel>
30+
<Label Grid.Row="1" Grid.Column="0"
31+
Content="Instance URL" />
32+
<TextBox Grid.Row="1" Grid.Column="1"
33+
x:Name="instanceUrl" />
34+
<Label Grid.Row="2" Grid.Column="0"
35+
Content="Username" />
36+
<TextBox Grid.Row="2" Grid.Column="1"
37+
x:Name="username" />
38+
</Grid>
39+
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"
40+
Margin="0,10">
41+
<Button Content="Show" Click="ShowCredentials"
42+
Padding="8,4"/>
43+
</StackPanel>
44+
</StackPanel>
45+
</TabItem>
46+
</TabControl>
47+
</Window>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Windows;
2+
using GitLab.UI.ViewModels;
3+
using GitLab.UI.Views;
4+
using GitCredentialManager.Interop.Windows;
5+
using GitCredentialManager.UI.Controls;
6+
7+
namespace GitLab.UI.Controls
8+
{
9+
public partial class TesterWindow : Window
10+
{
11+
private readonly WindowsEnvironment _environment = new WindowsEnvironment(new WindowsFileSystem());
12+
13+
public TesterWindow()
14+
{
15+
InitializeComponent();
16+
}
17+
18+
private void ShowCredentials(object sender, RoutedEventArgs e)
19+
{
20+
var vm = new CredentialsViewModel(_environment)
21+
{
22+
ShowBrowserLogin = useBrowser.IsChecked ?? false,
23+
ShowTokenLogin = usePat.IsChecked ?? false,
24+
ShowBasicLogin = useBasic.IsChecked ?? false,
25+
Url = instanceUrl.Text,
26+
UserName = username.Text
27+
};
28+
var view = new CredentialsView();
29+
var window = new DialogWindow(view) { DataContext = vm };
30+
window.ShowDialog();
31+
}
32+
}
33+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net472</TargetFramework>
6+
<UseWPF>true</UseWPF>
7+
<RootNamespace>GitLab.UI</RootNamespace>
8+
<AssemblyName>GitLab.UI</AssemblyName>
9+
<StartupObject>GitLab.UI.Program</StartupObject>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<ProjectReference Include="..\..\shared\GitLab.UI\GitLab.UI.csproj" />
14+
<ProjectReference Include="..\..\shared\Core.UI\Core.UI.csproj" />
15+
<ProjectReference Include="..\Core.UI.Windows\Core.UI.Windows.csproj" />
16+
</ItemGroup>
17+
18+
<ItemGroup Condition="'$(OSPlatform)' != 'windows'">
19+
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" />
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<Resource Include="Assets\gitlab-logo-gray-rgb.png" />
24+
</ItemGroup>
25+
26+
</Project>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using GitLab.UI.Commands;
4+
using GitLab.UI.Controls;
5+
using GitCredentialManager;
6+
using GitCredentialManager.UI;
7+
8+
namespace GitLab.UI
9+
{
10+
public static class Program
11+
{
12+
public static async Task Main(string[] args)
13+
{
14+
string appPath = ApplicationBase.GetEntryApplicationPath();
15+
using (var context = new CommandContext(appPath))
16+
using (var app = new HelperApplication(context))
17+
{
18+
if (args.Length == 0)
19+
{
20+
await Gui.ShowWindow(() => new TesterWindow(), IntPtr.Zero);
21+
return;
22+
}
23+
24+
app.RegisterCommand(new CredentialsCommandImpl(context));
25+
26+
int exitCode = app.RunAsync(args)
27+
.ConfigureAwait(false)
28+
.GetAwaiter()
29+
.GetResult();
30+
31+
Environment.Exit(exitCode);
32+
}
33+
}
34+
}
35+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<UserControl x:Class="GitLab.UI.Views.CredentialsView"
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:viewModels="clr-namespace:GitLab.UI.ViewModels;assembly=GitLab.UI.Shared"
7+
xmlns:converters="clr-namespace:GitCredentialManager.UI.Converters;assembly=gcmcoreuiwpf"
8+
xmlns:controls="clr-namespace:GitLab.UI.Controls"
9+
xmlns:sharedControls="clr-namespace:GitCredentialManager.UI.Controls;assembly=gcmcoreuiwpf"
10+
mc:Ignorable="d"
11+
d:DataContext="{d:DesignInstance viewModels:CredentialsViewModel}"
12+
d:DesignWidth="300">
13+
<UserControl.Resources>
14+
<ResourceDictionary>
15+
<ResourceDictionary.MergedDictionaries>
16+
<ResourceDictionary Source="../Assets/Styles.xaml"/>
17+
</ResourceDictionary.MergedDictionaries>
18+
<converters:NonEmptyStringToVisibleConverter x:Key="NonEmptyStringToVisibleConverter"/>
19+
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
20+
</ResourceDictionary>
21+
</UserControl.Resources>
22+
23+
<DockPanel>
24+
<StackPanel DockPanel.Dock="Top" Margin="0,0,0,15">
25+
<!-- TODO: replace with GitLab logo -->
26+
<Image Source="/Assets/gitlab-logo-gray-rgb.png"
27+
HorizontalAlignment="Center"
28+
Height="80"/>
29+
<TextBlock Text="Sign in"
30+
HorizontalAlignment="Center"
31+
FontSize="16"
32+
FontWeight="Light"
33+
Margin="0,0,0,5" />
34+
<StackPanel Visibility="{Binding Url, Converter={StaticResource NonEmptyStringToVisibleConverter}}"
35+
Margin="0,10,0,0">
36+
<TextBlock Text="{Binding Url}"
37+
HorizontalAlignment="Center"
38+
FontSize="14"/>
39+
</StackPanel>
40+
</StackPanel>
41+
42+
<WrapPanel DockPanel.Dock="Bottom" HorizontalAlignment="Center" VerticalAlignment="Center"
43+
Margin="0,20,0,0">
44+
<TextBlock Text="Don't have an account? "
45+
Margin="0,0,5,0"
46+
FontSize="14">
47+
<Hyperlink Command="{Binding SignUpCommand}">Sign Up</Hyperlink>
48+
</TextBlock>
49+
</WrapPanel>
50+
51+
<TabControl x:Name="tabControl"
52+
BorderThickness="0"
53+
Background="Transparent">
54+
<TabControl.Resources>
55+
<Style TargetType="TabPanel">
56+
<Setter Property="HorizontalAlignment" Value="Center"/>
57+
</Style>
58+
<Style TargetType="TabItem">
59+
<Setter Property="Template">
60+
<Setter.Value>
61+
<ControlTemplate TargetType="TabItem">
62+
<Border Name="Border" Margin="10,0,10,10"
63+
BorderThickness="0,0,0,2"
64+
BorderBrush="Transparent">
65+
<ContentPresenter x:Name="ContentSite"
66+
VerticalAlignment="Center"
67+
HorizontalAlignment="Center"
68+
ContentSource="Header"
69+
Margin="0,0,0,5"/>
70+
</Border>
71+
<ControlTemplate.Triggers>
72+
<Trigger Property="IsSelected" Value="True">
73+
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource AccentBrush}"/>
74+
</Trigger>
75+
</ControlTemplate.Triggers>
76+
</ControlTemplate>
77+
</Setter.Value>
78+
</Setter>
79+
</Style>
80+
</TabControl.Resources>
81+
82+
<TabItem IsEnabled="{Binding ShowBrowserLogin}"
83+
Visibility="{Binding ShowBrowserLogin, Converter={StaticResource BooleanToVisibilityConverter}}">
84+
<TabItem.Header>
85+
<TextBlock Text="{Binding OAuthModeTitle}" FontSize="12" />
86+
</TabItem.Header>
87+
<StackPanel x:Name="oauthPanel"
88+
Margin="0,10">
89+
<Button x:Name="browserButton"
90+
Content="Sign in with your browser"
91+
IsDefault="True"
92+
Command="{Binding SignInBrowserCommand}"
93+
HorizontalAlignment="Center"
94+
Margin="0,0,0,10"
95+
Style="{StaticResource AccentButton}"/>
96+
</StackPanel>
97+
</TabItem>
98+
99+
<TabItem IsEnabled="{Binding ShowTokenLogin}"
100+
Visibility="{Binding ShowTokenLogin, Converter={StaticResource BooleanToVisibilityConverter}}">
101+
<TabItem.Header>
102+
<TextBlock Text="Token" FontSize="12" />
103+
</TabItem.Header>
104+
<StackPanel x:Name="tokenPanel"
105+
Margin="0,10">
106+
<sharedControls:PromptTextBox x:Name="patUserNameTextBox"
107+
Margin="0,0,0,10"
108+
PromptText="Username or email (optional)"
109+
Text="{Binding TokenUserName}"/>
110+
<sharedControls:PasswordPromptTextBox x:Name="tokenTextBox"
111+
Margin="0,0,0,10"
112+
PromptText="Personal access token"
113+
Password="{Binding Token, UpdateSourceTrigger=PropertyChanged, Delay=300, Mode=OneWayToSource}"/>
114+
<Button Content="Sign in"
115+
IsDefault="True"
116+
Command="{Binding SignInTokenCommand}"
117+
HorizontalAlignment="Center"
118+
Style="{StaticResource AccentButton}"/>
119+
</StackPanel>
120+
</TabItem>
121+
122+
<TabItem IsEnabled="{Binding ShowBasicLogin}"
123+
Visibility="{Binding ShowBasicLogin, Converter={StaticResource BooleanToVisibilityConverter}}">
124+
<TabItem.Header>
125+
<TextBlock Text="Password" FontSize="12" />
126+
</TabItem.Header>
127+
<StackPanel x:Name="basicPanel"
128+
Margin="0,10">
129+
<sharedControls:PromptTextBox x:Name="userNameTextBox"
130+
Margin="0,0,0,10"
131+
PromptText="Username or email"
132+
Text="{Binding UserName}"/>
133+
<sharedControls:PasswordPromptTextBox x:Name="passwordTextBox"
134+
Margin="0,0,0,10"
135+
PromptText="Password"
136+
Password="{Binding Password, UpdateSourceTrigger=PropertyChanged, Delay=300, Mode=OneWayToSource}"/>
137+
<Button Content="Sign in"
138+
IsDefault="True"
139+
Command="{Binding SignInBasicCommand}"
140+
HorizontalAlignment="Center"
141+
Style="{StaticResource AccentButton}"/>
142+
</StackPanel>
143+
</TabItem>
144+
</TabControl>
145+
</DockPanel>
146+
</UserControl>

0 commit comments

Comments
 (0)