Skip to content

Commit 5047f82

Browse files
authored
Merge pull request #34 from FaithBeam/install
Add Start Menu Installer
2 parents 5b8cdbc + 9e83eba commit 5047f82

9 files changed

Lines changed: 207 additions & 7 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace YMouseButtonControl.Core.Services.StartMenuInstaller;
2+
3+
public interface IStartMenuInstallerService
4+
{
5+
bool InstallStatus();
6+
void Install();
7+
void Uninstall();
8+
}

YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using ReactiveUI;
88
using YMouseButtonControl.Core.Services.Logging;
99
using YMouseButtonControl.Core.Services.Settings;
10+
using YMouseButtonControl.Core.Services.StartMenuInstaller;
1011
using YMouseButtonControl.Core.Services.Theme;
1112
using YMouseButtonControl.Core.ViewModels.Models;
1213
using YMouseButtonControl.DataAccess.Models;
@@ -19,18 +20,22 @@ public class GlobalSettingsDialogViewModel : DialogBase, IGlobalSettingsDialogVi
1920
{
2021
private SettingBoolVm _startMinimizedSetting;
2122
private bool _loggingEnabled;
23+
private bool _startMenuChecked;
2224
private SettingIntVm _themeSetting;
2325
private ObservableCollection<ThemeVm> _themeCollection;
2426
private ThemeVm _selectedTheme;
2527
private readonly ObservableAsPropertyHelper<bool>? _applyIsExec;
2628

2729
public GlobalSettingsDialogViewModel(
30+
IStartMenuInstallerService startMenuInstallerService,
2831
IEnableLoggingService enableLoggingService,
2932
ISettingsService settingsService,
3033
IThemeService themeService
3134
)
3235
: base(themeService)
3336
{
37+
StartMenuEnabled = !OperatingSystem.IsMacOS();
38+
_startMenuChecked = StartMenuEnabled && startMenuInstallerService.InstallStatus();
3439
_startMinimizedSetting =
3540
settingsService.GetSetting("StartMinimized") as SettingBoolVm
3641
?? throw new Exception("Error retrieving StartMinimized setting");
@@ -54,16 +59,20 @@ IThemeService themeService
5459
x => x.LoggingEnabled,
5560
selector: val => val != enableLoggingService.GetLoggingState()
5661
);
62+
var startMenuChanged = this.WhenAnyValue(
63+
x => x.StartMenuChecked,
64+
selector: val => StartMenuEnabled && val != startMenuInstallerService.InstallStatus()
65+
);
5766
var themeChanged = this.WhenAnyValue(
5867
x => x.ThemeSetting.IntValue,
5968
selector: val =>
6069
settingsService.GetSetting("Theme") is not SettingIntVm curVal
6170
|| curVal.IntValue != val
6271
);
63-
6472
var applyIsExecObs = this.WhenAnyValue(x => x.AppIsExec);
6573
var canSave = startMinimizedChanged
6674
.Merge(loggingChanged)
75+
.Merge(startMenuChanged)
6776
.Merge(applyIsExecObs)
6877
.Merge(themeChanged);
6978
ApplyCommand = ReactiveCommand.Create(
@@ -80,6 +89,22 @@ IThemeService themeService
8089
enableLoggingService.DisableLogging();
8190
}
8291
}
92+
93+
if (
94+
StartMenuEnabled
95+
&& StartMenuChecked != startMenuInstallerService.InstallStatus()
96+
)
97+
{
98+
if (StartMenuChecked)
99+
{
100+
startMenuInstallerService.Install();
101+
}
102+
else
103+
{
104+
startMenuInstallerService.Uninstall();
105+
}
106+
}
107+
83108
using var trn = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
84109
settingsService.UpdateSetting(StartMinimized);
85110
settingsService.UpdateSetting(ThemeSetting);
@@ -92,6 +117,14 @@ IThemeService themeService
92117

93118
private bool AppIsExec => _applyIsExec?.Value ?? false;
94119

