From 9ca090513a99f5663ee524be41f7671d879d6d97 Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Fri, 6 Dec 2024 06:51:56 -0500 Subject: [PATCH 01/39] wip --- .../Repositories/ButtonMappingRepository.cs | 2 +- .../Repositories/ProfileRepository.cs | 2 +- .../Repositories/SettingRepository.cs | 2 +- .../Repositories/ThemeRepository.cs | 2 +- .../GlobalSettingsDialogViewModel.cs | 1 - .../YMouseButtonControl.Core.csproj | 19 +- .../Context/YMouseButtonControlDbContext.cs | 219 +++++++++--------- .../Queries/BaseQueries.cs | 21 -- .../Queries/ButtonMappingQueries.cs | 26 --- .../Queries/ProfileQueries.cs | 27 --- .../Queries/SettingQueries.cs | 20 -- .../Queries/ThemeQueries.cs | 19 -- ...YMouseButtonControl.Infrastructure.csproj} | 6 +- .../Models/ButtonMapping.cs | 2 +- .../Models/Profile.cs | 4 +- .../Models/Setting.cs | 2 +- .../Models/SimulatedKeystrokeType.cs | 2 +- .../Models/Theme.cs | 2 +- .../YMouseButtonControl.Domain.csproj | 9 + YMouseButtonControl.sln | 14 +- YMouseButtonControl/App.axaml.cs | 2 +- .../YMouseButtonControl.csproj | 1 - 22 files changed, 162 insertions(+), 242 deletions(-) delete mode 100644 YMouseButtonControl.DataAccess/Queries/BaseQueries.cs delete mode 100644 YMouseButtonControl.DataAccess/Queries/ButtonMappingQueries.cs delete mode 100644 YMouseButtonControl.DataAccess/Queries/ProfileQueries.cs delete mode 100644 YMouseButtonControl.DataAccess/Queries/SettingQueries.cs delete mode 100644 YMouseButtonControl.DataAccess/Queries/ThemeQueries.cs rename YMouseButtonControl.DataAccess/{YMouseButtonControl.DataAccess.csproj => YMouseButtonControl.Infrastructure.csproj} (65%) rename {YMouseButtonControl.DataAccess => YMouseButtonControl.Domain}/Models/ButtonMapping.cs (95%) rename {YMouseButtonControl.DataAccess => YMouseButtonControl.Domain}/Models/Profile.cs (80%) rename {YMouseButtonControl.DataAccess => YMouseButtonControl.Domain}/Models/Setting.cs (89%) rename {YMouseButtonControl.DataAccess => YMouseButtonControl.Domain}/Models/SimulatedKeystrokeType.cs (87%) rename {YMouseButtonControl.DataAccess => YMouseButtonControl.Domain}/Models/Theme.cs (79%) create mode 100644 YMouseButtonControl.Domain/YMouseButtonControl.Domain.csproj diff --git a/YMouseButtonControl.Core/Repositories/ButtonMappingRepository.cs b/YMouseButtonControl.Core/Repositories/ButtonMappingRepository.cs index f9db682..154c1fe 100644 --- a/YMouseButtonControl.Core/Repositories/ButtonMappingRepository.cs +++ b/YMouseButtonControl.Core/Repositories/ButtonMappingRepository.cs @@ -5,9 +5,9 @@ using Dapper; using YMouseButtonControl.Core.Mappings; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Context; using YMouseButtonControl.DataAccess.Models; using YMouseButtonControl.DataAccess.Queries; +using YMouseButtonControl.Infrastructure.Context; namespace YMouseButtonControl.Core.Repositories; diff --git a/YMouseButtonControl.Core/Repositories/ProfileRepository.cs b/YMouseButtonControl.Core/Repositories/ProfileRepository.cs index b1c04ac..3726ff1 100644 --- a/YMouseButtonControl.Core/Repositories/ProfileRepository.cs +++ b/YMouseButtonControl.Core/Repositories/ProfileRepository.cs @@ -5,9 +5,9 @@ using Dapper; using YMouseButtonControl.Core.Mappings; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Context; using YMouseButtonControl.DataAccess.Models; using YMouseButtonControl.DataAccess.Queries; +using YMouseButtonControl.Infrastructure.Context; namespace YMouseButtonControl.Core.Repositories; diff --git a/YMouseButtonControl.Core/Repositories/SettingRepository.cs b/YMouseButtonControl.Core/Repositories/SettingRepository.cs index 7c42ed2..626de1d 100644 --- a/YMouseButtonControl.Core/Repositories/SettingRepository.cs +++ b/YMouseButtonControl.Core/Repositories/SettingRepository.cs @@ -6,9 +6,9 @@ using Dapper; using YMouseButtonControl.Core.Mappings; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Context; using YMouseButtonControl.DataAccess.Models; using YMouseButtonControl.DataAccess.Queries; +using YMouseButtonControl.Infrastructure.Context; using static Dapper.SqlMapper; namespace YMouseButtonControl.Core.Repositories; diff --git a/YMouseButtonControl.Core/Repositories/ThemeRepository.cs b/YMouseButtonControl.Core/Repositories/ThemeRepository.cs index e34083a..a5554ef 100644 --- a/YMouseButtonControl.Core/Repositories/ThemeRepository.cs +++ b/YMouseButtonControl.Core/Repositories/ThemeRepository.cs @@ -6,9 +6,9 @@ using Dapper; using YMouseButtonControl.Core.Mappings; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Context; using YMouseButtonControl.DataAccess.Models; using YMouseButtonControl.DataAccess.Queries; +using YMouseButtonControl.Infrastructure.Context; namespace YMouseButtonControl.Core.Repositories; diff --git a/YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs index 0653252..8ab7720 100644 --- a/YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs @@ -10,7 +10,6 @@ using YMouseButtonControl.Core.Services.StartMenuInstaller; using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; namespace YMouseButtonControl.Core.ViewModels.MainWindow; diff --git a/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj b/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj index 77da661..8587cba 100644 --- a/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj +++ b/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj @@ -18,22 +18,21 @@ - - - - - - - - + + + + + + + - + - + diff --git a/YMouseButtonControl.DataAccess/Context/YMouseButtonControlDbContext.cs b/YMouseButtonControl.DataAccess/Context/YMouseButtonControlDbContext.cs index da048ff..395fd5f 100644 --- a/YMouseButtonControl.DataAccess/Context/YMouseButtonControlDbContext.cs +++ b/YMouseButtonControl.DataAccess/Context/YMouseButtonControlDbContext.cs @@ -1,117 +1,128 @@ using System.Data; using Dapper; using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; +using YMouseButtonControl.Domain.Models; -namespace YMouseButtonControl.DataAccess.Context; +namespace YMouseButtonControl.Infrastructure.Context; -public class YMouseButtonControlDbContext(IConfigurationRoot? configuration) +public class YMouseButtonControlDbContext(DbContextOptions opts) + : DbContext(opts) { - public IConfigurationRoot? Configuration { get; } = configuration; + public DbSet Profiles { get; set; } = null!; + public DbSet Settings { get; set; } = null!; + public DbSet SettingBools { get; set; } = null!; + public DbSet SettingStrings { get; set; } = null!; + public DbSet SettingInts { get; set; } = null!; + public DbSet Themes { get; set; } = null!; + public DbSet ButtonMappings { get; set; } = null!; + public DbSet DisabledMappings { get; set; } = null!; + public DbSet NothingMappings { get; set; } = null!; + public DbSet SimulatedKeystrokeMappings { get; set; } = null!; + public DbSet RightClickMappings { get; set; } = null!; - public IDbConnection CreateConnection() + protected override void OnModelCreating(ModelBuilder modelBuilder) { - return new SqliteConnection( - Configuration?.GetConnectionString("YMouseButtonControlContext") - ); - } - - public void Init() - { - using var conn = CreateConnection(); - InitProfiles(); - InitSettings(); - InitThemes(); - InitButtonMappings(); - return; - - void InitProfiles() - { - const string sql = """ - CREATE TABLE IF NOT EXISTS - Profiles ( - Id INTEGER PRIMARY KEY AUTOINCREMENT, - IsDefault BOOLEAN, - Checked BOOLEAN, - DisplayPriority INTEGER, - Name TEXT NOT NULL, - Description TEXT NOT NULL, - WindowCaption TEXT NOT NULL, - Process TEXT NOT NULL, - WindowClass TEXT NOT NULL, - ParentClass TEXT NOT NULL, - MatchType TEXT NOT NULL - ); - INSERT OR IGNORE INTO Profiles ( - Id, IsDefault, Checked, Name, Description, WindowCaption, Process, WindowClass, ParentClass, MatchType) - VALUES ('1', '1', '1', 'Default', 'Default description', 'N/A', '*', 'N/A', 'N/A', 'N/A'); - """; - conn.Execute(sql); - } - - void InitSettings() - { - const string sql = """ - CREATE TABLE IF NOT EXISTS - Settings ( - Id INTEGER PRIMARY KEY AUTOINCREMENT, - Name TEXT NOT NULL, - BoolValue BOOLEAN, - StringValue TEXT, - IntValue INTEGER, - SettingType INTEGER NOT NULL - ); - INSERT OR IGNORE INTO Settings (Id, Name, BoolValue, SettingType) VALUES ('1', 'StartMinimized', 0, '1'); - INSERT OR IGNORE INTO Settings (Id, Name, IntValue, SettingType) VALUES ('2', 'Theme', '1', '3'); - """; - conn.Execute(sql); - } + modelBuilder + .Entity() + .HasData( + new Profile + { + Id = 1, + IsDefault = true, + Checked = true, + DisplayPriority = 1, + Name = "Default", + Description = "Default description", + WindowCaption = "N/A", + Process = "*", + MatchType = "N/A", + ParentClass = "N/A", + WindowClass = "N/A", + } + ); - void InitThemes() - { - const string sql = """ - CREATE TABLE IF NOT EXISTS - Themes ( - Id INTEGER PRIMARY KEY AUTOINCREMENT, - Name TEXT NOT NULL, - Background TEXT NOT NULL, - Highlight TEXT NOT NULL - ); - INSERT OR IGNORE INTO Themes (Id, Name, Background, Highlight) VALUES ('1', 'Default', 'SystemAltHighColor','SystemAccentColor'); - INSERT OR IGNORE INTO Themes (Id, Name, Background, Highlight) VALUES ('2', 'Light', 'White', 'Yellow'); - INSERT OR IGNORE INTO Themes (Id, Name, Background, Highlight) VALUES ('3', 'Dark', 'Black', '#3700b3'); - """; - conn.Execute(sql); - } + modelBuilder + .Entity() + .HasData( + [ + new NothingMapping + { + Id = 1, + MouseButton = MouseButton.Mb1, + ProfileId = 1, + }, + new NothingMapping + { + Id = 2, + MouseButton = MouseButton.Mb2, + ProfileId = 1, + }, + new NothingMapping + { + Id = 3, + MouseButton = MouseButton.Mb3, + ProfileId = 1, + }, + new NothingMapping + { + Id = 4, + MouseButton = MouseButton.Mb4, + ProfileId = 1, + }, + new NothingMapping + { + Id = 5, + MouseButton = MouseButton.Mb5, + ProfileId = 1, + }, + new NothingMapping + { + Id = 6, + MouseButton = MouseButton.Mwu, + ProfileId = 1, + }, + new NothingMapping + { + Id = 7, + MouseButton = MouseButton.Mwd, + ProfileId = 1, + }, + new NothingMapping + { + Id = 8, + MouseButton = MouseButton.Mwl, + ProfileId = 1, + }, + new NothingMapping + { + Id = 9, + MouseButton = MouseButton.Mwr, + ProfileId = 1, + }, + ] + ); - void InitButtonMappings() - { - const string sql = """ - CREATE TABLE IF NOT EXISTS - ButtonMappings ( - Id INTEGER PRIMARY KEY AUTOINCREMENT, - Keys TEXT, - MouseButton INTEGER NOT NULL, - ProfileId INTEGER NOT NULL, - SimulatedKeystrokeType INTEGER, - Selected BOOLEAN, - BlockOriginalMouseInput BOOLEAN, - AutoRepeatDelay INTEGER, - AutoRepeatRandomizeDelayEnabled BOOLEAN, - ButtonMappingType INTEGER NOT NULL, - FOREIGN KEY (ProfileId) REFERENCES Profiles (Id) ON DELETE CASCADE - ); - INSERT OR IGNORE INTO ButtonMappings (Id, MouseButton, ProfileId, ButtonMappingType) VALUES ('1', '0', '1', '1'); - INSERT OR IGNORE INTO ButtonMappings (Id, MouseButton, ProfileId, ButtonMappingType) VALUES ('2', '1', '1', '1'); - INSERT OR IGNORE INTO ButtonMappings (Id, MouseButton, ProfileId, ButtonMappingType) VALUES ('3', '2', '1', '1'); - INSERT OR IGNORE INTO ButtonMappings (Id, MouseButton, ProfileId, ButtonMappingType) VALUES ('4', '3', '1', '1'); - INSERT OR IGNORE INTO ButtonMappings (Id, MouseButton, ProfileId, ButtonMappingType) VALUES ('5', '4', '1', '1'); - INSERT OR IGNORE INTO ButtonMappings (Id, MouseButton, ProfileId, ButtonMappingType) VALUES ('6', '5', '1', '1'); - INSERT OR IGNORE INTO ButtonMappings (Id, MouseButton, ProfileId, ButtonMappingType) VALUES ('7', '6', '1', '1'); - INSERT OR IGNORE INTO ButtonMappings (Id, MouseButton, ProfileId, ButtonMappingType) VALUES ('8', '7', '1', '1'); - INSERT OR IGNORE INTO ButtonMappings (Id, MouseButton, ProfileId, ButtonMappingType) VALUES ('9', '8', '1', '1'); - """; - conn.Execute(sql); - } + modelBuilder + .Entity() + .HasData( + new SettingBool + { + Id = 1, + Name = "StartMinimized", + BoolValue = false, + } + ); + modelBuilder + .Entity() + .HasData( + new SettingInt + { + Id = 2, + Name = "Theme", + IntValue = 3, + } + ); } } diff --git a/YMouseButtonControl.DataAccess/Queries/BaseQueries.cs b/YMouseButtonControl.DataAccess/Queries/BaseQueries.cs deleted file mode 100644 index 37f6cfa..0000000 --- a/YMouseButtonControl.DataAccess/Queries/BaseQueries.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace YMouseButtonControl.DataAccess.Queries; - -public abstract class BaseQueries -{ - public abstract string Add(); - - public virtual string GetByName(string tblName) => - $""" - SELECT * FROM {tblName} - WHERE Name = @Name - LIMIT 1; - """; - - public virtual string GetAll(string tblName) => $"SELECT * FROM {tblName};"; - - public virtual string GetById(string tblName) => $"SELECT * FROM {tblName} WHERE Id = @Id;"; - - public abstract string Update(); - - public virtual string DeleteById(string tblName) => $"DELETE FROM {tblName} WHERE Id = @Id;"; -} diff --git a/YMouseButtonControl.DataAccess/Queries/ButtonMappingQueries.cs b/YMouseButtonControl.DataAccess/Queries/ButtonMappingQueries.cs deleted file mode 100644 index f7f56c6..0000000 --- a/YMouseButtonControl.DataAccess/Queries/ButtonMappingQueries.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace YMouseButtonControl.DataAccess.Queries; - -public class ButtonMappingQueries : BaseQueries -{ - public string GetByProfileId() => "SELECT * FROM ButtonMappings WHERE ProfileId = @Id;"; - - public override string Add() => - """ - INSERT INTO ButtonMappings - (Keys, MouseButton, ProfileId, SimulatedKeystrokeType, Selected, BlockOriginalMouseInput, ButtonMappingType, AutoRepeatDelay, AutoRepeatRandomizeDelayEnabled) - VALUES (@Keys, @MouseButton, @ProfileId, @SimulatedKeystrokeType, @Selected, @BlockOriginalMouseInput, @ButtonMappingType, @AutoRepeatDelay, @AutoRepeatRandomizeDelayEnabled); - """; - - public override string Update() => - """ - UPDATE ButtonMappings - SET Keys = @Keys, - MouseButton = @MouseButton, - ProfileId = @ProfileId, - SimulatedKeystrokeType = @SimulatedKeystrokeType, - Selected = @Selected, - AutoRepeatDelay = @AutoRepeatDelay, - AutoRepeatRandomizeDelayEnabled = @AutoRepeatRandomizeDelayEnabled, - BlockOriginalMouseInput = @BlockOriginalMouseInput; - """; -} diff --git a/YMouseButtonControl.DataAccess/Queries/ProfileQueries.cs b/YMouseButtonControl.DataAccess/Queries/ProfileQueries.cs deleted file mode 100644 index 2f5fe9c..0000000 --- a/YMouseButtonControl.DataAccess/Queries/ProfileQueries.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace YMouseButtonControl.DataAccess.Queries; - -public class ProfileQueries : BaseQueries -{ - public override string Add() => - """ - INSERT INTO Profiles - (Id, IsDefault, Checked, DisplayPriority, Name, Description, WindowCaption, Process, WindowClass, ParentClass, MatchType) - VALUES (@Id, @IsDefault, @Checked, @DisplayPriority, @Name, @Description, @WindowCaption, @Process, @WindowClass, @ParentClass, @MatchType); - SELECT SEQ from sqlite_sequence WHERE name='Profiles'; - """; - - public override string Update() => - """ - UPDATE Profiles - SET IsDefault = @IsDefault, - Checked = @Checked, - DisplayPriority = @DisplayPriority, - Name = @Name, - Description = @Description, - WindowCaption = @WindowCaption, - Process = @Process, - WindowClass = @WindowClass, - ParentClass = @ParentClass, - MatchType = @MatchType; - """; -} diff --git a/YMouseButtonControl.DataAccess/Queries/SettingQueries.cs b/YMouseButtonControl.DataAccess/Queries/SettingQueries.cs deleted file mode 100644 index 02e6532..0000000 --- a/YMouseButtonControl.DataAccess/Queries/SettingQueries.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace YMouseButtonControl.DataAccess.Queries; - -public class SettingQueries : BaseQueries -{ - public override string Add() => - """ - INSERT INTO Settings (Id, Name, BoolValue, StringValue, IntValue) - VALUES (@Id, @Name, @BoolValue, @StringValue, @IntValue); - """; - - public override string Update() => - """ - UPDATE Settings - SET Name = @Name, - BoolValue = @BoolValue, - StringValue = @StringValue, - IntValue = @IntValue - WHERE Id = @Id; - """; -} diff --git a/YMouseButtonControl.DataAccess/Queries/ThemeQueries.cs b/YMouseButtonControl.DataAccess/Queries/ThemeQueries.cs deleted file mode 100644 index 45e9cff..0000000 --- a/YMouseButtonControl.DataAccess/Queries/ThemeQueries.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace YMouseButtonControl.DataAccess.Queries; - -public class ThemeQueries : BaseQueries -{ - public override string Add() => - """ - INSERT INTO Themes (Id, Name, Background, Highlight) - VALUES (@Id, @Name, @Background, @Highlight); - """; - - public override string Update() => - """ - UPDATE Themes - SET Name = @Name, - Background = @Background, - Highlight = @Highlight - Where Id = @Id, - """; -} diff --git a/YMouseButtonControl.DataAccess/YMouseButtonControl.DataAccess.csproj b/YMouseButtonControl.DataAccess/YMouseButtonControl.Infrastructure.csproj similarity index 65% rename from YMouseButtonControl.DataAccess/YMouseButtonControl.DataAccess.csproj rename to YMouseButtonControl.DataAccess/YMouseButtonControl.Infrastructure.csproj index bc46183..c4ca276 100644 --- a/YMouseButtonControl.DataAccess/YMouseButtonControl.DataAccess.csproj +++ b/YMouseButtonControl.DataAccess/YMouseButtonControl.Infrastructure.csproj @@ -7,9 +7,13 @@ - + + + + + diff --git a/YMouseButtonControl.DataAccess/Models/ButtonMapping.cs b/YMouseButtonControl.Domain/Models/ButtonMapping.cs similarity index 95% rename from YMouseButtonControl.DataAccess/Models/ButtonMapping.cs rename to YMouseButtonControl.Domain/Models/ButtonMapping.cs index 16cefea..c38817e 100644 --- a/YMouseButtonControl.DataAccess/Models/ButtonMapping.cs +++ b/YMouseButtonControl.Domain/Models/ButtonMapping.cs @@ -1,4 +1,4 @@ -namespace YMouseButtonControl.DataAccess.Models; +namespace YMouseButtonControl.Domain.Models; public enum MouseButton { diff --git a/YMouseButtonControl.DataAccess/Models/Profile.cs b/YMouseButtonControl.Domain/Models/Profile.cs similarity index 80% rename from YMouseButtonControl.DataAccess/Models/Profile.cs rename to YMouseButtonControl.Domain/Models/Profile.cs index 43e06c8..aa465ea 100644 --- a/YMouseButtonControl.DataAccess/Models/Profile.cs +++ b/YMouseButtonControl.Domain/Models/Profile.cs @@ -1,4 +1,4 @@ -namespace YMouseButtonControl.DataAccess.Models; +namespace YMouseButtonControl.Domain.Models; public class Profile { @@ -14,5 +14,5 @@ public class Profile public required string ParentClass { get; set; } public required string MatchType { get; set; } - public virtual ICollection? ButtonMappings { get; set; } + public virtual ICollection ButtonMappings { get; set; } = []; } diff --git a/YMouseButtonControl.DataAccess/Models/Setting.cs b/YMouseButtonControl.Domain/Models/Setting.cs similarity index 89% rename from YMouseButtonControl.DataAccess/Models/Setting.cs rename to YMouseButtonControl.Domain/Models/Setting.cs index 943e649..329638a 100644 --- a/YMouseButtonControl.DataAccess/Models/Setting.cs +++ b/YMouseButtonControl.Domain/Models/Setting.cs @@ -1,4 +1,4 @@ -namespace YMouseButtonControl.DataAccess.Models; +namespace YMouseButtonControl.Domain.Models; public abstract class Setting { diff --git a/YMouseButtonControl.DataAccess/Models/SimulatedKeystrokeType.cs b/YMouseButtonControl.Domain/Models/SimulatedKeystrokeType.cs similarity index 87% rename from YMouseButtonControl.DataAccess/Models/SimulatedKeystrokeType.cs rename to YMouseButtonControl.Domain/Models/SimulatedKeystrokeType.cs index 6d32881..332b730 100644 --- a/YMouseButtonControl.DataAccess/Models/SimulatedKeystrokeType.cs +++ b/YMouseButtonControl.Domain/Models/SimulatedKeystrokeType.cs @@ -1,4 +1,4 @@ -namespace YMouseButtonControl.DataAccess.Models; +namespace YMouseButtonControl.Domain.Models; public enum SimulatedKeystrokeType { diff --git a/YMouseButtonControl.DataAccess/Models/Theme.cs b/YMouseButtonControl.Domain/Models/Theme.cs similarity index 79% rename from YMouseButtonControl.DataAccess/Models/Theme.cs rename to YMouseButtonControl.Domain/Models/Theme.cs index c2090a1..b91c248 100644 --- a/YMouseButtonControl.DataAccess/Models/Theme.cs +++ b/YMouseButtonControl.Domain/Models/Theme.cs @@ -1,4 +1,4 @@ -namespace YMouseButtonControl.DataAccess.Models; +namespace YMouseButtonControl.Domain.Models; public class Theme { diff --git a/YMouseButtonControl.Domain/YMouseButtonControl.Domain.csproj b/YMouseButtonControl.Domain/YMouseButtonControl.Domain.csproj new file mode 100644 index 0000000..3a63532 --- /dev/null +++ b/YMouseButtonControl.Domain/YMouseButtonControl.Domain.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/YMouseButtonControl.sln b/YMouseButtonControl.sln index 996cabb..aa7e3fd 100644 --- a/YMouseButtonControl.sln +++ b/YMouseButtonControl.sln @@ -1,10 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35527.113 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YMouseButtonControl.Core.Tests", "YMouseButtonControl.Core.Tests\YMouseButtonControl.Core.Tests.csproj", "{0F770391-A4A1-611D-4FBA-125A6EB42834}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YMouseButtonControl.Core", "YMouseButtonControl.Core\YMouseButtonControl.Core.csproj", "{CEB84FCC-DB49-6456-7173-1F508E465D31}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YMouseButtonControl.DataAccess", "YMouseButtonControl.DataAccess\YMouseButtonControl.DataAccess.csproj", "{A4C2C9B9-43FA-ACCF-4C5B-E79ECC6F61BA}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YMouseButtonControl.Infrastructure", "YMouseButtonControl.DataAccess\YMouseButtonControl.Infrastructure.csproj", "{A4C2C9B9-43FA-ACCF-4C5B-E79ECC6F61BA}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YMouseButtonControl.Linux.Tests", "YMouseButtonControl.Linux.Tests\YMouseButtonControl.Linux.Tests.csproj", "{BD4EFA4F-A2CD-2BDE-BAA5-C55B4B220A84}" EndProject @@ -18,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YMouseButtonControl.Windows EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YMouseButtonControl", "YMouseButtonControl\YMouseButtonControl.csproj", "{9E275480-14AB-A39F-C3FB-ED2FDB97361F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YMouseButtonControl.Domain", "YMouseButtonControl.Domain\YMouseButtonControl.Domain.csproj", "{4DE55456-2875-4979-BB42-8D57B0FDE353}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -60,5 +65,12 @@ Global {9E275480-14AB-A39F-C3FB-ED2FDB97361F}.Debug|Any CPU.Build.0 = Debug|Any CPU {9E275480-14AB-A39F-C3FB-ED2FDB97361F}.Release|Any CPU.ActiveCfg = Release|Any CPU {9E275480-14AB-A39F-C3FB-ED2FDB97361F}.Release|Any CPU.Build.0 = Release|Any CPU + {4DE55456-2875-4979-BB42-8D57B0FDE353}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DE55456-2875-4979-BB42-8D57B0FDE353}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4DE55456-2875-4979-BB42-8D57B0FDE353}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4DE55456-2875-4979-BB42-8D57B0FDE353}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection EndGlobal diff --git a/YMouseButtonControl/App.axaml.cs b/YMouseButtonControl/App.axaml.cs index 946bfe7..2d457b1 100644 --- a/YMouseButtonControl/App.axaml.cs +++ b/YMouseButtonControl/App.axaml.cs @@ -18,8 +18,8 @@ using YMouseButtonControl.Core.ViewModels.MainWindow; using YMouseButtonControl.Core.ViewModels.Models; using YMouseButtonControl.Core.Views; -using YMouseButtonControl.DataAccess.Context; using YMouseButtonControl.DependencyInjection; +using YMouseButtonControl.Infrastructure.Context; using ILogger = Microsoft.Extensions.Logging.ILogger; using LogLevel = Microsoft.Extensions.Logging.LogLevel; diff --git a/YMouseButtonControl/YMouseButtonControl.csproj b/YMouseButtonControl/YMouseButtonControl.csproj index e93bb78..3b855d5 100644 --- a/YMouseButtonControl/YMouseButtonControl.csproj +++ b/YMouseButtonControl/YMouseButtonControl.csproj @@ -75,7 +75,6 @@ - From 7cd32e63551e8a590320757894c0a370de802193 Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sat, 7 Dec 2024 14:45:32 -0500 Subject: [PATCH 02/39] wip --- .../Mappings/ButtonMappingMapper.cs | 2 +- .../Mappings/ProfileMapper.cs | 2 +- .../Mappings/SettingMapper.cs | 2 +- .../Mappings/ThemeMapper.cs | 2 +- .../Repositories/ButtonMappingRepository.cs | 86 ++-- .../Repositories/IRepository.cs | 5 - .../Repositories/ProfileRepository.cs | 135 ++----- .../Repositories/SettingRepository.cs | 159 ++------ .../Repositories/ThemeRepository.cs | 76 ++-- .../Services/Profiles/ProfilesService.cs | 78 +++- .../Services/Settings/SettingsService.cs | 2 +- .../Services/Theme/ThemeService.cs | 4 +- .../LayerViewModel/LayerViewModel.cs | 2 +- .../LayerViewModel/MouseComboViewModel.cs | 3 +- .../MouseComboViewModelFactory.cs | 2 +- .../ShowSimulatedKeystrokesDialogService.cs | 2 +- .../SimulatedKeystrokesDialogViewModel.cs | 2 +- .../Features/Apply/ApplyProfiles.cs | 44 ++- .../GlobalSettingsDialogViewModel.cs | 2 - .../MainWindow/MainWindowViewModel.cs | 59 +-- .../ViewModels/Models/BaseButtonMappingVm.cs | 2 +- .../ViewModels/Models/ProfileVm.cs | 2 +- .../ProcessSelectorDialogViewModel.cs | 2 +- .../YMouseButtonControl.Core.csproj | 3 +- .../Context/YMouseButtonControlDbContext.cs | 38 +- .../20241207140626_Initial.Designer.cs | 349 ++++++++++++++++ .../Migrations/20241207140626_Initial.cs | 150 +++++++ .../20241207141716_AddThemes.Designer.cs | 372 ++++++++++++++++++ .../Migrations/20241207141716_AddThemes.cs | 45 +++ ...tDefaultProfileDisplayPriority.Designer.cs | 372 ++++++++++++++++++ ...35_CorrectDefaultProfileDisplayPriority.cs | 32 ++ ...ouseButtonControlDbContextModelSnapshot.cs | 369 +++++++++++++++++ YMouseButtonControl/App.axaml.cs | 8 +- .../DataAccessBootstrapper.cs | 7 +- .../ViewModelsBootstrapper.cs | 2 +- .../YMouseButtonControl.csproj | 7 + 36 files changed, 1993 insertions(+), 436 deletions(-) create mode 100644 YMouseButtonControl.DataAccess/Migrations/20241207140626_Initial.Designer.cs create mode 100644 YMouseButtonControl.DataAccess/Migrations/20241207140626_Initial.cs create mode 100644 YMouseButtonControl.DataAccess/Migrations/20241207141716_AddThemes.Designer.cs create mode 100644 YMouseButtonControl.DataAccess/Migrations/20241207141716_AddThemes.cs create mode 100644 YMouseButtonControl.DataAccess/Migrations/20241207142135_CorrectDefaultProfileDisplayPriority.Designer.cs create mode 100644 YMouseButtonControl.DataAccess/Migrations/20241207142135_CorrectDefaultProfileDisplayPriority.cs create mode 100644 YMouseButtonControl.DataAccess/Migrations/YMouseButtonControlDbContextModelSnapshot.cs diff --git a/YMouseButtonControl.Core/Mappings/ButtonMappingMapper.cs b/YMouseButtonControl.Core/Mappings/ButtonMappingMapper.cs index 46fd134..65a4254 100644 --- a/YMouseButtonControl.Core/Mappings/ButtonMappingMapper.cs +++ b/YMouseButtonControl.Core/Mappings/ButtonMappingMapper.cs @@ -1,7 +1,7 @@ using System; using Riok.Mapperly.Abstractions; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.Mappings; diff --git a/YMouseButtonControl.Core/Mappings/ProfileMapper.cs b/YMouseButtonControl.Core/Mappings/ProfileMapper.cs index 681b35d..87e76e0 100644 --- a/YMouseButtonControl.Core/Mappings/ProfileMapper.cs +++ b/YMouseButtonControl.Core/Mappings/ProfileMapper.cs @@ -2,7 +2,7 @@ using System.Linq; using Riok.Mapperly.Abstractions; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.Mappings; diff --git a/YMouseButtonControl.Core/Mappings/SettingMapper.cs b/YMouseButtonControl.Core/Mappings/SettingMapper.cs index 4173c2e..86f6221 100644 --- a/YMouseButtonControl.Core/Mappings/SettingMapper.cs +++ b/YMouseButtonControl.Core/Mappings/SettingMapper.cs @@ -1,6 +1,6 @@ using Riok.Mapperly.Abstractions; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.Mappings; diff --git a/YMouseButtonControl.Core/Mappings/ThemeMapper.cs b/YMouseButtonControl.Core/Mappings/ThemeMapper.cs index 97be0c3..a63b067 100644 --- a/YMouseButtonControl.Core/Mappings/ThemeMapper.cs +++ b/YMouseButtonControl.Core/Mappings/ThemeMapper.cs @@ -1,6 +1,6 @@ using Riok.Mapperly.Abstractions; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.Mappings; diff --git a/YMouseButtonControl.Core/Repositories/ButtonMappingRepository.cs b/YMouseButtonControl.Core/Repositories/ButtonMappingRepository.cs index 154c1fe..cda6f08 100644 --- a/YMouseButtonControl.Core/Repositories/ButtonMappingRepository.cs +++ b/YMouseButtonControl.Core/Repositories/ButtonMappingRepository.cs @@ -1,25 +1,20 @@ using System.Collections.Generic; using System.Data; using System.Linq; -using System.Threading.Tasks; -using Dapper; using YMouseButtonControl.Core.Mappings; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; -using YMouseButtonControl.DataAccess.Queries; +using YMouseButtonControl.Domain.Models; using YMouseButtonControl.Infrastructure.Context; namespace YMouseButtonControl.Core.Repositories; -public class ButtonMappingRepository(YMouseButtonControlDbContext ctx, ButtonMappingQueries queries) +public class ButtonMappingRepository(YMouseButtonControlDbContext ctx) : IRepository { private readonly YMouseButtonControlDbContext _ctx = ctx; - private const string TblName = "ButtonMappings"; public int Add(BaseButtonMappingVm vm) { - using var conn = _ctx.CreateConnection(); var ent = ButtonMappingMapper.Map(vm); ent.ButtonMappingType = ent switch { @@ -29,67 +24,56 @@ public int Add(BaseButtonMappingVm vm) RightClick => ButtonMappingType.RightClick, _ => throw new System.NotImplementedException(), }; - return conn.Execute(queries.Add(), ent); - } - - public async Task AddAsync(BaseButtonMappingVm vm) - { - using var conn = _ctx.CreateConnection(); - return await conn.ExecuteAsync(queries.Add(), vm); + var id = _ctx.ButtonMappings.Add(ent).Entity.Id; + _ctx.SaveChanges(); + return id; } public BaseButtonMappingVm? GetById(int id) { - using var conn = _ctx.CreateConnection(); - return ButtonMappingMapper.Map( - conn.QueryFirstOrDefault(queries.GetById(TblName), id) - ); - } - - public async Task GetByIdAsync(int id) - { - using var conn = _ctx.CreateConnection(); - return ButtonMappingMapper.Map( - await conn.QueryFirstOrDefaultAsync(queries.GetById(TblName), id) - ); + return ButtonMappingMapper.Map(_ctx.ButtonMappings.Find(id)); } public IEnumerable GetAll() { - using var conn = _ctx.CreateConnection(); - return conn.Query(queries.GetAll(TblName)).Select(ButtonMappingMapper.Map); - } - - public async Task> GetAllAsync() - { - using var conn = _ctx.CreateConnection(); - return (await conn.QueryAsync(queries.GetAll(TblName))).Select( - ButtonMappingMapper.Map - ); + return _ctx.ButtonMappings.Select(ButtonMappingMapper.Map); } public int Update(BaseButtonMappingVm vm) { - using var conn = _ctx.CreateConnection(); - return conn.Execute(queries.Update(), vm); - } - - public async Task UpdateAsync(BaseButtonMappingVm vm) - { - using var conn = _ctx.CreateConnection(); - return await conn.ExecuteAsync(queries.Update(), vm); + var ent = _ctx.ButtonMappings.Find(vm.Id); + if (ent is not null) + { + ent.MouseButton = vm.MouseButton; + ent.Keys = vm.Keys; + ent.Selected = vm.Selected; + ent.ProfileId = vm.ProfileId; + ent.BlockOriginalMouseInput = vm.BlockOriginalMouseInput; + ent.AutoRepeatDelay = vm.AutoRepeatDelay; + ent.AutoRepeatRandomizeDelayEnabled = vm.AutoRepeatRandomizeDelayEnabled; + ent.ButtonMappingType = ent.ButtonMappingType = ent switch + { + DisabledMapping => ButtonMappingType.Disabled, + NothingMapping => ButtonMappingType.Nothing, + SimulatedKeystroke => ButtonMappingType.SimulatedKeystroke, + RightClick => ButtonMappingType.RightClick, + _ => throw new System.NotImplementedException(), + }; + _ctx.SaveChanges(); + } + return ent?.Id ?? -1; } public int Delete(BaseButtonMappingVm vm) { - using var conn = _ctx.CreateConnection(); - return conn.Execute(queries.DeleteById(TblName), vm.Id); - } + var ent = _ctx.ButtonMappings.Find(vm.Id); + if (ent is not null) + { + _ctx.ButtonMappings.Remove(ent); + _ctx.SaveChanges(); + } - public Task DeleteAsync(BaseButtonMappingVm vm) - { - using var conn = _ctx.CreateConnection(); - return conn.ExecuteAsync(queries.DeleteById(TblName), vm.Id); + return ent?.Id ?? -1; } public BaseButtonMappingVm? GetByName(string name) diff --git a/YMouseButtonControl.Core/Repositories/IRepository.cs b/YMouseButtonControl.Core/Repositories/IRepository.cs index 4a12ded..8b4a100 100644 --- a/YMouseButtonControl.Core/Repositories/IRepository.cs +++ b/YMouseButtonControl.Core/Repositories/IRepository.cs @@ -6,14 +6,9 @@ namespace YMouseButtonControl.Core.Repositories; public interface IRepository { int Add(TVm vm); - Task AddAsync(TVm vm); TVm? GetByName(string name); TVm? GetById(int id); - Task GetByIdAsync(int id); IEnumerable GetAll(); - Task> GetAllAsync(); int Update(TVm vm); - Task UpdateAsync(TVm vm); int Delete(TVm vm); - Task DeleteAsync(TVm vm); } diff --git a/YMouseButtonControl.Core/Repositories/ProfileRepository.cs b/YMouseButtonControl.Core/Repositories/ProfileRepository.cs index 3726ff1..087637e 100644 --- a/YMouseButtonControl.Core/Repositories/ProfileRepository.cs +++ b/YMouseButtonControl.Core/Repositories/ProfileRepository.cs @@ -1,140 +1,73 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using Dapper; +using Microsoft.EntityFrameworkCore; using YMouseButtonControl.Core.Mappings; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; -using YMouseButtonControl.DataAccess.Queries; +using YMouseButtonControl.Domain.Models; using YMouseButtonControl.Infrastructure.Context; namespace YMouseButtonControl.Core.Repositories; -public class ProfileRepository( - YMouseButtonControlDbContext ctx, - ProfileQueries queries, - ButtonMappingQueries btnMappingQueries -) : IRepository +public class ProfileRepository(YMouseButtonControlDbContext ctx) : IRepository { private readonly YMouseButtonControlDbContext _ctx = ctx; - private const string TblName = "Profiles"; public int Add(ProfileVm vm) { - using var conn = _ctx.CreateConnection(); - return conn.Query(queries.Add(), vm).Single(); - } - - public async Task AddAsync(ProfileVm vm) - { - using var conn = _ctx.CreateConnection(); - return await conn.ExecuteAsync(queries.Add(), vm); - } - - public ProfileVm? GetById(int id) - { - using var conn = _ctx.CreateConnection(); - var profile = conn.QueryFirstOrDefault(queries.GetById(TblName), new { Id = id }); - if (profile == null) + var ent = ProfileMapper.Map(vm); + if (ent is not null) { - return null; + _ctx.Profiles.Add(ent); + _ctx.SaveChanges(); } - profile.ButtonMappings = GetButtonMappingsForProfileId(id); - return ProfileMapper.Map(profile); + return ent?.Id ?? -1; } - public async Task GetByIdAsync(int id) + public ProfileVm? GetById(int id) { - using var conn = _ctx.CreateConnection(); - return ProfileMapper.Map( - await conn.QueryFirstOrDefaultAsync(queries.GetById(TblName), id) - ); + var ent = _ctx.Profiles.Find(id); + return ent is null ? null : ProfileMapper.Map(ent); } public IEnumerable GetAll() { - using var conn = _ctx.CreateConnection(); - return conn.Query(queries.GetAll(TblName)) - .Select(p => - { - p.ButtonMappings = GetButtonMappingsForProfileId(p.Id); - return ProfileMapper.Map(p); - }); - } - - public async Task> GetAllAsync() - { - using var conn = _ctx.CreateConnection(); - return (await conn.QueryAsync(queries.GetAll(TblName))).Select(ProfileMapper.Map); + return _ctx.Profiles.Include(x => x.ButtonMappings).Select(x => ProfileMapper.Map(x)); } public int Update(ProfileVm vm) { - using var conn = _ctx.CreateConnection(); - return conn.Execute(queries.Update(), vm); - } - - public async Task UpdateAsync(ProfileVm vm) - { - using var conn = _ctx.CreateConnection(); - return await conn.ExecuteAsync(queries.Update(), vm); + var ent = _ctx.Profiles.Find(vm.Id); + if (ent is not null) + { + ent.Checked = vm.Checked; + ent.Description = vm.Description; + ent.DisplayPriority = vm.DisplayPriority; + ent.IsDefault = vm.IsDefault; + ent.MatchType = vm.MatchType; + ent.Name = vm.Name; + ent.ParentClass = vm.ParentClass; + ent.Process = vm.Process; + ent.WindowCaption = vm.WindowCaption; + ent.WindowClass = vm.WindowClass; + _ctx.SaveChanges(); + } + return ent?.Id ?? -1; } public int Delete(ProfileVm vm) { - using var conn = _ctx.CreateConnection(); - return conn.Execute(queries.DeleteById(TblName), vm); - } - - public Task DeleteAsync(ProfileVm vm) - { - using var conn = _ctx.CreateConnection(); - return conn.ExecuteAsync(queries.DeleteById(TblName), vm); - } - - private List GetButtonMappingsForProfileId(int id) - { - using var conn = _ctx.CreateConnection(); - using var reader = conn.ExecuteReader(btnMappingQueries.GetByProfileId(), new { Id = id }); - var nothingParser = reader.GetRowParser(); - var disabledParser = reader.GetRowParser(); - var simulatedKeystrokeParser = reader.GetRowParser(); - var rightClickParser = reader.GetRowParser(); - - var buttonMappings = new List(); - - while (reader.Read()) + var ent = _ctx.Profiles.Find(vm.Id); + if (ent is not null) { - var discriminator = (ButtonMappingType) - reader.GetInt32(reader.GetOrdinal("ButtonMappingType")); - switch (discriminator) - { - case ButtonMappingType.Disabled: - buttonMappings.Add(disabledParser(reader)); - break; - case ButtonMappingType.Nothing: - buttonMappings.Add(nothingParser(reader)); - break; - case ButtonMappingType.SimulatedKeystroke: - buttonMappings.Add(simulatedKeystrokeParser(reader)); - break; - case ButtonMappingType.RightClick: - buttonMappings.Add(rightClickParser(reader)); - break; - default: - throw new ArgumentOutOfRangeException(); - } + _ctx.Profiles.Remove(ent); + _ctx.SaveChanges(); } - - return buttonMappings; + return ent?.Id ?? -1; } public ProfileVm? GetByName(string name) { - using var conn = _ctx.CreateConnection(); - return ProfileMapper.Map( - conn.QuerySingleOrDefault(queries.GetByName(TblName), name) - ); + return ProfileMapper.Map(_ctx.Profiles.Find(name)); } } diff --git a/YMouseButtonControl.Core/Repositories/SettingRepository.cs b/YMouseButtonControl.Core/Repositories/SettingRepository.cs index 626de1d..ee9d726 100644 --- a/YMouseButtonControl.Core/Repositories/SettingRepository.cs +++ b/YMouseButtonControl.Core/Repositories/SettingRepository.cs @@ -3,160 +3,75 @@ using System.Data; using System.Linq; using System.Threading.Tasks; -using Dapper; using YMouseButtonControl.Core.Mappings; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; -using YMouseButtonControl.DataAccess.Queries; +using YMouseButtonControl.Domain.Models; using YMouseButtonControl.Infrastructure.Context; -using static Dapper.SqlMapper; namespace YMouseButtonControl.Core.Repositories; -public class SettingRepository(YMouseButtonControlDbContext ctx, SettingQueries queries) +public class SettingRepository(YMouseButtonControlDbContext ctx) : IRepository { private readonly YMouseButtonControlDbContext _ctx = ctx; - private const string TblName = "Settings"; public int Add(BaseSettingVm vm) { - using var conn = _ctx.CreateConnection(); - return conn.Execute(queries.Add(), vm); - } - - public async Task AddAsync(BaseSettingVm vm) - { - using var conn = _ctx.CreateConnection(); - return await conn.ExecuteAsync(queries.Add(), vm); + var ent = SettingMapper.Map(vm); + if (ent is not null) + { + _ctx.Add(ent); + _ctx.SaveChanges(); + } + return ent?.Id ?? -1; } public BaseSettingVm? GetById(int id) { - using var conn = _ctx.CreateConnection(); - return SettingMapper.Map(conn.QueryFirstOrDefault(queries.GetById(TblName), id)); - } - - public async Task GetByIdAsync(int id) - { - using var conn = _ctx.CreateConnection(); - return SettingMapper.Map( - await conn.QueryFirstOrDefaultAsync(queries.GetById(TblName), id) - ); + return SettingMapper.Map(_ctx.Settings.Find(id)); } public IEnumerable GetAll() { - using var conn = _ctx.CreateConnection(); - using var reader = conn.ExecuteReader(queries.GetAll(TblName)); - var settings = new List(); - var settingBoolParser = reader.GetRowParser(); - var settingIntParser = reader.GetRowParser(); - var settingStringParser = reader.GetRowParser(); - while (reader.Read()) - { - var discriminator = (SettingType) - reader.GetInt32(reader.GetOrdinal(nameof(SettingType))); - switch (discriminator) - { - case SettingType.SettingBool: - settings.Add(settingBoolParser(reader)); - break; - case SettingType.SettingString: - settings.Add(settingStringParser(reader)); - break; - case SettingType.SettingInt: - settings.Add(settingIntParser(reader)); - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - return settings.Select(SettingMapper.Map); + return _ctx.Settings.Select(x => SettingMapper.Map(x)); } public BaseSettingVm? GetByName(string name) { - using var conn = _ctx.CreateConnection(); - using var reader = conn.ExecuteReader(queries.GetByName(TblName), new { Name = name }); - var settingBoolParser = reader.GetRowParser(); - var settingIntParser = reader.GetRowParser(); - var settingStringParser = reader.GetRowParser(); - reader.Read(); - var discriminator = (SettingType)reader.GetInt32(reader.GetOrdinal(nameof(SettingType))); - return discriminator switch - { - SettingType.SettingBool => SettingMapper.Map(settingBoolParser(reader)), - SettingType.SettingString => SettingMapper.Map(settingStringParser(reader)), - SettingType.SettingInt => SettingMapper.Map(settingIntParser(reader)), - _ => throw new ArgumentOutOfRangeException(), - }; - } - - public async Task> GetAllAsync() - { - using var conn = _ctx.CreateConnection(); - return (await conn.QueryAsync(queries.GetAll(TblName))).Select(SettingMapper.Map); + return SettingMapper.Map(_ctx.Settings.First(x => x.Name == name)); } public int Update(BaseSettingVm vm) { - using var conn = _ctx.CreateConnection(); - var ent = SettingMapper.Map(vm); - return ent switch + var ent = _ctx.Settings.Find(vm.Id); + if (ent is not null) { - SettingBool t => conn.Execute( - queries.Update(), - new - { - ent.Id, - ent.Name, - t.BoolValue, - StringValue = (string?)null, - IntValue = (int?)null, - } - ), - SettingString t => conn.Execute( - queries.Update(), - new - { - ent.Id, - ent.Name, - BoolValue = (bool?)null, - t.StringValue, - IntValue = (int?)null, - } - ), - SettingInt t => conn.Execute( - queries.Update(), - new - { - ent.Id, - ent.Name, - BoolValue = (bool?)null, - StringValue = (string?)null, - t.IntValue, - } - ), - _ => throw new NotImplementedException(), - }; - } - - public async Task UpdateAsync(BaseSettingVm vm) - { - using var conn = _ctx.CreateConnection(); - return await conn.ExecuteAsync(queries.Update(), vm); + ent.Name = vm.Name; + if (ent is SettingBool sb) + { + sb.BoolValue = ((SettingBoolVm)vm).BoolValue; + } + else if (ent is SettingInt si) + { + si.IntValue = ((SettingIntVm)vm).IntValue; + } + else if (ent is SettingString ss) + { + ss.StringValue = ((SettingStringVm)vm).StringValue; + } + _ctx.SaveChanges(); + } + return ent?.Id ?? -1; } public int Delete(BaseSettingVm vm) { - using var conn = _ctx.CreateConnection(); - return conn.Execute(queries.DeleteById(TblName), vm.Id); - } - - public Task DeleteAsync(BaseSettingVm vm) - { - using var conn = _ctx.CreateConnection(); - return conn.ExecuteAsync(queries.DeleteById(TblName), vm.Id); + var ent = _ctx.Settings.Find(vm.Id); + if (ent is not null) + { + _ctx.Settings.Remove(ent); + _ctx.SaveChanges(); + } + return ent?.Id ?? -1; } } diff --git a/YMouseButtonControl.Core/Repositories/ThemeRepository.cs b/YMouseButtonControl.Core/Repositories/ThemeRepository.cs index a5554ef..a74d482 100644 --- a/YMouseButtonControl.Core/Repositories/ThemeRepository.cs +++ b/YMouseButtonControl.Core/Repositories/ThemeRepository.cs @@ -2,83 +2,63 @@ using System.Collections.Generic; using System.Data; using System.Linq; -using System.Threading.Tasks; -using Dapper; using YMouseButtonControl.Core.Mappings; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; -using YMouseButtonControl.DataAccess.Queries; +using YMouseButtonControl.Domain.Models; using YMouseButtonControl.Infrastructure.Context; namespace YMouseButtonControl.Core.Repositories; -public class ThemeRepository(YMouseButtonControlDbContext ctx, ThemeQueries queries) - : IRepository +public class ThemeRepository(YMouseButtonControlDbContext ctx) : IRepository { - private const string TblName = "Themes"; - public int Add(ThemeVm vm) { - using var conn = ctx.CreateConnection(); - return conn.Query(queries.Add(), ThemeMapper.Map(vm)).Single(); - } - - public Task AddAsync(ThemeVm vm) - { - throw new NotImplementedException(); + var ent = ThemeMapper.Map(vm); + if (ent is not null) + { + ctx.Themes.Add(ent); + ctx.SaveChanges(); + } + return ent?.Id ?? -1; } public int Delete(ThemeVm vm) { - using var conn = ctx.CreateConnection(); - return conn.Execute(queries.DeleteById(TblName), new { ThemeMapper.Map(vm).Id }); - } + var ent = ctx.Themes.Find(vm.Id); + if (ent is not null) + { + ctx.Themes.Remove(ent); + ctx.SaveChanges(); + } - public Task DeleteAsync(ThemeVm vm) - { - throw new NotImplementedException(); + return ent?.Id ?? -1; } public IEnumerable GetAll() { - using var conn = ctx.CreateConnection(); - return conn.Query(queries.GetAll(TblName)).Select(ThemeMapper.Map); - } - - public Task> GetAllAsync() - { - throw new NotImplementedException(); + return ctx.Themes.Select(ThemeMapper.Map); } public ThemeVm? GetById(int id) { - using var conn = ctx.CreateConnection(); - return ThemeMapper.Map( - conn.QueryFirstOrDefault(queries.GetById(TblName), new { Id = id }) - ); - } - - public Task GetByIdAsync(int id) - { - throw new NotImplementedException(); + return ThemeMapper.Map(ctx.Themes.Find(id)); } public ThemeVm? GetByName(string name) { - using var conn = ctx.CreateConnection(); - return ThemeMapper.Map( - conn.QuerySingleOrDefault(queries.GetByName(TblName), new { Name = name }) - ); + return ThemeMapper.Map(ctx.Themes.Find(name)); } public int Update(ThemeVm vm) { - using var conn = ctx.CreateConnection(); - return conn.Execute(queries.Update(), ThemeMapper.Map(vm)); - } - - public Task UpdateAsync(ThemeVm vm) - { - throw new NotImplementedException(); + var ent = ctx.Themes.Find(vm.Id); + if (ent is not null) + { + ent.Background = vm.Background; + ent.Highlight = vm.Highlight; + ent.Name = vm.Name; + ctx.SaveChanges(); + } + return ent?.Id ?? -1; } } diff --git a/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs b/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs index c8e364c..132aaaf 100644 --- a/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs +++ b/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs @@ -4,15 +4,14 @@ using System.IO; using System.Linq; using System.Reactive.Linq; -using Avalonia.Media.TextFormatting.Unicode; using DynamicData; -using DynamicData.Binding; using Newtonsoft.Json; using ReactiveUI; +using YMouseButtonControl.Core.Mappings; using YMouseButtonControl.Core.Repositories; using YMouseButtonControl.Core.Services.Profiles.Exceptions; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.Services.Profiles; @@ -20,6 +19,8 @@ public interface IProfilesService { ProfileVm? CurrentProfile { get; set; } ReadOnlyObservableCollection Profiles { get; } + bool Dirty { get; set; } + IObservable> Connect(); ProfileVm CopyProfile(ProfileVm p); void WriteProfileToFile(ProfileVm p, string path); @@ -30,6 +31,7 @@ public interface IProfilesService void MoveProfileDown(ProfileVm p); void RemoveProfile(ProfileVm profileVm); void AddOrUpdate(ProfileVm profileVm); + void CheckForDirty(); } public class ProfilesService : ReactiveObject, IProfilesService, IDisposable @@ -38,6 +40,7 @@ public class ProfilesService : ReactiveObject, IProfilesService, IDisposable private ProfileVm? _currentProfile; private readonly SourceCache _profiles; private readonly ReadOnlyObservableCollection _profilesObsCol; + private bool _dirty; public ProfilesService(IRepository profileRepository) { @@ -48,10 +51,77 @@ public ProfilesService(IRepository profileRepository) .AutoRefresh() .SortBy(x => x.DisplayPriority) .Bind(out _profilesObsCol) - .Subscribe(); + .Subscribe(IsDirty); _profiles.AddOrUpdate(profileRepository.GetAll().ToList()); } + private void IsDirty(IChangeSet set) + { + foreach (var cs in set.Where(x => x.Reason != ChangeReason.Refresh)) + { + if (cs.Reason == ChangeReason.Add) + { + if (_profileRepository.GetById(cs.Current.Id) is null) + { + Dirty = true; + return; + } + } + else if (cs.Reason == ChangeReason.Update) + { + var ent = + _profileRepository.GetById(cs.Current.Id) + ?? throw new Exception("Null entity on update reason"); + var mapped = ProfileMapper.Map(cs.Current); + if (!ent.Equals(mapped)) + { + Dirty = true; + return; + } + } + else if (cs.Reason == ChangeReason.Remove) + { + if (_profileRepository.GetById(cs.Current.Id) is null) + { + Dirty = false; + } + else + { + Dirty = true; + return; + } + } + } + } + + public void CheckForDirty() + { + var dbProfiles = _profileRepository.GetAll(); + foreach (var dbProf in dbProfiles) + { + if (_profilesObsCol.All(x => !x.Equals(dbProf))) + { + Dirty = true; + return; + } + } + foreach (var prof in _profilesObsCol) + { + if (dbProfiles.All(x => !x.Equals(prof))) + { + Dirty = true; + return; + } + } + Dirty = false; + } + + public bool Dirty + { + get => _dirty; + set => this.RaiseAndSetIfChanged(ref _dirty, value); + } + /// /// Read only collection of profiles /// diff --git a/YMouseButtonControl.Core/Services/Settings/SettingsService.cs b/YMouseButtonControl.Core/Services/Settings/SettingsService.cs index cadb738..8f0c705 100644 --- a/YMouseButtonControl.Core/Services/Settings/SettingsService.cs +++ b/YMouseButtonControl.Core/Services/Settings/SettingsService.cs @@ -1,7 +1,7 @@ using ReactiveUI; using YMouseButtonControl.Core.Repositories; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.Services.Settings; diff --git a/YMouseButtonControl.Core/Services/Theme/ThemeService.cs b/YMouseButtonControl.Core/Services/Theme/ThemeService.cs index 60ab85b..270fd7b 100644 --- a/YMouseButtonControl.Core/Services/Theme/ThemeService.cs +++ b/YMouseButtonControl.Core/Services/Theme/ThemeService.cs @@ -21,7 +21,7 @@ public interface IThemeService public class ThemeService : ReactiveObject, IThemeService { - private readonly IRepository _themeRepo; + private readonly IRepository _themeRepo; private readonly SettingIntVm _themeSetting; private readonly ThemeVm _themeVm; private IBrush _background; @@ -29,7 +29,7 @@ public class ThemeService : ReactiveObject, IThemeService private readonly ThemeVariant _themeVariant; public ThemeService( - IRepository themeRepo, + IRepository themeRepo, ISettingsService settingsService ) { diff --git a/YMouseButtonControl.Core/ViewModels/LayerViewModel/LayerViewModel.cs b/YMouseButtonControl.Core/ViewModels/LayerViewModel/LayerViewModel.cs index e8ef2de..6a598ac 100644 --- a/YMouseButtonControl.Core/ViewModels/LayerViewModel/LayerViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/LayerViewModel/LayerViewModel.cs @@ -1,7 +1,7 @@ using System; using ReactiveUI; using YMouseButtonControl.Core.Services.Profiles; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.ViewModels.LayerViewModel; diff --git a/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs b/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs index 933d26b..a88a0be 100644 --- a/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs @@ -9,12 +9,11 @@ using DynamicData; using ReactiveUI; using YMouseButtonControl.Core.Services.KeyboardAndMouse.Enums; -using YMouseButtonControl.Core.Services.KeyboardAndMouse.EventArgs; using YMouseButtonControl.Core.Services.KeyboardAndMouse.Implementations; using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.ViewModels.LayerViewModel; diff --git a/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModelFactory.cs b/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModelFactory.cs index 746aeac..1dfe687 100644 --- a/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModelFactory.cs +++ b/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModelFactory.cs @@ -1,7 +1,7 @@ using YMouseButtonControl.Core.Services.KeyboardAndMouse.Implementations; using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.Services.Theme; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.ViewModels.LayerViewModel; diff --git a/YMouseButtonControl.Core/ViewModels/LayerViewModel/ShowSimulatedKeystrokesDialogService.cs b/YMouseButtonControl.Core/ViewModels/LayerViewModel/ShowSimulatedKeystrokesDialogService.cs index 37e5fa9..28c3850 100644 --- a/YMouseButtonControl.Core/ViewModels/LayerViewModel/ShowSimulatedKeystrokesDialogService.cs +++ b/YMouseButtonControl.Core/ViewModels/LayerViewModel/ShowSimulatedKeystrokesDialogService.cs @@ -4,7 +4,7 @@ using YMouseButtonControl.Core.Services.KeyboardAndMouse.Implementations; using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.ViewModels.LayerViewModel; diff --git a/YMouseButtonControl.Core/ViewModels/LayerViewModel/SimulatedKeystrokesDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/LayerViewModel/SimulatedKeystrokesDialogViewModel.cs index 014b494..958cf3a 100644 --- a/YMouseButtonControl.Core/ViewModels/LayerViewModel/SimulatedKeystrokesDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/LayerViewModel/SimulatedKeystrokesDialogViewModel.cs @@ -8,7 +8,7 @@ using YMouseButtonControl.Core.Services.KeyboardAndMouse.Implementations; using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.ViewModels.LayerViewModel; diff --git a/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs b/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs index 11a6a80..2ed9939 100644 --- a/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs +++ b/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs @@ -1,8 +1,9 @@ -using System.Transactions; +using System.Linq; +using System.Transactions; using YMouseButtonControl.Core.Repositories; using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.ViewModels.MainWindow.Features.Apply; @@ -13,29 +14,30 @@ public interface IApply public class Apply( IRepository profileRepository, - IRepository buttonMappingRepository, + //IRepository buttonMappingRepository, IProfilesService profilesService ) : IApply { public void ApplyProfiles() { - using var trn = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); - foreach (var dbVm in profileRepository.GetAll()) - { - profileRepository.Delete(dbVm); - } - foreach (var vm in profilesService.Profiles) - { - var profileId = profileRepository.Add(vm); - foreach (var bm in vm.ButtonMappings) - { - if (bm.ProfileId <= 0) - { - bm.ProfileId = profileId; - } - buttonMappingRepository.Add(bm); - } - } - trn.Complete(); + var dbProfiles = profileRepository.GetAll(); + + // delete profiles + dbProfiles + .Where(x => !profilesService.Profiles.Any(y => y.Id == x.Id)) + .ToList() + .ForEach(x => profileRepository.Delete(x)); + + // update profiles + profilesService + .Profiles.Where(x => dbProfiles.Any(y => y.Id == x.Id)) + .ToList() + .ForEach(x => profileRepository.Update(x)); + + // add profiles + profilesService + .Profiles.Where(x => !dbProfiles.Any(y => y.Id == x.Id)) + .ToList() + .ForEach(x => profileRepository.Add(x)); } } diff --git a/YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs index 8ab7720..cc13947 100644 --- a/YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs @@ -104,10 +104,8 @@ IThemeService themeService } } - using var trn = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); settingsService.UpdateSetting(StartMinimized); settingsService.UpdateSetting(ThemeSetting); - trn.Complete(); }, canSave ); diff --git a/YMouseButtonControl.Core/ViewModels/MainWindow/MainWindowViewModel.cs b/YMouseButtonControl.Core/ViewModels/MainWindow/MainWindowViewModel.cs index 3ac7004..a22ccc1 100644 --- a/YMouseButtonControl.Core/ViewModels/MainWindow/MainWindowViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/MainWindow/MainWindowViewModel.cs @@ -1,25 +1,19 @@ using System; using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Linq; using System.Reactive; using System.Reactive.Linq; using System.Threading.Tasks; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using DynamicData; -using DynamicData.Binding; using ReactiveUI; -using YMouseButtonControl.Core.Repositories; using YMouseButtonControl.Core.Services.Profiles; -using YMouseButtonControl.Core.Services.Settings; using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.LayerViewModel; using YMouseButtonControl.Core.ViewModels.MainWindow.Features.Apply; using YMouseButtonControl.Core.ViewModels.Models; using YMouseButtonControl.Core.ViewModels.ProfilesInformationViewModel; using YMouseButtonControl.Core.ViewModels.ProfilesList; -using YMouseButtonControl.DataAccess.Models; namespace YMouseButtonControl.Core.ViewModels.MainWindow; @@ -40,14 +34,11 @@ public class MainWindowViewModel : ViewModelBase, IMainWindowViewModel { #region Fields - private readonly IRepository _profileRepository; private readonly IProfilesService _ps; private readonly IThemeService _themeService; private readonly IProfilesListViewModel _profilesListViewModel; private readonly IGlobalSettingsDialogViewModel _globalSettingsDialogViewModel; - private readonly ObservableAsPropertyHelper? _isExecutingSave; private readonly ReadOnlyObservableCollection _profileVms; - private bool _canSave; #endregion @@ -60,11 +51,9 @@ public MainWindowViewModel( IProfilesListViewModel profilesListViewModel, IProfilesInformationViewModel profilesInformationViewModel, IGlobalSettingsDialogViewModel globalSettingsDialogViewModel, - IApply apply, - IRepository profileRepository + IApply apply ) { - _profileRepository = profileRepository; _profilesListViewModel = profilesListViewModel; _globalSettingsDialogViewModel = globalSettingsDialogViewModel; _ps = ps; @@ -88,50 +77,16 @@ is IClassicDesktopStyleApplicationLifetime lifetime .RefCount() .Bind(out _profileVms) .DisposeMany() - .Subscribe(CanSaveHelper); - var isExecutingObservable = this.WhenAnyValue(x => x.IsExecutingSave) - .Subscribe(_ => CanSave = false); - var canSaveCmd = this.WhenAnyValue(x => x.CanSave); - ApplyCommand = ReactiveCommand.Create(apply.ApplyProfiles, canSaveCmd); - _isExecutingSave = ApplyCommand.IsExecuting.ToProperty(this, x => x.IsExecutingSave); - } - - private void CanSaveHelper(IChangeSet changeSet) - { - foreach (var cs in changeSet) - { - var entity = _profileRepository.GetById(cs.Current.Id); - switch (cs.Reason) - { - case ChangeReason.Add: - CanSave = entity is null; - break; - case ChangeReason.Update: - CanSave = !entity?.Equals(cs.Current) ?? true; - break; - case ChangeReason.Remove: - CanSave = entity is not null; - break; - case ChangeReason.Refresh: - CanSave = !entity?.Equals(cs.Current) ?? true; - break; - case ChangeReason.Moved: - break; - default: - throw new ArgumentOutOfRangeException(); - } - } + .Subscribe(); + var canExecuteApply = this.WhenAnyValue(x => x._ps.Dirty); + ApplyCommand = ReactiveCommand.Create(apply.ApplyProfiles, canExecuteApply); + var isExecutingObservable = this.WhenAnyObservable(x => x.ApplyCommand.IsExecuting); + canExecuteApply = canExecuteApply.Merge(isExecutingObservable); + isExecutingObservable.Skip(1).Where(x => !x).Subscribe(x => _ps.Dirty = false); } public ProfileVm? CurrentProfile => _ps.CurrentProfile; - public bool CanSave - { - get => _canSave; - set => this.RaiseAndSetIfChanged(ref _canSave, value); - } - public bool IsExecutingSave => _isExecutingSave?.Value ?? false; - #endregion #region Properties diff --git a/YMouseButtonControl.Core/ViewModels/Models/BaseButtonMappingVm.cs b/YMouseButtonControl.Core/ViewModels/Models/BaseButtonMappingVm.cs index f631ebe..2cad296 100644 --- a/YMouseButtonControl.Core/ViewModels/Models/BaseButtonMappingVm.cs +++ b/YMouseButtonControl.Core/ViewModels/Models/BaseButtonMappingVm.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; using ReactiveUI; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.ViewModels.Models; diff --git a/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs b/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs index 60571de..56f491f 100644 --- a/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs +++ b/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs @@ -4,7 +4,7 @@ using DynamicData; using Newtonsoft.Json; using ReactiveUI; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.ViewModels.Models; diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs index 61c30b6..8d10dbd 100644 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs @@ -10,7 +10,7 @@ using YMouseButtonControl.Core.Services.Processes; using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.ViewModels.ProfilesList; diff --git a/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj b/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj index 8587cba..ba05255 100644 --- a/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj +++ b/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj @@ -20,9 +20,10 @@ - + + diff --git a/YMouseButtonControl.DataAccess/Context/YMouseButtonControlDbContext.cs b/YMouseButtonControl.DataAccess/Context/YMouseButtonControlDbContext.cs index 395fd5f..5397991 100644 --- a/YMouseButtonControl.DataAccess/Context/YMouseButtonControlDbContext.cs +++ b/YMouseButtonControl.DataAccess/Context/YMouseButtonControlDbContext.cs @@ -1,5 +1,4 @@ using System.Data; -using Dapper; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -7,8 +6,7 @@ namespace YMouseButtonControl.Infrastructure.Context; -public class YMouseButtonControlDbContext(DbContextOptions opts) - : DbContext(opts) +public class YMouseButtonControlDbContext : DbContext { public DbSet Profiles { get; set; } = null!; public DbSet Settings { get; set; } = null!; @@ -22,6 +20,12 @@ public class YMouseButtonControlDbContext(DbContextOptions SimulatedKeystrokeMappings { get; set; } = null!; public DbSet RightClickMappings { get; set; } = null!; + public YMouseButtonControlDbContext(DbContextOptions opts) + : base(opts) + { + Database.EnsureCreated(); + } + protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder @@ -32,7 +36,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) Id = 1, IsDefault = true, Checked = true, - DisplayPriority = 1, + DisplayPriority = 0, Name = "Default", Description = "Default description", WindowCaption = "N/A", @@ -104,6 +108,32 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) ] ); + modelBuilder + .Entity() + .HasData( + new Theme + { + Id = 1, + Name = "Default", + Background = "SystemAltHighColor", + Highlight = "SystemAccentColor", + }, + new Theme + { + Id = 2, + Name = "Light", + Background = "White", + Highlight = "Yellow", + }, + new Theme + { + Id = 3, + Name = "Dark", + Background = "Black", + Highlight = "#3700b3", + } + ); + modelBuilder .Entity() .HasData( diff --git a/YMouseButtonControl.DataAccess/Migrations/20241207140626_Initial.Designer.cs b/YMouseButtonControl.DataAccess/Migrations/20241207140626_Initial.Designer.cs new file mode 100644 index 0000000..c437681 --- /dev/null +++ b/YMouseButtonControl.DataAccess/Migrations/20241207140626_Initial.Designer.cs @@ -0,0 +1,349 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using YMouseButtonControl.Infrastructure.Context; + +#nullable disable + +namespace YMouseButtonControl.Infrastructure.Migrations +{ + [DbContext(typeof(YMouseButtonControlDbContext))] + [Migration("20241207140626_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.11"); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.ButtonMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoRepeatDelay") + .HasColumnType("INTEGER"); + + b.Property("AutoRepeatRandomizeDelayEnabled") + .HasColumnType("INTEGER"); + + b.Property("BlockOriginalMouseInput") + .HasColumnType("INTEGER"); + + b.Property("ButtonMappingType") + .HasColumnType("INTEGER"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("TEXT"); + + b.Property("Keys") + .HasColumnType("TEXT"); + + b.Property("MouseButton") + .HasColumnType("INTEGER"); + + b.Property("ProfileId") + .HasColumnType("INTEGER"); + + b.Property("Selected") + .HasColumnType("INTEGER"); + + b.Property("SimulatedKeystrokeType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.ToTable("ButtonMappings"); + + b.HasDiscriminator().HasValue("ButtonMapping"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Checked") + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DisplayPriority") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("MatchType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ParentClass") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Process") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WindowCaption") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WindowClass") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Profiles"); + + b.HasData( + new + { + Id = 1, + Checked = true, + Description = "Default description", + DisplayPriority = 1, + IsDefault = true, + MatchType = "N/A", + Name = "Default", + ParentClass = "N/A", + Process = "*", + WindowCaption = "N/A", + WindowClass = "N/A" + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(13) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Settings"); + + b.HasDiscriminator().HasValue("Setting"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Theme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Highlight") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Themes"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.DisabledMapping", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("DisabledMapping"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.NothingMapping", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("NothingMapping"); + + b.HasData( + new + { + Id = 1, + ButtonMappingType = 0, + MouseButton = 0, + ProfileId = 1, + Selected = false + }, + new + { + Id = 2, + ButtonMappingType = 0, + MouseButton = 1, + ProfileId = 1, + Selected = false + }, + new + { + Id = 3, + ButtonMappingType = 0, + MouseButton = 2, + ProfileId = 1, + Selected = false + }, + new + { + Id = 4, + ButtonMappingType = 0, + MouseButton = 3, + ProfileId = 1, + Selected = false + }, + new + { + Id = 5, + ButtonMappingType = 0, + MouseButton = 4, + ProfileId = 1, + Selected = false + }, + new + { + Id = 6, + ButtonMappingType = 0, + MouseButton = 5, + ProfileId = 1, + Selected = false + }, + new + { + Id = 7, + ButtonMappingType = 0, + MouseButton = 6, + ProfileId = 1, + Selected = false + }, + new + { + Id = 8, + ButtonMappingType = 0, + MouseButton = 7, + ProfileId = 1, + Selected = false + }, + new + { + Id = 9, + ButtonMappingType = 0, + MouseButton = 8, + ProfileId = 1, + Selected = false + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.RightClick", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("RightClick"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SimulatedKeystroke", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("SimulatedKeystroke"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingBool", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("BoolValue") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("SettingBool"); + + b.HasData( + new + { + Id = 1, + Name = "StartMinimized", + BoolValue = false + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingInt", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("IntValue") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("SettingInt"); + + b.HasData( + new + { + Id = 2, + Name = "Theme", + IntValue = 3 + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingString", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("StringValue") + .HasColumnType("TEXT"); + + b.HasDiscriminator().HasValue("SettingString"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.ButtonMapping", b => + { + b.HasOne("YMouseButtonControl.Domain.Models.Profile", "Profile") + .WithMany("ButtonMappings") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Profile", b => + { + b.Navigation("ButtonMappings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/YMouseButtonControl.DataAccess/Migrations/20241207140626_Initial.cs b/YMouseButtonControl.DataAccess/Migrations/20241207140626_Initial.cs new file mode 100644 index 0000000..6833617 --- /dev/null +++ b/YMouseButtonControl.DataAccess/Migrations/20241207140626_Initial.cs @@ -0,0 +1,150 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace YMouseButtonControl.Infrastructure.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Profiles", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + IsDefault = table.Column(type: "INTEGER", nullable: false), + Checked = table.Column(type: "INTEGER", nullable: false), + DisplayPriority = table.Column(type: "INTEGER", nullable: false), + Name = table.Column(type: "TEXT", nullable: false), + Description = table.Column(type: "TEXT", nullable: false), + WindowCaption = table.Column(type: "TEXT", nullable: false), + Process = table.Column(type: "TEXT", nullable: false), + WindowClass = table.Column(type: "TEXT", nullable: false), + ParentClass = table.Column(type: "TEXT", nullable: false), + MatchType = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Profiles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Settings", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Name = table.Column(type: "TEXT", nullable: false), + Discriminator = table.Column(type: "TEXT", maxLength: 13, nullable: false), + BoolValue = table.Column(type: "INTEGER", nullable: true), + IntValue = table.Column(type: "INTEGER", nullable: true), + StringValue = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Settings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Themes", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Name = table.Column(type: "TEXT", nullable: false), + Background = table.Column(type: "TEXT", nullable: false), + Highlight = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Themes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ButtonMappings", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Keys = table.Column(type: "TEXT", nullable: true), + MouseButton = table.Column(type: "INTEGER", nullable: false), + ProfileId = table.Column(type: "INTEGER", nullable: false), + SimulatedKeystrokeType = table.Column(type: "INTEGER", nullable: true), + AutoRepeatDelay = table.Column(type: "INTEGER", nullable: true), + AutoRepeatRandomizeDelayEnabled = table.Column(type: "INTEGER", nullable: true), + Selected = table.Column(type: "INTEGER", nullable: false), + BlockOriginalMouseInput = table.Column(type: "INTEGER", nullable: true), + ButtonMappingType = table.Column(type: "INTEGER", nullable: false), + Discriminator = table.Column(type: "TEXT", maxLength: 21, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ButtonMappings", x => x.Id); + table.ForeignKey( + name: "FK_ButtonMappings_Profiles_ProfileId", + column: x => x.ProfileId, + principalTable: "Profiles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.InsertData( + table: "Profiles", + columns: new[] { "Id", "Checked", "Description", "DisplayPriority", "IsDefault", "MatchType", "Name", "ParentClass", "Process", "WindowCaption", "WindowClass" }, + values: new object[] { 1, true, "Default description", 1, true, "N/A", "Default", "N/A", "*", "N/A", "N/A" }); + + migrationBuilder.InsertData( + table: "Settings", + columns: new[] { "Id", "BoolValue", "Discriminator", "Name" }, + values: new object[] { 1, false, "SettingBool", "StartMinimized" }); + + migrationBuilder.InsertData( + table: "Settings", + columns: new[] { "Id", "Discriminator", "IntValue", "Name" }, + values: new object[] { 2, "SettingInt", 3, "Theme" }); + + migrationBuilder.InsertData( + table: "ButtonMappings", + columns: new[] { "Id", "AutoRepeatDelay", "AutoRepeatRandomizeDelayEnabled", "BlockOriginalMouseInput", "ButtonMappingType", "Discriminator", "Keys", "MouseButton", "ProfileId", "Selected", "SimulatedKeystrokeType" }, + values: new object[,] + { + { 1, null, null, null, 0, "NothingMapping", null, 0, 1, false, null }, + { 2, null, null, null, 0, "NothingMapping", null, 1, 1, false, null }, + { 3, null, null, null, 0, "NothingMapping", null, 2, 1, false, null }, + { 4, null, null, null, 0, "NothingMapping", null, 3, 1, false, null }, + { 5, null, null, null, 0, "NothingMapping", null, 4, 1, false, null }, + { 6, null, null, null, 0, "NothingMapping", null, 5, 1, false, null }, + { 7, null, null, null, 0, "NothingMapping", null, 6, 1, false, null }, + { 8, null, null, null, 0, "NothingMapping", null, 7, 1, false, null }, + { 9, null, null, null, 0, "NothingMapping", null, 8, 1, false, null } + }); + + migrationBuilder.CreateIndex( + name: "IX_ButtonMappings_ProfileId", + table: "ButtonMappings", + column: "ProfileId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ButtonMappings"); + + migrationBuilder.DropTable( + name: "Settings"); + + migrationBuilder.DropTable( + name: "Themes"); + + migrationBuilder.DropTable( + name: "Profiles"); + } + } +} diff --git a/YMouseButtonControl.DataAccess/Migrations/20241207141716_AddThemes.Designer.cs b/YMouseButtonControl.DataAccess/Migrations/20241207141716_AddThemes.Designer.cs new file mode 100644 index 0000000..b965823 --- /dev/null +++ b/YMouseButtonControl.DataAccess/Migrations/20241207141716_AddThemes.Designer.cs @@ -0,0 +1,372 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using YMouseButtonControl.Infrastructure.Context; + +#nullable disable + +namespace YMouseButtonControl.Infrastructure.Migrations +{ + [DbContext(typeof(YMouseButtonControlDbContext))] + [Migration("20241207141716_AddThemes")] + partial class AddThemes + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.11"); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.ButtonMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoRepeatDelay") + .HasColumnType("INTEGER"); + + b.Property("AutoRepeatRandomizeDelayEnabled") + .HasColumnType("INTEGER"); + + b.Property("BlockOriginalMouseInput") + .HasColumnType("INTEGER"); + + b.Property("ButtonMappingType") + .HasColumnType("INTEGER"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("TEXT"); + + b.Property("Keys") + .HasColumnType("TEXT"); + + b.Property("MouseButton") + .HasColumnType("INTEGER"); + + b.Property("ProfileId") + .HasColumnType("INTEGER"); + + b.Property("Selected") + .HasColumnType("INTEGER"); + + b.Property("SimulatedKeystrokeType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.ToTable("ButtonMappings"); + + b.HasDiscriminator().HasValue("ButtonMapping"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Checked") + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DisplayPriority") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("MatchType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ParentClass") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Process") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WindowCaption") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WindowClass") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Profiles"); + + b.HasData( + new + { + Id = 1, + Checked = true, + Description = "Default description", + DisplayPriority = 1, + IsDefault = true, + MatchType = "N/A", + Name = "Default", + ParentClass = "N/A", + Process = "*", + WindowCaption = "N/A", + WindowClass = "N/A" + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(13) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Settings"); + + b.HasDiscriminator().HasValue("Setting"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Theme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Highlight") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Themes"); + + b.HasData( + new + { + Id = 1, + Background = "SystemAltHighColor", + Highlight = "SystemAccentColor", + Name = "Default" + }, + new + { + Id = 2, + Background = "White", + Highlight = "Yellow", + Name = "Light" + }, + new + { + Id = 3, + Background = "Black", + Highlight = "#3700b3", + Name = "Dark" + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.DisabledMapping", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("DisabledMapping"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.NothingMapping", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("NothingMapping"); + + b.HasData( + new + { + Id = 1, + ButtonMappingType = 0, + MouseButton = 0, + ProfileId = 1, + Selected = false + }, + new + { + Id = 2, + ButtonMappingType = 0, + MouseButton = 1, + ProfileId = 1, + Selected = false + }, + new + { + Id = 3, + ButtonMappingType = 0, + MouseButton = 2, + ProfileId = 1, + Selected = false + }, + new + { + Id = 4, + ButtonMappingType = 0, + MouseButton = 3, + ProfileId = 1, + Selected = false + }, + new + { + Id = 5, + ButtonMappingType = 0, + MouseButton = 4, + ProfileId = 1, + Selected = false + }, + new + { + Id = 6, + ButtonMappingType = 0, + MouseButton = 5, + ProfileId = 1, + Selected = false + }, + new + { + Id = 7, + ButtonMappingType = 0, + MouseButton = 6, + ProfileId = 1, + Selected = false + }, + new + { + Id = 8, + ButtonMappingType = 0, + MouseButton = 7, + ProfileId = 1, + Selected = false + }, + new + { + Id = 9, + ButtonMappingType = 0, + MouseButton = 8, + ProfileId = 1, + Selected = false + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.RightClick", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("RightClick"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SimulatedKeystroke", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("SimulatedKeystroke"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingBool", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("BoolValue") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("SettingBool"); + + b.HasData( + new + { + Id = 1, + Name = "StartMinimized", + BoolValue = false + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingInt", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("IntValue") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("SettingInt"); + + b.HasData( + new + { + Id = 2, + Name = "Theme", + IntValue = 3 + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingString", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("StringValue") + .HasColumnType("TEXT"); + + b.HasDiscriminator().HasValue("SettingString"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.ButtonMapping", b => + { + b.HasOne("YMouseButtonControl.Domain.Models.Profile", "Profile") + .WithMany("ButtonMappings") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Profile", b => + { + b.Navigation("ButtonMappings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/YMouseButtonControl.DataAccess/Migrations/20241207141716_AddThemes.cs b/YMouseButtonControl.DataAccess/Migrations/20241207141716_AddThemes.cs new file mode 100644 index 0000000..81f279a --- /dev/null +++ b/YMouseButtonControl.DataAccess/Migrations/20241207141716_AddThemes.cs @@ -0,0 +1,45 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace YMouseButtonControl.Infrastructure.Migrations +{ + /// + public partial class AddThemes : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertData( + table: "Themes", + columns: new[] { "Id", "Background", "Highlight", "Name" }, + values: new object[,] + { + { 1, "SystemAltHighColor", "SystemAccentColor", "Default" }, + { 2, "White", "Yellow", "Light" }, + { 3, "Black", "#3700b3", "Dark" } + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "Themes", + keyColumn: "Id", + keyValue: 1); + + migrationBuilder.DeleteData( + table: "Themes", + keyColumn: "Id", + keyValue: 2); + + migrationBuilder.DeleteData( + table: "Themes", + keyColumn: "Id", + keyValue: 3); + } + } +} diff --git a/YMouseButtonControl.DataAccess/Migrations/20241207142135_CorrectDefaultProfileDisplayPriority.Designer.cs b/YMouseButtonControl.DataAccess/Migrations/20241207142135_CorrectDefaultProfileDisplayPriority.Designer.cs new file mode 100644 index 0000000..b3fbfff --- /dev/null +++ b/YMouseButtonControl.DataAccess/Migrations/20241207142135_CorrectDefaultProfileDisplayPriority.Designer.cs @@ -0,0 +1,372 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using YMouseButtonControl.Infrastructure.Context; + +#nullable disable + +namespace YMouseButtonControl.Infrastructure.Migrations +{ + [DbContext(typeof(YMouseButtonControlDbContext))] + [Migration("20241207142135_CorrectDefaultProfileDisplayPriority")] + partial class CorrectDefaultProfileDisplayPriority + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.11"); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.ButtonMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoRepeatDelay") + .HasColumnType("INTEGER"); + + b.Property("AutoRepeatRandomizeDelayEnabled") + .HasColumnType("INTEGER"); + + b.Property("BlockOriginalMouseInput") + .HasColumnType("INTEGER"); + + b.Property("ButtonMappingType") + .HasColumnType("INTEGER"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("TEXT"); + + b.Property("Keys") + .HasColumnType("TEXT"); + + b.Property("MouseButton") + .HasColumnType("INTEGER"); + + b.Property("ProfileId") + .HasColumnType("INTEGER"); + + b.Property("Selected") + .HasColumnType("INTEGER"); + + b.Property("SimulatedKeystrokeType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.ToTable("ButtonMappings"); + + b.HasDiscriminator().HasValue("ButtonMapping"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Checked") + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DisplayPriority") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("MatchType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ParentClass") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Process") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WindowCaption") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WindowClass") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Profiles"); + + b.HasData( + new + { + Id = 1, + Checked = true, + Description = "Default description", + DisplayPriority = 0, + IsDefault = true, + MatchType = "N/A", + Name = "Default", + ParentClass = "N/A", + Process = "*", + WindowCaption = "N/A", + WindowClass = "N/A" + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(13) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Settings"); + + b.HasDiscriminator().HasValue("Setting"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Theme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Highlight") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Themes"); + + b.HasData( + new + { + Id = 1, + Background = "SystemAltHighColor", + Highlight = "SystemAccentColor", + Name = "Default" + }, + new + { + Id = 2, + Background = "White", + Highlight = "Yellow", + Name = "Light" + }, + new + { + Id = 3, + Background = "Black", + Highlight = "#3700b3", + Name = "Dark" + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.DisabledMapping", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("DisabledMapping"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.NothingMapping", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("NothingMapping"); + + b.HasData( + new + { + Id = 1, + ButtonMappingType = 0, + MouseButton = 0, + ProfileId = 1, + Selected = false + }, + new + { + Id = 2, + ButtonMappingType = 0, + MouseButton = 1, + ProfileId = 1, + Selected = false + }, + new + { + Id = 3, + ButtonMappingType = 0, + MouseButton = 2, + ProfileId = 1, + Selected = false + }, + new + { + Id = 4, + ButtonMappingType = 0, + MouseButton = 3, + ProfileId = 1, + Selected = false + }, + new + { + Id = 5, + ButtonMappingType = 0, + MouseButton = 4, + ProfileId = 1, + Selected = false + }, + new + { + Id = 6, + ButtonMappingType = 0, + MouseButton = 5, + ProfileId = 1, + Selected = false + }, + new + { + Id = 7, + ButtonMappingType = 0, + MouseButton = 6, + ProfileId = 1, + Selected = false + }, + new + { + Id = 8, + ButtonMappingType = 0, + MouseButton = 7, + ProfileId = 1, + Selected = false + }, + new + { + Id = 9, + ButtonMappingType = 0, + MouseButton = 8, + ProfileId = 1, + Selected = false + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.RightClick", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("RightClick"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SimulatedKeystroke", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("SimulatedKeystroke"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingBool", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("BoolValue") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("SettingBool"); + + b.HasData( + new + { + Id = 1, + Name = "StartMinimized", + BoolValue = false + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingInt", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("IntValue") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("SettingInt"); + + b.HasData( + new + { + Id = 2, + Name = "Theme", + IntValue = 3 + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingString", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("StringValue") + .HasColumnType("TEXT"); + + b.HasDiscriminator().HasValue("SettingString"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.ButtonMapping", b => + { + b.HasOne("YMouseButtonControl.Domain.Models.Profile", "Profile") + .WithMany("ButtonMappings") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Profile", b => + { + b.Navigation("ButtonMappings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/YMouseButtonControl.DataAccess/Migrations/20241207142135_CorrectDefaultProfileDisplayPriority.cs b/YMouseButtonControl.DataAccess/Migrations/20241207142135_CorrectDefaultProfileDisplayPriority.cs new file mode 100644 index 0000000..7f1d4d2 --- /dev/null +++ b/YMouseButtonControl.DataAccess/Migrations/20241207142135_CorrectDefaultProfileDisplayPriority.cs @@ -0,0 +1,32 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace YMouseButtonControl.Infrastructure.Migrations +{ + /// + public partial class CorrectDefaultProfileDisplayPriority : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "Profiles", + keyColumn: "Id", + keyValue: 1, + column: "DisplayPriority", + value: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "Profiles", + keyColumn: "Id", + keyValue: 1, + column: "DisplayPriority", + value: 1); + } + } +} diff --git a/YMouseButtonControl.DataAccess/Migrations/YMouseButtonControlDbContextModelSnapshot.cs b/YMouseButtonControl.DataAccess/Migrations/YMouseButtonControlDbContextModelSnapshot.cs new file mode 100644 index 0000000..e0ff4ed --- /dev/null +++ b/YMouseButtonControl.DataAccess/Migrations/YMouseButtonControlDbContextModelSnapshot.cs @@ -0,0 +1,369 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using YMouseButtonControl.Infrastructure.Context; + +#nullable disable + +namespace YMouseButtonControl.Infrastructure.Migrations +{ + [DbContext(typeof(YMouseButtonControlDbContext))] + partial class YMouseButtonControlDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.11"); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.ButtonMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoRepeatDelay") + .HasColumnType("INTEGER"); + + b.Property("AutoRepeatRandomizeDelayEnabled") + .HasColumnType("INTEGER"); + + b.Property("BlockOriginalMouseInput") + .HasColumnType("INTEGER"); + + b.Property("ButtonMappingType") + .HasColumnType("INTEGER"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("TEXT"); + + b.Property("Keys") + .HasColumnType("TEXT"); + + b.Property("MouseButton") + .HasColumnType("INTEGER"); + + b.Property("ProfileId") + .HasColumnType("INTEGER"); + + b.Property("Selected") + .HasColumnType("INTEGER"); + + b.Property("SimulatedKeystrokeType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.ToTable("ButtonMappings"); + + b.HasDiscriminator().HasValue("ButtonMapping"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Checked") + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DisplayPriority") + .HasColumnType("INTEGER"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("MatchType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ParentClass") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Process") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WindowCaption") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WindowClass") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Profiles"); + + b.HasData( + new + { + Id = 1, + Checked = true, + Description = "Default description", + DisplayPriority = 0, + IsDefault = true, + MatchType = "N/A", + Name = "Default", + ParentClass = "N/A", + Process = "*", + WindowCaption = "N/A", + WindowClass = "N/A" + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(13) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Settings"); + + b.HasDiscriminator().HasValue("Setting"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Theme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Highlight") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Themes"); + + b.HasData( + new + { + Id = 1, + Background = "SystemAltHighColor", + Highlight = "SystemAccentColor", + Name = "Default" + }, + new + { + Id = 2, + Background = "White", + Highlight = "Yellow", + Name = "Light" + }, + new + { + Id = 3, + Background = "Black", + Highlight = "#3700b3", + Name = "Dark" + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.DisabledMapping", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("DisabledMapping"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.NothingMapping", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("NothingMapping"); + + b.HasData( + new + { + Id = 1, + ButtonMappingType = 0, + MouseButton = 0, + ProfileId = 1, + Selected = false + }, + new + { + Id = 2, + ButtonMappingType = 0, + MouseButton = 1, + ProfileId = 1, + Selected = false + }, + new + { + Id = 3, + ButtonMappingType = 0, + MouseButton = 2, + ProfileId = 1, + Selected = false + }, + new + { + Id = 4, + ButtonMappingType = 0, + MouseButton = 3, + ProfileId = 1, + Selected = false + }, + new + { + Id = 5, + ButtonMappingType = 0, + MouseButton = 4, + ProfileId = 1, + Selected = false + }, + new + { + Id = 6, + ButtonMappingType = 0, + MouseButton = 5, + ProfileId = 1, + Selected = false + }, + new + { + Id = 7, + ButtonMappingType = 0, + MouseButton = 6, + ProfileId = 1, + Selected = false + }, + new + { + Id = 8, + ButtonMappingType = 0, + MouseButton = 7, + ProfileId = 1, + Selected = false + }, + new + { + Id = 9, + ButtonMappingType = 0, + MouseButton = 8, + ProfileId = 1, + Selected = false + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.RightClick", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("RightClick"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SimulatedKeystroke", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.ButtonMapping"); + + b.HasDiscriminator().HasValue("SimulatedKeystroke"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingBool", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("BoolValue") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("SettingBool"); + + b.HasData( + new + { + Id = 1, + Name = "StartMinimized", + BoolValue = false + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingInt", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("IntValue") + .HasColumnType("INTEGER"); + + b.HasDiscriminator().HasValue("SettingInt"); + + b.HasData( + new + { + Id = 2, + Name = "Theme", + IntValue = 3 + }); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.SettingString", b => + { + b.HasBaseType("YMouseButtonControl.Domain.Models.Setting"); + + b.Property("StringValue") + .HasColumnType("TEXT"); + + b.HasDiscriminator().HasValue("SettingString"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.ButtonMapping", b => + { + b.HasOne("YMouseButtonControl.Domain.Models.Profile", "Profile") + .WithMany("ButtonMappings") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("YMouseButtonControl.Domain.Models.Profile", b => + { + b.Navigation("ButtonMappings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/YMouseButtonControl/App.axaml.cs b/YMouseButtonControl/App.axaml.cs index 2d457b1..03614f3 100644 --- a/YMouseButtonControl/App.axaml.cs +++ b/YMouseButtonControl/App.axaml.cs @@ -4,6 +4,7 @@ using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; using Avalonia.ReactiveUI; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -45,8 +46,11 @@ private void Init() .ConfigureServices(services => { services.UseMicrosoftDependencyResolver(); + services.AddDbContext(opts => + opts.UseSqlite(configuration.GetConnectionString("YMouseButtonControlContext")) + ); services.AddScoped(_ => configuration); - services.AddScoped(); + //services.AddScoped(); var resolver = Locator.CurrentMutable; resolver.InitializeSplat(); @@ -75,7 +79,7 @@ private void Init() Container = host.Services; Container.UseMicrosoftDependencyResolver(); - Container.GetRequiredService().Init(); + //Container.GetRequiredService().Init(); RxApp.MainThreadScheduler = AvaloniaScheduler.Instance; } diff --git a/YMouseButtonControl/DependencyInjection/DataAccessBootstrapper.cs b/YMouseButtonControl/DependencyInjection/DataAccessBootstrapper.cs index 7af089d..282e586 100644 --- a/YMouseButtonControl/DependencyInjection/DataAccessBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/DataAccessBootstrapper.cs @@ -1,8 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using YMouseButtonControl.Core.Repositories; using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.DataAccess.Models; -using YMouseButtonControl.DataAccess.Queries; +using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.DependencyInjection; @@ -11,10 +10,6 @@ public static class DataAccessBootstrapper public static void RegisterDataAccess(IServiceCollection services) { services - .AddScoped() - .AddScoped() - .AddScoped() - .AddScoped() .AddScoped, ProfileRepository>() .AddScoped, ButtonMappingRepository>() .AddScoped, SettingRepository>() diff --git a/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs b/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs index b724716..3be487b 100644 --- a/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs @@ -17,7 +17,7 @@ public static void RegisterViewModels(IServiceCollection services) private static void RegisterCommonViewModels(IServiceCollection services) { services - .AddScoped() + //.AddScoped() .AddScoped() .AddScoped() .AddScoped() diff --git a/YMouseButtonControl/YMouseButtonControl.csproj b/YMouseButtonControl/YMouseButtonControl.csproj index 3b855d5..d27593e 100644 --- a/YMouseButtonControl/YMouseButtonControl.csproj +++ b/YMouseButtonControl/YMouseButtonControl.csproj @@ -39,6 +39,9 @@ PreserveNewest + + Never + @@ -63,6 +66,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From b2ab9fa906fc1367c477ad6575d30f9d2c364f56 Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sat, 7 Dec 2024 16:30:01 -0500 Subject: [PATCH 03/39] wip --- .../Services/Profiles/ProfilesService.cs | 29 ----------- .../Features/Apply/ApplyProfiles.cs | 49 +++++++++++++++---- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs b/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs index 132aaaf..e281ff2 100644 --- a/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs +++ b/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs @@ -31,7 +31,6 @@ public interface IProfilesService void MoveProfileDown(ProfileVm p); void RemoveProfile(ProfileVm profileVm); void AddOrUpdate(ProfileVm profileVm); - void CheckForDirty(); } public class ProfilesService : ReactiveObject, IProfilesService, IDisposable @@ -94,28 +93,6 @@ private void IsDirty(IChangeSet set) } } - public void CheckForDirty() - { - var dbProfiles = _profileRepository.GetAll(); - foreach (var dbProf in dbProfiles) - { - if (_profilesObsCol.All(x => !x.Equals(dbProf))) - { - Dirty = true; - return; - } - } - foreach (var prof in _profilesObsCol) - { - if (dbProfiles.All(x => !x.Equals(prof))) - { - Dirty = true; - return; - } - } - Dirty = false; - } - public bool Dirty { get => _dirty; @@ -149,12 +126,6 @@ public ProfileVm CopyProfile(ProfileVm p) ) ?? throw new JsonSerializationException("Error deserializing profile"); } - public bool IsUnsavedChanges() - { - var dbProfiles = _profileRepository.GetAll().ToList(); - return !dbProfiles.SequenceEqual(_profiles.Items); - } - public void WriteProfileToFile(ProfileVm p, string path) { var jsonString = JsonConvert.SerializeObject( diff --git a/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs b/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs index 2ed9939..df7b161 100644 --- a/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs +++ b/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs @@ -1,9 +1,8 @@ using System.Linq; -using System.Transactions; -using YMouseButtonControl.Core.Repositories; +using Microsoft.EntityFrameworkCore; +using YMouseButtonControl.Core.Mappings; using YMouseButtonControl.Core.Services.Profiles; -using YMouseButtonControl.Core.ViewModels.Models; -using YMouseButtonControl.Domain.Models; +using YMouseButtonControl.Infrastructure.Context; namespace YMouseButtonControl.Core.ViewModels.MainWindow.Features.Apply; @@ -13,31 +12,63 @@ public interface IApply } public class Apply( - IRepository profileRepository, + YMouseButtonControlDbContext db, //IRepository buttonMappingRepository, IProfilesService profilesService ) : IApply { public void ApplyProfiles() { - var dbProfiles = profileRepository.GetAll(); + var dbProfiles = db.Profiles.AsNoTracking().ToList(); // delete profiles dbProfiles .Where(x => !profilesService.Profiles.Any(y => y.Id == x.Id)) .ToList() - .ForEach(x => profileRepository.Delete(x)); + .ForEach(x => + { + var ent = db.Profiles.Find(x.Id); + if (ent is not null) + { + db.Profiles.Remove(ent); + } + }); // update profiles profilesService .Profiles.Where(x => dbProfiles.Any(y => y.Id == x.Id)) .ToList() - .ForEach(x => profileRepository.Update(x)); + .ForEach(x => + { + var ent = db.Profiles.Find(x.Id); + if (ent is not null) + { + ent.Checked = x.Checked; + ent.Description = x.Description; + ent.DisplayPriority = x.DisplayPriority; + ent.IsDefault = x.IsDefault; + ent.MatchType = x.MatchType; + ent.Name = x.Name; + ent.ParentClass = x.ParentClass; + ent.Process = x.Process; + ent.WindowCaption = x.WindowCaption; + ent.WindowClass = x.WindowClass; + } + }); // add profiles profilesService .Profiles.Where(x => !dbProfiles.Any(y => y.Id == x.Id)) .ToList() - .ForEach(x => profileRepository.Add(x)); + .ForEach(x => + { + var ent = ProfileMapper.Map(x); + if (ent is not null) + { + db.Profiles.Add(ent); + } + }); + + db.SaveChanges(); } } From 28b288e8081cc23f73a7e4d25d33bf6d66d71a26 Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sun, 15 Dec 2024 11:42:16 -0500 Subject: [PATCH 04/39] wip --- .../Services/Profiles/ProfilesService.cs | 18 ++--- .../Features/Apply/ApplyProfiles.cs | 51 +++++++++++++++ .../ProfilesList/ProfilesListViewModel.cs | 65 +++++++++---------- .../KeyboardAndMouseBootstrapper.cs | 6 +- .../Views/ProfilesListView.axaml | 2 +- 5 files changed, 93 insertions(+), 49 deletions(-) diff --git a/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs b/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs index e281ff2..728d004 100644 --- a/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs +++ b/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; using System.IO; using System.Linq; using System.Reactive.Linq; @@ -52,11 +53,12 @@ public ProfilesService(IRepository profileRepository) .Bind(out _profilesObsCol) .Subscribe(IsDirty); _profiles.AddOrUpdate(profileRepository.GetAll().ToList()); + CurrentProfile ??= Profiles.FirstOrDefault(); } private void IsDirty(IChangeSet set) { - foreach (var cs in set.Where(x => x.Reason != ChangeReason.Refresh)) + foreach (var cs in set.Where(x => x.Reason is not ChangeReason.Refresh)) { if (cs.Reason == ChangeReason.Add) { @@ -68,11 +70,8 @@ private void IsDirty(IChangeSet set) } else if (cs.Reason == ChangeReason.Update) { - var ent = - _profileRepository.GetById(cs.Current.Id) - ?? throw new Exception("Null entity on update reason"); - var mapped = ProfileMapper.Map(cs.Current); - if (!ent.Equals(mapped)) + var ent = _profileRepository.GetById(cs.Current.Id); + if (ent is null || !ent.Equals(cs.Current)) { Dirty = true; return; @@ -80,17 +79,14 @@ private void IsDirty(IChangeSet set) } else if (cs.Reason == ChangeReason.Remove) { - if (_profileRepository.GetById(cs.Current.Id) is null) - { - Dirty = false; - } - else + if (_profileRepository.GetById(cs.Current.Id) is not null) { Dirty = true; return; } } } + Dirty = false; } public bool Dirty diff --git a/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs b/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs index df7b161..8796659 100644 --- a/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs +++ b/YMouseButtonControl.Core/ViewModels/MainWindow/Features/Apply/ApplyProfiles.cs @@ -1,7 +1,10 @@ using System.Linq; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using YMouseButtonControl.Core.Mappings; using YMouseButtonControl.Core.Services.Profiles; +using YMouseButtonControl.Core.ViewModels.Models; +using YMouseButtonControl.Domain.Models; using YMouseButtonControl.Infrastructure.Context; namespace YMouseButtonControl.Core.ViewModels.MainWindow.Features.Apply; @@ -53,6 +56,54 @@ public void ApplyProfiles() ent.Process = x.Process; ent.WindowCaption = x.WindowCaption; ent.WindowClass = x.WindowClass; + + x.ButtonMappings.ForEach(bm => + { + var dbBm = db.ButtonMappings.Find(bm.Id); + if (dbBm is not null) + { + dbBm.AutoRepeatDelay = bm.AutoRepeatDelay; + dbBm.AutoRepeatRandomizeDelayEnabled = + bm.AutoRepeatRandomizeDelayEnabled; + dbBm.BlockOriginalMouseInput = bm.BlockOriginalMouseInput; + dbBm.ButtonMappingType = bm switch + { + DisabledMappingVm => ButtonMappingType.Disabled, + NothingMappingVm => ButtonMappingType.Nothing, + SimulatedKeystrokeVm => ButtonMappingType.SimulatedKeystroke, + RightClickVm => ButtonMappingType.RightClick, + _ => throw new System.NotImplementedException(), + }; + dbBm.Keys = bm.Keys; + dbBm.MouseButton = bm.MouseButton; + dbBm.Selected = bm.Selected; + if (bm.SimulatedKeystrokeType is not null) + { + dbBm.SimulatedKeystrokeType = bm.SimulatedKeystrokeType switch + { + AsMousePressedAndReleasedActionTypeVm => + SimulatedKeystrokeType.AsMousePressedAndReleasedActionType, + DuringMouseActionTypeVm => + SimulatedKeystrokeType.DuringMouseActionType, + InAnotherThreadPressedActionTypeVm => + SimulatedKeystrokeType.InAnotherThreadPressedActionType, + InAnotherThreadReleasedActionTypeVm => + SimulatedKeystrokeType.InAnotherThreadReleasedActionType, + MouseButtonPressedActionTypeVm => + SimulatedKeystrokeType.MouseButtonPressedActionType, + MouseButtonReleasedActionTypeVm => + SimulatedKeystrokeType.MouseButtonReleasedActionType, + RepeatedlyWhileButtonDownActionTypeVm => + SimulatedKeystrokeType.RepeatedlyWhileButtonDownActionType, + StickyHoldActionTypeVm => + SimulatedKeystrokeType.StickyHoldActionType, + StickyRepeatActionTypeVm => + SimulatedKeystrokeType.StickyRepeatActionType, + _ => throw new System.NotImplementedException(), + }; + } + } + }); } }); diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs index feffdfc..33ab7c3 100644 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs @@ -19,7 +19,6 @@ public class ProfilesListViewModel : ViewModelBase, IProfilesListViewModel private IProfilesService _profilesService; private readonly IProcessSelectorDialogViewModel _processSelectorDialogViewModel; private readonly IAddProfile _addProfile; - private int _selectedIndex; public ICommand AddButtonCommand { get; } public ReactiveCommand EditButtonCommand { get; } @@ -86,41 +85,35 @@ curProf is not null EditButtonCommand = ReactiveCommand.CreateFromTask(EditButtonClickedAsync, editCanExecute); CopyCommand = ReactiveCommand.CreateFromTask(OnCopyClickedAsync); - SelectedIndex = _profilesService.Profiles.First(x => x.IsDefault).DisplayPriority; - this.WhenAnyValue(x => x.SelectedIndex) - .Subscribe(x => - { - if (_profilesService.CurrentProfile is null) - { - _profilesService.CurrentProfile = _profilesService.Profiles[x]; - } - else - { - if (SelectedIndex < 0) - { - SelectedIndex = _profilesService.CurrentProfile!.DisplayPriority; - } - else - { - if (_profilesService.Profiles.Count <= x) - { - SelectedIndex = _profilesService - .Profiles.First(y => y.IsDefault) - .DisplayPriority; - } - else - { - _profilesService.CurrentProfile = _profilesService.Profiles[x]; - } - } - } - }); - } - - public int SelectedIndex - { - get => _selectedIndex; - set => this.RaiseAndSetIfChanged(ref _selectedIndex, value); + //SelectedIndex = _profilesService.Profiles.First(x => x.IsDefault).DisplayPriority; + //this.WhenAnyValue(x => x.SelectedIndex) + // .Subscribe(x => + // { + // if (_profilesService.CurrentProfile is null) + // { + // _profilesService.CurrentProfile = _profilesService.Profiles[x]; + // } + // else + // { + // if (SelectedIndex < 0) + // { + // SelectedIndex = _profilesService.CurrentProfile!.DisplayPriority; + // } + // else + // { + // if (_profilesService.Profiles.Count <= x) + // { + // SelectedIndex = _profilesService + // .Profiles.First(y => y.IsDefault) + // .DisplayPriority; + // } + // else + // { + // _profilesService.CurrentProfile = _profilesService.Profiles[x]; + // } + // } + // } + // }); } public Interaction ShowExportFileDialog { get; } diff --git a/YMouseButtonControl/DependencyInjection/KeyboardAndMouseBootstrapper.cs b/YMouseButtonControl/DependencyInjection/KeyboardAndMouseBootstrapper.cs index 3403707..c928b67 100644 --- a/YMouseButtonControl/DependencyInjection/KeyboardAndMouseBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/KeyboardAndMouseBootstrapper.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using SharpHook; using SharpHook.Reactive; +using SharpHook.Testing; using YMouseButtonControl.Core.Services.KeyboardAndMouse; using YMouseButtonControl.Core.Services.KeyboardAndMouse.Implementations; using YMouseButtonControl.Core.Services.KeyboardAndMouse.Implementations.SimulatedKeystrokesTypes; @@ -43,7 +44,10 @@ private static void RegisterCommonKeyboardAndMouseServices(IServiceCollection se { services .AddScoped() - .AddScoped() + //.AddScoped() + .AddScoped( + (_) => new SimpleReactiveGlobalHook(globalHookProvider: new TestProvider()) + ) .AddScoped() .AddScoped() .AddScoped() diff --git a/YMouseButtonControl/Views/ProfilesListView.axaml b/YMouseButtonControl/Views/ProfilesListView.axaml index c29ae7f..37b865c 100644 --- a/YMouseButtonControl/Views/ProfilesListView.axaml +++ b/YMouseButtonControl/Views/ProfilesListView.axaml @@ -16,7 +16,7 @@ - + diff --git a/YMouseButtonControl/YMouseButtonControl.csproj b/YMouseButtonControl/YMouseButtonControl.csproj index d27593e..cc1ec93 100644 --- a/YMouseButtonControl/YMouseButtonControl.csproj +++ b/YMouseButtonControl/YMouseButtonControl.csproj @@ -39,9 +39,6 @@ PreserveNewest - - Never - From 05cd55b300b541df7d4314eb9c0b836ee559b036 Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sat, 21 Dec 2024 13:20:47 -0500 Subject: [PATCH 07/39] up --- .../ProcessSelectorDialogViewModel.cs | 133 ++++++++++++++++-- .../ProfilesList/ProfilesListViewModel.cs | 30 ---- 2 files changed, 123 insertions(+), 40 deletions(-) diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs index 66e81b3..fb9c10c 100644 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Reactive; using System.Reactive.Linq; using System.Windows.Input; @@ -8,6 +9,7 @@ using DynamicData.Binding; using ReactiveUI; using YMouseButtonControl.Core.Services.Processes; +using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.Models; using YMouseButtonControl.Domain.Models; @@ -29,7 +31,8 @@ public class ProcessSelectorDialogViewModel : DialogBase, IProcessSelectorDialog public ProcessSelectorDialogViewModel( IProcessMonitorService processMonitorService, - IThemeService themeService + IThemeService themeService, + IProfilesService profilesService ) : base(themeService) { @@ -51,15 +54,125 @@ IThemeService themeService OkCommand = ReactiveCommand.Create( () => { - var mb1 = new NothingMappingVm { MouseButton = MouseButton.Mb1, Selected = true }; - var mb2 = new NothingMappingVm { MouseButton = MouseButton.Mb2, Selected = true }; - var mb3 = new NothingMappingVm { MouseButton = MouseButton.Mb3, Selected = true }; - var mb4 = new NothingMappingVm { MouseButton = MouseButton.Mb4, Selected = true }; - var mb5 = new NothingMappingVm { MouseButton = MouseButton.Mb5, Selected = true }; - var mwu = new NothingMappingVm { MouseButton = MouseButton.Mwu, Selected = true }; - var mwd = new NothingMappingVm { MouseButton = MouseButton.Mwd, Selected = true }; - var mwl = new NothingMappingVm { MouseButton = MouseButton.Mwl, Selected = true }; - var mwr = new NothingMappingVm { MouseButton = MouseButton.Mwr, Selected = true }; + var maxBmId = profilesService + .Profiles.SelectMany(x => x.ButtonMappings) + .Max(x => x.Id); + var mb1 = new List + { + new NothingMappingVm + { + MouseButton = MouseButton.Mb1, + Selected = true, + Id = ++maxBmId, + }, + new DisabledMappingVm { MouseButton = MouseButton.Mb1, Id = ++maxBmId }, + new SimulatedKeystrokeVm { MouseButton = MouseButton.Mb1, Id = ++maxBmId }, + new RightClickVm { MouseButton = MouseButton.Mb1, Id = ++maxBmId }, + }; + + var mb2 = new List + { + new NothingMappingVm + { + MouseButton = MouseButton.Mb2, + Selected = true, + Id = ++maxBmId, + }, + new DisabledMappingVm { MouseButton = MouseButton.Mb2, Id = ++maxBmId }, + new SimulatedKeystrokeVm { MouseButton = MouseButton.Mb2, Id = ++maxBmId }, + new RightClickVm { MouseButton = MouseButton.Mb2, Id = ++maxBmId }, + }; + + var mb3 = new List + { + new NothingMappingVm + { + MouseButton = MouseButton.Mb3, + Selected = true, + Id = ++maxBmId, + }, + new DisabledMappingVm { MouseButton = MouseButton.Mb3, Id = ++maxBmId }, + new SimulatedKeystrokeVm { MouseButton = MouseButton.Mb3, Id = ++maxBmId }, + new RightClickVm { MouseButton = MouseButton.Mb3, Id = ++maxBmId }, + }; + + var mb4 = new List + { + new NothingMappingVm + { + MouseButton = MouseButton.Mb4, + Selected = true, + Id = ++maxBmId, + }, + new DisabledMappingVm { MouseButton = MouseButton.Mb4, Id = ++maxBmId }, + new SimulatedKeystrokeVm { MouseButton = MouseButton.Mb4, Id = ++maxBmId }, + new RightClickVm { MouseButton = MouseButton.Mb4, Id = ++maxBmId }, + }; + + var mb5 = new List + { + new NothingMappingVm + { + MouseButton = MouseButton.Mb5, + Selected = true, + Id = ++maxBmId, + }, + new DisabledMappingVm { MouseButton = MouseButton.Mb5, Id = ++maxBmId }, + new SimulatedKeystrokeVm { MouseButton = MouseButton.Mb5, Id = ++maxBmId }, + new RightClickVm { MouseButton = MouseButton.Mb5, Id = ++maxBmId }, + }; + + var mwu = new List + { + new NothingMappingVm + { + MouseButton = MouseButton.Mwu, + Selected = true, + Id = ++maxBmId, + }, + new DisabledMappingVm { MouseButton = MouseButton.Mwu, Id = ++maxBmId }, + new SimulatedKeystrokeVm { MouseButton = MouseButton.Mwu, Id = ++maxBmId }, + new RightClickVm { MouseButton = MouseButton.Mwu, Id = ++maxBmId }, + }; + + var mwd = new List + { + new NothingMappingVm + { + MouseButton = MouseButton.Mwd, + Selected = true, + Id = ++maxBmId, + }, + new DisabledMappingVm { MouseButton = MouseButton.Mwd, Id = ++maxBmId }, + new SimulatedKeystrokeVm { MouseButton = MouseButton.Mwd, Id = ++maxBmId }, + new RightClickVm { MouseButton = MouseButton.Mwd, Id = ++maxBmId }, + }; + + var mwl = new List + { + new NothingMappingVm + { + MouseButton = MouseButton.Mwl, + Selected = true, + Id = ++maxBmId, + }, + new DisabledMappingVm { MouseButton = MouseButton.Mwl, Id = ++maxBmId }, + new SimulatedKeystrokeVm { MouseButton = MouseButton.Mwl, Id = ++maxBmId }, + new RightClickVm { MouseButton = MouseButton.Mwl, Id = ++maxBmId }, + }; + + var mwr = new List + { + new NothingMappingVm + { + MouseButton = MouseButton.Mwr, + Selected = true, + Id = ++maxBmId, + }, + new DisabledMappingVm { MouseButton = MouseButton.Mwr, Id = ++maxBmId }, + new SimulatedKeystrokeVm { MouseButton = MouseButton.Mwr, Id = ++maxBmId }, + new RightClickVm { MouseButton = MouseButton.Mwr, Id = ++maxBmId }, + }; var buttonMappings = new List { diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs index 33ab7c3..2f3c3fd 100644 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs @@ -84,36 +84,6 @@ curProf is not null ); EditButtonCommand = ReactiveCommand.CreateFromTask(EditButtonClickedAsync, editCanExecute); CopyCommand = ReactiveCommand.CreateFromTask(OnCopyClickedAsync); - - //SelectedIndex = _profilesService.Profiles.First(x => x.IsDefault).DisplayPriority; - //this.WhenAnyValue(x => x.SelectedIndex) - // .Subscribe(x => - // { - // if (_profilesService.CurrentProfile is null) - // { - // _profilesService.CurrentProfile = _profilesService.Profiles[x]; - // } - // else - // { - // if (SelectedIndex < 0) - // { - // SelectedIndex = _profilesService.CurrentProfile!.DisplayPriority; - // } - // else - // { - // if (_profilesService.Profiles.Count <= x) - // { - // SelectedIndex = _profilesService - // .Profiles.First(y => y.IsDefault) - // .DisplayPriority; - // } - // else - // { - // _profilesService.CurrentProfile = _profilesService.Profiles[x]; - // } - // } - // } - // }); } public Interaction ShowExportFileDialog { get; } From f6274cb2b25557e13aea98c00490d14b232e5340 Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sat, 21 Dec 2024 14:06:17 -0500 Subject: [PATCH 08/39] Create button mappings in a function --- .../ProcessSelectorDialogViewModel.cs | 152 +++--------------- 1 file changed, 25 insertions(+), 127 deletions(-) diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs index fb9c10c..bce4435 100644 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs @@ -57,136 +57,18 @@ IProfilesService profilesService var maxBmId = profilesService .Profiles.SelectMany(x => x.ButtonMappings) .Max(x => x.Id); - var mb1 = new List - { - new NothingMappingVm - { - MouseButton = MouseButton.Mb1, - Selected = true, - Id = ++maxBmId, - }, - new DisabledMappingVm { MouseButton = MouseButton.Mb1, Id = ++maxBmId }, - new SimulatedKeystrokeVm { MouseButton = MouseButton.Mb1, Id = ++maxBmId }, - new RightClickVm { MouseButton = MouseButton.Mb1, Id = ++maxBmId }, - }; - - var mb2 = new List - { - new NothingMappingVm - { - MouseButton = MouseButton.Mb2, - Selected = true, - Id = ++maxBmId, - }, - new DisabledMappingVm { MouseButton = MouseButton.Mb2, Id = ++maxBmId }, - new SimulatedKeystrokeVm { MouseButton = MouseButton.Mb2, Id = ++maxBmId }, - new RightClickVm { MouseButton = MouseButton.Mb2, Id = ++maxBmId }, - }; - - var mb3 = new List - { - new NothingMappingVm - { - MouseButton = MouseButton.Mb3, - Selected = true, - Id = ++maxBmId, - }, - new DisabledMappingVm { MouseButton = MouseButton.Mb3, Id = ++maxBmId }, - new SimulatedKeystrokeVm { MouseButton = MouseButton.Mb3, Id = ++maxBmId }, - new RightClickVm { MouseButton = MouseButton.Mb3, Id = ++maxBmId }, - }; - - var mb4 = new List - { - new NothingMappingVm - { - MouseButton = MouseButton.Mb4, - Selected = true, - Id = ++maxBmId, - }, - new DisabledMappingVm { MouseButton = MouseButton.Mb4, Id = ++maxBmId }, - new SimulatedKeystrokeVm { MouseButton = MouseButton.Mb4, Id = ++maxBmId }, - new RightClickVm { MouseButton = MouseButton.Mb4, Id = ++maxBmId }, - }; - - var mb5 = new List - { - new NothingMappingVm - { - MouseButton = MouseButton.Mb5, - Selected = true, - Id = ++maxBmId, - }, - new DisabledMappingVm { MouseButton = MouseButton.Mb5, Id = ++maxBmId }, - new SimulatedKeystrokeVm { MouseButton = MouseButton.Mb5, Id = ++maxBmId }, - new RightClickVm { MouseButton = MouseButton.Mb5, Id = ++maxBmId }, - }; - - var mwu = new List - { - new NothingMappingVm - { - MouseButton = MouseButton.Mwu, - Selected = true, - Id = ++maxBmId, - }, - new DisabledMappingVm { MouseButton = MouseButton.Mwu, Id = ++maxBmId }, - new SimulatedKeystrokeVm { MouseButton = MouseButton.Mwu, Id = ++maxBmId }, - new RightClickVm { MouseButton = MouseButton.Mwu, Id = ++maxBmId }, - }; - - var mwd = new List - { - new NothingMappingVm - { - MouseButton = MouseButton.Mwd, - Selected = true, - Id = ++maxBmId, - }, - new DisabledMappingVm { MouseButton = MouseButton.Mwd, Id = ++maxBmId }, - new SimulatedKeystrokeVm { MouseButton = MouseButton.Mwd, Id = ++maxBmId }, - new RightClickVm { MouseButton = MouseButton.Mwd, Id = ++maxBmId }, - }; - - var mwl = new List - { - new NothingMappingVm - { - MouseButton = MouseButton.Mwl, - Selected = true, - Id = ++maxBmId, - }, - new DisabledMappingVm { MouseButton = MouseButton.Mwl, Id = ++maxBmId }, - new SimulatedKeystrokeVm { MouseButton = MouseButton.Mwl, Id = ++maxBmId }, - new RightClickVm { MouseButton = MouseButton.Mwl, Id = ++maxBmId }, - }; - - var mwr = new List - { - new NothingMappingVm - { - MouseButton = MouseButton.Mwr, - Selected = true, - Id = ++maxBmId, - }, - new DisabledMappingVm { MouseButton = MouseButton.Mwr, Id = ++maxBmId }, - new SimulatedKeystrokeVm { MouseButton = MouseButton.Mwr, Id = ++maxBmId }, - new RightClickVm { MouseButton = MouseButton.Mwr, Id = ++maxBmId }, - }; - var buttonMappings = new List { - mb1, - mb2, - mb3, - mb4, - mb5, - mwu, - mwd, - mwl, - mwr, + CreateButtonMappings(maxBmId, MouseButton.Mb1), + CreateButtonMappings(maxBmId += 4, MouseButton.Mb2), + CreateButtonMappings(maxBmId += 4, MouseButton.Mb3), + CreateButtonMappings(maxBmId += 4, MouseButton.Mb4), + CreateButtonMappings(maxBmId += 4, MouseButton.Mb5), + CreateButtonMappings(maxBmId += 4, MouseButton.Mwu), + CreateButtonMappings(maxBmId += 4, MouseButton.Mwd), + CreateButtonMappings(maxBmId += 4, MouseButton.Mwl), + CreateButtonMappings(maxBmId + 4, MouseButton.Mwr), }; - return new ProfileVm(buttonMappings) { Name = SelectedProcessModel!.Process.MainModule!.ModuleName, @@ -202,6 +84,22 @@ IProfilesService profilesService ); } + private static List CreateButtonMappings( + int id, + MouseButton mouseButton + ) => + [ + new NothingMappingVm + { + Id = ++id, + MouseButton = mouseButton, + Selected = true, + }, + new DisabledMappingVm { Id = ++id, MouseButton = mouseButton }, + new SimulatedKeystrokeVm { Id = ++id, MouseButton = mouseButton }, + new RightClickVm { Id = ++id, MouseButton = mouseButton }, + ]; + private Func CreateProcessFilterPredicate(string? txt) { if (string.IsNullOrWhiteSpace(txt)) From dfd3d768b0cda176d8d856d74d0a77dc0c59bcce Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sat, 21 Dec 2024 16:56:20 -0500 Subject: [PATCH 09/39] Default sort by process name --- .../ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs | 1 + YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs index bce4435..637e7ca 100644 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs @@ -43,6 +43,7 @@ IProfilesService profilesService var filteredDisposable = _sourceProcessModels .Connect() .Filter(dynamicFilter) + .Sort(SortExpressionComparer.Ascending(x => x.Process.ProcessName)) .Bind(out _filtered) .Subscribe(); RefreshProcessList(); diff --git a/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml b/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml index d96d590..a2a89ec 100644 --- a/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml +++ b/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml @@ -54,7 +54,7 @@ - + From b3c8acab47a3a6fd8da9435555a777547af08aa8 Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sat, 21 Dec 2024 18:30:26 -0500 Subject: [PATCH 10/39] up --- .../LayerViewModel/MouseComboViewModel.cs | 39 +++++++++++-------- .../ViewModels/Models/ProfileVm.cs | 4 +- .../ProcessSelectorDialogViewModel.cs | 4 +- .../Views/ProfilesListView.axaml.cs | 2 +- 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs b/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs index 725bf02..be60b70 100644 --- a/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs @@ -2,6 +2,7 @@ using System.Collections.ObjectModel; using System.Linq; using System.Reactive; +using System.Reactive.Linq; using System.Timers; using Avalonia.Media; using ReactiveUI; @@ -96,6 +97,25 @@ ReadOnlyObservableCollection btnMappings } SelectedBtnMap = BtnMappings.First(x => x.Selected); + this.WhenAnyValue(x => x.SelectedBtnMap) + .DistinctUntilChanged() + .WhereNotNull() + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(current => + { + profileVm.BtnSc.Edit(inner => + { + var previous = inner.Items.FirstOrDefault(x => + x.Selected && x.MouseButton == current.MouseButton && !x.Equals(current) + ); + if (previous != null) + { + previous.Selected = false; + } + var target = inner.Items.First(x => x.Id == current.Id); + target.Selected = true; + }); + }); ShowSimulatedKeystrokesDialogService = showSimulatedKeystrokesDialogService; var canClickUserClickedSettingsBtn = this.WhenAnyValue( x => x.SelectedBtnMap, @@ -128,11 +148,11 @@ previouslySelectedBtnMap is not null ) { previouslySelectedBtnMap.Selected = false; - _profileVm.AddOrUpdateBtnMapping(previouslySelectedBtnMap, newMapping); + _profileVm.AddOrUpdateBtnMapping([previouslySelectedBtnMap, newMapping]); } else { - _profileVm.AddOrUpdateBtnMapping(newMapping); + _profileVm.AddOrUpdateBtnMapping([newMapping]); } SelectedBtnMap = newMapping; } @@ -163,20 +183,7 @@ public IBrush BackgroundColor public BaseButtonMappingVm? SelectedBtnMap { get => _selectedBtnMap; - set - { - // if (_selectedBtnMap is not null) - // { - // _selectedBtnMap.Selected = false; - // } - - if (value is not null) - { - value.Selected = true; - } - - this.RaiseAndSetIfChanged(ref _selectedBtnMap, value); - } + set => this.RaiseAndSetIfChanged(ref _selectedBtnMap, value); } public string? LabelTxt diff --git a/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs b/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs index 97f9865..dae4931 100644 --- a/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs +++ b/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs @@ -170,9 +170,11 @@ public ProfileVm(List buttonMappings) .ToProperty(this, x => x.MouseWheelRight); } - public void AddOrUpdateBtnMapping(params BaseButtonMappingVm[] buttonMappingVms) => + public void AddOrUpdateBtnMapping(IEnumerable buttonMappingVms) => _btnSc.AddOrUpdate(buttonMappingVms); + public SourceCache BtnSc => _btnSc; + [JsonIgnore] public int Id { get; set; } public bool IsDefault { get; set; } diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs index 637e7ca..abfccc2 100644 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs @@ -18,7 +18,7 @@ namespace YMouseButtonControl.Core.ViewModels.ProfilesList; public interface IProcessSelectorDialogViewModel { - ICommand RefreshButtonCommand { get; } + ReactiveCommand RefreshButtonCommand { get; } } public class ProcessSelectorDialogViewModel : DialogBase, IProcessSelectorDialogViewModel @@ -119,7 +119,7 @@ public string? ProcessFilter set => this.RaiseAndSetIfChanged(ref _processFilter, value); } - public ICommand RefreshButtonCommand { get; } + public ReactiveCommand RefreshButtonCommand { get; } public ReactiveCommand OkCommand { get; } diff --git a/YMouseButtonControl/Views/ProfilesListView.axaml.cs b/YMouseButtonControl/Views/ProfilesListView.axaml.cs index 2a3d9fe..fcc3b55 100644 --- a/YMouseButtonControl/Views/ProfilesListView.axaml.cs +++ b/YMouseButtonControl/Views/ProfilesListView.axaml.cs @@ -90,7 +90,7 @@ private static async Task ShowProcessSelectorDialogAsync( IInteractionContext interaction ) { - interaction.Input.RefreshButtonCommand.Execute(null); + interaction.Input.RefreshButtonCommand.Execute(); var dialog = new ProcessSelectorDialog { DataContext = interaction.Input }; var result = await dialog.ShowDialog(MainWindowProvider.GetMainWindow()); interaction.SetOutput(result); From 5b6f00cd1299167582fdba888b18df1c5f65a3ed Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sun, 22 Dec 2024 08:43:19 -0500 Subject: [PATCH 11/39] Moved startmenu services --- .../IStartMenuInstallerService.cs | 8 ---- .../StartMenuInstall/IStartMenuInstall.cs | 6 +++ .../StartMenuInstall/StartMenuInstallLinux.cs | 15 +++---- .../StartMenuInstall/StartMenuInstallOsx.cs | 11 +++++ .../StartMenuInstallWindows.cs | 19 ++------ .../StartMenuUninstall/IStartMenuUninstall.cs | 7 +++ .../StartMenuUninstallLinux.cs | 21 +++++++++ .../StartMenuUninstallOsx.cs | 11 +++++ .../StartMenuUninstallWindows.cs | 31 +++++++++++++ .../GlobalSettingsDialogViewModel.cs | 21 +++++---- .../IStartMenuInstallerStatus.cs | 6 +++ .../StartMenuInstallerStatusLinux.cs | 25 +++++++++++ .../StartMenuInstallerStatusOsx.cs | 9 ++++ .../StartMenuInstallerStatusWindows.cs | 45 +++++++++++++++++++ .../LayerViewModel/LayerViewModel.cs | 1 + .../MainWindow/MainWindowViewModel.cs | 1 + .../MouseComboViewModel.cs | 13 +++--- .../MouseComboViewModelFactory.cs | 3 +- .../YMouseButtonControl.Core.csproj | 1 + .../Services/StartMenuInstaller.cs | 21 --------- .../FactoriesBootstrapper.cs | 2 +- .../KeyboardAndMouseBootstrapper.cs | 5 ++- .../ServicesBootstrapper.cs | 16 +++++-- .../ViewModelsBootstrapper.cs | 1 + YMouseButtonControl/Views/MainWindow.axaml.cs | 1 + .../Views/MouseButtonComboControl.axaml.cs | 1 + 26 files changed, 222 insertions(+), 79 deletions(-) delete mode 100644 YMouseButtonControl.Core/Services/StartMenuInstaller/IStartMenuInstallerService.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstall.cs rename YMouseButtonControl.Linux/Services/StartMenuInstallerService.cs => YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallLinux.cs (72%) create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallOsx.cs rename YMouseButtonControl.Windows/Services/StartMenuInstallerService.cs => YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallWindows.cs (72%) create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/IStartMenuUninstall.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallLinux.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallOsx.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallWindows.cs rename YMouseButtonControl.Core/ViewModels/{MainWindow => GlobalSettingsDialog}/GlobalSettingsDialogViewModel.cs (84%) create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatus.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusLinux.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusOsx.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusWindows.cs rename YMouseButtonControl.Core/ViewModels/{LayerViewModel => MouseComboViewModel}/MouseComboViewModel.cs (94%) rename YMouseButtonControl.Core/ViewModels/{LayerViewModel => MouseComboViewModel}/MouseComboViewModelFactory.cs (91%) delete mode 100644 YMouseButtonControl.MacOS/Services/StartMenuInstaller.cs diff --git a/YMouseButtonControl.Core/Services/StartMenuInstaller/IStartMenuInstallerService.cs b/YMouseButtonControl.Core/Services/StartMenuInstaller/IStartMenuInstallerService.cs deleted file mode 100644 index ff2ad4a..0000000 --- a/YMouseButtonControl.Core/Services/StartMenuInstaller/IStartMenuInstallerService.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace YMouseButtonControl.Core.Services.StartMenuInstaller; - -public interface IStartMenuInstallerService -{ - bool InstallStatus(); - void Install(); - void Uninstall(); -} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstall.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstall.cs new file mode 100644 index 0000000..a6dcbf3 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstall.cs @@ -0,0 +1,6 @@ +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; + +public interface IStartMenuInstall +{ + void Install(); +} diff --git a/YMouseButtonControl.Linux/Services/StartMenuInstallerService.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallLinux.cs similarity index 72% rename from YMouseButtonControl.Linux/Services/StartMenuInstallerService.cs rename to YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallLinux.cs index c2c57ad..9704b60 100644 --- a/YMouseButtonControl.Linux/Services/StartMenuInstallerService.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallLinux.cs @@ -1,8 +1,9 @@ -using YMouseButtonControl.Core.Services.StartMenuInstaller; +using System; +using System.IO; -namespace YMouseButtonControl.Linux.Services; +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; -public class StartMenuInstallerService : IStartMenuInstallerService +public class StartMenuInstallLinux : IStartMenuInstall { private const string DesktopFile = """ [Desktop Entry] @@ -22,24 +23,18 @@ [Desktop Entry] private readonly string _desktopFilePath; - public StartMenuInstallerService() + public StartMenuInstallLinux() { var applicationsDir = Path.Combine(_localShare, "applications"); _desktopFilePath = Path.Combine(applicationsDir, "YMouseButtonControl.desktop"); } - public bool InstallStatus() => - File.Exists(_desktopFilePath) - && File.ReadAllText(_desktopFilePath).Contains($"Exec={GetCurExePath()}"); - public void Install() => File.WriteAllText( _desktopFilePath, string.Format(DesktopFile, GetCurExePath(), GetCurExeParentPath()) ); - public void Uninstall() => File.Delete(_desktopFilePath); - private static string GetCurExeParentPath() => Path.GetDirectoryName(GetCurExePath()) ?? throw new Exception("Error retrieving parent of process path"); diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallOsx.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallOsx.cs new file mode 100644 index 0000000..2456bd2 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallOsx.cs @@ -0,0 +1,11 @@ +using System; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; + +public class StartMenuInstallOsx : IStartMenuInstall +{ + public void Install() + { + throw new NotImplementedException(); + } +} diff --git a/YMouseButtonControl.Windows/Services/StartMenuInstallerService.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallWindows.cs similarity index 72% rename from YMouseButtonControl.Windows/Services/StartMenuInstallerService.cs rename to YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallWindows.cs index 2371ef2..cd0bf36 100644 --- a/YMouseButtonControl.Windows/Services/StartMenuInstallerService.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallWindows.cs @@ -1,11 +1,10 @@ using System; using System.IO; using WindowsShortcutFactory; -using YMouseButtonControl.Core.Services.StartMenuInstaller; -namespace YMouseButtonControl.Windows.Services; +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; -public class StartMenuInstallerService : IStartMenuInstallerService +public class StartMenuInstallWindows : IStartMenuInstall { private readonly string _roamingAppDataFolder = Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData @@ -15,7 +14,7 @@ public class StartMenuInstallerService : IStartMenuInstallerService private readonly string _roamingYmouseButtonsShortcutPath; - public StartMenuInstallerService() + public StartMenuInstallWindows() { _roamingYMouseButtonsFolder = Path.Combine( _roamingAppDataFolder, @@ -31,16 +30,6 @@ public StartMenuInstallerService() ); } - public bool InstallStatus() - { - if (!File.Exists(_roamingYmouseButtonsShortcutPath)) - { - return false; - } - using var shortcut = WindowsShortcut.Load(_roamingYmouseButtonsShortcutPath); - return shortcut.Path == GetCurExePath(); - } - public void Install() { if (File.Exists(_roamingYmouseButtonsShortcutPath)) @@ -59,8 +48,6 @@ public void Install() shortcut.Save(_roamingYmouseButtonsShortcutPath); } - public void Uninstall() => File.Delete(_roamingYmouseButtonsShortcutPath); - private static string GetCurExeParentPath() => Path.GetDirectoryName(GetCurExePath()) ?? throw new Exception("Error retrieving parent of process path"); diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/IStartMenuUninstall.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/IStartMenuUninstall.cs new file mode 100644 index 0000000..9cc1dd1 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/IStartMenuUninstall.cs @@ -0,0 +1,7 @@ +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall +{ + public interface IStartMenuUninstall + { + void Uninstall(); + } +} \ No newline at end of file diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallLinux.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallLinux.cs new file mode 100644 index 0000000..781f70a --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallLinux.cs @@ -0,0 +1,21 @@ +using System; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; + +public class StartMenuUninstallLinux : IStartMenuUninstall +{ + private readonly string _localShare = Environment.GetFolderPath( + Environment.SpecialFolder.LocalApplicationData + ); + + private readonly string _desktopFilePath; + + public StartMenuUninstallLinux() + { + var applicationsDir = Path.Combine(_localShare, "applications"); + _desktopFilePath = Path.Combine(applicationsDir, "YMouseButtonControl.desktop"); + } + + public void Uninstall() => File.Delete(_desktopFilePath); +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallOsx.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallOsx.cs new file mode 100644 index 0000000..a15216b --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallOsx.cs @@ -0,0 +1,11 @@ +using System; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; + +public class StartMenuUninstallOsx : IStartMenuUninstall +{ + public void Uninstall() + { + throw new NotImplementedException(); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallWindows.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallWindows.cs new file mode 100644 index 0000000..1adea40 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallWindows.cs @@ -0,0 +1,31 @@ +using System; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; + +public class StartMenuUninstallWindows : IStartMenuUninstall +{ + private readonly string _roamingAppDataFolder = Environment.GetFolderPath( + Environment.SpecialFolder.ApplicationData + ); + private readonly string _roamingYMouseButtonsFolder; + private readonly string _roamingYmouseButtonsShortcutPath; + + public StartMenuUninstallWindows() + { + _roamingYMouseButtonsFolder = Path.Combine( + _roamingAppDataFolder, + "Microsoft", + "Windows", + "Start Menu", + "Programs", + "YMouseButtonControl" + ); + _roamingYmouseButtonsShortcutPath = Path.Combine( + _roamingYMouseButtonsFolder, + "YMouseButtonControl.lnk" + ); + } + + public void Uninstall() => File.Delete(_roamingYmouseButtonsShortcutPath); +} diff --git a/YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs similarity index 84% rename from YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs rename to YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs index cc13947..70a3d1f 100644 --- a/YMouseButtonControl.Core/ViewModels/MainWindow/GlobalSettingsDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs @@ -3,15 +3,16 @@ using System.Linq; using System.Reactive; using System.Reactive.Linq; -using System.Transactions; using ReactiveUI; using YMouseButtonControl.Core.Services.Logging; using YMouseButtonControl.Core.Services.Settings; -using YMouseButtonControl.Core.Services.StartMenuInstaller; using YMouseButtonControl.Core.Services.Theme; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; using YMouseButtonControl.Core.ViewModels.Models; -namespace YMouseButtonControl.Core.ViewModels.MainWindow; +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog; public interface IGlobalSettingsDialogViewModel; @@ -26,7 +27,9 @@ public class GlobalSettingsDialogViewModel : DialogBase, IGlobalSettingsDialogVi private readonly ObservableAsPropertyHelper? _applyIsExec; public GlobalSettingsDialogViewModel( - IStartMenuInstallerService startMenuInstallerService, + IStartMenuInstallerStatus startupMenuInstallerStatus, + IStartMenuInstall startMenuInstall, + IStartMenuUninstall startMenuUninstall, IEnableLoggingService enableLoggingService, ISettingsService settingsService, IThemeService themeService @@ -34,7 +37,7 @@ IThemeService themeService : base(themeService) { StartMenuEnabled = !OperatingSystem.IsMacOS(); - _startMenuChecked = StartMenuEnabled && startMenuInstallerService.InstallStatus(); + _startMenuChecked = StartMenuEnabled && startupMenuInstallerStatus.InstallStatus(); _startMinimizedSetting = settingsService.GetSetting("StartMinimized") as SettingBoolVm ?? throw new Exception("Error retrieving StartMinimized setting"); @@ -60,7 +63,7 @@ IThemeService themeService ); var startMenuChanged = this.WhenAnyValue( x => x.StartMenuChecked, - selector: val => StartMenuEnabled && val != startMenuInstallerService.InstallStatus() + selector: val => StartMenuEnabled && val != startupMenuInstallerStatus.InstallStatus() ); var themeChanged = this.WhenAnyValue( x => x.ThemeSetting.IntValue, @@ -91,16 +94,16 @@ IThemeService themeService if ( StartMenuEnabled - && StartMenuChecked != startMenuInstallerService.InstallStatus() + && StartMenuChecked != startupMenuInstallerStatus.InstallStatus() ) { if (StartMenuChecked) { - startMenuInstallerService.Install(); + startMenuInstall.Install(); } else { - startMenuInstallerService.Uninstall(); + startMenuUninstall.Uninstall(); } } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatus.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatus.cs new file mode 100644 index 0000000..58276d8 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatus.cs @@ -0,0 +1,6 @@ +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; + +public interface IStartMenuInstallerStatus +{ + public bool InstallStatus(); +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusLinux.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusLinux.cs new file mode 100644 index 0000000..19d5a52 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusLinux.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; + +public class StartMenuInstallerStatusLinux : IStartMenuInstallerStatus +{ + private readonly string _localShare = Environment.GetFolderPath( + Environment.SpecialFolder.LocalApplicationData + ); + private readonly string _desktopFilePath; + + public StartMenuInstallerStatusLinux() + { + var applicationsDir = Path.Combine(_localShare, "applications"); + _desktopFilePath = Path.Combine(applicationsDir, "YMouseButtonControl.desktop"); + } + + public bool InstallStatus() => + File.Exists(_desktopFilePath) + && File.ReadAllText(_desktopFilePath).Contains($"Exec={GetCurExePath()}"); + + private static string GetCurExePath() => + Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusOsx.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusOsx.cs new file mode 100644 index 0000000..1e24be4 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusOsx.cs @@ -0,0 +1,9 @@ +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; + +public class StartMenuInstallerStatusOsx : IStartMenuInstallerStatus +{ + public bool InstallStatus() + { + throw new System.NotImplementedException(); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusWindows.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusWindows.cs new file mode 100644 index 0000000..65291da --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusWindows.cs @@ -0,0 +1,45 @@ +using System; +using System.IO; +using WindowsShortcutFactory; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; + +public class StartMenuInstallerStatusWindows : IStartMenuInstallerStatus +{ + private readonly string _roamingAppDataFolder = Environment.GetFolderPath( + Environment.SpecialFolder.ApplicationData + ); + + private readonly string _roamingYMouseButtonsFolder; + + private readonly string _roamingYmouseButtonsShortcutPath; + + public StartMenuInstallerStatusWindows() + { + _roamingYMouseButtonsFolder = Path.Combine( + _roamingAppDataFolder, + "Microsoft", + "Windows", + "Start Menu", + "Programs", + "YMouseButtonControl" + ); + _roamingYmouseButtonsShortcutPath = Path.Combine( + _roamingYMouseButtonsFolder, + "YMouseButtonControl.lnk" + ); + } + + public bool InstallStatus() + { + if (!File.Exists(_roamingYmouseButtonsShortcutPath)) + { + return false; + } + using var shortcut = WindowsShortcut.Load(_roamingYmouseButtonsShortcutPath); + return shortcut.Path == GetCurExePath(); + } + + private static string GetCurExePath() => + Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); +} diff --git a/YMouseButtonControl.Core/ViewModels/LayerViewModel/LayerViewModel.cs b/YMouseButtonControl.Core/ViewModels/LayerViewModel/LayerViewModel.cs index f38beb3..54d2740 100644 --- a/YMouseButtonControl.Core/ViewModels/LayerViewModel/LayerViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/LayerViewModel/LayerViewModel.cs @@ -2,6 +2,7 @@ using System.Reactive.Linq; using ReactiveUI; using YMouseButtonControl.Core.Services.Profiles; +using YMouseButtonControl.Core.ViewModels.MouseComboViewModel; using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.ViewModels.LayerViewModel; diff --git a/YMouseButtonControl.Core/ViewModels/MainWindow/MainWindowViewModel.cs b/YMouseButtonControl.Core/ViewModels/MainWindow/MainWindowViewModel.cs index a22ccc1..fe10a93 100644 --- a/YMouseButtonControl.Core/ViewModels/MainWindow/MainWindowViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/MainWindow/MainWindowViewModel.cs @@ -9,6 +9,7 @@ using ReactiveUI; using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.Services.Theme; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog; using YMouseButtonControl.Core.ViewModels.LayerViewModel; using YMouseButtonControl.Core.ViewModels.MainWindow.Features.Apply; using YMouseButtonControl.Core.ViewModels.Models; diff --git a/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs b/YMouseButtonControl.Core/ViewModels/MouseComboViewModel/MouseComboViewModel.cs similarity index 94% rename from YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs rename to YMouseButtonControl.Core/ViewModels/MouseComboViewModel/MouseComboViewModel.cs index be60b70..bf34be9 100644 --- a/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/MouseComboViewModel/MouseComboViewModel.cs @@ -9,10 +9,11 @@ using YMouseButtonControl.Core.Services.KeyboardAndMouse.Enums; using YMouseButtonControl.Core.Services.KeyboardAndMouse.Implementations; using YMouseButtonControl.Core.Services.Theme; +using YMouseButtonControl.Core.ViewModels.LayerViewModel; using YMouseButtonControl.Core.ViewModels.Models; using YMouseButtonControl.Domain.Models; -namespace YMouseButtonControl.Core.ViewModels.LayerViewModel; +namespace YMouseButtonControl.Core.ViewModels.MouseComboViewModel; public interface IMouseComboViewModel { @@ -24,7 +25,6 @@ public interface IMouseComboViewModel public class MouseComboViewModel : ReactiveObject, IMouseComboViewModel, IDisposable { private readonly ProfileVm _profileVm; - private readonly MouseButton _mouseButton; private readonly ReadOnlyObservableCollection _btnMappings; private BaseButtonMappingVm? _selectedBtnMap; private readonly IDisposable? _mbDownDisposable; @@ -44,7 +44,6 @@ ReadOnlyObservableCollection btnMappings ) { _profileVm = profileVm; - _mouseButton = mouseButton; _btnMappings = btnMappings; _backgroundColor = themeService.Background; switch (mouseButton) @@ -100,7 +99,6 @@ ReadOnlyObservableCollection btnMappings this.WhenAnyValue(x => x.SelectedBtnMap) .DistinctUntilChanged() .WhereNotNull() - .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(current => { profileVm.BtnSc.Edit(inner => @@ -137,11 +135,10 @@ await ShowSimulatedKeystrokesDialogService.ShowSimulatedKeystrokesDialog( ); if (newMapping is not null) { - // SelectedBtnMap is already SimulatedKeystroke here newMapping.Selected = true; - var previouslySelectedBtnMap = BtnMappings - .FirstOrDefault(x => x.Selected && x.Id != newMapping.Id) - ?.Clone(); + var previouslySelectedBtnMap = BtnMappings.FirstOrDefault(x => + x.Selected && x.Id != newMapping.Id + ); if ( previouslySelectedBtnMap is not null && !previouslySelectedBtnMap.Equals(newMapping) diff --git a/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModelFactory.cs b/YMouseButtonControl.Core/ViewModels/MouseComboViewModel/MouseComboViewModelFactory.cs similarity index 91% rename from YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModelFactory.cs rename to YMouseButtonControl.Core/ViewModels/MouseComboViewModel/MouseComboViewModelFactory.cs index 3334537..2a78c6e 100644 --- a/YMouseButtonControl.Core/ViewModels/LayerViewModel/MouseComboViewModelFactory.cs +++ b/YMouseButtonControl.Core/ViewModels/MouseComboViewModel/MouseComboViewModelFactory.cs @@ -2,11 +2,12 @@ using YMouseButtonControl.Core.Services.KeyboardAndMouse.Implementations; using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.Services.Theme; +using YMouseButtonControl.Core.ViewModels.LayerViewModel; using YMouseButtonControl.Core.ViewModels.Models; using YMouseButtonControl.Domain.Models; using YMouseButtonControl.Infrastructure.Context; -namespace YMouseButtonControl.Core.ViewModels.LayerViewModel; +namespace YMouseButtonControl.Core.ViewModels.MouseComboViewModel; public interface IMouseComboViewModelFactory { diff --git a/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj b/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj index ba05255..05574fb 100644 --- a/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj +++ b/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj @@ -26,6 +26,7 @@ + diff --git a/YMouseButtonControl.MacOS/Services/StartMenuInstaller.cs b/YMouseButtonControl.MacOS/Services/StartMenuInstaller.cs deleted file mode 100644 index 26ddb0c..0000000 --- a/YMouseButtonControl.MacOS/Services/StartMenuInstaller.cs +++ /dev/null @@ -1,21 +0,0 @@ -using YMouseButtonControl.Core.Services.StartMenuInstaller; - -namespace YMouseButtonControl.MacOS.Services; - -public class StartMenuInstaller : IStartMenuInstallerService -{ - public bool InstallStatus() - { - throw new System.NotImplementedException(); - } - - public void Install() - { - throw new System.NotImplementedException(); - } - - public void Uninstall() - { - throw new System.NotImplementedException(); - } -} diff --git a/YMouseButtonControl/DependencyInjection/FactoriesBootstrapper.cs b/YMouseButtonControl/DependencyInjection/FactoriesBootstrapper.cs index 9f28da7..fc6ce19 100644 --- a/YMouseButtonControl/DependencyInjection/FactoriesBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/FactoriesBootstrapper.cs @@ -1,5 +1,5 @@ using Microsoft.Extensions.DependencyInjection; -using YMouseButtonControl.Core.ViewModels.LayerViewModel; +using YMouseButtonControl.Core.ViewModels.MouseComboViewModel; namespace YMouseButtonControl.DependencyInjection; diff --git a/YMouseButtonControl/DependencyInjection/KeyboardAndMouseBootstrapper.cs b/YMouseButtonControl/DependencyInjection/KeyboardAndMouseBootstrapper.cs index c928b67..e224fc9 100644 --- a/YMouseButtonControl/DependencyInjection/KeyboardAndMouseBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/KeyboardAndMouseBootstrapper.cs @@ -44,10 +44,13 @@ private static void RegisterCommonKeyboardAndMouseServices(IServiceCollection se { services .AddScoped() - //.AddScoped() +#if DEBUG .AddScoped( (_) => new SimpleReactiveGlobalHook(globalHookProvider: new TestProvider()) ) +#else + .AddScoped() +#endif .AddScoped() .AddScoped() .AddScoped() diff --git a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs index 797e398..015c5de 100644 --- a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs @@ -6,9 +6,11 @@ using YMouseButtonControl.Core.Services.Processes; using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.Services.Settings; -using YMouseButtonControl.Core.Services.StartMenuInstaller; using YMouseButtonControl.Core.Services.StartupInstaller; using YMouseButtonControl.Core.Services.Theme; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; namespace YMouseButtonControl.DependencyInjection; @@ -52,8 +54,10 @@ private static void RegisterPlatformSpecificServices(IServiceCollection services private static void RegisterLinuxServices(IServiceCollection services) { services + .AddScoped() + .AddScoped() + .AddScoped() .AddScoped() - .AddScoped() .AddScoped() .AddScoped(); if (Environment.GetEnvironmentVariable("XDG_SESSION_TYPE") == "x11") @@ -70,7 +74,9 @@ private static void RegisterLinuxServices(IServiceCollection services) private static void RegisterWindowsServices(IServiceCollection services) { services - .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() .AddScoped() .AddScoped() .AddScoped() @@ -80,8 +86,10 @@ private static void RegisterWindowsServices(IServiceCollection services) private static void RegisterMacOsServices(IServiceCollection services) { services + .AddScoped() + .AddScoped() + .AddScoped() .AddScoped() - .AddScoped() .AddScoped() .AddScoped() .AddScoped(); diff --git a/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs b/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs index 3be487b..40b9ea7 100644 --- a/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using YMouseButtonControl.Core.ViewModels.AppViewModel; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog; using YMouseButtonControl.Core.ViewModels.LayerViewModel; using YMouseButtonControl.Core.ViewModels.MainWindow; using YMouseButtonControl.Core.ViewModels.ProfilesInformationViewModel; diff --git a/YMouseButtonControl/Views/MainWindow.axaml.cs b/YMouseButtonControl/Views/MainWindow.axaml.cs index 4b815cd..2c2b818 100644 --- a/YMouseButtonControl/Views/MainWindow.axaml.cs +++ b/YMouseButtonControl/Views/MainWindow.axaml.cs @@ -3,6 +3,7 @@ using Avalonia; using Avalonia.ReactiveUI; using ReactiveUI; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog; using YMouseButtonControl.Core.ViewModels.MainWindow; using YMouseButtonControl.Core.Views; using YMouseButtonControl.Views.Dialogs; diff --git a/YMouseButtonControl/Views/MouseButtonComboControl.axaml.cs b/YMouseButtonControl/Views/MouseButtonComboControl.axaml.cs index 7ea5c77..af28a42 100644 --- a/YMouseButtonControl/Views/MouseButtonComboControl.axaml.cs +++ b/YMouseButtonControl/Views/MouseButtonComboControl.axaml.cs @@ -6,6 +6,7 @@ using ReactiveUI; using YMouseButtonControl.Core.ViewModels.LayerViewModel; using YMouseButtonControl.Core.ViewModels.Models; +using YMouseButtonControl.Core.ViewModels.MouseComboViewModel; using YMouseButtonControl.Views.Dialogs; namespace YMouseButtonControl.Views; From ff5af6818c201f49abab9c7e92e263fa00407f38 Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sun, 22 Dec 2024 09:18:26 -0500 Subject: [PATCH 12/39] Add StartMinimized Query Add UpdateStartsMinimizedCommand --- .../UpdateStartsMinimized.cs | 22 +++++++++++ .../GlobalSettingsDialogViewModel.cs | 26 +++++++------ .../StartsMinimized/StartsMinimized.cs | 35 ++++++++++++++++++ YMouseButtonControl.db-shm | Bin 0 -> 32768 bytes YMouseButtonControl.db-wal | Bin 0 -> 28872 bytes .../ServicesBootstrapper.cs | 4 ++ .../Views/Dialogs/GlobalSettingsDialog.axaml | 2 +- 7 files changed, 76 insertions(+), 13 deletions(-) create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs create mode 100644 YMouseButtonControl.db-shm create mode 100644 YMouseButtonControl.db-wal diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs new file mode 100644 index 0000000..4e4770c --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using YMouseButtonControl.Infrastructure.Context; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.UpdateStartsMinimized; + +public interface IUpdateStartsMinimized +{ + Task ExecuteAsync(UpdateStartsMinimized.Command c); +} + +public sealed class UpdateStartsMinimized(YMouseButtonControlDbContext db) : IUpdateStartsMinimized +{ + public sealed record Command(bool Value); + + public async Task ExecuteAsync(Command c) + { + var ent = await db.SettingBools.FirstAsync(x => x.Name == "StartMinimized"); + ent.BoolValue = c.Value; + await db.SaveChangesAsync(); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs index 70a3d1f..997e795 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs @@ -9,7 +9,9 @@ using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.UpdateStartsMinimized; using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartsMinimized; using YMouseButtonControl.Core.ViewModels.Models; namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog; @@ -18,7 +20,7 @@ public interface IGlobalSettingsDialogViewModel; public class GlobalSettingsDialogViewModel : DialogBase, IGlobalSettingsDialogViewModel { - private SettingBoolVm _startMinimizedSetting; + private StartsMinimized.StartsMinimizedResponse _startMinimizedSetting; private bool _loggingEnabled; private bool _startMenuChecked; private SettingIntVm _themeSetting; @@ -27,6 +29,8 @@ public class GlobalSettingsDialogViewModel : DialogBase, IGlobalSettingsDialogVi private readonly ObservableAsPropertyHelper? _applyIsExec; public GlobalSettingsDialogViewModel( + IStartsMinimized startsMinimized, + IUpdateStartsMinimized updateStartsMinimized, IStartMenuInstallerStatus startupMenuInstallerStatus, IStartMenuInstall startMenuInstall, IStartMenuUninstall startMenuUninstall, @@ -38,9 +42,7 @@ IThemeService themeService { StartMenuEnabled = !OperatingSystem.IsMacOS(); _startMenuChecked = StartMenuEnabled && startupMenuInstallerStatus.InstallStatus(); - _startMinimizedSetting = - settingsService.GetSetting("StartMinimized") as SettingBoolVm - ?? throw new Exception("Error retrieving StartMinimized setting"); + _startMinimizedSetting = startsMinimized.GetStartsMinimized(); _loggingEnabled = enableLoggingService.GetLoggingState(); _themeSetting = settingsService.GetSetting("Theme") as SettingIntVm @@ -52,10 +54,8 @@ IThemeService themeService this.WhenAnyValue(x => x.SelectedTheme).Subscribe(x => ThemeSetting.IntValue = x.Id); var startMinimizedChanged = this.WhenAnyValue( - x => x.StartMinimized.BoolValue, - selector: val => - settingsService.GetSetting("StartMinimized") is not SettingBoolVm curVal - || curVal.BoolValue != val + x => x.StartMinimized.Value, + selector: val => startsMinimized.GetStartsMinimized().Value != val ); var loggingChanged = this.WhenAnyValue( x => x.LoggingEnabled, @@ -77,8 +77,8 @@ IThemeService themeService .Merge(startMenuChanged) .Merge(applyIsExecObs) .Merge(themeChanged); - ApplyCommand = ReactiveCommand.Create( - () => + ApplyCommand = ReactiveCommand.CreateFromTask( + async () => { if (LoggingEnabled != enableLoggingService.GetLoggingState()) { @@ -107,7 +107,9 @@ IThemeService themeService } } - settingsService.UpdateSetting(StartMinimized); + await updateStartsMinimized.ExecuteAsync( + new UpdateStartsMinimized.Command(_startMinimizedSetting.Value) + ); settingsService.UpdateSetting(ThemeSetting); }, canSave @@ -125,7 +127,7 @@ public bool StartMenuChecked public bool StartMenuEnabled { get; init; } - public SettingBoolVm StartMinimized + public StartsMinimized.StartsMinimizedResponse StartMinimized { get => _startMinimizedSetting; set => this.RaiseAndSetIfChanged(ref _startMinimizedSetting, value); diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs new file mode 100644 index 0000000..6e4c8e7 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs @@ -0,0 +1,35 @@ +using System.Linq; +using Microsoft.EntityFrameworkCore; +using ReactiveUI; +using YMouseButtonControl.Domain.Models; +using YMouseButtonControl.Infrastructure.Context; +using static YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartsMinimized.StartsMinimized; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartsMinimized; + +public interface IStartsMinimized +{ + StartsMinimizedResponse GetStartsMinimized(); +} + +public class StartsMinimized(YMouseButtonControlDbContext db) : IStartsMinimized +{ + public class StartsMinimizedResponse : ReactiveObject + { + private bool _value; + + public StartsMinimizedResponse(SettingBool settingBool) + { + Value = settingBool.BoolValue; + } + + public bool Value + { + get => _value; + set => this.RaiseAndSetIfChanged(ref _value, value); + } + } + + public StartsMinimizedResponse GetStartsMinimized() => + new(db.SettingBools.AsNoTracking().First(x => x.Name == "StartMinimized")); +} diff --git a/YMouseButtonControl.db-shm b/YMouseButtonControl.db-shm new file mode 100644 index 0000000000000000000000000000000000000000..78387bec32546e249b5baf3231cef85f852f1b37 GIT binary patch literal 32768 zcmeI)y9vTj7zJQo(Za^^f-?v%U}K}h2(Dt`0ye1}#>xT2Aq0hZe-*K{&HWA>0wE9b zr9bI1>qNTmPDc3{9Z#F;zPZlVkNUV~i`X1@yD zBV#{?z~c*C;=*e}mxFJ&UXn&&2MZEF0!RP}AOR$R1pYAsvx3hbO~?7!2g;REZGU$A z?!KC78kIqHdb(U0pV>WJHO9)imK|-Z_owqps;J1>Tt?Y0#}+s)CJ*K0SmV(#d2P%N z9E%^@@AXIHasEWYRQKpwW820(pQT$&^$jRZ!iHL8D6#Bl3{I`6Y*zAeZm1~dwhau( z>7iVqm`_2y92?&1>S#zwC{vPQRhJMX+$lR|l_rmLnlN_EVtF{u>~Olyvi&; zcWRVZE2G9#`Jh&BtyCywCm~1Vf~IRFI0;8ciyzbO(~Z*PP_;Z>uBdvw^V!OD&2${# z2$w0(l&a+^Xlfc&2Cp%ob6EP_!@}~)*Tgj(XWJ3anrM+bj&aXs~l6WWwEGiSYxsWw*$!R{f& z*fDoZt(-aqBR!W|jdWstYH4!3YSbz)BuyJ^DUVO+@PQF%@I&v8bc_CIR~LUQQtw?s zGfjF?v#qDGhphVE`grT8zthXR$dg!~Vdzh)dhIsXM7Cls;4PR{=(^RwzJ`I(u;7a( z68w%jp_#ope8Jm2qwTF}m6GP#6&rZDoNFsEhU?(S_|Xx*PW?DvkIC|oZH0y?&NRJ; z%woar;-Kf@!mC zR9u&Xgw{W*ul>|-6IACv5RL< z!3eFq*d?*2GoVBDcL3PDzy*K%qbFAVxs%Qd2y|ZHE1VO!KL;Jp3JD+qB!C2v01`j~ zNB{{S0VIF~kbp%XD)_l*H@w(ip9ioe0N^DQQRe+ze06~13Z_~$2g?z zy**HXRb8~Hly1@mJJN=3RIQp)iLOXME1*k0+Aa3Hz|no1o{l^-a*oam^aKe9ZxMV< z-XJfK{bU!}MAnd&@U`$~;djF?h7W~zg)`x`;nvVkp)W)4gqzV6 z(&Wn3cDi&e9>^Ky1gw{5`PyaX13|w-aFtyz zCH+kVSK59q;dcvmF((N6U4ko^4+MPFC(N_v|Jw%dL#;dKi}m=grOF2SYD2ZA1lV4GbpB|S|9m)L$T;c*KtW=;_FxC9q5 z9|(#LL1NcSNwJAw*!FV?(JdHaP7oAbf7-^kH67F}qb5pCJ2eq%mQvG34Xh#{ q@r$WhL=B-POihTIAT_Pjv``~a6QIUVjgJ~HH6Ch2Y6MY~q`v?)&&xLe literal 0 HcmV?d00001 diff --git a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs index 015c5de..300035c 100644 --- a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs @@ -10,7 +10,9 @@ using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.UpdateStartsMinimized; using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartsMinimized; namespace YMouseButtonControl.DependencyInjection; @@ -25,6 +27,8 @@ public static void RegisterServices(IServiceCollection services) private static void RegisterCommonServices(IServiceCollection services) { services + .AddScoped() + .AddScoped() .AddScoped() .AddScoped() .AddScoped() diff --git a/YMouseButtonControl/Views/Dialogs/GlobalSettingsDialog.axaml b/YMouseButtonControl/Views/Dialogs/GlobalSettingsDialog.axaml index 6364560..3857db3 100644 --- a/YMouseButtonControl/Views/Dialogs/GlobalSettingsDialog.axaml +++ b/YMouseButtonControl/Views/Dialogs/GlobalSettingsDialog.axaml @@ -17,7 +17,7 @@ + IsChecked="{Binding StartMinimized.Value}" /> Date: Sun, 22 Dec 2024 14:09:34 -0500 Subject: [PATCH 13/39] change these to use handlers --- .../StartMenuInstall/IStartMenuInstall.cs | 6 -- .../IStartMenuInstallHandler.cs | 7 ++ .../StartMenuInstall/StartMenuInstallLinux.cs | 69 ++++++++-------- .../StartMenuInstall/StartMenuInstallOsx.cs | 9 ++- .../StartMenuInstallWindows.cs | 81 ++++++++++--------- ...stall.cs => IStartMenuUninstallHandler.cs} | 4 +- .../StartMenuUninstallLinux.cs | 25 +++--- .../StartMenuUninstallOsx.cs | 9 ++- .../StartMenuUninstallWindows.cs | 48 ++++++----- .../UpdateStartsMinimized.cs | 18 ++--- .../GlobalSettingsDialogViewModel.cs | 30 +++---- .../IStartMenuInstallerStatus.cs | 6 -- .../IStartMenuInstallerStatusHandler.cs | 7 ++ .../StartMenuInstallerStatusLinux.cs | 30 +++---- .../StartMenuInstallerStatusOsx.cs | 9 ++- .../StartMenuInstallerStatusWindows.cs | 54 ++++++------- .../StartsMinimized/StartsMinimized.cs | 19 ++--- .../ServicesBootstrapper.cs | 22 ++--- 18 files changed, 234 insertions(+), 219 deletions(-) delete mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstall.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstallHandler.cs rename YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/{IStartMenuUninstall.cs => IStartMenuUninstallHandler.cs} (61%) delete mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatus.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatusHandler.cs diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstall.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstall.cs deleted file mode 100644 index a6dcbf3..0000000 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstall.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; - -public interface IStartMenuInstall -{ - void Install(); -} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstallHandler.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstallHandler.cs new file mode 100644 index 0000000..1ecfd20 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/IStartMenuInstallHandler.cs @@ -0,0 +1,7 @@ +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall +{ + public interface IStartMenuInstallHandler + { + void Execute(); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallLinux.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallLinux.cs index 9704b60..1546c86 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallLinux.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallLinux.cs @@ -3,42 +3,45 @@ namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; -public class StartMenuInstallLinux : IStartMenuInstall +public static class StartMenuInstallLinux { - private const string DesktopFile = """ - [Desktop Entry] - Type=Application - Exec={0} - Path={1} - Hidden=false - NoDisplay=false - X-GNOME-Autostart-enabled=true - Name=YMouseButtonControl - Comment=YMouseButtonControl - """; - - private readonly string _localShare = Environment.GetFolderPath( - Environment.SpecialFolder.LocalApplicationData - ); - - private readonly string _desktopFilePath; - - public StartMenuInstallLinux() + public sealed class Handler : IStartMenuInstallHandler { - var applicationsDir = Path.Combine(_localShare, "applications"); - _desktopFilePath = Path.Combine(applicationsDir, "YMouseButtonControl.desktop"); - } - - public void Install() => - File.WriteAllText( - _desktopFilePath, - string.Format(DesktopFile, GetCurExePath(), GetCurExeParentPath()) + private const string DesktopFile = """ + [Desktop Entry] + Type=Application + Exec={0} + Path={1} + Hidden=false + NoDisplay=false + X-GNOME-Autostart-enabled=true + Name=YMouseButtonControl + Comment=YMouseButtonControl + """; + + private readonly string _localShare = Environment.GetFolderPath( + Environment.SpecialFolder.LocalApplicationData ); - private static string GetCurExeParentPath() => - Path.GetDirectoryName(GetCurExePath()) - ?? throw new Exception("Error retrieving parent of process path"); + private readonly string _desktopFilePath; + + public Handler() + { + var applicationsDir = Path.Combine(_localShare, "applications"); + _desktopFilePath = Path.Combine(applicationsDir, "YMouseButtonControl.desktop"); + } - private static string GetCurExePath() => - Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + public void Execute() => + File.WriteAllText( + _desktopFilePath, + string.Format(DesktopFile, GetCurExePath(), GetCurExeParentPath()) + ); + + private static string GetCurExeParentPath() => + Path.GetDirectoryName(GetCurExePath()) + ?? throw new Exception("Error retrieving parent of process path"); + + private static string GetCurExePath() => + Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + } } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallOsx.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallOsx.cs index 2456bd2..cd3e248 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallOsx.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallOsx.cs @@ -2,10 +2,13 @@ namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; -public class StartMenuInstallOsx : IStartMenuInstall +public static class StartMenuInstallOsx { - public void Install() + public sealed class Handler : IStartMenuInstallHandler { - throw new NotImplementedException(); + public void Execute() + { + throw new NotImplementedException(); + } } } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallWindows.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallWindows.cs index cd0bf36..2343ade 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallWindows.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuInstall/StartMenuInstallWindows.cs @@ -4,54 +4,57 @@ namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; -public class StartMenuInstallWindows : IStartMenuInstall +public static class StartMenuInstallWindows { - private readonly string _roamingAppDataFolder = Environment.GetFolderPath( - Environment.SpecialFolder.ApplicationData - ); - - private readonly string _roamingYMouseButtonsFolder; - - private readonly string _roamingYmouseButtonsShortcutPath; - - public StartMenuInstallWindows() + public sealed class Handler : IStartMenuInstallHandler { - _roamingYMouseButtonsFolder = Path.Combine( - _roamingAppDataFolder, - "Microsoft", - "Windows", - "Start Menu", - "Programs", - "YMouseButtonControl" + private readonly string _roamingAppDataFolder = Environment.GetFolderPath( + Environment.SpecialFolder.ApplicationData ); - _roamingYmouseButtonsShortcutPath = Path.Combine( - _roamingYMouseButtonsFolder, - "YMouseButtonControl.lnk" - ); - } - public void Install() - { - if (File.Exists(_roamingYmouseButtonsShortcutPath)) + private readonly string _roamingYMouseButtonsFolder; + + private readonly string _roamingYmouseButtonsShortcutPath; + + public Handler() { - File.Delete(_roamingYmouseButtonsShortcutPath); + _roamingYMouseButtonsFolder = Path.Combine( + _roamingAppDataFolder, + "Microsoft", + "Windows", + "Start Menu", + "Programs", + "YMouseButtonControl" + ); + _roamingYmouseButtonsShortcutPath = Path.Combine( + _roamingYMouseButtonsFolder, + "YMouseButtonControl.lnk" + ); } - if (!Directory.Exists(_roamingYMouseButtonsFolder)) + public void Execute() { - Directory.CreateDirectory(_roamingYMouseButtonsFolder); + if (File.Exists(_roamingYmouseButtonsShortcutPath)) + { + File.Delete(_roamingYmouseButtonsShortcutPath); + } + + if (!Directory.Exists(_roamingYMouseButtonsFolder)) + { + Directory.CreateDirectory(_roamingYMouseButtonsFolder); + } + + using var shortcut = new WindowsShortcut(); + shortcut.Path = GetCurExePath(); + shortcut.WorkingDirectory = GetCurExeParentPath(); + shortcut.Save(_roamingYmouseButtonsShortcutPath); } - using var shortcut = new WindowsShortcut(); - shortcut.Path = GetCurExePath(); - shortcut.WorkingDirectory = GetCurExeParentPath(); - shortcut.Save(_roamingYmouseButtonsShortcutPath); - } + private static string GetCurExeParentPath() => + Path.GetDirectoryName(GetCurExePath()) + ?? throw new Exception("Error retrieving parent of process path"); - private static string GetCurExeParentPath() => - Path.GetDirectoryName(GetCurExePath()) - ?? throw new Exception("Error retrieving parent of process path"); - - private static string GetCurExePath() => - Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + private static string GetCurExePath() => + Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + } } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/IStartMenuUninstall.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/IStartMenuUninstallHandler.cs similarity index 61% rename from YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/IStartMenuUninstall.cs rename to YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/IStartMenuUninstallHandler.cs index 9cc1dd1..cb07b3b 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/IStartMenuUninstall.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/IStartMenuUninstallHandler.cs @@ -1,7 +1,7 @@ namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall { - public interface IStartMenuUninstall + public interface IStartMenuUninstallHandler { - void Uninstall(); + void Execute(); } } \ No newline at end of file diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallLinux.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallLinux.cs index 781f70a..054ff00 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallLinux.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallLinux.cs @@ -3,19 +3,22 @@ namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; -public class StartMenuUninstallLinux : IStartMenuUninstall +public static class StartMenuUninstallLinux { - private readonly string _localShare = Environment.GetFolderPath( - Environment.SpecialFolder.LocalApplicationData - ); + public sealed class Handler : IStartMenuUninstallHandler + { + private readonly string _localShare = Environment.GetFolderPath( + Environment.SpecialFolder.LocalApplicationData + ); - private readonly string _desktopFilePath; + private readonly string _desktopFilePath; - public StartMenuUninstallLinux() - { - var applicationsDir = Path.Combine(_localShare, "applications"); - _desktopFilePath = Path.Combine(applicationsDir, "YMouseButtonControl.desktop"); - } + public Handler() + { + var applicationsDir = Path.Combine(_localShare, "applications"); + _desktopFilePath = Path.Combine(applicationsDir, "YMouseButtonControl.desktop"); + } - public void Uninstall() => File.Delete(_desktopFilePath); + public void Execute() => File.Delete(_desktopFilePath); + } } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallOsx.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallOsx.cs index a15216b..8dea09c 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallOsx.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallOsx.cs @@ -2,10 +2,13 @@ namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; -public class StartMenuUninstallOsx : IStartMenuUninstall +public static class StartMenuUninstallOsx { - public void Uninstall() + public sealed class Handler : IStartMenuUninstallHandler { - throw new NotImplementedException(); + public void Execute() + { + throw new NotImplementedException(); + } } } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallWindows.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallWindows.cs index 1adea40..0e9eab7 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallWindows.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/StartMenuUninstall/StartMenuUninstallWindows.cs @@ -3,29 +3,35 @@ namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; -public class StartMenuUninstallWindows : IStartMenuUninstall +public static class StartMenuUninstallWindows { - private readonly string _roamingAppDataFolder = Environment.GetFolderPath( - Environment.SpecialFolder.ApplicationData - ); - private readonly string _roamingYMouseButtonsFolder; - private readonly string _roamingYmouseButtonsShortcutPath; - - public StartMenuUninstallWindows() + public sealed class Handler : IStartMenuUninstallHandler { - _roamingYMouseButtonsFolder = Path.Combine( - _roamingAppDataFolder, - "Microsoft", - "Windows", - "Start Menu", - "Programs", - "YMouseButtonControl" - ); - _roamingYmouseButtonsShortcutPath = Path.Combine( - _roamingYMouseButtonsFolder, - "YMouseButtonControl.lnk" + private readonly string _roamingAppDataFolder = Environment.GetFolderPath( + Environment.SpecialFolder.ApplicationData ); - } + private readonly string _roamingYMouseButtonsFolder; + private readonly string _roamingYmouseButtonsShortcutPath; - public void Uninstall() => File.Delete(_roamingYmouseButtonsShortcutPath); + public Handler() + { + _roamingYMouseButtonsFolder = Path.Combine( + _roamingAppDataFolder, + "Microsoft", + "Windows", + "Start Menu", + "Programs", + "YMouseButtonControl" + ); + _roamingYmouseButtonsShortcutPath = Path.Combine( + _roamingYMouseButtonsFolder, + "YMouseButtonControl.lnk" + ); + } + + public void Execute() + { + File.Delete(_roamingYmouseButtonsShortcutPath); + } + } } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs index 4e4770c..ce8b38b 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs @@ -4,19 +4,17 @@ namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.UpdateStartsMinimized; -public interface IUpdateStartsMinimized -{ - Task ExecuteAsync(UpdateStartsMinimized.Command c); -} - -public sealed class UpdateStartsMinimized(YMouseButtonControlDbContext db) : IUpdateStartsMinimized +public static class UpdateStartsMinimized { public sealed record Command(bool Value); - public async Task ExecuteAsync(Command c) + public sealed class Handler(YMouseButtonControlDbContext db) { - var ent = await db.SettingBools.FirstAsync(x => x.Name == "StartMinimized"); - ent.BoolValue = c.Value; - await db.SaveChangesAsync(); + public async Task ExecuteAsync(Command c) + { + var ent = await db.SettingBools.FirstAsync(x => x.Name == "StartMinimized"); + ent.BoolValue = c.Value; + await db.SaveChangesAsync(); + } } } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs index 997e795..59f9e65 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs @@ -20,7 +20,7 @@ public interface IGlobalSettingsDialogViewModel; public class GlobalSettingsDialogViewModel : DialogBase, IGlobalSettingsDialogViewModel { - private StartsMinimized.StartsMinimizedResponse _startMinimizedSetting; + private StartsMinimized.StartsMinimizedVm _startMinimizedSetting; private bool _loggingEnabled; private bool _startMenuChecked; private SettingIntVm _themeSetting; @@ -29,11 +29,11 @@ public class GlobalSettingsDialogViewModel : DialogBase, IGlobalSettingsDialogVi private readonly ObservableAsPropertyHelper? _applyIsExec; public GlobalSettingsDialogViewModel( - IStartsMinimized startsMinimized, - IUpdateStartsMinimized updateStartsMinimized, - IStartMenuInstallerStatus startupMenuInstallerStatus, - IStartMenuInstall startMenuInstall, - IStartMenuUninstall startMenuUninstall, + StartsMinimized.Handler startsMinimizedHandler, + UpdateStartsMinimized.Handler updateStartsMinimizedHandler, + IStartMenuInstallerStatusHandler startupMenuInstallerStatusHandler, + IStartMenuInstallHandler startMenuInstallHandler, + IStartMenuUninstallHandler startMenuUninstallHandler, IEnableLoggingService enableLoggingService, ISettingsService settingsService, IThemeService themeService @@ -41,8 +41,8 @@ IThemeService themeService : base(themeService) { StartMenuEnabled = !OperatingSystem.IsMacOS(); - _startMenuChecked = StartMenuEnabled && startupMenuInstallerStatus.InstallStatus(); - _startMinimizedSetting = startsMinimized.GetStartsMinimized(); + _startMenuChecked = StartMenuEnabled && startupMenuInstallerStatusHandler.Execute(); + _startMinimizedSetting = startsMinimizedHandler.Execute(); _loggingEnabled = enableLoggingService.GetLoggingState(); _themeSetting = settingsService.GetSetting("Theme") as SettingIntVm @@ -55,7 +55,7 @@ IThemeService themeService var startMinimizedChanged = this.WhenAnyValue( x => x.StartMinimized.Value, - selector: val => startsMinimized.GetStartsMinimized().Value != val + selector: val => startsMinimizedHandler.Execute().Value != val ); var loggingChanged = this.WhenAnyValue( x => x.LoggingEnabled, @@ -63,7 +63,7 @@ IThemeService themeService ); var startMenuChanged = this.WhenAnyValue( x => x.StartMenuChecked, - selector: val => StartMenuEnabled && val != startupMenuInstallerStatus.InstallStatus() + selector: val => StartMenuEnabled && val != startupMenuInstallerStatusHandler.Execute() ); var themeChanged = this.WhenAnyValue( x => x.ThemeSetting.IntValue, @@ -94,20 +94,20 @@ IThemeService themeService if ( StartMenuEnabled - && StartMenuChecked != startupMenuInstallerStatus.InstallStatus() + && StartMenuChecked != startupMenuInstallerStatusHandler.Execute() ) { if (StartMenuChecked) { - startMenuInstall.Install(); + startMenuInstallHandler.Execute(); } else { - startMenuUninstall.Uninstall(); + startMenuUninstallHandler.Execute(); } } - await updateStartsMinimized.ExecuteAsync( + await updateStartsMinimizedHandler.ExecuteAsync( new UpdateStartsMinimized.Command(_startMinimizedSetting.Value) ); settingsService.UpdateSetting(ThemeSetting); @@ -127,7 +127,7 @@ public bool StartMenuChecked public bool StartMenuEnabled { get; init; } - public StartsMinimized.StartsMinimizedResponse StartMinimized + public StartsMinimized.StartsMinimizedVm StartMinimized { get => _startMinimizedSetting; set => this.RaiseAndSetIfChanged(ref _startMinimizedSetting, value); diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatus.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatus.cs deleted file mode 100644 index 58276d8..0000000 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatus.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; - -public interface IStartMenuInstallerStatus -{ - public bool InstallStatus(); -} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatusHandler.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatusHandler.cs new file mode 100644 index 0000000..33b8d15 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/IStartMenuInstallerStatusHandler.cs @@ -0,0 +1,7 @@ +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus +{ + public interface IStartMenuInstallerStatusHandler + { + bool Execute(); + } +} \ No newline at end of file diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusLinux.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusLinux.cs index 19d5a52..af94a93 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusLinux.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusLinux.cs @@ -3,23 +3,23 @@ namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; -public class StartMenuInstallerStatusLinux : IStartMenuInstallerStatus +public static class StartMenuInstallerStatusLinux { - private readonly string _localShare = Environment.GetFolderPath( - Environment.SpecialFolder.LocalApplicationData - ); - private readonly string _desktopFilePath; - - public StartMenuInstallerStatusLinux() + public sealed class Handler : IStartMenuInstallerStatusHandler { - var applicationsDir = Path.Combine(_localShare, "applications"); - _desktopFilePath = Path.Combine(applicationsDir, "YMouseButtonControl.desktop"); - } + private readonly string _localShare = Environment.GetFolderPath( + Environment.SpecialFolder.LocalApplicationData + ); - public bool InstallStatus() => - File.Exists(_desktopFilePath) - && File.ReadAllText(_desktopFilePath).Contains($"Exec={GetCurExePath()}"); + public bool Execute() + { + var applicationsDir = Path.Combine(_localShare, "applications"); + var desktopFilePath = Path.Combine(applicationsDir, "YMouseButtonControl.desktop"); + return File.Exists(desktopFilePath) + && File.ReadAllText(desktopFilePath).Contains($"Exec={GetCurExePath()}"); + } - private static string GetCurExePath() => - Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + private static string GetCurExePath() => + Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + } } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusOsx.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusOsx.cs index 1e24be4..3a19ede 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusOsx.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusOsx.cs @@ -1,9 +1,12 @@ namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; -public class StartMenuInstallerStatusOsx : IStartMenuInstallerStatus +public static class StartMenuInstallerStatusOsx { - public bool InstallStatus() + public sealed class Handler : IStartMenuInstallerStatusHandler { - throw new System.NotImplementedException(); + public bool Execute() + { + throw new System.NotImplementedException(); + } } } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusWindows.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusWindows.cs index 65291da..82296f2 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusWindows.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartMenuInstallerStatus/StartMenuInstallerStatusWindows.cs @@ -4,40 +4,34 @@ namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; -public class StartMenuInstallerStatusWindows : IStartMenuInstallerStatus +public static class StartMenuInstallerStatusWindows { - private readonly string _roamingAppDataFolder = Environment.GetFolderPath( - Environment.SpecialFolder.ApplicationData - ); - - private readonly string _roamingYMouseButtonsFolder; - - private readonly string _roamingYmouseButtonsShortcutPath; - - public StartMenuInstallerStatusWindows() - { - _roamingYMouseButtonsFolder = Path.Combine( - _roamingAppDataFolder, - "Microsoft", - "Windows", - "Start Menu", - "Programs", - "YMouseButtonControl" - ); - _roamingYmouseButtonsShortcutPath = Path.Combine( - _roamingYMouseButtonsFolder, - "YMouseButtonControl.lnk" - ); - } - - public bool InstallStatus() + public sealed class Handler : IStartMenuInstallerStatusHandler { - if (!File.Exists(_roamingYmouseButtonsShortcutPath)) + public bool Execute() { - return false; + var roamingAppDataFolder = Environment.GetFolderPath( + Environment.SpecialFolder.ApplicationData + ); + var roamingYMouseButtonsFolder = Path.Combine( + roamingAppDataFolder, + "Microsoft", + "Windows", + "Start Menu", + "Programs", + "YMouseButtonControl" + ); + var roamingYmouseButtonsShortcutPath = Path.Combine( + roamingYMouseButtonsFolder, + "YMouseButtonControl.lnk" + ); + if (!File.Exists(roamingYmouseButtonsShortcutPath)) + { + return false; + } + using var shortcut = WindowsShortcut.Load(roamingYmouseButtonsShortcutPath); + return shortcut.Path == GetCurExePath(); } - using var shortcut = WindowsShortcut.Load(_roamingYmouseButtonsShortcutPath); - return shortcut.Path == GetCurExePath(); } private static string GetCurExePath() => diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs index 6e4c8e7..d90c817 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs @@ -3,22 +3,16 @@ using ReactiveUI; using YMouseButtonControl.Domain.Models; using YMouseButtonControl.Infrastructure.Context; -using static YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartsMinimized.StartsMinimized; namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartsMinimized; -public interface IStartsMinimized +public static class StartsMinimized { - StartsMinimizedResponse GetStartsMinimized(); -} - -public class StartsMinimized(YMouseButtonControlDbContext db) : IStartsMinimized -{ - public class StartsMinimizedResponse : ReactiveObject + public sealed class StartsMinimizedVm : ReactiveObject { private bool _value; - public StartsMinimizedResponse(SettingBool settingBool) + public StartsMinimizedVm(SettingBool settingBool) { Value = settingBool.BoolValue; } @@ -30,6 +24,9 @@ public bool Value } } - public StartsMinimizedResponse GetStartsMinimized() => - new(db.SettingBools.AsNoTracking().First(x => x.Name == "StartMinimized")); + public sealed class Handler(YMouseButtonControlDbContext db) + { + public StartsMinimizedVm Execute() => + new(db.SettingBools.AsNoTracking().First(x => x.Name == "StartMinimized")); + } } diff --git a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs index 300035c..f2d4a0f 100644 --- a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs @@ -27,8 +27,8 @@ public static void RegisterServices(IServiceCollection services) private static void RegisterCommonServices(IServiceCollection services) { services - .AddScoped() - .AddScoped() + .AddScoped() + .AddScoped() .AddScoped() .AddScoped() .AddScoped() @@ -58,9 +58,9 @@ private static void RegisterPlatformSpecificServices(IServiceCollection services private static void RegisterLinuxServices(IServiceCollection services) { services - .AddScoped() - .AddScoped() - .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() .AddScoped() .AddScoped() .AddScoped(); @@ -78,9 +78,9 @@ private static void RegisterLinuxServices(IServiceCollection services) private static void RegisterWindowsServices(IServiceCollection services) { services - .AddScoped() - .AddScoped() - .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() .AddScoped() .AddScoped() .AddScoped() @@ -90,9 +90,9 @@ private static void RegisterWindowsServices(IServiceCollection services) private static void RegisterMacOsServices(IServiceCollection services) { services - .AddScoped() - .AddScoped() - .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() .AddScoped() .AddScoped() .AddScoped() From e94c9cbfc1a65b61a7c8b24a0e8232494289834e Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sun, 22 Dec 2024 15:57:23 -0500 Subject: [PATCH 14/39] theme variant --- .../Services/Logging/EnableLoggingService.cs | 102 ------------------ .../Services/Theme/ThemeService.cs | 6 +- .../ViewModels/DialogBase.cs | 6 +- .../Commands/Logging/DisableLogging.cs | 34 ++++++ .../Commands/Logging/EnableLogging.cs | 56 ++++++++++ .../Commands/Settings/UpdateSetting.cs | 36 +++++++ .../UpdateStartsMinimized.cs | 20 ---- ...lobalSettingsDialogHandlerRegistrations.cs | 47 ++++++++ .../GlobalSettingsDialogViewModel.cs | 90 +++++++++------- .../Queries/Logging/GetLoggingState.cs | 29 +++++ .../Queries/Settings/GetBoolSetting.cs | 21 ++++ .../Queries/Settings/GetIntSetting.cs | 26 +++++ .../Queries/Settings/Models/Query.cs | 3 + .../StartsMinimized/StartsMinimized.cs | 32 ------ .../Queries/Themes/GetThemeVariant.cs | 24 +++++ .../Queries/Themes/ListThemes.cs | 20 ++++ .../ShowSimulatedKeystrokesDialogService.cs | 8 +- .../SimulatedKeystrokesDialogViewModel.cs | 2 - .../ProcessSelectorDialogViewModel.cs | 3 - YMouseButtonControl.db-shm | Bin 32768 -> 32768 bytes YMouseButtonControl.db-wal | Bin 28872 -> 0 bytes .../ServicesBootstrapper.cs | 23 +--- .../Views/Dialogs/GlobalSettingsDialog.axaml | 2 +- 23 files changed, 358 insertions(+), 232 deletions(-) delete mode 100644 YMouseButtonControl.Core/Services/Logging/EnableLoggingService.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Logging/DisableLogging.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Logging/EnableLogging.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Settings/UpdateSetting.cs delete mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogHandlerRegistrations.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Logging/GetLoggingState.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/GetBoolSetting.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/GetIntSetting.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/Models/Query.cs delete mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Themes/GetThemeVariant.cs create mode 100644 YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Themes/ListThemes.cs diff --git a/YMouseButtonControl.Core/Services/Logging/EnableLoggingService.cs b/YMouseButtonControl.Core/Services/Logging/EnableLoggingService.cs deleted file mode 100644 index 46d2b0b..0000000 --- a/YMouseButtonControl.Core/Services/Logging/EnableLoggingService.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.IO; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace YMouseButtonControl.Core.Services.Logging; - -public interface IEnableLoggingService -{ - void EnableLogging(); - void DisableLogging(); - - /// - /// True = enabled - /// False = disabled - /// - /// - /// - bool GetLoggingState(); -} - -public class EnableLoggingService : IEnableLoggingService -{ - private readonly string _pathToAppSettings = Path.Join( - AppContext.BaseDirectory, - "appsettings.json" - ); - - /// - /// True = enabled - /// False = disabled - /// - /// - /// - public bool GetLoggingState() - { - if (!File.Exists(_pathToAppSettings)) - { - throw new Exception($"Appsettings file not found: {_pathToAppSettings}"); - } - var json = - JsonConvert.DeserializeObject(File.ReadAllText(_pathToAppSettings)) - ?? throw new Exception($"Error deserializing {_pathToAppSettings}"); - return json.GetValue("Logging") != null; - } - - public void EnableLogging() - { - if (!File.Exists(_pathToAppSettings)) - { - throw new Exception($"Appsettings file not found: {_pathToAppSettings}"); - } - var json = - JsonConvert.DeserializeObject(File.ReadAllText(_pathToAppSettings)) - ?? throw new Exception($"Error deserializing {_pathToAppSettings}"); - var toAdd = new JProperty( - "Logging", - new JObject( - new JProperty( - "LogLevel", - new JObject( - new JProperty("Default", "Debug"), - new JProperty("System", "Information"), - new JProperty("Microsoft", "Error") - ) - ), - new JProperty( - "File", - new JObject( - new JProperty("Path", "YMouseButtonControl.log"), - new JProperty("Append", true), - new JProperty("MinLevel", "Information"), - new JProperty("FileSizeLimitBytes", 0), - new JProperty("MaxRollingFiles", 0) - ) - ) - ) - ); - json.Add(toAdd); - File.WriteAllText( - _pathToAppSettings, - JsonConvert.SerializeObject(json, Formatting.Indented) - ); - } - - public void DisableLogging() - { - if (!File.Exists(_pathToAppSettings)) - { - throw new Exception($"Appsettings file not found: {_pathToAppSettings}"); - } - - var json = - JsonConvert.DeserializeObject(File.ReadAllText(_pathToAppSettings)) - ?? throw new Exception($"Error deserializing {_pathToAppSettings}"); - json.Remove("Logging"); - File.WriteAllText( - _pathToAppSettings, - JsonConvert.SerializeObject(json, Formatting.Indented) - ); - } -} diff --git a/YMouseButtonControl.Core/Services/Theme/ThemeService.cs b/YMouseButtonControl.Core/Services/Theme/ThemeService.cs index 270fd7b..1f00969 100644 --- a/YMouseButtonControl.Core/Services/Theme/ThemeService.cs +++ b/YMouseButtonControl.Core/Services/Theme/ThemeService.cs @@ -129,9 +129,8 @@ out var highlightBrush return Brush.Parse(_themeVm.Highlight); } - private ThemeVariant GetThemeVariant() - { - return _themeSetting.IntValue switch + private ThemeVariant GetThemeVariant() => + _themeSetting.IntValue switch { 1 => Application.Current!.ActualThemeVariant == ThemeVariant.Light ? ThemeVariant.Light @@ -142,5 +141,4 @@ private ThemeVariant GetThemeVariant() $"Invalid theme id: {_themeSetting.IntValue}" ), }; - } } diff --git a/YMouseButtonControl.Core/ViewModels/DialogBase.cs b/YMouseButtonControl.Core/ViewModels/DialogBase.cs index e545229..992e367 100644 --- a/YMouseButtonControl.Core/ViewModels/DialogBase.cs +++ b/YMouseButtonControl.Core/ViewModels/DialogBase.cs @@ -1,9 +1,5 @@ using ReactiveUI; -using YMouseButtonControl.Core.Services.Theme; namespace YMouseButtonControl.Core.ViewModels; -public class DialogBase(IThemeService themeService) : ReactiveObject -{ - public IThemeService ThemeService { get; } = themeService; -} +public class DialogBase : ReactiveObject { } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Logging/DisableLogging.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Logging/DisableLogging.cs new file mode 100644 index 0000000..d579902 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Logging/DisableLogging.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.Logging; + +public static class DisableLogging +{ + public sealed class Handler + { + private readonly string _pathToAppSettings = Path.Join( + AppContext.BaseDirectory, + "appsettings.json" + ); + + public void Execute() + { + if (!File.Exists(_pathToAppSettings)) + { + throw new Exception($"Appsettings file not found: {_pathToAppSettings}"); + } + + var json = + JsonConvert.DeserializeObject(File.ReadAllText(_pathToAppSettings)) + ?? throw new Exception($"Error deserializing {_pathToAppSettings}"); + json.Remove("Logging"); + File.WriteAllText( + _pathToAppSettings, + JsonConvert.SerializeObject(json, Formatting.Indented) + ); + } + } +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Logging/EnableLogging.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Logging/EnableLogging.cs new file mode 100644 index 0000000..0a38bd3 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Logging/EnableLogging.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.Logging; + +public static class EnableLogging +{ + public sealed class Handler + { + private readonly string _pathToAppSettings = Path.Join( + AppContext.BaseDirectory, + "appsettings.json" + ); + + public void Execute() + { + if (!File.Exists(_pathToAppSettings)) + { + throw new Exception($"Appsettings file not found: {_pathToAppSettings}"); + } + var json = + JsonConvert.DeserializeObject(File.ReadAllText(_pathToAppSettings)) + ?? throw new Exception($"Error deserializing {_pathToAppSettings}"); + var toAdd = new JProperty( + "Logging", + new JObject( + new JProperty( + "LogLevel", + new JObject( + new JProperty("Default", "Debug"), + new JProperty("System", "Information"), + new JProperty("Microsoft", "Error") + ) + ), + new JProperty( + "File", + new JObject( + new JProperty("Path", "YMouseButtonControl.log"), + new JProperty("Append", true), + new JProperty("MinLevel", "Information"), + new JProperty("FileSizeLimitBytes", 0), + new JProperty("MaxRollingFiles", 0) + ) + ) + ) + ); + json.Add(toAdd); + File.WriteAllText( + _pathToAppSettings, + JsonConvert.SerializeObject(json, Formatting.Indented) + ); + } + } +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Settings/UpdateSetting.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Settings/UpdateSetting.cs new file mode 100644 index 0000000..3d03940 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/Settings/UpdateSetting.cs @@ -0,0 +1,36 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using YMouseButtonControl.Infrastructure.Context; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.Settings; + +public static class UpdateSetting +{ + public sealed record Command(string Name, T Value); + + public sealed class Handler(YMouseButtonControlDbContext db) + { + public async Task ExecuteAsync(Command c) + { + switch (c.Value) + { + case string: + var entStr = await db.SettingStrings.FirstAsync(x => x.Name == c.Name); + entStr.StringValue = c.Value as string; + break; + case int: + var entInt = await db.SettingInts.FirstAsync(x => x.Name == c.Name); + entInt.IntValue = Convert.ToInt32(c.Value); + break; + case bool: + var entBool = await db.SettingBools.FirstAsync(x => x.Name == c.Name); + entBool.BoolValue = Convert.ToBoolean(c.Value); + break; + default: + throw new ArgumentOutOfRangeException(nameof(c.Value)); + } + await db.SaveChangesAsync(); + } + } +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs deleted file mode 100644 index ce8b38b..0000000 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Commands/UpdateStartsMinimized/UpdateStartsMinimized.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using YMouseButtonControl.Infrastructure.Context; - -namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.UpdateStartsMinimized; - -public static class UpdateStartsMinimized -{ - public sealed record Command(bool Value); - - public sealed class Handler(YMouseButtonControlDbContext db) - { - public async Task ExecuteAsync(Command c) - { - var ent = await db.SettingBools.FirstAsync(x => x.Name == "StartMinimized"); - ent.BoolValue = c.Value; - await db.SaveChangesAsync(); - } - } -} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogHandlerRegistrations.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogHandlerRegistrations.cs new file mode 100644 index 0000000..4e9f914 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogHandlerRegistrations.cs @@ -0,0 +1,47 @@ +using Microsoft.Extensions.DependencyInjection; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.Logging; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.Settings; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Logging; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Settings; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Themes; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog; + +public static class GlobalSettingsDialogHandlerRegistrations +{ + public static void RegisterCommon(IServiceCollection services) + { + services + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped.Handler>() + .AddScoped.Handler>() + .AddScoped.Handler>(); + } + + public static void RegisterWindows(IServiceCollection services) => + services + .AddScoped() + .AddScoped() + .AddScoped(); + + public static void RegisterLinux(IServiceCollection services) => + services + .AddScoped() + .AddScoped() + .AddScoped(); + + public static void RegisterOsx(IServiceCollection services) => + services + .AddScoped() + .AddScoped() + .AddScoped(); +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs index 59f9e65..982cf32 100644 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/GlobalSettingsDialogViewModel.cs @@ -3,16 +3,16 @@ using System.Linq; using System.Reactive; using System.Reactive.Linq; +using Avalonia.Styling; using ReactiveUI; -using YMouseButtonControl.Core.Services.Logging; -using YMouseButtonControl.Core.Services.Settings; -using YMouseButtonControl.Core.Services.Theme; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.Logging; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.Settings; using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; -using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.UpdateStartsMinimized; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Logging; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Settings; using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; -using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartsMinimized; -using YMouseButtonControl.Core.ViewModels.Models; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Themes; namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog; @@ -20,56 +20,64 @@ public interface IGlobalSettingsDialogViewModel; public class GlobalSettingsDialogViewModel : DialogBase, IGlobalSettingsDialogViewModel { - private StartsMinimized.StartsMinimizedVm _startMinimizedSetting; + private GetBoolSetting.BoolSettingVm _startMinimizedSetting; private bool _loggingEnabled; private bool _startMenuChecked; - private SettingIntVm _themeSetting; - private ObservableCollection _themeCollection; - private ThemeVm _selectedTheme; + private GetIntSetting.IntSettingVm _themeSetting; + private ObservableCollection _themeCollection; + private ListThemes.ThemeVm _selectedTheme; private readonly ObservableAsPropertyHelper? _applyIsExec; + private readonly ThemeVariant _themeVariant; public GlobalSettingsDialogViewModel( - StartsMinimized.Handler startsMinimizedHandler, - UpdateStartsMinimized.Handler updateStartsMinimizedHandler, + GetBoolSetting.Handler getBoolSettingHandler, IStartMenuInstallerStatusHandler startupMenuInstallerStatusHandler, IStartMenuInstallHandler startMenuInstallHandler, IStartMenuUninstallHandler startMenuUninstallHandler, - IEnableLoggingService enableLoggingService, - ISettingsService settingsService, - IThemeService themeService + EnableLogging.Handler enableLoggingHandler, + DisableLogging.Handler disableLoggingHandler, + GetLoggingState.Handler loggingStateHandler, + GetIntSetting.Handler getIntSettingHandler, + UpdateSetting.Handler updateSettingIntHandler, + UpdateSetting.Handler updateSettingBoolHandler, + GetThemeVariant.Handler getThemeVariantHandler, + ListThemes.Handler listThemesHandler ) - : base(themeService) { + _themeVariant = getThemeVariantHandler.Execute(); StartMenuEnabled = !OperatingSystem.IsMacOS(); _startMenuChecked = StartMenuEnabled && startupMenuInstallerStatusHandler.Execute(); - _startMinimizedSetting = startsMinimizedHandler.Execute(); - _loggingEnabled = enableLoggingService.GetLoggingState(); - _themeSetting = - settingsService.GetSetting("Theme") as SettingIntVm - ?? throw new Exception("Error retrieving Theme setting"); - _themeCollection = [.. themeService.Themes]; - _selectedTheme = _themeCollection.First(x => x.Id == _themeSetting.IntValue); + _startMinimizedSetting = getBoolSettingHandler.Execute( + new Queries.Settings.Models.Query("StartMinimized") + ); + _loggingEnabled = loggingStateHandler.Execute(); + _themeSetting = getIntSettingHandler.Execute(new Queries.Settings.Models.Query("Theme")); + _themeCollection = [.. listThemesHandler.Execute()]; + _selectedTheme = _themeCollection.First(x => x.Id == _themeSetting.Value); // Update the theme setting selected theme value - this.WhenAnyValue(x => x.SelectedTheme).Subscribe(x => ThemeSetting.IntValue = x.Id); + this.WhenAnyValue(x => x.SelectedTheme).Subscribe(x => ThemeSetting.Value = x.Id); var startMinimizedChanged = this.WhenAnyValue( x => x.StartMinimized.Value, - selector: val => startsMinimizedHandler.Execute().Value != val + selector: val => + getBoolSettingHandler + .Execute(new Queries.Settings.Models.Query("StartMinimized")) + .Value != val ); var loggingChanged = this.WhenAnyValue( x => x.LoggingEnabled, - selector: val => val != enableLoggingService.GetLoggingState() + selector: val => val != loggingStateHandler.Execute() ); var startMenuChanged = this.WhenAnyValue( x => x.StartMenuChecked, selector: val => StartMenuEnabled && val != startupMenuInstallerStatusHandler.Execute() ); var themeChanged = this.WhenAnyValue( - x => x.ThemeSetting.IntValue, + x => x.ThemeSetting.Value, selector: val => - settingsService.GetSetting("Theme") is not SettingIntVm curVal - || curVal.IntValue != val + getIntSettingHandler.Execute(new Queries.Settings.Models.Query("Theme")).Value + != val ); var applyIsExecObs = this.WhenAnyValue(x => x.AppIsExec); var canSave = startMinimizedChanged @@ -80,15 +88,15 @@ IThemeService themeService ApplyCommand = ReactiveCommand.CreateFromTask( async () => { - if (LoggingEnabled != enableLoggingService.GetLoggingState()) + if (LoggingEnabled != loggingStateHandler.Execute()) { if (LoggingEnabled) { - enableLoggingService.EnableLogging(); + enableLoggingHandler.Execute(); } else { - enableLoggingService.DisableLogging(); + disableLoggingHandler.Execute(); } } @@ -107,10 +115,12 @@ IThemeService themeService } } - await updateStartsMinimizedHandler.ExecuteAsync( - new UpdateStartsMinimized.Command(_startMinimizedSetting.Value) + await updateSettingBoolHandler.ExecuteAsync( + new UpdateSetting.Command("StartMinimized", StartMinimized.Value) + ); + await updateSettingIntHandler.ExecuteAsync( + new UpdateSetting.Command("Theme", ThemeSetting.Value) ); - settingsService.UpdateSetting(ThemeSetting); }, canSave ); @@ -127,7 +137,7 @@ public bool StartMenuChecked public bool StartMenuEnabled { get; init; } - public StartsMinimized.StartsMinimizedVm StartMinimized + public GetBoolSetting.BoolSettingVm StartMinimized { get => _startMinimizedSetting; set => this.RaiseAndSetIfChanged(ref _startMinimizedSetting, value); @@ -139,23 +149,25 @@ public bool LoggingEnabled set => this.RaiseAndSetIfChanged(ref _loggingEnabled, value); } - public ThemeVm SelectedTheme + public ListThemes.ThemeVm SelectedTheme { get => _selectedTheme; set => this.RaiseAndSetIfChanged(ref _selectedTheme, value); } - public SettingIntVm ThemeSetting + public GetIntSetting.IntSettingVm ThemeSetting { get => _themeSetting; set => this.RaiseAndSetIfChanged(ref _themeSetting, value); } - public ObservableCollection ThemeCollection + public ObservableCollection ThemeCollection { get => _themeCollection; set => this.RaiseAndSetIfChanged(ref _themeCollection, value); } public ReactiveCommand ApplyCommand { get; init; } + + public ThemeVariant ThemeVariant => _themeVariant; } diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Logging/GetLoggingState.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Logging/GetLoggingState.cs new file mode 100644 index 0000000..3a0828e --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Logging/GetLoggingState.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Logging; + +public static class GetLoggingState +{ + public sealed class Handler + { + private readonly string _pathToAppSettings = Path.Join( + AppContext.BaseDirectory, + "appsettings.json" + ); + + public bool Execute() + { + if (!File.Exists(_pathToAppSettings)) + { + throw new Exception($"Appsettings file not found: {_pathToAppSettings}"); + } + var json = + JsonConvert.DeserializeObject(File.ReadAllText(_pathToAppSettings)) + ?? throw new Exception($"Error deserializing {_pathToAppSettings}"); + return json.GetValue("Logging") != null; + } + } +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/GetBoolSetting.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/GetBoolSetting.cs new file mode 100644 index 0000000..12eab05 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/GetBoolSetting.cs @@ -0,0 +1,21 @@ +using System.Linq; +using ReactiveUI; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Settings.Models; +using YMouseButtonControl.Domain.Models; +using YMouseButtonControl.Infrastructure.Context; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Settings; + +public static class GetBoolSetting +{ + public sealed class BoolSettingVm(SettingBool setting) : ReactiveObject + { + public string Name { get; } = setting.Name; + public bool Value { get; } = setting.BoolValue; + } + + public sealed class Handler(YMouseButtonControlDbContext db) + { + public BoolSettingVm Execute(Query q) => new(db.SettingBools.First(x => x.Name == q.Name)); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/GetIntSetting.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/GetIntSetting.cs new file mode 100644 index 0000000..bbc4ee0 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/GetIntSetting.cs @@ -0,0 +1,26 @@ +using System.Linq; +using ReactiveUI; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Settings.Models; +using YMouseButtonControl.Domain.Models; +using YMouseButtonControl.Infrastructure.Context; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Settings; + +public static class GetIntSetting +{ + public sealed class IntSettingVm(SettingInt setting) : ReactiveObject + { + private int _value = setting.IntValue; + public string Name { get; } = setting.Name; + public int Value + { + get => _value; + set => this.RaiseAndSetIfChanged(ref _value, value); + } + } + + public sealed class Handler(YMouseButtonControlDbContext db) + { + public IntSettingVm Execute(Query q) => new(db.SettingInts.First(x => x.Name == q.Name)); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/Models/Query.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/Models/Query.cs new file mode 100644 index 0000000..348ad9f --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Settings/Models/Query.cs @@ -0,0 +1,3 @@ +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Settings.Models; + +public sealed record Query(string Name); diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs deleted file mode 100644 index d90c817..0000000 --- a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/StartsMinimized/StartsMinimized.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Linq; -using Microsoft.EntityFrameworkCore; -using ReactiveUI; -using YMouseButtonControl.Domain.Models; -using YMouseButtonControl.Infrastructure.Context; - -namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartsMinimized; - -public static class StartsMinimized -{ - public sealed class StartsMinimizedVm : ReactiveObject - { - private bool _value; - - public StartsMinimizedVm(SettingBool settingBool) - { - Value = settingBool.BoolValue; - } - - public bool Value - { - get => _value; - set => this.RaiseAndSetIfChanged(ref _value, value); - } - } - - public sealed class Handler(YMouseButtonControlDbContext db) - { - public StartsMinimizedVm Execute() => - new(db.SettingBools.AsNoTracking().First(x => x.Name == "StartMinimized")); - } -} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Themes/GetThemeVariant.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Themes/GetThemeVariant.cs new file mode 100644 index 0000000..e423618 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Themes/GetThemeVariant.cs @@ -0,0 +1,24 @@ +using System; +using System.Linq; +using Avalonia; +using Avalonia.Styling; +using YMouseButtonControl.Infrastructure.Context; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Themes; + +public static class GetThemeVariant +{ + public sealed class Handler(YMouseButtonControlDbContext db) + { + public ThemeVariant Execute() => + db.SettingInts.First(x => x.Name == "Theme").IntValue switch + { + 1 => Application.Current!.ActualThemeVariant == ThemeVariant.Light + ? ThemeVariant.Light + : ThemeVariant.Dark, + 2 => ThemeVariant.Light, + 3 => ThemeVariant.Dark, + _ => throw new ArgumentOutOfRangeException($"Invalid theme id"), + }; + } +} diff --git a/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Themes/ListThemes.cs b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Themes/ListThemes.cs new file mode 100644 index 0000000..4144228 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/GlobalSettingsDialog/Queries/Themes/ListThemes.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using YMouseButtonControl.Infrastructure.Context; + +namespace YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.Themes; + +public class ListThemes +{ + public sealed class ThemeVm(Domain.Models.Theme theme) + { + public int Id { get; } = theme.Id; + public string Name { get; } = theme.Name; + } + + public sealed class Handler(YMouseButtonControlDbContext db) + { + public List Execute() => [.. db.Themes.AsNoTracking().Select(x => new ThemeVm(x))]; + } +} diff --git a/YMouseButtonControl.Core/ViewModels/LayerViewModel/ShowSimulatedKeystrokesDialogService.cs b/YMouseButtonControl.Core/ViewModels/LayerViewModel/ShowSimulatedKeystrokesDialogService.cs index 28c3850..a16e868 100644 --- a/YMouseButtonControl.Core/ViewModels/LayerViewModel/ShowSimulatedKeystrokesDialogService.cs +++ b/YMouseButtonControl.Core/ViewModels/LayerViewModel/ShowSimulatedKeystrokesDialogService.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using ReactiveUI; using YMouseButtonControl.Core.Services.KeyboardAndMouse.Implementations; -using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.Models; using YMouseButtonControl.Domain.Models; @@ -22,10 +21,8 @@ BaseButtonMappingVm mapping ); } -public class ShowSimulatedKeystrokesDialogService( - IMouseListener mouseListener, - IThemeService themeService -) : IShowSimulatedKeystrokesDialogService +public class ShowSimulatedKeystrokesDialogService(IMouseListener mouseListener) + : IShowSimulatedKeystrokesDialogService { public Interaction< SimulatedKeystrokesDialogViewModel, @@ -41,7 +38,6 @@ public Interaction< return await ShowSimulatedKeystrokesPickerInteraction.Handle( new SimulatedKeystrokesDialogViewModel( mouseListener, - themeService, buttonName, mouseButton, mapping as SimulatedKeystrokeVm diff --git a/YMouseButtonControl.Core/ViewModels/LayerViewModel/SimulatedKeystrokesDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/LayerViewModel/SimulatedKeystrokesDialogViewModel.cs index 958cf3a..9fef95f 100644 --- a/YMouseButtonControl.Core/ViewModels/LayerViewModel/SimulatedKeystrokesDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/LayerViewModel/SimulatedKeystrokesDialogViewModel.cs @@ -43,12 +43,10 @@ public class SimulatedKeystrokesDialogViewModel : DialogBase, IDisposable public SimulatedKeystrokesDialogViewModel( IMouseListener mouseListener, - IThemeService themeService, string buttonName, MouseButton mouseButton, SimulatedKeystrokeVm? currentMapping = null ) - : base(themeService) { _title = $"SimulatedKeystrokes - {buttonName}"; _mouseListener = mouseListener; diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs index abfccc2..234d61a 100644 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs @@ -10,7 +10,6 @@ using ReactiveUI; using YMouseButtonControl.Core.Services.Processes; using YMouseButtonControl.Core.Services.Profiles; -using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.Models; using YMouseButtonControl.Domain.Models; @@ -31,10 +30,8 @@ public class ProcessSelectorDialogViewModel : DialogBase, IProcessSelectorDialog public ProcessSelectorDialogViewModel( IProcessMonitorService processMonitorService, - IThemeService themeService, IProfilesService profilesService ) - : base(themeService) { _sourceProcessModels = new SourceList(); _processMonitorService = processMonitorService; diff --git a/YMouseButtonControl.db-shm b/YMouseButtonControl.db-shm index 78387bec32546e249b5baf3231cef85f852f1b37..fe9ac2845eca6fe6da8a63cd096d9cf9e24ece10 100644 GIT binary patch delta 80 zcmZo@U}|V!;+1%$%K!t66BkO0TChv7nNGgVi7p`mlYpuI4+Il)WHxT_bK1B;%N78h CH53H^ delta 209 zcmZo@U}|V!s+V}A%K!q55G=qBq(PWl`akRMoF@hzf0nJ8V0*#++OmcDQ+`M|k*XeO z6c~Wa{Eq~n!V~K`B|%m*0WmWWvj8zG5VHX>`^LstCq~ANjenUKnZP77m}CKytYDH2 KOafK%Y6Ae$PCNks diff --git a/YMouseButtonControl.db-wal b/YMouseButtonControl.db-wal index 8e6c4effb1bcd4ff266d5bace7ce6073d906b15e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 28872 zcmeI5U2GIp6vyXdzoy;Y3zY3rN@2QGWL*?CeZU7v-0n_cL%XfJi-mw8!*<%Po$i$F zZ1|7_3nYXG4T&#kVuC)1F~pAtk%VY`kOwtJgYdwMCVnJFLn8WMj6^(lJ9n6!E(M~A zXwFUdOy{0E=Rfy%&rGv7Gq)QL`;KrAf3u9^7ICy}x$)ZBlbgQSJp0_uowNN*PeK*% ztgpVcEiiuQsgDXz43tex9y6*_swwxv(SpD|F3ZqXfRCRZV-+uKJ!}WI^>~i`X1@yD zBV#{?z~c*C;=*e}mxFJ&UXn&&2MZEF0!RP}AOR$R1pYAsvx3hbO~?7!2g;REZGU$A z?!KC78kIqHdb(U0pV>WJHO9)imK|-Z_owqps;J1>Tt?Y0#}+s)CJ*K0SmV(#d2P%N z9E%^@@AXIHasEWYRQKpwW820(pQT$&^$jRZ!iHL8D6#Bl3{I`6Y*zAeZm1~dwhau( z>7iVqm`_2y92?&1>S#zwC{vPQRhJMX+$lR|l_rmLnlN_EVtF{u>~Olyvi&; zcWRVZE2G9#`Jh&BtyCywCm~1Vf~IRFI0;8ciyzbO(~Z*PP_;Z>uBdvw^V!OD&2${# z2$w0(l&a+^Xlfc&2Cp%ob6EP_!@}~)*Tgj(XWJ3anrM+bj&aXs~l6WWwEGiSYxsWw*$!R{f& z*fDoZt(-aqBR!W|jdWstYH4!3YSbz)BuyJ^DUVO+@PQF%@I&v8bc_CIR~LUQQtw?s zGfjF?v#qDGhphVE`grT8zthXR$dg!~Vdzh)dhIsXM7Cls;4PR{=(^RwzJ`I(u;7a( z68w%jp_#ope8Jm2qwTF}m6GP#6&rZDoNFsEhU?(S_|Xx*PW?DvkIC|oZH0y?&NRJ; z%woar;-Kf@!mC zR9u&Xgw{W*ul>|-6IACv5RL< z!3eFq*d?*2GoVBDcL3PDzy*K%qbFAVxs%Qd2y|ZHE1VO!KL;Jp3JD+qB!C2v01`j~ zNB{{S0VIF~kbp%XD)_l*H@w(ip9ioe0N^DQQRe+ze06~13Z_~$2g?z zy**HXRb8~Hly1@mJJN=3RIQp)iLOXME1*k0+Aa3Hz|no1o{l^-a*oam^aKe9ZxMV< z-XJfK{bU!}MAnd&@U`$~;djF?h7W~zg)`x`;nvVkp)W)4gqzV6 z(&Wn3cDi&e9>^Ky1gw{5`PyaX13|w-aFtyz zCH+kVSK59q;dcvmF((N6U4ko^4+MPFC(N_v|Jw%dL#;dKi}m=grOF2SYD2ZA1lV4GbpB|S|9m)L$T;c*KtW=;_FxC9q5 z9|(#LL1NcSNwJAw*!FV?(JdHaP7oAbf7-^kH67F}qb5pCJ2eq%mQvG34Xh#{ q@r$WhL=B-POihTIAT_Pjv``~a6QIUVjgJ~HH6Ch2Y6MY~q`v?)&&xLe diff --git a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs index f2d4a0f..0dae11f 100644 --- a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs @@ -2,17 +2,12 @@ using System.Runtime.Versioning; using Microsoft.Extensions.DependencyInjection; using YMouseButtonControl.Core.Services.BackgroundTasks; -using YMouseButtonControl.Core.Services.Logging; using YMouseButtonControl.Core.Services.Processes; using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.Services.Settings; using YMouseButtonControl.Core.Services.StartupInstaller; using YMouseButtonControl.Core.Services.Theme; -using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuInstall; -using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.StartMenuUninstall; -using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Commands.UpdateStartsMinimized; -using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartMenuInstallerStatus; -using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog.Queries.StartsMinimized; +using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog; namespace YMouseButtonControl.DependencyInjection; @@ -26,10 +21,8 @@ public static void RegisterServices(IServiceCollection services) private static void RegisterCommonServices(IServiceCollection services) { + GlobalSettingsDialogHandlerRegistrations.RegisterCommon(services); services - .AddScoped() - .AddScoped() - .AddScoped() .AddScoped() .AddScoped() .AddScoped(); @@ -57,10 +50,8 @@ private static void RegisterPlatformSpecificServices(IServiceCollection services private static void RegisterLinuxServices(IServiceCollection services) { + GlobalSettingsDialogHandlerRegistrations.RegisterLinux(services); services - .AddScoped() - .AddScoped() - .AddScoped() .AddScoped() .AddScoped() .AddScoped(); @@ -77,10 +68,8 @@ private static void RegisterLinuxServices(IServiceCollection services) [SupportedOSPlatform("windows5.1.2600")] private static void RegisterWindowsServices(IServiceCollection services) { + GlobalSettingsDialogHandlerRegistrations.RegisterWindows(services); services - .AddScoped() - .AddScoped() - .AddScoped() .AddScoped() .AddScoped() .AddScoped() @@ -89,10 +78,8 @@ private static void RegisterWindowsServices(IServiceCollection services) private static void RegisterMacOsServices(IServiceCollection services) { + GlobalSettingsDialogHandlerRegistrations.RegisterOsx(services); services - .AddScoped() - .AddScoped() - .AddScoped() .AddScoped() .AddScoped() .AddScoped() diff --git a/YMouseButtonControl/Views/Dialogs/GlobalSettingsDialog.axaml b/YMouseButtonControl/Views/Dialogs/GlobalSettingsDialog.axaml index 3857db3..d60e1bc 100644 --- a/YMouseButtonControl/Views/Dialogs/GlobalSettingsDialog.axaml +++ b/YMouseButtonControl/Views/Dialogs/GlobalSettingsDialog.axaml @@ -9,7 +9,7 @@ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="YMouseButtonControl.Views.Dialogs.GlobalSettingsDialog" Title="Global Settings" - RequestedThemeVariant="{Binding ThemeService.ThemeVariant}"> + RequestedThemeVariant="{Binding ThemeVariant}"> From abde216a071748b824fca90a54c30bd664a98d66 Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sun, 22 Dec 2024 17:10:01 -0500 Subject: [PATCH 15/39] Startup installer --- .../AppViewModel/AppHandlerRegistrations.cs | 41 ++++++++++++ .../ViewModels/AppViewModel/AppViewModel.cs | 19 ++++-- .../Install/IInstallHandler.cs | 7 +++ .../StartupInstaller/Install/InstallLinux.cs | 46 ++++++++++++++ .../StartupInstaller/Install/InstallOsx.cs | 51 +++++++++++++++ .../Install/InstallWindows.cs | 32 ++++++++++ .../Uninstall/IUninstallHandler.cs | 7 +++ .../Uninstall/UninstallLinux.cs | 24 +++++++ .../Uninstall/UninstallOsx.cs | 25 ++++++++ .../Uninstall/UninstallWindows.cs | 27 ++++++++ .../CanBeInstalled/CanBeInstalledLinux.cs | 22 +++++++ .../CanBeInstalled/CanBeInstalledOsx.cs | 23 +++++++ .../CanBeInstalled/CanBeInstalledWindows.cs | 9 +++ .../CanBeInstalled/ICanBeInstalledHandler.cs | 7 +++ .../IsInstalled/IIsInstalledHandler.cs | 7 +++ .../IsInstalled/IsInstalledLinux.cs | 41 ++++++++++++ .../IsInstalled/IsInstalledOsx.cs | 30 +++++++++ .../IsInstalled/IsInstalledWindows.cs | 31 ++++++++++ .../StartupInstallerTests.cs | 44 ------------- .../Services/StartupInstallerService.cs | 62 ------------------- .../Services/StartupInstallerService.cs | 57 ----------------- .../StartupInstallerTests.cs | 47 -------------- .../Services/ProcessMonitorService.cs | 5 +- .../Services/StartupInstallerService.cs | 59 ------------------ .../ServicesBootstrapper.cs | 9 +-- 25 files changed, 451 insertions(+), 281 deletions(-) create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/AppHandlerRegistrations.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/IInstallHandler.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallLinux.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallOsx.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallWindows.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/IUninstallHandler.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallLinux.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallOsx.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallWindows.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledLinux.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledOsx.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledWindows.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/ICanBeInstalledHandler.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IIsInstalledHandler.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledLinux.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledOsx.cs create mode 100644 YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledWindows.cs delete mode 100644 YMouseButtonControl.Linux.Tests/StartupInstallerTests.cs delete mode 100644 YMouseButtonControl.Linux/Services/StartupInstallerService.cs delete mode 100644 YMouseButtonControl.MacOS/Services/StartupInstallerService.cs delete mode 100644 YMouseButtonControl.Windows.Tests/StartupInstallerTests.cs delete mode 100644 YMouseButtonControl.Windows/Services/StartupInstallerService.cs diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/AppHandlerRegistrations.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/AppHandlerRegistrations.cs new file mode 100644 index 0000000..6820865 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/AppHandlerRegistrations.cs @@ -0,0 +1,41 @@ +using System.Runtime.Versioning; +using Microsoft.Extensions.DependencyInjection; +using YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Install; +using YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Uninstall; +using YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.CanBeInstalled; +using YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.IsInstalled; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel; + +public static class AppHandlerRegistrations +{ + public static void RegisterCommon(IServiceCollection services) { } + + public static void RegisterLinux(IServiceCollection services) + { + services + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped(); + } + + public static void RegisterOsx(IServiceCollection services) + { + services + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped(); + } + + [SupportedOSPlatform("windows5.1.2600")] + public static void RegisterWindows(IServiceCollection services) + { + services + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped(); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/AppViewModel.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/AppViewModel.cs index 0fb38a9..07b7f70 100644 --- a/YMouseButtonControl.Core/ViewModels/AppViewModel/AppViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/AppViewModel.cs @@ -4,6 +4,10 @@ using Avalonia.Controls.ApplicationLifetimes; using ReactiveUI; using YMouseButtonControl.Core.Services.StartupInstaller; +using YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Install; +using YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Uninstall; +using YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.CanBeInstalled; +using YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.IsInstalled; using YMouseButtonControl.Core.ViewModels.MainWindow; using YMouseButtonControl.Core.Views; @@ -21,13 +25,16 @@ public class AppViewModel : ViewModelBase, IAppViewModel private string _runAtStartupHeader = ""; public AppViewModel( - IStartupInstallerService startupInstallerService, + ICanBeInstalledHandler canBeInstalledHandler, + IIsInstalledHandler isInstalledHandler, + IInstallHandler installHandler, + IUninstallHandler uninstallHandler, IMainWindow mainWindow, IMainWindowViewModel mainWindowViewModel ) { - RunAtStartupIsEnabled = startupInstallerService.ButtonEnabled(); - RunAtStartupIsChecked = startupInstallerService.InstallStatus(); + RunAtStartupIsEnabled = canBeInstalledHandler.Execute(); + RunAtStartupIsChecked = isInstalledHandler.Execute(); RunAtStartupHeader = RunAtStartupIsChecked ? string.Format(RunAtStartupHeaderFmt, RunAtStartupChecked) : string.Format(RunAtStartupHeaderFmt, RunAtStartupNotChecked); @@ -61,10 +68,10 @@ is IClassicDesktopStyleApplicationLifetime lifetime RunAtStartupCommand = ReactiveCommand.Create( () => { - if (startupInstallerService.InstallStatus()) + if (isInstalledHandler.Execute()) { // uninstall - startupInstallerService.Uninstall(); + uninstallHandler.Execute(); RunAtStartupIsChecked = false; RunAtStartupHeader = string.Format( RunAtStartupHeaderFmt, @@ -74,7 +81,7 @@ is IClassicDesktopStyleApplicationLifetime lifetime else { // install - startupInstallerService.Install(); + installHandler.Execute(); RunAtStartupIsChecked = true; RunAtStartupHeader = string.Format(RunAtStartupHeaderFmt, RunAtStartupChecked); } diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/IInstallHandler.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/IInstallHandler.cs new file mode 100644 index 0000000..82b27f8 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/IInstallHandler.cs @@ -0,0 +1,7 @@ +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Install +{ + public interface IInstallHandler + { + void Execute(); + } +} \ No newline at end of file diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallLinux.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallLinux.cs new file mode 100644 index 0000000..319be7a --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallLinux.cs @@ -0,0 +1,46 @@ +using System; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Install; + +public static class InstallLinux +{ + public sealed class Handler : IInstallHandler + { + private const string DesktopFile = """ + [Desktop Entry] + Type=Application + Exec={0} + Path={1} + Hidden=false + NoDisplay=false + X-GNOME-Autostart-enabled=true + Name=YMouseButtonControl + Comment=YMouseButtonControl + """; + private readonly string _configDir = Environment.GetFolderPath( + Environment.SpecialFolder.ApplicationData + ); + private readonly string _autostartDir; + private readonly string _desktopFilePath; + + public Handler() + { + _autostartDir = Path.Combine(_configDir, "autostart"); + _desktopFilePath = Path.Combine(_autostartDir, "YMouseButtonControl.desktop"); + } + + public void Execute() => + File.WriteAllText( + _desktopFilePath, + string.Format(DesktopFile, GetCurExePath(), GetCurExeParentPath()) + ); + + private static string GetCurExeParentPath() => + Path.GetDirectoryName(GetCurExePath()) + ?? throw new Exception("Error retrieving parent of process path"); + + private static string GetCurExePath() => + Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallOsx.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallOsx.cs new file mode 100644 index 0000000..9abd7e1 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallOsx.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Install; + +public static class InstallOsx +{ + public sealed class Handler : IInstallHandler + { + private const string PlistData = """ + + + + + Label + com.github.ymousebuttoncontrol + + ProgramArguments + + {0} + + + RunAtLoad + + + KeepAlive + + + + """; + + private readonly string _usrLaunchAgentsDir; + private readonly string _plistPath; + + public Handler() + { + _usrLaunchAgentsDir = Path.Join( + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + "Library", + "LaunchAgents" + ); + _plistPath = Path.Join(_usrLaunchAgentsDir, "com.github.ymousebuttoncontrol.plist"); + } + + public void Execute() => + File.WriteAllText(_plistPath, string.Format(PlistData, GetCurExePath())); + + private static string GetCurExePath() => + Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallWindows.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallWindows.cs new file mode 100644 index 0000000..a3e76c8 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Install/InstallWindows.cs @@ -0,0 +1,32 @@ +using System; +using System.IO; +using System.Runtime.Versioning; +using System.Security.AccessControl; +using Microsoft.Win32; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Install; + +[SupportedOSPlatform("windows")] +public static class InstallWindows +{ + public sealed class Handler : IInstallHandler + { + private const string BaseKeyPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run\"; + private const string ValName = "YMouseButtonControl"; + + public void Execute() + { + using var key = + Registry.CurrentUser.OpenSubKey( + BaseKeyPath, + RegistryKeyPermissionCheck.ReadWriteSubTree, + RegistryRights.FullControl + ) ?? throw new Exception($"Error opening key {BaseKeyPath}"); + var newKeyVal = $"\"{Path.Join(GetCurExePath())}\""; + key.SetValue(ValName, newKeyVal); + } + + private static string GetCurExePath() => + Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/IUninstallHandler.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/IUninstallHandler.cs new file mode 100644 index 0000000..00f80a6 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/IUninstallHandler.cs @@ -0,0 +1,7 @@ +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Uninstall +{ + public interface IUninstallHandler + { + void Execute(); + } +} \ No newline at end of file diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallLinux.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallLinux.cs new file mode 100644 index 0000000..58cfde8 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallLinux.cs @@ -0,0 +1,24 @@ +using System; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Uninstall; + +public static class UninstallLinux +{ + public sealed class Handler : IUninstallHandler + { + private readonly string _configDir = Environment.GetFolderPath( + Environment.SpecialFolder.ApplicationData + ); + private readonly string _autostartDir; + private readonly string _desktopFilePath; + + public Handler() + { + _autostartDir = Path.Combine(_configDir, "autostart"); + _desktopFilePath = Path.Combine(_autostartDir, "YMouseButtonControl.desktop"); + } + + public void Execute() => File.Delete(_desktopFilePath); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallOsx.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallOsx.cs new file mode 100644 index 0000000..8af7a7c --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallOsx.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Uninstall; + +public static class UninstallOsx +{ + public sealed class Handler : IUninstallHandler + { + private readonly string _usrLaunchAgentsDir; + private readonly string _plistPath; + + public Handler() + { + _usrLaunchAgentsDir = Path.Join( + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + "Library", + "LaunchAgents" + ); + _plistPath = Path.Join(_usrLaunchAgentsDir, "com.github.ymousebuttoncontrol.plist"); + } + + public void Execute() => File.Delete(_plistPath); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallWindows.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallWindows.cs new file mode 100644 index 0000000..6360b8c --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Commands/StartupInstaller/Uninstall/UninstallWindows.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.Versioning; +using System.Security.AccessControl; +using Microsoft.Win32; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Uninstall; + +[SupportedOSPlatform("windows")] +public static class UninstallWindows +{ + public sealed class Handler : IUninstallHandler + { + private const string BaseKeyPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run\"; + private const string ValName = "YMouseButtonControl"; + + public void Execute() + { + using var key = + Registry.CurrentUser.OpenSubKey( + BaseKeyPath, + RegistryKeyPermissionCheck.ReadWriteSubTree, + RegistryRights.FullControl + ) ?? throw new Exception($"Error opening key {BaseKeyPath}"); + key.DeleteValue(ValName); + } + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledLinux.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledLinux.cs new file mode 100644 index 0000000..f68cab5 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledLinux.cs @@ -0,0 +1,22 @@ +using System; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.CanBeInstalled; + +public static class CanBeInstalledLinux +{ + public sealed class Handler : ICanBeInstalledHandler + { + private readonly string _configDir = Environment.GetFolderPath( + Environment.SpecialFolder.ApplicationData + ); + private readonly string _autostartDir; + + public Handler() + { + _autostartDir = Path.Combine(_configDir, "autostart"); + } + + public bool Execute() => Directory.Exists(_autostartDir); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledOsx.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledOsx.cs new file mode 100644 index 0000000..e0b37c2 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledOsx.cs @@ -0,0 +1,23 @@ +using System; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.CanBeInstalled; + +public static class CanBeInstalledOsx +{ + public sealed class Handler : ICanBeInstalledHandler + { + private readonly string _usrLaunchAgentsDir; + + public Handler() + { + _usrLaunchAgentsDir = Path.Join( + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + "Library", + "LaunchAgents" + ); + } + + public bool Execute() => Directory.Exists(_usrLaunchAgentsDir); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledWindows.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledWindows.cs new file mode 100644 index 0000000..4d721b1 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/CanBeInstalledWindows.cs @@ -0,0 +1,9 @@ +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.CanBeInstalled; + +public static class CanBeInstalledWindows +{ + public sealed class Handler : ICanBeInstalledHandler + { + public bool Execute() => true; + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/ICanBeInstalledHandler.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/ICanBeInstalledHandler.cs new file mode 100644 index 0000000..a39bdb8 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/CanBeInstalled/ICanBeInstalledHandler.cs @@ -0,0 +1,7 @@ +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.CanBeInstalled +{ + public interface ICanBeInstalledHandler + { + bool Execute(); + } +} \ No newline at end of file diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IIsInstalledHandler.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IIsInstalledHandler.cs new file mode 100644 index 0000000..2646625 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IIsInstalledHandler.cs @@ -0,0 +1,7 @@ +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.IsInstalled +{ + public interface IIsInstalledHandler + { + bool Execute(); + } +} \ No newline at end of file diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledLinux.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledLinux.cs new file mode 100644 index 0000000..bc27557 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledLinux.cs @@ -0,0 +1,41 @@ +using System; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.IsInstalled; + +public static class IsInstalledLinux +{ + public sealed class Handler : IIsInstalledHandler + { + private readonly string _configDir = Environment.GetFolderPath( + Environment.SpecialFolder.ApplicationData + ); + private readonly string _autostartDir; + private readonly string _desktopFilePath; + + public Handler() + { + _autostartDir = Path.Combine(_configDir, "autostart"); + _desktopFilePath = Path.Combine(_autostartDir, "YMouseButtonControl.desktop"); + } + + public bool Execute() + { + if (!Directory.Exists(_autostartDir)) + { + return false; + } + + if (!File.Exists(_desktopFilePath)) + { + return false; + } + + var expectedExecLine = $"Exec={GetCurExePath()}"; + return File.ReadAllText(_desktopFilePath).Contains(expectedExecLine); + } + + private static string GetCurExePath() => + Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledOsx.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledOsx.cs new file mode 100644 index 0000000..4751a64 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledOsx.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.IsInstalled; + +public static class IsInstalledOsx +{ + public sealed class Handler : IIsInstalledHandler + { + private readonly string _usrLaunchAgentsDir; + private readonly string _plistPath; + + public Handler() + { + _usrLaunchAgentsDir = Path.Join( + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + "Library", + "LaunchAgents" + ); + _plistPath = Path.Join(_usrLaunchAgentsDir, "com.github.ymousebuttoncontrol.plist"); + } + + public bool Execute() => + File.Exists(_plistPath) + && File.ReadAllText(_plistPath).Contains($"{GetCurExePath()}"); + + private static string GetCurExePath() => + Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledWindows.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledWindows.cs new file mode 100644 index 0000000..9e0847f --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/Queries/StartupInstaller/IsInstalled/IsInstalledWindows.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.Versioning; +using System.Security.AccessControl; +using Microsoft.Win32; + +namespace YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.IsInstalled; + +public static class IsInstalledWindows +{ + [SupportedOSPlatform("windows")] + public sealed class Handler : IIsInstalledHandler + { + private const string BaseKeyPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run\"; + private const string ValName = "YMouseButtonControl"; + + public bool Execute() + { + using var key = Registry.CurrentUser.OpenSubKey(BaseKeyPath, RegistryRights.ReadKey); + var keyVal = key?.GetValue(ValName)?.ToString(); + if (string.IsNullOrWhiteSpace(keyVal)) + { + return false; + } + + return keyVal.Trim('"') == GetCurExePath(); + } + + private static string GetCurExePath() => + Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); + } +} diff --git a/YMouseButtonControl.Linux.Tests/StartupInstallerTests.cs b/YMouseButtonControl.Linux.Tests/StartupInstallerTests.cs deleted file mode 100644 index e7000ca..0000000 --- a/YMouseButtonControl.Linux.Tests/StartupInstallerTests.cs +++ /dev/null @@ -1,44 +0,0 @@ -using YMouseButtonControl.Linux.Services; - -namespace YMouseButtonControl.Linux.Tests; - -[Explicit] -public class StartupInstallerTests -{ - [Test] - public void I_can_get_startup_install_status() - { - var sut = new StartupInstallerService(); - - Assert.DoesNotThrow(() => - { - sut.InstallStatus(); - }); - } - - [Test] - public void I_can_install() - { - var sut = new StartupInstallerService(); - - Assert.DoesNotThrow(() => - { - sut.Install(); - - Assert.That(sut.InstallStatus(), Is.True); - }); - } - - [Test] - public void I_can_uninstall() - { - var sut = new StartupInstallerService(); - - Assert.DoesNotThrow(() => - { - sut.Uninstall(); - - Assert.That(sut.InstallStatus(), Is.False); - }); - } -} diff --git a/YMouseButtonControl.Linux/Services/StartupInstallerService.cs b/YMouseButtonControl.Linux/Services/StartupInstallerService.cs deleted file mode 100644 index 47b5a68..0000000 --- a/YMouseButtonControl.Linux/Services/StartupInstallerService.cs +++ /dev/null @@ -1,62 +0,0 @@ -using YMouseButtonControl.Core.Services.StartupInstaller; - -namespace YMouseButtonControl.Linux.Services; - -public class StartupInstallerService : IStartupInstallerService -{ - private const string DesktopFile = """ - [Desktop Entry] - Type=Application - Exec={0} - Path={1} - Hidden=false - NoDisplay=false - X-GNOME-Autostart-enabled=true - Name=YMouseButtonControl - Comment=YMouseButtonControl - """; - private readonly string _configDir = Environment.GetFolderPath( - Environment.SpecialFolder.ApplicationData - ); - private readonly string _autostartDir; - private readonly string _desktopFilePath; - - public StartupInstallerService() - { - _autostartDir = Path.Combine(_configDir, "autostart"); - _desktopFilePath = Path.Combine(_autostartDir, "YMouseButtonControl.desktop"); - } - - public bool ButtonEnabled() => Directory.Exists(_autostartDir); - - public bool InstallStatus() - { - if (!Directory.Exists(_autostartDir)) - { - return false; - } - - if (!File.Exists(_desktopFilePath)) - { - return false; - } - - var expectedExecLine = $"Exec={GetCurExePath()}"; - return File.ReadAllText(_desktopFilePath).Contains(expectedExecLine); - } - - public void Install() => - File.WriteAllText( - _desktopFilePath, - string.Format(DesktopFile, GetCurExePath(), GetCurExeParentPath()) - ); - - public void Uninstall() => File.Delete(_desktopFilePath); - - private static string GetCurExeParentPath() => - Path.GetDirectoryName(GetCurExePath()) - ?? throw new Exception("Error retrieving parent of process path"); - - private static string GetCurExePath() => - Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); -} diff --git a/YMouseButtonControl.MacOS/Services/StartupInstallerService.cs b/YMouseButtonControl.MacOS/Services/StartupInstallerService.cs deleted file mode 100644 index 51c8893..0000000 --- a/YMouseButtonControl.MacOS/Services/StartupInstallerService.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.IO; -using YMouseButtonControl.Core.Services.StartupInstaller; - -namespace YMouseButtonControl.MacOS.Services; - -public class StartupInstallerService : IStartupInstallerService -{ - private const string PlistData = """ - - - - - Label - com.github.ymousebuttoncontrol - - ProgramArguments - - {0} - - - RunAtLoad - - - KeepAlive - - - - """; - - private readonly string _usrLaunchAgentsDir; - private readonly string _plistPath; - - public StartupInstallerService() - { - _usrLaunchAgentsDir = Path.Join( - Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), - "Library", - "LaunchAgents" - ); - _plistPath = Path.Join(_usrLaunchAgentsDir, "com.github.ymousebuttoncontrol.plist"); - } - - public bool ButtonEnabled() => Directory.Exists(_usrLaunchAgentsDir); - - public bool InstallStatus() => - File.Exists(_plistPath) - && File.ReadAllText(_plistPath).Contains($"{GetCurExePath()}"); - - public void Install() => - File.WriteAllText(_plistPath, string.Format(PlistData, GetCurExePath())); - - public void Uninstall() => File.Delete(_plistPath); - - private static string GetCurExePath() => - Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); -} diff --git a/YMouseButtonControl.Windows.Tests/StartupInstallerTests.cs b/YMouseButtonControl.Windows.Tests/StartupInstallerTests.cs deleted file mode 100644 index 857b77c..0000000 --- a/YMouseButtonControl.Windows.Tests/StartupInstallerTests.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Runtime.Versioning; -using YMouseButtonControl.Windows; -using YMouseButtonControl.Windows.Services; - -namespace YMouseButtonControl.Windows.Tests; - -[SupportedOSPlatform("windows")] -[Explicit] -public class StartupInstallerTests -{ - [Test] - public void I_can_get_startup_install_status() - { - var sut = new StartupInstallerService(); - - Assert.DoesNotThrow(() => - { - sut.InstallStatus(); - }); - } - - [Test] - public void I_can_install() - { - var sut = new StartupInstallerService(); - - Assert.DoesNotThrow(() => - { - sut.Install(); - - Assert.That(sut.InstallStatus(), Is.True); - }); - } - - [Test] - public void I_can_uninstall() - { - var sut = new StartupInstallerService(); - - Assert.DoesNotThrow(() => - { - sut.Uninstall(); - - Assert.That(sut.InstallStatus(), Is.False); - }); - } -} diff --git a/YMouseButtonControl.Windows/Services/ProcessMonitorService.cs b/YMouseButtonControl.Windows/Services/ProcessMonitorService.cs index c2aba8f..29f476b 100644 --- a/YMouseButtonControl.Windows/Services/ProcessMonitorService.cs +++ b/YMouseButtonControl.Windows/Services/ProcessMonitorService.cs @@ -1,4 +1,5 @@ -using System.Collections.Concurrent; +using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; @@ -29,7 +30,7 @@ public IEnumerable GetProcesses() cb.Add(p); } } - catch (Win32Exception) { } + catch (Exception ex) when (ex is Win32Exception or AggregateException) { } } ); return cb.DistinctBy(x => x.MainModule!.FileName) diff --git a/YMouseButtonControl.Windows/Services/StartupInstallerService.cs b/YMouseButtonControl.Windows/Services/StartupInstallerService.cs deleted file mode 100644 index b3d40bf..0000000 --- a/YMouseButtonControl.Windows/Services/StartupInstallerService.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.IO; -using System.Runtime.Versioning; -using System.Security.AccessControl; -using Microsoft.Win32; -using YMouseButtonControl.Core.Services.StartupInstaller; - -namespace YMouseButtonControl.Windows.Services; - -[SupportedOSPlatform("windows")] -public class StartupInstallerService : IStartupInstallerService -{ - private const string BaseKeyPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run\"; - private const string ValName = "YMouseButtonControl"; - - public bool ButtonEnabled() => true; - - /// - /// Gets the start-up install status of the program - /// - /// True = installed, False = not installed - public bool InstallStatus() - { - using var key = Registry.CurrentUser.OpenSubKey(BaseKeyPath, RegistryRights.ReadKey); - var keyVal = key?.GetValue(ValName)?.ToString(); - if (string.IsNullOrWhiteSpace(keyVal)) - { - return false; - } - - return keyVal.Trim('"') == GetCurExePath(); - } - - public void Install() - { - using var key = - Registry.CurrentUser.OpenSubKey( - BaseKeyPath, - RegistryKeyPermissionCheck.ReadWriteSubTree, - RegistryRights.FullControl - ) ?? throw new Exception($"Error opening key {BaseKeyPath}"); - var newKeyVal = $"\"{Path.Join(GetCurExePath())}\""; - key.SetValue(ValName, newKeyVal); - } - - public void Uninstall() - { - using var key = - Registry.CurrentUser.OpenSubKey( - BaseKeyPath, - RegistryKeyPermissionCheck.ReadWriteSubTree, - RegistryRights.FullControl - ) ?? throw new Exception($"Error opening key {BaseKeyPath}"); - key.DeleteValue(ValName); - } - - private static string GetCurExePath() => - Environment.ProcessPath ?? throw new Exception("Error retrieving process path"); -} diff --git a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs index 0dae11f..bf3ef3f 100644 --- a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs @@ -5,8 +5,8 @@ using YMouseButtonControl.Core.Services.Processes; using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.Services.Settings; -using YMouseButtonControl.Core.Services.StartupInstaller; using YMouseButtonControl.Core.Services.Theme; +using YMouseButtonControl.Core.ViewModels.AppViewModel; using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog; namespace YMouseButtonControl.DependencyInjection; @@ -21,6 +21,7 @@ public static void RegisterServices(IServiceCollection services) private static void RegisterCommonServices(IServiceCollection services) { + AppHandlerRegistrations.RegisterCommon(services); GlobalSettingsDialogHandlerRegistrations.RegisterCommon(services); services .AddScoped() @@ -50,9 +51,9 @@ private static void RegisterPlatformSpecificServices(IServiceCollection services private static void RegisterLinuxServices(IServiceCollection services) { + AppHandlerRegistrations.RegisterLinux(services); GlobalSettingsDialogHandlerRegistrations.RegisterLinux(services); services - .AddScoped() .AddScoped() .AddScoped(); if (Environment.GetEnvironmentVariable("XDG_SESSION_TYPE") == "x11") @@ -68,9 +69,9 @@ private static void RegisterLinuxServices(IServiceCollection services) [SupportedOSPlatform("windows5.1.2600")] private static void RegisterWindowsServices(IServiceCollection services) { + AppHandlerRegistrations.RegisterWindows(services); GlobalSettingsDialogHandlerRegistrations.RegisterWindows(services); services - .AddScoped() .AddScoped() .AddScoped() .AddScoped(); @@ -78,9 +79,9 @@ private static void RegisterWindowsServices(IServiceCollection services) private static void RegisterMacOsServices(IServiceCollection services) { + AppHandlerRegistrations.RegisterOsx(services); GlobalSettingsDialogHandlerRegistrations.RegisterOsx(services); services - .AddScoped() .AddScoped() .AddScoped() .AddScoped(); From 94fdd54c97ddf84dd691ae5398d40cc4d3be8541 Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Sun, 22 Dec 2024 17:12:09 -0500 Subject: [PATCH 16/39] remove unused interface --- .../StartupInstaller/IStartupInstallerService.cs | 9 --------- .../ViewModels/AppViewModel/AppViewModel.cs | 1 - 2 files changed, 10 deletions(-) delete mode 100644 YMouseButtonControl.Core/Services/StartupInstaller/IStartupInstallerService.cs diff --git a/YMouseButtonControl.Core/Services/StartupInstaller/IStartupInstallerService.cs b/YMouseButtonControl.Core/Services/StartupInstaller/IStartupInstallerService.cs deleted file mode 100644 index c45a998..0000000 --- a/YMouseButtonControl.Core/Services/StartupInstaller/IStartupInstallerService.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace YMouseButtonControl.Core.Services.StartupInstaller; - -public interface IStartupInstallerService -{ - public bool ButtonEnabled(); - public bool InstallStatus(); - public void Install(); - public void Uninstall(); -} diff --git a/YMouseButtonControl.Core/ViewModels/AppViewModel/AppViewModel.cs b/YMouseButtonControl.Core/ViewModels/AppViewModel/AppViewModel.cs index 07b7f70..d771647 100644 --- a/YMouseButtonControl.Core/ViewModels/AppViewModel/AppViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/AppViewModel/AppViewModel.cs @@ -3,7 +3,6 @@ using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using ReactiveUI; -using YMouseButtonControl.Core.Services.StartupInstaller; using YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Install; using YMouseButtonControl.Core.ViewModels.AppViewModel.Commands.StartupInstaller.Uninstall; using YMouseButtonControl.Core.ViewModels.AppViewModel.Queries.StartupInstaller.CanBeInstalled; From 4efd37c4513d78ce586828f1ed1d1d93c72ae6b9 Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Mon, 23 Dec 2024 07:08:24 -0500 Subject: [PATCH 17/39] wip --- .../ProcessSelectorDialogViewModel.cs | 3 +-- .../ViewModels/ProfilesList/ProfilesListViewModel.cs | 1 + .../Queries/Profiles/ListCacheProfiles.cs | 11 +++++++++++ .../YMouseButtonControl.Core.csproj | 1 + .../DependencyInjection/ViewModelsBootstrapper.cs | 1 + .../Views/Dialogs/ProcessSelectorDialog.axaml | 3 ++- .../Views/Dialogs/ProcessSelectorDialog.axaml.cs | 1 + YMouseButtonControl/Views/ProfilesListView.axaml.cs | 1 + 8 files changed, 19 insertions(+), 3 deletions(-) rename YMouseButtonControl.Core/ViewModels/{ProfilesList => ProcessSelectorDialogVm}/ProcessSelectorDialogViewModel.cs (98%) create mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListCacheProfiles.cs diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogViewModel.cs similarity index 98% rename from YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs rename to YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogViewModel.cs index 234d61a..bdbad9d 100644 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProcessSelectorDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogViewModel.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Reactive; using System.Reactive.Linq; -using System.Windows.Input; using DynamicData; using DynamicData.Binding; using ReactiveUI; @@ -13,7 +12,7 @@ using YMouseButtonControl.Core.ViewModels.Models; using YMouseButtonControl.Domain.Models; -namespace YMouseButtonControl.Core.ViewModels.ProfilesList; +namespace YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm; public interface IProcessSelectorDialogViewModel { diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs index 2f3c3fd..8f85bf7 100644 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs @@ -8,6 +8,7 @@ using ReactiveUI; using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.ViewModels.Models; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm; using YMouseButtonControl.Core.ViewModels.ProfilesList.Features.Add; namespace YMouseButtonControl.Core.ViewModels.ProfilesList; diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListCacheProfiles.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListCacheProfiles.cs new file mode 100644 index 0000000..6d5c029 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListCacheProfiles.cs @@ -0,0 +1,11 @@ +using YMouseButtonControl.Core.Services.Profiles; + +namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Queries.Profiles; + +public static class ListCacheProfiles +{ + public sealed class Handler(IProfilesService profilesService) + { + public void Execute() { } + } +} diff --git a/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj b/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj index 05574fb..7ea42d6 100644 --- a/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj +++ b/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj @@ -31,6 +31,7 @@ + diff --git a/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs b/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs index 40b9ea7..e0b1bc3 100644 --- a/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/ViewModelsBootstrapper.cs @@ -3,6 +3,7 @@ using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog; using YMouseButtonControl.Core.ViewModels.LayerViewModel; using YMouseButtonControl.Core.ViewModels.MainWindow; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm; using YMouseButtonControl.Core.ViewModels.ProfilesInformationViewModel; using YMouseButtonControl.Core.ViewModels.ProfilesList; diff --git a/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml b/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml index a2a89ec..935afc9 100644 --- a/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml +++ b/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml @@ -4,6 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:converters="clr-namespace:YMouseButtonControl.Converters" xmlns:profilesList="clr-namespace:YMouseButtonControl.Core.ViewModels.ProfilesList;assembly=YMouseButtonControl.Core" + xmlns:processSelectorDialogVm="clr-namespace:YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm;assembly=YMouseButtonControl.Core" mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="600" @@ -16,7 +17,7 @@ RequestedThemeVariant="{Binding ThemeService.ThemeVariant}"> - + diff --git a/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml.cs b/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml.cs index 2f2150f..f3f1cc8 100644 --- a/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml.cs +++ b/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml.cs @@ -4,6 +4,7 @@ using Avalonia.Markup.Xaml; using Avalonia.ReactiveUI; using ReactiveUI; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm; using YMouseButtonControl.Core.ViewModels.ProfilesList; namespace YMouseButtonControl.Views.Dialogs; diff --git a/YMouseButtonControl/Views/ProfilesListView.axaml.cs b/YMouseButtonControl/Views/ProfilesListView.axaml.cs index fcc3b55..9647878 100644 --- a/YMouseButtonControl/Views/ProfilesListView.axaml.cs +++ b/YMouseButtonControl/Views/ProfilesListView.axaml.cs @@ -7,6 +7,7 @@ using Avalonia.ReactiveUI; using ReactiveUI; using YMouseButtonControl.Core.ViewModels.Models; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm; using YMouseButtonControl.Core.ViewModels.ProfilesList; using YMouseButtonControl.Views.Dialogs; From dc21e55cf5628793050298bd134cf0e9fa1ea53c Mon Sep 17 00:00:00 2001 From: FaithBeam <32502411+FaithBeam@users.noreply.github.com> Date: Tue, 24 Dec 2024 08:28:45 -0500 Subject: [PATCH 18/39] more --- .../Processes/IProcessMonitorService.cs | 8 - .../Services/Profiles/ProfilesService.cs | 47 ++-- .../ViewModels/Models/BaseButtonMappingVm.cs | 33 ++- .../Models/BaseSimulatedKeystrokeTypeVm.cs | 40 +++- .../ViewModels/Models/ProfileVm.cs | 17 ++ ...ocessSelectorDialogHandlerRegistrations.cs | 22 ++ .../ProcessSelectorDialogViewModel.cs | 81 ++++--- .../ProcessSelectorDialogVmFactory.cs | 18 ++ .../Processes/IListProcessesHandler.cs | 10 + .../Queries/Processes/ListProcessesLinux.cs | 20 ++ .../Queries/Processes/ListProcessesOsx.cs | 18 ++ .../Queries/Processes/ListProcessesWindows.cs | 64 ++++++ .../Queries/Processes/Models/ProcessModel.cs | 16 ++ .../Queries/Profiles/GetMaxProfileId.cs | 13 ++ .../Commands/Profiles/AddProfile.cs | 24 +++ .../Commands/Profiles/CopyProfile.cs | 61 ++++++ .../Commands/Profiles/RemoveProfile.cs | 14 ++ .../Commands/Profiles/SetCurrentProfile.cs | 29 +++ .../ProfilesList/Features/Add/AddProfile.cs | 25 --- .../Models/ProfilesListProfileModel.cs | 130 +++++++++++ .../ProfilesListHandlerRegistrations.cs | 20 ++ .../ProfilesList/ProfilesListViewModel.cs | 203 ++++++++++-------- .../Queries/Profiles/ExportProfile.cs | 16 ++ .../Queries/Profiles/GetCurrentProfile.cs | 17 ++ .../Queries/Profiles/ListCacheProfiles.cs | 11 - .../Queries/Profiles/ListProfiles.cs | 31 +++ .../YMouseButtonControl.Core.csproj | 2 +- .../Services/ProcessMonitorService.cs | 16 -- .../Services/ProcessMonitorService.cs | 15 -- .../Services/ProcessMonitorService.cs | 62 ------ .../FactoriesBootstrapper.cs | 5 +- .../FeaturesBootstrapper.cs | 3 +- .../ServicesBootstrapper.cs | 13 +- .../Views/Dialogs/ProcessSelectorDialog.axaml | 6 +- .../Views/ProfilesListView.axaml | 2 +- 35 files changed, 811 insertions(+), 301 deletions(-) delete mode 100644 YMouseButtonControl.Core/Services/Processes/IProcessMonitorService.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogHandlerRegistrations.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogVmFactory.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/IListProcessesHandler.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesLinux.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesOsx.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesWindows.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/Models/ProcessModel.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Profiles/GetMaxProfileId.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/AddProfile.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/CopyProfile.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/RemoveProfile.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/SetCurrentProfile.cs delete mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/Features/Add/AddProfile.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/Models/ProfilesListProfileModel.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListHandlerRegistrations.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ExportProfile.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/GetCurrentProfile.cs delete mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListCacheProfiles.cs create mode 100644 YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListProfiles.cs delete mode 100644 YMouseButtonControl.Linux/Services/ProcessMonitorService.cs delete mode 100644 YMouseButtonControl.MacOS/Services/ProcessMonitorService.cs delete mode 100644 YMouseButtonControl.Windows/Services/ProcessMonitorService.cs diff --git a/YMouseButtonControl.Core/Services/Processes/IProcessMonitorService.cs b/YMouseButtonControl.Core/Services/Processes/IProcessMonitorService.cs deleted file mode 100644 index 89ffa37..0000000 --- a/YMouseButtonControl.Core/Services/Processes/IProcessMonitorService.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Collections.Generic; - -namespace YMouseButtonControl.Core.Services.Processes; - -public interface IProcessMonitorService -{ - IEnumerable GetProcesses(); -} diff --git a/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs b/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs index 6e229bd..50eb7be 100644 --- a/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs +++ b/YMouseButtonControl.Core/Services/Profiles/ProfilesService.cs @@ -14,6 +14,7 @@ namespace YMouseButtonControl.Core.Services.Profiles; public interface IProfilesService { + SourceCache ProfilesSc { get; } ProfileVm? CurrentProfile { get; set; } ReadOnlyObservableCollection Profiles { get; } bool Dirty { get; set; } @@ -26,7 +27,6 @@ public interface IProfilesService void ReplaceProfile(ProfileVm oldProfileVm, ProfileVm newProfileVm); void MoveProfileUp(ProfileVm p); void MoveProfileDown(ProfileVm p); - void RemoveProfile(ProfileVm profileVm); void AddOrUpdate(ProfileVm profileVm); } @@ -34,21 +34,21 @@ public class ProfilesService : ReactiveObject, IProfilesService, IDisposable { private readonly IRepository _profileRepository; private ProfileVm? _currentProfile; - private readonly SourceCache _profiles; + private readonly SourceCache _profilesSc; private readonly ReadOnlyObservableCollection _profilesObsCol; private bool _dirty; public ProfilesService(IRepository profileRepository) { _profileRepository = profileRepository; - _profiles = new SourceCache(x => x.Id); - _profiles + _profilesSc = new SourceCache(x => x.Id); + _profilesSc .Connect() .AutoRefresh() .SortBy(x => x.DisplayPriority) .Bind(out _profilesObsCol) .Subscribe(IsDirty); - _profiles.AddOrUpdate(profileRepository.GetAll().ToList()); + _profilesSc.AddOrUpdate(profileRepository.GetAll().ToList()); CurrentProfile ??= Profiles.FirstOrDefault(); } @@ -68,9 +68,9 @@ public bool Dirty /// public ReadOnlyObservableCollection Profiles => _profilesObsCol; - public void AddOrUpdate(ProfileVm profile) => _profiles.AddOrUpdate(profile); + public void AddOrUpdate(ProfileVm profile) => _profilesSc.AddOrUpdate(profile); - public IObservable> Connect() => _profiles.Connect(); + public IObservable> Connect() => _profilesSc.Connect(); public ProfileVm? CurrentProfile { @@ -78,6 +78,8 @@ public ProfileVm? CurrentProfile set => this.RaiseAndSetIfChanged(ref _currentProfile, value); } + public SourceCache ProfilesSc => _profilesSc; + public ProfileVm CopyProfile(ProfileVm p) { var jsonString = JsonConvert.SerializeObject( @@ -116,7 +118,7 @@ public void ImportProfileFromPath(string path) public void AddProfile(ProfileVm profile) { - _profiles.AddOrUpdate(profile); + _profilesSc.AddOrUpdate(profile); } public void ReplaceProfile(ProfileVm oldProfile, ProfileVm newProfile) @@ -127,7 +129,7 @@ public void ReplaceProfile(ProfileVm oldProfile, ProfileVm newProfile) } newProfile.Id = oldProfile.Id; - _profiles.AddOrUpdate(newProfile); + _profilesSc.AddOrUpdate(newProfile); } public void MoveProfileUp(ProfileVm p) @@ -137,9 +139,9 @@ public void MoveProfileUp(ProfileVm p) throw new InvalidMoveException("Cannot move the default profile"); } - _profiles.Edit(updater => + _profilesSc.Edit(updater => { - var nextSmaller = _profiles + var nextSmaller = _profilesSc .Items.Where(x => x.DisplayPriority < p.DisplayPriority) .MaxBy(x => x.DisplayPriority); if (nextSmaller is null) @@ -169,7 +171,7 @@ public void MoveProfileDown(ProfileVm p) throw new InvalidMoveException("Cannot move the default profile"); } - var nextLargerPriority = _profiles + var nextLargerPriority = _profilesSc .Items.Where(x => x.DisplayPriority > p.DisplayPriority) .MinBy(x => x.DisplayPriority); if (nextLargerPriority is null) @@ -186,27 +188,8 @@ public void MoveProfileDown(ProfileVm p) ); } - public void RemoveProfile(ProfileVm profile) - { - if (profile.IsDefault) - { - throw new Exception("Attempted to remove default profile"); - } - - var nextSmallerPriority = _profiles - .Items.Where(x => x.DisplayPriority < profile.DisplayPriority) - .MaxBy(x => x.DisplayPriority); - if (nextSmallerPriority is null) - { - throw new Exception("Unable to find next profile to set as current profile"); - } - - _profiles.Remove(profile); - CurrentProfile = nextSmallerPriority; - } - public void Dispose() { - _profiles.Dispose(); + _profilesSc.Dispose(); } } diff --git a/YMouseButtonControl.Core/ViewModels/Models/BaseButtonMappingVm.cs b/YMouseButtonControl.Core/ViewModels/Models/BaseButtonMappingVm.cs index 9ecdbb8..49c0019 100644 --- a/YMouseButtonControl.Core/ViewModels/Models/BaseButtonMappingVm.cs +++ b/YMouseButtonControl.Core/ViewModels/Models/BaseButtonMappingVm.cs @@ -24,6 +24,7 @@ public abstract class BaseButtonMappingVm : ReactiveObject, IEquatable this.RaiseAndSetIfChanged(ref _blockOriginalMouseInput, value); } - public BaseButtonMappingVm Clone() => (BaseButtonMappingVm)MemberwiseClone(); + protected BaseButtonMappingVm CreateClone(BaseButtonMappingVm clone) + { + clone.Id = Id; + clone.ProfileId = ProfileId; + clone.MouseButton = MouseButton; + clone.Index = Index; + clone.Selected = Selected; + clone.HasSettingsPopped = HasSettingsPopped; + clone.Enabled = Enabled; + clone.Description = Description; + clone.PriorityDescription = PriorityDescription; + clone.AutoRepeatDelay = AutoRepeatDelay; + clone.AutoRepeatRandomizeDelayEnabled = AutoRepeatRandomizeDelayEnabled; + clone.Keys = Keys; + clone.State = State; + clone.CanRaiseDialog = CanRaiseDialog; + clone.SimulatedKeystrokeType = SimulatedKeystrokeType?.Clone(); + clone.BlockOriginalMouseInput = BlockOriginalMouseInput; + + return clone; + } + + public abstract BaseButtonMappingVm Clone(); public override string? ToString() { @@ -165,6 +188,8 @@ public DisabledMappingVm() Index = 1; Description = "Disabled"; } + + public override BaseButtonMappingVm Clone() => CreateClone(new DisabledMappingVm()); } public class NothingMappingVm : BaseButtonMappingVm @@ -174,6 +199,8 @@ public NothingMappingVm() Index = 0; Description = "** No Change (Don't Intercept) **"; } + + public override BaseButtonMappingVm Clone() => CreateClone(new NothingMappingVm()); } public class SimulatedKeystrokeVm : BaseButtonMappingVm @@ -186,6 +213,8 @@ public SimulatedKeystrokeVm() BlockOriginalMouseInput = true; } + public override BaseButtonMappingVm Clone() => CreateClone(new SimulatedKeystrokeVm()); + public override string? ToString() { var myStr = SimulatedKeystrokeType is not null @@ -213,4 +242,6 @@ public RightClickVm() Index = 3; Description = "Right Click"; } + + public override BaseButtonMappingVm Clone() => CreateClone(new RightClickVm()); } diff --git a/YMouseButtonControl.Core/ViewModels/Models/BaseSimulatedKeystrokeTypeVm.cs b/YMouseButtonControl.Core/ViewModels/Models/BaseSimulatedKeystrokeTypeVm.cs index 6eb13bd..35ac957 100644 --- a/YMouseButtonControl.Core/ViewModels/Models/BaseSimulatedKeystrokeTypeVm.cs +++ b/YMouseButtonControl.Core/ViewModels/Models/BaseSimulatedKeystrokeTypeVm.cs @@ -34,6 +34,17 @@ public bool Enabled set => this.RaiseAndSetIfChanged(ref _enabled, value); } + protected BaseSimulatedKeystrokeTypeVm CreateClone(BaseSimulatedKeystrokeTypeVm clone) + { + clone.Index = Index; + clone.Description = Description; + clone.ShortDescription = ShortDescription; + clone.Enabled = Enabled; + return clone; + } + + public abstract BaseSimulatedKeystrokeTypeVm Clone(); + public override string ToString() => $"{Index + 1} {Description}"; public bool Equals(BaseSimulatedKeystrokeTypeVm? other) @@ -54,7 +65,7 @@ public override bool Equals(object? obj) return false; if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) + if (obj.GetType() != GetType()) return false; return Equals((BaseSimulatedKeystrokeTypeVm)obj); } @@ -74,6 +85,9 @@ public AsMousePressedAndReleasedActionTypeVm() ShortDescription = "pressed & released"; Enabled = true; } + + public override BaseSimulatedKeystrokeTypeVm Clone() => + CreateClone(new AsMousePressedAndReleasedActionTypeVm()); } public class DuringMouseActionTypeVm : BaseSimulatedKeystrokeTypeVm @@ -85,6 +99,9 @@ public DuringMouseActionTypeVm() ShortDescription = "during"; Enabled = true; } + + public override BaseSimulatedKeystrokeTypeVm Clone() => + CreateClone(new DuringMouseActionTypeVm()); } public class InAnotherThreadPressedActionTypeVm : BaseSimulatedKeystrokeTypeVm @@ -96,6 +113,9 @@ public InAnotherThreadPressedActionTypeVm() ShortDescription = "thread-down"; Enabled = false; } + + public override BaseSimulatedKeystrokeTypeVm Clone() => + CreateClone(new InAnotherThreadPressedActionTypeVm()); } public class InAnotherThreadReleasedActionTypeVm : BaseSimulatedKeystrokeTypeVm @@ -107,6 +127,9 @@ public InAnotherThreadReleasedActionTypeVm() ShortDescription = "thread-up"; Enabled = false; } + + public override BaseSimulatedKeystrokeTypeVm Clone() => + CreateClone(new InAnotherThreadReleasedActionTypeVm()); } public class MouseButtonPressedActionTypeVm : BaseSimulatedKeystrokeTypeVm @@ -118,6 +141,9 @@ public MouseButtonPressedActionTypeVm() ShortDescription = "pressed"; Enabled = true; } + + public override BaseSimulatedKeystrokeTypeVm Clone() => + CreateClone(new MouseButtonPressedActionTypeVm()); } public class MouseButtonReleasedActionTypeVm : BaseSimulatedKeystrokeTypeVm @@ -129,6 +155,9 @@ public MouseButtonReleasedActionTypeVm() ShortDescription = "released"; Enabled = true; } + + public override BaseSimulatedKeystrokeTypeVm Clone() => + CreateClone(new MouseButtonReleasedActionTypeVm()); } public class RepeatedlyWhileButtonDownActionTypeVm : BaseSimulatedKeystrokeTypeVm @@ -140,6 +169,9 @@ public RepeatedlyWhileButtonDownActionTypeVm() ShortDescription = "repeat"; Enabled = true; } + + public override BaseSimulatedKeystrokeTypeVm Clone() => + CreateClone(new RepeatedlyWhileButtonDownActionTypeVm()); } public class StickyHoldActionTypeVm : BaseSimulatedKeystrokeTypeVm @@ -151,6 +183,9 @@ public StickyHoldActionTypeVm() ShortDescription = "sticky hold"; Enabled = true; } + + public override BaseSimulatedKeystrokeTypeVm Clone() => + CreateClone(new StickyHoldActionTypeVm()); } public class StickyRepeatActionTypeVm : BaseSimulatedKeystrokeTypeVm @@ -162,4 +197,7 @@ public StickyRepeatActionTypeVm() ShortDescription = "sticky repeat"; Enabled = true; } + + public override BaseSimulatedKeystrokeTypeVm Clone() => + CreateClone(new StickyRepeatActionTypeVm()); } diff --git a/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs b/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs index dae4931..37f6ff1 100644 --- a/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs +++ b/YMouseButtonControl.Core/ViewModels/Models/ProfileVm.cs @@ -173,6 +173,7 @@ public ProfileVm(List buttonMappings) public void AddOrUpdateBtnMapping(IEnumerable buttonMappingVms) => _btnSc.AddOrUpdate(buttonMappingVms); + [JsonIgnore] public SourceCache BtnSc => _btnSc; [JsonIgnore] @@ -292,6 +293,22 @@ public int DisplayPriority set => this.RaiseAndSetIfChanged(ref _displayPriority, value); } + public ProfileVm Clone() => + new ProfileVm(ButtonMappings.Select(x => x.Clone()).ToList()) + { + Id = Id, + Checked = Checked, + DisplayPriority = DisplayPriority, + IsDefault = IsDefault, + Name = Name, + Description = Description, + MatchType = MatchType, + ParentClass = ParentClass, + Process = Process, + WindowClass = WindowClass, + WindowCaption = WindowCaption, + }; + public bool Equals(ProfileVm? other) { if (ReferenceEquals(null, other)) diff --git a/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogHandlerRegistrations.cs b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogHandlerRegistrations.cs new file mode 100644 index 0000000..4973abb --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogHandlerRegistrations.cs @@ -0,0 +1,22 @@ +using System.Runtime.Versioning; +using Microsoft.Extensions.DependencyInjection; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Processes; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Profiles; + +namespace YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm; + +public static class ProcessSelectorDialogHandlerRegistrations +{ + public static void RegisterCommon(IServiceCollection services) => + services.AddScoped(); + + public static void RegisterLinux(IServiceCollection services) => + services.AddScoped(); + + public static void RegisterOsx(IServiceCollection services) => + services.AddScoped(); + + [SupportedOSPlatform("windows5.1.2600")] + public static void RegisterWindows(IServiceCollection services) => + services.AddScoped(); +} diff --git a/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogViewModel.cs index bdbad9d..b5b4eb7 100644 --- a/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogViewModel.cs @@ -7,9 +7,9 @@ using DynamicData; using DynamicData.Binding; using ReactiveUI; -using YMouseButtonControl.Core.Services.Processes; -using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.ViewModels.Models; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Processes; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Profiles; using YMouseButtonControl.Domain.Models; namespace YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm; @@ -21,29 +21,36 @@ public interface IProcessSelectorDialogViewModel public class ProcessSelectorDialogViewModel : DialogBase, IProcessSelectorDialogViewModel { - private readonly IProcessMonitorService _processMonitorService; - private readonly SourceList _sourceProcessModels; + private readonly SourceList _sourceProcessModels; private string? _processFilter; - private readonly ReadOnlyObservableCollection _filtered; - private ProcessModel? _processModel; + private readonly ReadOnlyObservableCollection _filtered; + private Queries.Processes.Models.ProcessModel? _processModel; + private string? _selectedProcessModuleName; + private string? _selectedProcessMainWindowTitle; public ProcessSelectorDialogViewModel( - IProcessMonitorService processMonitorService, - IProfilesService profilesService + IListProcessesHandler listProcessesHandler, + GetMaxProfileId.Handler getMaxProfileIdHandler, + string? selectedProcessModuleName ) { - _sourceProcessModels = new SourceList(); - _processMonitorService = processMonitorService; + _sourceProcessModels = new SourceList(); var dynamicFilter = this.WhenValueChanged(x => x.ProcessFilter) .Select(CreateProcessFilterPredicate); var filteredDisposable = _sourceProcessModels .Connect() .Filter(dynamicFilter) - .Sort(SortExpressionComparer.Ascending(x => x.Process.ProcessName)) + .Sort( + SortExpressionComparer.Ascending(x => + x.Process.ProcessName + ) + ) .Bind(out _filtered) .Subscribe(); - RefreshProcessList(); - RefreshButtonCommand = ReactiveCommand.Create(RefreshProcessList); + _sourceProcessModels.EditDiff(listProcessesHandler.Execute()); + RefreshButtonCommand = ReactiveCommand.Create( + () => _sourceProcessModels.EditDiff(listProcessesHandler.Execute()) + ); var canExecuteOkCommand = this.WhenAnyValue( x => x.SelectedProcessModel, selector: model => model is not null @@ -51,9 +58,7 @@ IProfilesService profilesService OkCommand = ReactiveCommand.Create( () => { - var maxBmId = profilesService - .Profiles.SelectMany(x => x.ButtonMappings) - .Max(x => x.Id); + var maxBmId = getMaxProfileIdHandler.Execute(); var buttonMappings = new List { CreateButtonMappings(maxBmId, MouseButton.Mb1), @@ -68,9 +73,9 @@ IProfilesService profilesService }; return new ProfileVm(buttonMappings) { - Name = SelectedProcessModel!.Process.MainModule!.ModuleName, - Description = SelectedProcessModel.Process.MainWindowTitle, - Process = SelectedProcessModel.Process.MainModule.ModuleName, + Name = SelectedProcessModuleName ?? string.Empty, + Description = SelectedProcessMainWindowTitle ?? string.Empty, + Process = SelectedProcessModuleName ?? string.Empty, WindowCaption = "N/A", WindowClass = "N/A", ParentClass = "N/A", @@ -79,6 +84,22 @@ IProfilesService profilesService }, canExecuteOkCommand ); + this.WhenAnyValue(x => x.SelectedProcessModel) + .Subscribe(x => + { + SelectedProcessModuleName = x?.Process.MainModule?.ModuleName; + SelectedProcessMainWindowTitle = x?.Process.MainWindowTitle; + }); + if (!string.IsNullOrWhiteSpace(selectedProcessModuleName)) + { + var foundProc = _filtered.FirstOrDefault(x => + x.Process.MainModule?.ModuleName == selectedProcessModuleName + ); + if (foundProc is not null) + { + SelectedProcessModel = foundProc; + } + } } private static List CreateButtonMappings( @@ -97,7 +118,9 @@ MouseButton mouseButton new RightClickVm { Id = ++id, MouseButton = mouseButton }, ]; - private Func CreateProcessFilterPredicate(string? txt) + private Func CreateProcessFilterPredicate( + string? txt + ) { if (string.IsNullOrWhiteSpace(txt)) { @@ -119,14 +142,24 @@ public string? ProcessFilter public ReactiveCommand OkCommand { get; } - public ReadOnlyObservableCollection Filtered => _filtered; + public ReadOnlyObservableCollection Filtered => + _filtered; - public ProcessModel? SelectedProcessModel + public Queries.Processes.Models.ProcessModel? SelectedProcessModel { get => _processModel; set => this.RaiseAndSetIfChanged(ref _processModel, value); } - private void RefreshProcessList() => - _sourceProcessModels.EditDiff(_processMonitorService.GetProcesses()); + public string? SelectedProcessModuleName + { + get => _selectedProcessModuleName; + set => this.RaiseAndSetIfChanged(ref _selectedProcessModuleName, value); + } + + public string? SelectedProcessMainWindowTitle + { + get => _selectedProcessMainWindowTitle; + set => this.RaiseAndSetIfChanged(ref _selectedProcessMainWindowTitle, value); + } } diff --git a/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogVmFactory.cs b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogVmFactory.cs new file mode 100644 index 0000000..881c3f8 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/ProcessSelectorDialogVmFactory.cs @@ -0,0 +1,18 @@ +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Processes; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Profiles; + +namespace YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm; + +public interface IProcessSelectorDialogVmFactory +{ + ProcessSelectorDialogViewModel Create(string? moduleName = null); +} + +public class ProcessSelectorDialogVmFactory( + IListProcessesHandler listProcessesHandler, + GetMaxProfileId.Handler getMaxProfileIdHandler +) : IProcessSelectorDialogVmFactory +{ + public ProcessSelectorDialogViewModel Create(string? moduleName = null) => + new(listProcessesHandler, getMaxProfileIdHandler, moduleName); +} diff --git a/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/IListProcessesHandler.cs b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/IListProcessesHandler.cs new file mode 100644 index 0000000..19ba643 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/IListProcessesHandler.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Processes.Models; + +namespace YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Processes +{ + public interface IListProcessesHandler + { + IEnumerable Execute(); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesLinux.cs b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesLinux.cs new file mode 100644 index 0000000..53266d6 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesLinux.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Processes; + +public static class ListProcessesLinux +{ + public sealed class Handler : IListProcessesHandler + { + public IEnumerable Execute() => + Process + .GetProcesses() + .Select(x => new Models.ProcessModel(x)) + .Where(x => + !string.IsNullOrWhiteSpace(x.Process.MainModule?.ModuleName) + && !string.IsNullOrWhiteSpace(x.Process.ProcessName) + ); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesOsx.cs b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesOsx.cs new file mode 100644 index 0000000..afc98aa --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesOsx.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Processes.Models; + +namespace YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Processes; + +public static class ListProcessesOsx +{ + public sealed class Handler : IListProcessesHandler + { + public IEnumerable Execute() => + Process + .GetProcesses() + .Select(x => new ProcessModel(x)) + .Where(x => !string.IsNullOrWhiteSpace(x.Process.ProcessName)); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesWindows.cs b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesWindows.cs new file mode 100644 index 0000000..8f17521 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/ListProcessesWindows.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Runtime.Versioning; +using System.Threading.Tasks; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Processes.Models; + +namespace YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Processes; + +[SupportedOSPlatform("windows5.1.2600")] +public static class ListProcessesWindows +{ + public sealed class Handler : IListProcessesHandler + { + public IEnumerable Execute() + { + var cb = new ConcurrentBag(); + Parallel.ForEach( + Process.GetProcesses().DistinctBy(x => x.ProcessName), + p => + { + try + { + if (p.MainModule != null) + { + cb.Add(p); + } + } + catch (Exception ex) when (ex is Win32Exception or AggregateException) { } + } + ); + return cb.DistinctBy(x => x.MainModule!.FileName) + .Select(x => new ProcessModel(x) + { + Bitmap = GetBitmapStreamFromPath(x.MainModule!.FileName), + }); + } + + private static MemoryStream? GetBitmapStreamFromPath(string path) + { + if (path is null or "/") + { + return null; + } + + var icon = Icon.ExtractAssociatedIcon(path); + var bmp = icon?.ToBitmap(); + if (bmp is null) + { + return null; + } + var stream = new MemoryStream(); + bmp.Save(stream, ImageFormat.Bmp); + stream.Position = 0; + return stream; + } + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/Models/ProcessModel.cs b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/Models/ProcessModel.cs new file mode 100644 index 0000000..8b46f55 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Processes/Models/ProcessModel.cs @@ -0,0 +1,16 @@ +using System.Diagnostics; +using System.IO; + +namespace YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Processes.Models; + +public record ProcessModel(Process P) +{ + public Process Process { get; } = P; + public Stream? Bitmap { get; set; } + + public void Dispose() + { + Process.Dispose(); + Bitmap?.Dispose(); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Profiles/GetMaxProfileId.cs b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Profiles/GetMaxProfileId.cs new file mode 100644 index 0000000..64192b5 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProcessSelectorDialogVm/Queries/Profiles/GetMaxProfileId.cs @@ -0,0 +1,13 @@ +using System.Linq; +using YMouseButtonControl.Core.Services.Profiles; + +namespace YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm.Queries.Profiles; + +public static class GetMaxProfileId +{ + public sealed class Handler(IProfilesService profilesService) + { + public int Execute() => + profilesService.Profiles.SelectMany(x => x.ButtonMappings).Max(x => x.Id); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/AddProfile.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/AddProfile.cs new file mode 100644 index 0000000..062eedc --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/AddProfile.cs @@ -0,0 +1,24 @@ +using System; +using System.Linq; +using YMouseButtonControl.Core.Services.Profiles; +using YMouseButtonControl.Core.ViewModels.Models; + +namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Commands.Profiles; + +public static class AddProfile +{ + public sealed record Command(ProfileVm Profile); + + public sealed class Handler(IProfilesService profilesService) + { + public void Execute(Command c) + { + profilesService.ProfilesSc.Edit(inner => + { + c.Profile.Id = inner.Items.Max(x => x.Id) + 1; + c.Profile.DisplayPriority = inner.Items.Max(x => x.DisplayPriority) + 1; + inner.AddOrUpdate(c.Profile); + }); + } + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/CopyProfile.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/CopyProfile.cs new file mode 100644 index 0000000..b3b5129 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/CopyProfile.cs @@ -0,0 +1,61 @@ +using System; +using System.Linq; +using YMouseButtonControl.Core.Services.Profiles; +using YMouseButtonControl.Core.ViewModels.Models; +using YMouseButtonControl.Core.ViewModels.ProfilesList.Models; + +namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Commands.Profiles; + +public static class CopyProfile +{ + public sealed record Command( + int ProfileIdToCopyBtnMappingsFrom, + string Name, + string Description, + bool Checked, + string Process, + string MatchType, + string ParentClass, + string WindowClass + ); + + public sealed class Handler(IProfilesService profilesService) + { + public ProfilesListProfileModel Execute(Command c) + { + ProfilesListProfileModel? result = default; + profilesService.ProfilesSc.Edit(inner => + { + var clonedBtnMappings = inner + .Items.First(x => x.Id == c.ProfileIdToCopyBtnMappingsFrom) + .Clone() + .ButtonMappings.ToList(); + var newProfileVm = new ProfileVm(clonedBtnMappings) + { + Id = inner.Items.Max(x => x.Id) + 1, + DisplayPriority = inner.Items.Max(x => x.DisplayPriority) + 1, + Description = c.Description, + MatchType = c.MatchType, + ParentClass = c.ParentClass, + Process = c.Process, + WindowClass = c.WindowClass, + Name = c.Name, + }; + + foreach (var bm in newProfileVm.ButtonMappings) + { + bm.ProfileId = newProfileVm.Id; + } + var maxBtnMappingId = inner.Items.SelectMany(x => x.ButtonMappings).Max(x => x.Id); + foreach (var bm in newProfileVm.ButtonMappings) + { + bm.Id = ++maxBtnMappingId; + } + inner.AddOrUpdate(newProfileVm); + result = new ProfilesListProfileModel(newProfileVm, profilesService); + }); + + return result ?? throw new Exception("Result null exception"); + } + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/RemoveProfile.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/RemoveProfile.cs new file mode 100644 index 0000000..a5dcd78 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/RemoveProfile.cs @@ -0,0 +1,14 @@ +using YMouseButtonControl.Core.Services.Profiles; + +namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Commands.Profiles; + +public static class RemoveProfile +{ + public sealed record Command(int Id); + + public sealed class Handler(IProfilesService profilesService) + { + public void Execute(Command c) => + profilesService.ProfilesSc.Edit(inner => inner.RemoveKey(c.Id)); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/SetCurrentProfile.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/SetCurrentProfile.cs new file mode 100644 index 0000000..84f4595 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/Commands/Profiles/SetCurrentProfile.cs @@ -0,0 +1,29 @@ +using System.Linq; +using YMouseButtonControl.Core.Services.Profiles; +using YMouseButtonControl.Core.ViewModels.ProfilesList.Models; + +namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Commands.Profiles; + +/// +/// Assign ProfilesService CurrentProfile to a new profile +/// +public static class SetCurrentProfile +{ + public sealed record Command(ProfilesListProfileModel? Profile); + + public sealed class Handler(IProfilesService profilesService) + { + public void Execute(Command c) + { + if (c.Profile is null) + { + profilesService.CurrentProfile = null; + } + else + { + var profile = profilesService.Profiles.First(x => x.Id == c.Profile.Id); + profilesService.CurrentProfile = profile; + } + } + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/Features/Add/AddProfile.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/Features/Add/AddProfile.cs deleted file mode 100644 index ae3ca17..0000000 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/Features/Add/AddProfile.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Linq; -using YMouseButtonControl.Core.Services.Profiles; -using YMouseButtonControl.Core.ViewModels.Models; - -namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Features.Add; - -public interface IAddProfile -{ - void Add(ProfileVm profile); -} - -public class AddProfile(IProfilesService profilesService) : IAddProfile -{ - public void Add(ProfileVm profile) - { - profile.Id = GetNextProfileId(); - profile.DisplayPriority = GetNextProfileDisplayPriority(); - profilesService.AddOrUpdate(profile); - } - - private int GetNextProfileDisplayPriority() => - profilesService.Profiles.Max(x => x.DisplayPriority) + 1; - - private int GetNextProfileId() => profilesService.Profiles.Max(x => x.Id) + 1; -} diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/Models/ProfilesListProfileModel.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/Models/ProfilesListProfileModel.cs new file mode 100644 index 0000000..3bbebd7 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/Models/ProfilesListProfileModel.cs @@ -0,0 +1,130 @@ +using System; +using System.Linq; +using ReactiveUI; +using YMouseButtonControl.Core.Services.Profiles; +using YMouseButtonControl.Core.ViewModels.Models; + +namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Models; + +public sealed class ProfilesListProfileModel : ReactiveObject +{ + private int _id; + private string _description; + private bool _checked; + private readonly bool _isDefault; + private readonly int _displayPriority; + private string? _process; + private string? _name; + + public ProfilesListProfileModel(ProfileVm profileVm, IProfilesService profilesService) + { + _id = profileVm.Id; + _description = profileVm.Description; + _checked = profileVm.Checked; + _isDefault = profileVm.IsDefault; + _displayPriority = profileVm.DisplayPriority; + _process = profileVm.Process; + _name = profileVm.Name; + + this.WhenAnyValue(x => x.Id) + .Subscribe(id => + { + profilesService.ProfilesSc.Edit(inner => + { + var tgt = inner.Items.FirstOrDefault(x => x.Id == Id); + if (tgt is not null) + { + tgt.Id = id; + } + }); + }); + this.WhenAnyValue(x => x.Description) + .Subscribe(description => + { + profilesService.ProfilesSc.Edit(inner => + { + var tgt = inner.Items.FirstOrDefault(x => x.Id == Id); + if (tgt is not null) + { + tgt.Description = description; + } + }); + }); + this.WhenAnyValue(x => x.Checked) + .Subscribe(@checked => + { + profilesService.ProfilesSc.Edit(inner => + { + var tgt = inner.Items.FirstOrDefault(x => x.Id == Id); + if (tgt is not null) + { + tgt.Checked = @checked; + } + }); + }); + this.WhenAnyValue(x => x.DisplayPriority) + .Subscribe(displayPriority => + { + profilesService.ProfilesSc.Edit(inner => + { + var tgt = inner.Items.FirstOrDefault(x => x.Id == Id); + if (tgt is not null) + { + tgt.DisplayPriority = displayPriority; + } + }); + }); + this.WhenAnyValue(x => x.Process) + .Subscribe(Process => + { + profilesService.ProfilesSc.Edit(inner => + { + var tgt = inner.Items.FirstOrDefault(x => x.Id == Id); + if (tgt is not null) + { + tgt.Process = Process!; + } + }); + }); + this.WhenAnyValue(x => x.Name) + .Subscribe(Name => + { + profilesService.ProfilesSc.Edit(inner => + { + var tgt = inner.Items.FirstOrDefault(x => x.Id == Id); + if (tgt is not null) + { + tgt.Name = Name!; + } + }); + }); + } + + public int Id + { + get => _id; + set => this.RaiseAndSetIfChanged(ref _id, value); + } + public string Description + { + get => _description; + set => this.RaiseAndSetIfChanged(ref _description, value); + } + public bool Checked + { + get => _checked; + set => this.RaiseAndSetIfChanged(ref _checked, value); + } + public bool IsDefault => _isDefault; + public int DisplayPriority => _displayPriority; + public string? Process + { + get => _process; + set => this.RaiseAndSetIfChanged(ref _process, value); + } + public string? Name + { + get => _name; + set => this.RaiseAndSetIfChanged(ref _name, value); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListHandlerRegistrations.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListHandlerRegistrations.cs new file mode 100644 index 0000000..f6e82c2 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListHandlerRegistrations.cs @@ -0,0 +1,20 @@ +using Microsoft.Extensions.DependencyInjection; +using YMouseButtonControl.Core.ViewModels.ProfilesList.Commands.Profiles; +using YMouseButtonControl.Core.ViewModels.ProfilesList.Queries.Profiles; + +namespace YMouseButtonControl.Core.ViewModels.ProfilesList; + +public static class ProfilesListHandlerRegistrations +{ + public static void RegisterCommon(IServiceCollection services) + { + services + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped(); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs index 8f85bf7..9f2c0b7 100644 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/ProfilesListViewModel.cs @@ -1,15 +1,19 @@ using System; +using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Reactive; using System.Reactive.Linq; +using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Input; using ReactiveUI; using YMouseButtonControl.Core.Services.Profiles; using YMouseButtonControl.Core.ViewModels.Models; using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm; -using YMouseButtonControl.Core.ViewModels.ProfilesList.Features.Add; +using YMouseButtonControl.Core.ViewModels.ProfilesList.Commands.Profiles; +using YMouseButtonControl.Core.ViewModels.ProfilesList.Models; +using YMouseButtonControl.Core.ViewModels.ProfilesList.Queries.Profiles; namespace YMouseButtonControl.Core.ViewModels.ProfilesList; @@ -18,8 +22,7 @@ public interface IProfilesListViewModel; public class ProfilesListViewModel : ViewModelBase, IProfilesListViewModel { private IProfilesService _profilesService; - private readonly IProcessSelectorDialogViewModel _processSelectorDialogViewModel; - private readonly IAddProfile _addProfile; + private ProfilesListProfileModel? _currentProfile; public ICommand AddButtonCommand { get; } public ReactiveCommand EditButtonCommand { get; } @@ -36,65 +39,144 @@ public Interaction< public ProfilesListViewModel( IProfilesService profilesService, - IProcessSelectorDialogViewModel processSelectorDialogViewModel, - IAddProfile addProfile + ListProfiles.Handler listCacheProfilesHandler, + GetCurrentProfile.Handler getCurrentProfileHandler, + SetCurrentProfile.Handler setCurrentProfileHandler, + RemoveProfile.Handler removeProfileHandler, + IProcessSelectorDialogVmFactory processSelectorDialogVmFactory, + AddProfile.Handler addProfileHandler, + ExportProfile.Handler exportProfileHandler, + CopyProfile.Handler copyProfileHandler ) { _profilesService = profilesService; - AddButtonCommand = ReactiveCommand.CreateFromTask(ShowProcessPickerDialogAsync); + CurrentProfile = getCurrentProfileHandler.Execute(); + Profiles = listCacheProfilesHandler.Execute(); + this.WhenAnyValue(x => x.CurrentProfile) + .WhereNotNull() + .Select(cur => new SetCurrentProfile.Command(cur)) + .Subscribe(setCurrentProfileHandler.Execute); + ShowProcessSelectorInteraction = + new Interaction(); + AddButtonCommand = ReactiveCommand.CreateFromTask(async () => + { + var result = await ShowProcessSelectorInteraction.Handle( + processSelectorDialogVmFactory.Create() + ); + if (result is null) + { + return; + } + addProfileHandler.Execute(new AddProfile.Command(result)); + }); ShowExportFileDialog = new Interaction(); ShowImportFileDialog = new Interaction(); ImportCommand = ReactiveCommand.CreateFromTask(OnImportClickedAsync); var exportCanExecute = this.WhenAnyValue( - x => x.ProfilesService.CurrentProfile, + x => x.CurrentProfile, curProf => !curProf?.IsDefault ?? false ); ExportCommand = ReactiveCommand.CreateFromTask(OnExportClickedAsync, exportCanExecute); + var removeCanExecute = this.WhenAnyValue( - x => x.ProfilesService.CurrentProfile, + x => x.CurrentProfile, curProf => !curProf?.IsDefault ?? false ); - RemoveButtonCommand = ReactiveCommand.Create(OnRemoveButtonClicked, removeCanExecute); + RemoveButtonCommand = ReactiveCommand.Create( + () => + { + if (CurrentProfile is not null) + { + var curProfileDisplayPriority = CurrentProfile.DisplayPriority; + removeProfileHandler.Execute(new RemoveProfile.Command(CurrentProfile.Id)); + CurrentProfile = Profiles + .Where(x => x.DisplayPriority < curProfileDisplayPriority) + .MinBy(x => x.DisplayPriority); + } + }, + removeCanExecute + ); + var upCommandCanExecute = this.WhenAnyValue( - x => x.ProfilesService.CurrentProfile, - x => x.ProfilesService.CurrentProfile!.DisplayPriority, - selector: (curProf, _) => + x => x.CurrentProfile, + x => x.CurrentProfile!.DisplayPriority, + selector: (curProf, curProfDisplayPriority) => curProf is not null && !curProf.IsDefault - && _profilesService.Profiles.Any(p => - !p.IsDefault && p.DisplayPriority < curProf.DisplayPriority - ) + && listCacheProfilesHandler + .Execute() + .Any(p => !p.IsDefault && p.DisplayPriority < curProfDisplayPriority) ); UpCommand = ReactiveCommand.Create(UpButtonClicked, upCommandCanExecute); var downCommandCanExecute = this.WhenAnyValue( - x => x.ProfilesService.CurrentProfile, - x => x.ProfilesService.CurrentProfile!.DisplayPriority, + x => x.CurrentProfile, + x => x.CurrentProfile!.DisplayPriority, selector: (curProf, _) => curProf is not null && !curProf.IsDefault - && _profilesService.Profiles.Any(p => p.DisplayPriority > curProf.DisplayPriority) + && listCacheProfilesHandler + .Execute() + .Any(p => p.DisplayPriority > curProf.DisplayPriority) ); DownCommand = ReactiveCommand.Create(DownButtonClicked, downCommandCanExecute); - _processSelectorDialogViewModel = processSelectorDialogViewModel; - _addProfile = addProfile; - ShowProcessSelectorInteraction = - new Interaction(); + var editCanExecute = this.WhenAnyValue( - x => x.ProfilesService.CurrentProfile, + x => x.CurrentProfile, curProf => !curProf?.IsDefault ?? false ); - EditButtonCommand = ReactiveCommand.CreateFromTask(EditButtonClickedAsync, editCanExecute); - CopyCommand = ReactiveCommand.CreateFromTask(OnCopyClickedAsync); + EditButtonCommand = ReactiveCommand.CreateFromTask( + async () => + { + var result = await ShowProcessSelectorInteraction.Handle( + processSelectorDialogVmFactory.Create(CurrentProfile?.Process) + ); + if (result is null) + { + return; + } + + CurrentProfile!.Process = result.Process; + CurrentProfile.Name = result.Name; + CurrentProfile.Description = result.Description; + }, + editCanExecute + ); + CopyCommand = ReactiveCommand.CreateFromTask(async () => + { + var newProfile = await ShowProcessSelectorInteraction.Handle( + processSelectorDialogVmFactory.Create() + ); + if (newProfile is null) + { + return; + } + + var copiedProfile = copyProfileHandler.Execute( + new CopyProfile.Command( + CurrentProfile!.Id, + newProfile.Name, + newProfile.Description, + newProfile.Checked, + newProfile.Process, + newProfile.MatchType, + newProfile.ParentClass, + newProfile.WindowClass + ) + ); + setCurrentProfileHandler.Execute(new SetCurrentProfile.Command(copiedProfile)); + CurrentProfile = getCurrentProfileHandler.Execute(); + }); } public Interaction ShowExportFileDialog { get; } public Interaction ShowImportFileDialog { get; } - public IProfilesService ProfilesService + public ProfilesListProfileModel? CurrentProfile { - get => _profilesService; - set => _profilesService = value; + get => _currentProfile; + set => this.RaiseAndSetIfChanged(ref _currentProfile, value); } + public ReadOnlyObservableCollection Profiles { get; } private async Task OnImportClickedAsync() { @@ -122,41 +204,6 @@ private async Task OnExportClickedAsync() _profilesService.WriteProfileToFile(_profilesService.CurrentProfile, result); } - private async Task OnCopyClickedAsync() - { - var newProfile = await ShowProcessSelectorInteraction.Handle( - _processSelectorDialogViewModel - ); - if (newProfile is null) - { - return; - } - - Debug.Assert( - _profilesService.CurrentProfile != null, - "_profilesService.CurrentProfile != null" - ); - var copiedProfile = _profilesService.CopyProfile(_profilesService.CurrentProfile); - copiedProfile.Name = newProfile.Name; - copiedProfile.Description = newProfile.Description; - copiedProfile.Checked = newProfile.Checked; - copiedProfile.Process = newProfile.Process; - copiedProfile.MatchType = newProfile.MatchType; - copiedProfile.ParentClass = newProfile.ParentClass; - copiedProfile.WindowCaption = newProfile.WindowCaption; - copiedProfile.WindowClass = newProfile.WindowClass; - _profilesService.AddProfile(copiedProfile); - } - - private void OnRemoveButtonClicked() - { - Debug.Assert( - _profilesService.CurrentProfile != null, - "_profilesService.CurrentProfile != null" - ); - _profilesService.RemoveProfile(_profilesService.CurrentProfile); - } - private void UpButtonClicked() { Debug.Assert( @@ -173,35 +220,5 @@ private void DownButtonClicked() "_profilesService.CurrentProfile != null" ); _profilesService.MoveProfileDown(_profilesService.CurrentProfile); - // SelectedIndex++; - } - - private async Task EditButtonClickedAsync() - { - var result = await ShowProcessSelectorInteraction.Handle(_processSelectorDialogViewModel); - if (result is null) - { - return; - } - - Debug.Assert( - _profilesService.CurrentProfile != null, - "_profilesService.CurrentProfile != null" - ); - var newProfile = _profilesService.CopyProfile(_profilesService.CurrentProfile); - newProfile.Process = result.Process; - newProfile.Name = result.Name; - newProfile.Description = result.Description; - _profilesService.ReplaceProfile(_profilesService.CurrentProfile, newProfile); - } - - private async Task ShowProcessPickerDialogAsync() - { - var result = await ShowProcessSelectorInteraction.Handle(_processSelectorDialogViewModel); - if (result is null) - { - return; - } - _addProfile.Add(result); } } diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ExportProfile.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ExportProfile.cs new file mode 100644 index 0000000..19c6a95 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ExportProfile.cs @@ -0,0 +1,16 @@ +using System.Linq; +using YMouseButtonControl.Core.Services.Profiles; +using YMouseButtonControl.Core.ViewModels.ProfilesList.Models; + +namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Queries.Profiles; + +public static class ExportProfile +{ + public sealed record Query(int Id); + + public sealed class Handler(IProfilesService profilesService) + { + public ProfilesListProfileModel Execute(Query q) => + new(profilesService.Profiles.First(x => x.Id == q.Id).Clone(), profilesService); + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/GetCurrentProfile.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/GetCurrentProfile.cs new file mode 100644 index 0000000..85bdf22 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/GetCurrentProfile.cs @@ -0,0 +1,17 @@ +using YMouseButtonControl.Core.Services.Profiles; +using YMouseButtonControl.Core.ViewModels.Models; +using YMouseButtonControl.Core.ViewModels.ProfilesList.Models; + +namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Queries.Profiles; + +public static class GetCurrentProfile +{ + public sealed class Handler(IProfilesService profilesService) + { + public ProfilesListProfileModel? Execute() + { + var vm = profilesService.CurrentProfile; + return vm is null ? null : new(vm, profilesService); + } + } +} diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListCacheProfiles.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListCacheProfiles.cs deleted file mode 100644 index 6d5c029..0000000 --- a/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListCacheProfiles.cs +++ /dev/null @@ -1,11 +0,0 @@ -using YMouseButtonControl.Core.Services.Profiles; - -namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Queries.Profiles; - -public static class ListCacheProfiles -{ - public sealed class Handler(IProfilesService profilesService) - { - public void Execute() { } - } -} diff --git a/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListProfiles.cs b/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListProfiles.cs new file mode 100644 index 0000000..aa277c6 --- /dev/null +++ b/YMouseButtonControl.Core/ViewModels/ProfilesList/Queries/Profiles/ListProfiles.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.ObjectModel; +using DynamicData; +using YMouseButtonControl.Core.Services.Profiles; +using YMouseButtonControl.Core.ViewModels.ProfilesList.Models; + +namespace YMouseButtonControl.Core.ViewModels.ProfilesList.Queries.Profiles; + +public static class ListProfiles +{ + public sealed class Handler(IProfilesService profilesService) : IDisposable + { + private IDisposable? _disposable; + + public ReadOnlyObservableCollection Execute() + { + _disposable = profilesService + .Connect() + .Transform(x => new ProfilesListProfileModel(x, profilesService)) + .Bind(out ReadOnlyObservableCollection profiles) + .DisposeMany() + .Subscribe(); + return profiles; + } + + public void Dispose() + { + _disposable?.Dispose(); + } + } +} diff --git a/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj b/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj index 7ea42d6..9ec6f86 100644 --- a/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj +++ b/YMouseButtonControl.Core/YMouseButtonControl.Core.csproj @@ -26,12 +26,12 @@ + - diff --git a/YMouseButtonControl.Linux/Services/ProcessMonitorService.cs b/YMouseButtonControl.Linux/Services/ProcessMonitorService.cs deleted file mode 100644 index c983a6a..0000000 --- a/YMouseButtonControl.Linux/Services/ProcessMonitorService.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Diagnostics; -using YMouseButtonControl.Core.Services.Processes; - -namespace YMouseButtonControl.Linux.Services; - -public class ProcessMonitorService : IProcessMonitorService -{ - public IEnumerable GetProcesses() => - Process - .GetProcesses() - .Select(x => new ProcessModel(x)) - .Where(x => - !string.IsNullOrWhiteSpace(x.Process.MainModule?.ModuleName) - && !string.IsNullOrWhiteSpace(x.Process.ProcessName) - ); -} diff --git a/YMouseButtonControl.MacOS/Services/ProcessMonitorService.cs b/YMouseButtonControl.MacOS/Services/ProcessMonitorService.cs deleted file mode 100644 index 305a767..0000000 --- a/YMouseButtonControl.MacOS/Services/ProcessMonitorService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using YMouseButtonControl.Core.Services.Processes; - -namespace YMouseButtonControl.MacOS.Services; - -public class ProcessMonitorService : IProcessMonitorService -{ - public IEnumerable GetProcesses() => - Process - .GetProcesses() - .Select(x => new ProcessModel(x)) - .Where(x => !string.IsNullOrWhiteSpace(x.Process.ProcessName)); -} diff --git a/YMouseButtonControl.Windows/Services/ProcessMonitorService.cs b/YMouseButtonControl.Windows/Services/ProcessMonitorService.cs deleted file mode 100644 index 29f476b..0000000 --- a/YMouseButtonControl.Windows/Services/ProcessMonitorService.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using System.Linq; -using System.Runtime.Versioning; -using System.Threading.Tasks; -using YMouseButtonControl.Core.Services.Processes; - -namespace YMouseButtonControl.Windows.Services; - -[SupportedOSPlatform("windows5.1.2600")] -public class ProcessMonitorService : IProcessMonitorService -{ - public IEnumerable GetProcesses() - { - var cb = new ConcurrentBag(); - Parallel.ForEach( - Process.GetProcesses().DistinctBy(x => x.ProcessName), - p => - { - try - { - if (p.MainModule != null) - { - cb.Add(p); - } - } - catch (Exception ex) when (ex is Win32Exception or AggregateException) { } - } - ); - return cb.DistinctBy(x => x.MainModule!.FileName) - .Select(x => new ProcessModel(x) - { - Bitmap = GetBitmapStreamFromPath(x.MainModule!.FileName), - }) - .ToList(); - } - - private static MemoryStream? GetBitmapStreamFromPath(string path) - { - if (path is null or "/") - { - return null; - } - - var icon = Icon.ExtractAssociatedIcon(path); - var bmp = icon?.ToBitmap(); - if (bmp is null) - { - return null; - } - var stream = new MemoryStream(); - bmp.Save(stream, ImageFormat.Bmp); - stream.Position = 0; - return stream; - } -} diff --git a/YMouseButtonControl/DependencyInjection/FactoriesBootstrapper.cs b/YMouseButtonControl/DependencyInjection/FactoriesBootstrapper.cs index fc6ce19..d195dc7 100644 --- a/YMouseButtonControl/DependencyInjection/FactoriesBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/FactoriesBootstrapper.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using YMouseButtonControl.Core.ViewModels.MouseComboViewModel; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm; namespace YMouseButtonControl.DependencyInjection; @@ -7,6 +8,8 @@ public static class FactoriesBootstrapper { public static void RegisterFactories(IServiceCollection services) { - services.AddScoped(); + services + .AddScoped() + .AddScoped(); } } diff --git a/YMouseButtonControl/DependencyInjection/FeaturesBootstrapper.cs b/YMouseButtonControl/DependencyInjection/FeaturesBootstrapper.cs index 1d85be5..63fbb3e 100644 --- a/YMouseButtonControl/DependencyInjection/FeaturesBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/FeaturesBootstrapper.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.DependencyInjection; using YMouseButtonControl.Core.ViewModels.MainWindow.Features.Apply; -using YMouseButtonControl.Core.ViewModels.ProfilesList.Features.Add; namespace YMouseButtonControl.DependencyInjection; @@ -8,6 +7,6 @@ public static class FeaturesBootstrapper { public static void RegisterFeatures(IServiceCollection services) { - services.AddTransient().AddTransient(); + services.AddTransient(); } } diff --git a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs index bf3ef3f..ab318e4 100644 --- a/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs +++ b/YMouseButtonControl/DependencyInjection/ServicesBootstrapper.cs @@ -8,6 +8,8 @@ using YMouseButtonControl.Core.Services.Theme; using YMouseButtonControl.Core.ViewModels.AppViewModel; using YMouseButtonControl.Core.ViewModels.GlobalSettingsDialog; +using YMouseButtonControl.Core.ViewModels.ProcessSelectorDialogVm; +using YMouseButtonControl.Core.ViewModels.ProfilesList; namespace YMouseButtonControl.DependencyInjection; @@ -22,6 +24,8 @@ public static void RegisterServices(IServiceCollection services) private static void RegisterCommonServices(IServiceCollection services) { AppHandlerRegistrations.RegisterCommon(services); + ProcessSelectorDialogHandlerRegistrations.RegisterCommon(services); + ProfilesListHandlerRegistrations.RegisterCommon(services); GlobalSettingsDialogHandlerRegistrations.RegisterCommon(services); services .AddScoped() @@ -53,9 +57,8 @@ private static void RegisterLinuxServices(IServiceCollection services) { AppHandlerRegistrations.RegisterLinux(services); GlobalSettingsDialogHandlerRegistrations.RegisterLinux(services); - services - .AddScoped() - .AddScoped(); + ProcessSelectorDialogHandlerRegistrations.RegisterLinux(services); + services.AddScoped(); if (Environment.GetEnvironmentVariable("XDG_SESSION_TYPE") == "x11") { services.AddScoped(); @@ -70,9 +73,9 @@ private static void RegisterLinuxServices(IServiceCollection services) private static void RegisterWindowsServices(IServiceCollection services) { AppHandlerRegistrations.RegisterWindows(services); + ProcessSelectorDialogHandlerRegistrations.RegisterWindows(services); GlobalSettingsDialogHandlerRegistrations.RegisterWindows(services); services - .AddScoped() .AddScoped() .AddScoped(); } @@ -80,9 +83,9 @@ private static void RegisterWindowsServices(IServiceCollection services) private static void RegisterMacOsServices(IServiceCollection services) { AppHandlerRegistrations.RegisterOsx(services); + ProcessSelectorDialogHandlerRegistrations.RegisterOsx(services); GlobalSettingsDialogHandlerRegistrations.RegisterOsx(services); services - .AddScoped() .AddScoped() .AddScoped(); } diff --git a/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml b/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml index 935afc9..48475ed 100644 --- a/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml +++ b/YMouseButtonControl/Views/Dialogs/ProcessSelectorDialog.axaml @@ -38,7 +38,7 @@