Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0daea96

Browse files
committedFeb 7, 2025·
feat: Sign in Window views & view models
1 parent 4c6d2bd commit 0daea96

12 files changed

+403
-16
lines changed
 

‎App/App.csproj

+18
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,24 @@
4141
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.250108002" />
4242
</ItemGroup>
4343

44+
<ItemGroup>
45+
<Page Update="SignInTokenPage.xaml">
46+
<Generator>MSBuild:Compile</Generator>
47+
</Page>
48+
</ItemGroup>
49+
50+
<ItemGroup>
51+
<Page Update="SignInWindow.xaml">
52+
<Generator>MSBuild:Compile</Generator>
53+
</Page>
54+
</ItemGroup>
55+
56+
<ItemGroup>
57+
<Page Update="SignInURLPage.xaml">
58+
<Generator>MSBuild:Compile</Generator>
59+
</Page>
60+
</ItemGroup>
61+
4462
<ItemGroup>
4563
<Page Update="TrayIcon.xaml">
4664
<Generator>MSBuild:Compile</Generator>

‎App/App.xaml.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
1+
using Coder.Desktop.App.ViewModels;
12
using Microsoft.UI.Xaml;
23

34
namespace Coder.Desktop.App;
45

56
public partial class App : Application
67
{
78
private TrayWindow? TrayWindow;
9+
public SignInViewModel SignInViewModel { get; }
810

911
public App()
1012
{
13+
SignInViewModel = new SignInViewModel();
1114
InitializeComponent();
1215
}
1316

1417
private bool HandleClosedEvents { get; } = true;
1518

1619
protected override void OnLaunched(LaunchActivatedEventArgs args)
1720
{
18-
TrayWindow = new TrayWindow();
21+
TrayWindow = new TrayWindow(SignInViewModel);
1922
TrayWindow.Closed += (sender, args) =>
2023
{
2124
// TODO: wire up HandleClosedEvents properly

‎App/DisplayScale.cs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using Microsoft.UI.Xaml;
3+
using WinRT.Interop;
4+
using System.Runtime.InteropServices;
5+
6+
namespace Coder.Desktop.App;
7+
8+
/// <summary>
9+
/// A static utility class to house methods related to the visual scale of the display monitor.
10+
/// </summary>
11+
public static class DisplayScale
12+
{
13+
public static double WindowScale(Window win)
14+
{
15+
var hwnd = WindowNative.GetWindowHandle(win);
16+
var dpi = NativeApi.GetDpiForWindow(hwnd);
17+
if (dpi == 0) return 1; // assume scale of 1
18+
return dpi / 96.0; // 96 DPI == 1
19+
}
20+
21+
public class NativeApi
22+
{
23+
[DllImport("user32.dll")]
24+
public static extern int GetDpiForWindow(IntPtr hwnd);
25+
}
26+
}

‎App/SignInTokenPage.xaml

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Page
3+
x:Class="Coder.Desktop.App.SignInTokenPage"
4+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
5+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
6+
xmlns:local="using:Coder.Desktop.App"
7+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
8+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9+
mc:Ignorable="d"
10+
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
11+
12+
<StackPanel
13+
Orientation="Vertical"
14+
HorizontalAlignment="Stretch"
15+
VerticalAlignment="Top"
16+
Padding="20"
17+
Spacing="10">
18+
19+
<TextBlock
20+
Text="Coder Desktop"
21+
FontSize="24"
22+
VerticalAlignment="Center"
23+
HorizontalAlignment="Center"/>
24+
25+
<Grid>
26+
<Grid.ColumnDefinitions>
27+
<ColumnDefinition Width="Auto" />
28+
<ColumnDefinition Width="*" />
29+
</Grid.ColumnDefinitions>
30+
<Grid.RowDefinitions>
31+
<RowDefinition Height="1*" />
32+
<RowDefinition Height="1*" />
33+
<RowDefinition Height="1*" />
34+
</Grid.RowDefinitions>
35+
36+
<TextBlock
37+
Grid.Column="0"
38+
Grid.Row="0"
39+
Text="Server URL"
40+
HorizontalAlignment="Right"
41+
Padding="10"/>
42+
43+
<TextBlock
44+
Grid.Column="1"
45+
Grid.Row="0"
46+
HorizontalAlignment="Stretch"
47+
VerticalAlignment="Center"
48+
Padding="10"
49+
Text="{x:Bind Path=ViewModel.Url, Mode=OneTime}"
50+
/>
51+
52+
<TextBlock
53+
Grid.Column="0"
54+
Grid.Row="1"
55+
Text="Session Token"
56+
HorizontalAlignment="Right"
57+
Padding="10"/>
58+
59+
<TextBox
60+
Grid.Column="1"
61+
Grid.Row="1"
62+
HorizontalAlignment="Stretch"
63+
PlaceholderText="paste your token here"
64+
Text="{x:Bind Path=ViewModel.CoderToken, Mode=TwoWay}"
65+
/>
66+
67+
<HyperlinkButton
68+
Grid.Column="1"
69+
Grid.Row="2"
70+
Content="Generate a token via the Web UI"
71+
NavigateUri="{x:Bind ViewModel.GenTokenURL, Mode=OneTime}" />
72+
73+
</Grid>
74+
75+
<StackPanel
76+
Orientation="Horizontal"
77+
HorizontalAlignment="Center"
78+
Spacing="10">
79+
<Button Content="Back" HorizontalAlignment="Right"
80+
Click="{x:Bind SignInWindow.NavigateToURLPage}"/>
81+
<Button Content="Sign In" HorizontalAlignment="Left" Style="{StaticResource AccentButtonStyle}"
82+
Click="{x:Bind ViewModel.SignIn_Click}"/>
83+
</StackPanel>
84+
85+
<TextBlock
86+
Text="{x:Bind ViewModel.LoginError, Mode=OneWay}"
87+
HorizontalAlignment="Center"
88+
Foreground="Red"
89+
/>
90+
91+
92+
</StackPanel>
93+
</Page>

‎App/SignInTokenPage.xaml.cs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Runtime.InteropServices.WindowsRuntime;
6+
using Coder.Desktop.App.ViewModels;
7+
using Microsoft.UI.Xaml;
8+
using Microsoft.UI.Xaml.Controls;
9+
using Microsoft.UI.Xaml.Controls.Primitives;
10+
using Microsoft.UI.Xaml.Data;
11+
using Microsoft.UI.Xaml.Input;
12+
using Microsoft.UI.Xaml.Media;
13+
using Microsoft.UI.Xaml.Navigation;
14+
using Windows.Foundation;
15+
using Windows.Foundation.Collections;
16+
17+
// To learn more about WinUI, the WinUI project structure,
18+
// and more about our project templates, see: http://aka.ms/winui-project-info.
19+
20+
namespace Coder.Desktop.App
21+
{
22+
/// <summary>
23+
/// An empty page that can be used on its own or navigated to within a Frame.
24+
/// </summary>
25+
public sealed partial class SignInTokenPage : Page
26+
{
27+
public SignInTokenPage(SignInWindow parent, SignInViewModel viewModel)
28+
{
29+
InitializeComponent();
30+
ViewModel = viewModel;
31+
SignInWindow = parent;
32+
}
33+
34+
public readonly SignInViewModel ViewModel;
35+
public readonly SignInWindow SignInWindow;
36+
}
37+
}

‎App/SignInURLPage.xaml

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Page
3+
x:Class="Coder.Desktop.App.SignInURLPage"
4+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
5+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
6+
xmlns:local="using:Coder.Desktop.App"
7+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
8+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9+
mc:Ignorable="d"
10+
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
11+
12+
<StackPanel
13+
Orientation="Vertical"
14+
HorizontalAlignment="Stretch"
15+
VerticalAlignment="Top"
16+
Padding="20"
17+
Spacing="10">
18+
19+
<TextBlock
20+
Text="Coder Desktop"
21+
FontSize="24"
22+
VerticalAlignment="Center"
23+
HorizontalAlignment="Center"/>
24+
25+
<Grid>
26+
<Grid.ColumnDefinitions>
27+
<ColumnDefinition Width="Auto" />
28+
<ColumnDefinition Width="*" />
29+
</Grid.ColumnDefinitions>
30+
<TextBlock
31+
Grid.Column="0"
32+
Text="Server URL"
33+
HorizontalAlignment="Right"
34+
Padding="10"/>
35+
36+
<TextBox
37+
Name="URLTextBox"
38+
Grid.Column="1"
39+
HorizontalAlignment="Stretch"
40+
PlaceholderText="https://coder.example.com"
41+
Text="{x:Bind Path=ViewModel.Url, Mode=TwoWay}"
42+
/>
43+
44+
</Grid>
45+
46+
<Button
47+
Content="Next"
48+
HorizontalAlignment="Center"
49+
Click="{x:Bind SignInWindow.NavigateToTokenPage}"
50+
Style="{StaticResource AccentButtonStyle}" />
51+
52+
</StackPanel>
53+
</Page>

‎App/SignInURLPage.xaml.cs

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Runtime.InteropServices.WindowsRuntime;
6+
using Coder.Desktop.App.ViewModels;
7+
using Microsoft.UI.Xaml;
8+
using Microsoft.UI.Xaml.Controls;
9+
using Microsoft.UI.Xaml.Controls.Primitives;
10+
using Microsoft.UI.Xaml.Data;
11+
using Microsoft.UI.Xaml.Input;
12+
using Microsoft.UI.Xaml.Media;
13+
using Microsoft.UI.Xaml.Navigation;
14+
using Windows.Foundation;
15+
using Windows.Foundation.Collections;
16+
17+
namespace Coder.Desktop.App;
18+
19+
/// <summary>
20+
/// A login page to enter the Coder Server URL
21+
/// </summary>
22+
public sealed partial class SignInURLPage : Page
23+
{
24+
public SignInURLPage(SignInWindow parent, SignInViewModel viewModel)
25+
{
26+
InitializeComponent();
27+
ViewModel = viewModel;
28+
SignInWindow = parent;
29+
}
30+
31+
public readonly SignInViewModel ViewModel;
32+
public readonly SignInWindow SignInWindow;
33+
}

‎App/SignInWindow.xaml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Window
3+
x:Class="Coder.Desktop.App.SignInWindow"
4+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
5+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
6+
xmlns:local="using:Coder.Desktop.App"
7+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
8+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9+
mc:Ignorable="d"
10+
Title="Sign in to Coder">
11+
12+
<Window.SystemBackdrop>
13+
<DesktopAcrylicBackdrop />
14+
</Window.SystemBackdrop>
15+
</Window>

‎App/SignInWindow.xaml.cs

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Runtime.InteropServices.WindowsRuntime;
6+
using Coder.Desktop.App.ViewModels;
7+
using CommunityToolkit.Mvvm.Input;
8+
using Microsoft.UI.Xaml;
9+
using Microsoft.UI.Xaml.Controls;
10+
using Microsoft.UI.Xaml.Controls.Primitives;
11+
using Microsoft.UI.Xaml.Data;
12+
using Microsoft.UI.Xaml.Input;
13+
using Microsoft.UI.Xaml.Media;
14+
using Microsoft.UI.Xaml.Navigation;
15+
using Windows.Foundation;
16+
using Windows.Foundation.Collections;
17+
using Windows.Graphics;
18+
19+
// To learn more about WinUI, the WinUI project structure,
20+
// and more about our project templates, see: http://aka.ms/winui-project-info.
21+
22+
namespace Coder.Desktop.App;
23+
24+
/// <summary>
25+
/// An empty window that can be used on its own or navigated to within a Frame.
26+
/// </summary>
27+
public sealed partial class SignInWindow : Window
28+
{
29+
private const double WIDTH = 600.0;
30+
private const double HEIGHT = 300.0;
31+
32+
private readonly SignInViewModel viewModel;
33+
public SignInWindow(SignInViewModel vm)
34+
{
35+
viewModel = vm;
36+
InitializeComponent();
37+
var urlPage = new SignInURLPage(this, viewModel);
38+
Content = urlPage;
39+
ResizeWindow();
40+
}
41+
42+
[RelayCommand]
43+
public void NavigateToTokenPage()
44+
{
45+
var tokenPage = new SignInTokenPage(this, viewModel);
46+
Content = tokenPage;
47+
}
48+
49+
[RelayCommand]
50+
public void NavigateToURLPage()
51+
{
52+
var urlPage = new SignInURLPage(this, viewModel);
53+
Content = urlPage;
54+
}
55+
56+
private void ResizeWindow()
57+
{
58+
var scale = DisplayScale.WindowScale(this);
59+
var height = (int)(HEIGHT * scale);
60+
var width = (int)(WIDTH * scale);
61+
AppWindow.Resize(new SizeInt32(width, height));
62+
}
63+
}

‎App/TrayWindow.xaml

+3-2
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,10 @@
159159
<HyperlinkButton
160160
Margin="-10,0,-10,0"
161161
HorizontalAlignment="Stretch"
162-
HorizontalContentAlignment="Left">
162+
HorizontalContentAlignment="Left"
163+
Click="{x:Bind SignIn_Click}">
163164

164-
<TextBlock Text="Sign out" Foreground="{ThemeResource DefaultTextForegroundThemeBrush}" />
165+
<TextBlock Text="Sign in" Foreground="{ThemeResource DefaultTextForegroundThemeBrush}" />
165166
</HyperlinkButton>
166167

167168
<!-- For some strange reason, setting OpenCommand and ExitCommand here doesn't work, see .cs -->

‎App/TrayWindow.xaml.cs

+13-13
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using Microsoft.UI.Xaml.Media;
2020
using WinRT.Interop;
2121
using WindowActivatedEventArgs = Microsoft.UI.Xaml.WindowActivatedEventArgs;
22+
using Coder.Desktop.App.ViewModels;
2223

2324
namespace Coder.Desktop.App;
2425

@@ -139,8 +140,11 @@ public sealed partial class TrayWindow : Window
139140
},
140141
];
141142

142-
public TrayWindow()
143+
public SignInViewModel SignInViewModel { get; }
144+
145+
public TrayWindow(SignInViewModel signInViewModel)
143146
{
147+
SignInViewModel = signInViewModel;
144148
InitializeComponent();
145149
AppWindow.Hide();
146150
SystemBackdrop = new DesktopAcrylicBackdrop();
@@ -190,20 +194,12 @@ private void ResizeWindow()
190194
var desiredSize = content.DesiredSize;
191195

192196
// Adjust the AppWindow size
193-
var scale = GetDisplayScale();
197+
var scale = DisplayScale.WindowScale(this);
194198
var height = (int)(desiredSize.Height * scale);
195199
var width = (int)(WIDTH * scale);
196200
AppWindow.Resize(new SizeInt32(width, height));
197201
}
198202

199-
private double GetDisplayScale()
200-
{
201-
var hwnd = WindowNative.GetWindowHandle(this);
202-
var dpi = NativeApi.GetDpiForWindow(hwnd);
203-
if (dpi == 0) return 1; // assume scale of 1
204-
return dpi / 96.0; // 96 DPI == 1
205-
}
206-
207203
public void MoveResizeAndActivate()
208204
{
209205
SaveCursorPos();
@@ -313,13 +309,17 @@ public class NativeApi
313309
[DllImport("user32.dll")]
314310
public static extern bool SetForegroundWindow(IntPtr hwnd);
315311

316-
[DllImport("user32.dll")]
317-
public static extern int GetDpiForWindow(IntPtr hwnd);
318-
319312
public struct POINT
320313
{
321314
public int X;
322315
public int Y;
323316
}
324317
}
318+
319+
[RelayCommand]
320+
private void SignIn_Click()
321+
{
322+
var window = new SignInWindow(SignInViewModel);
323+
window.Activate();
324+
}
325325
}

‎App/ViewModels/SignInViewModel.cs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using CommunityToolkit.Mvvm.ComponentModel;
7+
using CommunityToolkit.Mvvm.Input;
8+
9+
namespace Coder.Desktop.App.ViewModels;
10+
11+
/// <summary>
12+
/// The View Model backing the sign in window and all its associated pages.
13+
/// </summary>
14+
public partial class SignInViewModel : ObservableObject
15+
{
16+
public SignInViewModel()
17+
{
18+
_url = string.Empty;
19+
CoderToken = string.Empty;
20+
}
21+
22+
[ObservableProperty]
23+
private string _url;
24+
25+
public string CoderToken;
26+
27+
[ObservableProperty]
28+
private string? _loginError;
29+
30+
[RelayCommand]
31+
public void SignIn_Click()
32+
{
33+
// TODO: this should call into the backing model to do the login with _url and Token.
34+
LoginError = "This is a placeholder error.";
35+
}
36+
37+
public string GenTokenURL
38+
{
39+
get
40+
{
41+
// TODO: use a real URL parsing library
42+
return _url + "/cli-auth";
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)
Please sign in to comment.