Add MAUI sample and delete Android

This commit is contained in:
Morten Nielsen 2024-07-03 12:41:49 -07:00
parent d37bd9af08
commit 59cbcc761d
42 changed files with 1192 additions and 340 deletions

View file

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.0.0
# Visual Studio Version 17
VisualStudioVersion = 17.10.34916.146
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NmeaParser", "NmeaParser", "{1701F3BA-A09C-4706-A612-24FD9340FC18}"
EndProject
@ -29,20 +29,15 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NmeaParser.Tests.UWP", "Uni
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "NmeaParser.Tests", "UnitTests\NmeaParser.Tests\NmeaParser.Tests.shproj", "{979AE182-EB59-4181-9D45-3FD6E4817F11}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{456E7573-3324-43CB-8BA0-8D9C300EEB50}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApp.Droid", "SampleApp.Droid\SampleApp.Droid.csproj", "{48540D33-4349-42D2-9D49-144A7049565A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NmeaParser.Tests.Net", "UnitTests\NmeaParser.Tests.NET\NmeaParser.Tests.Net.csproj", "{73EFB2EF-DE40-46C4-9685-745A9815C0D2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApp.NetCore", "SampleApp.WinDesktop\SampleApp.NetCore.csproj", "{6F97C607-42A0-458B-B9E9-CF5AF53CBB1E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Maui", "Maui", "{09136598-F229-45CD-8AEA-97DC890C3314}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApp.Maui", "SampleApp.Maui\SampleApp.Maui.csproj", "{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{73efb2ef-de40-46c4-9685-745a9815c0d2}*SharedItemsImports = 5
UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{92cad93b-6c3b-45a0-a723-be046de50fec}*SharedItemsImports = 4
UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{979ae182-eb59-4181-9d45-3fd6e4817f11}*SharedItemsImports = 13
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
@ -116,30 +111,6 @@ Global
{92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x86.ActiveCfg = Release|x86
{92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x86.Build.0 = Release|x86
{92CAD93B-6C3B-45A0-A723-BE046DE50FEC}.Release|x86.Deploy.0 = Release|x86
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|ARM.ActiveCfg = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|ARM.Build.0 = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|ARM.Deploy.0 = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|x64.ActiveCfg = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|x64.Build.0 = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|x64.Deploy.0 = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|x86.ActiveCfg = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|x86.Build.0 = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Debug|x86.Deploy.0 = Debug|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|Any CPU.Build.0 = Release|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|Any CPU.Deploy.0 = Release|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|ARM.ActiveCfg = Release|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|ARM.Build.0 = Release|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|ARM.Deploy.0 = Release|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|x64.ActiveCfg = Release|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|x64.Build.0 = Release|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|x64.Deploy.0 = Release|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|x86.ActiveCfg = Release|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|x86.Build.0 = Release|Any CPU
{48540D33-4349-42D2-9D49-144A7049565A}.Release|x86.Deploy.0 = Release|Any CPU
{73EFB2EF-DE40-46C4-9685-745A9815C0D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73EFB2EF-DE40-46C4-9685-745A9815C0D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73EFB2EF-DE40-46C4-9685-745A9815C0D2}.Debug|ARM.ActiveCfg = Debug|Any CPU
@ -172,6 +143,30 @@ Global
{6F97C607-42A0-458B-B9E9-CF5AF53CBB1E}.Release|x64.Build.0 = Release|Any CPU
{6F97C607-42A0-458B-B9E9-CF5AF53CBB1E}.Release|x86.ActiveCfg = Release|Any CPU
{6F97C607-42A0-458B-B9E9-CF5AF53CBB1E}.Release|x86.Build.0 = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|ARM.ActiveCfg = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|ARM.Build.0 = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|ARM.Deploy.0 = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|x64.ActiveCfg = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|x64.Build.0 = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|x64.Deploy.0 = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|x86.ActiveCfg = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|x86.Build.0 = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Debug|x86.Deploy.0 = Debug|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|Any CPU.Build.0 = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|Any CPU.Deploy.0 = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|ARM.ActiveCfg = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|ARM.Build.0 = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|ARM.Deploy.0 = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|x64.ActiveCfg = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|x64.Build.0 = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|x64.Deploy.0 = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|x86.ActiveCfg = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|x86.Build.0 = Release|Any CPU
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC}.Release|x86.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -184,12 +179,17 @@ Global
{1ADC3666-1DDB-48C4-9811-1E58B6D09A7C} = {1701F3BA-A09C-4706-A612-24FD9340FC18}
{92CAD93B-6C3B-45A0-A723-BE046DE50FEC} = {28B8E327-C504-4E08-B2CE-09D1CBB8B904}
{979AE182-EB59-4181-9D45-3FD6E4817F11} = {28B8E327-C504-4E08-B2CE-09D1CBB8B904}
{456E7573-3324-43CB-8BA0-8D9C300EEB50} = {A4B9D59A-C8C6-4199-A7F3-F3AF0C748281}
{48540D33-4349-42D2-9D49-144A7049565A} = {456E7573-3324-43CB-8BA0-8D9C300EEB50}
{73EFB2EF-DE40-46C4-9685-745A9815C0D2} = {28B8E327-C504-4E08-B2CE-09D1CBB8B904}
{6F97C607-42A0-458B-B9E9-CF5AF53CBB1E} = {7ABA337E-6748-484E-A0F4-E1715E1C95F1}
{09136598-F229-45CD-8AEA-97DC890C3314} = {A4B9D59A-C8C6-4199-A7F3-F3AF0C748281}
{9C02F330-0392-41F3-BBC1-D6E389FA9CCC} = {09136598-F229-45CD-8AEA-97DC890C3314}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {03788B53-C0BF-485B-AA19-A9EAB0E9AF7B}
EndGlobalSection
GlobalSection(SharedMSBuildProjectFiles) = preSolution
UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{73efb2ef-de40-46c4-9685-745a9815c0d2}*SharedItemsImports = 5
UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{92cad93b-6c3b-45a0-a723-be046de50fec}*SharedItemsImports = 4
UnitTests\NmeaParser.Tests\NmeaParser.Tests.projitems*{979ae182-eb59-4181-9d45-3fd6e4817f11}*SharedItemsImports = 13
EndGlobalSection
EndGlobal

View file

@ -1,173 +0,0 @@
using Android;
using Android.Bluetooth;
using Android.Content.PM;
using AndroidX.Core.App;
namespace SampleApp.Droid;
[Activity(Label = "@string/app_name", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
private Button startButton;
private Button stopButton;
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
startButton = FindViewById<Button>(Resource.Id.startButton)!;
startButton.Click += StartButton_Click;
stopButton = FindViewById<Button>(Resource.Id.stopButton)!;
stopButton.Click += StopButton_Click;
stopButton.Enabled = false;
devices.Add("System GPS", null);
var devicePicker = FindViewById<Spinner>(Resource.Id.device_picker);
if (this.ApplicationContext!.CheckSelfPermission(Manifest.Permission.BluetoothConnect) != Permission.Granted)
{
ActivityCompat.RequestPermissions(this, new[] { Manifest.Permission.BluetoothConnect }, 1000);
return;
}
foreach (var d in NmeaParser.BluetoothDevice.GetBluetoothSerialDevices(ApplicationContext))
{
devices[d.Name + " " + d.Address] = d;
}
devicePicker.Adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleSpinnerDropDownItem, devices.Keys.ToArray());
devicePicker.SetSelection(0);
}
private Dictionary<string, BluetoothDevice?> devices = new Dictionary<string, BluetoothDevice?>();
private void StopButton_Click(object? sender, EventArgs e)
{
if (listener?.IsOpen == true)
{
Stop();
}
}
private void Stop()
{
listener!.MessageReceived -= Listener_MessageReceived;
monitor!.LocationChanged -= Monitor_LocationChanged;
socket?.Close();
socket?.Dispose();
socket = null;
_ = listener.CloseAsync();
listener = null;
startButton.Enabled = !(stopButton.Enabled = false);
}
private void StartButton_Click(object? sender, EventArgs e)
{
if (listener?.IsOpen != true)
{
Start();
}
}
private NmeaParser.NmeaDevice? listener;
private NmeaParser.Gnss.GnssMonitor? monitor;
private TextView? status;
private bool launched;
private Android.Bluetooth.BluetoothSocket? socket;
private async void Start()
{
startButton.Enabled = false;
status = FindViewById<TextView>(Resource.Id.output);
var devicePicker = FindViewById<Spinner>(Resource.Id.device_picker)!;
var id = devicePicker.SelectedItem?.ToString();
var btAddress = devices[id];
if (btAddress == null)
{
if (this.ApplicationContext!.CheckSelfPermission(Manifest.Permission.AccessFineLocation) != Permission.Granted)
{
ActivityCompat.RequestPermissions(this, new[] { Manifest.Permission.AccessFineLocation }, 1000);
return;
}
if (launched)
return;
launched = true;
listener = new NmeaParser.SystemNmeaDevice(ApplicationContext);
}
else //Bluetooth
{
try
{
listener = new NmeaParser.BluetoothDevice(btAddress, ApplicationContext!);
}
catch (System.Exception ex)
{
socket?.Dispose();
socket = null;
status.Text += "\nError opening Bluetooth device:\n" + ex.Message;
}
}
if (listener != null)
{
listener.MessageReceived += Listener_MessageReceived;
status!.Text += "\nOpening device...";
try
{
await listener.OpenAsync();
status.Text += "\nConnected!";
monitor = new NmeaParser.Gnss.GnssMonitor(listener);
monitor.LocationChanged += Monitor_LocationChanged;
startButton.Enabled = !(stopButton.Enabled = true);
}
catch (Exception ex)
{
status.Text += "\nError opening device:\n" + ex.Message;
startButton.Enabled = true;
stopButton.Enabled = false;
}
finally
{
}
}
else
{
startButton.Enabled = !(stopButton.Enabled = false);
}
}
protected override void OnDestroy()
{
Stop();
base.OnDestroy();
}
protected override void OnResume()
{
base.OnResume();
// if it was resumed by the GPS permissions dialog
//Start();
}
Queue<NmeaParser.Messages.NmeaMessage> messages = new Queue<NmeaParser.Messages.NmeaMessage>(100);
private void Listener_MessageReceived(object? sender, NmeaParser.NmeaMessageReceivedEventArgs e)
{
var message = e.Message;
RunOnUiThread(() =>
{
if (messages.Count == 100) messages.Dequeue();
messages.Enqueue(message);
status!.Text = string.Join("\n", messages.Reverse().Select(n => n.ToString()));
});
}
private void Monitor_LocationChanged(object? sender, EventArgs e)
{
FindViewById<TextView>(Resource.Id.latitude)!.Text = "Latitude = " + monitor!.Latitude.ToString("0.0000000");
FindViewById<TextView>(Resource.Id.longitude)!.Text = "Longitude = " + monitor!.Longitude.ToString("0.0000000");
FindViewById<TextView>(Resource.Id.altitude)!.Text = "Altitude = " + monitor!.Altitude.ToString();
}
}

