mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
142 lines
5.7 KiB
C#
142 lines
5.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using System.Reactive;
|
|
using System.Reactive.Disposables;
|
|
using System.Reactive.Linq;
|
|
using System.Threading.Tasks;
|
|
using Artemis.Core;
|
|
using Artemis.Core.ScriptingProviders;
|
|
using Artemis.Core.Services;
|
|
using Artemis.UI.DryIoc.Factories;
|
|
using Artemis.UI.Screens.Scripting.Dialogs;
|
|
using Artemis.UI.Shared;
|
|
using Artemis.UI.Shared.Services;
|
|
using Artemis.UI.Shared.Services.Builders;
|
|
using DynamicData;
|
|
using DynamicData.Binding;
|
|
using PropertyChanged.SourceGenerator;
|
|
using ReactiveUI;
|
|
|
|
namespace Artemis.UI.Screens.Scripting;
|
|
|
|
public partial class ScriptsDialogViewModel : DialogViewModelBase<object?>
|
|
{
|
|
private readonly Dictionary<ScriptingProvider, IScriptEditorViewModel> _providerViewModels = new();
|
|
private readonly IScriptingService _scriptingService;
|
|
private readonly IWindowService _windowService;
|
|
private ObservableAsPropertyHelper<bool>? _hasScripts;
|
|
[Notify] private ReadOnlyObservableCollection<ScriptConfigurationViewModel> _scriptConfigurations;
|
|
[Notify] private IScriptEditorViewModel? _scriptEditorViewModel;
|
|
[Notify] private ScriptConfigurationViewModel? _selectedScript;
|
|
|
|
public ScriptsDialogViewModel(IScriptingService scriptingService, IWindowService windowService, IProfileService profileService, IScriptVmFactory scriptVmFactory)
|
|
{
|
|
_scriptingService = scriptingService;
|
|
_windowService = windowService;
|
|
|
|
ScriptType = ScriptType.Global;
|
|
ScriptingProviders = new List<ScriptingProvider>(scriptingService.ScriptingProviders);
|
|
|
|
AddScriptConfiguration = ReactiveCommand.CreateFromTask(ExecuteAddScriptConfiguration, Observable.Return(ScriptingProviders.Any()));
|
|
this.WhenAnyValue(vm => vm.SelectedScript).Subscribe(s => SetupScriptEditor(s?.ScriptConfiguration));
|
|
|
|
_scriptConfigurations = new ReadOnlyObservableCollection<ScriptConfigurationViewModel>(new ObservableCollection<ScriptConfigurationViewModel>());
|
|
// TODO: When not bound to a profile, base the contents of the UI on the ScriptingService
|
|
}
|
|
|
|
public ScriptsDialogViewModel(Profile profile, IScriptingService scriptingService, IWindowService windowService, IProfileService profileService, IScriptVmFactory scriptVmFactory)
|
|
: this(scriptingService, windowService, profileService, scriptVmFactory)
|
|
{
|
|
ScriptType = ScriptType.Profile;
|
|
Profile = profile;
|
|
|
|
this.WhenActivated(d =>
|
|
{
|
|
_hasScripts = Profile.ScriptConfigurations.ToObservableChangeSet()
|
|
.Count()
|
|
.Select(c => c > 0)
|
|
.ToProperty(this, vm => vm.HasScripts)
|
|
.DisposeWith(d);
|
|
Profile.ScriptConfigurations.ToObservableChangeSet()
|
|
.Transform(c => scriptVmFactory.ScriptConfigurationViewModel(Profile, c))
|
|
.Bind(out ReadOnlyObservableCollection<ScriptConfigurationViewModel> scriptConfigurationViewModels)
|
|
.Subscribe()
|
|
.DisposeWith(d);
|
|
|
|
ScriptConfigurations = scriptConfigurationViewModels;
|
|
SelectedScript = ScriptConfigurations.FirstOrDefault();
|
|
Disposable.Create(() => profileService.SaveProfile(Profile, false)).DisposeWith(d);
|
|
});
|
|
}
|
|
|
|
public ScriptType ScriptType { get; }
|
|
public List<ScriptingProvider> ScriptingProviders { get; }
|
|
public Profile? Profile { get; }
|
|
public bool HasScripts => _hasScripts?.Value ?? false;
|
|
public ReactiveCommand<Unit, Unit> AddScriptConfiguration { get; }
|
|
|
|
public async Task<bool> CanClose()
|
|
{
|
|
if (!ScriptConfigurations.Any(s => s.ScriptConfiguration.HasChanges))
|
|
return true;
|
|
|
|
bool result = await _windowService.ShowConfirmContentDialog("Discard changes", "One or more scripts still have pending changes, do you want to discard them?");
|
|
if (!result)
|
|
return false;
|
|
|
|
foreach (ScriptConfigurationViewModel scriptConfigurationViewModel in ScriptConfigurations)
|
|
scriptConfigurationViewModel.ScriptConfiguration.DiscardPendingChanges();
|
|
return true;
|
|
}
|
|
|
|
|
|
private void SetupScriptEditor(ScriptConfiguration? scriptConfiguration)
|
|
{
|
|
if (scriptConfiguration == null)
|
|
{
|
|
ScriptEditorViewModel = null;
|
|
return;
|
|
}
|
|
|
|
// The script is null if the provider is missing
|
|
if (scriptConfiguration.Script == null)
|
|
{
|
|
ScriptEditorViewModel = null;
|
|
return;
|
|
}
|
|
|
|
if (!_providerViewModels.TryGetValue(scriptConfiguration.Script.ScriptingProvider, out IScriptEditorViewModel? viewModel))
|
|
{
|
|
viewModel = scriptConfiguration.Script.ScriptingProvider.CreateScriptEditor(ScriptType);
|
|
_providerViewModels.Add(scriptConfiguration.Script.ScriptingProvider, viewModel);
|
|
}
|
|
|
|
ScriptEditorViewModel = viewModel;
|
|
ScriptEditorViewModel.ChangeScript(scriptConfiguration.Script);
|
|
}
|
|
|
|
private async Task ExecuteAddScriptConfiguration()
|
|
{
|
|
await _windowService.CreateContentDialog()
|
|
.WithTitle("Add script")
|
|
.WithViewModel(out ScriptConfigurationCreateViewModel vm)
|
|
.WithCloseButtonText("Cancel")
|
|
.HavingPrimaryButton(b => b.WithText("Confirm").WithCommand(vm.Submit))
|
|
.WithDefaultButton(ContentDialogButton.Primary)
|
|
.ShowAsync();
|
|
|
|
if (vm.ScriptConfiguration == null)
|
|
return;
|
|
|
|
// Add the script to the profile and instantiate it
|
|
if (Profile != null)
|
|
_scriptingService.AddScript(vm.ScriptConfiguration, Profile);
|
|
else
|
|
_scriptingService.AddScript(vm.ScriptConfiguration);
|
|
|
|
// Select the new script
|
|
SelectedScript = ScriptConfigurations.LastOrDefault();
|
|
}
|
|
} |