Add v5 only preferences

This commit is contained in:
ahjephson
2025-10-22 10:40:14 +01:00
parent 5b4fbde7b2
commit 3d0dbde9f4
14 changed files with 204 additions and 16 deletions

View File

@@ -371,7 +371,7 @@ namespace Lantean.QBTMud.Components
{ {
var torrents = GetAffectedTorrentHashes(type); var torrents = GetAffectedTorrentHashes(type);
await DialogService.InvokeDeleteTorrentDialog(ApiClient, [.. torrents]); await DialogService.InvokeDeleteTorrentDialog(ApiClient, Preferences?.ConfirmTorrentDeletion == true, [.. torrents]);
} }
private Dictionary<string, int> GetTags() private Dictionary<string, int> GetTags()

View File

@@ -68,6 +68,21 @@
</MudCardContent> </MudCardContent>
</MudCard> </MudCard>
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.subtitle2">Confirmation</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent Class="pt-0">
<MudGrid>
<MudItem xs="12">
<FieldSwitch Label="Confirm torrent recheck" Value="ConfirmTorrentRecheck" ValueChanged="ConfirmTorrentRecheckChanged" />
</MudItem>
</MudGrid>
</MudCardContent>
</MudCard>
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4 mt-4"> <MudCard Elevation="1" Class="ml-4 mr-4 mb-4 mt-4">
<MudCardHeader> <MudCardHeader>
<CardHeaderContent> <CardHeaderContent>

View File