View file

@ -1,44 +0,0 @@
Images, layout descriptions, binary blobs and string dictionaries can be included
in your application as resource files. Various Android APIs are designed to
operate on the resource IDs instead of dealing with images, strings or binary blobs
directly.
For example, a sample Android app that contains a user interface layout (main.xml),
an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
would keep its resources in the "Resources" directory of the application:
Resources/
drawable/
icon.png
layout/
main.xml
values/
strings.xml
In order to get the build system to recognize Android resources, set the build action to
"AndroidResource". The native Android APIs do not operate directly with filenames, but
instead operate on resource IDs. When you compile an Android application that uses resources,
the build system will package the resources for distribution and generate a class called "Resource"
(this is an Android convention) that contains the tokens for each one of the resources
included. For example, for the above Resources layout, this is what the Resource class would expose:
public class Resource {
public class Drawable {
public const int icon = 0x123;
}
public class Layout {
public const int main = 0x456;
}
public class Strings {
public const int first_string = 0xabc;
public const int second_string = 0xbcd;
}
}
You would then use Resource.Drawable.icon to reference the drawable/icon.png file, or
Resource.Layout.main to reference the layout/main.xml file, or Resource.Strings.first_string
to reference the first string in the dictionary file values/strings.xml.

View file

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/longitude"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Latitude = " />
<TextView
android:id="@+id/latitude"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Longitude = " />
<TextView
android:id="@+id/altitude"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Altitude =" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="NMEA Device:" />
<Spinner
android:id="@+id/device_picker"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/startButton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="start" />
<Button
android:id="@+id/stopButton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="stop" />
</LinearLayout>
<TextView
android:id="@+id/output"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
</LinearLayout>

