Got Avalonia.Ui working.

This commit is contained in:
2026-01-31 13:24:14 +01:00
parent d86d0d2f32
commit e4dd1b6150
33 changed files with 396 additions and 283 deletions

View File

@@ -7,6 +7,7 @@
<!-- Avalonia packages --> <!-- Avalonia packages -->
<!-- Important: keep version in sync! --> <!-- Important: keep version in sync! -->
<PackageVersion Include="Avalonia" Version="11.3.10" /> <PackageVersion Include="Avalonia" Version="11.3.10" />
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.3.8" />
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.3.10" /> <PackageVersion Include="Avalonia.Themes.Fluent" Version="11.3.10" />
<PackageVersion Include="Avalonia.Fonts.Inter" Version="11.3.10" /> <PackageVersion Include="Avalonia.Fonts.Inter" Version="11.3.10" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.10" /> <PackageVersion Include="Avalonia.Diagnostics" Version="11.3.10" />
@@ -17,7 +18,6 @@
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" /> <PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" /> <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" />
<PackageVersion Include="Refit" Version="9.0.2" /> <PackageVersion Include="Refit" Version="9.0.2" />
<PackageVersion Include="Refit.Newtonsoft.Json" Version="9.0.2" />
<PackageVersion Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1.15" /> <PackageVersion Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1.15" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -4,7 +4,7 @@
<TargetFramework>net9.0-android</TargetFramework> <TargetFramework>net9.0-android</TargetFramework>
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion> <SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ApplicationId>com.CompanyName.gamenight.ui</ApplicationId> <ApplicationId>com.CompanyName.Gamenight.Ui</ApplicationId>
<ApplicationVersion>1</ApplicationVersion> <ApplicationVersion>1</ApplicationVersion>
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion> <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<AndroidPackageFormat>apk</AndroidPackageFormat> <AndroidPackageFormat>apk</AndroidPackageFormat>
@@ -23,6 +23,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\gamenight.ui\gamenight.ui.csproj" /> <ProjectReference Include="..\Gamenight.Ui\Gamenight.Ui.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -3,10 +3,10 @@ using Android.Content.PM;
using Avalonia; using Avalonia;
using Avalonia.Android; using Avalonia.Android;
namespace gamenight.ui.Android; namespace Gamenight.Ui.Android;
[Activity( [Activity(
Label = "gamenight.ui.Android", Label = "Gamenight.Ui.Android",
Theme = "@style/MyTheme.NoActionBar", Theme = "@style/MyTheme.NoActionBar",
Icon = "@drawable/icon", Icon = "@drawable/icon",
MainLauncher = true, MainLauncher = true,

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application android:label="gamenight.ui" android:icon="@drawable/Icon" /> <application android:label="Gamenight.Ui" android:icon="@drawable/Icon" />
</manifest> </manifest>

View File

@@ -11,6 +11,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\gamenight.ui\gamenight.ui.csproj" /> <ProjectReference Include="..\Gamenight.Ui\Gamenight.Ui.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -2,7 +2,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia; using Avalonia;
using Avalonia.Browser; using Avalonia.Browser;
using gamenight.ui; using Gamenight.Ui;
internal sealed partial class Program internal sealed partial class Program
{ {

View File

@@ -1,6 +1,6 @@
{ {
"profiles": { "profiles": {
"gamenight.ui.Browser": { "Gamenight.Ui.Browser": {
"commandName": "Project", "commandName": "Project",
"launchBrowser": true, "launchBrowser": true,
"environmentVariables": { "environmentVariables": {

View File

@@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<title>gamenight.ui.Browser</title> <title>Gamenight.Ui.Browser</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./app.css" /> <link rel="stylesheet" href="./app.css" />

View File

@@ -21,6 +21,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\gamenight.ui\gamenight.ui.csproj" /> <ProjectReference Include="..\Gamenight.Ui\Gamenight.Ui.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,7 +1,8 @@
using System; using System;
using Avalonia; using Avalonia;
using Avalonia.ReactiveUI;
namespace gamenight.ui.Desktop; namespace Gamenight.Ui.Desktop;
sealed class Program sealed class Program
{ {
@@ -17,5 +18,6 @@ sealed class Program
=> AppBuilder.Configure<App>() => AppBuilder.Configure<App>()
.UsePlatformDetect() .UsePlatformDetect()
.WithInterFont() .WithInterFont()
.LogToTrace(); .LogToTrace()
.UseReactiveUI();
} }

View File

@@ -3,7 +3,7 @@
<!-- This manifest is used on Windows only. <!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls. Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests --> For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="gamenight.ui.Desktop"/> <assemblyIdentity version="1.0.0.0" name="Gamenight.Ui.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application> <application>

View File

@@ -5,7 +5,7 @@ using Avalonia.Controls;
using Avalonia.iOS; using Avalonia.iOS;
using Avalonia.Media; using Avalonia.Media;
namespace gamenight.ui.iOS; namespace Gamenight.Ui.iOS;
// The UIApplicationDelegate for the application. This class is responsible for launching the // The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to // User Interface of the application, as well as listening (and optionally responding) to

View File

@@ -11,6 +11,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\gamenight.ui\gamenight.ui.csproj" /> <ProjectReference Include="..\Gamenight.Ui\Gamenight.Ui.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -3,9 +3,9 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>gamenight.ui</string> <string>Gamenight.Ui</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>companyName.gamenight.ui</string> <string>companyName.Gamenight.Ui</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0</string> <string>1.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>

View File

@@ -1,6 +1,6 @@
using UIKit; using UIKit;
namespace gamenight.ui.iOS; namespace Gamenight.Ui.iOS;
public class Application public class Application
{ {

View File

@@ -18,7 +18,7 @@
<color key="textColor" cocoaTouchSystemColor="darkTextColor" /> <color key="textColor" cocoaTouchSystemColor="darkTextColor" />
<nil key="highlightedColor" /> <nil key="highlightedColor" />
</label> </label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="gamenight.ui" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Gamenight.Ui" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines"
minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX"> minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43" /> <rect key="frame" x="20" y="140" width="441" height="43" />
<fontDescription key="fontDescription" type="boldSystem" pointSize="36" /> <fontDescription key="fontDescription" type="boldSystem" pointSize="36" />

View File

@@ -1,7 +1,7 @@
<Application xmlns="https://github.com/avaloniaui" <Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:gamenight.ui" xmlns:local="using:Gamenight.Ui"
x:Class="gamenight.ui.App" x:Class="Gamenight.Ui.App"
RequestedThemeVariant="Default"> RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. --> <!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->

View File

@@ -1,22 +1,21 @@
using Avalonia; using Avalonia;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core;
using Avalonia.Data.Core.Plugins; using Avalonia.Data.Core.Plugins;
using System.Linq; using System.Linq;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using gamenight.ui.ViewModels; using Avalonia.ReactiveUI;
using gamenight.ui.Views; using Gamenight.Ui.ViewModels;
using Gamenight.Ui.Views;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using gamenight.ui.Services; using Gamenight.Ui.Services;
using System; using System;
using Refit; using Refit;
using System.Runtime.Serialization;
namespace gamenight.ui; namespace Gamenight.Ui;
public partial class App : Application public partial class App : Application
{ {
private IServiceProvider? ServiceProvider; private IServiceProvider? ServiceProvider { get; set; }
public override void Initialize() public override void Initialize()
{ {
@@ -27,13 +26,13 @@ public partial class App : Application
{ {
// Register all the services needed for the application to run // Register all the services needed for the application to run
var collection = new ServiceCollection(); var collection = new ServiceCollection();
var gamenightApi = RestService.For<IGamenightApi>("https://localhost:8080", var gamenightApi = RestService.For<IGamenightApi>("http://localhost:8080",
new RefitSettings { new RefitSettings {}
ContentSerializer = new NewtonsoftJsonContentSerializer()
}
); );
collection.AddSingleton(gamenightApi); collection.AddSingleton(gamenightApi);
collection.AddSingleton<MainViewModel>(); collection.AddSingleton<MainViewModel>();
collection.AddSingleton<HeaderViewModel>();
collection.AddSingleton<SideBarViewModel>();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime) if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime)
{ {
collection.AddSingleton<MainWindow>(); collection.AddSingleton<MainWindow>();

View File

@@ -12,6 +12,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" /> <PackageReference Include="Avalonia" />
<PackageReference Include="Avalonia.ReactiveUI" />
<PackageReference Include="Avalonia.Themes.Fluent" /> <PackageReference Include="Avalonia.Themes.Fluent" />
<PackageReference Include="Avalonia.Fonts.Inter" /> <PackageReference Include="Avalonia.Fonts.Inter" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
@@ -22,6 +23,5 @@
<PackageReference Include="CommunityToolkit.Mvvm" /> <PackageReference Include="CommunityToolkit.Mvvm" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Refit" /> <PackageReference Include="Refit" />
<PackageReference Include="Refit.Newtonsoft.Json" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -10,12 +10,13 @@ using System.Threading.Tasks;
#nullable enable annotations #nullable enable annotations
namespace gamenight.ui.Services namespace Gamenight.Ui.Services
{ {
/// <summary>Gamenight</summary> /// <summary>Gamenight</summary>
[System.CodeDom.Compiler.GeneratedCode("Refitter", "1.7.1.0")] [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.7.1.0")]
public partial interface IGamenightApi public partial interface IGamenightApi
{ {
/// <summary>Login a user.</summary>
/// <remarks>Submit your credentials to get a JWT-token to use with the rest of the api.</remarks> /// <remarks>Submit your credentials to get a JWT-token to use with the rest of the api.</remarks>
/// <returns>Example response</returns> /// <returns>Example response</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
@@ -31,9 +32,10 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Get("/token")] [Post("/token")]
Task<Token> TokenGet([Body] Login body); Task<Token> Token([Body] Login body);
/// <summary>Refresh a user token</summary>
/// <remarks>Refresh your JWT-token without logging in again.</remarks> /// <remarks>Refresh your JWT-token without logging in again.</remarks>
/// <returns>Example response</returns> /// <returns>Example response</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
@@ -49,9 +51,10 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Post("/token")] [Post("/refresh_token")]
Task<Token> TokenPost(); Task<Token> RefreshToken();
/// <summary>Get all users</summary>
/// <returns>List of all Users</returns> /// <returns>List of all Users</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -71,8 +74,9 @@ namespace gamenight.ui.Services
/// </list> /// </list>
/// </exception> /// </exception>
[Get("/users")] [Get("/users")]
Task<ICollection<User>> Users(); Task<ICollection<User>> UsersGet();
/// <summary>Registers a user into gamenight.</summary>
/// <remarks>Create a new user given a registration token and user information, username and email must be unique, and password and password_repeat must match.</remarks> /// <remarks>Create a new user given a registration token and user information, username and email must be unique, and password and password_repeat must match.</remarks>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns> /// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
@@ -88,10 +92,11 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Post("/user")] [Post("/users")]
Task UserPost([Body] Registration body); Task UsersPost([Body] Registration body);
/// <remarks>Get a user from primary id</remarks> /// <remarks>Get a user from primary id</remarks>
/// <param name="userId">Uuid of user to get</param>
/// <returns>A user in the gamenight system</returns> /// <returns>A user in the gamenight system</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -114,8 +119,31 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Get("/user")] [Get("/user/{userId}")]
Task<User> UserGet([Body] UserId body); Task<User> User(string userId);
/// <summary>Get owned games of user</summary>
/// <param name="userId">Uuid of user to get owned games for.</param>
/// <returns>A list of OwnedGames</returns>
/// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code:
/// <list type="table">
/// <listheader>
/// <term>Status</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>401</term>
/// <description>Example response</description>
/// </item>
/// <item>
/// <term>422</term>
/// <description>Example response</description>
/// </item>
/// </list>
/// </exception>
[Get("/user/{userId}/owned_games")]
Task<ICollection<OwnedGame>> OwnedGames(string userId);
/// <summary>Get a all gamenights</summary> /// <summary>Get a all gamenights</summary>
/// <remarks>Retrieve the list of gamenights on this gamenight server. Requires authorization.</remarks> /// <remarks>Retrieve the list of gamenights on this gamenight server. Requires authorization.</remarks>
@@ -138,31 +166,9 @@ namespace gamenight.ui.Services
/// </list> /// </list>
/// </exception> /// </exception>
[Get("/gamenights")] [Get("/gamenights")]
Task<ICollection<Gamenight>> Gamenights(); Task<ICollection<Gamenight>> GamenightsGet();
/// <summary>Get all participants for a gamenight</summary>
/// <remarks>Retrieve the participants of a single gamenight by id.</remarks>
/// <returns>Response with a list of participant uuids</returns>
/// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code:
/// <list type="table">
/// <listheader>
/// <term>Status</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>400</term>
/// <description>Example response</description>
/// </item>
/// <item>
/// <term>401</term>
/// <description>Example response</description>
/// </item>
/// </list>
/// </exception>
[Get("/participants")]
Task<Participants> Participants([Body] GamenightId body);
/// <summary>Gets the gamenight</summary>
/// <remarks>Add a gamenight by providing a name and a date, only available when providing an JWT token.</remarks> /// <remarks>Add a gamenight by providing a name and a date, only available when providing an JWT token.</remarks>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns> /// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
@@ -182,9 +188,11 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Post("/gamenight")] [Post("/gamenights")]
Task GamenightPost([Body] AddGamenightRequestBody body); Task GamenightsPost([Body] AddGamenightRequestBody body);
/// <summary>get the specified gamenight</summary>
/// <param name="gamenightId">Uuid of gamenight to get.</param>
/// <returns>A gamenight being hosted</returns> /// <returns>A gamenight being hosted</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -203,9 +211,35 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Get("/gamenight")] [Get("/gamenight/{gamenightId}")]
Task<Gamenight> GamenightGet([Body] GetGamenightRequestBody body); Task<Gamenight> Gamenight(string gamenightId);
/// <summary>Get all participants for a gamenight</summary>
/// <remarks>Retrieve the participants of a single gamenight by id.</remarks>
/// <param name="gamenightId">Uuid of gamenight to get participants for.</param>
/// <returns>Response with a list of participant uuids</returns>
/// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code:
/// <list type="table">
/// <listheader>
/// <term>Status</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>400</term>
/// <description>Example response</description>
/// </item>
/// <item>
/// <term>401</term>
/// <description>Example response</description>
/// </item>
/// </list>
/// </exception>
[Get("/gamenight/{gamenightId}/participants")]
Task<Participants> ParticipantsGet(string gamenightId);
/// <summary>Add a participant</summary>
/// <param name="gamenightId">Uuid of gamenight to add participants for.</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns> /// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -224,9 +258,12 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Post("/join")] [Post("/gamenight/{gamenightId}/participants")]
Task Join([Body] GamenightId body); Task ParticipantsPost(string gamenightId, [Body] UserId body);
/// <summary>deletes a gamenight participant</summary>
/// <param name="gamenightId">Uuid of gamenight to delete participant for</param>
/// <param name="userId">Uuid of the of the participant to remove</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns> /// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -245,9 +282,10 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Post("/leave")] [Delete("/gamenight/{gamenightId}/participant/{userId}")]
Task Leave([Body] GamenightId body); Task Participant(string gamenightId, string userId);
/// <summary>get all games</summary>
/// <returns>A list of Games in this gamenight instance.</returns> /// <returns>A list of Games in this gamenight instance.</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -267,29 +305,9 @@ namespace gamenight.ui.Services
/// </list> /// </list>
/// </exception> /// </exception>
[Get("/games")] [Get("/games")]
Task<ICollection<Game>> Games(); Task<ICollection<Game>> GamesGet();
/// <returns>A game.</returns>
/// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code:
/// <list type="table">
/// <listheader>
/// <term>Status</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>401</term>
/// <description>Example response</description>
/// </item>
/// <item>
/// <term>422</term>
/// <description>Example response</description>
/// </item>
/// </list>
/// </exception>
[Get("/game")]
Task<Game> GameGet([Body] GameId body);
/// <summary>add a game</summary>
/// <returns>a game id</returns> /// <returns>a game id</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -308,9 +326,34 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Post("/game")] [Post("/games")]
Task<GameId> GamePost([Body] AddGameRequestBody body); Task<GameId> GamesPost([Body] AddGameRequestBody body);
/// <summary>Get this specific game</summary>
/// <param name="gameId">Uuid of game to get.</param>
/// <returns>A game.</returns>
/// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code:
/// <list type="table">
/// <listheader>
/// <term>Status</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>401</term>
/// <description>Example response</description>
/// </item>
/// <item>
/// <term>422</term>
/// <description>Example response</description>
/// </item>
/// </list>
/// </exception>
[Get("/game/{gameId}")]
Task<Game> GameGet(string gameId);
/// <summary>Delete this game.</summary>
/// <param name="gameId">Uuid of game to delete.</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns> /// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -329,9 +372,11 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Delete("/game")] [Delete("/game/{gameId}")]
Task GameDelete([Body] GameId body); Task GameDelete(string gameId);
/// <summary>Changes this game resource</summary>
/// <param name="gameId">Uuid of game to change.</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns> /// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -350,9 +395,11 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Post("/rename_game")] [Put("/game/{gameId}")]
Task RenameGame([Body] RenameGameRequestBody body); Task GamePut(string gameId, [Body] EditGameRequestBody body);
/// <summary>Own this game</summary>
/// <param name="gameId">Uuid of game to own.</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns> /// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -371,9 +418,12 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Post("/own")] [Post("/game/{gameId}/owners")]
Task Own([Body] OwnGameRequestBody body); Task Owners(string gameId, [Body] OwnGame body);
/// <summary>no longer own this game</summary>
/// <param name="gameId">Uuid of game that user no longer owns.</param>
/// <param name="userId">Uuid of user that no longer owns.</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns> /// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -392,72 +442,10 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Post("/disown")] [Delete("/game/{gameId}/owner/{userId}")]
Task Disown([Body] GameId body); Task Owner(string gameId, string userId);
/// <returns>A list of game ids.</returns>
/// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code:
/// <list type="table">
/// <listheader>
/// <term>Status</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>401</term>
/// <description>Example response</description>
/// </item>
/// <item>
/// <term>422</term>
/// <description>Example response</description>
/// </item>
/// </list>
/// </exception>
[Get("/owned_games")]
Task<ICollection<OwnedGame>> OwnedGames([Body] UserId body);
/// <returns>A location</returns>
/// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code:
/// <list type="table">
/// <listheader>
/// <term>Status</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>401</term>
/// <description>Example response</description>
/// </item>
/// <item>
/// <term>422</term>
/// <description>Example response</description>
/// </item>
/// </list>
/// </exception>
[Get("/location")]
Task<Location> LocationGet([Body] LocationId body);
/// <returns>A location Id</returns>
/// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code:
/// <list type="table">
/// <listheader>
/// <term>Status</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>401</term>
/// <description>Example response</description>
/// </item>
/// <item>
/// <term>422</term>
/// <description>Example response</description>
/// </item>
/// </list>
/// </exception>
[Post("/location")]
Task<LocationId> LocationPost([Body] AddLocationRequestBody body);
/// <summary>get all locations</summary>
/// <returns>A list of all LocationsResponse</returns> /// <returns>A list of all LocationsResponse</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -477,9 +465,10 @@ namespace gamenight.ui.Services
/// </list> /// </list>
/// </exception> /// </exception>
[Get("/locations")] [Get("/locations")]
Task<ICollection<Location>> Locations(); Task<ICollection<Location>> LocationsGet();
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns> /// <summary>add a location</summary>
/// <returns>A location Id</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
/// <list type="table"> /// <list type="table">
@@ -497,9 +486,34 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Post("/location_authorize")] [Post("/locations")]
Task LocationAuthorize([Body] AuthorizeLocationRequestBody body); Task<LocationId> LocationsPost([Body] AddLocationRequestBody body);
/// <summary>gets this location</summary>
/// <param name="locationId">Uuid of location to get.</param>
/// <returns>A location</returns>
/// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code:
/// <list type="table">
/// <listheader>
/// <term>Status</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>401</term>
/// <description>Example response</description>
/// </item>
/// <item>
/// <term>422</term>
/// <description>Example response</description>
/// </item>
/// </list>
/// </exception>
[Get("/location/{locationId}")]
Task<Location> Location(string locationId);
/// <summary>gets this locations authorized users</summary>
/// <param name="locationId">Uuid of location to get authorized users for.</param>
/// <returns>A list of user ids.</returns> /// <returns>A list of user ids.</returns>
/// <exception cref="ApiException"> /// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code: /// Thrown when the request returns a non-success status code:
@@ -518,8 +532,55 @@ namespace gamenight.ui.Services
/// </item> /// </item>
/// </list> /// </list>
/// </exception> /// </exception>
[Get("/authorized_location_user_ids")] [Get("/location/{locationId}/authorized_users/")]
Task<ICollection<UserId>> AuthorizedLocationUserIds([Body] LocationId body); Task<ICollection<UserId>> AuthorizedUsersGet(string locationId);
/// <summary>Authorize a user</summary>
/// <param name="locationId">Uuid location to authorize for.</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code:
/// <list type="table">
/// <listheader>
/// <term>Status</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>401</term>
/// <description>Example response</description>
/// </item>
/// <item>
/// <term>422</term>
/// <description>Example response</description>
/// </item>
/// </list>
/// </exception>
[Post("/location/{locationId}/authorized_users/")]
Task AuthorizedUsersPost(string locationId, [Body] UserId body);
/// <summary>remove an authorized user from a location</summary>
/// <param name="locationId">Uuid of location to deauthorize for.</param>
/// <param name="userId">Uuid of user ot deauthorize.</param>
/// <returns>A <see cref="Task"/> that completes when the request is finished.</returns>
/// <exception cref="ApiException">
/// Thrown when the request returns a non-success status code:
/// <list type="table">
/// <listheader>
/// <term>Status</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>401</term>
/// <description>Example response</description>
/// </item>
/// <item>
/// <term>422</term>
/// <description>Example response</description>
/// </item>
/// </list>
/// </exception>
[Delete("/location/{locationId}/authorized_user/{userId}")]
Task AuthorizedUser(string locationId, string userId);
} }
@@ -548,7 +609,7 @@ namespace gamenight.ui.Services
#pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type" #pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type"
#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)." #pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)."
namespace gamenight.ui.Services namespace Gamenight.Ui.Services
{ {
using System = global::System; using System = global::System;
@@ -723,10 +784,36 @@ namespace gamenight.ui.Services
} }
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class OwnGame
{
[JsonPropertyName("user_id")]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string UserId { get; set; }
[JsonPropertyName("location_id")]
public string LocationId { get; set; }
private IDictionary<string, object> _additionalProperties;
[JsonExtensionData]
public IDictionary<string, object> AdditionalProperties
{
get { return _additionalProperties ?? (_additionalProperties = new Dictionary<string, object>()); }
set { _additionalProperties = value; }
}
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")] [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class OwnedGame public partial class OwnedGame
{ {
[JsonPropertyName("user_id")]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string UserId { get; set; }
[JsonPropertyName("game_id")] [JsonPropertyName("game_id")]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string GameId { get; set; } public string GameId { get; set; }
@@ -825,24 +912,6 @@ namespace gamenight.ui.Services
} }
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class GetGamenightRequestBody
{
[JsonPropertyName("id")]
public string Id { get; set; }
private IDictionary<string, object> _additionalProperties;
[JsonExtensionData]
public IDictionary<string, object> AdditionalProperties
{
get { return _additionalProperties ?? (_additionalProperties = new Dictionary<string, object>()); }
set { _additionalProperties = value; }
}
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")] [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class User public partial class User
{ {
@@ -912,7 +981,7 @@ namespace gamenight.ui.Services
} }
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")] [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class RenameGameRequestBody public partial class EditGameRequestBody
{ {
[JsonPropertyName("id")] [JsonPropertyName("id")]
@@ -935,29 +1004,7 @@ namespace gamenight.ui.Services
} }
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")] [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class OwnGameRequestBody public partial class GameIdsResponse : System.Collections.ObjectModel.Collection<GameId>
{
[JsonPropertyName("game_id")]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string GameId { get; set; }
[JsonPropertyName("location_id")]
public string LocationId { get; set; }
private IDictionary<string, object> _additionalProperties;
[JsonExtensionData]
public IDictionary<string, object> AdditionalProperties
{
get { return _additionalProperties ?? (_additionalProperties = new Dictionary<string, object>()); }
set { _additionalProperties = value; }
}
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class GameIdsResponse : System.Collections.ObjectModel.Collection<OwnedGame>
{ {
} }
@@ -1022,46 +1069,6 @@ namespace gamenight.ui.Services
} }
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class AuthorizeLocationRequestBody
{
[JsonPropertyName("location_id")]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string LocationId { get; set; }
[JsonPropertyName("user_id")]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
public string UserId { get; set; }
[JsonPropertyName("op")]
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
[JsonConverter(typeof(JsonStringEnumConverter<AuthorizeLocationRequestBodyOp>))]
public AuthorizeLocationRequestBodyOp Op { get; set; }
private IDictionary<string, object> _additionalProperties;
[JsonExtensionData]
public IDictionary<string, object> AdditionalProperties
{
get { return _additionalProperties ?? (_additionalProperties = new Dictionary<string, object>()); }
set { _additionalProperties = value; }
}
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))")]
public enum AuthorizeLocationRequestBodyOp
{
[System.Runtime.Serialization.EnumMember(Value = @"grant")]
Grant = 0,
[System.Runtime.Serialization.EnumMember(Value = @"revoke")]
Revoke = 1,
}
} }

View File

@@ -2,9 +2,9 @@ using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using gamenight.ui.ViewModels; using Gamenight.Ui.ViewModels;
namespace gamenight.ui; namespace Gamenight.Ui;
/// <summary> /// <summary>
/// Given a view model, returns the corresponding view if possible. /// Given a view model, returns the corresponding view if possible.

View File

@@ -0,0 +1,7 @@
namespace Gamenight.Ui.ViewModels;
public class HeaderViewModel : ViewModelBase
{
}

View File

@@ -1,26 +1,37 @@
using CommunityToolkit.Mvvm.ComponentModel; using System.Threading.Tasks;
using gamenight.ui.Services; using System.Windows.Input;
using CommunityToolkit.Mvvm.ComponentModel;
using Gamenight.Ui.Services;
using ReactiveUI;
namespace gamenight.ui.ViewModels; namespace Gamenight.Ui.ViewModels;
public partial class MainViewModel : ViewModelBase public partial class MainViewModel : ViewModelBase
{ {
[ObservableProperty] [ObservableProperty]
private string _greeting = "Welcome to Avalonia!"; private string _greeting = "Welcome to Avalonia!";
private IGamenightApi GamenightApi { get; } private IGamenightApi GamenightApi { get; }
public HeaderViewModel HeaderViewModel { get; }
public SideBarViewModel SideBarViewModel { get; }
public MainViewModel(IGamenightApi gamenightApi) [ObservableProperty]
private ICommand _loginCommand;
public MainViewModel(IGamenightApi gamenightApi, HeaderViewModel headerViewModel, SideBarViewModel sideBarViewModel)
{ {
GamenightApi = gamenightApi; GamenightApi = gamenightApi;
HeaderViewModel = headerViewModel;
SideBarViewModel = sideBarViewModel;
Test(); _loginCommand = ReactiveCommand.Create(Test);
} }
public async void Test() { public MainViewModel() => throw new System.NotImplementedException();
var token = await GamenightApi.TokenGet(new Login() {
Username = "Admin", public async Task Test() {
Password = "Gamenight!" var token = await GamenightApi.Token(new Login() {
Username = "admin",
Password = "gamenight!"
}); });
System.Console.WriteLine($"Token: {token.JwtToken}"); System.Console.WriteLine($"Token: {token.JwtToken}");

View File

@@ -0,0 +1,7 @@
namespace Gamenight.Ui.ViewModels;
public class SideBarViewModel : ViewModelBase
{
}

View File

@@ -1,6 +1,6 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
namespace gamenight.ui.ViewModels; namespace Gamenight.Ui.ViewModels;
public abstract class ViewModelBase : ObservableObject public abstract class ViewModelBase : ObservableObject
{ {

View File

@@ -0,0 +1,15 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:Gamenight.Ui.ViewModels"
xmlns:views="clr-namespace:Gamenight.Ui.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Gamenight.Ui.Views.HeaderView"
x:DataType="vm:HeaderViewModel">
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:HeaderViewModel />
</Design.DataContext>
</UserControl>

View File

@@ -0,0 +1,17 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Gamenight.Ui.Views;
public partial class HeaderView : UserControl
{
public HeaderView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}

View File

@@ -2,15 +2,32 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:gamenight.ui.ViewModels" xmlns:vm="using:Gamenight.Ui.ViewModels"
xmlns:views="clr-namespace:Gamenight.Ui.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="gamenight.ui.Views.MainView" x:Class="Gamenight.Ui.Views.MainView"
x:DataType="vm:MainViewModel"> x:DataType="vm:MainViewModel">
<Design.DataContext> <Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE, <!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) --> to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:MainViewModel /> <vm:MainViewModel />
</Design.DataContext> </Design.DataContext>
<Grid>
<TextBlock Text="{Binding Greeting}" HorizontalAlignment="Center" VerticalAlignment="Center"/> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--<views:HeaderView Grid.Row="0" DataContext="{Binding HeaderViewModel}"/>-->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<views:SideBarView Grid.Column="0" DataContext="{Binding SideBarViewModel}"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding Greeting}" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Button Content="Login" Command="{Binding LoginCommand}"/>
</StackPanel>
</Grid>
</Grid>
</UserControl> </UserControl>

View File

@@ -1,6 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
namespace gamenight.ui.Views; namespace Gamenight.Ui.Views;
public partial class MainView : UserControl public partial class MainView : UserControl
{ {

View File

@@ -1,12 +1,11 @@
<Window xmlns="https://github.com/avaloniaui" <Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:gamenight.ui.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="using:gamenight.ui.Views" xmlns:views="using:Gamenight.Ui.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="gamenight.ui.Views.MainWindow" x:Class="Gamenight.Ui.Views.MainWindow"
Icon="/Assets/avalonia-logo.ico" Icon="/Assets/avalonia-logo.ico"
Title="gamenight.ui"> Title="Gamenight.Ui">
<views:MainView /> <views:MainView />
</Window> </Window>

View File

@@ -1,6 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
namespace gamenight.ui.Views; namespace Gamenight.Ui.Views;
public partial class MainWindow : Window public partial class MainWindow : Window
{ {

View File

@@ -0,0 +1,15 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:Gamenight.Ui.ViewModels"
xmlns:views="clr-namespace:Gamenight.Ui.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Gamenight.Ui.Views.SideBarView"
x:DataType="vm:SideBarViewModel">
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:SideBarViewModel />
</Design.DataContext>
</UserControl>

View File

@@ -0,0 +1,17 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Gamenight.Ui.Views;
public partial class SideBarView : UserControl
{
public SideBarView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}