@@ -16,6 +16,8 @@ namespace Lantean.QBTMud.Components.Options
protected int SaveResumeDataInterval { get; private set; } protected int SaveResumeDataInterval { get; private set; }
protected int TorrentFileSizeLimit { get; private set; } protected int TorrentFileSizeLimit { get; private set; }
protected bool RecheckCompletedTorrents { get; private set; } protected bool RecheckCompletedTorrents { get; private set; }
protected bool ConfirmTorrentRecheck { get; private set; }
protected string? AppInstanceName { get; private set; } protected string? AppInstanceName { get; private set; }
protected int RefreshInterval { get; private set; } protected int RefreshInterval { get; private set; }
protected bool ResolvePeerCountries { get; private set; } protected bool ResolvePeerCountries { get; private set; }
@@ -97,6 +99,7 @@ namespace Lantean.QBTMud.Components.Options
SaveResumeDataInterval = Preferences.SaveResumeDataInterval; SaveResumeDataInterval = Preferences.SaveResumeDataInterval;
TorrentFileSizeLimit = Preferences.TorrentFileSizeLimit / 1024 / 1024; TorrentFileSizeLimit = Preferences.TorrentFileSizeLimit / 1024 / 1024;
RecheckCompletedTorrents = Preferences.RecheckCompletedTorrents; RecheckCompletedTorrents = Preferences.RecheckCompletedTorrents;
ConfirmTorrentRecheck = Preferences.ConfirmTorrentRecheck;
AppInstanceName = Preferences.AppInstanceName; AppInstanceName = Preferences.AppInstanceName;
RefreshInterval = Preferences.RefreshInterval; RefreshInterval = Preferences.RefreshInterval;
ResolvePeerCountries = Preferences.ResolvePeerCountries; ResolvePeerCountries = Preferences.ResolvePeerCountries;
@@ -209,6 +212,13 @@ namespace Lantean.QBTMud.Components.Options
await PreferencesChanged.InvokeAsync(UpdatePreferences); await PreferencesChanged.InvokeAsync(UpdatePreferences);
} }
protected async Task ConfirmTorrentRecheckChanged(bool value)
{
ConfirmTorrentRecheck = value;
UpdatePreferences.ConfirmTorrentRecheck = value;
await PreferencesChanged.InvokeAsync(UpdatePreferences);
}
protected async Task AppInstanceNameChanged(string value) protected async Task AppInstanceNameChanged(string value)
{ {
AppInstanceName = value; AppInstanceName = value;

View File

@@ -17,6 +17,24 @@
</MudCardContent> </MudCardContent>
</MudCard> </MudCard>
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.subtitle2">Transfer List</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent Class="pt-0">
<MudGrid>
<MudItem xs="12">
<FieldSwitch Label="Confirm when deleting torrents" Value="ConfirmTorrentDeletion" ValueChanged="ConfirmTorrentDeletionChanged" />
</MudItem>
<MudItem xs="12">
<FieldSwitch Label="Show external IP in status bar" Value="StatusBarExternalIp" ValueChanged="StatusBarExternalIpChanged" />
</MudItem>
</MudGrid>
</MudCardContent>
</MudCard>
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4"> <MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
<MudCardHeader> <MudCardHeader>
<CardHeaderContent> <CardHeaderContent>

View File

@@ -4,6 +4,10 @@ namespace Lantean.QBTMud.Components.Options
{ {
public partial class BehaviourOptions : Options public partial class BehaviourOptions : Options
{ {
protected bool ConfirmTorrentDeletion { get; set; }
protected bool StatusBarExternalIp { get; set; }
protected bool FileLogEnabled { get; set; } protected bool FileLogEnabled { get; set; }
protected string? FileLogPath { get; set; } protected string? FileLogPath { get; set; }
@@ -27,6 +31,8 @@ namespace Lantean.QBTMud.Components.Options
return false; return false;
} }
ConfirmTorrentDeletion = Preferences.ConfirmTorrentDeletion;
StatusBarExternalIp = Preferences.StatusBarExternalIp;
FileLogEnabled = Preferences.FileLogEnabled; FileLogEnabled = Preferences.FileLogEnabled;
FileLogPath = Preferences.FileLogPath; FileLogPath = Preferences.FileLogPath;
FileLogBackupEnabled = Preferences.FileLogBackupEnabled; FileLogBackupEnabled = Preferences.FileLogBackupEnabled;
@@ -39,6 +45,20 @@ namespace Lantean.QBTMud.Components.Options
return true; return true;
} }
protected async Task ConfirmTorrentDeletionChanged(bool value)
{
ConfirmTorrentDeletion = value;
UpdatePreferences.ConfirmTorrentDeletion = value;
await PreferencesChanged.InvokeAsync(UpdatePreferences);
}
protected async Task StatusBarExternalIpChanged(bool value)
{
StatusBarExternalIp = value;
UpdatePreferences.StatusBarExternalIp = value;
await PreferencesChanged.InvokeAsync(UpdatePreferences);
}
protected async Task FileLogEnabledChanged(bool value) protected async Task FileLogEnabledChanged(bool value)
{ {
FileLogEnabled = value; FileLogEnabled = value;

View File

@@ -7,7 +7,6 @@ using Lantean.QBTMud.Services;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop; using Microsoft.JSInterop;
using MudBlazor; using MudBlazor;
using System.Linq;
namespace Lantean.QBTMud.Components namespace Lantean.QBTMud.Components
{ {
@@ -162,7 +161,7 @@ namespace Lantean.QBTMud.Components
protected async Task Remove() protected async Task Remove()
{ {
var deleted = await DialogService.InvokeDeleteTorrentDialog(ApiClient, Hashes.ToArray()); var deleted = await DialogService.InvokeDeleteTorrentDialog(ApiClient, Preferences?.ConfirmTorrentDeletion == true, Hashes.ToArray());
if (deleted) if (deleted)
{ {
@@ -258,7 +257,7 @@ namespace Lantean.QBTMud.Components
protected async Task ForceRecheck() protected async Task ForceRecheck()
{ {
await ApiClient.RecheckTorrents(null, Hashes.ToArray()); await DialogService.ForceRecheckAsync(ApiClient, Hashes, Preferences?.ConfirmTorrentRecheck == true);
} }
protected async Task ForceReannounce() protected async Task ForceReannounce()

View File

@@ -122,7 +122,7 @@ namespace Lantean.QBTMud.Helpers
_ = await apiClient.AddTorrent(addTorrentParams); _ = await apiClient.AddTorrent(addTorrentParams);
} }
public static async Task<bool> InvokeDeleteTorrentDialog(this IDialogService dialogService, IApiClient apiClient, params string[] hashes) public static async Task<bool> InvokeDeleteTorrentDialog(this IDialogService dialogService, IApiClient apiClient, bool confirmTorrentDeletion, params string[] hashes)
{ {
if (hashes.Length == 0) if (hashes.Length == 0)
{ {
@@ -134,6 +134,12 @@ namespace Lantean.QBTMud.Helpers
{ nameof(DeleteDialog.Count), hashes.Length } { nameof(DeleteDialog.Count), hashes.Length }
}; };
if (!confirmTorrentDeletion)
{
await apiClient.DeleteTorrents(hashes: hashes, deleteFiles: false);
return true;
}
var reference = await dialogService.ShowAsync<DeleteDialog>($"Remove torrent{(hashes.Length == 1 ? "" : "s")}?", parameters, ConfirmDialogOptions); var reference = await dialogService.ShowAsync<DeleteDialog>($"Remove torrent{(hashes.Length == 1 ? "" : "s")}?", parameters, ConfirmDialogOptions);
var dialogResult = await reference.Result; var dialogResult = await reference.Result;
if (dialogResult is null || dialogResult.Canceled || dialogResult.Data is null) if (dialogResult is null || dialogResult.Canceled || dialogResult.Data is null)
@@ -146,6 +152,28 @@ namespace Lantean.QBTMud.Helpers
return true; return true;
} }
public static async Task ForceRecheckAsync(this IDialogService dialogService, IApiClient apiClient, IEnumerable<string> hashes, bool confirmTorrentRecheck)
{
var hashArray = hashes?.ToArray() ?? [];
if (hashArray.Length == 0)
{
return;
}
if (confirmTorrentRecheck)
{
var content = $"Are you sure you want to recheck the selected torrent{(hashArray.Length == 1 ? "" : "s")}?";
var confirmed = await dialogService.ShowConfirmDialog("Force recheck", content);
if (!confirmed)
{
return;
}
}
await apiClient.RecheckTorrents(null, hashArray);
}
public static async Task InvokeDownloadRateDialog(this IDialogService dialogService, IApiClient apiClient, long rate, IEnumerable<string> hashes) public static async Task InvokeDownloadRateDialog(this IDialogService dialogService, IApiClient apiClient, long rate, IEnumerable<string> hashes)
{ {
Func<long, string> valueDisplayFunc = v => v == Limits.NoLimit ? "∞" : v.ToString(); Func<long, string> valueDisplayFunc = v => v == Limits.NoLimit ? "∞" : v.ToString();

View File

@@ -33,6 +33,14 @@
} }
<MudSpacer /> <MudSpacer />
<MudText Class="mx-2 mb-1 d-none d-sm-flex">@DisplayHelpers.Size(MainData?.ServerState.FreeSpaceOnDisk, "Free space: ")</MudText> <MudText Class="mx-2 mb-1 d-none d-sm-flex">@DisplayHelpers.Size(MainData?.ServerState.FreeSpaceOnDisk, "Free space: ")</MudText>
@{
var externalIpLabel = Preferences?.StatusBarExternalIp == true ? BuildExternalIpLabel(MainData?.ServerState) : null;
}
@if (!string.IsNullOrEmpty(externalIpLabel))
{
<MudDivider Vertical="true" Class="d-none d-sm-flex" />
<MudText Class="mx-2 mb-1 d-none d-sm-flex">@externalIpLabel</MudText>
}
<MudDivider Vertical="true" Class="d-none d-sm-flex" /> <MudDivider Vertical="true" Class="d-none d-sm-flex" />
<MudText Class="mx-2 mb-1 d-none d-sm-flex">DHT @(MainData?.ServerState.DHTNodes ?? 0) nodes</MudText> <MudText Class="mx-2 mb-1 d-none d-sm-flex">DHT @(MainData?.ServerState.DHTNodes ?? 0) nodes</MudText>
<MudDivider Vertical="true" Class="d-none d-sm-flex" /> <MudDivider Vertical="true" Class="d-none d-sm-flex" />

View File

@@ -201,6 +201,32 @@ namespace Lantean.QBTMud.Layout
}; };
} }
private static string? BuildExternalIpLabel(ServerState? serverState)
{
if (serverState is null)
{
return null;
}
var v4 = serverState.LastExternalAddressV4;
var v6 = serverState.LastExternalAddressV6;
var hasV4 = !string.IsNullOrWhiteSpace(v4);
var hasV6 = !string.IsNullOrWhiteSpace(v6);
if (!hasV4 && !hasV6)
{
return "External IP: N/A";
}
if (hasV4 && hasV6)
{
return $"External IPs: {v4}, {v6}";
}
var address = hasV4 ? v4 : v6;
return $"External IP: {address}";
}
private void OnCategoryChanged(string category) private void OnCategoryChanged(string category)
{ {
if (Category == category) if (Category == category)

View File

@@ -27,7 +27,17 @@
long uploadRateLimit, long uploadRateLimit,
bool useAltSpeedLimits, bool useAltSpeedLimits,
bool useSubcategories, bool useSubcategories,
float writeCacheOverload) : base(connectionStatus, dHTNodes, downloadInfoData, downloadInfoSpeed, downloadRateLimit, uploadInfoData, uploadInfoSpeed, uploadRateLimit) float writeCacheOverload,
string lastExternalAddressV4,
string lastExternalAddressV6) : base(
connectionStatus,
dHTNodes,
downloadInfoData,
downloadInfoSpeed,
downloadRateLimit,
uploadInfoData,
uploadInfoSpeed,
uploadRateLimit)
{ {
AllTimeDownloaded = allTimeDownloaded; AllTimeDownloaded = allTimeDownloaded;
AllTimeUploaded = allTimeUploaded; AllTimeUploaded = allTimeUploaded;
@@ -46,6 +56,8 @@
UseAltSpeedLimits = useAltSpeedLimits; UseAltSpeedLimits = useAltSpeedLimits;
UseSubcategories = useSubcategories; UseSubcategories = useSubcategories;
WriteCacheOverload = writeCacheOverload; WriteCacheOverload = writeCacheOverload;
LastExternalAddressV4 = lastExternalAddressV4;
LastExternalAddressV6 = lastExternalAddressV6;
} }
public ServerState() public ServerState()
@@ -85,5 +97,9 @@
public bool UseSubcategories { get; set; } public bool UseSubcategories { get; set; }
public float WriteCacheOverload { get; set; } public float WriteCacheOverload { get; set; }
public string LastExternalAddressV4 { get; set; } = string.Empty;
public string LastExternalAddressV6 { get; set; } = string.Empty;
} }
} }