120+
public bool StartMenuChecked
121+
{
122+
get => _startMenuChecked;
123+
set => this.RaiseAndSetIfChanged(ref _startMenuChecked, value);
124+
}
125+
126+
public bool StartMenuEnabled { get; init; }
127+
95128
public SettingBoolVm StartMinimized
96129
{
97130
get => _startMinimizedSetting;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using YMouseButtonControl.Core.Services.StartMenuInstaller;
2+
3+
namespace YMouseButtonControl.Linux.Services;
4+
5+
public class StartMenuInstallerService : IStartMenuInstallerService
6+
{
7+
private const string DesktopFile = """
8+
[Desktop Entry]
9+
Type=Application
10+
Exec={0}
11+
Path={1}
12+
Hidden=false
13+
NoDisplay=false
14+
X-GNOME-Autostart-enabled=true
15+
Name=YMouseButtonControl
16+
Comment=YMouseButtonControl
17+
""";
18+
19+
private readonly string _localShare = Environment.GetFolderPath(
20+
Environment.SpecialFolder.LocalApplicationData
21+
);
22+
23+
private readonly string _desktopFilePath;
24+
25+
public StartMenuInstallerService()
26+
{
27+
var applicationsDir = Path.Combine(_localShare, "applications");
28+
_desktopFilePath = Path.Combine(applicationsDir, "YMouseButtonControl.desktop");
29+
}
30+
31+
public bool InstallStatus() =>
32+
File.Exists(_desktopFilePath)
33+
&& File.ReadAllText(_desktopFilePath).Contains($"Exec={GetCurExePath()}");
34+
35+
public void Install() =>
36+
File.WriteAllText(
37+
_desktopFilePath,
38+
string.Format(DesktopFile, GetCurExePath(), GetCurExeParentPath())
39+
);
40+
41+
public void Uninstall() => File.Delete(_desktopFilePath);
42+
43+
private static string GetCurExeParentPath() =>
44+
Path.GetDirectoryName(GetCurExePath())
45+
?? throw new Exception("Error retrieving parent of process path");
46+
47+
private static string GetCurExePath() =>
48+
Environment.ProcessPath ?? throw new Exception("Error retrieving process path");
49+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using YMouseButtonControl.Core.Services.StartMenuInstaller;
2+
3+
namespace YMouseButtonControl.MacOS.Services;
4+
5+
public class StartMenuInstaller : IStartMenuInstallerService
6+
{
7+
public bool InstallStatus()
8+
{
9+
throw new System.NotImplementedException();
10+
}
11+
12+
public void Install()
13+
{
14+
throw new System.NotImplementedException();
15+
}
16+
17+
public void Uninstall()
18+
{
19+
throw new System.NotImplementedException();
20+
}
21+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System;
2+
using System.IO;
3+
using WindowsShortcutFactory;
4+
using YMouseButtonControl.Core.Services.StartMenuInstaller;
5+
6+
namespace YMouseButtonControl.Windows.Services;
7+
8+
public class StartMenuInstallerService : IStartMenuInstallerService
9+
{
10+
private readonly string _roamingAppDataFolder = Environment.GetFolderPath(
11+
Environment.SpecialFolder.ApplicationData
12+
);
13+
14+
private readonly string _roamingYMouseButtonsFolder;
15+
16+
private readonly string _roamingYmouseButtonsShortcutPath;
17+
18+
public StartMenuInstallerService()
19+
{
20+
_roamingYMouseButtonsFolder = Path.Combine(
21+
_roamingAppDataFolder,
22+
"Microsoft",
23+
"Windows",
24+
"Start Menu",
25+
"Programs",
26+
"YMouseButtonControl"
27+
);
28+
_roamingYmouseButtonsShortcutPath = Path.Combine(
29+
_roamingYMouseButtonsFolder,
30+
"YMouseButtonControl.lnk"
31+
);
32+
}
33+
34+
public bool InstallStatus()
35+
{
36+
if (!File.Exists(_roamingYmouseButtonsShortcutPath))
37+
{
38+
return false;
39+
}
40+
using var shortcut = WindowsShortcut.Load(_roamingYmouseButtonsShortcutPath);
41+
return shortcut.Path == GetCurExePath();
42+
}
43+
44+
public void Install()
45+
{
46+
if (File.Exists(_roamingYmouseButtonsShortcutPath))
47+
{
48+
File.Delete(_roamingYmouseButtonsShortcutPath);
49+
}
50+
51+
if (!Directory.Exists(_roamingYMouseButtonsFolder))
52+
{
53+
Directory.CreateDirectory(_roamingYMouseButtonsFolder);
54+
}
55+
56+
using var shortcut = new WindowsShortcut();
57+
shortcut.Path = GetCurExePath();
58+
shortcut.WorkingDirectory = GetCurExeParentPath();
59+
shortcut.Save(_roamingYmouseButtonsShortcutPath);
60+
}
61+
62+
public void Uninstall() => File.Delete(_roamingYmouseButtonsShortcutPath);
63+
64+
private static string GetCurExeParentPath() =>
65+
Path.GetDirectoryName(GetCurExePath())
66+
?? throw new Exception("Error retrieving parent of process path");
67+
68+
private static string GetCurExePath() =>
69+
Environment.ProcessPath ?? throw new Exception("Error retrieving process path");
70+
}

YMouseButtonControl.Windows/YMouseButtonControl.Windows.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
</PackageReference>
2525
<PackageReference Include="ReactiveUI" Version="20.1.1" />
2626
<PackageReference Include="System.Drawing.Common" Version="8.0.8" />
27+
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />
2728
</ItemGroup>
2829

2930
</Project>

YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using YMouseButtonControl.Core.Services.Processes;
88
using YMouseButtonControl.Core.Services.Profiles;
99
using YMouseButtonControl.Core.Services.Settings;
10+
using YMouseButtonControl.Core.Services.StartMenuInstaller;
1011
using YMouseButtonControl.Core.Services.StartupInstaller;
1112
using YMouseButtonControl.Core.Services.Theme;
1213

@@ -53,6 +54,7 @@ private static void RegisterLinuxServices(IServiceCollection services)
5354
{
5455
services
5556
.AddScoped<IStartupInstallerService, Linux.Services.StartupInstallerService>()
57+
.AddScoped<IStartMenuInstallerService, Linux.Services.StartMenuInstallerService>()
5658
.AddScoped<IProcessMonitorService, Linux.Services.ProcessMonitorService>()
5759
.AddScoped<IBackgroundTasksRunner, Linux.Services.BackgroundTasksRunner>();
5860
if (Environment.GetEnvironmentVariable("XDG_SESSION_TYPE") == "x11")
@@ -69,6 +71,7 @@ private static void RegisterLinuxServices(IServiceCollection services)
6971
private static void RegisterWindowsServices(IServiceCollection services)
7072
{
7173
services
74+
.AddScoped<IStartMenuInstallerService, Windows.Services.StartMenuInstallerService>()
7275
.AddScoped<IStartupInstallerService, Windows.Services.StartupInstallerService>()
7376
.AddScoped<IProcessMonitorService, Windows.Services.ProcessMonitorService>()
7477
.AddScoped<ICurrentWindowService, Windows.Services.CurrentWindowService>()
@@ -79,6 +82,7 @@ private static void RegisterMacOsServices(IServiceCollection services)
7982
{
8083
services
8184
.AddScoped<IStartupInstallerService, MacOS.Services.StartupInstallerService>()
85+
.AddScoped<IStartMenuInstallerService, MacOS.Services.StartMenuInstaller>()
8286
.AddScoped<IProcessMonitorService, MacOS.Services.ProcessMonitorService>()
8387
.AddScoped<ICurrentWindowService, MacOS.Services.CurrentWindowService>()
8488
.AddScoped<IBackgroundTasksRunner, MacOS.Services.BackgroundTasksRunner>();

YMouseButtonControl/Views/Dialogs/GlobalSettingsDialog.axaml

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,32 @@
1414
<mainWindow:GlobalSettingsDialogViewModel />
1515
</Design.DataContext>
1616

17-
<Grid Margin="6" RowDefinitions="Auto,Auto,Auto,*">
18-
<CheckBox Grid.Row="0" Content="Start Minimized"
17+
<Grid Margin="6" RowDefinitions="Auto,Auto,Auto,Auto,*">
18+
<CheckBox Grid.Row="0"
19+
Content="Start Minimized"
1920
IsChecked="{Binding StartMinimized.BoolValue}" />
20-
<CheckBox Grid.Row="1" Content="Logging"
21+
<CheckBox Grid.Row="1"
22+
Content="Start Menu"
23+
IsEnabled="{Binding StartMenuEnabled}"
24+
IsChecked="{Binding StartMenuChecked}">
25+
<ToolTip.Tip>
26+
<TextBlock>
27+
Add YMouseButtonControl to the start menu.
28+
<LineBreak />
29+
Disabled for macOS.
30+
</TextBlock>
31+
</ToolTip.Tip>
32+
</CheckBox>
33+
<CheckBox Grid.Row="2"
34+
Content="Logging"
2135
IsChecked="{Binding LoggingEnabled}">
2236
<ToolTip.Tip>
2337
<TextBlock>
2438
Whether or not logging to file YMouseButtonControl.log is performed. Requires a restart.
2539
</TextBlock>
2640
</ToolTip.Tip>
2741
</CheckBox>
28-
<StackPanel Grid.Row="2">
42+
<StackPanel Grid.Row="3">
2943
<Label Content="Theme" />
3044
<ComboBox ItemsSource="{Binding ThemeCollection}"
3145
SelectedItem="{Binding SelectedTheme}">
@@ -47,7 +61,7 @@
4761
</TextBlock>
4862
</ToolTip.Tip>
4963
</StackPanel>
50-
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom">
64+
<StackPanel Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom">
5165
<Button Content="Apply" Command="{Binding ApplyCommand}" />
5266
<Button Content="Cancel" Click="Cancel_OnClick"></Button>
5367
</StackPanel>

YMouseButtonControl/YMouseButtonControl.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<!--Avalonia doesen't support TrimMode=link currently,but we are working on that https://github.com/AvaloniaUI/Avalonia/issues/6892 -->
77
<TrimMode>copyused</TrimMode>
88
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
9-
<LangVersion>10</LangVersion>
9+
<LangVersion>default</LangVersion>
1010
<AssemblyVersion>0.1.0</AssemblyVersion>
1111
<FileVersion>0.1.0</FileVersion>
1212
<Version>0.1.0</Version>

0 commit comments

Comments
 (0)