Skip to content

Commit d59cd44

Browse files
committed
generic-ui: add Avalonia impl of OAuth and Device Code
Add AvaloniaUI based implementations of the OAuth and Device Code generic UI prompts.
1 parent 6702935 commit d59cd44

File tree

10 files changed

+276
-0
lines changed

10 files changed

+276
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using GitCredentialManager.UI.ViewModels;
4+
using GitCredentialManager.UI.Views;
5+
6+
namespace GitCredentialManager.UI.Commands
7+
{
8+
public class DeviceCodeCommandImpl : DeviceCodeCommand
9+
{
10+
public DeviceCodeCommandImpl(ICommandContext context) : base(context) { }
11+
12+
protected override Task ShowAsync(DeviceCodeViewModel viewModel, CancellationToken ct)
13+
{
14+
return AvaloniaUi.ShowViewAsync<DeviceCodeView>(viewModel, GetParentHandle(), ct);
15+
}
16+
}
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using GitCredentialManager.UI.ViewModels;
4+
using GitCredentialManager.UI.Views;
5+
6+
namespace GitCredentialManager.UI.Commands
7+
{
8+
public class OAuthCommandImpl : OAuthCommand
9+
{
10+
public OAuthCommandImpl(ICommandContext context) : base(context) { }
11+
12+
protected override Task ShowAsync(OAuthViewModel viewModel, CancellationToken ct)
13+
{
14+
return AvaloniaUi.ShowViewAsync<OAuthView>(viewModel, GetParentHandle(), ct);
15+
}
16+
}
17+
}

src/shared/Git-Credential-Manager.UI.Avalonia/Controls/TesterWindow.axaml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,54 @@
4545
<Button Classes="accent" Content="Show" Click="ShowBasic" />
4646
</StackPanel>
4747
</TabItem>
48+
<TabItem Header="OAuth">
49+
<StackPanel>
50+
<Grid RowDefinitions="Auto,Auto,Auto,Auto" ColumnDefinitions="Auto,*">
51+
<Label Grid.Row="0" Grid.Column="0"
52+
Content="Window Title" />
53+
<TextBox Grid.Row="0" Grid.Column="1"
54+
x:Name="oauthTitle" Text="Git Credential Manager" />
55+
<Label Grid.Row="1" Grid.Column="0"
56+
Content="Description" />
57+
<TextBox Grid.Row="1" Grid.Column="1"
58+
x:Name="oauthDescription" Text="Sign in to 'https://example.com'" />
59+
<Label Grid.Row="2" Grid.Column="0"
60+
Content="Modes" />
61+
<StackPanel Grid.Row="2" Grid.Column="1"
62+
Orientation="Horizontal" VerticalAlignment="Center">
63+
<CheckBox Content="Browser" x:Name="oauthBrowser" MinWidth="90" IsChecked="True" />
64+
<CheckBox Content="Device Code" x:Name="oauthDeviceCode" MinWidth="80" IsChecked="True" />
65+
</StackPanel>
66+
<Label Grid.Row="3" Grid.Column="0"
67+
Content="Show Logo" />
68+
<CheckBox Grid.Row="3" Grid.Column="1"
69+
x:Name="oauthShowLogo" IsChecked="True" />
70+
</Grid>
71+
<Button Classes="accent" Content="Show" Click="ShowOAuth" />
72+
</StackPanel>
73+
</TabItem>
74+
<TabItem Header="Device Code">
75+
<StackPanel>
76+
<Grid RowDefinitions="Auto,Auto,Auto,Auto" ColumnDefinitions="Auto,*">
77+
<Label Grid.Row="0" Grid.Column="0"
78+
Content="Window Title" />
79+
<TextBox Grid.Row="0" Grid.Column="1"
80+
x:Name="deviceTitle" Text="Git Credential Manager" />
81+
<Label Grid.Row="1" Grid.Column="0"
82+
Content="User Code" />
83+
<TextBox Grid.Row="1" Grid.Column="1"
84+
x:Name="deviceUserCode" Text="ABCD-EFGH-1234" />
85+
<Label Grid.Row="2" Grid.Column="0"
86+
Content="Verification URL" />
87+
<TextBox Grid.Row="2" Grid.Column="1"
88+
x:Name="deviceVerificationUrl" Text="https://example.com/signin/device" />
89+
<Label Grid.Row="3" Grid.Column="0"
90+
Content="Show Logo" />
91+
<CheckBox Grid.Row="3" Grid.Column="1"
92+
x:Name="deviceShowLogo" IsChecked="True" />
93+
</Grid>
94+
<Button Classes="accent" Content="Show" Click="ShowDeviceCode" />
95+
</StackPanel>
96+
</TabItem>
4897
</TabControl>
4998
</Window>

src/shared/Git-Credential-Manager.UI.Avalonia/Controls/TesterWindow.axaml.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,44 @@
33
using Avalonia.Controls;
44
using Avalonia.Interactivity;
55
using Avalonia.Markup.Xaml;
6+
using GitCredentialManager.Interop.Linux;
7+
using GitCredentialManager.Interop.MacOS;
8+
using GitCredentialManager.Interop.Posix;
9+
using GitCredentialManager.Interop.Windows;
610
using GitCredentialManager.UI.ViewModels;
711
using GitCredentialManager.UI.Views;
812

913
namespace GitCredentialManager.UI.Controls
1014
{
1115
public class TesterWindow : Window
1216
{
17+
private readonly IEnvironment _environment;
18+
1319
public TesterWindow()
1420
{
1521
InitializeComponent();
1622
#if DEBUG
1723
this.AttachDevTools();
1824
#endif
25+
26+
if (PlatformUtils.IsWindows())
27+
{
28+
_environment = new WindowsEnvironment(new WindowsFileSystem());
29+
}
30+
else
31+
{
32+
IFileSystem fs;
33+
if (PlatformUtils.IsMacOS())
34+
{
35+
fs = new MacOSFileSystem();
36+
}
37+
else
38+
{
39+
fs = new LinuxFileSystem();
40+
}
41+
42+
_environment = new PosixEnvironment(fs);
43+
}
1944
}
2045

2146
private void InitializeComponent()
@@ -36,5 +61,34 @@ private void ShowBasic(object sender, RoutedEventArgs e)
3661
var window = new DialogWindow(view) {DataContext = vm};
3762
window.ShowDialog(this);
3863
}
64+
65+
private void ShowOAuth(object sender, RoutedEventArgs e)
66+
{
67+
var vm = new OAuthViewModel
68+
{
69+
Title = this.FindControl<TextBox>("oauthTitle").Text,
70+
Description = this.FindControl<TextBox>("oauthDescription").Text,
71+
ShowBrowserLogin = this.FindControl<CheckBox>("oauthBrowser").IsChecked ?? false,
72+
ShowDeviceCodeLogin = this.FindControl<CheckBox>("oauthDeviceCode").IsChecked ?? false,
73+
ShowProductHeader = this.FindControl<CheckBox>("oauthShowLogo").IsChecked ?? false
74+
};
75+
var view = new OAuthView();
76+
var window = new DialogWindow(view) {DataContext = vm};
77+
window.ShowDialog(this);
78+
}
79+
80+
private void ShowDeviceCode(object sender, RoutedEventArgs e)
81+
{
82+
var vm = new DeviceCodeViewModel(_environment)
83+
{
84+
Title = this.FindControl<TextBox>("deviceTitle").Text,
85+
UserCode = this.FindControl<TextBox>("deviceUserCode").Text,
86+
VerificationUrl = this.FindControl<TextBox>("deviceVerificationUrl").Text,
87+
ShowProductHeader = this.FindControl<CheckBox>("deviceShowLogo").IsChecked ?? false
88+
};
89+
var view = new DeviceCodeView();
90+
var window = new DialogWindow(view) {DataContext = vm};
91+
window.ShowDialog(this);
92+
}
3993
}
4094
}

