Skip to content

Commit 6ce75df

Browse files
committed
Added Settings page
1 parent 9e7678f commit 6ce75df

10 files changed

Lines changed: 273 additions & 7 deletions

File tree

HttpGamepadInput/App.xaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
33
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
44
xmlns:local="clr-namespace:HttpGamepadInput"
5+
xmlns:converters="clr-namespace:HttpGamepadInput.BaseClasses.Converters"
56
x:Class="HttpGamepadInput.App">
67
<Application.Resources>
78
<ResourceDictionary>
9+
<converters:StringNotEmptyConverter x:Key="StringNotEmptyConverter" />
10+
<converters:BoolToColorConverter x:Key="BoolToColorConverter"
11+
TrueColor="Green"
12+
FalseColor="Red" />
813
<ResourceDictionary.MergedDictionaries>
914
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
1015
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />

HttpGamepadInput/AppShell.xaml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@
55
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
66
xmlns:views="clr-namespace:HttpGamepadInput.Views"
77
Shell.FlyoutBehavior="Flyout"
8+
Shell.NavBarIsVisible="False"
89
Title="Gamepad Input via HTTP">
910

10-
<ShellContent
11-
Title="Gamepad"
12-
ContentTemplate="{DataTemplate views:MainPage}"
13-
Route="MainPage" />
14-
11+
<FlyoutItem Title="Gamepads">
12+
<ShellContent ContentTemplate="{DataTemplate views:MainPage}"
13+
Title="1 Gamepad"
14+
Route="MainPage" />
15+
</FlyoutItem>
16+
<FlyoutItem Title="Settings">
17+
<ShellContent ContentTemplate="{DataTemplate views:SettingsPage}"
18+
Title="Settings"
19+
Route="Settings" />
20+
</FlyoutItem>
1521
</Shell>

HttpGamepadInput/AppShell.xaml.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
namespace HttpGamepadInput;
1+
using HttpGamepadInput.Views;
2+
3+
namespace HttpGamepadInput;
24