View File

@@ -145,7 +145,9 @@ namespace Lantean.QBTMud.Services
serverState.UploadRateLimit.GetValueOrDefault(), serverState.UploadRateLimit.GetValueOrDefault(),
serverState.UseAltSpeedLimits.GetValueOrDefault(), serverState.UseAltSpeedLimits.GetValueOrDefault(),
serverState.UseSubcategories.GetValueOrDefault(), serverState.UseSubcategories.GetValueOrDefault(),
serverState.WriteCacheOverload.GetValueOrDefault()); serverState.WriteCacheOverload.GetValueOrDefault(),
serverState.LastExternalAddressV4 ?? string.Empty,
serverState.LastExternalAddressV6 ?? string.Empty);
} }
public bool MergeMainData(QBitTorrentClient.Models.MainData mainData, MainData torrentList, out bool filterChanged) public bool MergeMainData(QBitTorrentClient.Models.MainData mainData, MainData torrentList, out bool filterChanged)
@@ -551,6 +553,18 @@ namespace Lantean.QBTMud.Services
changed = true; changed = true;
} }
if (serverState.LastExternalAddressV4 is not null && existingServerState.LastExternalAddressV4 != serverState.LastExternalAddressV4)
{
existingServerState.LastExternalAddressV4 = serverState.LastExternalAddressV4;
changed = true;
}
if (serverState.LastExternalAddressV6 is not null && existingServerState.LastExternalAddressV6 != serverState.LastExternalAddressV6)
{
existingServerState.LastExternalAddressV6 = serverState.LastExternalAddressV6;
changed = true;
}
return changed; return changed;
} }

