Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Sign in Window views & view models #20

Merged
merged 2 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions App/App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.250108002" />
</ItemGroup>

<ItemGroup>
<Page Update="SignInTokenPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>

<ItemGroup>
<Page Update="SignInWindow.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>

<ItemGroup>
<Page Update="SignInURLPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>

<ItemGroup>
<Page Update="TrayIcon.xaml">
<Generator>MSBuild:Compile</Generator>
Expand Down
5 changes: 4 additions & 1 deletion App/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
using Coder.Desktop.App.ViewModels;
using Microsoft.UI.Xaml;

namespace Coder.Desktop.App;

public partial class App : Application
{
private TrayWindow? TrayWindow;
public SignInViewModel SignInViewModel { get; }

public App()
{
SignInViewModel = new SignInViewModel();
InitializeComponent();
}

private bool HandleClosedEvents { get; } = true;

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
TrayWindow = new TrayWindow();
TrayWindow = new TrayWindow(SignInViewModel);
TrayWindow.Closed += (sender, args) =>
{
// TODO: wire up HandleClosedEvents properly
Expand Down
26 changes: 26 additions & 0 deletions App/DisplayScale.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using Microsoft.UI.Xaml;
using WinRT.Interop;
using System.Runtime.InteropServices;

namespace Coder.Desktop.App;

/// <summary>
/// A static utility class to house methods related to the visual scale of the display monitor.
/// </summary>
public static class DisplayScale
{
public static double WindowScale(Window win)
{
var hwnd = WindowNative.GetWindowHandle(win);
var dpi = NativeApi.GetDpiForWindow(hwnd);
if (dpi == 0) return 1; // assume scale of 1
return dpi / 96.0; // 96 DPI == 1
}

public class NativeApi
{
[DllImport("user32.dll")]
public static extern int GetDpiForWindow(IntPtr hwnd);
}
}
93 changes: 93 additions & 0 deletions App/SignInTokenPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<Page
x:Class="Coder.Desktop.App.SignInTokenPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Coder.Desktop.App"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<StackPanel
Orientation="Vertical"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Padding="20"
Spacing="10">

<TextBlock
Text="Coder Desktop"
FontSize="24"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>

<TextBlock
Grid.Column="0"
Grid.Row="0"
Text="Server URL"
HorizontalAlignment="Right"
Padding="10"/>

<TextBlock
Grid.Column="1"
Grid.Row="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Padding="10"
Text="{x:Bind Path=ViewModel.Url, Mode=OneTime}"
/>

<TextBlock
Grid.Column="0"
Grid.Row="1"
Text="Session Token"
HorizontalAlignment="Right"
Padding="10"/>

<TextBox
Grid.Column="1"
Grid.Row="1"
HorizontalAlignment="Stretch"
PlaceholderText="paste your token here"
Text="{x:Bind Path=ViewModel.CoderToken, Mode=TwoWay}"
/>

<HyperlinkButton
Grid.Column="1"
Grid.Row="2"
Content="Generate a token via the Web UI"
NavigateUri="{x:Bind ViewModel.GenTokenURL, Mode=OneTime}" />

</Grid>

<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Center"
Spacing="10">
<Button Content="Back" HorizontalAlignment="Right"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the better way of doing forwards/backwards navigation is to use a <RootFrame> in the window rather than setting Window.Content directly.

One pitfall that might make it hard to use the RootFrame's built-in navigation stuff is that I don't think it lets you instantiate the Window types yourself - which makes it hard to get a ViewModel in there.

In the TrayWindow code in my PR, I ended up just setting RootFrame.Content directly because of this limitation (and because I don't need forwards/backwards navigation). But if you could get that working it'd be more idiomatic I think

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I switched it to using a Frame so we're not just touching the window content directly, but I'm not using the forward/backwards functionality yet because of the aforementioned issue.

In the future if we solve it, we could have the "Coder Desktop" text and the navigation buttons be on the Window itself, rather than in each page.

Click="{x:Bind SignInWindow.NavigateToURLPage}"/>
<Button Content="Sign In" HorizontalAlignment="Left" Style="{StaticResource AccentButtonStyle}"
Click="{x:Bind ViewModel.SignIn_Click}"/>
</StackPanel>

<TextBlock
Text="{x:Bind ViewModel.LoginError, Mode=OneWay}"
HorizontalAlignment="Center"
Foreground="Red"
/>


</StackPanel>
</Page>
37 changes: 37 additions & 0 deletions App/SignInTokenPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Coder.Desktop.App.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Windows.Foundation;
using Windows.Foundation.Collections;

// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.

namespace Coder.Desktop.App
{
/// <summary>
/// A sign in page to accept the user's Coder token.
/// </summary>
public sealed partial class SignInTokenPage : Page
{
public SignInTokenPage(SignInWindow parent, SignInViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
SignInWindow = parent;
}

public readonly SignInViewModel ViewModel;
public readonly SignInWindow SignInWindow;
}
}
53 changes: 53 additions & 0 deletions App/SignInURLPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Page
x:Class="Coder.Desktop.App.SignInURLPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Coder.Desktop.App"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<StackPanel
Orientation="Vertical"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Padding="20"
Spacing="10">

<TextBlock
Text="Coder Desktop"
FontSize="24"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Text="Server URL"
HorizontalAlignment="Right"
Padding="10"/>

<TextBox
Name="URLTextBox"
Grid.Column="1"
HorizontalAlignment="Stretch"
PlaceholderText="https://coder.example.com"
Text="{x:Bind Path=ViewModel.Url, Mode=TwoWay}"
/>

</Grid>

<Button
Content="Next"
HorizontalAlignment="Center"
Click="{x:Bind SignInWindow.NavigateToTokenPage}"
Style="{StaticResource AccentButtonStyle}" />

</StackPanel>
</Page>
33 changes: 33 additions & 0 deletions App/SignInURLPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Coder.Desktop.App.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Windows.Foundation;
using Windows.Foundation.Collections;

namespace Coder.Desktop.App;

/// <summary>
/// A login page to enter the Coder Server URL
/// </summary>
public sealed partial class SignInURLPage : Page
{
public SignInURLPage(SignInWindow parent, SignInViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
SignInWindow = parent;
}

public readonly SignInViewModel ViewModel;
public readonly SignInWindow SignInWindow;
}
15 changes: 15 additions & 0 deletions App/SignInWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="Coder.Desktop.App.SignInWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Coder.Desktop.App"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Sign in to Coder">

<Window.SystemBackdrop>
<DesktopAcrylicBackdrop />
</Window.SystemBackdrop>
</Window>
60 changes: 60 additions & 0 deletions App/SignInWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Coder.Desktop.App.ViewModels;
using CommunityToolkit.Mvvm.Input;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Graphics;

namespace Coder.Desktop.App;

/// <summary>
/// The dialog window to allow the user to sign into their Coder server.
/// </summary>
public sealed partial class SignInWindow : Window
{
private const double WIDTH = 600.0;
private const double HEIGHT = 300.0;

private readonly SignInViewModel viewModel;
public SignInWindow(SignInViewModel vm)
{
viewModel = vm;
InitializeComponent();
var urlPage = new SignInURLPage(this, viewModel);
Content = urlPage;
ResizeWindow();
}

[RelayCommand]
public void NavigateToTokenPage()
{
var tokenPage = new SignInTokenPage(this, viewModel);
Content = tokenPage;
}

[RelayCommand]
public void NavigateToURLPage()
{
var urlPage = new SignInURLPage(this, viewModel);
Content = urlPage;
}

private void ResizeWindow()
{
var scale = DisplayScale.WindowScale(this);
var height = (int)(HEIGHT * scale);
var width = (int)(WIDTH * scale);
AppWindow.Resize(new SizeInt32(width, height));
}
}
5 changes: 3 additions & 2 deletions App/TrayWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,10 @@
<HyperlinkButton
Margin="-10,0,-10,0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left">
HorizontalContentAlignment="Left"
Click="{x:Bind SignIn_Click}">

<TextBlock Text="Sign out" Foreground="{ThemeResource DefaultTextForegroundThemeBrush}" />
<TextBlock Text="Sign in" Foreground="{ThemeResource DefaultTextForegroundThemeBrush}" />
</HyperlinkButton>

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