Skip to content

Commit

Permalink
- added Extensions generic hosting
Browse files Browse the repository at this point in the history
- refactoring System.Component background thread with Background Service
- fixed grid width on profiles
- minor improvements to integration tab
- enable stopping/starting web listener
- improved install/uninstall gsi config
- improved the splash screen text with gsi config install
  • Loading branch information
pjmagee committed Jan 9, 2025
1 parent 5985ae7 commit 2222600
Show file tree
Hide file tree
Showing 20 changed files with 309 additions and 151 deletions.
131 changes: 66 additions & 65 deletions src/Dota2Helper/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@
using Dota2Helper.Views;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using static Avalonia.Controls.Design;

namespace Dota2Helper;

public partial class App : Application
{
public static IServiceProvider ServiceProvider => _serviceProvider ?? throw new InvalidOperationException("Service provider is not initialized");

static IServiceProvider? _serviceProvider;
public static IServiceProvider ServiceProvider => _host?.Services ?? throw new InvalidOperationException("Service provider is not initialized");
static IHost? _host;

public override void Initialize()
{
Expand All @@ -36,68 +36,73 @@ public override void Initialize()

public override async void OnFrameworkInitializationCompleted()
{
var services = new ServiceCollection().AddOptions();

if (IsDesignMode)
{
services.AddSingleton<SettingsService>(new DesignSettingsService());
}
else
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false)
.AddJsonFile("appsettings.timers.default.json", optional: false, reloadOnChange: false)
.Build();

services
.Configure<Settings>(configuration.Bind)
.Configure<List<DotaTimer>>(configuration.GetSection("DefaultTimers").Bind);

services
.AddSingleton<SettingsService>();
}
IHostBuilder builder = Host.CreateDefaultBuilder();

services
.AddSingleton<GameTimeProvider>()
.AddSingleton<ITimeProvider>(sp => sp.GetRequiredService<GameTimeProvider>())
.AddSingleton<DemoProvider>()
.AddSingleton<ViewModelFactory>()
.AddKeyedSingleton<IAudioService, AudioService>(nameof(AudioService))
.AddKeyedSingleton<IAudioService, TimerAudioService>(nameof(TimerAudioService))
.AddSingleton<RealProvider>()
.AddSingleton<GsiConfigWatcher>()
.AddSingleton<GsiConfigService>()
.AddSingleton<ProfileService>()
.AddSingleton<AudioService>()
.AddSingleton<TimerAudioService>()
.AddSingleton<SettingsWindow>()
.AddSingleton<LocalListener>()
.AddSingleton<SplashScreenViewModel>()
.AddSingleton<TimersViewModel>()
.AddSingleton<SettingsViewModel>();

_serviceProvider = services.BuildServiceProvider();

var dota2ConfigService = ServiceProvider.GetRequiredService<GsiConfigService>();
var localListener = ServiceProvider.GetRequiredService<LocalListener>();
localListener.RunWorkerAsync();
builder.ConfigureAppConfiguration((hostingContext, config) =>
{
if (!IsDesignMode)
{
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false);
config.AddJsonFile("appsettings.timers.default.json", optional: false, reloadOnChange: false);
}
}
);

builder.ConfigureServices((hostingContext, services) =>
{
services.AddOptions();

if (IsDesignMode)
{
services.AddSingleton<SettingsService>(new DesignSettingsService());
}
else
{
services
.Configure<Settings>(hostingContext.Configuration)
.Configure<List<DotaTimer>>(hostingContext.Configuration.GetSection("DefaultTimers").Bind);

services
.AddSingleton<SettingsService>();
}

services
.AddSingleton<GameTimeProvider>()
.AddSingleton<ITimeProvider>(sp => sp.GetRequiredService<GameTimeProvider>())
.AddSingleton<DemoTimeProvider>()
.AddSingleton<ViewModelFactory>()
.AddKeyedSingleton<IAudioService, AudioService>(nameof(AudioService))
.AddKeyedSingleton<IAudioService, TimerAudioService>(nameof(TimerAudioService))
.AddSingleton<RealGameTimeProvider>()
.AddSingleton<GsiConfigWatcher>()
.AddSingleton<GsiConfigService>()
.AddSingleton<ProfileService>()
.AddSingleton<AudioService>()
.AddSingleton<TimerAudioService>()
.AddSingleton<SettingsWindow>()
.AddSingleton<LocalListener>()
.AddSingleton<SplashScreenViewModel>()
.AddSingleton<TimersViewModel>()
.AddSingleton<SettingsViewModel>();

services
.AddHostedService(sp => sp.GetRequiredService<GameTimeProvider>())
.AddHostedService(sp => sp.GetRequiredService<LocalListener>())
.AddHostedService(sp => sp.GetRequiredService<DemoTimeProvider>());
}
);