View file

@ -1,3 +0,0 @@
<resources>
<string name="app_name">NMEA Parser SampleApp</string>
</resources>

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#2C3E50</color>
</resources>

View file

@ -1,22 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-android</TargetFramework>
<SupportedOSPlatformVersion>23</SupportedOSPlatformVersion>
<OutputType>Exe</OutputType>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ApplicationId>com.companyname.SampleApp.Droid</ApplicationId>
<ApplicationVersion>1</ApplicationVersion>
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
</PropertyGroup>
<ItemGroup>
<None Remove="Resources\drawable\icon.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.10.1.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NmeaParser\NmeaParser.csproj" />
</ItemGroup>
</Project>

View file

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

View file

@ -0,0 +1,12 @@
namespace SampleApp.Maui
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new AppShell();
}
}
}

View file

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

View file

@ -0,0 +1,10 @@
namespace SampleApp.Maui
{
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
}
}
}

View file

@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NmeaParser;
#if WINDOWS
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
#endif
namespace SampleApp.Maui
{
public class DeviceInfo
{
public DeviceInfo(string name, Func<Task<NmeaDevice>> createMethod) {
DisplayName = name;
CreateMethod = createMethod;
}
public Func<Task<NmeaDevice>> CreateMethod { get; }
public string DisplayName { get; }
public override string ToString() => DisplayName;
}
internal static class DeviceHelper
{
public static async Task<List<DeviceInfo>> LoadDevices()
{
List<DeviceInfo> deviceList = new List<DeviceInfo>();
#if WINDOWS
//Get list of devices
var btdevices = await NmeaParser.BluetoothDevice.GetBluetoothSerialDevicesAsync();
foreach (var item in btdevices)
{
deviceList.Add(new DeviceInfo($"{item.Device.Name} (Bluetooth)", () => Task.FromResult<NmeaParser.NmeaDevice>(new NmeaParser.BluetoothDevice(item))));
}
// Find serial devices
foreach(var port in System.IO.Ports.SerialPort.GetPortNames().OrderBy(s => s))
{
var serialDevice = new System.IO.Ports.SerialPort(port, 9600);
deviceList.Add(new DeviceInfo($"Serial Port {port} @ 9600 baud", () => Task.FromResult<NmeaParser.NmeaDevice>(new NmeaParser.SerialPortDevice(serialDevice))));
}
#elif ANDROID
var permission = await Permissions.RequestAsync<Permissions.Bluetooth>();
deviceList.Add(new DeviceInfo("System NMEA device",
async () =>
{
var permissionLocation = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
if (permissionLocation == PermissionStatus.Granted)
return new NmeaParser.SystemNmeaDevice(Maui.MainApplication.Context);
throw new InvalidOperationException("Access not granted");
}));
if (permission == PermissionStatus.Granted)
{
foreach (var d in NmeaParser.BluetoothDevice.GetBluetoothSerialDevices(Maui.MainApplication.Context))
{
deviceList.Add(new DeviceInfo(d.Name + " " + d.Address, () => Task.FromResult<NmeaDevice>(new NmeaParser.BluetoothDevice(d, Maui.MainApplication.Context))));
}
}
#elif IOS
string[] knownDevices = { "com.bad-elf.gps", "com.dualav.xgps150", "00001101-0000-1000-8000-00805F9B34FB" }; // If you add more, also update info.plist
foreach (var accessory in ExternalAccessory.EAAccessoryManager.SharedAccessoryManager.ConnectedAccessories)
{
foreach (var str in knownDevices)
{
if (accessory.ProtocolStrings.Contains(str))
deviceList.Add(new DeviceInfo(str, () => Task.FromResult<NmeaDevice>(new EAAccessoryDevice(accessory, str))));
}
}
#endif
return deviceList;
}
}
}

