Suggested changes.
@ -393,8 +393,7 @@ namespace Emby.Server.Implementations
|
|||||||
|
|
||||||
if (_creatingInstances.IndexOf(type) != -1)
|
if (_creatingInstances.IndexOf(type) != -1)
|
||||||
{
|
{
|
||||||
Logger.LogError("DI Loop detected.");
|
Logger.LogError("DI Loop detected in the attempted creation of {Type}", type.FullName);
|
||||||
Logger.LogError("Attempted creation of {Type}", type.FullName);
|
|
||||||
foreach (var entry in _creatingInstances)
|
foreach (var entry in _creatingInstances)
|
||||||
{
|
{
|
||||||
Logger.LogError("Called from: {stack}", entry.FullName);
|
Logger.LogError("Called from: {stack}", entry.FullName);
|
||||||
|
@ -73,12 +73,5 @@
|
|||||||
<EmbeddedResource Include="Localization\countries.json" />
|
<EmbeddedResource Include="Localization\countries.json" />
|
||||||
<EmbeddedResource Include="Localization\Core\*.json" />
|
<EmbeddedResource Include="Localization\Core\*.json" />
|
||||||
<EmbeddedResource Include="Localization\Ratings\*.csv" />
|
<EmbeddedResource Include="Localization\Ratings\*.csv" />
|
||||||
<EmbeddedResource Include="Plugins\blank.png" />
|
|
||||||
<EmbeddedResource Include="Plugins\Superceded.png" />
|
|
||||||
<EmbeddedResource Include="Plugins\Disabled.png" />
|
|
||||||
<EmbeddedResource Include="Plugins\NotSupported.png" />
|
|
||||||
<EmbeddedResource Include="Plugins\Malfunction.png" />
|
|
||||||
<EmbeddedResource Include="Plugins\RestartRequired.png" />
|
|
||||||
<EmbeddedResource Include="Plugins\Active.png" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.0 KiB |
@ -1,7 +1,6 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@ -23,8 +22,6 @@ namespace Emby.Server.Implementations
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PluginManager : IPluginManager
|
public class PluginManager : IPluginManager
|
||||||
{
|
{
|
||||||
private const int OffsetFromTopRightCorner = 38;
|
|
||||||
|
|
||||||
private readonly string _pluginsPath;
|
private readonly string _pluginsPath;
|
||||||
private readonly Version _appVersion;
|
private readonly Version _appVersion;
|
||||||
private readonly JsonSerializerOptions _jsonOptions;
|
private readonly JsonSerializerOptions _jsonOptions;
|
||||||
|
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 120 B |
@ -167,7 +167,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Uninstalls a plugin.
|
/// Uninstalls a plugin by version.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pluginId">Plugin id.</param>
|
/// <param name="pluginId">Plugin id.</param>
|
||||||
/// <param name="version">Plugin version.</param>
|
/// <param name="version">Plugin version.</param>
|
||||||
@ -178,7 +178,7 @@ namespace Jellyfin.Api.Controllers
|
|||||||
[Authorize(Policy = Policies.RequiresElevation)]
|
[Authorize(Policy = Policies.RequiresElevation)]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult UninstallPlugin([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version)
|
public ActionResult UninstallPluginByVersion([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version)
|
||||||
{
|
{
|
||||||
if (!_pluginManager.TryGetPlugin(pluginId, version, out var plugin))
|
if (!_pluginManager.TryGetPlugin(pluginId, version, out var plugin))
|
||||||
{
|
{
|
||||||
@ -189,6 +189,35 @@ namespace Jellyfin.Api.Controllers
|
|||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uninstalls a plugin.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pluginId">Plugin id.</param>
|
||||||
|
/// <response code="204">Plugin uninstalled.</response>
|
||||||
|
/// <response code="404">Plugin not found.</response>
|
||||||
|
/// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns>
|
||||||
|
[HttpDelete("{pluginId}")]
|
||||||
|
[Authorize(Policy = Policies.RequiresElevation)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[Obsolete("Please use the UninstallByVersion API.")]
|
||||||
|
public ActionResult UninstallPlugin([FromRoute, Required] Guid pluginId)
|
||||||
|
{
|
||||||
|
// If no version is given, return the current instance.
|
||||||
|
var plugins = _pluginManager.Plugins.Where(p => p.Id.Equals(pluginId));
|
||||||
|
|
||||||
|
// Select the un-instanced one first.
|
||||||
|
var plugin = plugins.FirstOrDefault(p => p.Instance != null);
|
||||||
|
if (plugin == null)
|
||||||
|
{
|
||||||
|
// Then by the status.
|
||||||
|
plugin = plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
_installationManager.UninstallPlugin(plugin!);
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets plugin configuration.
|
/// Gets plugin configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -281,33 +310,6 @@ namespace Jellyfin.Api.Controllers
|
|||||||
return PhysicalFile(imgPath, MimeTypes.GetMimeType(imgPath));
|
return PhysicalFile(imgPath, MimeTypes.GetMimeType(imgPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a plugin's status image.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pluginId">Plugin id.</param>
|
|
||||||
/// <param name="version">Plugin version.</param>
|
|
||||||
/// <response code="200">Plugin image returned.</response>
|
|
||||||
/// <returns>Plugin's image.</returns>
|
|
||||||
[HttpGet("{pluginId}/{version}/StatusImage")]
|
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
||||||
[ProducesImageFile]
|
|
||||||
[AllowAnonymous]
|
|
||||||
public ActionResult GetPluginStatusImage([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version)
|
|
||||||
{
|
|
||||||
if (!_pluginManager.TryGetPlugin(pluginId, version, out var plugin))
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Icons from http://www.fatcow.com/free-icons
|
|
||||||
var status = plugin!.Manifest.Status;
|
|
||||||
|
|
||||||
var type = _pluginManager.GetType();
|
|
||||||
var stream = type.Assembly.GetManifestResourceStream($"{type.Namespace}.Plugins.{status}.png");
|
|
||||||
return File(stream, "image/png");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a plugin's manifest.
|
/// Gets a plugin's manifest.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|