mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Merge branch 'development'
This commit is contained in:
commit
13c4820738
6
.github/workflows/docfx.yml
vendored
6
.github/workflows/docfx.yml
vendored
@ -12,9 +12,9 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v2
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: "8.0.x"
|
dotnet-version: "8.0.x"
|
||||||
- name: Setup DocFX
|
- name: Setup DocFX
|
||||||
@ -26,7 +26,7 @@ jobs:
|
|||||||
- name: Build DocFX
|
- name: Build DocFX
|
||||||
run: docfx docfx/docfx_project/docfx.json
|
run: docfx docfx/docfx_project/docfx.json
|
||||||
- name: Upload to FTP
|
- name: Upload to FTP
|
||||||
uses: SamKirkland/FTP-Deploy-Action@4.3.2
|
uses: maverage/FTP-Deploy-Action@4.3.5
|
||||||
with:
|
with:
|
||||||
server: www360.your-server.de
|
server: www360.your-server.de
|
||||||
protocol: ftps
|
protocol: ftps
|
||||||
|
|||||||
10
.github/workflows/master.yml
vendored
10
.github/workflows/master.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
|||||||
version-number: ${{ steps.get-version.outputs.version-number }}
|
version-number: ${{ steps.get-version.outputs.version-number }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Get Version String
|
- name: Get Version String
|
||||||
@ -49,16 +49,16 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Artemis
|
- name: Checkout Artemis
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
path: Artemis
|
path: Artemis
|
||||||
- name: Checkout Plugins
|
- name: Checkout Plugins
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: Artemis-RGB/Artemis.Plugins
|
repository: Artemis-RGB/Artemis.Plugins
|
||||||
path: Artemis.Plugins
|
path: Artemis.Plugins
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v2
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: '8.0.x'
|
dotnet-version: '8.0.x'
|
||||||
- name: Publish Artemis
|
- name: Publish Artemis
|
||||||
@ -73,7 +73,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: artemis-${{ matrix.rid }}-${{ needs.version.outputs.version-number }}
|
name: artemis-${{ matrix.rid }}-${{ needs.version.outputs.version-number }}
|
||||||
path: build/${{ matrix.rid }}
|
path: build/${{ matrix.rid }}
|
||||||
|
|||||||
6
.github/workflows/nuget.yml
vendored
6
.github/workflows/nuget.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
|||||||
version-number: ${{ steps.get-version.outputs.version-number }}
|
version-number: ${{ steps.get-version.outputs.version-number }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Get Version String
|
- name: Get Version String
|
||||||
@ -35,11 +35,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v2
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: '8.0.x'
|
dotnet-version: '8.0.x'
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Pack Artemis.Core
|
- name: Pack Artemis.Core
|
||||||
run: dotnet pack -c Release -p:Version=${{ needs.version.outputs.version-number }} -p:BuildingNuget=True src/Artemis.Core/Artemis.Core.csproj
|
run: dotnet pack -c Release -p:Version=${{ needs.version.outputs.version-number }} -p:BuildingNuget=True src/Artemis.Core/Artemis.Core.csproj
|
||||||
- name: Pack Artemis.UI.Shared
|
- name: Pack Artemis.UI.Shared
|
||||||
|
|||||||
@ -9,13 +9,8 @@ namespace Artemis.Core;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents basic info about a plugin feature and contains a reference to the instance of said feature
|
/// Represents basic info about a plugin feature and contains a reference to the instance of said feature
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PluginFeatureInfo : CorePropertyChanged, IPrerequisitesSubject
|
public class PluginFeatureInfo : IPrerequisitesSubject
|
||||||
{
|
{
|
||||||
private string? _description;
|
|
||||||
private PluginFeature? _instance;
|
|
||||||
private Exception? _loadException;
|
|
||||||
private string _name = null!;
|
|
||||||
|
|
||||||
internal PluginFeatureInfo(Plugin plugin, Type featureType, PluginFeatureEntity pluginFeatureEntity, PluginFeatureAttribute? attribute)
|
internal PluginFeatureInfo(Plugin plugin, Type featureType, PluginFeatureEntity pluginFeatureEntity, PluginFeatureAttribute? attribute)
|
||||||
{
|
{
|
||||||
Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin));
|
Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin));
|
||||||
@ -53,29 +48,17 @@ public class PluginFeatureInfo : CorePropertyChanged, IPrerequisitesSubject
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the exception thrown while loading
|
/// Gets the exception thrown while loading
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Exception? LoadException
|
public Exception? LoadException { get; internal set; }
|
||||||
{
|
|
||||||
get => _loadException;
|
|
||||||
internal set => SetAndNotify(ref _loadException, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the feature
|
/// The name of the feature
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name
|
public string Name { get; }
|
||||||
{
|
|
||||||
get => _name;
|
|
||||||
internal set => SetAndNotify(ref _name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A short description of the feature
|
/// A short description of the feature
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Description
|
public string? Description { get; }
|
||||||
{
|
|
||||||
get => _description;
|
|
||||||
set => SetAndNotify(ref _description, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marks the feature to always be enabled as long as the plugin is enabled and cannot be disabled.
|
/// Marks the feature to always be enabled as long as the plugin is enabled and cannot be disabled.
|
||||||
@ -92,19 +75,7 @@ public class PluginFeatureInfo : CorePropertyChanged, IPrerequisitesSubject
|
|||||||
/// Gets the feature this info is associated with
|
/// Gets the feature this info is associated with
|
||||||
/// <para>Note: <see langword="null" /> if the associated <see cref="Plugin" /> is disabled</para>
|
/// <para>Note: <see langword="null" /> if the associated <see cref="Plugin" /> is disabled</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PluginFeature? Instance
|
public PluginFeature? Instance { get; internal set; }
|
||||||
{
|
|
||||||
get => _instance;
|
|
||||||
internal set => SetAndNotify(ref _instance, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal PluginFeatureEntity Entity { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Instance?.Id ?? "Uninitialized feature";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public List<PluginPrerequisite> Prerequisites { get; } = new();
|
public List<PluginPrerequisite> Prerequisites { get; } = new();
|
||||||
@ -117,4 +88,12 @@ public class PluginFeatureInfo : CorePropertyChanged, IPrerequisitesSubject
|
|||||||
{
|
{
|
||||||
return PlatformPrerequisites.All(p => p.IsMet());
|
return PlatformPrerequisites.All(p => p.IsMet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Instance?.Id ?? "Uninitialized feature";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal PluginFeatureEntity Entity { get; }
|
||||||
}
|
}
|
||||||
@ -6,237 +6,134 @@ using System.Text.Json.Serialization;
|
|||||||
namespace Artemis.Core;
|
namespace Artemis.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents basic info about a plugin and contains a reference to the instance of said plugin
|
/// Represents basic info about a plugin and contains a reference to the instance of said plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PluginInfo : CorePropertyChanged, IPrerequisitesSubject
|
public class PluginInfo : IPrerequisitesSubject
|
||||||
{
|
{
|
||||||
private Version? _api = new(1, 0, 0);
|
|
||||||
private string? _author;
|
|
||||||
private bool _autoEnableFeatures = true;
|
|
||||||
private string? _description;
|
|
||||||
private Guid _guid;
|
|
||||||
private string? _icon;
|
|
||||||
private string _main = null!;
|
|
||||||
private string _name = null!;
|
|
||||||
private PluginPlatform? _platforms;
|
|
||||||
private Plugin _plugin = null!;
|
|
||||||
private Uri? _repository;
|
|
||||||
private bool _requiresAdmin;
|
|
||||||
private string _version = null!;
|
|
||||||
private Uri? _website;
|
|
||||||
private Uri? _helpPage;
|
|
||||||
private bool _hotReloadSupported = true;
|
|
||||||
private Uri? _license;
|
|
||||||
private string? _licenseName;
|
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
internal PluginInfo()
|
internal PluginInfo()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The plugins GUID
|
/// The plugins GUID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public Guid Guid
|
public Guid Guid { get; internal init; }
|
||||||
{
|
|
||||||
get => _guid;
|
|
||||||
internal set => SetAndNotify(ref _guid, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the plugin
|
/// The name of the plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public string Name
|
public string Name { get; internal init; } = null!;
|
||||||
{
|
|
||||||
get => _name;
|
|
||||||
internal set => SetAndNotify(ref _name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A short description of the plugin
|
/// The version of the plugin
|
||||||
/// </summary>
|
|
||||||
public string? Description
|
|
||||||
{
|
|
||||||
get => _description;
|
|
||||||
set => SetAndNotify(ref _description, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the author of this plugin
|
|
||||||
/// </summary>
|
|
||||||
public string? Author
|
|
||||||
{
|
|
||||||
get => _author;
|
|
||||||
set => SetAndNotify(ref _author, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the website of this plugin or its author
|
|
||||||
/// </summary>
|
|
||||||
public Uri? Website
|
|
||||||
{
|
|
||||||
get => _website;
|
|
||||||
set => SetAndNotify(ref _website, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the repository of this plugin
|
|
||||||
/// </summary>
|
|
||||||
public Uri? Repository
|
|
||||||
{
|
|
||||||
get => _repository;
|
|
||||||
set => SetAndNotify(ref _repository, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the help page of this plugin
|
|
||||||
/// </summary>
|
|
||||||
public Uri? HelpPage
|
|
||||||
{
|
|
||||||
get => _helpPage;
|
|
||||||
set => SetAndNotify(ref _helpPage, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the help page of this plugin
|
|
||||||
/// </summary>
|
|
||||||
public Uri? License
|
|
||||||
{
|
|
||||||
get => _license;
|
|
||||||
set => SetAndNotify(ref _license, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the author of this plugin
|
|
||||||
/// </summary>
|
|
||||||
public string? LicenseName
|
|
||||||
{
|
|
||||||
get => _licenseName;
|
|
||||||
set => SetAndNotify(ref _licenseName, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The plugins display icon that's shown in the settings see <see href="https://materialdesignicons.com" /> for
|
|
||||||
/// available icons
|
|
||||||
/// </summary>
|
|
||||||
public string? Icon
|
|
||||||
{
|
|
||||||
get => _icon;
|
|
||||||
set => SetAndNotify(ref _icon, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The version of the plugin
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public string Version
|
public string Version { get; internal init; } = null!;
|
||||||
{
|
|
||||||
get => _version;
|
|
||||||
internal set => SetAndNotify(ref _version, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main entry DLL, should contain a class implementing Plugin
|
/// The main entry DLL, should contain a class implementing Plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public string Main
|
public string Main { get; internal init; } = null!;
|
||||||
{
|
|
||||||
get => _main;
|
|
||||||
internal set => SetAndNotify(ref _main, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a boolean indicating whether this plugin should automatically enable all its features when it is first
|
/// A short description of the plugin
|
||||||
/// loaded
|
|
||||||
/// </summary>
|
|
||||||
public bool AutoEnableFeatures
|
|
||||||
{
|
|
||||||
get => _autoEnableFeatures;
|
|
||||||
set => SetAndNotify(ref _autoEnableFeatures, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a boolean indicating whether this plugin requires elevated admin privileges
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public bool RequiresAdmin
|
public string? Description { get; internal init; }
|
||||||
{
|
|
||||||
get => _requiresAdmin;
|
/// <summary>
|
||||||
internal set => SetAndNotify(ref _requiresAdmin, value);
|
/// Gets or sets the author of this plugin
|
||||||
}
|
/// </summary>
|
||||||
|
[JsonInclude]
|
||||||
|
public string? Author { get; internal init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the website of this plugin or its author
|
||||||
|
/// </summary>
|
||||||
|
[JsonInclude]
|
||||||
|
public Uri? Website { get; internal init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the repository of this plugin
|
||||||
|
/// </summary>
|
||||||
|
[JsonInclude]
|
||||||
|
public Uri? Repository { get; internal init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the help page of this plugin
|
||||||
|
/// </summary>
|
||||||
|
[JsonInclude]
|
||||||
|
public Uri? HelpPage { get; internal init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the help page of this plugin
|
||||||
|
/// </summary>
|
||||||
|
[JsonInclude]
|
||||||
|
public Uri? License { get; internal init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the author of this plugin
|
||||||
|
/// </summary>
|
||||||
|
[JsonInclude]
|
||||||
|
public string? LicenseName { get; internal init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The plugins display icon that's shown in the settings see <see href="https://materialdesignicons.com" /> for
|
||||||
|
/// available icons
|
||||||
|
/// </summary>
|
||||||
|
[JsonInclude]
|
||||||
|
public string? Icon { get; internal init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating whether this plugin requires elevated admin privileges
|
||||||
|
/// </summary>
|
||||||
|
[JsonInclude]
|
||||||
|
public bool RequiresAdmin { get; internal init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a boolean indicating whether hot reloading this plugin is supported
|
/// Gets or sets a boolean indicating whether hot reloading this plugin is supported
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HotReloadSupported
|
[JsonInclude]
|
||||||
{
|
public bool HotReloadSupported { get; internal init; } = true;
|
||||||
get => _hotReloadSupported;
|
|
||||||
set => SetAndNotify(ref _hotReloadSupported, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets
|
/// Gets
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public PluginPlatform? Platforms
|
public PluginPlatform? Platforms { get; internal init; }
|
||||||
{
|
|
||||||
get => _platforms;
|
|
||||||
internal set => SetAndNotify(ref _platforms, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the API version the plugin was built for
|
/// Gets the API version the plugin was built for
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonInclude]
|
[JsonInclude]
|
||||||
public Version? Api
|
public Version? Api { get; internal init; } = new(1, 0, 0);
|
||||||
{
|
|
||||||
get => _api;
|
|
||||||
internal set => SetAndNotify(ref _api, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin this info is associated with
|
/// Gets the plugin this info is associated with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Plugin Plugin
|
public Plugin Plugin { get; internal set; } = null!;
|
||||||
{
|
|
||||||
get => _plugin;
|
|
||||||
internal set => SetAndNotify(ref _plugin, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a string representing either a full path pointing to an svg or the markdown icon
|
/// Gets a string representing either a full path pointing to an svg or the markdown icon
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string? ResolvedIcon
|
public string? ResolvedIcon => Icon == null ? null : Icon.Contains('.') ? Plugin.ResolveRelativePath(Icon) : Icon;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Icon == null)
|
|
||||||
return null;
|
|
||||||
return Icon.Contains('.') ? Plugin.ResolveRelativePath(Icon) : Icon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether this plugin is compatible with the current operating system and API version
|
/// Gets a boolean indicating whether this plugin is compatible with the current operating system and API version
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
public bool IsCompatible => Platforms.MatchesCurrentOperatingSystem() && Api != null && Api.Major >= Constants.PluginApiVersion;
|
public bool IsCompatible => Platforms.MatchesCurrentOperatingSystem() && Api != null && Api.Major >= Constants.PluginApiVersion;
|
||||||
|
|
||||||
internal string PreferredPluginDirectory => $"{Main.Split(".dll")[0].Replace("/", "").Replace("\\", "")}-{Guid.ToString().Substring(0, 8)}";
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{Name} v{Version} - {Guid}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<PluginPrerequisite> Prerequisites { get; } = new();
|
public List<PluginPrerequisite> Prerequisites { get; } = new();
|
||||||
@ -245,9 +142,18 @@ public class PluginInfo : CorePropertyChanged, IPrerequisitesSubject
|
|||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<PluginPrerequisite> PlatformPrerequisites => Prerequisites.Where(p => p.AppliesToPlatform());
|
public IEnumerable<PluginPrerequisite> PlatformPrerequisites => Prerequisites.Where(p => p.AppliesToPlatform());
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
internal string PreferredPluginDirectory => $"{Main.Split(".dll")[0].Replace("/", "").Replace("\\", "")}-{Guid.ToString().Substring(0, 8)}";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool ArePrerequisitesMet()
|
public bool ArePrerequisitesMet()
|
||||||
{
|
{
|
||||||
return PlatformPrerequisites.All(p => p.IsMet());
|
return PlatformPrerequisites.All(p => p.IsMet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Name} v{Version} - {Guid}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -18,7 +18,7 @@ internal class M0003SystemTextJson : IProfileMigration
|
|||||||
ConvertToSystemTextJson(profileJson);
|
ConvertToSystemTextJson(profileJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConvertToSystemTextJson(JsonObject jsonObject)
|
internal static void ConvertToSystemTextJson(JsonObject jsonObject)
|
||||||
{
|
{
|
||||||
FilterType(jsonObject);
|
FilterType(jsonObject);
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ internal class M0003SystemTextJson : IProfileMigration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FilterType(JsonObject jsonObject)
|
internal static void FilterType(JsonObject jsonObject)
|
||||||
{
|
{
|
||||||
// Replace or remove $type depending on whether there's a matching JsonDerivedType
|
// Replace or remove $type depending on whether there's a matching JsonDerivedType
|
||||||
// This could be done with reflection but that would mean this migration automatically gains new behaviour over time.
|
// This could be done with reflection but that would mean this migration automatically gains new behaviour over time.
|
||||||
|
|||||||
147
src/Artemis.Storage/Migrations/Profile/M0004NodeStorage.cs
Normal file
147
src/Artemis.Storage/Migrations/Profile/M0004NodeStorage.cs
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace Artemis.Storage.Migrations.Profile
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Migrates nodes to be provider-based.
|
||||||
|
/// This requires giving them a ProviderId and updating the their namespaces to match the namespace of the new plugin.
|
||||||
|
/// </summary>
|
||||||
|
internal class M0004NodeStorage : IProfileMigration
|
||||||
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public M0004NodeStorage(ILogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public int Version => 4;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Migrate(JsonObject configurationJson, JsonObject profileJson)
|
||||||
|
{
|
||||||
|
MigrateNodeScript(configurationJson["ActivationCondition"]);
|
||||||
|
|
||||||
|
JsonArray? folders = profileJson["Folders"]?.AsArray();
|
||||||
|
JsonArray? layers = profileJson["Layers"]?.AsArray();
|
||||||
|
|
||||||
|
if (folders != null)
|
||||||
|
{
|
||||||
|
foreach (JsonNode? folder in folders)
|
||||||
|
MigrateProfileElement(folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layers != null)
|
||||||
|
{
|
||||||
|
foreach (JsonNode? layer in layers)
|
||||||
|
{
|
||||||
|
MigrateProfileElement(layer);
|
||||||
|
MigratePropertyGroup(layer?["GeneralPropertyGroup"]);
|
||||||
|
MigratePropertyGroup(layer?["TransformPropertyGroup"]);
|
||||||
|
MigratePropertyGroup(layer?["LayerBrush"]?["PropertyGroup"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigrateProfileElement(JsonNode? profileElement)
|
||||||
|
{
|
||||||
|
if (profileElement == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
JsonArray? layerEffects = profileElement["LayerEffects"]?.AsArray();
|
||||||
|
if (layerEffects != null)
|
||||||
|
{
|
||||||
|
foreach (JsonNode? layerEffect in layerEffects)
|
||||||
|
MigratePropertyGroup(layerEffect?["PropertyGroup"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode? displayCondition = profileElement["DisplayCondition"];
|
||||||
|
if (displayCondition != null)
|
||||||
|
MigrateNodeScript(displayCondition["Script"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigratePropertyGroup(JsonNode? propertyGroup)
|
||||||
|
{
|
||||||
|
if (propertyGroup == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
JsonArray? properties = propertyGroup["Properties"]?.AsArray();
|
||||||
|
JsonArray? propertyGroups = propertyGroup["PropertyGroups"]?.AsArray();
|
||||||
|
if (properties != null)
|
||||||
|
{
|
||||||
|
foreach (JsonNode? property in properties)
|
||||||
|
MigrateNodeScript(property?["DataBinding"]?["NodeScript"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertyGroups != null)
|
||||||
|
{
|
||||||
|
foreach (JsonNode? childPropertyGroup in propertyGroups)
|
||||||
|
MigratePropertyGroup(childPropertyGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigrateNodeScript(JsonNode? nodeScript)
|
||||||
|
{
|
||||||
|
JsonArray? nodes = nodeScript?["Nodes"]?.AsArray();
|
||||||
|
if (nodes == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (JsonNode? jsonNode in nodes)
|
||||||
|
{
|
||||||
|
if (jsonNode == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
JsonObject nodeObject = jsonNode.AsObject();
|
||||||
|
nodeObject["Storage"] = MigrateNodeStorageJson(nodeObject["Storage"]?.GetValue<string>(), _logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string? MigrateNodeStorageJson(string? json, ILogger logger)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(json))
|
||||||
|
return json;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
JsonDocument jsonDocument = JsonDocument.Parse(json);
|
||||||
|
if (jsonDocument.RootElement.ValueKind != JsonValueKind.Object)
|
||||||
|
return json;
|
||||||
|
|
||||||
|
JsonObject? jsonObject = JsonObject.Create(jsonDocument.RootElement);
|
||||||
|
if (jsonObject == null)
|
||||||
|
return json;
|
||||||
|
|
||||||
|
if (jsonObject["$type"] != null && jsonObject["$values"] != null)
|
||||||
|
{
|
||||||
|
JsonArray? values = jsonObject["$values"]?.AsArray();
|
||||||
|
if (values != null)
|
||||||
|
{
|
||||||
|
foreach (JsonNode? jsonNode in values.ToList())
|
||||||
|
{
|
||||||
|
if (jsonNode is JsonObject childObject)
|
||||||
|
M0003SystemTextJson.ConvertToSystemTextJson(childObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return values.ToJsonString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
M0003SystemTextJson.ConvertToSystemTextJson(jsonObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonObject.ToJsonString();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.Error(e, "Failed to migrate node storage JSON");
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
119
src/Artemis.Storage/Migrations/Storage/M0026NodeStorage.cs
Normal file
119
src/Artemis.Storage/Migrations/Storage/M0026NodeStorage.cs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Artemis.Storage.Migrations.Profile;
|
||||||
|
using LiteDB;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace Artemis.Storage.Migrations.Storage;
|
||||||
|
|
||||||
|
public class M0026NodeStorage : IStorageMigration
|
||||||
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public M0026NodeStorage(ILogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
public int UserVersion => 26;
|
||||||
|
|
||||||
|
public void Apply(LiteRepository repository)
|
||||||
|
{
|
||||||
|
ILiteCollection<BsonDocument> categoryCollection = repository.Database.GetCollection("ProfileCategoryEntity");
|
||||||
|
List<BsonDocument> toUpdate = new();
|
||||||
|
foreach (BsonDocument profileCategoryBson in categoryCollection.FindAll())
|
||||||
|
{
|
||||||
|
BsonArray? profiles = profileCategoryBson["ProfileConfigurations"]?.AsArray;
|
||||||
|
if (profiles != null)
|
||||||
|
{
|
||||||
|
foreach (BsonValue profile in profiles)
|
||||||
|
{
|
||||||
|
profile["Version"] = 4;
|
||||||
|
MigrateNodeScript(profile["ActivationCondition"]?.AsDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
toUpdate.Add(profileCategoryBson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
categoryCollection.Update(toUpdate);
|
||||||
|
|
||||||
|
ILiteCollection<BsonDocument> collection = repository.Database.GetCollection("ProfileEntity");
|
||||||
|
List<BsonDocument> profilesToUpdate = new();
|
||||||
|
foreach (BsonDocument profileBson in collection.FindAll())
|
||||||
|
{
|
||||||
|
BsonArray? folders = profileBson["Folders"]?.AsArray;
|
||||||
|
BsonArray? layers = profileBson["Layers"]?.AsArray;
|
||||||
|
|
||||||
|
if (folders != null)
|
||||||
|
{
|
||||||
|
foreach (BsonValue folder in folders)
|
||||||
|
MigrateProfileElement(folder.AsDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layers != null)
|
||||||
|
{
|
||||||
|
foreach (BsonValue layer in layers)
|
||||||
|
{
|
||||||
|
MigrateProfileElement(layer.AsDocument);
|
||||||
|
MigratePropertyGroup(layer.AsDocument["GeneralPropertyGroup"].AsDocument);
|
||||||
|
MigratePropertyGroup(layer.AsDocument["TransformPropertyGroup"].AsDocument);
|
||||||
|
MigratePropertyGroup(layer.AsDocument["LayerBrush"]?["PropertyGroup"].AsDocument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
profilesToUpdate.Add(profileBson);
|
||||||
|
}
|
||||||
|
|
||||||
|
collection.Update(profilesToUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigrateProfileElement(BsonDocument profileElement)
|
||||||
|
{
|
||||||
|
BsonArray? layerEffects = profileElement["LayerEffects"]?.AsArray;
|
||||||
|
if (layerEffects != null)
|
||||||
|
{
|
||||||
|
foreach (BsonValue layerEffect in layerEffects)
|
||||||
|
MigratePropertyGroup(layerEffect.AsDocument["PropertyGroup"].AsDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
BsonValue? displayCondition = profileElement["DisplayCondition"];
|
||||||
|
if (displayCondition != null)
|
||||||
|
MigrateNodeScript(displayCondition.AsDocument["Script"].AsDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigratePropertyGroup(BsonDocument? propertyGroup)
|
||||||
|
{
|
||||||
|
if (propertyGroup == null || propertyGroup.Keys.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BsonArray? properties = propertyGroup["Properties"]?.AsArray;
|
||||||
|
BsonArray? propertyGroups = propertyGroup["PropertyGroups"]?.AsArray;
|
||||||
|
|
||||||
|
if (properties != null)
|
||||||
|
{
|
||||||
|
foreach (BsonValue property in properties)
|
||||||
|
MigrateNodeScript(property.AsDocument["DataBinding"]?["NodeScript"]?.AsDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertyGroups != null)
|
||||||
|
{
|
||||||
|
foreach (BsonValue childPropertyGroup in propertyGroups)
|
||||||
|
MigratePropertyGroup(childPropertyGroup.AsDocument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigrateNodeScript(BsonDocument? nodeScript)
|
||||||
|
{
|
||||||
|
if (nodeScript == null || nodeScript.Keys.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BsonArray? nodes = nodeScript["Nodes"]?.AsArray;
|
||||||
|
if (nodes == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (BsonValue node in nodes)
|
||||||
|
{
|
||||||
|
// Migrate the storage of the node
|
||||||
|
node["Storage"] = M0004NodeStorage.MigrateNodeStorageJson(node.AsDocument["Storage"]?.AsString, _logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,7 +9,7 @@ namespace Artemis.Storage;
|
|||||||
|
|
||||||
public class StorageMigrationService
|
public class StorageMigrationService
|
||||||
{
|
{
|
||||||
public const int PROFILE_VERSION = 3;
|
public const int PROFILE_VERSION = 4;
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IList<IStorageMigration> _migrations;
|
private readonly IList<IStorageMigration> _migrations;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user