From 82c9b141aaf439d5a357cac82abdab9567e4a115 Mon Sep 17 00:00:00 2001 From: Paul-Winpenny <92634321+Paul-Winpenny@users.noreply.github.com> Date: Wed, 6 Nov 2024 15:58:50 +0000 Subject: [PATCH] Phone app looking alright! --- App/RobobinApp/App.xaml.cs | 2 +- App/RobobinApp/AppShell.xaml | 4 +- App/RobobinApp/AppShell.xaml.cs | 35 +++++-- .../Platforms/Android/AndroidManifest.xml | 4 +- .../Android/Resources/drawable/bin.svg | 17 ++++ .../Android/Resources/mipmap/robobinlogo1.png | Bin 0 -> 19785 bytes App/RobobinApp/Resources/AppIcon/appicon.svg | 4 - .../Resources/AppIcon/appiconfg.svg | 8 -- App/RobobinApp/Resources/Splash/bin.svg | 17 ++++ App/RobobinApp/RobobinApp.csproj | 30 +++++- App/RobobinApp/RobobinApp.csproj.user | 9 +- .../ViewModels/ConnectionPageViewModel.cs | 12 ++- App/RobobinApp/Views/MainPage_Android.xaml | 69 +++++++++++++ App/RobobinApp/Views/MainPage_Android.xaml.cs | 91 ++++++++++++++++++ 14 files changed, 267 insertions(+), 35 deletions(-) create mode 100644 App/RobobinApp/Platforms/Android/Resources/drawable/bin.svg create mode 100644 App/RobobinApp/Platforms/Android/Resources/mipmap/robobinlogo1.png delete mode 100644 App/RobobinApp/Resources/AppIcon/appicon.svg delete mode 100644 App/RobobinApp/Resources/AppIcon/appiconfg.svg create mode 100644 App/RobobinApp/Resources/Splash/bin.svg create mode 100644 App/RobobinApp/Views/MainPage_Android.xaml create mode 100644 App/RobobinApp/Views/MainPage_Android.xaml.cs diff --git a/App/RobobinApp/App.xaml.cs b/App/RobobinApp/App.xaml.cs index 4ae70a3d..e1472dcd 100644 --- a/App/RobobinApp/App.xaml.cs +++ b/App/RobobinApp/App.xaml.cs @@ -1,7 +1,7 @@ using Microsoft.Extensions.Logging; using Plugin.BLE; using Plugin.BLE.Abstractions.Contracts; -using RobobinApp.Networking; // Make sure to include the namespace for WifiManager +using RobobinApp.Networking; namespace RobobinApp { diff --git a/App/RobobinApp/AppShell.xaml b/App/RobobinApp/AppShell.xaml index 270d8c2c..fc1cc13a 100644 --- a/App/RobobinApp/AppShell.xaml +++ b/App/RobobinApp/AppShell.xaml @@ -3,6 +3,4 @@ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:views="clr-namespace:RobobinApp.Views" x:Class="RobobinApp.AppShell"> - - <ShellContent ContentTemplate="{DataTemplate views:MainPage}" /> -</Shell> \ No newline at end of file +</Shell> diff --git a/App/RobobinApp/AppShell.xaml.cs b/App/RobobinApp/AppShell.xaml.cs index 96c31576..2b242776 100644 --- a/App/RobobinApp/AppShell.xaml.cs +++ b/App/RobobinApp/AppShell.xaml.cs @@ -1,9 +1,32 @@ -namespace RobobinApp; +using Microsoft.Maui.Controls; +using RobobinApp.Views; -public partial class AppShell : Shell +namespace RobobinApp { - public AppShell() - { - InitializeComponent(); - } + public partial class AppShell : Shell + { + public AppShell() + { + InitializeComponent(); + + // Conditionally add ShellContent based on the platform +#if WINDOWS + Items.Add(new ShellContent + { + ContentTemplate = new DataTemplate(typeof(MainPage)) + }); +#elif ANDROID + Items.Add(new ShellContent + { + ContentTemplate = new DataTemplate(typeof(MainPage_Android)) + }); +#else + // Fallback if you need it for other platforms + Items.Add(new ShellContent + { + ContentTemplate = new DataTemplate(typeof(MainPage_Default)) + }); +#endif + } + } } diff --git a/App/RobobinApp/Platforms/Android/AndroidManifest.xml b/App/RobobinApp/Platforms/Android/AndroidManifest.xml index 4dcde8fe..d2d79fe1 100644 --- a/App/RobobinApp/Platforms/Android/AndroidManifest.xml +++ b/App/RobobinApp/Platforms/Android/AndroidManifest.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1"> - <application android:allowBackup="true" android:icon="@mipmap/appicon" android:supportsRtl="true" android:label="RoboBin"></application> + <application android:allowBackup="true" android:supportsRtl="true" android:label="RoboBin"></application> <!-- Required permissions --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> @@ -10,6 +10,4 @@ <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> - - </manifest> \ No newline at end of file diff --git a/App/RobobinApp/Platforms/Android/Resources/drawable/bin.svg b/App/RobobinApp/Platforms/Android/Resources/drawable/bin.svg new file mode 100644 index 00000000..8c4771bf --- /dev/null +++ b/App/RobobinApp/Platforms/Android/Resources/drawable/bin.svg @@ -0,0 +1,17 @@ +<?xml version="1.0" ?> + <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --> +<svg width="800px" height="800px" viewBox="0 0 48 48" data-name="Layer 1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"> + <defs> + <style>.cls-1{fill:#55aae1;}.cls-2{opacity:0.35;}</style> + </defs> + <title/> + <path class="cls-1" d="M36,44H12a3,3,0,0,1-3-3V12a1,1,0,0,1,1-1H38a1,1,0,0,1,1,1V41A3,3,0,0,1,36,44ZM11,13V41a1,1,0,0,0,1,1H36a1,1,0,0,0,1-1V13Z"/> + <g class="cls-2"> + <path class="cls-1" d="M35,12V38a2,2,0,0,1-2,2H10v1a2,2,0,0,0,2,2H36a2,2,0,0,0,2-2V12Z"/> + </g> + <path class="cls-1" d="M43,13H5a1,1,0,0,1,0-2H43a1,1,0,0,1,0,2Z"/> + <path class="cls-1" d="M17,35a1,1,0,0,1-1-1V20a1,1,0,0,1,2,0V34A1,1,0,0,1,17,35Z"/> + <path class="cls-1" d="M31,35a1,1,0,0,1-1-1V20a1,1,0,0,1,2,0V34A1,1,0,0,1,31,35Z"/> + <path class="cls-1" d="M24,37a1,1,0,0,1-1-1V18a1,1,0,0,1,2,0V36A1,1,0,0,1,24,37Z"/> + <path class="cls-1" d="M33,13H15a1,1,0,0,1-1-1V7a3,3,0,0,1,3-3H31a3,3,0,0,1,3,3v5A1,1,0,0,1,33,13ZM16,11H32V7a1,1,0,0,0-1-1H17a1,1,0,0,0-1,1Z"/> + </svg> \ No newline at end of file diff --git a/App/RobobinApp/Platforms/Android/Resources/mipmap/robobinlogo1.png b/App/RobobinApp/Platforms/Android/Resources/mipmap/robobinlogo1.png new file mode 100644 index 0000000000000000000000000000000000000000..f22f9630a604d4823e7bdd5ff576f0af86627b8e GIT binary patch literal 19785 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 DEy-tU literal 0 HcmV?d00001 diff --git a/App/RobobinApp/Resources/AppIcon/appicon.svg b/App/RobobinApp/Resources/AppIcon/appicon.svg deleted file mode 100644 index 5f04fcfc..00000000 --- a/App/RobobinApp/Resources/AppIcon/appicon.svg +++ /dev/null @@ -1,4 +0,0 @@ -<?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="#512BD4" /> -</svg> \ No newline at end of file diff --git a/App/RobobinApp/Resources/AppIcon/appiconfg.svg b/App/RobobinApp/Resources/AppIcon/appiconfg.svg deleted file mode 100644 index 62d66d7a..00000000 --- a/App/RobobinApp/Resources/AppIcon/appiconfg.svg +++ /dev/null @@ -1,8 +0,0 @@ -<?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> \ No newline at end of file diff --git a/App/RobobinApp/Resources/Splash/bin.svg b/App/RobobinApp/Resources/Splash/bin.svg new file mode 100644 index 00000000..8c4771bf --- /dev/null +++ b/App/RobobinApp/Resources/Splash/bin.svg @@ -0,0 +1,17 @@ +<?xml version="1.0" ?> + <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --> +<svg width="800px" height="800px" viewBox="0 0 48 48" data-name="Layer 1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"> + <defs> + <style>.cls-1{fill:#55aae1;}.cls-2{opacity:0.35;}</style> + </defs> + <title/> + <path class="cls-1" d="M36,44H12a3,3,0,0,1-3-3V12a1,1,0,0,1,1-1H38a1,1,0,0,1,1,1V41A3,3,0,0,1,36,44ZM11,13V41a1,1,0,0,0,1,1H36a1,1,0,0,0,1-1V13Z"/> + <g class="cls-2"> + <path class="cls-1" d="M35,12V38a2,2,0,0,1-2,2H10v1a2,2,0,0,0,2,2H36a2,2,0,0,0,2-2V12Z"/> + </g> + <path class="cls-1" d="M43,13H5a1,1,0,0,1,0-2H43a1,1,0,0,1,0,2Z"/> + <path class="cls-1" d="M17,35a1,1,0,0,1-1-1V20a1,1,0,0,1,2,0V34A1,1,0,0,1,17,35Z"/> + <path class="cls-1" d="M31,35a1,1,0,0,1-1-1V20a1,1,0,0,1,2,0V34A1,1,0,0,1,31,35Z"/> + <path class="cls-1" d="M24,37a1,1,0,0,1-1-1V18a1,1,0,0,1,2,0V36A1,1,0,0,1,24,37Z"/> + <path class="cls-1" d="M33,13H15a1,1,0,0,1-1-1V7a3,3,0,0,1,3-3H31a3,3,0,0,1,3,3v5A1,1,0,0,1,33,13ZM16,11H32V7a1,1,0,0,0-1-1H17a1,1,0,0,0-1,1Z"/> + </svg> \ No newline at end of file diff --git a/App/RobobinApp/RobobinApp.csproj b/App/RobobinApp/RobobinApp.csproj index 294a17f8..29a2b946 100644 --- a/App/RobobinApp/RobobinApp.csproj +++ b/App/RobobinApp/RobobinApp.csproj @@ -1,6 +1,6 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <!-->TargetFrameworks>net8.0-ios;net8.0-maccatalyst</TargetFrameworks--> + <TargetFrameworks>net8.0-android</TargetFrameworks> <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks> <OutputType>Exe</OutputType> <RootNamespace>Robobin</RootNamespace> @@ -12,20 +12,38 @@ <ApplicationId>com.companyname.robobin</ApplicationId> <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion> <ApplicationVersion>1</ApplicationVersion> - <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion> + <EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk> + <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</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> + <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-android|AnyCPU'"> + <EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk> + </PropertyGroup> <ItemGroup> + <MauiIcon Include="Platforms\Android\Resources\mipmap\robobinlogo1.png" /> <MauiIcon Include="Resources\AppIcon\robobinlogo.png" /> - <MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" /> <MauiImage Include="Resources\Images\*" /> <MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" /> <MauiFont Include="Resources\Fonts\*" /> <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> + <MauiSplashScreen Include="Platforms\Android\Resources\drawable\bin.svg"> + <Color>#512BD4</Color> + <BaseSize>128,128</BaseSize> + </MauiSplashScreen> + <MauiSplashScreen Include="Resources\Splash\bin.svg" Color="#8185b4" BaseSize="128,128" /> + </ItemGroup> + + <ItemGroup> + <AndroidResource Remove="Platforms\Android\Resources\mipmap\robobinlogo1.png" /> + </ItemGroup> + + <ItemGroup> + <None Remove="Platforms\Android\Resources\drawable\bin.svg" /> + <None Remove="Platforms\Android\Resources\mipmap\robobinlogo1.png" /> </ItemGroup> <ItemGroup> @@ -50,6 +68,9 @@ <Compile Update="Views\ConnectionPage.xaml.cs"> <DependentUpon>ConnectionPage.xaml</DependentUpon> </Compile> + <Compile Update="Views\MainPage_Android.xaml.cs"> + <DependentUpon>MainPage_Android.xaml</DependentUpon> + </Compile> </ItemGroup> <ItemGroup> @@ -62,6 +83,9 @@ <MauiXaml Update="Views\ConnectionPage.xaml"> <Generator>MSBuild:Compile</Generator> </MauiXaml> + <MauiXaml Update="Views\MainPage_Android.xaml"> + <Generator>MSBuild:Compile</Generator> + </MauiXaml> <MauiXaml Update="Views\SideBox.xaml"> <Generator>MSBuild:Compile</Generator> </MauiXaml> diff --git a/App/RobobinApp/RobobinApp.csproj.user b/App/RobobinApp/RobobinApp.csproj.user index db9abdfa..8e54b9db 100644 --- a/App/RobobinApp/RobobinApp.csproj.user +++ b/App/RobobinApp/RobobinApp.csproj.user @@ -2,9 +2,9 @@ <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <IsFirstTimeProjectOpen>False</IsFirstTimeProjectOpen> - <ActiveDebugFramework>net8.0-windows10.0.19041.0</ActiveDebugFramework> - <ActiveDebugProfile>Windows Machine</ActiveDebugProfile> - <SelectedPlatformGroup>Emulator</SelectedPlatformGroup> + <ActiveDebugFramework>net8.0-android</ActiveDebugFramework> + <ActiveDebugProfile>Samsung SM-A805F (Android 9.0 - API 28)</ActiveDebugProfile> + <SelectedPlatformGroup>PhysicalDevice</SelectedPlatformGroup> <DefaultDevice>pixel_5_-_api_34</DefaultDevice> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-android|AnyCPU'"> @@ -26,6 +26,9 @@ <MauiXaml Update="Views\ConnectionPage.xaml"> <SubType>Designer</SubType> </MauiXaml> + <MauiXaml Update="Views\MainPage_Android.xaml"> + <SubType>Designer</SubType> + </MauiXaml> <MauiXaml Update="Views\SideBox.xaml"> <SubType>Designer</SubType> </MauiXaml> diff --git a/App/RobobinApp/ViewModels/ConnectionPageViewModel.cs b/App/RobobinApp/ViewModels/ConnectionPageViewModel.cs index 74427aa2..97e98a2b 100644 --- a/App/RobobinApp/ViewModels/ConnectionPageViewModel.cs +++ b/App/RobobinApp/ViewModels/ConnectionPageViewModel.cs @@ -13,12 +13,16 @@ using RobobinApp.Models; using System.Net.NetworkInformation; using System.Collections.Generic; +#if WINDOWS using Windows.Networking.Connectivity; using Windows.Devices.WiFi; using System.Reflection.PortableExecutable; using Plugin.BLE.Windows; -using System.Text; using System.Windows.Documents; +#endif + +using System.Text; + using RobobinApp.Networking; namespace RobobinApp.ViewModels @@ -328,8 +332,8 @@ namespace RobobinApp.ViewModels private void OnDeviceDiscovered(object? sender, DeviceEventArgs e) { Debug.WriteLine($"Discovered device: {e.Device.Name ?? e.Device.Id.ToString()}"); - if (e.Device.Name.Equals("RoboBin-BT")) - { + //if (e.Device.Name.Equals("RoboBin-BT")) + //{ var bluetoothDevice = new BluetoothDevice( string.IsNullOrWhiteSpace(e.Device.Name) ? e.Device.Id.ToString() : e.Device.Name, e.Device.Id.ToString() @@ -341,7 +345,7 @@ namespace RobobinApp.ViewModels // Device is new, add it Microsoft.Maui.Controls.Device.BeginInvokeOnMainThread(() => BluetoothDevices.Add(bluetoothDevice)); } - } + //} } diff --git a/App/RobobinApp/Views/MainPage_Android.xaml b/App/RobobinApp/Views/MainPage_Android.xaml new file mode 100644 index 00000000..09ba3e2d --- /dev/null +++ b/App/RobobinApp/Views/MainPage_Android.xaml @@ -0,0 +1,69 @@ +<?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" + xmlns:local="clr-namespace:RobobinApp.Views" + xmlns:viewModels="clr-namespace:RobobinApp.ViewModels" + xmlns:drawable="clr-namespace:RobobinApp.Views" + x:Class="RobobinApp.Views.MainPage_Android" + Title=""> + + <ContentPage.BindingContext> + <viewModels:MainPageViewModel /> + </ContentPage.BindingContext> + + <ContentPage.Resources> + <ResourceDictionary> + <drawable:GraphicsDrawable x:Key="drawable" /> + <StyleSheet Source="/Resources/Styles/appstyle.css" /> + </ResourceDictionary> + </ContentPage.Resources> + + <!-- Make the entire content scrollable --> + <ScrollView> + <VerticalStackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"> + + <!-- Top Frame --> + <VerticalStackLayout StyleClass="sideFrame" + HorizontalOptions="FillAndExpand" + VerticalOptions="Start"> + <HorizontalStackLayout HorizontalOptions="Start" VerticalOptions="End"> + <Button Text="Admin" Command="{Binding ConnectToRobobinCommand}"/> + <Button Text="Setup" Command="{Binding ConnectToRobobinCommand}"/> + <Button Text="Info" /> + <Picker Title="Select Graph" + ItemsSource="{Binding GraphNames}" + SelectedIndexChanged="OnGraphSelected" + HorizontalOptions="Center" /> + </HorizontalStackLayout> + + <local:SideBox HeaderTitle="Queue:" /> + <local:SideBox HeaderTitle="Status:" /> + </VerticalStackLayout> + + <!-- Main Drawable Area with specific HeightRequest to ensure visibility --> + <Frame StyleClass="mainFrame" + HorizontalOptions="FillAndExpand" + VerticalOptions="Center" + HeightRequest="400"> + <!-- Adjust this value as needed --> + <GraphicsView x:Name="GraphicsView" + Drawable="{StaticResource drawable}"> + <GraphicsView.GestureRecognizers> + <TapGestureRecognizer Tapped="OnGraphicsViewTapped" /> + </GraphicsView.GestureRecognizers> + </GraphicsView> + </Frame> + + <!-- Bottom Frame --> + <VerticalStackLayout StyleClass="sideFrame" + HorizontalOptions="FillAndExpand" + VerticalOptions="End"> + + + <local:SideBox HeaderTitle="Mode:" /> + <local:SideBox HeaderTitle="Admin:" /> + </VerticalStackLayout> + + </VerticalStackLayout> + </ScrollView> +</ContentPage> diff --git a/App/RobobinApp/Views/MainPage_Android.xaml.cs b/App/RobobinApp/Views/MainPage_Android.xaml.cs new file mode 100644 index 00000000..2358d155 --- /dev/null +++ b/App/RobobinApp/Views/MainPage_Android.xaml.cs @@ -0,0 +1,91 @@ +using Microsoft.Maui.Controls; +using RobobinApp.ViewModels; +using RobobinApp.Models; +using System.Diagnostics; +using RobobinApp.Views; +using Robobin.Models; + +namespace RobobinApp.Views +{ + public partial class MainPage_Android : ContentPage + { + public MainPage_Android() + { + InitializeComponent(); + + + var drawable = (GraphicsDrawable)Resources["drawable"]; + if (BindingContext is MainPageViewModel viewModel) + { + drawable.SetGraph(viewModel.Graph); + } + } + + private void OnGraphSelected(object sender, EventArgs e) + { + + if (sender is Picker picker && BindingContext is MainPageViewModel viewModel) + { + + viewModel.SelectGraphCommand.Execute(picker.SelectedIndex); + + + var drawable = (GraphicsDrawable)Resources["drawable"]; + var newGraph = viewModel.Graphs.FirstOrDefault(g => g.Name == viewModel.Graph.Name); + + + if (newGraph != null) + { + drawable.SetGraph(newGraph); + GraphicsView.Invalidate(); + Debug.WriteLine("New Graph picked and drawn"); + } + else + { + Debug.WriteLine("Graph not found!"); + } + } + } + + private void OnGraphicsViewTapped(object sender, TappedEventArgs e) + { + var tapPoint = e.GetPosition(GraphicsView); + var drawable = (GraphicsDrawable)Resources["drawable"]; + + float scale = drawable.CurrentScale; + var offset = drawable.CurrentOffset; + + var tapPointX = (float)tapPoint.Value.X; + var tapPointY = (float)tapPoint.Value.Y; + var nearestNode = drawable.FindNearestNode(tapPointX, tapPointY, scale, offset.X, offset.Y); + + // Highlight the nearest node + drawable.HighlightNode(nearestNode); + + if (nearestNode != null) + { + // Find the home node + Node homeNode = drawable.GetHomeNode(); + + if (homeNode != null) + { + + List<Node> path = drawable.AStarPathfinding(nearestNode, homeNode); + drawable.Path = path; + GraphicsView.Invalidate(); + } + + DisplayAlert("Node Clicked", $"You clicked on node: {nearestNode.Name}", "OK"); + } + else + { + DisplayAlert("No Node", "No node was clicked.", "OK"); + } + + // Invalidate to trigger a redraw and highlight the node + GraphicsView.Invalidate(); + } + + } + +} -- GitLab