View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SampleApp.Maui.MainPage">
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Stroke="Black" StrokeThickness="1" >
<StackLayout x:Name="gnssMonitorView" Padding="5" >
<StackLayout Orientation="Horizontal">
<Label Text="Latitude: " />
<Label Text="{Binding Latitude}" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Longitude: " />
<Label Text="{Binding Longitude}" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Altitude: " />
<Label Text="{Binding Altitude}" />
</StackLayout>
</StackLayout>
</Border>
<Picker Title="NMEA Device:" x:Name="nmeaDevicePicker" Grid.Row="1" Margin="0, 10" />
<StackLayout Orientation="Horizontal" Grid.Row="2">
<Button Text="Start" x:Name="startButton" Clicked="startButton_Click" />
<Button Text="Stop" IsEnabled="False" x:Name="stopButton" Clicked="stopButton_Click" />
</StackLayout>
<Editor IsReadOnly="True" x:Name="output" Grid.Row="3" Margin="0, 10" VerticalTextAlignment="Start" />
</Grid>
</ContentPage>

View file

@ -0,0 +1,81 @@
using System.Collections.ObjectModel;
using NmeaParser;
namespace SampleApp.Maui
{
public partial class MainPage : ContentPage
{
private Queue<string> messages = new Queue<string>(101);
private NmeaParser.NmeaDevice? listener;
private NmeaParser.Gnss.GnssMonitor? monitor;
private ObservableCollection<DeviceInfo> deviceList = new ObservableCollection<DeviceInfo>();
public MainPage()
{
InitializeComponent();
nmeaDevicePicker.ItemsSource = deviceList;
deviceList.Add(new SampleApp.Maui.DeviceInfo("Simulated NMEA Device", () => Task.FromResult<NmeaDevice>(new MauiAssetStreamDevice("NmeaSampleData.txt"))));
nmeaDevicePicker.SelectedIndex = 0;
LoadDevices();
}
private async void LoadDevices()
{
foreach(var device in await DeviceHelper.LoadDevices())
{
deviceList.Add(device);
}
}
private async void startButton_Click(object sender, EventArgs e)
{
var info = nmeaDevicePicker.SelectedItem as DeviceInfo;
if (info != null)
{
var device = await info.CreateMethod();
output.Text = string.Empty;
messages.Clear();
device.MessageReceived += device_MessageReceived;
var _ = device.OpenAsync();
listener = device;
startButton.IsEnabled = false;
stopButton.IsEnabled = true;
monitor = new NmeaParser.Gnss.GnssMonitor(device);
gnssMonitorView.BindingContext = monitor;
}
}
private void stopButton_Click(object sender, EventArgs e)
{
if (listener != null)
{
gnssMonitorView.BindingContext = null;
_ = listener.CloseAsync();
listener.Dispose();
listener = null;
startButton.IsEnabled = true;
stopButton.IsEnabled = false;
}
}
private void device_MessageReceived(object? sender, NmeaParser.NmeaMessageReceivedEventArgs args)
{
var _ = Dispatcher.Dispatch(() =>
{
messages.Enqueue(args.Message.MessageType + ": " + args.Message.ToString());
if (messages.Count > 100) messages.Dequeue(); //Keep message queue at 100
output.Text = string.Join("\n", messages.ToArray());
});
}
private class MauiAssetStreamDevice : BufferedStreamDevice
{
string _filename;
public MauiAssetStreamDevice(string filename) : base()
{
_filename = filename;
}
protected override Task<Stream> GetStreamAsync() => FileSystem.OpenAppPackageFileAsync(_filename);
}
}
}

