add option to get storage usage per library (#242)
See how much space each library uses.
This commit is contained in:
parent
bf5402d2bd
commit
92aa5fef88
@ -541,7 +541,7 @@
|
|||||||
<h3 style="margin:0">Introduction timestamp editor</h3>
|
<h3 style="margin:0">Introduction timestamp editor</h3>
|
||||||
<p style="margin:0">All times are displayed in the format (HH:MM:SS)</p>
|
<p style="margin:0">All times are displayed in the format (HH:MM:SS)</p>
|
||||||
<br />
|
<br />
|
||||||
<table class="detailTable">
|
<table class="detailTable">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col" class="detailTableHeaderCell">Episode</th>
|
<th scope="col" class="detailTableHeaderCell">Episode</th>
|
||||||
<th scope="col" class="detailTableHeaderCell">Section</th>
|
<th scope="col" class="detailTableHeaderCell">Section</th>
|
||||||
@ -639,7 +639,7 @@
|
|||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<div id="eraseSeasonContainer" style="display: none;">
|
<div id="eraseSeasonContainer" style="display: none;">
|
||||||
<button id="btnEraseSeasonTimestamps" type="button">
|
<button id="btnEraseSeasonTimestamps" type="button">
|
||||||
Erase all timestamps for this season
|
Erase all timestamps for this season
|
||||||
</button>
|
</button>
|
||||||
@ -647,7 +647,7 @@
|
|||||||
<input type="checkbox" id="eraseSeasonCacheCheckbox" style="margin-left: 10px;">
|
<input type="checkbox" id="eraseSeasonCacheCheckbox" style="margin-left: 10px;">
|
||||||
<label for="eraseSeasonCacheCheckbox" style="margin-left: 5px;">Erase cached fingerprint files</label>
|
<label for="eraseSeasonCacheCheckbox" style="margin-left: 5px;">Erase cached fingerprint files</label>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<br />
|
||||||
|
|
||||||
<button id="btnEraseIntroTimestamps">
|
<button id="btnEraseIntroTimestamps">
|
||||||
Erase all introduction timestamps (globally)
|
Erase all introduction timestamps (globally)
|
||||||
@ -662,6 +662,15 @@
|
|||||||
<input type="checkbox" id="eraseModeCacheCheckbox" style="margin-left: 10px;">
|
<input type="checkbox" id="eraseModeCacheCheckbox" style="margin-left: 10px;">
|
||||||
<label for="eraseModeCacheCheckbox" style="margin-left: 5px;">Erase cached fingerprint files</label>
|
<label for="eraseModeCacheCheckbox" style="margin-left: 5px;">Erase cached fingerprint files</label>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<details id="storage">
|
||||||
|
<br />
|
||||||
|
<summary>Storage Usage</summary>
|
||||||
|
<div class="fieldDescription">
|
||||||
|
See how much space each library uses.
|
||||||
|
</div>
|
||||||
|
<textarea id="storage" rows="20" cols="75" readonly></textarea>
|
||||||
|
</details>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -683,6 +692,7 @@
|
|||||||
// settings elements
|
// settings elements
|
||||||
var visualizer = document.querySelector("details#visualizer");
|
var visualizer = document.querySelector("details#visualizer");
|
||||||
var support = document.querySelector("details#support");
|
var support = document.querySelector("details#support");
|
||||||
|
var storage = document.querySelector("details#storage");
|
||||||
var btnEraseIntroTimestamps = document.querySelector("button#btnEraseIntroTimestamps");
|
var btnEraseIntroTimestamps = document.querySelector("button#btnEraseIntroTimestamps");
|
||||||
var btnEraseCreditTimestamps = document.querySelector("button#btnEraseCreditTimestamps");
|
var btnEraseCreditTimestamps = document.querySelector("button#btnEraseCreditTimestamps");
|
||||||
|
|
||||||
@ -852,6 +862,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fetch the storage whenever the detail section is opened.
|
||||||
|
async function storageToggled() {
|
||||||
|
if (!storage.open) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the support bundle
|
||||||
|
const bundle = await fetchWithAuth("IntroSkipper/Storage", "GET", null);
|
||||||
|
const bundleText = await bundle.text();
|
||||||
|
|
||||||
|
// Display it to the user
|
||||||
|
const ta = document.querySelector("textarea#storage");
|
||||||
|
ta.value = bundleText;
|
||||||
|
}
|
||||||
|
|
||||||
// show changed, populate seasons
|
// show changed, populate seasons
|
||||||
async function showChanged() {
|
async function showChanged() {
|
||||||
clearSelect(selectSeason);
|
clearSelect(selectSeason);
|
||||||
@ -1149,6 +1174,7 @@
|
|||||||
|
|
||||||
visualizer.addEventListener("toggle", visualizerToggled);
|
visualizer.addEventListener("toggle", visualizerToggled);
|
||||||
support.addEventListener("toggle", supportToggled);
|
support.addEventListener("toggle", supportToggled);
|
||||||
|
storage.addEventListener("toggle", storageToggled);
|
||||||
txtOffset.addEventListener("change", renderTroubleshooter);
|
txtOffset.addEventListener("change", renderTroubleshooter);
|
||||||
selectShow.addEventListener("change", showChanged);
|
selectShow.addEventListener("change", showChanged);
|
||||||
selectSeason.addEventListener("change", seasonChanged);
|
selectSeason.addEventListener("change", seasonChanged);
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Net.Mime;
|
using System.Net.Mime;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Common.Api;
|
using MediaBrowser.Common.Api;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Controller.Library;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@ -19,6 +21,7 @@ namespace ConfusedPolarBear.Plugin.IntroSkipper.Controllers;
|
|||||||
[Route("IntroSkipper")]
|
[Route("IntroSkipper")]
|
||||||
public class TroubleshootingController : ControllerBase
|
public class TroubleshootingController : ControllerBase
|
||||||
{
|
{
|
||||||
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IApplicationHost _applicationHost;
|
private readonly IApplicationHost _applicationHost;
|
||||||
private readonly ILogger<TroubleshootingController> _logger;
|
private readonly ILogger<TroubleshootingController> _logger;
|
||||||
|
|
||||||
@ -26,11 +29,14 @@ public class TroubleshootingController : ControllerBase
|
|||||||
/// Initializes a new instance of the <see cref="TroubleshootingController"/> class.
|
/// Initializes a new instance of the <see cref="TroubleshootingController"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="applicationHost">Application host.</param>
|
/// <param name="applicationHost">Application host.</param>
|
||||||
|
/// <param name="libraryManager">Library Manager.</param>
|
||||||
/// <param name="logger">Logger.</param>
|
/// <param name="logger">Logger.</param>
|
||||||
public TroubleshootingController(
|
public TroubleshootingController(
|
||||||
IApplicationHost applicationHost,
|
IApplicationHost applicationHost,
|
||||||
|
ILibraryManager libraryManager,
|
||||||
ILogger<TroubleshootingController> logger)
|
ILogger<TroubleshootingController> logger)
|
||||||
{
|
{
|
||||||
|
_libraryManager = libraryManager;
|
||||||
_applicationHost = applicationHost;
|
_applicationHost = applicationHost;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
@ -85,4 +91,61 @@ public class TroubleshootingController : ControllerBase
|
|||||||
|
|
||||||
return bundle.ToString();
|
return bundle.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a Markdown formatted support bundle.
|
||||||
|
/// </summary>
|
||||||
|
/// <response code="200">Support bundle created.</response>
|
||||||
|
/// <returns>Support bundle.</returns>
|
||||||
|
[HttpGet("Storage")]
|
||||||
|
[Produces(MediaTypeNames.Text.Plain)]
|
||||||
|
public ActionResult<string> GetFreeSpace()
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(Plugin.Instance);
|
||||||
|
var bundle = new StringBuilder();
|
||||||
|
|
||||||
|
var libraries = _libraryManager.GetVirtualFolders();
|
||||||
|
foreach (var library in libraries)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DriveInfo driveInfo = new DriveInfo(library.Locations[0]);
|
||||||
|
// Get available free space in bytes
|
||||||
|
long availableFreeSpace = driveInfo.AvailableFreeSpace;
|
||||||
|
|
||||||
|
// Get total size of the drive in bytes
|
||||||
|
long totalSize = driveInfo.TotalSize;
|
||||||
|
|
||||||
|
// Get total used space in Percentage
|
||||||
|
double usedSpacePercentage = totalSize > 0 ? (totalSize - availableFreeSpace) / (double)totalSize * 100 : 0;
|
||||||
|
|
||||||
|
bundle.Append(CultureInfo.CurrentCulture, $"Library: {library.Name}\n");
|
||||||
|
bundle.Append(CultureInfo.CurrentCulture, $"Drive: {driveInfo.Name}\n");
|
||||||
|
bundle.Append(CultureInfo.CurrentCulture, $"Total Size: {GetHumanReadableSize(totalSize)}\n");
|
||||||
|
bundle.Append(CultureInfo.CurrentCulture, $"Available Free Space: {GetHumanReadableSize(availableFreeSpace)}\n");
|
||||||
|
bundle.Append(CultureInfo.CurrentCulture, $"Total used in Percentage: {Math.Round(usedSpacePercentage, 2)}%\n\n");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Unable to get DriveInfo: {Exception}", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bundle.ToString().TrimEnd('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetHumanReadableSize(long bytes)
|
||||||
|
{
|
||||||
|
string[] sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||||
|
double len = bytes;
|
||||||
|
int order = 0;
|
||||||
|
|
||||||
|
while (len >= 1024 && order < sizes.Length - 1)
|
||||||
|
{
|
||||||
|
order++;
|
||||||
|
len = len / 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{len:0.##} {sizes[order]}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user