View File

@@ -221,7 +221,10 @@ namespace Lantean.QBitTorrentClient.Models
bool webUiUpnp, bool webUiUpnp,
bool webUiUseCustomHttpHeadersEnabled, bool webUiUseCustomHttpHeadersEnabled,
string webUiUsername, string webUiUsername,
string webUiPassword string webUiPassword,
bool confirmTorrentDeletion,
bool confirmTorrentRecheck,
bool statusBarExternalIp
) )
{ {
AddToTopOfQueue = addToTopOfQueue; AddToTopOfQueue = addToTopOfQueue;
@@ -440,6 +443,9 @@ namespace Lantean.QBitTorrentClient.Models
WebUiUseCustomHttpHeadersEnabled = webUiUseCustomHttpHeadersEnabled; WebUiUseCustomHttpHeadersEnabled = webUiUseCustomHttpHeadersEnabled;
WebUiUsername = webUiUsername; WebUiUsername = webUiUsername;
WebUiPassword = webUiPassword; WebUiPassword = webUiPassword;
ConfirmTorrentDeletion = confirmTorrentDeletion;
ConfirmTorrentRecheck = confirmTorrentRecheck;
StatusBarExternalIp = statusBarExternalIp;
} }
[JsonPropertyName("add_to_top_of_queue")] [JsonPropertyName("add_to_top_of_queue")]
@@ -1089,5 +1095,14 @@ namespace Lantean.QBitTorrentClient.Models
[JsonPropertyName("web_ui_password")] [JsonPropertyName("web_ui_password")]
public string WebUiPassword { get; } public string WebUiPassword { get; }
[JsonPropertyName("confirm_torrent_deletion")]
public bool ConfirmTorrentDeletion { get; }
[JsonPropertyName("confirm_torrent_recheck")]
public bool ConfirmTorrentRecheck { get; }
[JsonPropertyName("status_bar_external_ip")]
public bool StatusBarExternalIp { get; }
} }
} }