View file

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

View file

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<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>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<application android:allowBackup="true" android:label="@string/app_name" android:supportsRtl="true"></application>
<uses-sdk />
</manifest>

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,14 @@
<?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">
<plist version="1.0">
<!-- See https://aka.ms/maui-publish-app-store#add-entitlements for more information about adding entitlements.-->
<dict>
<!-- App Sandbox must be enabled to distribute a MacCatalyst app through the Mac App Store. -->
<key>com.apple.security.app-sandbox</key>
<true/>
<!-- When App Sandbox is enabled, this value is required to open outgoing network connections. -->
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,38 @@
<?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">
<plist version="1.0">
<dict>
<!-- The Mac App Store requires you specify if the app uses encryption. -->
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/itsappusesnonexemptencryption -->
<!-- <key>ITSAppUsesNonExemptEncryption</key> -->
<!-- Please indicate <true/> or <false/> here. -->
<!-- Specify the category for your app here. -->
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype -->
<!-- <key>LSApplicationCategoryType</key> -->
<!-- <string>public.app-category.YOUR-CATEGORY-HERE</string> -->
<key>UIDeviceFamily</key>
<array>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
</dict>
</plist>

View file

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

View file

@ -0,0 +1,17 @@
using System;
using Microsoft.Maui;
using Microsoft.Maui.Hosting;
namespace SampleApp.Maui
{
internal class Program : MauiApplication
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
static void Main(string[] args)
{
var app = new Program();
app.Run(args);
}
}
}

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="maui-application-id-placeholder" version="0.0.0" api-version="8" xmlns="http://tizen.org/ns/packages">
<profile name="common" />
<ui-application appid="maui-application-id-placeholder" exec="SampleApp.Maui.dll" multiple="false" nodisplay="false" taskmanage="true" type="dotnet" launch_mode="single">
<label>maui-application-title-placeholder</label>
<icon>maui-appicon-placeholder</icon>
<metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
</ui-application>
<shortcut-list />
<privileges>
<privilege>http://tizen.org/privilege/internet</privilege>
</privileges>
<dependencies />
<provides-appdefined-privileges />
</manifest>

