Skip to content

Commit

Permalink
Add auto-start functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
haefele committed Oct 15, 2023
1 parent f52e517 commit 7bd5891
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 29 deletions.
1 change: 1 addition & 0 deletions src/ChatPrisma/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ private IHostBuilder CreateHostBuilder(string[] args) => Microsoft.Extensions.Ho
});
services.AddSingleton<IPackageExtractor, ZipPackageExtractor>();
services.AddSingleton<IUpdateManager, UpdateManager>();
services.AddSingleton<IAutoStartService, RegistryAutoStartService>();

// Hosted Services
services.AddHostedService<StartKeyboardHooksHostedService>();
Expand Down
4 changes: 2 additions & 2 deletions src/ChatPrisma/HostedServices/PrismaHostedService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ChatPrisma.Services.Dialogs;
using ChatPrisma.Services.Dialogs;
using ChatPrisma.Services.KeyboardHooks;
using ChatPrisma.Services.TextExtractor;
using ChatPrisma.Services.ViewModels;
Expand Down Expand Up @@ -36,7 +36,7 @@ private async void KeyboardHooksOnCombinationPressed(object? sender, EventArgs e
try
{
var textEnhancementViewModel = viewModelFactory.CreateTextEnhancementViewModel(text);
dialogService.ShowDialog(textEnhancementViewModel);
await dialogService.ShowDialog(textEnhancementViewModel);
}
finally
{
Expand Down
7 changes: 7 additions & 0 deletions src/ChatPrisma/Services/AutoStart/IAutoStartService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ChatPrisma.Services.AutoStart;

public interface IAutoStartService
{
Task<bool> IsInAutoStart();
Task SetAutoStart(bool enabled);
}
42 changes: 42 additions & 0 deletions src/ChatPrisma/Services/AutoStart/RegistryAutoStartService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using ChatPrisma.Options;
using Microsoft.Extensions.Options;
using Microsoft.Win32;

namespace ChatPrisma.Services.AutoStart;

public class RegistryAutoStartService(IOptions<ApplicationOptions> applicationOptions) : IAutoStartService
{
public async Task<bool> IsInAutoStart()
{
await Task.CompletedTask;

var key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", writable: false);
var result = key?.GetValue(applicationOptions.Value.ApplicationName) is not null;

// If auto-start is enabled, ensure that we have the correct application path in the registry
// We do that by just enabling auto-start again
if (result is true)
{
await this.SetAutoStart(true);
}

return result;
}

public async Task SetAutoStart(bool enabled)
{
await Task.CompletedTask;

var key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", writable: true) ??
Registry.CurrentUser.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");

if (enabled)
{
key.SetValue(applicationOptions.Value.ApplicationName, $"\"{Environment.ProcessPath}\"");
}
else
{
key.DeleteValue(applicationOptions.Value.ApplicationName, throwOnMissingValue: false);
}
}
}
22 changes: 14 additions & 8 deletions src/ChatPrisma/Services/Dialogs/DialogService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Windows;
using System.Windows;
using System.Windows.Data;
using ChatPrisma.Options;
using ChatPrisma.Themes;
Expand All @@ -9,12 +9,9 @@ namespace ChatPrisma.Services.Dialogs;

public class DialogService(IServiceProvider serviceProvider, IOptions<ApplicationOptions> applicationOptions) : IDialogService
{
public bool? ShowDialog(object viewModel)
public async Task<bool?> ShowDialog(object viewModel)
{
var viewType = this.TryResolveViewType(viewModel);

if (viewType is null)
throw new PrismaException();
var viewType = this.ResolveViewType(viewModel);

var view = (FrameworkElement)ActivatorUtilities.CreateInstance(serviceProvider, viewType);
this.InvokeInitializeComponents(view);
Expand Down Expand Up @@ -49,13 +46,22 @@ public class DialogService(IServiceProvider serviceProvider, IOptions<Applicatio
configureWindow.Configure(window);
}

if (viewModel is IInitialize initialize)
{
await initialize.InitializeAsync();
}

return window.ShowDialog();
}

private Type? TryResolveViewType(object viewModel)
private Type ResolveViewType(object viewModel)
{
var viewTypeFullName = viewModel.GetType().FullName?.Replace("ViewModel", "View", StringComparison.OrdinalIgnoreCase);
return viewModel.GetType().Assembly.GetType(viewTypeFullName ?? string.Empty);
var viewType = viewModel.GetType().Assembly.GetType(viewTypeFullName ?? string.Empty);

return viewType is not null
? viewType
: throw new PrismaException($"Couldn't find view for view-model {viewModel.GetType().Name}");
}

private void InvokeInitializeComponents(FrameworkElement view)
Expand Down
6 changes: 3 additions & 3 deletions src/ChatPrisma/Services/Dialogs/IDialogService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace ChatPrisma.Services.Dialogs;
namespace ChatPrisma.Services.Dialogs;

public interface IDialogService
{
bool? ShowDialog(object viewModel);
}
Task<bool?> ShowDialog(object viewModel);
}
6 changes: 6 additions & 0 deletions src/ChatPrisma/Services/Dialogs/IInitialize.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace ChatPrisma.Services.Dialogs;

public interface IInitialize
{
Task InitializeAsync();
}
40 changes: 34 additions & 6 deletions src/ChatPrisma/Views/Settings/SettingsView.xaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,41 @@
<UserControl x:Class="ChatPrisma.Views.Settings.SettingsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="clr-namespace:ChatPrisma.Views.Settings"
xmlns:wpf="clr-namespace:FluentIcons.WPF;assembly=FluentIcons.WPF"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:themes="clr-namespace:ChatPrisma.Themes"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ChatPrisma.Views.Settings"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
d:DataContext="{d:DesignInstance local:SettingsViewModel}">
<Grid>
<TextBox Text="{Binding Test}" />
</Grid>

d:DataContext="{d:DesignInstance local:SettingsViewModel}"

themes:Attached.WindowTitle="Einstellungen"

Width="300">
<UserControl.Resources>
<dxmvvm:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<dxmvvm:BooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" Inverse="True" />
</UserControl.Resources>

<StackPanel>
<GroupBox Header="Autostart">
<Grid>
<StackPanel Visibility="{Binding IsAutoStartActive, Converter={StaticResource BooleanToVisibilityConverter}}"
Orientation="Horizontal">
<TextBlock Text="Autostart ist aktiviert" />
<wpf:SymbolIcon Symbol="Checkmark" Foreground="Green" />
<Button Content="Deaktivieren" Command="{Binding DisableAutoStartCommand}" />
</StackPanel>
<StackPanel Visibility="{Binding IsAutoStartActive, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
Orientation="Horizontal">
<TextBlock Text="Autostart ist deaktiviert" />
<wpf:SymbolIcon Symbol="ClockDismiss" Foreground="Red" />
<Button Content="Aktivieren" Command="{Binding EnableAutoStartCommand}" />
</StackPanel>
</Grid>
</GroupBox>
</StackPanel>
</UserControl>
26 changes: 25 additions & 1 deletion src/ChatPrisma/Views/Settings/SettingsViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
using ChatPrisma.Services.AutoStart;
using ChatPrisma.Services.Dialogs;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace ChatPrisma.Views.Settings;

public partial class SettingsViewModel : ObservableObject
public partial class SettingsViewModel(IAutoStartService autoStartService) : ObservableObject, IInitialize
{
[ObservableProperty]
private bool _isAutoStartActive;

public async Task InitializeAsync()
{
this.IsAutoStartActive = await autoStartService.IsInAutoStart();
}

[RelayCommand]
private async Task EnableAutoStart()
{
await autoStartService.SetAutoStart(true);
this.IsAutoStartActive = true;
}

[RelayCommand]
private async Task DisableAutoStart()
{
await autoStartService.SetAutoStart(false);
this.IsAutoStartActive = false;
}
}
18 changes: 9 additions & 9 deletions src/ChatPrisma/WindowsTray.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Windows;
using System.Windows;
using System.Windows.Controls;
using ChatPrisma.Services.Dialogs;
using ChatPrisma.Services.ViewModels;
Expand All @@ -12,9 +12,9 @@ namespace ChatPrisma;

public static class WindowsTray
{
public static void HandleDoubleClick(IServiceProvider serviceProvider)
public static async void HandleDoubleClick(IServiceProvider serviceProvider)
{
ShowAbout(serviceProvider);
await ShowAbout(serviceProvider);
}

public static ContextMenu CreateContextMenu(IServiceProvider serviceProvider)
Expand All @@ -27,33 +27,33 @@ public static ContextMenu CreateContextMenu(IServiceProvider serviceProvider)
{
Icon = new SymbolIcon { Symbol = Symbol.Settings },
Header = "Einstellungen",
Command = new RelayCommand(() => ShowSettings(serviceProvider))
Command = new AsyncRelayCommand(() => ShowSettings(serviceProvider))
},
new MenuItem
{
Icon = new SymbolIcon { Symbol = Symbol.Info },
Header = "Über",
Command = new RelayCommand(() => ShowAbout(serviceProvider))
Command = new AsyncRelayCommand(() => ShowAbout(serviceProvider))
}
}
};
}

private static void ShowSettings(IServiceProvider serviceProvider)
private static async Task ShowSettings(IServiceProvider serviceProvider)
{
var viewModelFactory = serviceProvider.GetRequiredService<IViewModelFactory>();
var dialogService = serviceProvider.GetRequiredService<IDialogService>();

var app = viewModelFactory.CreateSettingsViewModel();
dialogService.ShowDialog(app);
await dialogService.ShowDialog(app);
}

private static void ShowAbout(IServiceProvider serviceProvider)
private static async Task ShowAbout(IServiceProvider serviceProvider)
{
var viewModelFactory = serviceProvider.GetRequiredService<IViewModelFactory>();
var dialogService = serviceProvider.GetRequiredService<IDialogService>();

var app = viewModelFactory.CreateAboutViewModel();
dialogService.ShowDialog(app);
await dialogService.ShowDialog(app);
}
}

0 comments on commit 7bd5891

Please sign in to comment.