Add ShareRatio to include ShareLimitAction

This commit is contained in:
ahjephson
2025-10-22 12:42:30 +01:00
parent e4ea79a8ed
commit e64a13c7c9
7 changed files with 141 additions and 53 deletions

View File

@@ -1,4 +1,5 @@
@inherits SubmittableDialog
@inherits SubmittableDialog
@using Lantean.QBitTorrentClient.Models
<MudDialog>
<DialogContent>
@@ -34,6 +35,15 @@
<MudItem xs="9">
<MudNumericField T="int" Value="InactiveMinutes" ValueChanged="InactiveMinutesChanged" Disabled="@(!(CustomEnabled && InactiveMinutesEnabled))" Min="1" Max="1024000" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="minutes" />
</MudItem>
<MudItem xs="12">
<MudSelect T="ShareLimitAction" Label="Action when limit is reached" Value="SelectedShareLimitAction" ValueChanged="ShareLimitActionChanged" Disabled="@(!CustomEnabled)" Variant="Variant.Outlined">
<MudSelectItem Value="ShareLimitAction.Default">Default</MudSelectItem>
<MudSelectItem Value="ShareLimitAction.Stop">Stop torrent</MudSelectItem>
<MudSelectItem Value="ShareLimitAction.Remove">Remove torrent</MudSelectItem>
<MudSelectItem Value="ShareLimitAction.RemoveWithContent">Remove torrent and data</MudSelectItem>
<MudSelectItem Value="ShareLimitAction.EnableSuperSeeding">Enable super seeding</MudSelectItem>
</MudSelect>
</MudItem>
</MudGrid>
</DialogContent>
<DialogActions>

View File