View file

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

View file

@ -0,0 +1,25 @@
using Microsoft.UI.Xaml;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace SampleApp.Maui.WinUI
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
public partial class App : MauiWinUIApplication
{
/// <summary>
/// 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().
/// </summary>
public App()
{
this.InitializeComponent();
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
}

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" />
<mp:PhoneIdentity PhoneProductId="5E9D56C8-C803-4DCE-8AD0-C70E422C59AC" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>$placeholder$</DisplayName>
<PublisherDisplayName>User Name</PublisherDisplayName>
<Logo>$placeholder$.png</Logo>
</Properties>
<Dependencies>
<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" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="$placeholder$"
Description="$placeholder$"
Square150x150Logo="$placeholder$.png"
Square44x44Logo="$placeholder$.png"
BackgroundColor="transparent">
<uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" />
<uap:SplashScreen Image="$placeholder$.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>

View file

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

View file

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

View file

@ -0,0 +1,39 @@
<?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">
<plist version="1.0">
<dict>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
<key>UISupportedExternalAccessoryProtocols</key>
<array>
<string>com.bad-elf.gps</string>
<string>com.dualav.xgps150</string>
<string>00001101-0000-1000-8000-00805F9B34FB</string>
</array>
</dict>
</plist>

View file

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

View file

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

View file

@ -0,0 +1,4 @@
<?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">
<rect x="0" y="0" width="456" height="456" fill="#ffffff" />
</svg>

After

Width:  |  Height:  |  Size: 228 B

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,15 @@
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
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
These files will be deployed with your package and will be accessible using Essentials:
async Task LoadMauiAsset()
{
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
using var reader = new StreamReader(stream);
var contents = reader.ReadToEnd();
}

View file

@ -0,0 +1,8 @@
<?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">
<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 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 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>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

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

View file

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

View file

@ -0,0 +1,68 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
<!-- Note for MacCatalyst:
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
<OutputType>Exe</OutputType>
<RootNamespace>SampleApp.Maui</RootNamespace>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- Display name -->
<ApplicationTitle>NMEA SampleApp (Maui)</ApplicationTitle>
<!-- App Identifier -->
<ApplicationId>com.companyname.sampleapp.maui</ApplicationId>
<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
</PropertyGroup>
<ItemGroup>
<!-- App Icon -->
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\icon.png" Color="#FFFFFF" />
<!-- Splash Screen -->
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
<!-- Images -->
<MauiImage Include="Resources\Images\*" />
<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
<MauiAsset Include="..\NmeaSampleData.txt" Link="NmeaSampleData.txt" LogicalName="%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<ProjectReference Include="..\NmeaParser\NmeaParser.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\Images\" />
</ItemGroup>
</Project>