View File

@@ -30,7 +30,9 @@ namespace Lantean.QBitTorrentClient.Models
long? uploadRateLimit, long? uploadRateLimit,
bool? useAltSpeedLimits, bool? useAltSpeedLimits,
bool? useSubcategories, bool? useSubcategories,
float? writeCacheOverload) : base(connectionStatus, dHTNodes, downloadInfoData, downloadInfoSpeed, downloadRateLimit, uploadInfoData, uploadInfoSpeed, uploadRateLimit) float? writeCacheOverload,
string? lastExternalAddressV4 = null,
string? lastExternalAddressV6 = null) : base(connectionStatus, dHTNodes, downloadInfoData, downloadInfoSpeed, downloadRateLimit, uploadInfoData, uploadInfoSpeed, uploadRateLimit)
{ {
AllTimeDownloaded = allTimeDownloaded; AllTimeDownloaded = allTimeDownloaded;
AllTimeUploaded = allTimeUploaded; AllTimeUploaded = allTimeUploaded;
@@ -49,6 +51,8 @@ namespace Lantean.QBitTorrentClient.Models
UseAltSpeedLimits = useAltSpeedLimits; UseAltSpeedLimits = useAltSpeedLimits;
UseSubcategories = useSubcategories; UseSubcategories = useSubcategories;
WriteCacheOverload = writeCacheOverload; WriteCacheOverload = writeCacheOverload;
LastExternalAddressV4 = lastExternalAddressV4;
LastExternalAddressV6 = lastExternalAddressV6;
} }
[JsonPropertyName("alltime_dl")] [JsonPropertyName("alltime_dl")]
@@ -101,5 +105,11 @@ namespace Lantean.QBitTorrentClient.Models
[JsonPropertyName("write_cache_overload")] [JsonPropertyName("write_cache_overload")]
public float? WriteCacheOverload { get; } public float? WriteCacheOverload { get; }
[JsonPropertyName("last_external_address_v4")]
public string? LastExternalAddressV4 { get; }
[JsonPropertyName("last_external_address_v6")]
public string? LastExternalAddressV6 { get; }
} }
} }

View File

@@ -653,6 +653,15 @@ namespace Lantean.QBitTorrentClient.Models
[JsonPropertyName("web_ui_password")] [JsonPropertyName("web_ui_password")]
public string? WebUiPassword { get; set; } public string? WebUiPassword { get; set; }
[JsonPropertyName("confirm_torrent_deletion")]
public bool? ConfirmTorrentDeletion { get; set; }
[JsonPropertyName("confirm_torrent_recheck")]
public bool? ConfirmTorrentRecheck { get; set; }
[JsonPropertyName("status_bar_external_ip")]
public bool? StatusBarExternalIp { get; set; }
public void Validate() public void Validate()
{ {
if (MaxRatio.HasValue && MaxRatioEnabled.HasValue) if (MaxRatio.HasValue && MaxRatioEnabled.HasValue)