diff --git a/src/Camelot.Services.Abstractions/IAppearanceSettingsService.cs b/src/Camelot.Services.Abstractions/IAppearanceSettingsService.cs new file mode 100644 index 00000000..60dc14ec --- /dev/null +++ b/src/Camelot.Services.Abstractions/IAppearanceSettingsService.cs @@ -0,0 +1,11 @@ +using Camelot.Services.Abstractions.Models; +using Camelot.Services.Abstractions.Models.Enums; + +namespace Camelot.Services.Abstractions; + +public interface IAppearanceSettingsService +{ + AppearanceSettingsModel GetAppearanceSettings(); + + void SaveAppearanceSettings(AppearanceSettingsModel appearanceSettingsModel); +} \ No newline at end of file diff --git a/src/Camelot.Services.Abstractions/Models/AppearanceSettingsModel.cs b/src/Camelot.Services.Abstractions/Models/AppearanceSettingsModel.cs new file mode 100644 index 00000000..d6209283 --- /dev/null +++ b/src/Camelot.Services.Abstractions/Models/AppearanceSettingsModel.cs @@ -0,0 +1,11 @@ +namespace Camelot.Services.Abstractions.Models; + +public class AppearanceSettingsModel +{ + public bool ShowKeyboardShortcuts { get; } + + public AppearanceSettingsModel(bool showKeyboardShortcuts) + { + ShowKeyboardShortcuts = showKeyboardShortcuts; + } +} \ No newline at end of file diff --git a/src/Camelot.Services/AppearanceSettingsService.cs b/src/Camelot.Services/AppearanceSettingsService.cs new file mode 100644 index 00000000..2c12ef5b --- /dev/null +++ b/src/Camelot.Services/AppearanceSettingsService.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Camelot.DataAccess.UnitOfWork; +using Camelot.Services.Abstractions; +using Camelot.Services.Abstractions.Models; +using Camelot.Services.Abstractions.Models.Enums; + +namespace Camelot.Services; + +public class AppearanceSettingsService : IAppearanceSettingsService +{ + private const string SettingsId = "AppearanceSettings"; + private readonly AppearanceSettingsModel _default; + private readonly IUnitOfWorkFactory _unitOfWorkFactory; + private AppearanceSettingsModel _cachedSettingsValue; + public AppearanceSettingsService(IUnitOfWorkFactory unitOfWorkFactory) + { + _unitOfWorkFactory = unitOfWorkFactory; + _default = new AppearanceSettingsModel(false); + GetAppearanceSettings(); + } + + public AppearanceSettingsModel GetAppearanceSettings() + { + if (_cachedSettingsValue == null) + { + using var uow = _unitOfWorkFactory.Create(); + var repository = uow.GetRepository(); + var dbModel = repository.GetById(SettingsId); + if (dbModel != null) + _cachedSettingsValue = dbModel; + else + _cachedSettingsValue = _default; + } + else + { + // we set value of _cachedValue in 'save', + // so no need to read from the repository every time. + } + return _cachedSettingsValue; + } + + + public void SaveAppearanceSettings(AppearanceSettingsModel appearanceSettingsModel) + { + if (appearanceSettingsModel == null) + throw new ArgumentNullException(nameof(appearanceSettingsModel)); + + using var uow = _unitOfWorkFactory.Create(); + var repository = uow.GetRepository(); + repository.Upsert(SettingsId, appearanceSettingsModel); + _cachedSettingsValue = appearanceSettingsModel; + } +} diff --git a/src/Camelot.ViewModels/Implementations/Dialogs/SettingsDialogViewModel.cs b/src/Camelot.ViewModels/Implementations/Dialogs/SettingsDialogViewModel.cs index a2ca2d87..9190e05a 100644 --- a/src/Camelot.ViewModels/Implementations/Dialogs/SettingsDialogViewModel.cs +++ b/src/Camelot.ViewModels/Implementations/Dialogs/SettingsDialogViewModel.cs @@ -17,6 +17,7 @@ public class SettingsDialogViewModel : DialogViewModelBase public ISettingsViewModel GeneralSettingsViewModel { get; set; } public ISettingsViewModel IconsSettingsViewModel { get; set; } + public ISettingsViewModel AppearanceSettingsViewModel { get; set; } public int SelectedIndex { get => _selectedIndex; @@ -31,16 +32,21 @@ public int SelectedIndex public SettingsDialogViewModel( ISettingsViewModel generalSettingsViewModel, + ISettingsViewModel appearanceSettingsViewModel, ISettingsViewModel terminalSettingsViewModel, ISettingsViewModel iconsSettingsViewModel) { TerminalSettingsViewModel = terminalSettingsViewModel; GeneralSettingsViewModel = generalSettingsViewModel; IconsSettingsViewModel = iconsSettingsViewModel; - + AppearanceSettingsViewModel = appearanceSettingsViewModel; + // Items in next array should be in same order as 'tabs' in xaml, + // Otherwise, Activate will called for wrong model. + // TODO: need to make it more dynamic, and not rely on order in view. _settingsViewModels = new[] { generalSettingsViewModel, + appearanceSettingsViewModel, terminalSettingsViewModel, iconsSettingsViewModel }; diff --git a/src/Camelot.ViewModels/Implementations/MainWindow/Operations/TopOperationsViewModel.cs b/src/Camelot.ViewModels/Implementations/MainWindow/Operations/TopOperationsViewModel.cs index f1665c8e..33b94d37 100644 --- a/src/Camelot.ViewModels/Implementations/MainWindow/Operations/TopOperationsViewModel.cs +++ b/src/Camelot.ViewModels/Implementations/MainWindow/Operations/TopOperationsViewModel.cs @@ -22,6 +22,7 @@ public class TopOperationsViewModel : ViewModelBase, ITopOperationsViewModel private readonly IArchiveService _archiveService; private readonly INodesSelectionService _nodesSelectionService; private readonly ISystemDialogService _systemDialogService; + private readonly IAppearanceSettingsService _appearanceSettingsService; public ICommand PackCommand { get; } @@ -31,6 +32,14 @@ public class TopOperationsViewModel : ViewModelBase, ITopOperationsViewModel public ICommand OpenTerminalCommand { get; } + public bool KeyboardShortcutIsVisible + { + get + { + return _appearanceSettingsService.GetAppearanceSettings().ShowKeyboardShortcuts; + } + } + public TopOperationsViewModel( ITerminalService terminalService, IDirectoryService directoryService, @@ -39,7 +48,8 @@ public TopOperationsViewModel( IPathService pathService, IArchiveService archiveService, INodesSelectionService nodesSelectionService, - ISystemDialogService systemDialogService) + ISystemDialogService systemDialogService, + IAppearanceSettingsService appearanceSettingsService) { _terminalService = terminalService; _directoryService = directoryService; @@ -49,6 +59,7 @@ public TopOperationsViewModel( _archiveService = archiveService; _nodesSelectionService = nodesSelectionService; _systemDialogService = systemDialogService; + _appearanceSettingsService = appearanceSettingsService; PackCommand = ReactiveCommand.CreateFromTask(PackAsync); ExtractCommand = ReactiveCommand.Create(ExtractAsync); diff --git a/src/Camelot.ViewModels/Implementations/Settings/AppearanceSettingsViewModel.cs b/src/Camelot.ViewModels/Implementations/Settings/AppearanceSettingsViewModel.cs new file mode 100644 index 00000000..f5c847e6 --- /dev/null +++ b/src/Camelot.ViewModels/Implementations/Settings/AppearanceSettingsViewModel.cs @@ -0,0 +1,46 @@ +using Camelot.Services.Abstractions; +using Camelot.Services.Abstractions.Models; +using Camelot.ViewModels.Interfaces.Settings; +using ReactiveUI.Fody.Helpers; + +namespace Camelot.ViewModels.Implementations.Settings; + +public class AppearanceSettingsViewModel : ViewModelBase, ISettingsViewModel +{ + private readonly IAppearanceSettingsService _appearanceSettingService; + private bool _initialShowKeyboardShortcuts; + + private bool _isActivated; + + [Reactive] + public bool ShowKeyboardShortcuts { get; set; } + + + public bool IsChanged => _initialShowKeyboardShortcuts != ShowKeyboardShortcuts; + + public AppearanceSettingsViewModel( + IAppearanceSettingsService appearanceSettingService) + { + _appearanceSettingService = appearanceSettingService; + } + + public void Activate() + { + if (_isActivated) + { + return; + } + + _isActivated = true; + + var model = _appearanceSettingService.GetAppearanceSettings(); + _initialShowKeyboardShortcuts = model.ShowKeyboardShortcuts; + ShowKeyboardShortcuts = _initialShowKeyboardShortcuts; + } + + public void SaveChanges() + { + var model = new AppearanceSettingsModel(ShowKeyboardShortcuts); + _appearanceSettingService.SaveAppearanceSettings(model); + } +} \ No newline at end of file diff --git a/src/Camelot/DependencyInjection/ServicesBootstrapper.cs b/src/Camelot/DependencyInjection/ServicesBootstrapper.cs index 8108f688..3bfe0400 100644 --- a/src/Camelot/DependencyInjection/ServicesBootstrapper.cs +++ b/src/Camelot/DependencyInjection/ServicesBootstrapper.cs @@ -177,6 +177,10 @@ private static void RegisterCommonServices(IMutableDependencyResolver services, resolver.GetRequiredService(), resolver.GetRequiredService() )); + + services.RegisterLazySingleton(() => new AppearanceSettingsService( + resolver.GetRequiredService() + )); } private static void RegisterPlatformSpecificServices(IMutableDependencyResolver services, IReadonlyDependencyResolver resolver) diff --git a/src/Camelot/DependencyInjection/ViewModelsBootstrapper.cs b/src/Camelot/DependencyInjection/ViewModelsBootstrapper.cs index 593ae04e..5c75f82a 100644 --- a/src/Camelot/DependencyInjection/ViewModelsBootstrapper.cs +++ b/src/Camelot/DependencyInjection/ViewModelsBootstrapper.cs @@ -213,12 +213,17 @@ private static void RegisterCommonViewModels(IMutableDependencyResolver services )); services.Register(() => new SettingsDialogViewModel( resolver.GetRequiredService(), + resolver.GetRequiredService(), resolver.GetRequiredService(), resolver.GetRequiredService() )); services.Register(() => new IconsSettingsViewModel( resolver.GetRequiredService() )); + services.Register(() => new AppearanceSettingsViewModel( + resolver.GetRequiredService() + )); + services.RegisterLazySingleton(() => new FilePropertiesBehavior( resolver.GetRequiredService() )); @@ -312,7 +317,8 @@ private static void RegisterCommonViewModels(IMutableDependencyResolver services resolver.GetRequiredService(), resolver.GetRequiredService(), resolver.GetRequiredService(), - resolver.GetRequiredService() + resolver.GetRequiredService(), + resolver.GetRequiredService() )); services.RegisterLazySingleton(() => new OperationStateViewModelFactory( resolver.GetRequiredService() diff --git a/src/Camelot/Properties/Resources.Designer.cs b/src/Camelot/Properties/Resources.Designer.cs index a3568ce2..396f4b7f 100644 --- a/src/Camelot/Properties/Resources.Designer.cs +++ b/src/Camelot/Properties/Resources.Designer.cs @@ -914,5 +914,15 @@ public static string SupportedOnWindowsOnly { return ResourceManager.GetString("SupportedOnWindowsOnly", resourceCulture); } } + public static string Appearance { + get { + return ResourceManager.GetString("Appearance", resourceCulture); + } + } + public static string ShowKeyboardShortcuts { + get { + return ResourceManager.GetString("ShowKeyboardShortcuts", resourceCulture); + } + } } } diff --git a/src/Camelot/Properties/Resources.resx b/src/Camelot/Properties/Resources.resx index ad062707..b0d24f0f 100644 --- a/src/Camelot/Properties/Resources.resx +++ b/src/Camelot/Properties/Resources.resx @@ -552,4 +552,10 @@ * Supported on Windows only + + Appearance + + + Show keyboard shortcuts + \ No newline at end of file diff --git a/src/Camelot/Styles/MainWindow.xaml b/src/Camelot/Styles/MainWindow.xaml index 83b40578..1b970875 100644 --- a/src/Camelot/Styles/MainWindow.xaml +++ b/src/Camelot/Styles/MainWindow.xaml @@ -35,6 +35,14 @@ + +