src/shared/Git-Credential-Manager.UI.Avalonia/Git-Credential-Manager.UI.Avalonia.csproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@
2121
<DependentUpon>TesterWindow.axaml</DependentUpon>
2222
<SubType>Code</SubType>
2323
</Compile>
24+
<Compile Update="Views\OAuthView.axaml.cs">
25+
<DependentUpon>OAuthView.axaml</DependentUpon>
26+
<SubType>Code</SubType>
27+
</Compile>
28+
<Compile Update="Views\DeviceCodeView.axaml.cs">
29+
<DependentUpon>DeviceCodeView.axaml</DependentUpon>
30+
<SubType>Code</SubType>
31+
</Compile>
2432
</ItemGroup>
2533

2634
</Project>

src/shared/Git-Credential-Manager.UI.Avalonia/Program.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ private static void AppMain(object o)
4848
using (var app = new HelperApplication(context))
4949
{
5050
app.RegisterCommand(new CredentialsCommandImpl(context));
51+
app.RegisterCommand(new OAuthCommandImpl(context));
52+
app.RegisterCommand(new DeviceCodeCommandImpl(context));
5153

5254
int exitCode = app.RunAsync(args)
5355
.ConfigureAwait(false)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<UserControl xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:sharedVms="clr-namespace:GitCredentialManager.UI.ViewModels;assembly=gcmcoreui"
6+
mc:Ignorable="d" d:DesignWidth="420"
7+
x:Class="GitCredentialManager.UI.Views.DeviceCodeView">
8+
<Design.DataContext>
9+
<sharedVms:DeviceCodeViewModel/>
10+
</Design.DataContext>
11+
<DockPanel>
12+
<StackPanel DockPanel.Dock="Top" Margin="0,0,0,15">
13+
<StackPanel Margin="0"
14+
Orientation="Horizontal"
15+
HorizontalAlignment="Center"
16+
IsVisible="{Binding ShowProductHeader}">
17+
<Image Margin="0,0,10,0"
18+
VerticalAlignment="Center"
19+
Source="{StaticResource GcmLogo}"
20+
Width="32" Height="32" />
21+
<TextBlock Text="Git Credential Manager"
22+
VerticalAlignment="Center"
23+
FontSize="18"
24+
FontWeight="Light"/>
25+
</StackPanel>
26+
</StackPanel>
27+
28+
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
29+
<TextBlock Text="Visit the URL below, sign in, and enter the following device code to continue."
30+
Margin="0,0,0,20"
31+
TextWrapping="Wrap" TextAlignment="Center"/>
32+
<TextBox Text="{Binding UserCode}"
33+
Margin="0,0,0,20"
34+
HorizontalAlignment="Center"
35+
FontSize="24"
36+
TextAlignment="Center"
37+
Classes="label monospace"/>
38+
<Button Content="{Binding VerificationUrl}"
39+
Command="{Binding VerificationUrlCommand}"
40+
HorizontalAlignment="Center"
41+
Classes="hyperlink" />
42+
</StackPanel>
43+
</DockPanel>
44+
</UserControl>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using Avalonia.Controls;
2+
using Avalonia.Markup.Xaml;
3+
4+
namespace GitCredentialManager.UI.Views
5+
{
6+
public class DeviceCodeView : UserControl
7+
{
8+
public DeviceCodeView()
9+
{
10+
InitializeComponent();
11+
}
12+
13+
private void InitializeComponent()
14+
{
15+
AvaloniaXamlLoader.Load(this);
16+
}
17+
}
18+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<UserControl xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:vm="clr-namespace:GitCredentialManager.UI.ViewModels;assembly=gcmcoreui"
6+
mc:Ignorable="d" d:DesignWidth="420"
7+
x:Class="GitCredentialManager.UI.Views.OAuthView">
8+
<Design.DataContext>
9+
<vm:OAuthViewModel/>
10+
</Design.DataContext>
11+
<DockPanel>
12+
<StackPanel DockPanel.Dock="Top" Margin="10,0,10,10">
13+
<StackPanel Margin="0"
14+
Orientation="Horizontal"
15+
HorizontalAlignment="Center"
16+
IsVisible="{Binding ShowProductHeader}">
17+
<Image Margin="0,0,10,0"
18+
VerticalAlignment="Center"
19+
Source="{StaticResource GcmLogo}"
20+
Width="32" Height="32" />
21+
<TextBlock Text="Git Credential Manager"
22+
VerticalAlignment="Center"
23+
FontSize="18"
24+
FontWeight="Light"/>
25+
</StackPanel>
26+
27+
<TextBlock Text="{Binding Description}"
28+
FontSize="14"
29+
HorizontalAlignment="Center"
30+
TextWrapping="Wrap"
31+
Margin="0,15,0,15"/>
32+
</StackPanel>
33+
34+
<StackPanel Margin="20,0">
35+
<Button Content="Sign in with your browser"
36+
IsDefault="True"
37+
Command="{Binding SignInBrowserCommand}"
38+
HorizontalAlignment="Center"
39+
Classes="accent"
40+
Margin="0,0,0,10"
41+
IsVisible="{Binding ShowBrowserLogin}"/>
42+
<Button Content="Sign in with a code"
43+
IsDefault="True"
44+
Command="{Binding SignInDeviceCodeCommand}"
45+
HorizontalAlignment="Center"
46+
IsVisible="{Binding ShowDeviceCodeLogin}"/>
47+
</StackPanel>
48+
</DockPanel>
49+
</UserControl>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using Avalonia.Controls;
2+
using Avalonia.Markup.Xaml;
3+
4+
namespace GitCredentialManager.UI.Views
5+
{
6+
public class OAuthView : UserControl
7+
{
8+
public OAuthView()
9+
{
10+
InitializeComponent();
11+
}
12+
13+
private void InitializeComponent()
14+
{
15+
AvaloniaXamlLoader.Load(this);
16+
}
17+
}
18+
}

0 commit comments

Comments
 (0)