@@ -1,4 +1,7 @@
using Lantean.QBitTorrentClient;
using System;
using System.Collections.Generic;
using Lantean.QBitTorrentClient;
using Lantean.QBitTorrentClient.Models;
using Lantean.QBTMud.Models;
using Microsoft.AspNetCore.Components;
using MudBlazor;
@@ -16,6 +19,9 @@ namespace Lantean.QBTMud.Components.Dialogs
[Parameter]
public ShareRatioMax? Value { get; set; }
[Parameter]
public ShareRatioMax? CurrentValue { get; set; }
[Parameter]
public bool Disabled { get; set; }
@@ -33,6 +39,8 @@ namespace Lantean.QBTMud.Components.Dialogs
protected int InactiveMinutes { get; set; }
protected ShareLimitAction SelectedShareLimitAction { get; set; } = ShareLimitAction.Default;
protected bool CustomEnabled => ShareRatioType == 0;
protected void RatioEnabledChanged(bool value)
@@ -65,40 +73,75 @@ namespace Lantean.QBTMud.Components.Dialogs
InactiveMinutes = value;
}
protected void ShareLimitActionChanged(ShareLimitAction value)
{
SelectedShareLimitAction = value;
}
protected override void OnParametersSet()
{
if (Value is null || Value.RatioLimit == Limits.GlobalLimit && Value.SeedingTimeLimit == Limits.GlobalLimit && Value.InactiveSeedingTimeLimit == Limits.GlobalLimit)
RatioEnabled = false;
TotalMinutesEnabled = false;
InactiveMinutesEnabled = false;
var baseline = Value ?? CurrentValue;
SelectedShareLimitAction = baseline?.ShareLimitAction ?? ShareLimitAction.Default;
if (baseline is null || baseline.RatioLimit == Limits.GlobalLimit && baseline.SeedingTimeLimit == Limits.GlobalLimit && baseline.InactiveSeedingTimeLimit == Limits.GlobalLimit)
{
ShareRatioType = Limits.GlobalLimit;
return;
}
else if (Value.MaxRatio == Limits.NoLimit && Value.MaxSeedingTime == Limits.NoLimit && Value.MaxInactiveSeedingTime == Limits.NoLimit)
if (baseline.MaxRatio == Limits.NoLimit && baseline.MaxSeedingTime == Limits.NoLimit && baseline.MaxInactiveSeedingTime == Limits.NoLimit)
{
ShareRatioType = Limits.NoLimit;
return;
}
ShareRatioType = 0;
if (baseline.RatioLimit >= 0)
{
RatioEnabled = true;
Ratio = baseline.RatioLimit;
}
else
{
ShareRatioType = 0;
if (Value.RatioLimit >= 0)
{
RatioEnabled = true;
Ratio = Value.RatioLimit;
Ratio = 0;
}
if (Value.SeedingTimeLimit >= 0)
if (baseline.SeedingTimeLimit >= 0)
{
TotalMinutesEnabled = true;
TotalMinutes = (int)Value.SeedingTimeLimit;
TotalMinutes = (int)baseline.SeedingTimeLimit;
}
if (Value.InactiveSeedingTimeLimit >= 0)
else
{
TotalMinutes = 0;
}
if (baseline.InactiveSeedingTimeLimit >= 0)
{
InactiveMinutesEnabled = true;
InactiveMinutes = (int)Value.InactiveSeedingTimeLimit;
InactiveMinutes = (int)baseline.InactiveSeedingTimeLimit;
}
else
{
InactiveMinutes = 0;
}
}
protected void ShareRatioTypeChanged(int value)
{
ShareRatioType = value;
if (!CustomEnabled)
{
RatioEnabled = false;
TotalMinutesEnabled = false;
InactiveMinutesEnabled = false;
SelectedShareLimitAction = ShareLimitAction.Default;
}
}
protected void Cancel()
@@ -112,16 +155,19 @@ namespace Lantean.QBTMud.Components.Dialogs
if (ShareRatioType == Limits.GlobalLimit)
{
result.RatioLimit = result.SeedingTimeLimit = result.InactiveSeedingTimeLimit = Limits.GlobalLimit;
result.ShareLimitAction = ShareLimitAction.Default;
}
else if (ShareRatioType == Limits.NoLimit)
{
result.RatioLimit = result.SeedingTimeLimit = result.InactiveSeedingTimeLimit = Limits.NoLimit;
result.ShareLimitAction = ShareLimitAction.Default;
}
else
{
result.RatioLimit = RatioEnabled ? Ratio : Limits.NoLimit;
result.SeedingTimeLimit = TotalMinutesEnabled ? TotalMinutes : Limits.NoLimit;
result.InactiveSeedingTimeLimit = InactiveMinutesEnabled ? InactiveMinutes : Limits.NoLimit;
result.ShareLimitAction = SelectedShareLimitAction;
}
MudDialog.Close(DialogResult.Ok(result));
}

View File

@@ -1,9 +1,10 @@
using Lantean.QBitTorrentClient;
using System.Linq;
using Lantean.QBitTorrentClient;
using ShareLimitAction = Lantean.QBitTorrentClient.Models.ShareLimitAction;
using Lantean.QBTMud.Components.Dialogs;
using Lantean.QBTMud.Filter;
using Lantean.QBTMud.Models;
using MudBlazor;
using System.Linq;
namespace Lantean.QBTMud.Helpers
{
@@ -241,21 +242,30 @@ namespace Lantean.QBTMud.Helpers
public static async Task InvokeShareRatioDialog(this IDialogService dialogService, IApiClient apiClient, IEnumerable<Torrent> torrents)
{
var torrentShareRatios = torrents.Select(t => new ShareRatioMax
var torrentList = torrents.ToList();
if (torrentList.Count == 0)
{
return;
}
var shareRatioValues = torrentList.Select(t => new ShareRatioMax
{
InactiveSeedingTimeLimit = t.InactiveSeedingTimeLimit,
MaxInactiveSeedingTime = t.InactiveSeedingTimeLimit,
MaxInactiveSeedingTime = t.MaxInactiveSeedingTime,
MaxRatio = t.MaxRatio,
MaxSeedingTime = t.MaxSeedingTime,
RatioLimit = t.RatioLimit,
SeedingTimeLimit = t.SeedingTimeLimit,
});
ShareLimitAction = t.ShareLimitAction,
}).ToList();
var torrentsHaveSameShareRatio = torrentShareRatios.Distinct().Count() == 1;
var referenceValue = shareRatioValues.First();
var torrentsHaveSameShareRatio = shareRatioValues.Distinct().Count() == 1;
var parameters = new DialogParameters
{
{ nameof(ShareRatioDialog.Value), torrentsHaveSameShareRatio ? torrentShareRatios.FirstOrDefault() : null },
{ nameof(ShareRatioDialog.Value), torrentsHaveSameShareRatio ? referenceValue : null },
{ nameof(ShareRatioDialog.CurrentValue), referenceValue },
};
var result = await dialogService.ShowAsync<ShareRatioDialog>("Share ratio", parameters, FormDialogOptions);
@@ -267,7 +277,7 @@ namespace Lantean.QBTMud.Helpers
var shareRatio = (ShareRatio)dialogResult.Data;
await apiClient.SetTorrentShareLimit(shareRatio.RatioLimit, shareRatio.SeedingTimeLimit, shareRatio.InactiveSeedingTimeLimit, hashes: torrents.Select(t => t.Hash).ToArray());
await apiClient.SetTorrentShareLimit(shareRatio.RatioLimit, shareRatio.SeedingTimeLimit, shareRatio.InactiveSeedingTimeLimit, shareRatio.ShareLimitAction ?? ShareLimitAction.Default, hashes: torrentList.Select(t => t.Hash).ToArray());
}
public static async Task InvokeStringFieldDialog(this IDialogService dialogService, string title, string label, string? value, Func<string, Task> onSuccess)
@@ -461,3 +471,5 @@ namespace Lantean.QBTMud.Helpers
}
}
}

