mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
273 lines
10 KiB
C#
273 lines
10 KiB
C#
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Artemis.Core;
|
|
using Artemis.Core.Modules;
|
|
using Artemis.Core.Services;
|
|
using Artemis.UI.Shared;
|
|
using Artemis.UI.Shared.Services.Interfaces;
|
|
using Avalonia.Media.Imaging;
|
|
using Avalonia.Svg.Skia;
|
|
using Avalonia.Threading;
|
|
using Material.Icons;
|
|
using Newtonsoft.Json;
|
|
using ReactiveUI;
|
|
|
|
namespace Artemis.UI.Screens.Sidebar
|
|
{
|
|
public class ProfileConfigurationEditViewModel : DialogViewModelBase<bool>
|
|
{
|
|
private readonly ProfileCategory _profileCategory;
|
|
private readonly IProfileService _profileService;
|
|
private readonly IWindowService _windowService;
|
|
private ProfileConfigurationIconType _iconType;
|
|
private ProfileConfigurationHotkeyMode _hotkeyMode;
|
|
private ObservableCollection<ProfileIconViewModel>? _materialIcons;
|
|
private ProfileConfiguration _profileConfiguration;
|
|
private string _profileName;
|
|
private Bitmap? _selectedBitmapSource;
|
|
private ProfileIconViewModel? _selectedMaterialIcon;
|
|
private ProfileModuleViewModel? _selectedModule;
|
|
private string? _selectedIconPath;
|
|
private SvgImage? _selectedSvgSource;
|
|
private Hotkey? _enableHotkey;
|
|
private Hotkey? _disableHotkey;
|
|
|
|
public ProfileConfigurationEditViewModel(ProfileCategory profileCategory, ProfileConfiguration? profileConfiguration, IWindowService windowService,
|
|
IProfileService profileService, IPluginManagementService pluginManagementService)
|
|
{
|
|
_profileCategory = profileCategory;
|
|
_windowService = windowService;
|
|
_profileService = profileService;
|
|
_profileConfiguration = profileConfiguration ?? profileService.CreateProfileConfiguration(profileCategory, "New profile", Enum.GetValues<MaterialIconKind>().First().ToString());
|
|
_profileName = _profileConfiguration.Name;
|
|
_iconType = _profileConfiguration.Icon.IconType;
|
|
_hotkeyMode = _profileConfiguration.HotkeyMode;
|
|
if (_profileConfiguration.EnableHotkey != null)
|
|
_enableHotkey = new Hotkey() {Key = _profileConfiguration.EnableHotkey.Key, Modifiers = profileConfiguration.EnableHotkey.Modifiers};
|
|
if (_profileConfiguration.DisableHotkey != null)
|
|
_disableHotkey = new Hotkey() {Key = _profileConfiguration.DisableHotkey.Key, Modifiers = profileConfiguration.DisableHotkey.Modifiers};
|
|
|
|
IsNew = profileConfiguration == null;
|
|
DisplayName = IsNew ? "Artemis | Add profile" : "Artemis | Edit profile";
|
|
Modules = new ObservableCollection<ProfileModuleViewModel>(
|
|
pluginManagementService.GetFeaturesOfType<Module>().Where(m => !m.IsAlwaysAvailable).Select(m => new ProfileModuleViewModel(m))
|
|
);
|
|
|
|
Dispatcher.UIThread.Post(LoadIcon, DispatcherPriority.Background);
|
|
}
|
|
|
|
public bool IsNew { get; }
|
|
|
|
public ProfileConfiguration ProfileConfiguration
|
|
{
|
|
get => _profileConfiguration;
|
|
set => this.RaiseAndSetIfChanged(ref _profileConfiguration, value);
|
|
}
|
|
|
|
public string ProfileName
|
|
{
|
|
get => _profileName;
|
|
set => this.RaiseAndSetIfChanged(ref _profileName, value);
|
|
}
|
|
|
|
public ProfileConfigurationHotkeyMode HotkeyMode
|
|
{
|
|
get => _hotkeyMode;
|
|
set => this.RaiseAndSetIfChanged(ref _hotkeyMode, value);
|
|
}
|
|
|
|
public Hotkey? EnableHotkey
|
|
{
|
|
get => _enableHotkey;
|
|
set => this.RaiseAndSetIfChanged(ref _enableHotkey, value);
|
|
}
|
|
|
|
public Hotkey? DisableHotkey
|
|
{
|
|
get => _disableHotkey;
|
|
set => this.RaiseAndSetIfChanged(ref _disableHotkey, value);
|
|
}
|
|
|
|
public ObservableCollection<ProfileModuleViewModel> Modules { get; }
|
|
|
|
public ProfileModuleViewModel? SelectedModule
|
|
{
|
|
get => _selectedModule;
|
|
set => this.RaiseAndSetIfChanged(ref _selectedModule, value);
|
|
}
|
|
|
|
public async Task Import()
|
|
{
|
|
if (!IsNew)
|
|
return;
|
|
|
|
string[]? result = await _windowService.CreateOpenFileDialog()
|
|
.HavingFilter(f => f.WithExtension("json").WithName("Artemis profile"))
|
|
.ShowAsync();
|
|
|
|
if (result == null)
|
|
return;
|
|
|
|
string json = await File.ReadAllTextAsync(result[0]);
|
|
ProfileConfigurationExportModel? profileConfigurationExportModel = null;
|
|
try
|
|
{
|
|
profileConfigurationExportModel = JsonConvert.DeserializeObject<ProfileConfigurationExportModel>(json, IProfileService.ExportSettings);
|
|
}
|
|
catch (JsonException e)
|
|
{
|
|
_windowService.ShowExceptionDialog("Import profile failed", e);
|
|
}
|
|
|
|
if (profileConfigurationExportModel == null)
|
|
{
|
|
await _windowService.ShowConfirmContentDialog("Import profile", "Failed to import this profile, make sure it is a valid Artemis profile.", "Confirm", null);
|
|
return;
|
|
}
|
|
|
|
// Remove the temporary profile configuration
|
|
_profileService.RemoveProfileConfiguration(_profileConfiguration);
|
|
// Import the new profile configuration
|
|
_profileService.ImportProfile(_profileCategory, profileConfigurationExportModel);
|
|
|
|
Close(true);
|
|
}
|
|
|
|
public async Task Delete()
|
|
{
|
|
if (IsNew)
|
|
return;
|
|
if (!await _windowService.ShowConfirmContentDialog("Delete profile", "Are you sure you want to permanently delete this profile?"))
|
|
return;
|
|
|
|
_profileService.RemoveProfileConfiguration(_profileConfiguration);
|
|
Close(true);
|
|
}
|
|
|
|
public async Task Confirm()
|
|
{
|
|
ProfileConfiguration.Name = ProfileName;
|
|
ProfileConfiguration.Module = SelectedModule?.Module;
|
|
ProfileConfiguration.HotkeyMode = HotkeyMode;
|
|
ProfileConfiguration.EnableHotkey = EnableHotkey;
|
|
ProfileConfiguration.DisableHotkey = DisableHotkey;
|
|
|
|
await SaveIcon();
|
|
|
|
_profileService.SaveProfileConfigurationIcon(ProfileConfiguration);
|
|
_profileService.SaveProfileCategory(_profileCategory);
|
|
Close(true);
|
|
}
|
|
|
|
public void Cancel()
|
|
{
|
|
if (IsNew)
|
|
_profileService.RemoveProfileConfiguration(_profileConfiguration);
|
|
Close(false);
|
|
}
|
|
|
|
#region Icon
|
|
|
|
public ProfileConfigurationIconType IconType
|
|
{
|
|
get => _iconType;
|
|
set => this.RaiseAndSetIfChanged(ref _iconType, value);
|
|
}
|
|
|
|
public ObservableCollection<ProfileIconViewModel>? MaterialIcons
|
|
{
|
|
get => _materialIcons;
|
|
set => this.RaiseAndSetIfChanged(ref _materialIcons, value);
|
|
}
|
|
|
|
public ProfileIconViewModel? SelectedMaterialIcon
|
|
{
|
|
get => _selectedMaterialIcon;
|
|
set => this.RaiseAndSetIfChanged(ref _selectedMaterialIcon, value);
|
|
}
|
|
|
|
public Bitmap? SelectedBitmapSource
|
|
{
|
|
get => _selectedBitmapSource;
|
|
set => this.RaiseAndSetIfChanged(ref _selectedBitmapSource, value);
|
|
}
|
|
|
|
public SvgImage? SelectedSvgSource
|
|
{
|
|
get => _selectedSvgSource;
|
|
set => this.RaiseAndSetIfChanged(ref _selectedSvgSource, value);
|
|
}
|
|
|
|
private void LoadIcon()
|
|
{
|
|
// Preselect the icon based on streams if needed
|
|
if (_profileConfiguration.Icon.IconType == ProfileConfigurationIconType.BitmapImage)
|
|
{
|
|
SelectedBitmapSource = new Bitmap(_profileConfiguration.Icon.GetIconStream());
|
|
}
|
|
else if (_profileConfiguration.Icon.IconType == ProfileConfigurationIconType.SvgImage)
|
|
{
|
|
SvgSource newSource = new();
|
|
newSource.Load(_profileConfiguration.Icon.GetIconStream());
|
|
SelectedSvgSource = new SvgImage {Source = newSource};
|
|
}
|
|
|
|
// Prepare the contents of the dropdown box, it should be virtualized so no need to wait with this
|
|
ObservableCollection<ProfileIconViewModel> icons = new(Enum.GetValues<MaterialIconKind>()
|
|
.Select(kind => new ProfileIconViewModel(kind))
|
|
.DistinctBy(vm => vm.DisplayName)
|
|
.OrderBy(vm => vm.DisplayName));
|
|
|
|
// Preselect the icon or fall back to a random one
|
|
SelectedMaterialIcon = !IsNew && Enum.TryParse(_profileConfiguration.Icon.IconName, out MaterialIconKind enumValue)
|
|
? icons.FirstOrDefault(m => m.Icon == enumValue)
|
|
: icons.ElementAt(new Random().Next(0, icons.Count - 1));
|
|
MaterialIcons = icons;
|
|
}
|
|
|
|
private async Task SaveIcon()
|
|
{
|
|
if (IconType == ProfileConfigurationIconType.MaterialIcon && SelectedMaterialIcon != null)
|
|
ProfileConfiguration.Icon.SetIconByName(SelectedMaterialIcon.Icon.ToString());
|
|
else if (_selectedIconPath != null)
|
|
{
|
|
await using FileStream fileStream = File.OpenRead(_selectedIconPath);
|
|
ProfileConfiguration.Icon.SetIconByStream(Path.GetFileName(_selectedIconPath), fileStream);
|
|
}
|
|
}
|
|
|
|
public async Task BrowseBitmapFile()
|
|
{
|
|
string[]? result = await _windowService.CreateOpenFileDialog()
|
|
.HavingFilter(f => f.WithExtension("png").WithExtension("jpg").WithExtension("bmp").WithName("Bitmap image"))
|
|
.ShowAsync();
|
|
|
|
if (result == null)
|
|
return;
|
|
|
|
SelectedBitmapSource = new Bitmap(result[0]);
|
|
_selectedIconPath = result[0];
|
|
}
|
|
|
|
public async Task BrowseSvgFile()
|
|
{
|
|
string[]? result = await _windowService.CreateOpenFileDialog()
|
|
.HavingFilter(f => f.WithExtension("svg").WithName("SVG image"))
|
|
.ShowAsync();
|
|
|
|
if (result == null)
|
|
return;
|
|
|
|
SvgSource newSource = new();
|
|
newSource.Load(result[0]);
|
|
|
|
SelectedSvgSource = new SvgImage {Source = newSource};
|
|
_selectedIconPath = result[0];
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |