From e5a5f10286d5292480da7ed1c2890cce2302605a Mon Sep 17 00:00:00 2001 From: RobertBeekman Date: Sun, 3 Mar 2024 20:19:36 +0100 Subject: [PATCH] Profiles - Added IPluginFeatureDependent interface and implement throughout profiles (#842) * Profiles - Added IPluginFeatureDependent interface and implement througout profiles * Workshop - Include dependencies in profile upload request --- .../Models/IPluginFeatureDependent.cs | 15 +++++++++++ .../Profile/Conditions/AlwaysOnCondition.cs | 11 ++++++++ .../Profile/Conditions/EventCondition.cs | 10 ++++++++ .../Models/Profile/Conditions/ICondition.cs | 2 +- .../Profile/Conditions/PlayOnceCondition.cs | 11 ++++++++ .../Profile/Conditions/StaticCondition.cs | 11 ++++++++ .../Profile/DataBindings/DataBinding.cs | 10 ++++++++ .../Profile/DataBindings/IDataBinding.cs | 2 +- .../Models/Profile/DataModel/DataModelPath.cs | 10 +++++++- src/Artemis.Core/Models/Profile/Folder.cs | 8 ++++++ src/Artemis.Core/Models/Profile/Layer.cs | 12 ++++++++- .../Profile/LayerProperties/ILayerProperty.cs | 2 +- .../Profile/LayerProperties/LayerProperty.cs | 6 +++++ .../Models/Profile/LayerPropertyGroup.cs | 12 ++++++++- src/Artemis.Core/Models/Profile/Profile.cs | 6 +++++ .../Models/Profile/ProfileElement.cs | 5 +++- .../ProfileConfiguration.cs | 25 ++++++++++++++----- .../LayerBrushes/Internal/BaseLayerBrush.cs | 16 +++++++++++- .../LayerEffects/Internal/BaseLayerEffect.cs | 20 +++++++++++++-- .../VisualScripting/Interfaces/INode.cs | 2 +- .../VisualScripting/Interfaces/INodeScript.cs | 2 +- .../VisualScripting/NodeScript.cs | 10 ++++++++ .../VisualScripting/Nodes/Node.cs | 11 +++++++- .../Models/SubmissionWizardState.cs | 3 ++- .../Profile/ProfileSelectionStepViewModel.cs | 4 +-- .../Implementations/ProfileEntrySource.cs | 6 +++-- .../ProfileEntryUploadHandler.cs | 1 + 27 files changed, 209 insertions(+), 24 deletions(-) create mode 100644 src/Artemis.Core/Models/IPluginFeatureDependent.cs diff --git a/src/Artemis.Core/Models/IPluginFeatureDependent.cs b/src/Artemis.Core/Models/IPluginFeatureDependent.cs new file mode 100644 index 000000000..a1531bfc5 --- /dev/null +++ b/src/Artemis.Core/Models/IPluginFeatureDependent.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace Artemis.Core; + +/// +/// Represents a class that depends on plugin features +/// +public interface IPluginFeatureDependent +{ + /// + /// Gets the plugin features this class depends on, may contain the same plugin feature twice if depending on it in multiple ways. + /// + /// A of this class depends on. + public IEnumerable GetFeatureDependencies(); +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Conditions/AlwaysOnCondition.cs b/src/Artemis.Core/Models/Profile/Conditions/AlwaysOnCondition.cs index eeeece9c5..b42c1e1fb 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/AlwaysOnCondition.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/AlwaysOnCondition.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Artemis.Storage.Entities.Profile.Abstract; using Artemis.Storage.Entities.Profile.Conditions; @@ -82,4 +83,14 @@ public class AlwaysOnCondition : ICondition } #endregion + + #region Implementation of IPluginFeatureDependent + + /// + public IEnumerable GetFeatureDependencies() + { + return []; + } + + #endregion } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Conditions/EventCondition.cs b/src/Artemis.Core/Models/Profile/Conditions/EventCondition.cs index f198b5397..826634d67 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/EventCondition.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/EventCondition.cs @@ -325,4 +325,14 @@ public class EventCondition : CorePropertyChanged, INodeScriptCondition } #endregion + + #region Implementation of IPluginFeatureDependent + + /// + public IEnumerable GetFeatureDependencies() + { + return Script.GetFeatureDependencies().Concat(EventPath?.GetFeatureDependencies() ?? []); + } + + #endregion } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Conditions/ICondition.cs b/src/Artemis.Core/Models/Profile/Conditions/ICondition.cs index ef3b17c13..b1d3fa9f4 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/ICondition.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/ICondition.cs @@ -6,7 +6,7 @@ namespace Artemis.Core; /// /// Represents a condition applied to a /// -public interface ICondition : IDisposable, IStorageModel +public interface ICondition : IDisposable, IStorageModel, IPluginFeatureDependent { /// /// Gets the entity used to store this condition diff --git a/src/Artemis.Core/Models/Profile/Conditions/PlayOnceCondition.cs b/src/Artemis.Core/Models/Profile/Conditions/PlayOnceCondition.cs index 40178ad6e..4e3ff0ff1 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/PlayOnceCondition.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/PlayOnceCondition.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Artemis.Storage.Entities.Profile.Abstract; using Artemis.Storage.Entities.Profile.Conditions; @@ -82,4 +83,14 @@ public class PlayOnceCondition : ICondition } #endregion + + #region Implementation of IPluginFeatureDependent + + /// + public IEnumerable GetFeatureDependencies() + { + return []; + } + + #endregion } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Conditions/StaticCondition.cs b/src/Artemis.Core/Models/Profile/Conditions/StaticCondition.cs index 5ab81e22c..fddc62306 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/StaticCondition.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/StaticCondition.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using Artemis.Storage.Entities.Profile.Abstract; using Artemis.Storage.Entities.Profile.Conditions; @@ -159,6 +160,16 @@ public class StaticCondition : CorePropertyChanged, INodeScriptCondition } #endregion + + #region Implementation of IPluginFeatureDependent + + /// + public IEnumerable GetFeatureDependencies() + { + return Script.GetFeatureDependencies(); + } + + #endregion } /// diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs index 42b10ccde..9bf8e94e6 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs @@ -243,4 +243,14 @@ public class DataBinding : IDataBinding } #endregion + + #region Implementation of IPluginFeatureDependent + + /// + public IEnumerable GetFeatureDependencies() + { + return Script.GetFeatureDependencies(); + } + + #endregion } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/DataBindings/IDataBinding.cs b/src/Artemis.Core/Models/Profile/DataBindings/IDataBinding.cs index a5856d018..e87868d52 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/IDataBinding.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/IDataBinding.cs @@ -8,7 +8,7 @@ namespace Artemis.Core; /// Represents a data binding that binds a certain to a value inside a /// /// -public interface IDataBinding : IStorageModel, IDisposable +public interface IDataBinding : IStorageModel, IDisposable, IPluginFeatureDependent { /// /// Gets the layer property the data binding is applied to diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs index 681ddb923..deeff25bc 100644 --- a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs +++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs @@ -11,7 +11,7 @@ namespace Artemis.Core; /// /// Represents a path that points to a property in data model /// -public class DataModelPath : IStorageModel, IDisposable +public class DataModelPath : IStorageModel, IDisposable, IPluginFeatureDependent { private readonly LinkedList _segments; private Expression>? _accessorLambda; @@ -188,6 +188,14 @@ public class DataModelPath : IStorageModel, IDisposable return string.IsNullOrWhiteSpace(Path) ? "this" : Path; } + /// + public IEnumerable GetFeatureDependencies() + { + if (Target == null) + return []; + return [Target.Module]; + } + /// /// Occurs whenever the path becomes invalid /// diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs index 2db77c92b..a845bd331 100644 --- a/src/Artemis.Core/Models/Profile/Folder.cs +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -179,6 +179,14 @@ public sealed class Folder : RenderProfileElement return $"[Folder] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; } + /// + public override IEnumerable GetFeatureDependencies() + { + return LayerEffects.SelectMany(e => e.GetFeatureDependencies()) + .Concat(Children.SelectMany(c => c.GetFeatureDependencies())) + .Concat(DisplayCondition.GetFeatureDependencies()); + } + #region Rendering /// diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 41661290d..2f7de1d48 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -189,6 +189,16 @@ public sealed class Layer : RenderProfileElement return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; } + /// + public override IEnumerable GetFeatureDependencies() + { + return LayerEffects.SelectMany(e => e.GetFeatureDependencies()) + .Concat(LayerBrush?.GetFeatureDependencies() ?? []) + .Concat(General.GetFeatureDependencies()) + .Concat(Transform.GetFeatureDependencies()) + .Concat(DisplayCondition.GetFeatureDependencies()); + } + /// /// Occurs when a property affecting the rendering properties of this layer has been updated /// @@ -768,7 +778,7 @@ public sealed class Layer : RenderProfileElement if (!_leds.Remove(led)) return; - + CalculateRenderProperties(); } diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs index a7b5aa8ef..e3d1f11e4 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs @@ -11,7 +11,7 @@ namespace Artemis.Core; /// initialize these for you. /// /// -public interface ILayerProperty : IStorageModel, IDisposable +public interface ILayerProperty : IStorageModel, IDisposable, IPluginFeatureDependent { /// /// Gets the description attribute applied to this property diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs index 5ecfeeca6..85dcba517 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -54,6 +54,12 @@ public class LayerProperty : CorePropertyChanged, ILayerProperty return $"{Path} - {CurrentValue} ({PropertyType})"; } + /// + public IEnumerable GetFeatureDependencies() + { + return DataBinding.GetFeatureDependencies(); + } + /// /// Releases the unmanaged resources used by the object and optionally releases the managed resources. /// diff --git a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs index 31b4af879..84de5c444 100644 --- a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs +++ b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs @@ -15,7 +15,7 @@ namespace Artemis.Core; /// initialize these for you. /// /// -public abstract class LayerPropertyGroup : IDisposable +public abstract class LayerPropertyGroup : IDisposable, IPluginFeatureDependent { private readonly List _layerProperties; private readonly List _layerPropertyGroups; @@ -343,4 +343,14 @@ public abstract class LayerPropertyGroup : IDisposable Dispose(true); GC.SuppressFinalize(this); } + + #region Implementation of IPluginFeatureDependent + + /// + public IEnumerable GetFeatureDependencies() + { + return LayerProperties.SelectMany(p => p.GetFeatureDependencies()).Concat(LayerPropertyGroups.SelectMany(g => g.GetFeatureDependencies())); + } + + #endregion } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index 2a0d96a23..073afa540 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -171,6 +171,12 @@ public sealed class Profile : ProfileElement return $"[Profile] {nameof(Name)}: {Name}"; } + /// + public override IEnumerable GetFeatureDependencies() + { + return GetRootFolder().GetFeatureDependencies().Concat(Scripts.Select(c => c.ScriptingProvider)); + } + /// /// Populates all the LEDs on the elements in this profile /// diff --git a/src/Artemis.Core/Models/Profile/ProfileElement.cs b/src/Artemis.Core/Models/Profile/ProfileElement.cs index dbce946a8..921910db5 100644 --- a/src/Artemis.Core/Models/Profile/ProfileElement.cs +++ b/src/Artemis.Core/Models/Profile/ProfileElement.cs @@ -9,7 +9,7 @@ namespace Artemis.Core; /// /// Represents an element of a /// -public abstract class ProfileElement : BreakableModel, IDisposable +public abstract class ProfileElement : BreakableModel, IDisposable, IPluginFeatureDependent { internal readonly List ChildrenList; private Guid _entityId; @@ -122,6 +122,9 @@ public abstract class ProfileElement : BreakableModel, IDisposable return $"{nameof(EntityId)}: {EntityId}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}"; } + /// + public abstract IEnumerable GetFeatureDependencies(); + /// /// Occurs when a child was added to the list /// diff --git a/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs b/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs index 04f84c8f1..a4c1e89f4 100644 --- a/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs +++ b/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs @@ -9,13 +9,13 @@ namespace Artemis.Core; /// /// Represents the configuration of a profile, contained in a /// -public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable +public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable, IPluginFeatureDependent { /// /// Represents an empty profile. /// public static readonly ProfileConfiguration Empty = new(ProfileCategory.Empty, "Empty", "Empty"); - + private ActivationBehaviour _activationBehaviour; private bool _activationConditionMet; private ProfileCategory _category; @@ -146,7 +146,7 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable get => _activationConditionMet; private set => SetAndNotify(ref _activationConditionMet, value); } - + /// /// Gets the profile of this profile configuration /// @@ -159,8 +159,8 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable /// /// Gets or sets a boolean indicating whether this profile should fade in and out when enabling or disabling /// - public bool FadeInAndOut - { + public bool FadeInAndOut + { get => _fadeInAndOut; set => SetAndNotify(ref _fadeInAndOut, value); } @@ -188,7 +188,7 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable /// alongside any activation requirements of the , if set /// public NodeScript ActivationCondition { get; } - + /// /// Gets the entity used by this profile config /// @@ -247,6 +247,19 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable return $"[ProfileConfiguration] {nameof(Name)}: {Name}"; } + /// + public IEnumerable GetFeatureDependencies() + { + if (_disposed) + throw new ObjectDisposedException("ProfileConfiguration"); + if (Profile == null) + throw new InvalidOperationException("Cannot determine feature dependencies when the profile is not loaded."); + + return ActivationCondition.GetFeatureDependencies() + .Concat(Profile.GetFeatureDependencies()) + .Concat(Module != null ? [Module] : []); + } + internal void LoadModules(List enabledModules) { if (_disposed) diff --git a/src/Artemis.Core/Plugins/LayerBrushes/Internal/BaseLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrushes/Internal/BaseLayerBrush.cs index cadbd5e7e..8410012a9 100644 --- a/src/Artemis.Core/Plugins/LayerBrushes/Internal/BaseLayerBrush.cs +++ b/src/Artemis.Core/Plugins/LayerBrushes/Internal/BaseLayerBrush.cs @@ -9,7 +9,7 @@ namespace Artemis.Core.LayerBrushes; /// /// For internal use only, please use or or instead /// -public abstract class BaseLayerBrush : BreakableModel, IDisposable +public abstract class BaseLayerBrush : BreakableModel, IDisposable, IPluginFeatureDependent { private LayerBrushType _brushType; private ILayerBrushConfigurationDialog? _configurationDialog; @@ -199,6 +199,20 @@ public abstract class BaseLayerBrush : BreakableModel, IDisposable Dispose(true); GC.SuppressFinalize(this); } + + #region Implementation of IPluginFeatureDependent + + /// + public IEnumerable GetFeatureDependencies() + { + IEnumerable result = [Descriptor.Provider]; + if (BaseProperties != null) + result = result.Concat(BaseProperties.GetFeatureDependencies()); + + return result; + } + + #endregion } /// diff --git a/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs b/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs index 7d300077f..651df32f9 100644 --- a/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs +++ b/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Artemis.Storage.Entities.Profile; using SkiaSharp; @@ -7,7 +9,7 @@ namespace Artemis.Core.LayerEffects; /// /// For internal use only, please use instead /// -public abstract class BaseLayerEffect : BreakableModel, IDisposable, IStorageModel +public abstract class BaseLayerEffect : BreakableModel, IDisposable, IStorageModel, IPluginFeatureDependent { private ILayerEffectConfigurationDialog? _configurationDialog; private LayerEffectDescriptor _descriptor; @@ -164,7 +166,7 @@ public abstract class BaseLayerEffect : BreakableModel, IDisposable, IStorageMod // Not only is this needed to initialize properties on the layer effects, it also prevents implementing anything // but LayerEffect outside the core internal abstract void Initialize(); - + internal void InternalUpdate(Timeline timeline) { BaseProperties?.Update(timeline); @@ -235,4 +237,18 @@ public abstract class BaseLayerEffect : BreakableModel, IDisposable, IStorageMod BaseProperties?.ApplyToEntity(); LayerEffectEntity.PropertyGroup = BaseProperties?.PropertyGroupEntity; } + + #region Implementation of IPluginFeatureDependent + + /// + public IEnumerable GetFeatureDependencies() + { + IEnumerable result = [Descriptor.Provider]; + if (BaseProperties != null) + result = result.Concat(BaseProperties.GetFeatureDependencies()); + + return result; + } + + #endregion } \ No newline at end of file diff --git a/src/Artemis.Core/VisualScripting/Interfaces/INode.cs b/src/Artemis.Core/VisualScripting/Interfaces/INode.cs index 4ce40a0ab..06c382749 100644 --- a/src/Artemis.Core/VisualScripting/Interfaces/INode.cs +++ b/src/Artemis.Core/VisualScripting/Interfaces/INode.cs @@ -8,7 +8,7 @@ namespace Artemis.Core; /// /// Represents a kind of node inside a /// -public interface INode : INotifyPropertyChanged, IBreakableModel +public interface INode : INotifyPropertyChanged, IBreakableModel, IPluginFeatureDependent { /// /// Gets or sets the ID of the node. diff --git a/src/Artemis.Core/VisualScripting/Interfaces/INodeScript.cs b/src/Artemis.Core/VisualScripting/Interfaces/INodeScript.cs index 456692a4d..7ed23e898 100644 --- a/src/Artemis.Core/VisualScripting/Interfaces/INodeScript.cs +++ b/src/Artemis.Core/VisualScripting/Interfaces/INodeScript.cs @@ -8,7 +8,7 @@ namespace Artemis.Core; /// /// Represents a node script /// -public interface INodeScript : INotifyPropertyChanged, IDisposable, IStorageModel +public interface INodeScript : INotifyPropertyChanged, IDisposable, IStorageModel, IPluginFeatureDependent { /// /// Gets the name of the node script. diff --git a/src/Artemis.Core/VisualScripting/NodeScript.cs b/src/Artemis.Core/VisualScripting/NodeScript.cs index e8ccddd4a..8f281f6c3 100644 --- a/src/Artemis.Core/VisualScripting/NodeScript.cs +++ b/src/Artemis.Core/VisualScripting/NodeScript.cs @@ -401,6 +401,16 @@ public abstract class NodeScript : CorePropertyChanged, INodeScript } #endregion + + #region Implementation of IPluginFeatureDependent + + /// + public IEnumerable GetFeatureDependencies() + { + return Nodes.SelectMany(n => n.GetFeatureDependencies()); + } + + #endregion } /// diff --git a/src/Artemis.Core/VisualScripting/Nodes/Node.cs b/src/Artemis.Core/VisualScripting/Nodes/Node.cs index 8d4a40d3d..b3c4ad3ee 100644 --- a/src/Artemis.Core/VisualScripting/Nodes/Node.cs +++ b/src/Artemis.Core/VisualScripting/Nodes/Node.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using Artemis.Core.Events; -using DryIoc; namespace Artemis.Core; @@ -404,4 +403,14 @@ public abstract class Node : BreakableModel, INode } #endregion + + #region Implementation of IPluginFeatureDependent + + /// + public virtual IEnumerable GetFeatureDependencies() + { + return NodeData == null ? [] : [NodeData.Provider]; + } + + #endregion } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs index e06f14ce9..c92f6290b 100644 --- a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs +++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using Artemis.Core; using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Layout; using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Plugin; using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile; @@ -37,7 +38,7 @@ public class SubmissionWizardState : IDisposable public List Images { get; set; } = new(); public IEntrySource? EntrySource { get; set; } - + public void ChangeScreen() where TSubmissionViewModel : SubmissionViewModel { try diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Profile/ProfileSelectionStepViewModel.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Profile/ProfileSelectionStepViewModel.cs index d52457a55..4a5b9cae9 100644 --- a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Profile/ProfileSelectionStepViewModel.cs +++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Profile/ProfileSelectionStepViewModel.cs @@ -65,10 +65,10 @@ public partial class ProfileSelectionStepViewModel : SubmissionViewModel private void ExecuteContinue() { - if (SelectedProfile == null) + if (SelectedProfile?.Profile == null) return; - State.EntrySource = new ProfileEntrySource(SelectedProfile); + State.EntrySource = new ProfileEntrySource(SelectedProfile, SelectedProfile.GetFeatureDependencies().Distinct().ToList()); State.Name = SelectedProfile.Name; State.Icon = SelectedProfile.Icon.GetIconStream(); diff --git a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntrySource.cs b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntrySource.cs index 739f8e28f..16235a935 100644 --- a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntrySource.cs +++ b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntrySource.cs @@ -4,10 +4,12 @@ namespace Artemis.WebClient.Workshop.Handlers.UploadHandlers; public class ProfileEntrySource : IEntrySource { - public ProfileEntrySource(ProfileConfiguration profileConfiguration) + public ProfileEntrySource(ProfileConfiguration profileConfiguration, List dependencies) { ProfileConfiguration = profileConfiguration; + Dependencies = dependencies; } - public ProfileConfiguration ProfileConfiguration { get; set; } + public ProfileConfiguration ProfileConfiguration { get; } + public List Dependencies { get; } } \ No newline at end of file diff --git a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntryUploadHandler.cs b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntryUploadHandler.cs index 012491729..3dbbd68e9 100644 --- a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntryUploadHandler.cs +++ b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntryUploadHandler.cs @@ -31,6 +31,7 @@ public class ProfileEntryUploadHandler : IEntryUploadHandler MultipartFormDataContent content = new(); StreamContent streamContent = new(archiveStream); streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/zip"); + content.Add(JsonContent.Create(source.Dependencies.Select(d => new {PluginId = d.Plugin.Guid, FeatureId = d.Id}).ToList()), "ReleaseDependencies"); content.Add(streamContent, "file", "file.zip"); // Submit