_host = builder.Build();

if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
var splash = new SplashWindow
{
DataContext = ServiceProvider.GetRequiredService<SplashScreenViewModel>(),
};

var splash = new SplashWindow(dataContext: ServiceProvider.GetRequiredService<SplashScreenViewModel>());
desktop.MainWindow = splash;
splash.Show();

dota2ConfigService.TryInstall();

await Task.WhenAny(
Task.Delay(8000),
Task.Delay(Timeout.Infinite, ((SplashScreenViewModel)splash.DataContext).CancellationToken)
Task.Delay(Timeout.Infinite, ((SplashScreenViewModel)splash.DataContext!).CancellationToken)
);

BindingPlugins.DataValidators.RemoveAt(0);
Expand All @@ -107,21 +112,17 @@ await Task.WhenAny(
DataContext = ServiceProvider.GetRequiredService<TimersViewModel>(),
};

var task = _host.RunAsync();

desktop.MainWindow.Show();
splash.Close();
}
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
{
singleViewPlatform.MainView = new TimersWindow

desktop.MainWindow.Closing += (sender, args) =>
{
DataContext = ServiceProvider.GetRequiredService<TimersViewModel>(),
_host.Dispose();
};
}

base.OnFrameworkInitializationCompleted();
}




}
9 changes: 3 additions & 6 deletions src/Dota2Helper/Controls/AboutTabContent.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="viewModels:SettingsViewModel"
x:Class="Dota2Helper.Controls.AboutTabContent" Margin="5">

<StackPanel Orientation="Vertical" Spacing="5" HorizontalAlignment="Center">
<TextBlock Margin="5" FontWeight="Bold" TextAlignment="Center">
All 3rd party packages used in this project.
</TextBlock>
<StackPanel Orientation="Vertical" Spacing="5">
<TextBlock>Dota2 Helper is created by Patrick Magee</TextBlock>
<TextBlock>Third party packages and licenses</TextBlock>
<DataGrid ItemsSource="{Binding PackageItems}"
IsReadOnly="True" Margin="5"
GridLinesVisibility="All"
Expand All @@ -21,5 +19,4 @@
HorizontalScrollBarVisibility="Visible"
AutoGenerateColumns="True" />
</StackPanel>

</UserControl>
26 changes: 17 additions & 9 deletions src/Dota2Helper/Controls/IntegrationTabContent.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:Dota2Helper.ViewModels"
xmlns:timers="clr-namespace:Dota2Helper.Features.Timers"
xmlns:converters="clr-namespace:Dota2Helper.Features.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Dota2Helper.Controls.IntegrationTabContent"
x:DataType="vm:SettingsViewModel">
<UserControl.Resources>
<converters:IsListeningConverter x:Key="IsListeningConverter" />
<converters:IsConfigInstalledConverter x:Key="IsConfigInstalledConverter" />
</UserControl.Resources>

<StackPanel Margin="0 10" Orientation="Vertical">

<StackPanel Margin="5" Orientation="Vertical" Spacing="5">
Expand Down Expand Up @@ -47,7 +53,7 @@

<!-- row 1 -->
<Label Grid.Column="0" Grid.Row="1" VerticalAlignment="Center">
Connection:
Status:
</Label>
<TextBlock Grid.Column="1" Grid.Row="1"
VerticalAlignment="Center" IsVisible="{Binding IsListening}" Text="Listening" Foreground="Green" />
Expand Down Expand Up @@ -79,37 +85,39 @@
</Grid>

<StackPanel Margin="5" Orientation="Vertical" Spacing="5">

<Button Width="140" Height="30"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
ToolTip.Tip="Copy the gamestate_integration_d2helper.cfg file to the Dota 2 game folder."
Padding="2"
Command="{Binding InstallCommand}">
Command="{Binding OpenFolderCommand}">
<Button.Content>
<StackPanel Orientation="Horizontal" Spacing="2">
<TextBlock Text="Install GSI" VerticalAlignment="Center" />
<TextBlock Text="Open Folder" VerticalAlignment="Center" />
</StackPanel>
</Button.Content>
</Button>