View File

@@ -1,10 +1,13 @@
namespace Lantean.QBTMud.Models
using Lantean.QBitTorrentClient.Models;
namespace Lantean.QBTMud.Models
{
public record ShareRatio
{
public float RatioLimit { get; set; }
public float SeedingTimeLimit { get; set; }
public float InactiveSeedingTimeLimit { get; set; }
public ShareLimitAction? ShareLimitAction { get; set; }
}
public record ShareRatioMax : ShareRatio

View File

@@ -1,4 +1,9 @@
namespace Lantean.QBTMud.Models
using System;
using System.Collections.Generic;
using System.Linq;
using Lantean.QBitTorrentClient.Models;
namespace Lantean.QBTMud.Models
{
public class Torrent
{
@@ -57,6 +62,7 @@
string downloadPath,
string rootPath,
bool isPrivate,
ShareLimitAction shareLimitAction,
string comment)
{
Hash = hash;
@@ -113,25 +119,27 @@
DownloadPath = downloadPath;
RootPath = rootPath;
IsPrivate = isPrivate;
ShareLimitAction = shareLimitAction;
Comment = comment;
}
protected Torrent()
{
Hash = "";
Category = "";
ContentPath = "";
InfoHashV1 = "";
InfoHashV2 = "";
MagnetUri = "";
Name = "";
SavePath = "";
DownloadPath = "";
RootPath = "";
State = "";
Tags = [];
Tracker = "";
Comment = "";
Hash = string.Empty;
Category = string.Empty;
ContentPath = string.Empty;
InfoHashV1 = string.Empty;
InfoHashV2 = string.Empty;
MagnetUri = string.Empty;
Name = string.Empty;
SavePath = string.Empty;
DownloadPath = string.Empty;
RootPath = string.Empty;
State = string.Empty;
Tags = new List<string>();
Tracker = string.Empty;
ShareLimitAction = ShareLimitAction.Default;
Comment = string.Empty;
}
public string Hash { get; }
@@ -242,6 +250,8 @@
public bool IsPrivate { get; set; }
public ShareLimitAction ShareLimitAction { get; set; }
public string Comment { get; set; }
public override bool Equals(object? obj)

View File

@@ -1,5 +1,6 @@
using Lantean.QBTMud.Helpers;
using Lantean.QBTMud.Helpers;
using Lantean.QBTMud.Models;
using ShareLimitAction = Lantean.QBitTorrentClient.Models.ShareLimitAction;
namespace Lantean.QBTMud.Services
{
@@ -705,6 +706,7 @@ namespace Lantean.QBTMud.Services
torrent.DownloadPath ?? string.Empty,
torrent.RootPath ?? string.Empty,
torrent.IsPrivate.GetValueOrDefault(),
torrent.ShareLimitAction ?? ShareLimitAction.Default,
torrent.Comment ?? string.Empty);
}
@@ -1354,6 +1356,11 @@ namespace Lantean.QBTMud.Services
existingTorrent.IsPrivate = torrent.IsPrivate.Value;
dataChanged = true;
}
if (torrent.ShareLimitAction.HasValue && existingTorrent.ShareLimitAction != torrent.ShareLimitAction.Value)
{
existingTorrent.ShareLimitAction = torrent.ShareLimitAction.Value;
dataChanged = true;
}
if (torrent.Comment is not null && !string.Equals(existingTorrent.Comment, torrent.Comment, StringComparison.Ordinal))
{

View File

@@ -10,16 +10,16 @@
- **Tracker grouping & removal**: When grouping trackers by host in `FiltersNav`, retain original URL entries so removal can target the right string. Replace the placeholder "Remove tracker" action with a real implementation and disable it for synthetic buckets.
## ~~Torrent Data Model & Columns~~
~~- **Model sync**: Bring `Lantean.QBTMud.Models.Torrent` into parity with v5 (`Popularity`, `DownloadPath`, `RootPath`, `InfoHashV1/2`, `IsPrivate`, share-limit action fields, tracker flags, etc.) and map them in `DataManager.CreateTorrent`.~~
~~- **Column set alignment**: Match the v5 table defaults—add missing columns (Popularity, Reannounce in, Info hashes, Download path, Private, etc.), fix "Ratio Limit" to display `RatioLimit`, and ensure column ordering/enabled state mirrors `DynamicTable.TorrentsTable`.~~
~~- **Helper updates**: Extend `DisplayHelpers` to format the new fields (popularity, private flag, info hashes, error state icons).~~
- ~~**Model sync**: Bring `Lantean.QBTMud.Models.Torrent` into parity with v5 (`Popularity`, `DownloadPath`, `RootPath`, `InfoHashV1/2`, `IsPrivate`, share-limit action fields, tracker flags, etc.) and map them in `DataManager.CreateTorrent`.~~
- ~~**Column set alignment**: Match the v5 table defaults—add missing columns (Popularity, Reannounce in, Info hashes, Download path, Private, etc.), fix "Ratio Limit" to display `RatioLimit`, and ensure column ordering/enabled state mirrors `DynamicTable.TorrentsTable`.~~
- ~~**Helper updates**: Extend `DisplayHelpers` to format the new fields (popularity, private flag, info hashes, error state icons).~~
## Actions & Dialogs
- ~~**Copy submenu**: Add "Copy comment" and "Copy content path" to the copy submenu in `TorrentActions`, keeping clipboard behaviour identical to v5.~~
- **Share ratio dialog**: Update `ShareRatioDialog`, `ShareRatio/ShareRatioMax`, and `DialogHelper.InvokeShareRatioDialog` to surface `ShareLimitAction`, fix the `MaxInactiveSeedingTime` mapping, and call `SetTorrentShareLimit` with the action.
- ~~**Share ratio dialog**: Update `ShareRatioDialog`, `ShareRatio/ShareRatioMax`, and `DialogHelper.InvokeShareRatioDialog` to surface `ShareLimitAction`, fix the `MaxInactiveSeedingTime` mapping, and call `SetTorrentShareLimit` with the action.~~
## Add-Torrent Flow
- Mirror the v5 add-torrent pane: add controls for incomplete save path, tags, auto-start, queue position, share-limit action, etc., in `AddTorrentOptions.razor`, and wire the new fields into the submission object.
## ~~Preferences & Local Settings~~
~~- Introduce new v5 toggles such as "Display full tracker URL" in `AdvancedOptions`, persist them via the preferences service, and respect the setting in the tracker column rendering.~~
- ~~Introduce new v5 toggles such as "Display full tracker URL" in `AdvancedOptions`, persist them via the preferences service, and respect the setting in the tracker column rendering.~~