35
public partial class AppShell : Shell
46
{
57
public AppShell()
68
{
79
InitializeComponent();
10+
11+
Routing.RegisterRoute(nameof(MainPage), typeof(MainPage));
12+
Routing.RegisterRoute(nameof(SettingsPage), typeof(SettingsPage));
813
}
914
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using System.Globalization;
3+
using Microsoft.Maui.Controls;
4+
5+
namespace HttpGamepadInput.BaseClasses.Converters;
6+
7+
public class BoolToColorConverter : IValueConverter
8+
{
9+
public Color TrueColor { get; set; } = Colors.Green;
10+
public Color FalseColor { get; set; } = Colors.Red;
11+
12+
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
13+
{
14+
if (value is bool b)
15+
return b ? TrueColor : FalseColor;
16+
17+
return FalseColor;
18+
}
19+
20+
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
21+
=> throw new NotImplementedException();
22+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.Globalization;
3+
using Microsoft.Maui.Controls;
4+
5+
namespace HttpGamepadInput.BaseClasses.Converters;
6+
7+
public class StringNotEmptyConverter : IValueConverter
8+
{
9+
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
10+
=> !string.IsNullOrWhiteSpace(value?.ToString());
11+
12+
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
13+
=> throw new NotImplementedException();
14+
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
using System.Windows.Input;
2+
using HttpGamepadInput.BaseClasses;
3+
4+
namespace HttpGamepadInput.ViewModels;
5+
6+
public class SettingsViewModel : BindableBase
7+
{
8+
public ICommand SaveCommand { get; }
9+
public ICommand TestConnectionCommand { get; }
10+
11+
private string _serverUrl = "http://localhost:8080";
12+
public string ServerUrl
13+
{
14+
get => _serverUrl;
15+
set => SetProperty(ref _serverUrl, value);
16+
}
17+
18+
private bool _isNotError = true;
19+
public bool IsNotError
20+
{
21+
get => _isNotError;
22+
set => SetProperty(ref _isNotError, value);
23+
}
24+
25+
private string _validationMessage;
26+
public string ValidationMessage
27+
{
28+
get => _validationMessage;
29+
set
30+
{
31+
if (_validationMessage != value)
32+
{
33+
_validationMessage = value;
34+
OnPropertyChanged();
35+
}
36+
}
37+
}
38+
39+
public SettingsViewModel()
40+
{
41+
SaveCommand = new Command(OnSaveClicked);
42+
TestConnectionCommand = new Command(OnTestConnectionClicked);
43+
}
44+
45+
private bool IsValidUrl(string url)
46+
{
47+
if (string.IsNullOrWhiteSpace(ServerUrl))
48+
{
49+
ValidationMessage = "URL can't be empty.";
50+
IsNotError = false;
51+
return false;
52+
}
53+
else if (!Uri.TryCreate(ServerUrl, UriKind.Absolute, out var uri) ||
54+
!(uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
55+
{
56+
ValidationMessage = "Enter valid url address (http or https).";
57+
IsNotError = false;
58+
return false;
59+
}
60+
else
61+
{
62+
ValidationMessage = string.Empty; // All Ok
63+
IsNotError = true;
64+
}
65+
return true;
66+
}
67+
68+
private void OnSaveClicked()
69+
{
70+
string url = ServerUrl.Trim();
71+
72+
if (!IsValidUrl(url))
73+
{
74+
return;
75+
}
76+
77+
Preferences.Set("ServerUrl", url);
78+
}
79+
80+
private async void OnTestConnectionClicked()
81+
{
82+
string url = ServerUrl.Trim();
83+
84+
if (!IsValidUrl(url))
85+
{
86+
return;
87+
}
88+
89+
if (!Uri.TryCreate(url, UriKind.Absolute, out var baseUri))
90+
{
91+
ValidationMessage = "Error: Filed creating Uri.";
92+
IsNotError = false;
93+
return;
94+
}
95+
96+
try
97+
{
98+
var versionUri = new Uri(baseUri, "/version/");
99+
100+
using HttpClient client = new HttpClient
101+
{
102+
Timeout = TimeSpan.FromSeconds(5)
103+
};
104+
105+
HttpResponseMessage response = await client.GetAsync(versionUri);
106+
if (response.IsSuccessStatusCode)
107+
{
108+
ValidationMessage = "Success! Connection to the server established.";
109+
IsNotError = true;
110+
}
111+
else
112+
{
113+
ValidationMessage = $"Error. Server response: {(int)response.StatusCode} {response.ReasonPhrase}";
114+
IsNotError = false;
115+
}
116+
}
117+
catch (Exception ex)
118+
{
119+
ValidationMessage = $"Error. Failed to connect: {ex.Message}";
120+
IsNotError = false;
121+
}
122+
}
123+
}

HttpGamepadInput/Views/MainPage.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
xmlns:base="clr-namespace:HttpGamepadInput.BaseClasses"
66
x:Class="HttpGamepadInput.Views.MainPage"
77
Background="White"
8+
Shell.NavBarIsVisible="False"
89
x:DataType="viewModels:GamepadViewModel">
910

1011
<ContentPage.BindingContext>

HttpGamepadInput/Views/MainPage.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace HttpGamepadInput.Views;
44

55
public partial class MainPage : ContentPage
66
{
7-
public GamepadViewModel ViewModel => (GamepadViewModel)BindingContext;
7+
private GamepadViewModel ViewModel => (GamepadViewModel) BindingContext;
88
public MainPage()
99
{
1010
InitializeComponent();
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
5+
xmlns:viewModels="clr-namespace:HttpGamepadInput.ViewModels"
6+
Shell.NavBarIsVisible="False"
7+
x:Class="HttpGamepadInput.Views.SettingsPage"
8+
x:DataType="viewModels:SettingsViewModel">
9+
10+
<ContentPage.BindingContext>
11+
<viewModels:SettingsViewModel />
12+
</ContentPage.BindingContext>
13+
14+
<ContentPage.Content>
15+
<VerticalStackLayout Padding="20" Spacing="15">
16+
<Label Text="Server URL:"
17+
FontSize="18" />
18+
19+
<Entry x:Name="ServerUrlEntry"
20+
Placeholder="https://example.com/"
21+
Text="{Binding ServerUrl}"
22+
Keyboard="Url" />
23+
24+
<!-- Error message -->
25+
<Label Text="{Binding ValidationMessage}"
26+
TextColor="{Binding IsNotError, Converter={StaticResource BoolToColorConverter}}"
27+
IsVisible="{Binding ValidationMessage, Converter={StaticResource StringNotEmptyConverter}}"/>
28+
29+
<Button Text="Save"
30+
Command="{Binding SaveCommand}"
31+
BackgroundColor="LightGray"
32+
TextColor="Black" >
33+
<VisualStateManager.VisualStateGroups>
34+
<VisualStateGroup Name="CommonStates">
35+
<VisualState Name="Normal" />
36+
<VisualState Name="Pressed">
37+
<VisualState.Setters>
38+
<Setter Property="BackgroundColor" Value="Gray" />
39+
</VisualState.Setters>
40+
</VisualState>
41+
</VisualStateGroup>
42+
</VisualStateManager.VisualStateGroups>
43+
</Button>
44+
45+
<Button Text="Test connection"
46+
Command="{Binding TestConnectionCommand}"
47+
BackgroundColor="LightGray"
48+
TextColor="Black" >
49+
<VisualStateManager.VisualStateGroups>
50+
<VisualStateGroup Name="CommonStates">
51+
<VisualState Name="Normal" />
52+
<VisualState Name="Pressed">
53+
<VisualState.Setters>
54+
<Setter Property="BackgroundColor" Value="Gray" />
55+
</VisualState.Setters>
56+
</VisualState>
57+
</VisualStateGroup>
58+
</VisualStateManager.VisualStateGroups>
59+
</Button>
60+
</VerticalStackLayout>
61+
</ContentPage.Content>
62+
</ContentPage>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using HttpGamepadInput.ViewModels;
7+
8+
namespace HttpGamepadInput.Views;
9+
10+
public partial class SettingsPage : ContentPage
11+
{
12+
public SettingsViewModel ViewModel => (SettingsViewModel) BindingContext;
13+
14+
public SettingsPage()
15+
{
16+
InitializeComponent();
17+
}
18+
19+
protected override void OnAppearing()
20+
{
21+
base.OnAppearing();
22+
23+
if (Preferences.ContainsKey("ServerUrl"))
24+
{
25+
ServerUrlEntry.Text = Preferences.Get("ServerUrl", string.Empty);
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)