<Button Width="140" Height="30"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Padding="2"
Command="{Binding OpenFolderCommand}">
Padding="2" ToolTip.Tip="Copy/Delete the gamestate_integration_d2helper.cfg file to the Dota 2 game folder."
Command="{Binding InstallUninstallCommand}">
<Button.Content>
<StackPanel Orientation="Horizontal" Spacing="2">
<TextBlock Text="Open Folder" VerticalAlignment="Center" />
<TextBlock Text="{Binding IsInstalled, Converter={StaticResource IsConfigInstalledConverter}}" VerticalAlignment="Center" />
</StackPanel>
</Button.Content>
</Button>
<!-- Buttons for Starting and Stopping the Listener -->
<Button Width="140" Height="30"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Padding="2"
Command="{Binding InstallCommand}">
Command="{Binding StartStopListeningCommand}">
<Button.Content>
<StackPanel Orientation="Horizontal" Spacing="2">
<TextBlock Text="Uninstall GSI" VerticalAlignment="Center" />
<TextBlock Text="{Binding IsListening, Converter={StaticResource IsListeningConverter}}" VerticalAlignment="Center" />
</StackPanel>
</Button.Content>
</Button>
Expand Down
7 changes: 3 additions & 4 deletions src/Dota2Helper/Controls/ProfilesTabContent.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,16 @@
CanUserSortColumns="True"
BorderThickness="0.5"
MaxHeight="400"
Width="600"
ColumnHeaderTheme="{DynamicResource DataGridHeaderTheme}"
HorizontalAlignment="Left"
SelectedItem="{Binding SelectedProfileViewModel, Mode=TwoWay}"
SelectedIndex="{Binding SelectedProfileIndex, Mode=TwoWay}"
SelectionMode="Single"
SelectionMode="Single" AutoGenerateColumns="False"
HorizontalScrollBarVisibility="Auto">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="200" />
<DataGridTextColumn Header="Timers" Binding="{Binding Timers.Count}" />
<DataGridTemplateColumn>
<DataGridTextColumn Header="Timers" Binding="{Binding Timers.Count}" Width="150" />
<DataGridTemplateColumn Header="Actions" Width="150">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Width="30" Height="30"
Expand Down
5 changes: 3 additions & 2 deletions src/Dota2Helper/Controls/TimersTabContent.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
xmlns:avalonia="clr-namespace:FluentIcons.Avalonia;assembly=FluentIcons.Avalonia"
xmlns:viewModels="clr-namespace:Dota2Helper.ViewModels"
xmlns:audio="clr-namespace:Dota2Helper.Features.Audio"
xmlns:converters="clr-namespace:Dota2Helper.Features.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Dota2Helper.Controls.TimersTabContent"
x:DataType="viewModels:SettingsViewModel">
<TemplatedControl.Resources>
<audio:AudioFilePathConverter x:Key="AudioFilePathConverter" />
<converters:AudioFilePathConverter x:Key="AudioFilePathConverter" />
</TemplatedControl.Resources>
<StackPanel Orientation="Vertical" Margin="0 10" Spacing="5">
<TextBlock Text="OpenAI was used for the default audio that comes with the application." />
<StackPanel Orientation="Horizontal" Spacing="5">
<DataGrid x:Name="DataGrid"
ItemsSource="{Binding Timers}"
Expand Down Expand Up @@ -169,6 +171,5 @@
</Button.Content>
</Button>
</StackPanel>
<TextBlock Text="AI was used for the default audio that comes with the application." />
</StackPanel>
</UserControl>
2 changes: 1 addition & 1 deletion src/Dota2Helper/Design/DesignTimersViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class DesignTimersViewModel : TimersViewModel

}

DesignTimersViewModel(SettingsService settingsService) : this(new GameTimeProvider(settingsService, new RealProvider(), new DemoProvider()))
DesignTimersViewModel(SettingsService settingsService) : this(new GameTimeProvider(settingsService, new RealGameTimeProvider(), new DemoTimeProvider()))
{

}
Expand Down
5 changes: 3 additions & 2 deletions src/Dota2Helper/Dota2Helper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.3" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.3" />
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.3" Condition="'$(Configuration)' == 'Debug'" />
<PackageReference Include="Avalonia.Xaml.Interactions" Version="11.2.0.1" />
<PackageReference Include="Avalonia.Xaml.Interactions.Events" Version="11.2.0.1" />
<PackageReference Include="Avalonia.Xaml.Interactions" Version="11.2.0.7" />
<PackageReference Include="Avalonia.Xaml.Interactions.Events" Version="11.2.0.7" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="FluentIcons.Avalonia" Version="1.1.271" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.0" />
<PackageReference Include="NAudio" Version="2.2.1" />
<PackageReference Include="ValveKeyValue" Version="0.12.0.391" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Avalonia.Controls;
using Avalonia.Data.Converters;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Styling;
using Dota2Helper.ViewModels;

namespace Dota2Helper.Features.Audio;
namespace Dota2Helper.Features.Converters;


public class AudioFilePathConverter : IValueConverter
{
Expand Down
23 changes: 23 additions & 0 deletions src/Dota2Helper/Features/Converters/IsConfigInstalledConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Globalization;
using Avalonia.Data.Converters;

namespace Dota2Helper.Features.Converters;

public class IsConfigInstalledConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is bool isConfigInstalled)
{
return isConfigInstalled ? "Uninstall" : "Install";
}

return value;
}

public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Loading

0 comments on commit 2222600

Please sign in to comment.