2 Commits

Author SHA1 Message Date
a1ddf380dd remade into 1 project 2026-03-14 18:40:42 -04:00
eb927b3038 remade into 1 project 2026-03-14 18:33:38 -04:00
42 changed files with 1971 additions and 1946 deletions

25
.dockerignore Normal file
View File

@@ -0,0 +1,25 @@
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/.idea
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

184
.gitignore vendored
View File

@@ -1,93 +1,93 @@
############################################ ############################################
# .NET Build # .NET Build
############################################ ############################################
bin/ bin/
obj/ obj/
out/ out/
publish/ publish/
############################################ ############################################
# Visual Studio # Visual Studio
############################################ ############################################
.vs/ .vs/
*.user *.user
*.suo *.suo
*.userprefs *.userprefs
*.csproj.user *.csproj.user
*.dbmdl *.dbmdl
*.cache *.cache
*.pdb *.pdb
*.opendb *.opendb
############################################ ############################################
# Rider / JetBrains # Rider / JetBrains
############################################ ############################################
.idea/ .idea/
*.sln.iml *.sln.iml
############################################ ############################################
# VSCode # VSCode
############################################ ############################################
.vscode/ .vscode/
############################################ ############################################
# NuGet # NuGet
############################################ ############################################
*.nupkg *.nupkg
*.snupkg *.snupkg
packages/ packages/
.nuget/ .nuget/
.nuget/packages/ .nuget/packages/
############################################ ############################################
# Logs # Logs
############################################ ############################################
*.log *.log
logs/ logs/
############################################ ############################################
# OS files # OS files
############################################ ############################################
.DS_Store .DS_Store
Thumbs.db Thumbs.db
############################################ ############################################
# Local secrets / environment # Local secrets / environment
############################################ ############################################
.env .env
.env.* .env.*
secrets.json secrets.json
appsettings.Development.json appsettings.Development.json
############################################ ############################################
# E2EE private keys # E2EE private keys
############################################ ############################################
keys/* keys/*
!keys/.gitkeep !keys/.gitkeep
############################################ ############################################
# Local test databases / data folders # Local test databases / data folders
############################################ ############################################
data/ data/
*.db *.db
*.sqlite *.sqlite
*.sqlite3 *.sqlite3
############################################ ############################################
# Temporary files # Temporary files
############################################ ############################################
*.tmp *.tmp
*.temp *.temp
*.bak *.bak
*.swp *.swp

124
Relay.sln
View File

@@ -1,62 +1,62 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59 VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelayCore", "RelayCore\RelayCore.csproj", "{346BE501-DE74-4E88-9787-4722FBC8BD0D}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelayCore", "RelayCore\RelayCore.csproj", "{346BE501-DE74-4E88-9787-4722FBC8BD0D}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelayClient", "RelayClient\RelayClient.csproj", "{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelayClient", "RelayClient\RelayClient.csproj", "{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelayServer", "RelayServer\RelayServer.csproj", "{38995780-E9AA-44D6-B62D-07CCA45E4E4C}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelayServer", "RelayServer\RelayServer.csproj", "{38995780-E9AA-44D6-B62D-07CCA45E4E4C}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
Debug|x86 = Debug|x86 Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64 Release|x64 = Release|x64
Release|x86 = Release|x86 Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|Any CPU.Build.0 = Debug|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x64.ActiveCfg = Debug|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x64.ActiveCfg = Debug|Any CPU
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x64.Build.0 = Debug|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x64.Build.0 = Debug|Any CPU
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x86.ActiveCfg = Debug|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x86.ActiveCfg = Debug|Any CPU
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x86.Build.0 = Debug|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x86.Build.0 = Debug|Any CPU
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|Any CPU.Build.0 = Release|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|Any CPU.Build.0 = Release|Any CPU
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x64.ActiveCfg = Release|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x64.ActiveCfg = Release|Any CPU
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x64.Build.0 = Release|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x64.Build.0 = Release|Any CPU
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x86.ActiveCfg = Release|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x86.ActiveCfg = Release|Any CPU
{346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x86.Build.0 = Release|Any CPU {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x86.Build.0 = Release|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|Any CPU.Build.0 = Debug|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x64.ActiveCfg = Debug|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x64.ActiveCfg = Debug|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x64.Build.0 = Debug|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x64.Build.0 = Debug|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x86.ActiveCfg = Debug|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x86.ActiveCfg = Debug|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x86.Build.0 = Debug|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x86.Build.0 = Debug|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|Any CPU.ActiveCfg = Release|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|Any CPU.Build.0 = Release|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|Any CPU.Build.0 = Release|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x64.ActiveCfg = Release|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x64.ActiveCfg = Release|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x64.Build.0 = Release|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x64.Build.0 = Release|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x86.ActiveCfg = Release|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x86.ActiveCfg = Release|Any CPU
{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x86.Build.0 = Release|Any CPU {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x86.Build.0 = Release|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|Any CPU.Build.0 = Debug|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x64.ActiveCfg = Debug|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x64.ActiveCfg = Debug|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x64.Build.0 = Debug|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x64.Build.0 = Debug|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x86.ActiveCfg = Debug|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x86.ActiveCfg = Debug|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x86.Build.0 = Debug|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x86.Build.0 = Debug|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|Any CPU.ActiveCfg = Release|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|Any CPU.Build.0 = Release|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|Any CPU.Build.0 = Release|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x64.ActiveCfg = Release|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x64.ActiveCfg = Release|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x64.Build.0 = Release|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x64.Build.0 = Release|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x86.ActiveCfg = Release|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x86.ActiveCfg = Release|Any CPU
{38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x86.Build.0 = Release|Any CPU {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

184
RelayClient/.gitignore vendored
View File

@@ -1,93 +1,93 @@
############################################ ############################################
# .NET Build # .NET Build
############################################ ############################################
bin/ bin/
obj/ obj/
out/ out/
publish/ publish/
############################################ ############################################
# Visual Studio # Visual Studio
############################################ ############################################
.vs/ .vs/
*.user *.user
*.suo *.suo
*.userprefs *.userprefs
*.csproj.user *.csproj.user
*.dbmdl *.dbmdl
*.cache *.cache
*.pdb *.pdb
*.opendb *.opendb
############################################ ############################################
# Rider / JetBrains # Rider / JetBrains
############################################ ############################################
.idea/ .idea/
*.sln.iml *.sln.iml
############################################ ############################################
# VSCode # VSCode
############################################ ############################################
.vscode/ .vscode/
############################################ ############################################
# NuGet # NuGet
############################################ ############################################
*.nupkg *.nupkg
*.snupkg *.snupkg
packages/ packages/
.nuget/ .nuget/
.nuget/packages/ .nuget/packages/
############################################ ############################################
# Logs # Logs
############################################ ############################################
*.log *.log
logs/ logs/
############################################ ############################################
# OS files # OS files
############################################ ############################################
.DS_Store .DS_Store
Thumbs.db Thumbs.db
############################################ ############################################
# Local secrets / environment # Local secrets / environment
############################################ ############################################
.env .env
.env.* .env.*
secrets.json secrets.json
appsettings.Development.json appsettings.Development.json
############################################ ############################################
# E2EE private keys # E2EE private keys
############################################ ############################################
keys/* keys/*
!keys/.gitkeep !keys/.gitkeep
############################################ ############################################
# Local test databases / data folders # Local test databases / data folders
############################################ ############################################
data/ data/
*.db *.db
*.sqlite *.sqlite
*.sqlite3 *.sqlite3
############################################ ############################################
# Temporary files # Temporary files
############################################ ############################################
*.tmp *.tmp
*.temp *.temp
*.bak *.bak
*.swp *.swp

View File

@@ -1,14 +1,14 @@
<?xml version = "1.0" encoding = "UTF-8" ?> <?xml version = "1.0" encoding = "UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui" <Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:RelayClient" xmlns:local="clr-namespace:RelayClient"
x:Class="RelayClient.App"> x:Class="RelayClient.App">
<Application.Resources> <Application.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml" /> <ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" /> <ResourceDictionary Source="Resources/Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</Application.Resources> </Application.Resources>
</Application> </Application>

View File

@@ -1,16 +1,16 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace RelayClient; namespace RelayClient;
public partial class App : Application public partial class App : Application
{ {
public App() public App()
{ {
InitializeComponent(); InitializeComponent();
} }
protected override Window CreateWindow(IActivationState? activationState) protected override Window CreateWindow(IActivationState? activationState)
{ {
return new Window(new AppShell()); return new Window(new AppShell());
} }
} }

View File

@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<Shell <Shell
x:Class="RelayClient.AppShell" x:Class="RelayClient.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:RelayClient" xmlns:local="clr-namespace:RelayClient"
Title="RelayClient"> Title="RelayClient">
<ShellContent <ShellContent
Title="Home" Title="Home"
ContentTemplate="{DataTemplate local:MainPage}" ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage" /> Route="MainPage" />
</Shell> </Shell>

View File

@@ -1,9 +1,9 @@
namespace RelayClient; namespace RelayClient;
public partial class AppShell : Shell public partial class AppShell : Shell
{ {
public AppShell() public AppShell()
{ {
InitializeComponent(); InitializeComponent();
} }
} }

View File

@@ -1,36 +1,36 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="RelayClient.MainPage"> x:Class="RelayClient.MainPage">
<ScrollView> <ScrollView>
<VerticalStackLayout <VerticalStackLayout
Padding="30,0" Padding="30,0"
Spacing="25"> Spacing="25">
<Image <Image
Source="dotnet_bot.png" Source="dotnet_bot.png"
HeightRequest="185" HeightRequest="185"
Aspect="AspectFit" Aspect="AspectFit"
SemanticProperties.Description="dot net bot in a submarine number ten" /> SemanticProperties.Description="dot net bot in a submarine number ten" />
<Label <Label
Text="Hello, World!" Text="Hello, World!"
Style="{StaticResource Headline}" Style="{StaticResource Headline}"
SemanticProperties.HeadingLevel="Level1" /> SemanticProperties.HeadingLevel="Level1" />
<Label <Label
Text="Welcome to &#10;.NET Multi-platform App UI" Text="Welcome to &#10;.NET Multi-platform App UI"
Style="{StaticResource SubHeadline}" Style="{StaticResource SubHeadline}"
SemanticProperties.HeadingLevel="Level2" SemanticProperties.HeadingLevel="Level2"
SemanticProperties.Description="Welcome to dot net Multi platform App U I" /> SemanticProperties.Description="Welcome to dot net Multi platform App U I" />
<Button <Button
x:Name="CounterBtn" x:Name="CounterBtn"
Text="Click me" Text="Click me"
SemanticProperties.Hint="Counts the number of times you click" SemanticProperties.Hint="Counts the number of times you click"
Clicked="OnCounterClicked" Clicked="OnCounterClicked"
HorizontalOptions="Fill" /> HorizontalOptions="Fill" />
</VerticalStackLayout> </VerticalStackLayout>
</ScrollView> </ScrollView>
</ContentPage> </ContentPage>

View File

@@ -1,23 +1,23 @@
namespace RelayClient; namespace RelayClient;
public partial class MainPage : ContentPage public partial class MainPage : ContentPage
{ {
int count = 0; int count = 0;
public MainPage() public MainPage()
{ {
InitializeComponent(); InitializeComponent();
} }
private void OnCounterClicked(object? sender, EventArgs e) private void OnCounterClicked(object? sender, EventArgs e)
{ {
count++; count++;
if (count == 1) if (count == 1)
CounterBtn.Text = $"Clicked {count} time"; CounterBtn.Text = $"Clicked {count} time";
else else
CounterBtn.Text = $"Clicked {count} times"; CounterBtn.Text = $"Clicked {count} times";
SemanticScreenReader.Announce(CounterBtn.Text); SemanticScreenReader.Announce(CounterBtn.Text);
} }
} }

View File

@@ -1,25 +1,25 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Maui.Hosting; using Microsoft.Maui.Hosting;
namespace RelayClient; namespace RelayClient;
public static class MauiProgram public static class MauiProgram
{ {
public static MauiApp CreateMauiApp() public static MauiApp CreateMauiApp()
{ {
var builder = MauiApp.CreateBuilder(); var builder = MauiApp.CreateBuilder();
builder builder
.UseMauiApp<App>() .UseMauiApp<App>()
.ConfigureFonts(fonts => .ConfigureFonts(fonts =>
{ {
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
}); });
#if DEBUG #if DEBUG
builder.Logging.AddDebug(); builder.Logging.AddDebug();
#endif #endif
return builder.Build(); return builder.Build();
} }
} }

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application> <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
</manifest> </manifest>

View File

@@ -1,12 +1,12 @@
using Android.App; using Android.App;
using Android.Content.PM; using Android.Content.PM;
using Android.OS; using Android.OS;
namespace RelayClient; namespace RelayClient;
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode |
ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity public class MainActivity : MauiAppCompatActivity
{ {
} }

View File

@@ -1,15 +1,15 @@
using Android.App; using Android.App;
using Android.Runtime; using Android.Runtime;
namespace RelayClient; namespace RelayClient;
[Application] [Application]
public class MainApplication : MauiApplication public class MainApplication : MauiApplication
{ {
public MainApplication(IntPtr handle, JniHandleOwnership ownership) public MainApplication(IntPtr handle, JniHandleOwnership ownership)
: base(handle, ownership) : base(handle, ownership)
{ {
} }
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
} }

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="colorPrimary">#512BD4</color> <color name="colorPrimary">#512BD4</color>
<color name="colorPrimaryDark">#2B0B98</color> <color name="colorPrimaryDark">#2B0B98</color>
<color name="colorAccent">#2B0B98</color> <color name="colorAccent">#2B0B98</color>
</resources> </resources>

View File

@@ -1,9 +1,9 @@
using Foundation; using Foundation;
namespace RelayClient; namespace RelayClient;
[Register("AppDelegate")] [Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate public class AppDelegate : MauiUIApplicationDelegate
{ {
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
} }

View File

@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<!-- See https://aka.ms/maui-publish-app-store#add-entitlements for more information about adding entitlements.--> <!-- See https://aka.ms/maui-publish-app-store#add-entitlements for more information about adding entitlements.-->
<dict> <dict>
<!-- App Sandbox must be enabled to distribute a MacCatalyst app through the Mac App Store. --> <!-- App Sandbox must be enabled to distribute a MacCatalyst app through the Mac App Store. -->
<key>com.apple.security.app-sandbox</key> <key>com.apple.security.app-sandbox</key>
<true/> <true/>
<!-- When App Sandbox is enabled, this value is required to open outgoing network connections. --> <!-- When App Sandbox is enabled, this value is required to open outgoing network connections. -->
<key>com.apple.security.network.client</key> <key>com.apple.security.network.client</key>
<true/> <true/>
</dict> </dict>
</plist> </plist>

View File

@@ -1,40 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<!-- The Mac App Store requires you specify if the app uses encryption. --> <!-- The Mac App Store requires you specify if the app uses encryption. -->
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/itsappusesnonexemptencryption --> <!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/itsappusesnonexemptencryption -->
<!-- <key>ITSAppUsesNonExemptEncryption</key> --> <!-- <key>ITSAppUsesNonExemptEncryption</key> -->
<!-- Please indicate <true/> or <false/> here. --> <!-- Please indicate <true/> or <false/> here. -->
<!-- Specify the category for your app here. --> <!-- Specify the category for your app here. -->
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype --> <!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype -->
<!-- <key>LSApplicationCategoryType</key> --> <!-- <key>LSApplicationCategoryType</key> -->
<!-- <string>public.app-category.YOUR-CATEGORY-HERE</string> --> <!-- <string>public.app-category.YOUR-CATEGORY-HERE</string> -->
<key>UIDeviceFamily</key> <key>UIDeviceFamily</key>
<array> <array>
<integer>2</integer> <integer>2</integer>
</array> </array>
<key>LSApplicationCategoryType</key> <key>LSApplicationCategoryType</key>
<string>public.app-category.lifestyle</string> <string>public.app-category.lifestyle</string>
<key>UIRequiredDeviceCapabilities</key> <key>UIRequiredDeviceCapabilities</key>
<array> <array>
<string>arm64</string> <string>arm64</string>
</array> </array>
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>UISupportedInterfaceOrientations~ipad</key> <key>UISupportedInterfaceOrientations~ipad</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string> <string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>XSAppIconAssets</key> <key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string> <string>Assets.xcassets/appicon.appiconset</string>
</dict> </dict>
</plist> </plist>

View File

@@ -1,15 +1,15 @@
using ObjCRuntime; using ObjCRuntime;
using UIKit; using UIKit;
namespace RelayClient; namespace RelayClient;
public class Program public class Program
{ {
// This is the main entry point of the application. // This is the main entry point of the application.
static void Main(string[] args) static void Main(string[] args)
{ {
// if you want to use a different Application Delegate class from "AppDelegate" // if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here. // you can specify it here.
UIApplication.Main(args, null, typeof(AppDelegate)); UIApplication.Main(args, null, typeof(AppDelegate));
} }
} }

View File

@@ -1,8 +1,8 @@
<maui:MauiWinUIApplication <maui:MauiWinUIApplication
x:Class="RelayClient.WinUI.App" x:Class="RelayClient.WinUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:maui="using:Microsoft.Maui" xmlns:maui="using:Microsoft.Maui"
xmlns:local="using:RelayClient.WinUI"> xmlns:local="using:RelayClient.WinUI">
</maui:MauiWinUIApplication> </maui:MauiWinUIApplication>

View File

@@ -1,23 +1,23 @@
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
// To learn more about WinUI, the WinUI project structure, // To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info. // and more about our project templates, see: http://aka.ms/winui-project-info.
namespace RelayClient.WinUI; namespace RelayClient.WinUI;
/// <summary> /// <summary>
/// Provides application-specific behavior to supplement the default Application class. /// Provides application-specific behavior to supplement the default Application class.
/// </summary> /// </summary>
public partial class App : MauiWinUIApplication public partial class App : MauiWinUIApplication
{ {
/// <summary> /// <summary>
/// Initializes the singleton application object. This is the first line of authored code /// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain(). /// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary> /// </summary>
public App() public App()
{ {
this.InitializeComponent(); this.InitializeComponent();
} }
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
} }

View File

@@ -1,46 +1,46 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Package <Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap"> IgnorableNamespaces="uap rescap">
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" /> <Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" />
<mp:PhoneIdentity PhoneProductId="19688391-335B-479B-9E8A-8026C5759DFE" PhonePublisherId="00000000-0000-0000-0000-000000000000"/> <mp:PhoneIdentity PhoneProductId="19688391-335B-479B-9E8A-8026C5759DFE" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties> <Properties>
<DisplayName>$placeholder$</DisplayName> <DisplayName>$placeholder$</DisplayName>
<PublisherDisplayName>User Name</PublisherDisplayName> <PublisherDisplayName>User Name</PublisherDisplayName>
<Logo>$placeholder$.png</Logo> <Logo>$placeholder$.png</Logo>
</Properties> </Properties>
<Dependencies> <Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /> <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /> <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
</Dependencies> </Dependencies>
<Resources> <Resources>
<Resource Language="x-generate" /> <Resource Language="x-generate" />
</Resources> </Resources>
<Applications> <Applications>
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$"> <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
<uap:VisualElements <uap:VisualElements
DisplayName="$placeholder$" DisplayName="$placeholder$"
Description="$placeholder$" Description="$placeholder$"
Square150x150Logo="$placeholder$.png" Square150x150Logo="$placeholder$.png"
Square44x44Logo="$placeholder$.png" Square44x44Logo="$placeholder$.png"
BackgroundColor="transparent"> BackgroundColor="transparent">
<uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" /> <uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" />
<uap:SplashScreen Image="$placeholder$.png" /> <uap:SplashScreen Image="$placeholder$.png" />
</uap:VisualElements> </uap:VisualElements>
</Application> </Application>
</Applications> </Applications>
<Capabilities> <Capabilities>
<rescap:Capability Name="runFullTrust" /> <rescap:Capability Name="runFullTrust" />
</Capabilities> </Capabilities>
</Package> </Package>

View File

@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="RelayClient.WinUI.app"/> <assemblyIdentity version="1.0.0.0" name="RelayClient.WinUI.app"/>
<application xmlns="urn:schemas-microsoft-com:asm.v3"> <application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings> <windowsSettings>
<!-- The combination of below two tags have the following effect: <!-- The combination of below two tags have the following effect:
1) Per-Monitor for >= Windows 10 Anniversary Update 1) Per-Monitor for >= Windows 10 Anniversary Update
2) System < Windows 10 Anniversary Update 2) System < Windows 10 Anniversary Update
--> -->
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware> <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness> <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware> <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings> </windowsSettings>
</application> </application>
</assembly> </assembly>

View File

@@ -1,9 +1,9 @@
using Foundation; using Foundation;
namespace RelayClient; namespace RelayClient;
[Register("AppDelegate")] [Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate public class AppDelegate : MauiUIApplicationDelegate
{ {
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
} }

View File

@@ -1,32 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UIDeviceFamily</key> <key>UIDeviceFamily</key>
<array> <array>
<integer>1</integer> <integer>1</integer>
<integer>2</integer> <integer>2</integer>
</array> </array>
<key>UIRequiredDeviceCapabilities</key> <key>UIRequiredDeviceCapabilities</key>
<array> <array>
<string>arm64</string> <string>arm64</string>
</array> </array>
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>UISupportedInterfaceOrientations~ipad</key> <key>UISupportedInterfaceOrientations~ipad</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string> <string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>XSAppIconAssets</key> <key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string> <string>Assets.xcassets/appicon.appiconset</string>
</dict> </dict>
</plist> </plist>

View File

@@ -1,15 +1,15 @@
using ObjCRuntime; using ObjCRuntime;
using UIKit; using UIKit;
namespace RelayClient; namespace RelayClient;
public class Program public class Program
{ {
// This is the main entry point of the application. // This is the main entry point of the application.
static void Main(string[] args) static void Main(string[] args)
{ {
// if you want to use a different Application Delegate class from "AppDelegate" // if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here. // you can specify it here.
UIApplication.Main(args, null, typeof(AppDelegate)); UIApplication.Main(args, null, typeof(AppDelegate));
} }
} }

View File

@@ -1,51 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
This is the minimum required version of the Apple Privacy Manifest for .NET MAUI apps. This is the minimum required version of the Apple Privacy Manifest for .NET MAUI apps.
The contents below are needed because of APIs that are used in the .NET framework and .NET MAUI SDK. The contents below are needed because of APIs that are used in the .NET framework and .NET MAUI SDK.
You are responsible for adding extra entries as needed for your application. You are responsible for adding extra entries as needed for your application.
More information: https://aka.ms/maui-privacy-manifest More information: https://aka.ms/maui-privacy-manifest
--> -->
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>NSPrivacyAccessedAPITypes</key> <key>NSPrivacyAccessedAPITypes</key>
<array> <array>
<dict> <dict>
<key>NSPrivacyAccessedAPIType</key> <key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string> <string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key> <key>NSPrivacyAccessedAPITypeReasons</key>
<array> <array>
<string>C617.1</string> <string>C617.1</string>
</array> </array>
</dict> </dict>
<dict> <dict>
<key>NSPrivacyAccessedAPIType</key> <key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string> <string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key> <key>NSPrivacyAccessedAPITypeReasons</key>
<array> <array>
<string>35F9.1</string> <string>35F9.1</string>
</array> </array>
</dict> </dict>
<dict> <dict>
<key>NSPrivacyAccessedAPIType</key> <key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string> <string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key> <key>NSPrivacyAccessedAPITypeReasons</key>
<array> <array>
<string>E174.1</string> <string>E174.1</string>
</array> </array>
</dict> </dict>
<!-- <!--
The entry below is only needed when you're using the Preferences API in your app. The entry below is only needed when you're using the Preferences API in your app.
<dict> <dict>
<key>NSPrivacyAccessedAPIType</key> <key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string> <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key> <key>NSPrivacyAccessedAPITypeReasons</key>
<array> <array>
<string>CA92.1</string> <string>CA92.1</string>
</array> </array>
</dict> --> </dict> -->
</array> </array>
</dict> </dict>
</plist> </plist>

View File

@@ -1,8 +1,8 @@
{ {
"profiles": { "profiles": {
"Windows Machine": { "Windows Machine": {
"commandName": "Project", "commandName": "Project",
"nativeDebugging": false "nativeDebugging": false
} }
} }
} }

View File

@@ -1,46 +1,46 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net10.0-android;net10.0-ios;net10.0-maccatalyst</TargetFrameworks> <TargetFrameworks>net10.0-android;net10.0-ios;net10.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))"> <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">
$(TargetFrameworks);net10.0-windows10.0.19041.0 $(TargetFrameworks);net10.0-windows10.0.19041.0
</TargetFrameworks> </TargetFrameworks>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RootNamespace>RelayClient</RootNamespace> <RootNamespace>RelayClient</RootNamespace>
<UseMaui>true</UseMaui> <UseMaui>true</UseMaui>
<SingleProject>true</SingleProject> <SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<MauiXamlInflator>SourceGen</MauiXamlInflator> <MauiXamlInflator>SourceGen</MauiXamlInflator>
<ApplicationTitle>RelayClient</ApplicationTitle> <ApplicationTitle>RelayClient</ApplicationTitle>
<ApplicationId>com.companyname.relayclient</ApplicationId> <ApplicationId>com.companyname.relayclient</ApplicationId>
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion> <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion> <ApplicationVersion>1</ApplicationVersion>
<WindowsPackageType>None</WindowsPackageType> <WindowsPackageType>None</WindowsPackageType>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion> <TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" /> <MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" /> <MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
<MauiImage Include="Resources\Images\*" /> <MauiImage Include="Resources\Images\*" />
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" /> <MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
<MauiFont Include="Resources\Fonts\*" /> <MauiFont Include="Resources\Fonts\*" />
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" /> <PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="10.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="10.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg"> <svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="456" height="456" fill="#512BD4" /> <rect x="0" y="0" width="456" height="456" fill="#512BD4" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 231 B

After

Width:  |  Height:  |  Size: 228 B

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> <svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> <path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> <path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> <path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> <path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,15 +1,15 @@
Any raw assets you want to be deployed with your application can be placed in Any raw assets you want to be deployed with your application can be placed in
this directory (and child directories). Deployment of the asset to your application this directory (and child directories). Deployment of the asset to your application
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
These files will be deployed with your package and will be accessible using Essentials: These files will be deployed with your package and will be accessible using Essentials:
async Task LoadMauiAsset() async Task LoadMauiAsset()
{ {
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
using var reader = new StreamReader(stream); using var reader = new StreamReader(stream);
var contents = reader.ReadToEnd(); var contents = reader.ReadToEnd();
} }

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> <svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> <path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> <path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> <path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> <path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,44 +1,44 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<ResourceDictionary <ResourceDictionary
xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<!-- Note: For Android please see also Platforms\Android\Resources\values\colors.xml --> <!-- Note: For Android please see also Platforms\Android\Resources\values\colors.xml -->
<Color x:Key="Primary">#512BD4</Color> <Color x:Key="Primary">#512BD4</Color>
<Color x:Key="PrimaryDark">#ac99ea</Color> <Color x:Key="PrimaryDark">#ac99ea</Color>
<Color x:Key="PrimaryDarkText">#242424</Color> <Color x:Key="PrimaryDarkText">#242424</Color>
<Color x:Key="Secondary">#DFD8F7</Color> <Color x:Key="Secondary">#DFD8F7</Color>
<Color x:Key="SecondaryDarkText">#9880e5</Color> <Color x:Key="SecondaryDarkText">#9880e5</Color>
<Color x:Key="Tertiary">#2B0B98</Color> <Color x:Key="Tertiary">#2B0B98</Color>
<Color x:Key="White">White</Color> <Color x:Key="White">White</Color>
<Color x:Key="Black">Black</Color> <Color x:Key="Black">Black</Color>
<Color x:Key="Magenta">#D600AA</Color> <Color x:Key="Magenta">#D600AA</Color>
<Color x:Key="MidnightBlue">#190649</Color> <Color x:Key="MidnightBlue">#190649</Color>
<Color x:Key="OffBlack">#1f1f1f</Color> <Color x:Key="OffBlack">#1f1f1f</Color>
<Color x:Key="Gray100">#E1E1E1</Color> <Color x:Key="Gray100">#E1E1E1</Color>
<Color x:Key="Gray200">#C8C8C8</Color> <Color x:Key="Gray200">#C8C8C8</Color>
<Color x:Key="Gray300">#ACACAC</Color> <Color x:Key="Gray300">#ACACAC</Color>
<Color x:Key="Gray400">#919191</Color> <Color x:Key="Gray400">#919191</Color>
<Color x:Key="Gray500">#6E6E6E</Color> <Color x:Key="Gray500">#6E6E6E</Color>
<Color x:Key="Gray600">#404040</Color> <Color x:Key="Gray600">#404040</Color>
<Color x:Key="Gray900">#212121</Color> <Color x:Key="Gray900">#212121</Color>
<Color x:Key="Gray950">#141414</Color> <Color x:Key="Gray950">#141414</Color>
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/> <SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/>
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/> <SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/>
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/> <SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/>
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/> <SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/>
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/> <SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/>
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/> <SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/>
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/> <SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/>
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/> <SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/>
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/> <SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/>
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/> <SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/>
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/> <SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/>
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/> <SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/>
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/> <SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/>
</ResourceDictionary> </ResourceDictionary>

View File

@@ -1,434 +1,434 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<ResourceDictionary <ResourceDictionary
xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Style TargetType="ActivityIndicator"> <Style TargetType="ActivityIndicator">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> <Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
</Style> </Style>
<Style TargetType="IndicatorView"> <Style TargetType="IndicatorView">
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/> <Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/>
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/> <Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/>
</Style> </Style>
<Style TargetType="Border"> <Style TargetType="Border">
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> <Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="StrokeShape" Value="Rectangle"/> <Setter Property="StrokeShape" Value="Rectangle"/>
<Setter Property="StrokeThickness" Value="1"/> <Setter Property="StrokeThickness" Value="1"/>
</Style> </Style>
<Style TargetType="BoxView"> <Style TargetType="BoxView">
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
</Style> </Style>
<Style TargetType="Button"> <Style TargetType="Button">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource PrimaryDarkText}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource PrimaryDarkText}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}}" /> <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/> <Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/> <Setter Property="FontSize" Value="14"/>
<Setter Property="BorderWidth" Value="0"/> <Setter Property="BorderWidth" Value="0"/>
<Setter Property="CornerRadius" Value="8"/> <Setter Property="CornerRadius" Value="8"/>
<Setter Property="Padding" Value="14,10"/> <Setter Property="Padding" Value="14,10"/>
<Setter Property="MinimumHeightRequest" Value="44"/> <Setter Property="MinimumHeightRequest" Value="44"/>
<Setter Property="MinimumWidthRequest" Value="44"/> <Setter Property="MinimumWidthRequest" Value="44"/>
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" /> <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
<VisualState x:Name="PointerOver" /> <VisualState x:Name="PointerOver" />
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="CheckBox"> <Style TargetType="CheckBox">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> <Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="MinimumHeightRequest" Value="44"/> <Setter Property="MinimumHeightRequest" Value="44"/>
<Setter Property="MinimumWidthRequest" Value="44"/> <Setter Property="MinimumWidthRequest" Value="44"/>
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="DatePicker"> <Style TargetType="DatePicker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" /> <Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/> <Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/> <Setter Property="FontSize" Value="14"/>
<Setter Property="MinimumHeightRequest" Value="44"/> <Setter Property="MinimumHeightRequest" Value="44"/>
<Setter Property="MinimumWidthRequest" Value="44"/> <Setter Property="MinimumWidthRequest" Value="44"/>
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="Editor"> <Style TargetType="Editor">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" /> <Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/> <Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14" /> <Setter Property="FontSize" Value="14" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> <Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="MinimumHeightRequest" Value="44"/> <Setter Property="MinimumHeightRequest" Value="44"/>
<Setter Property="MinimumWidthRequest" Value="44"/> <Setter Property="MinimumWidthRequest" Value="44"/>
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="Entry"> <Style TargetType="Entry">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" /> <Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/> <Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14" /> <Setter Property="FontSize" Value="14" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> <Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="MinimumHeightRequest" Value="44"/> <Setter Property="MinimumHeightRequest" Value="44"/>
<Setter Property="MinimumWidthRequest" Value="44"/> <Setter Property="MinimumWidthRequest" Value="44"/>
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="ImageButton"> <Style TargetType="ImageButton">
<Setter Property="Opacity" Value="1" /> <Setter Property="Opacity" Value="1" />
<Setter Property="BorderColor" Value="Transparent"/> <Setter Property="BorderColor" Value="Transparent"/>
<Setter Property="BorderWidth" Value="0"/> <Setter Property="BorderWidth" Value="0"/>
<Setter Property="CornerRadius" Value="0"/> <Setter Property="CornerRadius" Value="0"/>
<Setter Property="MinimumHeightRequest" Value="44"/> <Setter Property="MinimumHeightRequest" Value="44"/>
<Setter Property="MinimumWidthRequest" Value="44"/> <Setter Property="MinimumWidthRequest" Value="44"/>
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="Opacity" Value="0.5" /> <Setter Property="Opacity" Value="0.5" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
<VisualState x:Name="PointerOver" /> <VisualState x:Name="PointerOver" />
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="Label"> <Style TargetType="Label">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" /> <Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" /> <Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" /> <Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="Label" x:Key="Headline"> <Style TargetType="Label" x:Key="Headline">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
<Setter Property="FontSize" Value="32" /> <Setter Property="FontSize" Value="32" />
<Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="HorizontalTextAlignment" Value="Center" /> <Setter Property="HorizontalTextAlignment" Value="Center" />
</Style> </Style>
<Style TargetType="Label" x:Key="SubHeadline"> <Style TargetType="Label" x:Key="SubHeadline">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
<Setter Property="FontSize" Value="24" /> <Setter Property="FontSize" Value="24" />
<Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="HorizontalTextAlignment" Value="Center" /> <Setter Property="HorizontalTextAlignment" Value="Center" />
</Style> </Style>
<Style TargetType="Picker"> <Style TargetType="Picker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> <Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
<Setter Property="BackgroundColor" Value="Transparent" /> <Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/> <Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14" /> <Setter Property="FontSize" Value="14" />
<Setter Property="MinimumHeightRequest" Value="44"/> <Setter Property="MinimumHeightRequest" Value="44"/>
<Setter Property="MinimumWidthRequest" Value="44"/> <Setter Property="MinimumWidthRequest" Value="44"/>
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="ProgressBar"> <Style TargetType="ProgressBar">
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> <Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="RadioButton"> <Style TargetType="RadioButton">
<Setter Property="BackgroundColor" Value="Transparent"/> <Setter Property="BackgroundColor" Value="Transparent"/>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/> <Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/> <Setter Property="FontSize" Value="14"/>
<Setter Property="MinimumHeightRequest" Value="44"/> <Setter Property="MinimumHeightRequest" Value="44"/>
<Setter Property="MinimumWidthRequest" Value="44"/> <Setter Property="MinimumWidthRequest" Value="44"/>
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="RefreshView"> <Style TargetType="RefreshView">
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> <Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
</Style> </Style>
<Style TargetType="SearchBar"> <Style TargetType="SearchBar">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" /> <Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" /> <Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" />
<Setter Property="BackgroundColor" Value="Transparent" /> <Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" /> <Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" /> <Setter Property="FontSize" Value="14" />
<Setter Property="MinimumHeightRequest" Value="44"/> <Setter Property="MinimumHeightRequest" Value="44"/>
<Setter Property="MinimumWidthRequest" Value="44"/> <Setter Property="MinimumWidthRequest" Value="44"/>
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="SearchHandler"> <Style TargetType="SearchHandler">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" /> <Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
<Setter Property="BackgroundColor" Value="Transparent" /> <Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" /> <Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" /> <Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="Shadow"> <Style TargetType="Shadow">
<Setter Property="Radius" Value="15" /> <Setter Property="Radius" Value="15" />
<Setter Property="Opacity" Value="0.5" /> <Setter Property="Opacity" Value="0.5" />
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" /> <Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
<Setter Property="Offset" Value="10,10" /> <Setter Property="Offset" Value="10,10" />
</Style> </Style>
<Style TargetType="Slider"> <Style TargetType="Slider">
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> <Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" /> <Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> <Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> <Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> <Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> <Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="SwipeItem"> <Style TargetType="SwipeItem">
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
</Style> </Style>
<Style TargetType="Switch"> <Style TargetType="Switch">
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> <Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="ThumbColor" Value="{StaticResource White}" /> <Setter Property="ThumbColor" Value="{StaticResource White}" />
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
<VisualState x:Name="On"> <VisualState x:Name="On">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" /> <Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> <Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
<VisualState x:Name="Off"> <VisualState x:Name="Off">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" /> <Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<Style TargetType="TimePicker"> <Style TargetType="TimePicker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent"/> <Setter Property="BackgroundColor" Value="Transparent"/>
<Setter Property="FontFamily" Value="OpenSansRegular"/> <Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/> <Setter Property="FontSize" Value="14"/>
<Setter Property="MinimumHeightRequest" Value="44"/> <Setter Property="MinimumHeightRequest" Value="44"/>
<Setter Property="MinimumWidthRequest" Value="44"/> <Setter Property="MinimumWidthRequest" Value="44"/>
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" /> <VisualState x:Name="Normal" />
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
<!-- <!--
<Style TargetType="TitleBar"> <Style TargetType="TitleBar">
<Setter Property="MinimumHeightRequest" Value="32"/> <Setter Property="MinimumHeightRequest" Value="32"/>
<Setter Property="VisualStateManager.VisualStateGroups"> <Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList> <VisualStateGroupList>
<VisualStateGroup x:Name="TitleActiveStates"> <VisualStateGroup x:Name="TitleActiveStates">
<VisualState x:Name="TitleBarTitleActive"> <VisualState x:Name="TitleBarTitleActive">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="BackgroundColor" Value="Transparent" /> <Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> <Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
<VisualState x:Name="TitleBarTitleInactive"> <VisualState x:Name="TitleBarTitleInactive">
<VisualState.Setters> <VisualState.Setters>
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
<Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" /> <Setter Property="ForegroundColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
</VisualState.Setters> </VisualState.Setters>
</VisualState> </VisualState>
</VisualStateGroup> </VisualStateGroup>
</VisualStateGroupList> </VisualStateGroupList>
</Setter> </Setter>
</Style> </Style>
--> -->
<Style TargetType="Page" ApplyToDerivedTypes="True"> <Style TargetType="Page" ApplyToDerivedTypes="True">
<Setter Property="Padding" Value="0"/> <Setter Property="Padding" Value="0"/>
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
</Style> </Style>
<Style TargetType="Shell" ApplyToDerivedTypes="True"> <Style TargetType="Shell" ApplyToDerivedTypes="True">
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> <Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
<Setter Property="Shell.ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" /> <Setter Property="Shell.ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" />
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" /> <Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" />
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" /> <Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" /> <Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" />
<Setter Property="Shell.NavBarHasShadow" Value="False" /> <Setter Property="Shell.NavBarHasShadow" Value="False" />
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> <Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> <Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> <Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> <Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
</Style> </Style>
<Style TargetType="NavigationPage"> <Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> <Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" /> <Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" /> <Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
</Style> </Style>
<Style TargetType="TabbedPage"> <Style TargetType="TabbedPage">
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" /> <Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> <Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" /> <Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> <Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
</Style> </Style>
</ResourceDictionary> </ResourceDictionary>

184
RelayCore/.gitignore vendored
View File

@@ -1,93 +1,93 @@
############################################ ############################################
# .NET Build # .NET Build
############################################ ############################################
bin/ bin/
obj/ obj/
out/ out/
publish/ publish/
############################################ ############################################
# Visual Studio # Visual Studio
############################################ ############################################
.vs/ .vs/
*.user *.user
*.suo *.suo
*.userprefs *.userprefs
*.csproj.user *.csproj.user
*.dbmdl *.dbmdl
*.cache *.cache
*.pdb *.pdb
*.opendb *.opendb
############################################ ############################################
# Rider / JetBrains # Rider / JetBrains
############################################ ############################################
.idea/ .idea/
*.sln.iml *.sln.iml
############################################ ############################################
# VSCode # VSCode
############################################ ############################################
.vscode/ .vscode/
############################################ ############################################
# NuGet # NuGet
############################################ ############################################
*.nupkg *.nupkg
*.snupkg *.snupkg
packages/ packages/
.nuget/ .nuget/
.nuget/packages/ .nuget/packages/
############################################ ############################################
# Logs # Logs
############################################ ############################################
*.log *.log
logs/ logs/
############################################ ############################################
# OS files # OS files
############################################ ############################################
.DS_Store .DS_Store
Thumbs.db Thumbs.db
############################################ ############################################
# Local secrets / environment # Local secrets / environment
############################################ ############################################
.env .env
.env.* .env.*
secrets.json secrets.json
appsettings.Development.json appsettings.Development.json
############################################ ############################################
# E2EE private keys # E2EE private keys
############################################ ############################################
keys/* keys/*
!keys/.gitkeep !keys/.gitkeep
############################################ ############################################
# Local test databases / data folders # Local test databases / data folders
############################################ ############################################
data/ data/
*.db *.db
*.sqlite *.sqlite
*.sqlite3 *.sqlite3
############################################ ############################################
# Temporary files # Temporary files
############################################ ############################################
*.tmp *.tmp
*.temp *.temp
*.bak *.bak
*.swp *.swp

View File

@@ -1,82 +1,82 @@
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
namespace RelayCore; namespace RelayCore;
public static class E2EeHelper public static class E2EeHelper
{ {
public static (string publicKey, string privateKey) GenerateRsaKeyPair() public static (string publicKey, string privateKey) GenerateRsaKeyPair()
{ {
using var rsa = RSA.Create(2048); using var rsa = RSA.Create(2048);
var publicKey = Convert.ToBase64String(rsa.ExportSubjectPublicKeyInfo()); var publicKey = Convert.ToBase64String(rsa.ExportSubjectPublicKeyInfo());
var privateKey = Convert.ToBase64String(rsa.ExportPkcs8PrivateKey()); var privateKey = Convert.ToBase64String(rsa.ExportPkcs8PrivateKey());
return (publicKey, privateKey); return (publicKey, privateKey);
} }
public static EncryptedMessagePayload EncryptForRecipient(string plainText, string recipientPublicKeyBase64) public static EncryptedMessagePayload EncryptForRecipient(string plainText, string recipientPublicKeyBase64)
{ {
var aesKey = RandomNumberGenerator.GetBytes(32); var aesKey = RandomNumberGenerator.GetBytes(32);
var nonce = RandomNumberGenerator.GetBytes(12); var nonce = RandomNumberGenerator.GetBytes(12);
var plainBytes = Encoding.UTF8.GetBytes(plainText); var plainBytes = Encoding.UTF8.GetBytes(plainText);
var cipherBytes = new byte[plainBytes.Length]; var cipherBytes = new byte[plainBytes.Length];
var tag = new byte[16]; var tag = new byte[16];
using (var aes = new AesGcm(aesKey, 16)) using (var aes = new AesGcm(aesKey, 16))
{ {
aes.Encrypt(nonce, plainBytes, cipherBytes, tag); aes.Encrypt(nonce, plainBytes, cipherBytes, tag);
} }
var recipientPublicKey = Convert.FromBase64String(recipientPublicKeyBase64); var recipientPublicKey = Convert.FromBase64String(recipientPublicKeyBase64);
byte[] encryptedKey; byte[] encryptedKey;
using (var rsa = RSA.Create()) using (var rsa = RSA.Create())
{ {
rsa.ImportSubjectPublicKeyInfo(recipientPublicKey, out _); rsa.ImportSubjectPublicKeyInfo(recipientPublicKey, out _);
encryptedKey = rsa.Encrypt(aesKey, RSAEncryptionPadding.OaepSHA256); encryptedKey = rsa.Encrypt(aesKey, RSAEncryptionPadding.OaepSHA256);
} }
return new EncryptedMessagePayload return new EncryptedMessagePayload
{ {
CipherText = Convert.ToBase64String(cipherBytes), CipherText = Convert.ToBase64String(cipherBytes),
Nonce = Convert.ToBase64String(nonce), Nonce = Convert.ToBase64String(nonce),
Tag = Convert.ToBase64String(tag), Tag = Convert.ToBase64String(tag),
EncryptedKey = Convert.ToBase64String(encryptedKey) EncryptedKey = Convert.ToBase64String(encryptedKey)
}; };
} }
public static string DecryptForRecipient(EncryptedMessagePayload payload, string recipientPrivateKeyBase64) public static string DecryptForRecipient(EncryptedMessagePayload payload, string recipientPrivateKeyBase64)
{ {
var encryptedKey = Convert.FromBase64String(payload.EncryptedKey); var encryptedKey = Convert.FromBase64String(payload.EncryptedKey);
var privateKey = Convert.FromBase64String(recipientPrivateKeyBase64); var privateKey = Convert.FromBase64String(recipientPrivateKeyBase64);
byte[] aesKey; byte[] aesKey;
using (var rsa = RSA.Create()) using (var rsa = RSA.Create())
{ {
rsa.ImportPkcs8PrivateKey(privateKey, out _); rsa.ImportPkcs8PrivateKey(privateKey, out _);
aesKey = rsa.Decrypt(encryptedKey, RSAEncryptionPadding.OaepSHA256); aesKey = rsa.Decrypt(encryptedKey, RSAEncryptionPadding.OaepSHA256);
} }
var nonce = Convert.FromBase64String(payload.Nonce); var nonce = Convert.FromBase64String(payload.Nonce);
var tag = Convert.FromBase64String(payload.Tag); var tag = Convert.FromBase64String(payload.Tag);
var cipherBytes = Convert.FromBase64String(payload.CipherText); var cipherBytes = Convert.FromBase64String(payload.CipherText);
var plainBytes = new byte[cipherBytes.Length]; var plainBytes = new byte[cipherBytes.Length];
using (var aes = new AesGcm(aesKey, 16)) using (var aes = new AesGcm(aesKey, 16))
{ {
aes.Decrypt(nonce, cipherBytes, tag, plainBytes); aes.Decrypt(nonce, cipherBytes, tag, plainBytes);
} }
return Encoding.UTF8.GetString(plainBytes); return Encoding.UTF8.GetString(plainBytes);
} }
} }
public class EncryptedMessagePayload public class EncryptedMessagePayload
{ {
public required string CipherText { get; set; } public required string CipherText { get; set; }
public required string Nonce { get; set; } public required string Nonce { get; set; }
public required string Tag { get; set; } public required string Tag { get; set; }
public required string EncryptedKey { get; set; } public required string EncryptedKey { get; set; }
} }

View File

@@ -1,109 +1,109 @@
using System; using System;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using Konscious.Security.Cryptography; using Konscious.Security.Cryptography;
namespace PasswordHasher namespace PasswordHasher
{ {
/// <summary> /// <summary>
/// Provides secure password hashing functionality using Argon2id algorithm /// Provides secure password hashing functionality using Argon2id algorithm
/// </summary> /// </summary>
public class PasswordHasher public class PasswordHasher
{ {
/// <summary> /// <summary>
/// Size of the salt in bytes /// Size of the salt in bytes
/// </summary> /// </summary>
private const int SaltSize = 16; private const int SaltSize = 16;
/// <summary> /// <summary>
/// Size of the hash in bytes /// Size of the hash in bytes
/// </summary> /// </summary>
private const int HashSize = 32; private const int HashSize = 32;
/// <summary> /// <summary>
/// Number of threads to use for parallel computation /// Number of threads to use for parallel computation
/// </summary> /// </summary>
private const int DegreeOfParallelism = 1; private const int DegreeOfParallelism = 1;
/// <summary> /// <summary>
/// Number of iterations for the Argon2id algorithm /// Number of iterations for the Argon2id algorithm
/// </summary> /// </summary>
private const int Iterations = 2; private const int Iterations = 2;
/// <summary> /// <summary>
/// Memory size in KB to use /// Memory size in KB to use
/// </summary> /// </summary>
private const int MemorySize = 19456; // 19 MB private const int MemorySize = 19456; // 19 MB
/// <summary> /// <summary>
/// Generates a secure hash of a password using Argon2id with a random salt /// Generates a secure hash of a password using Argon2id with a random salt
/// </summary> /// </summary>
/// <param name="password">The plain text password to hash</param> /// <param name="password">The plain text password to hash</param>
/// <returns>A Base64 string containing the combined salt and hash</returns> /// <returns>A Base64 string containing the combined salt and hash</returns>
/// <exception cref="ArgumentNullException">Thrown when password is null</exception> /// <exception cref="ArgumentNullException">Thrown when password is null</exception>
public string HashPassword(string password) public string HashPassword(string password)
{ {
// Generate a random salt // Generate a random salt
byte[] salt = new byte[SaltSize]; byte[] salt = new byte[SaltSize];
using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
{ {
rng.GetBytes(salt); rng.GetBytes(salt);
} }
// Create hash // Create hash
byte[] hash = HashPassword(password, salt); byte[] hash = HashPassword(password, salt);
// Combine salt and hash // Combine salt and hash
var combinedBytes = new byte[salt.Length + hash.Length]; var combinedBytes = new byte[salt.Length + hash.Length];
Array.Copy(salt, 0, combinedBytes, 0, salt.Length); Array.Copy(salt, 0, combinedBytes, 0, salt.Length);
Array.Copy(hash, 0, combinedBytes, salt.Length, hash.Length); Array.Copy(hash, 0, combinedBytes, salt.Length, hash.Length);
// Convert to base64 for storage // Convert to base64 for storage
return Convert.ToBase64String(combinedBytes); return Convert.ToBase64String(combinedBytes);
} }
/// <summary> /// <summary>
/// Generates a password hash using Argon2id with a specific salt /// Generates a password hash using Argon2id with a specific salt
/// </summary> /// </summary>
/// <param name="password">The plain text password</param> /// <param name="password">The plain text password</param>
/// <param name="salt">The salt to use for hashing</param> /// <param name="salt">The salt to use for hashing</param>
/// <returns>A byte array containing the password hash</returns> /// <returns>A byte array containing the password hash</returns>
private byte[] HashPassword(string password, byte[] salt) private byte[] HashPassword(string password, byte[] salt)
{ {
var argon2 = new Argon2id(Encoding.UTF8.GetBytes(password)) var argon2 = new Argon2id(Encoding.UTF8.GetBytes(password))
{ {
Salt = salt, Salt = salt,
DegreeOfParallelism = DegreeOfParallelism, DegreeOfParallelism = DegreeOfParallelism,
Iterations = Iterations, Iterations = Iterations,
MemorySize = MemorySize MemorySize = MemorySize
}; };
return argon2.GetBytes(HashSize); return argon2.GetBytes(HashSize);
} }
/// <summary> /// <summary>
/// Verifies if a password matches a stored hash /// Verifies if a password matches a stored hash
/// </summary> /// </summary>
/// <param name="password">The plain text password to verify</param> /// <param name="password">The plain text password to verify</param>
/// <param name="hashedPassword">The stored hash in Base64 format</param> /// <param name="hashedPassword">The stored hash in Base64 format</param>
/// <returns>True if the password matches the hash, false otherwise</returns> /// <returns>True if the password matches the hash, false otherwise</returns>
/// <exception cref="ArgumentNullException">Thrown when password or hashedPassword are null</exception> /// <exception cref="ArgumentNullException">Thrown when password or hashedPassword are null</exception>
/// <exception cref="FormatException">Thrown when hashedPassword is not in valid Base64 format</exception> /// <exception cref="FormatException">Thrown when hashedPassword is not in valid Base64 format</exception>
public bool VerifyPassword(string password, string hashedPassword) public bool VerifyPassword(string password, string hashedPassword)
{ {
// Decode the stored hash // Decode the stored hash
byte[] combinedBytes = Convert.FromBase64String(hashedPassword); byte[] combinedBytes = Convert.FromBase64String(hashedPassword);
// Extract salt and hash // Extract salt and hash
byte[] salt = new byte[SaltSize]; byte[] salt = new byte[SaltSize];
byte[] hash = new byte[HashSize]; byte[] hash = new byte[HashSize];
Array.Copy(combinedBytes, 0, salt, 0, SaltSize); Array.Copy(combinedBytes, 0, salt, 0, SaltSize);
Array.Copy(combinedBytes, SaltSize, hash, 0, HashSize); Array.Copy(combinedBytes, SaltSize, hash, 0, HashSize);
// Compute hash for the input password // Compute hash for the input password
byte[] newHash = HashPassword(password, salt); byte[] newHash = HashPassword(password, salt);
// Compare the hashes // Compare the hashes
return CryptographicOperations.FixedTimeEquals(hash, newHash); return CryptographicOperations.FixedTimeEquals(hash, newHash);
} }
} }
} }

View File

@@ -1,298 +1,298 @@
using SurrealDb.Net; using SurrealDb.Net;
using SurrealDb.Net.Models; using SurrealDb.Net.Models;
using SurrealDb.Net.Models.Auth; using SurrealDb.Net.Models.Auth;
using System.Text.Json; using System.Text.Json;
using PasswordHasher; using PasswordHasher;
using RelayCore; using RelayCore;
using var db = new SurrealDbClient("ws://127.0.0.1:8000/rpc"); using var db = new SurrealDbClient("ws://127.0.0.1:8000/rpc");
await db.SignIn(new RootAuth { Username = "root", Password = "secret" }); await db.SignIn(new RootAuth { Username = "root", Password = "secret" });
await db.Use("test", "test"); await db.Use("test", "test");
var keeper = await CreateUserAsync(db, "Keeper317", "Keeper317@gmail.com", "password"); var keeper = await CreateUserAsync(db, "Keeper317", "Keeper317@gmail.com", "password");
var kira = await CreateUserAsync(db, "Ru_Kira", "jduesling13@gmail.com", "password"); var kira = await CreateUserAsync(db, "Ru_Kira", "jduesling13@gmail.com", "password");
Console.WriteLine($"Keeper created: {ToJsonString(keeper)}"); Console.WriteLine($"Keeper created: {ToJsonString(keeper)}");
Console.WriteLine($"Kira created: {ToJsonString(kira)}"); Console.WriteLine($"Kira created: {ToJsonString(kira)}");
var keeperKeys = E2EeHelper.GenerateRsaKeyPair(); var keeperKeys = E2EeHelper.GenerateRsaKeyPair();
var kiraKeys = E2EeHelper.GenerateRsaKeyPair(); var kiraKeys = E2EeHelper.GenerateRsaKeyPair();
KeyStorage.SavePrivateKey("Keeper317", keeperKeys.privateKey); KeyStorage.SavePrivateKey("Keeper317", keeperKeys.privateKey);
KeyStorage.SavePrivateKey("Ru_Kira", kiraKeys.privateKey); KeyStorage.SavePrivateKey("Ru_Kira", kiraKeys.privateKey);
await db.Create("user_keys", new UserKeys await db.Create("user_keys", new UserKeys
{ {
UserId = keeper.Id.ToString(), UserId = keeper.Id.ToString(),
PublicKey = keeperKeys.publicKey, PublicKey = keeperKeys.publicKey,
CreatedAt = DateTime.UtcNow, CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow UpdatedAt = DateTime.UtcNow
}); });
await db.Create("user_keys", new UserKeys await db.Create("user_keys", new UserKeys
{ {
UserId = kira.Id.ToString(), UserId = kira.Id.ToString(),
PublicKey = kiraKeys.publicKey, PublicKey = kiraKeys.publicKey,
CreatedAt = DateTime.UtcNow, CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow UpdatedAt = DateTime.UtcNow
}); });
Console.WriteLine("Public keys stored for both users."); Console.WriteLine("Public keys stored for both users.");
var conversation = await db.Create("conversations", new Conversations var conversation = await db.Create("conversations", new Conversations
{ {
CreatedByUserId = keeper.Id.ToString(), CreatedByUserId = keeper.Id.ToString(),
CreatedAt = DateTime.UtcNow, CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow,
Title = "Keeper317 + Ru_Kira", Title = "Keeper317 + Ru_Kira",
IsDirectMessage = true IsDirectMessage = true
}); });
Console.WriteLine($"Conversation created: {ToJsonString(conversation)}"); Console.WriteLine($"Conversation created: {ToJsonString(conversation)}");
await db.Create("conversation_members", new ConversationMembers await db.Create("conversation_members", new ConversationMembers
{ {
ConversationId = conversation.Id.ToString(), ConversationId = conversation.Id.ToString(),
UserId = keeper.Id.ToString(), UserId = keeper.Id.ToString(),
JoinedAt = DateTime.UtcNow JoinedAt = DateTime.UtcNow
}); });
await db.Create("conversation_members", new ConversationMembers await db.Create("conversation_members", new ConversationMembers
{ {
ConversationId = conversation.Id.ToString(), ConversationId = conversation.Id.ToString(),
UserId = kira.Id.ToString(), UserId = kira.Id.ToString(),
JoinedAt = DateTime.UtcNow JoinedAt = DateTime.UtcNow
}); });
Console.WriteLine("Conversation members added."); Console.WriteLine("Conversation members added.");
var encrypted = E2EeHelper.EncryptForRecipient("hello from Keeper317", kiraKeys.publicKey); var encrypted = E2EeHelper.EncryptForRecipient("hello from Keeper317", kiraKeys.publicKey);
var savedMessage = await db.Create("messages", new Messages var savedMessage = await db.Create("messages", new Messages
{ {
ConversationId = conversation.Id.ToString(), ConversationId = conversation.Id.ToString(),
SenderUserId = keeper.Id.ToString(), SenderUserId = keeper.Id.ToString(),
RecipientUserId = kira.Id.ToString(), RecipientUserId = kira.Id.ToString(),
CipherText = encrypted.CipherText, CipherText = encrypted.CipherText,
Nonce = encrypted.Nonce, Nonce = encrypted.Nonce,
Tag = encrypted.Tag, Tag = encrypted.Tag,
EncryptedKey = encrypted.EncryptedKey, EncryptedKey = encrypted.EncryptedKey,
CreatedAt = DateTime.UtcNow CreatedAt = DateTime.UtcNow
}); });
Console.WriteLine($"Encrypted message saved: {ToJsonString(savedMessage)}"); Console.WriteLine($"Encrypted message saved: {ToJsonString(savedMessage)}");
var decrypted = E2EeHelper.DecryptForRecipient(encrypted, kiraKeys.privateKey); var decrypted = E2EeHelper.DecryptForRecipient(encrypted, kiraKeys.privateKey);
Console.WriteLine($"Decrypted for Ru_Kira: {decrypted}"); Console.WriteLine($"Decrypted for Ru_Kira: {decrypted}");
return; return;
static string ToJsonString(object? o) static string ToJsonString(object? o)
{ {
return JsonSerializer.Serialize(o, new JsonSerializerOptions { WriteIndented = true }); return JsonSerializer.Serialize(o, new JsonSerializerOptions { WriteIndented = true });
} }
static async Task<Users> CreateUserAsync(SurrealDbClient db, string username, string email, string rawPassword) static async Task<Users> CreateUserAsync(SurrealDbClient db, string username, string email, string rawPassword)
{ {
var now = DateTime.UtcNow; var now = DateTime.UtcNow;
var user = new Users var user = new Users
{ {
Username = username, Username = username,
Email = email, Email = email,
CreatedAt = now, CreatedAt = now,
UpdatedAt = now, UpdatedAt = now,
LastLogin = now, LastLogin = now,
TwoFactorEnabled = false, TwoFactorEnabled = false,
EmailVerified = false, EmailVerified = false,
AccountStatus = (int)AccountStatuses.Active, AccountStatus = (int)AccountStatuses.Active,
OnlineStatus = (int)OnlineStatuses.Online, OnlineStatus = (int)OnlineStatuses.Online,
}; };
var created = await db.Create("users", user); var created = await db.Create("users", user);
var hasher = new PasswordHasher.PasswordHasher(); var hasher = new PasswordHasher.PasswordHasher();
var passwordHash = hasher.HashPassword(created.Id.ToString() + rawPassword); var passwordHash = hasher.HashPassword(created.Id.ToString() + rawPassword);
var updated = await db.Merge<PasswordHash, Users>(new PasswordHash var updated = await db.Merge<PasswordHash, Users>(new PasswordHash
{ {
Id = created.Id, Id = created.Id,
Password = passwordHash Password = passwordHash
}); });
return updated; return updated;
} }
public static class KeyStorage public static class KeyStorage
{ {
public static void SavePrivateKey(string username, string privateKey) public static void SavePrivateKey(string username, string privateKey)
{ {
Directory.CreateDirectory("keys"); Directory.CreateDirectory("keys");
File.WriteAllText(Path.Combine("keys", $"{username}.private.key"), privateKey); File.WriteAllText(Path.Combine("keys", $"{username}.private.key"), privateKey);
} }
public static string LoadPrivateKey(string username) public static string LoadPrivateKey(string username)
{ {
return File.ReadAllText(Path.Combine("keys", $"{username}.private.key")); return File.ReadAllText(Path.Combine("keys", $"{username}.private.key"));
} }
public static bool PrivateKeyExists(string username) public static bool PrivateKeyExists(string username)
{ {
return File.Exists(Path.Combine("keys", $"{username}.private.key")); return File.Exists(Path.Combine("keys", $"{username}.private.key"));
} }
} }
public class ResponsibilityMerge : Record public class ResponsibilityMerge : Record
{ {
public bool Marketing { get; set; } public bool Marketing { get; set; }
} }
public class Group public class Group
{ {
public bool Marketing { get; set; } public bool Marketing { get; set; }
public int Count { get; set; } public int Count { get; set; }
} }
public class Users : Record public class Users : Record
{ {
public required string Username { get; set; } public required string Username { get; set; }
public string? Password { get; set; } public string? Password { get; set; }
public required string Email { get; set; } public required string Email { get; set; }
public required DateTime CreatedAt { get; set; } public required DateTime CreatedAt { get; set; }
public required DateTime UpdatedAt { get; set; } public required DateTime UpdatedAt { get; set; }
public required DateTime LastLogin { get; set; } public required DateTime LastLogin { get; set; }
public bool TwoFactorEnabled { get; set; } public bool TwoFactorEnabled { get; set; }
public bool EmailVerified { get; set; } public bool EmailVerified { get; set; }
public required int AccountStatus { get; set; } public required int AccountStatus { get; set; }
public required int OnlineStatus { get; set; } public required int OnlineStatus { get; set; }
} }
public class PasswordHash : Record public class PasswordHash : Record
{ {
public string? Password { get; set; } public string? Password { get; set; }
} }
public class Sessions : Record public class Sessions : Record
{ {
public required string UserId { get; set; } public required string UserId { get; set; }
public required string TokenHash { get; set; } public required string TokenHash { get; set; }
public required DateTime IssuedAt { get; set; } public required DateTime IssuedAt { get; set; }
public required DateTime ExpiresAt { get; set; } public required DateTime ExpiresAt { get; set; }
public DateTime? LastUsedAt { get; set; } public DateTime? LastUsedAt { get; set; }
public bool Revoked { get; set; } public bool Revoked { get; set; }
public required string DeviceName { get; set; } public required string DeviceName { get; set; }
public required string IpAddress { get; set; } public required string IpAddress { get; set; }
public required string UserAgent { get; set; } public required string UserAgent { get; set; }
} }
public class PasswordReset : Record public class PasswordReset : Record
{ {
public required string UserId { get; set; } public required string UserId { get; set; }
public required string TokenHash { get; set; } public required string TokenHash { get; set; }
public required DateTime CreatedAt { get; set; } public required DateTime CreatedAt { get; set; }
public required DateTime ExpiresAt { get; set; } public required DateTime ExpiresAt { get; set; }
public bool Revoked { get; set; } public bool Revoked { get; set; }
} }
public class Licenses : Record public class Licenses : Record
{ {
public required string UserId { get; set; } public required string UserId { get; set; }
public required int LicenseType { get; set; } public required int LicenseType { get; set; }
public required int Status { get; set; } public required int Status { get; set; }
public required DateTime CreatedAt { get; set; } public required DateTime CreatedAt { get; set; }
public required DateTime StartsAt { get; set; } public required DateTime StartsAt { get; set; }
public required DateTime UpdatedAt { get; set; } public required DateTime UpdatedAt { get; set; }
public required DateTime ExpiresAt { get; set; } public required DateTime ExpiresAt { get; set; }
} }
public class AuthAudits : Record public class AuthAudits : Record
{ {
public required string UserId { get; set; } public required string UserId { get; set; }
public required int EventType { get; set; } public required int EventType { get; set; }
public bool Success { get; set; } public bool Success { get; set; }
public required string IpAddress { get; set; } public required string IpAddress { get; set; }
public required string UserAgent { get; set; } public required string UserAgent { get; set; }
public required string Details { get; set; } public required string Details { get; set; }
public required DateTime CreatedAt { get; set; } public required DateTime CreatedAt { get; set; }
} }
public class UserKeys : Record public class UserKeys : Record
{ {
public required string UserId { get; set; } public required string UserId { get; set; }
public required string PublicKey { get; set; } public required string PublicKey { get; set; }
public required DateTime CreatedAt { get; set; } public required DateTime CreatedAt { get; set; }
public required DateTime UpdatedAt { get; set; } public required DateTime UpdatedAt { get; set; }
} }
public class Conversations : Record public class Conversations : Record
{ {
public required string CreatedByUserId { get; set; } public required string CreatedByUserId { get; set; }
public required DateTime CreatedAt { get; set; } public required DateTime CreatedAt { get; set; }
public required DateTime UpdatedAt { get; set; } public required DateTime UpdatedAt { get; set; }
public string? Title { get; set; } public string? Title { get; set; }
public bool IsDirectMessage { get; set; } public bool IsDirectMessage { get; set; }
} }
public class ConversationMembers : Record public class ConversationMembers : Record
{ {
public required string ConversationId { get; set; } public required string ConversationId { get; set; }
public required string UserId { get; set; } public required string UserId { get; set; }
public required DateTime JoinedAt { get; set; } public required DateTime JoinedAt { get; set; }
} }
public class Messages : Record public class Messages : Record
{ {
public required string ConversationId { get; set; } public required string ConversationId { get; set; }
public required string SenderUserId { get; set; } public required string SenderUserId { get; set; }
public required string RecipientUserId { get; set; } public required string RecipientUserId { get; set; }
public required string CipherText { get; set; } public required string CipherText { get; set; }
public required string Nonce { get; set; } public required string Nonce { get; set; }
public required string Tag { get; set; } public required string Tag { get; set; }
public required string EncryptedKey { get; set; } public required string EncryptedKey { get; set; }
public required DateTime CreatedAt { get; set; } public required DateTime CreatedAt { get; set; }
} }
enum AccountStatuses enum AccountStatuses
{ {
Active, Active,
Suspended, Suspended,
Banned, Banned,
Deleted Deleted
} }
enum OnlineStatuses enum OnlineStatuses
{ {
Online, Online,
Busy, Busy,
DND, DND,
Invisible, Invisible,
Offline Offline
} }
enum LicenseStatuses enum LicenseStatuses
{ {
Active, Active,
Expired, Expired,
Renewable, Renewable,
Revoked Revoked
} }
enum LicenseType enum LicenseType
{ {
Free, Free,
Basic, Basic,
Advanced, Advanced,
Pro, Pro,
Enterprise Enterprise
} }
enum LogEvents enum LogEvents
{ {
LoginSuccess, LoginSuccess,
LoginFailure, LoginFailure,
LogoutSuccess, LogoutSuccess,
LogoutFailure, LogoutFailure,
PasswordResetSuccess, PasswordResetSuccess,
PasswordResetFailure, PasswordResetFailure,
} }

View File

@@ -1,16 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.1" /> <PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.1" />
<PackageReference Include="SurrealDb.Net" Version="0.9.0" /> <PackageReference Include="SurrealDb.Net" Version="0.9.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

184
RelayServer/.gitignore vendored
View File

@@ -1,93 +1,93 @@
############################################ ############################################
# .NET Build # .NET Build
############################################ ############################################
bin/ bin/
obj/ obj/
out/ out/
publish/ publish/
############################################ ############################################
# Visual Studio # Visual Studio
############################################ ############################################
.vs/ .vs/
*.user *.user
*.suo *.suo
*.userprefs *.userprefs
*.csproj.user *.csproj.user
*.dbmdl *.dbmdl
*.cache *.cache
*.pdb *.pdb
*.opendb *.opendb
############################################ ############################################
# Rider / JetBrains # Rider / JetBrains
############################################ ############################################
.idea/ .idea/
*.sln.iml *.sln.iml
############################################ ############################################
# VSCode # VSCode
############################################ ############################################
.vscode/ .vscode/
############################################ ############################################
# NuGet # NuGet
############################################ ############################################
*.nupkg *.nupkg
*.snupkg *.snupkg
packages/ packages/
.nuget/ .nuget/
.nuget/packages/ .nuget/packages/
############################################ ############################################
# Logs # Logs
############################################ ############################################
*.log *.log
logs/ logs/
############################################ ############################################
# OS files # OS files
############################################ ############################################
.DS_Store .DS_Store
Thumbs.db Thumbs.db
############################################ ############################################
# Local secrets / environment # Local secrets / environment
############################################ ############################################
.env .env
.env.* .env.*
secrets.json secrets.json
appsettings.Development.json appsettings.Development.json
############################################ ############################################
# E2EE private keys # E2EE private keys
############################################ ############################################
keys/* keys/*
!keys/.gitkeep !keys/.gitkeep
############################################ ############################################
# Local test databases / data folders # Local test databases / data folders
############################################ ############################################
data/ data/
*.db *.db
*.sqlite *.sqlite
*.sqlite3 *.sqlite3
############################################ ############################################
# Temporary files # Temporary files
############################################ ############################################
*.tmp *.tmp
*.temp *.temp
*.bak *.bak
*.swp *.swp

View File

@@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
</Project> </Project>