mirror of
https://github.com/lantean-code/qbtmud.git
synced 2025-11-13 18:36:11 +00:00
Compare commits
27 Commits
feature/ne
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e854ad8071 | ||
|
|
d373ec3f6f | ||
|
|
b72aae734a | ||
|
|
fca17edfd1 | ||
|
|
d8535fa262 | ||
|
|
1c6bfed6ee | ||
|
|
281caf8026 | ||
|
|
ff905e7cac | ||
|
|
cb80dd0d6b | ||
|
|
9113fb90ee | ||
|
|
d8b4e932d1 | ||
|
|
3d0d211d10 | ||
|
|
7db4f2f78d | ||
|
|
1f606b4449 | ||
|
|
88d66b4887 | ||
|
|
2ad7be1073 | ||
|
|
300e81345c | ||
|
|
9d8d84168e | ||
|
|
bb66b97f45 | ||
|
|
4824037ba7 | ||
|
|
1f9b631a36 | ||
|
|
2c744cd972 | ||
|
|
b02bb7cfae | ||
|
|
e4dac8556e | ||
|
|
a9a8a4eba8 | ||
|
|
bb524450f0 | ||
|
|
4eaa46b2b3 |
95
.github/workflows/dotnet.yml
vendored
95
.github/workflows/dotnet.yml
vendored
@@ -4,6 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
workflow_dispatch:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- '**'
|
- '**'
|
||||||
@@ -32,58 +33,112 @@ jobs:
|
|||||||
id: gitversion
|
id: gitversion
|
||||||
run: |
|
run: |
|
||||||
VERSION=$(dotnet gitversion /output json /showvariable FullSemVer)
|
VERSION=$(dotnet gitversion /output json /showvariable FullSemVer)
|
||||||
|
SAFE_VERSION=$(echo "$VERSION" | sed -E 's/[^A-Za-z0-9._+-]+/-/g')
|
||||||
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
||||||
|
echo "VERSION_SAFE=$SAFE_VERSION" >> $GITHUB_ENV
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
|
- name: Set Release Channel
|
||||||
|
id: release_channel
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if [ "${GITHUB_REF}" = "refs/heads/master" ]; then
|
||||||
|
echo "channel=stable" >> $GITHUB_OUTPUT
|
||||||
|
echo "prerelease=false" >> $GITHUB_OUTPUT
|
||||||
|
echo "label=Release" >> $GITHUB_OUTPUT
|
||||||
|
elif [ "${GITHUB_REF}" = "refs/heads/develop" ]; then
|
||||||
|
echo "channel=beta" >> $GITHUB_OUTPUT
|
||||||
|
echo "prerelease=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "label=Beta" >> $GITHUB_OUTPUT
|
||||||
|
elif [[ "${GITHUB_REF}" == refs/heads/feature/* ]]; then
|
||||||
|
echo "channel=alpha" >> $GITHUB_OUTPUT
|
||||||
|
echo "prerelease=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "label=Alpha" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "channel=none" >> $GITHUB_OUTPUT
|
||||||
|
echo "prerelease=false" >> $GITHUB_OUTPUT
|
||||||
|
echo "label=" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Restore dependencies
|
- name: Restore dependencies
|
||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: dotnet build --configuration Release --no-restore
|
run: dotnet build --configuration Release --no-restore
|
||||||
|
|
||||||
- name: Run Tests
|
- name: Run Tests with Coverage
|
||||||
run: dotnet test --no-build --configuration Release
|
run: dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" --results-directory TestResults
|
||||||
|
|
||||||
- name: Publish (only on master)
|
- name: Install ReportGenerator
|
||||||
if: github.ref == 'refs/heads/master'
|
run: dotnet tool install --global dotnet-reportgenerator-globaltool
|
||||||
run: dotnet publish Lantean.QBTMud/Lantean.QBTMud.csproj -c Release -o output
|
|
||||||
|
- name: Generate Coverage Report
|
||||||
|
run: reportgenerator -reports:"TestResults/**/coverage.cobertura.xml" -targetdir:"coverage-report" -reporttypes:"HtmlInline_AzurePipelines;Cobertura"
|
||||||
|
|
||||||
|
- name: Upload Coverage Artifact
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-report
|
||||||
|
path: coverage-report
|
||||||
|
|
||||||
|
- name: Publish
|
||||||
|
if: steps.release_channel.outputs.channel != 'none'
|
||||||
|
run: dotnet publish src/Lantean.QBTMud/Lantean.QBTMud.csproj -c Release -o output
|
||||||
|
|
||||||
- name: Prepare Release ZIP
|
- name: Prepare Release ZIP
|
||||||
if: github.ref == 'refs/heads/master'
|
if: steps.release_channel.outputs.channel != 'none'
|
||||||
run: |
|
run: |
|
||||||
cd output
|
cd output
|
||||||
mv wwwroot public
|
mv wwwroot public
|
||||||
zip -r "../qbt-mud-v${{ env.VERSION }}.zip" public
|
zip -r "../qbt-mud-v${{ env.VERSION_SAFE }}.zip" public
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Check if Tag Exists
|
- name: Resolve Release Tag
|
||||||
id: check_tag
|
if: steps.release_channel.outputs.channel != 'none'
|
||||||
|
id: resolve_tag
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
if git rev-parse "v${{ env.VERSION }}" >/dev/null 2>&1; then
|
if git rev-parse "${VERSION}" >/dev/null 2>&1; then
|
||||||
echo "TAG_EXISTS=true" >> $GITHUB_ENV
|
echo "tag=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
echo "exists=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "Using existing tag '${VERSION}'"
|
||||||
|
elif git rev-parse "v${VERSION}" >/dev/null 2>&1; then
|
||||||
|
echo "tag=v${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
echo "exists=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "Using existing tag 'v${VERSION}'"
|
||||||
else
|
else
|
||||||
echo "TAG_EXISTS=false" >> $GITHUB_ENV
|
echo "tag=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
echo "exists=false" >> $GITHUB_OUTPUT
|
||||||
|
echo "::warning::No matching git tag found for '${VERSION}' or 'v${VERSION}'."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
- name: Ensure Release Tag Exists
|
||||||
|
if: steps.release_channel.outputs.channel == 'stable' && steps.resolve_tag.outputs.exists != 'true'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "::error::Expected an existing git tag '${VERSION}' (or 'v${VERSION}') before creating a release."
|
||||||
|
exit 1
|
||||||
|
|
||||||
- name: Create GitHub Release
|
- name: Create GitHub Release
|
||||||
if: github.ref == 'refs/heads/master' && env.TAG_EXISTS == 'false'
|
if: steps.release_channel.outputs.channel != 'none' && (steps.resolve_tag.outputs.exists == 'true' || steps.release_channel.outputs.channel != 'stable')
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: actions/create-release@v1
|
uses: actions/create-release@v1
|
||||||
with:
|
with:
|
||||||
tag_name: v${{ env.VERSION }}
|
tag_name: ${{ steps.resolve_tag.outputs.tag }}
|
||||||
release_name: Release v${{ env.VERSION }}
|
release_name: ${{ steps.release_channel.outputs.label }} ${{ steps.resolve_tag.outputs.tag }}
|
||||||
draft: false
|
draft: ${{ steps.release_channel.outputs.channel != 'alpha' }}
|
||||||
prerelease: false
|
prerelease: ${{ steps.release_channel.outputs.prerelease }}
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Upload Release Asset
|
- name: Upload Release Asset
|
||||||
if: github.ref == 'refs/heads/master' && env.TAG_EXISTS == 'false'
|
if: steps.release_channel.outputs.channel != 'none' && (steps.resolve_tag.outputs.exists == 'true' || steps.release_channel.outputs.channel != 'stable')
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: qbt-mud-v${{ env.VERSION }}.zip
|
asset_path: qbt-mud-v${{ env.VERSION_SAFE }}.zip
|
||||||
asset_name: qbt-mud-v${{ env.VERSION }}.zip
|
asset_name: qbt-mud-v${{ env.VERSION_SAFE }}.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -360,4 +360,5 @@ MigrationBackup/
|
|||||||
.ionide/
|
.ionide/
|
||||||
|
|
||||||
# Fody - auto-generated XML schema
|
# Fody - auto-generated XML schema
|
||||||
FodyWeavers.xsd
|
FodyWeavers.xsd
|
||||||
|
/output
|
||||||
|
|||||||
@@ -10,11 +10,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AwesomeAssertions" Version="9.0.0" />
|
<PackageReference Include="AwesomeAssertions" Version="9.2.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
|
||||||
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
|
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||||
<PackageReference Include="xunit" Version="2.9.3" />
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.0">
|
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Lantean.QBitTorrentClient;
|
using Lantean.QBitTorrentClient;
|
||||||
using Lantean.QBitTorrentClient.Models;
|
using Lantean.QBitTorrentClient.Models;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
protected IDialogService DialogService { get; set; } = default!;
|
protected IDialogService DialogService { get; set; } = default!;
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
protected HashSet<string> Tags { get; } = [];
|
protected HashSet<string> Tags { get; } = [];
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class AddTorrentFileDialog
|
public partial class AddTorrentFileDialog
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
protected IReadOnlyList<IBrowserFile> Files { get; set; } = [];
|
protected IReadOnlyList<IBrowserFile> Files { get; set; } = [];
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
protected IKeyboardService KeyboardService { get; set; } = default!;
|
protected IKeyboardService KeyboardService { get; set; } = default!;
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string? Url { get; set; }
|
public string? Url { get; set; }
|
||||||
|
|||||||
@@ -65,4 +65,4 @@
|
|||||||
<MudNumericField Label="Limit upload rate" @bind-Value="UploadLimit" Variant="Variant.Outlined" Min="0" />
|
<MudNumericField Label="Limit upload rate" @bind-Value="UploadLimit" Variant="Variant.Outlined" Min="0" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCollapse>
|
</MudCollapse>
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using Lantean.QBitTorrentClient;
|
using Lantean.QBitTorrentClient;
|
||||||
using Lantean.QBTMud.Models;
|
using Lantean.QBTMud.Models;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using MudBlazor;
|
|
||||||
|
|
||||||
namespace Lantean.QBTMud.Components.Dialogs
|
namespace Lantean.QBTMud.Components.Dialogs
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class AddTrackerDialog
|
public partial class AddTrackerDialog
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
protected HashSet<string> Trackers { get; } = [];
|
protected HashSet<string> Trackers { get; } = [];
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
private string _savePath = string.Empty;
|
private string _savePath = string.Empty;
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
protected IApiClient ApiClient { get; set; } = default!;
|
protected IApiClient ApiClient { get; set; } = default!;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class ConfirmDialog
|
public partial class ConfirmDialog
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Content { get; set; } = default!;
|
public string Content { get; set; } = default!;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class DeleteDialog
|
public partial class DeleteDialog
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int Count { get; set; }
|
public int Count { get; set; }
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class ExceptionDialog
|
public partial class ExceptionDialog
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Exception? Exception { get; set; }
|
public Exception? Exception { get; set; }
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
private static readonly IReadOnlyList<PropertyInfo> _properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
|
private static readonly IReadOnlyList<PropertyInfo> _properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
protected IReadOnlyList<PropertyInfo> Columns => _properties;
|
protected IReadOnlyList<PropertyInfo> Columns => _properties;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
protected IDialogService DialogService { get; set; } = default!;
|
protected IDialogService DialogService { get; set; } = default!;
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public IEnumerable<string> Hashes { get; set; } = [];
|
public IEnumerable<string> Hashes { get; set; } = [];
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
protected IDialogService DialogService { get; set; } = default!;
|
protected IDialogService DialogService { get; set; } = default!;
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public IEnumerable<string> Hashes { get; set; } = [];
|
public IEnumerable<string> Hashes { get; set; } = [];
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class MultipleFieldDialog
|
public partial class MultipleFieldDialog
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Label { get; set; } = default!;
|
public string Label { get; set; } = default!;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class NumericFieldDialog<T> where T : struct, INumber<T>
|
public partial class NumericFieldDialog<T> where T : struct, INumber<T>
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string? Label { get; set; }
|
public string? Label { get; set; }
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
protected ILocalStorageService LocalStorage { get; set; } = default!;
|
protected ILocalStorageService LocalStorage { get; set; } = default!;
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string? Hash { get; set; }
|
public string? Hash { get; set; }
|
||||||
@@ -426,7 +426,6 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
{
|
{
|
||||||
await LocalStorage.RemoveItemAsync(_preferencesStorageKey);
|
await LocalStorage.RemoveItemAsync(_preferencesStorageKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
@@ -495,7 +494,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
{
|
{
|
||||||
var oldPath = renamedFile.Path + renamedFile.OriginalName;
|
var oldPath = renamedFile.Path + renamedFile.OriginalName;
|
||||||
var newPath = renamedFile.Path + renamedFile.NewName;
|
var newPath = renamedFile.Path + renamedFile.NewName;
|
||||||
|
|
||||||
await ApiClient.RenameFolder(Hash, oldPath, newPath);
|
await ApiClient.RenameFolder(Hash, oldPath, newPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
private readonly List<string> _unsavedRuleNames = [];
|
private readonly List<string> _unsavedRuleNames = [];
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
protected IDialogService DialogService { get; set; } = default!;
|
protected IDialogService DialogService { get; set; } = default!;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class ShareRatioDialog
|
public partial class ShareRatioDialog
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string? Label { get; set; }
|
public string? Label { get; set; }
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class SliderFieldDialog<T> where T : struct, INumber<T>
|
public partial class SliderFieldDialog<T> where T : struct, INumber<T>
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string? Label { get; set; }
|
public string? Label { get; set; }
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class StringFieldDialog
|
public partial class StringFieldDialog
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string? Label { get; set; }
|
public string? Label { get; set; }
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class SubMenuDialog
|
public partial class SubMenuDialog
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public UIAction? ParentAction { get; set; }
|
public UIAction? ParentAction { get; set; }
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Lantean.QBTMud.Components.Dialogs
|
|||||||
public partial class TorrentOptionsDialog
|
public partial class TorrentOptionsDialog
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
IMudDialogInstance MudDialog { get; set; } = default!;
|
private IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
[EditorRequired]
|
[EditorRequired]
|
||||||
|
|||||||
@@ -1,46 +1,49 @@
|
|||||||
<ContextMenu @ref="ContextMenu" Dense="true">
|
<MudMenu @ref="ContextMenu" Dense="true" PositionAtCursor="true" ListClass="unselectable" PopoverClass="unselectable">
|
||||||
<MudMenuItem Icon="@Icons.Material.Filled.DriveFileRenameOutline" OnClick="RenameFileContextMenu">Rename</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Filled.DriveFileRenameOutline" OnClick="RenameFileContextMenu">Rename</MudMenuItem>
|
||||||
</ContextMenu>
|
</MudMenu>
|
||||||
|
|
||||||
<div style="overflow-x: auto; white-space: nowrap; width: 100%;">
|
<div class="content-panel">
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel__toolbar content-panel__toolbar--scroll">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.DriveFileRenameOutline" OnClick="RenameFileToolbar" title="Rename" />
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudDivider Vertical="true" />
|
<MudIconButton Icon="@Icons.Material.Filled.DriveFileRenameOutline" OnClick="RenameFileToolbar" title="Rename" />
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.ViewColumn" Color="Color.Inherit" OnClick="ColumnOptions" title="Choose Columns" />
|
<MudDivider Vertical="true" />
|
||||||
<MudDivider Vertical="true" />
|
<MudIconButton Icon="@Icons.Material.Outlined.ViewColumn" Color="Color.Inherit" OnClick="ColumnOptions" title="Choose Columns" />
|
||||||
<MudMenu Icon="@Icons.Material.Outlined.FileDownloadOff" Label="Do Not Download" AnchorOrigin="Origin.BottomLeft" TransformOrigin="Origin.TopLeft" title="Do Not Download">
|
<MudDivider Vertical="true" />
|
||||||
<MudMenuItem OnClick="DoNotDownloadLessThan100PercentAvailability">Less Than 100% Availability</MudMenuItem>
|
<MudMenu Icon="@Icons.Material.Outlined.FileDownloadOff" Label="Do Not Download" AnchorOrigin="Origin.BottomLeft" TransformOrigin="Origin.TopLeft" title="Do Not Download">
|
||||||
<MudMenuItem OnClick="DoNotDownloadLessThan80PercentAvailability">Less than 80% Availability</MudMenuItem>
|
<MudMenuItem OnClick="DoNotDownloadLessThan100PercentAvailability">Less Than 100% Availability</MudMenuItem>
|
||||||
<MudMenuItem OnClick="DoNotDownloadCurrentlyFilteredFiles">Currently Filtered Files</MudMenuItem>
|
<MudMenuItem OnClick="DoNotDownloadLessThan80PercentAvailability">Less than 80% Availability</MudMenuItem>
|
||||||
</MudMenu>
|
<MudMenuItem OnClick="DoNotDownloadCurrentlyFilteredFiles">Currently Filtered Files</MudMenuItem>
|
||||||
<MudMenu Icon="@Icons.Material.Outlined.FileDownload" Label="Normal Priority" AnchorOrigin="Origin.BottomLeft" TransformOrigin="Origin.TopLeft" title="Download">
|
</MudMenu>
|
||||||
<MudMenuItem OnClick="NormalPriorityLessThan100PercentAvailability">Less Than 100% Availability</MudMenuItem>
|
<MudMenu Icon="@Icons.Material.Outlined.FileDownload" Label="Normal Priority" AnchorOrigin="Origin.BottomLeft" TransformOrigin="Origin.TopLeft" title="Download">
|
||||||
<MudMenuItem OnClick="NormalPriorityLessThan80PercentAvailability">Less than 80% Availability</MudMenuItem>
|
<MudMenuItem OnClick="NormalPriorityLessThan100PercentAvailability">Less Than 100% Availability</MudMenuItem>
|
||||||
<MudMenuItem OnClick="NormalPriorityCurrentlyFilteredFiles">Currently Filtered Files</MudMenuItem>
|
<MudMenuItem OnClick="NormalPriorityLessThan80PercentAvailability">Less than 80% Availability</MudMenuItem>
|
||||||
</MudMenu>
|
<MudMenuItem OnClick="NormalPriorityCurrentlyFilteredFiles">Currently Filtered Files</MudMenuItem>
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.FilterList" OnClick="ShowFilterDialog" title="Filter" />
|
</MudMenu>
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.FilterListOff" OnClick="RemoveFilter" title="Remove Filter" />
|
<MudIconButton Icon="@Icons.Material.Outlined.FilterList" OnClick="ShowFilterDialog" title="Filter" />
|
||||||
<MudSpacer />
|
<MudIconButton Icon="@Icons.Material.Outlined.FilterListOff" OnClick="RemoveFilter" title="Remove Filter" />
|
||||||
<MudTextField T="string" Value="SearchText" ValueChanged="SearchTextChanged" Immediate="true" DebounceInterval="500" Placeholder="Filter file list" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
|
<MudSpacer />
|
||||||
</MudToolBar>
|
<MudTextField T="string" Value="SearchText" ValueChanged="SearchTextChanged" Immediate="true" DebounceInterval="500" Placeholder="Filter file list" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
<div class="content-panel__body">
|
||||||
|
<DynamicTable
|
||||||
|
@ref="Table"
|
||||||
|
T="ContentItem"
|
||||||
|
ColumnDefinitions="Columns"
|
||||||
|
Items="Files"
|
||||||
|
MultiSelection="false"
|
||||||
|
SelectOnRowClick="true"
|
||||||
|
PreSorted="true"
|
||||||
|
SelectedItemChanged="SelectedItemChanged"
|
||||||
|
SortColumnChanged="SortColumnChanged"
|
||||||
|
SortDirectionChanged="SortDirectionChanged"
|
||||||
|
OnTableDataContextMenu="TableDataContextMenu"
|
||||||
|
OnTableDataLongPress="TableDataLongPress"
|
||||||
|
Class="file-list content-panel__table"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DynamicTable
|
|
||||||
@ref="Table"
|
|
||||||
T="ContentItem"
|
|
||||||
ColumnDefinitions="Columns"
|
|
||||||
Items="Files"
|
|
||||||
MultiSelection="false"
|
|
||||||
SelectOnRowClick="true"
|
|
||||||
PreSorted="true"
|
|
||||||
SelectedItemChanged="SelectedItemChanged"
|
|
||||||
SortColumnChanged="SortColumnChanged"
|
|
||||||
SortDirectionChanged="SortDirectionChanged"
|
|
||||||
OnTableDataContextMenu="TableDataContextMenu"
|
|
||||||
OnTableDataLongPress="TableDataLongPress"
|
|
||||||
Class="file-list"
|
|
||||||
/>
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private RenderFragment<RowContext<ContentItem>> NameColumn
|
private RenderFragment<RowContext<ContentItem>> NameColumn
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ namespace Lantean.QBTMud.Components
|
|||||||
|
|
||||||
private readonly CancellationTokenSource _timerCancellationToken = new();
|
private readonly CancellationTokenSource _timerCancellationToken = new();
|
||||||
private bool _disposedValue;
|
private bool _disposedValue;
|
||||||
|
private static readonly ReadOnlyCollection<ContentItem> EmptyContentItems = new ReadOnlyCollection<ContentItem>(Array.Empty<ContentItem>());
|
||||||
|
private ReadOnlyCollection<ContentItem> _visibleFiles = EmptyContentItems;
|
||||||
|
private bool _filesDirty = true;
|
||||||
|
|
||||||
private List<PropertyFilterDefinition<ContentItem>>? _filterDefinitions;
|
private List<PropertyFilterDefinition<ContentItem>>? _filterDefinitions;
|
||||||
private readonly Dictionary<string, RenderFragment<RowContext<ContentItem>>> _columnRenderFragments = [];
|
private readonly Dictionary<string, RenderFragment<RowContext<ContentItem>>> _columnRenderFragments = [];
|
||||||
@@ -65,7 +68,7 @@ namespace Lantean.QBTMud.Components
|
|||||||
|
|
||||||
private DynamicTable<ContentItem>? Table { get; set; }
|
private DynamicTable<ContentItem>? Table { get; set; }
|
||||||
|
|
||||||
private ContextMenu? ContextMenu { get; set; }
|
private MudMenu? ContextMenu { get; set; }
|
||||||
|
|
||||||
public FilesTab()
|
public FilesTab()
|
||||||
{
|
{
|
||||||
@@ -102,6 +105,7 @@ namespace Lantean.QBTMud.Components
|
|||||||
if (_filterDefinitions is null)
|
if (_filterDefinitions is null)
|
||||||
{
|
{
|
||||||
Filters = null;
|
Filters = null;
|
||||||
|
MarkFilesDirty();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,11 +117,13 @@ namespace Lantean.QBTMud.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
Filters = filters;
|
Filters = filters;
|
||||||
|
MarkFilesDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void RemoveFilter()
|
protected void RemoveFilter()
|
||||||
{
|
{
|
||||||
Filters = null;
|
Filters = null;
|
||||||
|
MarkFilesDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask DisposeAsync()
|
public async ValueTask DisposeAsync()
|
||||||
@@ -157,6 +163,7 @@ namespace Lantean.QBTMud.Components
|
|||||||
protected void SearchTextChanged(string value)
|
protected void SearchTextChanged(string value)
|
||||||
{
|
{
|
||||||
SearchText = value;
|
SearchText = value;
|
||||||
|
MarkFilesDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Task TableDataContextMenu(TableDataContextMenuEventArgs<ContentItem> eventArgs)
|
protected Task TableDataContextMenu(TableDataContextMenuEventArgs<ContentItem> eventArgs)
|
||||||
@@ -178,7 +185,9 @@ namespace Lantean.QBTMud.Components
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ContextMenu.OpenMenuAsync(eventArgs);
|
var normalizedEventArgs = eventArgs.NormalizeForContextMenu();
|
||||||
|
|
||||||
|
await ContextMenu.OpenMenuAsync(normalizedEventArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
@@ -197,6 +206,7 @@ namespace Lantean.QBTMud.Components
|
|||||||
{
|
{
|
||||||
while (!_timerCancellationToken.IsCancellationRequested && await timer.WaitForNextTickAsync())
|
while (!_timerCancellationToken.IsCancellationRequested && await timer.WaitForNextTickAsync())
|
||||||
{
|
{
|
||||||
|
var hasUpdates = false;
|
||||||
if (Active && Hash is not null)
|
if (Active && Hash is not null)
|
||||||
{
|
{
|
||||||
IReadOnlyList<QBitTorrentClient.Models.FileData> files;
|
IReadOnlyList<QBitTorrentClient.Models.FileData> files;
|
||||||
@@ -213,14 +223,20 @@ namespace Lantean.QBTMud.Components
|
|||||||
if (FileList is null)
|
if (FileList is null)
|
||||||
{
|
{
|
||||||
FileList = DataManager.CreateContentsList(files);
|
FileList = DataManager.CreateContentsList(files);
|
||||||
|
hasUpdates = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DataManager.MergeContentsList(files, FileList);
|
hasUpdates = DataManager.MergeContentsList(files, FileList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await InvokeAsync(StateHasChanged);
|
if (hasUpdates)
|
||||||
|
{
|
||||||
|
MarkFilesDirty();
|
||||||
|
PruneSelectionIfMissing();
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,6 +262,8 @@ namespace Lantean.QBTMud.Components
|
|||||||
|
|
||||||
var contents = await ApiClient.GetTorrentContents(Hash);
|
var contents = await ApiClient.GetTorrentContents(Hash);
|
||||||
FileList = DataManager.CreateContentsList(contents);
|
FileList = DataManager.CreateContentsList(contents);
|
||||||
|
MarkFilesDirty();
|
||||||
|
PruneSelectionIfMissing();
|
||||||
|
|
||||||
var expandedNodes = await LocalStorage.GetItemAsync<HashSet<string>>($"{_expandedNodesStorageKey}.{Hash}");
|
var expandedNodes = await LocalStorage.GetItemAsync<HashSet<string>>($"{_expandedNodesStorageKey}.{Hash}");
|
||||||
if (expandedNodes is not null)
|
if (expandedNodes is not null)
|
||||||
@@ -256,6 +274,8 @@ namespace Lantean.QBTMud.Components
|
|||||||
{
|
{
|
||||||
ExpandedNodes.Clear();
|
ExpandedNodes.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MarkFilesDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task PriorityValueChanged(ContentItem contentItem, Priority priority)
|
protected async Task PriorityValueChanged(ContentItem contentItem, Priority priority)
|
||||||
@@ -320,11 +340,13 @@ namespace Lantean.QBTMud.Components
|
|||||||
protected void SortColumnChanged(string sortColumn)
|
protected void SortColumnChanged(string sortColumn)
|
||||||
{
|
{
|
||||||
_sortColumn = sortColumn;
|
_sortColumn = sortColumn;
|
||||||
|
MarkFilesDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void SortDirectionChanged(SortDirection sortDirection)
|
protected void SortDirectionChanged(SortDirection sortDirection)
|
||||||
{
|
{
|
||||||
_sortDirection = sortDirection;
|
_sortDirection = sortDirection;
|
||||||
|
MarkFilesDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void SelectedItemChanged(ContentItem item)
|
protected void SelectedItemChanged(ContentItem item)
|
||||||
@@ -343,6 +365,7 @@ namespace Lantean.QBTMud.Components
|
|||||||
ExpandedNodes.Add(contentItem.Name);
|
ExpandedNodes.Add(contentItem.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MarkFilesDirty();
|
||||||
await LocalStorage.SetItemAsync($"{_expandedNodesStorageKey}.{Hash}", ExpandedNodes);
|
await LocalStorage.SetItemAsync($"{_expandedNodesStorageKey}.{Hash}", ExpandedNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,44 +391,6 @@ namespace Lantean.QBTMud.Components
|
|||||||
return FileList!.Values.Where(f => f.Name.StartsWith(contentItem.Name + Extensions.DirectorySeparator) && !f.IsFolder);
|
return FileList!.Values.Where(f => f.Name.StartsWith(contentItem.Name + Extensions.DirectorySeparator) && !f.IsFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<ContentItem> GetChildren(ContentItem folder, int level)
|
|
||||||
{
|
|
||||||
level++;
|
|
||||||
var descendantsKey = folder.GetDescendantsKey(level);
|
|
||||||
|
|
||||||
foreach (var item in FileList!.Values.Where(f => f.Name.StartsWith(descendantsKey) && f.Level == level).OrderByDirection(_sortDirection, GetSortSelector()))
|
|
||||||
{
|
|
||||||
if (item.IsFolder)
|
|
||||||
{
|
|
||||||
var descendants = GetChildren(item, level);
|
|
||||||
// if the filter returns some results then show folder item
|
|
||||||
if (descendants.Any())
|
|
||||||
{
|
|
||||||
yield return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the folder is not expanded - don't return children
|
|
||||||
if (!ExpandedNodes.Contains(item.Name))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// then show children
|
|
||||||
foreach (var descendant in descendants)
|
|
||||||
{
|
|
||||||
yield return descendant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (FilterContentItem(item))
|
|
||||||
{
|
|
||||||
yield return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool FilterContentItem(ContentItem item)
|
private bool FilterContentItem(ContentItem item)
|
||||||
{
|
{
|
||||||
if (Filters is not null)
|
if (Filters is not null)
|
||||||
@@ -429,38 +414,130 @@ namespace Lantean.QBTMud.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ReadOnlyCollection<ContentItem> GetFiles()
|
private ReadOnlyCollection<ContentItem> GetFiles()
|
||||||
|
{
|
||||||
|
if (!_filesDirty)
|
||||||
|
{
|
||||||
|
return _visibleFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
_visibleFiles = BuildVisibleFiles();
|
||||||
|
_filesDirty = false;
|
||||||
|
|
||||||
|
return _visibleFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReadOnlyCollection<ContentItem> BuildVisibleFiles()
|
||||||
{
|
{
|
||||||
if (FileList is null || FileList.Values.Count == 0)
|
if (FileList is null || FileList.Values.Count == 0)
|
||||||
{
|
{
|
||||||
return new ReadOnlyCollection<ContentItem>([]);
|
return EmptyContentItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxLevel = FileList.Values.Max(f => f.Level);
|
var lookup = BuildChildrenLookup();
|
||||||
// this is a flat file structure
|
if (!lookup.TryGetValue(string.Empty, out var roots))
|
||||||
if (maxLevel == 0)
|
|
||||||
{
|
{
|
||||||
return FileList.Values.Where(FilterContentItem).OrderByDirection(_sortDirection, GetSortSelector()).ToList().AsReadOnly();
|
return EmptyContentItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
var list = new List<ContentItem>();
|
var sortSelector = GetSortSelector();
|
||||||
|
var orderedRoots = roots.OrderByDirection(_sortDirection, sortSelector).ToList();
|
||||||
|
var result = new List<ContentItem>(FileList.Values.Count);
|
||||||
|
|
||||||
var rootItems = FileList.Values.Where(c => c.Level == 0).OrderByDirection(_sortDirection, GetSortSelector()).ToList();
|
foreach (var item in orderedRoots)
|
||||||
foreach (var item in rootItems)
|
|
||||||
{
|
{
|
||||||
list.Add(item);
|
if (item.IsFolder)
|
||||||
|
|
||||||
if (item.IsFolder && ExpandedNodes.Contains(item.Name))
|
|
||||||
{
|
{
|
||||||
var level = 0;
|
result.Add(item);
|
||||||
var descendants = GetChildren(item, level);
|
|
||||||
foreach (var descendant in descendants)
|
if (!ExpandedNodes.Contains(item.Name))
|
||||||
{
|
{
|
||||||
list.Add(descendant);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var descendants = GetVisibleDescendants(item, lookup, sortSelector);
|
||||||
|
result.AddRange(descendants);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (FilterContentItem(item))
|
||||||
|
{
|
||||||
|
result.Add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return list.AsReadOnly();
|
return new ReadOnlyCollection<ContentItem>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<string, List<ContentItem>> BuildChildrenLookup()
|
||||||
|
{
|
||||||
|
var lookup = new Dictionary<string, List<ContentItem>>(FileList!.Count);
|
||||||
|
|
||||||
|
foreach (var item in FileList!.Values)
|
||||||
|
{
|
||||||
|
var parentPath = item.Level == 0 ? string.Empty : item.Name.GetDirectoryPath();
|
||||||
|
if (!lookup.TryGetValue(parentPath, out var children))
|
||||||
|
{
|
||||||
|
children = [];
|
||||||
|
lookup[parentPath] = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
children.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lookup;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ContentItem> GetVisibleDescendants(ContentItem folder, Dictionary<string, List<ContentItem>> lookup, Func<ContentItem, object?> sortSelector)
|
||||||
|
{
|
||||||
|
if (!lookup.TryGetValue(folder.Name, out var children))
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var orderedChildren = children.OrderByDirection(_sortDirection, sortSelector).ToList();
|
||||||
|
var visible = new List<ContentItem>();
|
||||||
|
|
||||||
|
foreach (var child in orderedChildren)
|
||||||
|
{
|
||||||
|
if (child.IsFolder)
|
||||||
|
{
|
||||||
|
var descendants = GetVisibleDescendants(child, lookup, sortSelector);
|
||||||
|
if (descendants.Count != 0)
|
||||||
|
{
|
||||||
|
visible.Add(child);
|
||||||
|
|
||||||
|
if (ExpandedNodes.Contains(child.Name))
|
||||||
|
{
|
||||||
|
visible.AddRange(descendants);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (FilterContentItem(child))
|
||||||
|
{
|
||||||
|
visible.Add(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MarkFilesDirty()
|
||||||
|
{
|
||||||
|
_filesDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PruneSelectionIfMissing()
|
||||||
|
{
|
||||||
|
if (SelectedItem is not null && (FileList is null || !FileList.ContainsKey(SelectedItem.Name)))
|
||||||
|
{
|
||||||
|
SelectedItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ContextMenuItem is not null && (FileList is null || !FileList.ContainsKey(ContextMenuItem.Name)))
|
||||||
|
{
|
||||||
|
ContextMenuItem = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task DoNotDownloadLessThan100PercentAvailability()
|
protected async Task DoNotDownloadLessThan100PercentAvailability()
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<ContextMenu @ref="StatusContextMenu" Dense="true" AdjustmentY="-60">
|
<MudMenu @ref="StatusContextMenu" Dense="true" PositionAtCursor="true" ListClass="unselectable" PopoverClass="unselectable">
|
||||||
@TorrentControls(_statusType)
|
@TorrentControls(_statusType)
|
||||||
</ContextMenu>
|
</MudMenu>
|
||||||
|
|
||||||
<ContextMenu @ref="CategoryContextMenu" Dense="true" AdjustmentY="-60">
|
<MudMenu @ref="CategoryContextMenu" Dense="true" PositionAtCursor="true" ListClass="unselectable" PopoverClass="unselectable">
|
||||||
<MudMenuItem Icon="@Icons.Material.Outlined.AddCircle" IconColor="Color.Info" OnClick="AddCategory">Add category</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Outlined.AddCircle" IconColor="Color.Info" OnClick="AddCategory">Add category</MudMenuItem>
|
||||||
@if (IsCategoryTarget)
|
@if (IsCategoryTarget)
|
||||||
{
|
{
|
||||||
@@ -12,9 +12,9 @@
|
|||||||
<MudMenuItem Icon="@Icons.Material.Filled.Delete" IconColor="Color.Error" OnClick="RemoveUnusedCategories">Remove unused categories</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Filled.Delete" IconColor="Color.Error" OnClick="RemoveUnusedCategories">Remove unused categories</MudMenuItem>
|
||||||
<MudDivider />
|
<MudDivider />
|
||||||
@TorrentControls(_categoryType)
|
@TorrentControls(_categoryType)
|
||||||
</ContextMenu>
|
</MudMenu>
|
||||||
|
|
||||||
<ContextMenu @ref="TagContextMenu" Dense="true" AdjustmentY="-60">
|
<MudMenu @ref="TagContextMenu" Dense="true" PositionAtCursor="true" ListClass="unselectable" PopoverClass="unselectable">
|
||||||
<MudMenuItem Icon="@Icons.Material.Outlined.AddCircle" IconColor="Color.Info" OnClick="AddTag">Add tag</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Outlined.AddCircle" IconColor="Color.Info" OnClick="AddTag">Add tag</MudMenuItem>
|
||||||
@if (IsTagTarget)
|
@if (IsTagTarget)
|
||||||
{
|
{
|
||||||
@@ -23,13 +23,13 @@
|
|||||||
<MudMenuItem Icon="@Icons.Material.Filled.Delete" IconColor="Color.Error" OnClick="RemoveUnusedTags">Remove unused tags</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Filled.Delete" IconColor="Color.Error" OnClick="RemoveUnusedTags">Remove unused tags</MudMenuItem>
|
||||||
<MudDivider />
|
<MudDivider />
|
||||||
@TorrentControls(_tagType)
|
@TorrentControls(_tagType)
|
||||||
</ContextMenu>
|
</MudMenu>
|
||||||
|
|
||||||
<ContextMenu @ref="TrackerContextMenu" Dense="true" AdjustmentY="-60">
|
<MudMenu @ref="TrackerContextMenu" Dense="true" PositionAtCursor="true" ListClass="unselectable" PopoverClass="unselectable">
|
||||||
<MudMenuItem Icon="@Icons.Material.Filled.Delete" IconColor="Color.Error" OnClick="RemoveUnusedCategories">Remove tracker</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Filled.Delete" IconColor="Color.Error" OnClick="RemoveUnusedCategories">Remove tracker</MudMenuItem>
|
||||||
<MudDivider />
|
<MudDivider />
|
||||||
@TorrentControls(_trackerType)
|
@TorrentControls(_trackerType)
|
||||||
</ContextMenu>
|
</MudMenu>
|
||||||
|
|
||||||
<MudNavMenu Dense="true">
|
<MudNavMenu Dense="true">
|
||||||
<MudNavGroup Title="Status" @bind-Expanded="_statusExpanded">
|
<MudNavGroup Title="Status" @bind-Expanded="_statusExpanded">
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Blazored.LocalStorage;
|
using Blazored.LocalStorage;
|
||||||
using Lantean.QBitTorrentClient;
|
using Lantean.QBitTorrentClient;
|
||||||
using Lantean.QBTMud.Components.UI;
|
|
||||||
using Lantean.QBTMud.Helpers;
|
using Lantean.QBTMud.Helpers;
|
||||||
using Lantean.QBTMud.Models;
|
using Lantean.QBTMud.Models;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
@@ -69,13 +68,13 @@ namespace Lantean.QBTMud.Components
|
|||||||
|
|
||||||
protected Dictionary<string, int> Statuses => GetStatuses();
|
protected Dictionary<string, int> Statuses => GetStatuses();
|
||||||
|
|
||||||
protected ContextMenu? StatusContextMenu { get; set; }
|
protected MudMenu? StatusContextMenu { get; set; }
|
||||||
|
|
||||||
protected ContextMenu? CategoryContextMenu { get; set; }
|
protected MudMenu? CategoryContextMenu { get; set; }
|
||||||
|
|
||||||
protected ContextMenu? TagContextMenu { get; set; }
|
protected MudMenu? TagContextMenu { get; set; }
|
||||||
|
|
||||||
protected ContextMenu? TrackerContextMenu { get; set; }
|
protected MudMenu? TrackerContextMenu { get; set; }
|
||||||
|
|
||||||
protected string? ContextMenuStatus { get; set; }
|
protected string? ContextMenuStatus { get; set; }
|
||||||
|
|
||||||
@@ -154,7 +153,9 @@ namespace Lantean.QBTMud.Components
|
|||||||
|
|
||||||
ContextMenuStatus = value;
|
ContextMenuStatus = value;
|
||||||
|
|
||||||
return StatusContextMenu.OpenMenuAsync(args);
|
var normalizedArgs = args.NormalizeForContextMenu();
|
||||||
|
|
||||||
|
return StatusContextMenu.OpenMenuAsync(normalizedArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task CategoryValueChanged(string value)
|
protected async Task CategoryValueChanged(string value)
|
||||||
@@ -192,7 +193,9 @@ namespace Lantean.QBTMud.Components
|
|||||||
IsCategoryTarget = value != FilterHelper.CATEGORY_ALL && value != FilterHelper.CATEGORY_UNCATEGORIZED;
|
IsCategoryTarget = value != FilterHelper.CATEGORY_ALL && value != FilterHelper.CATEGORY_UNCATEGORIZED;
|
||||||
ContextMenuCategory = value;
|
ContextMenuCategory = value;
|
||||||
|
|
||||||
return CategoryContextMenu.OpenMenuAsync(args);
|
var normalizedArgs = args.NormalizeForContextMenu();
|
||||||
|
|
||||||
|
return CategoryContextMenu.OpenMenuAsync(normalizedArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task TagValueChanged(string value)
|
protected async Task TagValueChanged(string value)
|
||||||
@@ -230,7 +233,9 @@ namespace Lantean.QBTMud.Components
|
|||||||
IsTagTarget = value != FilterHelper.TAG_ALL && value != FilterHelper.TAG_UNTAGGED;
|
IsTagTarget = value != FilterHelper.TAG_ALL && value != FilterHelper.TAG_UNTAGGED;
|
||||||
ContextMenuTag = value;
|
ContextMenuTag = value;
|
||||||
|
|
||||||
return TagContextMenu.OpenMenuAsync(args);
|
var normalizedArgs = args.NormalizeForContextMenu();
|
||||||
|
|
||||||
|
return TagContextMenu.OpenMenuAsync(normalizedArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task TrackerValueChanged(string value)
|
protected async Task TrackerValueChanged(string value)
|
||||||
@@ -267,7 +272,9 @@ namespace Lantean.QBTMud.Components
|
|||||||
|
|
||||||
ContextMenuTracker = value;
|
ContextMenuTracker = value;
|
||||||
|
|
||||||
return TrackerContextMenu.OpenMenuAsync(args);
|
var normalizedArgs = args.NormalizeForContextMenu();
|
||||||
|
|
||||||
|
return TrackerContextMenu.OpenMenuAsync(normalizedArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task AddCategory()
|
protected async Task AddCategory()
|
||||||
|
|||||||
@@ -98,4 +98,4 @@
|
|||||||
<MudField Label="Comment">@Properties?.Comment</MudField>
|
<MudField Label="Comment">@Properties?.Comment</MudField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudContainer>
|
</MudContainer>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@inherits Options
|
@inherits Options
|
||||||
|
|
||||||
<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>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Physical memory (RAM) usage limit (applied if libtorrent >= 2.0)" Value="MemoryWorkingSetLimit" ValueChanged="MemoryWorkingSetLimitChanged" Min="0" HelperText="This option is less effective on Linux" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="MiB" />
|
<MudNumericField T="int" Label="Physical memory (RAM) usage limit (applied if libtorrent >= 2.0)" Value="MemoryWorkingSetLimit" ValueChanged="MemoryWorkingSetLimitChanged" Min="0" HelperText="This option is less effective on Linux" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="MiB" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudSelect T="string" Label="Network interface" Value="CurrentNetworkInterface" ValueChanged="CurrentNetworkInterfaceChanged" Variant="Variant.Outlined">
|
<MudSelect T="string" Label="Network interface" Value="CurrentNetworkInterface" ValueChanged="CurrentNetworkInterfaceChanged" Variant="Variant.Outlined">
|
||||||
@@ -38,19 +38,16 @@
|
|||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Save resume data interval" Value="SaveResumeDataInterval" ValueChanged="SaveResumeDataIntervalChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="min" />
|
<MudNumericField T="int" Label="Save resume data interval" Value="SaveResumeDataInterval" ValueChanged="SaveResumeDataIntervalChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="min" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Save transfer statistics interval" Value="SaveStatisticsInterval" ValueChanged="SaveStatisticsIntervalChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="min" />
|
<MudNumericField T="int" Label=".torrent file size limit" Value="TorrentFileSizeLimit" ValueChanged="TorrentFileSizeLimitChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="MiB" />
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label=".torrent file size limit" Value="TorrentFileSizeLimit" ValueChanged="TorrentFileSizeLimitChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="MiB" />
|
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Recheck torrents on completion" Value="RecheckCompletedTorrents" ValueChanged="RecheckCompletedTorrentsChanged" />
|
<FieldSwitch Label="Recheck torrents on completion" Value="RecheckCompletedTorrents" ValueChanged="RecheckCompletedTorrentsChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Refresh interval" Value="RefreshInterval" ValueChanged="RefreshIntervalChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="ms" />
|
<MudNumericField T="int" Label="Refresh interval" Value="RefreshInterval" ValueChanged="RefreshIntervalChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="ms" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Resolve peer countries" Value="ResolvePeerCountries" ValueChanged="ResolvePeerCountriesChanged" />
|
<FieldSwitch Label="Resolve peer countries" Value="ResolvePeerCountries" ValueChanged="ResolvePeerCountriesChanged" />
|
||||||
@@ -62,7 +59,7 @@
|
|||||||
<FieldSwitch Label="Enable embedded tracker" Value="EnableEmbeddedTracker" ValueChanged="EnableEmbeddedTrackerChanged" />
|
<FieldSwitch Label="Enable embedded tracker" Value="EnableEmbeddedTracker" ValueChanged="EnableEmbeddedTrackerChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Embedded tracker port" Value="EmbeddedTrackerPort" ValueChanged="EmbeddedTrackerPortChanged" Min="@Options.MinPortValue" Max="@Options.MaxPortValue" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Embedded tracker port" Value="EmbeddedTrackerPort" ValueChanged="EmbeddedTrackerPortChanged" Min="@Options.MinPortValue" Max="@Options.MaxPortValue" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Enable port forwarding for embedded tracker" Value="EmbeddedTrackerPortForwarding" ValueChanged="EmbeddedTrackerPortForwardingChanged" />
|
<FieldSwitch Label="Enable port forwarding for embedded tracker" Value="EmbeddedTrackerPortForwarding" ValueChanged="EmbeddedTrackerPortForwardingChanged" />
|
||||||
@@ -80,31 +77,31 @@
|
|||||||
<MudCardContent Class="pt-0">
|
<MudCardContent Class="pt-0">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Bdecode depth limit" Value="BdecodeDepthLimit" ValueChanged="BdecodeDepthLimitChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Bdecode depth limit" Value="BdecodeDepthLimit" ValueChanged="BdecodeDepthLimitChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Bdecode token limit" Value="BdecodeTokenLimit" ValueChanged="BdecodeTokenLimitChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Bdecode token limit" Value="BdecodeTokenLimit" ValueChanged="BdecodeTokenLimitChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Asynchronous I/O threads" Value="AsyncIoThreads" ValueChanged="AsyncIoThreadsChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Asynchronous I/O threads" Value="AsyncIoThreads" ValueChanged="AsyncIoThreadsChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Hashing threads (requires libtorrent >= 2.0)" Value="HashingThreads" ValueChanged="HashingThreadsChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Hashing threads (requires libtorrent >= 2.0)" Value="HashingThreads" ValueChanged="HashingThreadsChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="File pool size" Value="FilePoolSize" ValueChanged="FilePoolSizeChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="File pool size" Value="FilePoolSize" ValueChanged="FilePoolSizeChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Outstanding memory when checking torrents" Value="CheckingMemoryUse" ValueChanged="CheckingMemoryUseChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="MiB" />
|
<MudNumericField T="int" Label="Outstanding memory when checking torrents" Value="CheckingMemoryUse" ValueChanged="CheckingMemoryUseChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="MiB" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Disk cache (requires libtorrent < 2.0)" Value="DiskCache" ValueChanged="DiskCacheChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="MiB" />
|
<MudNumericField T="int" Label="Disk cache (requires libtorrent < 2.0)" Value="DiskCache" ValueChanged="DiskCacheChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="MiB" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Disk cache expiry interval (requires libtorrent < 2.0)" Value="DiskCacheTtl" ValueChanged="DiskCacheTtlChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="s" />
|
<MudNumericField T="int" Label="Disk cache expiry interval (requires libtorrent < 2.0)" Value="DiskCacheTtl" ValueChanged="DiskCacheTtlChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="s" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Disk queue size" Value="DiskQueueSize" ValueChanged="DiskQueueSizeChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
<MudNumericField T="int" Label="Disk queue size" Value="DiskQueueSize" ValueChanged="DiskQueueSizeChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudSelect T="int" Label="Disk IO type (libtorrent >= 2.0; requires restart)" Value="DiskIoType" ValueChanged="DiskIoTypeChanged" Variant="Variant.Outlined">
|
<MudSelect T="int" Label="Disk IO type (libtorrent >= 2.0; requires restart)" Value="DiskIoType" ValueChanged="DiskIoTypeChanged" Variant="Variant.Outlined">
|
||||||
@@ -136,40 +133,40 @@
|
|||||||
<FieldSwitch Label="Send upload piece suggestions" Value="EnableUploadSuggestions" ValueChanged="EnableUploadSuggestionsChanged" />
|
<FieldSwitch Label="Send upload piece suggestions" Value="EnableUploadSuggestions" ValueChanged="EnableUploadSuggestionsChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Send buffer watermark" Value="SendBufferWatermark" ValueChanged="SendBufferWatermarkChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
<MudNumericField T="int" Label="Send buffer watermark" Value="SendBufferWatermark" ValueChanged="SendBufferWatermarkChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Send buffer low watermark" Value="SendBufferLowWatermark" ValueChanged="SendBufferLowWatermarkChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
<MudNumericField T="int" Label="Send buffer low watermark" Value="SendBufferLowWatermark" ValueChanged="SendBufferLowWatermarkChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Send buffer watermark factor" Value="SendBufferWatermarkFactor" ValueChanged="SendBufferWatermarkFactorChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="%" />
|
<MudNumericField T="int" Label="Send buffer watermark factor" Value="SendBufferWatermarkFactor" ValueChanged="SendBufferWatermarkFactorChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="%" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Outgoing connections per second" Value="ConnectionSpeed" ValueChanged="ConnectionSpeedChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Outgoing connections per second" Value="ConnectionSpeed" ValueChanged="ConnectionSpeedChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Socket send buffer size [0: system default]" Value="SocketSendBufferSize" ValueChanged="SocketSendBufferSizeChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
<MudNumericField T="int" Label="Socket send buffer size [0: system default]" Value="SocketSendBufferSize" ValueChanged="SocketSendBufferSizeChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Socket receive buffer size [0: system default]" Value="SocketReceiveBufferSize" ValueChanged="SocketReceiveBufferSizeChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
<MudNumericField T="int" Label="Socket receive buffer size [0: system default]" Value="SocketReceiveBufferSize" ValueChanged="SocketReceiveBufferSizeChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Socket backlog size" Value="SocketBacklogSize" ValueChanged="SocketBacklogSizeChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Socket backlog size" Value="SocketBacklogSize" ValueChanged="SocketBacklogSizeChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Outgoing ports (Min) [0: disabled]" Value="OutgoingPortsMin" ValueChanged="OutgoingPortsMinChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Outgoing ports (Min) [0: disabled]" Value="OutgoingPortsMin" ValueChanged="OutgoingPortsMinChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Outgoing ports (Max) [0: disabled]" Value="OutgoingPortsMax" ValueChanged="OutgoingPortsMaxChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Outgoing ports (Max) [0: disabled]" Value="OutgoingPortsMax" ValueChanged="OutgoingPortsMaxChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="UPnP lease duration [0: permanent lease]" Value="UpnpLeaseDuration" ValueChanged="UpnpLeaseDurationChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="UPnP lease duration [0: permanent lease]" Value="UpnpLeaseDuration" ValueChanged="UpnpLeaseDurationChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Type of service (ToS) for connections to peers" Value="PeerTos" ValueChanged="PeerTosChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Type of service (ToS) for connections to peers" Value="PeerTos" ValueChanged="PeerTosChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudSelect T="int" Label="<EFBFBD>TP-TCP mixed mode algorithm" Value="UtpTcpMixedMode" ValueChanged="UtpTcpMixedModeChanged" Variant="Variant.Outlined">
|
<MudSelect T="int" Label="μTP-TCP mixed mode algorithm" Value="UtpTcpMixedMode" ValueChanged="UtpTcpMixedModeChanged" Variant="Variant.Outlined">
|
||||||
<MudSelectItem T="int" Value="0">Prefer TCP</MudSelectItem>
|
<MudSelectItem T="int" Value="0">Prefer TCP</MudSelectItem>
|
||||||
<MudSelectItem T="int" Value="1">Peer proportional (throttles TCP)</MudSelectItem>
|
<MudSelectItem T="int" Value="1">Peer proportional (throttles TCP)</MudSelectItem>
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
@@ -183,9 +180,6 @@
|
|||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Validate HTTPS tracker certificate" Value="ValidateHttpsTrackerCertificate" ValueChanged="ValidateHttpsTrackerCertificateChanged" />
|
<FieldSwitch Label="Validate HTTPS tracker certificate" Value="ValidateHttpsTrackerCertificate" ValueChanged="ValidateHttpsTrackerCertificateChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
|
||||||
<FieldSwitch Label="Ignore SSL errors" Value="IgnoreSslErrors" ValueChanged="IgnoreSslErrorsChanged" />
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Server-side request forgery (SSRF) mitigation" Value="SsrfMitigation" ValueChanged="SsrfMitigationChanged" />
|
<FieldSwitch Label="Server-side request forgery (SSRF) mitigation" Value="SsrfMitigation" ValueChanged="SsrfMitigationChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
@@ -212,47 +206,38 @@
|
|||||||
<FieldSwitch Label="Always announce to all tiers" Value="AnnounceToAllTiers" ValueChanged="AnnounceToAllTiersChanged" />
|
<FieldSwitch Label="Always announce to all tiers" Value="AnnounceToAllTiers" ValueChanged="AnnounceToAllTiersChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="IP address reported to trackers (requires restart)" Value="AnnounceIp" ValueChanged="AnnounceIpChanged" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="IP address reported to trackers (requires restart)" Value="AnnounceIp" ValueChanged="AnnounceIpChanged" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Port reported to trackers (requires restart)" Value="AnnouncePort" ValueChanged="AnnouncePortChanged" Min="0" Max="65535" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Max concurrent HTTP announces" Value="MaxConcurrentHttpAnnounces" ValueChanged="MaxConcurrentHttpAnnouncesChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Max concurrent HTTP announces" Value="MaxConcurrentHttpAnnounces" ValueChanged="MaxConcurrentHttpAnnouncesChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Stop tracker timeout [0: disabled]" Value="StopTrackerTimeout" ValueChanged="StopTrackerTimeoutChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Stop tracker timeout [0: disabled]" Value="StopTrackerTimeout" ValueChanged="StopTrackerTimeoutChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Peer turnover disconnect percentage:" Value="PeerTurnover" ValueChanged="PeerTurnoverChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="%" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Peer turnover disconnect percentage:" Value="PeerTurnover" ValueChanged="PeerTurnoverChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="%" />
|
<MudNumericField T="int" Label="Peer turnover threshold percentage" Value="PeerTurnoverCutoff" ValueChanged="PeerTurnoverCutoffChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="%" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Peer turnover threshold percentage" Value="PeerTurnoverCutoff" ValueChanged="PeerTurnoverCutoffChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="%" />
|
<MudNumericField T="int" Label="Peer turnover disconnect interval" Value="PeerTurnoverInterval" ValueChanged="PeerTurnoverIntervalChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="s" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Peer turnover disconnect interval" Value="PeerTurnoverInterval" ValueChanged="PeerTurnoverIntervalChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="s" />
|
<MudNumericField T="int" Label="Maximum outstanding requests to a single peer" Value="RequestQueueSize" ValueChanged="RequestQueueSizeChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Hostname lookup cache TTL" Value="HostnameCacheTtl" ValueChanged="HostnameCacheTtlChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="s" />
|
<MudNumericField T="int" Label="I2P inbound quantity (requires libtorrent >= 2.0)" Value="I2pInboundQuantity" ValueChanged="I2pInboundQuantityChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Maximum outstanding requests to a single peer" Value="RequestQueueSize" ValueChanged="RequestQueueSizeChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="I2P outbound quantity (requires libtorrent >= 2.0)" Value="I2pOutboundQuantity" ValueChanged="I2pOutboundQuantityChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="I2P inbound quantity (requires libtorrent >= 2.0)" Value="I2pInboundQuantity" ValueChanged="I2pInboundQuantityChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="I2P inbound length (requires libtorrent >= 2.0)" Value="I2pInboundLength" ValueChanged="I2pInboundLengthChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="I2P outbound quantity (requires libtorrent >= 2.0)" Value="I2pOutboundQuantity" ValueChanged="I2pOutboundQuantityChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="I2P outbound length (requires libtorrent >= 2.0)" Value="I2pOutboundLength" ValueChanged="I2pOutboundLengthChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="I2P inbound length (requires libtorrent >= 2.0)" Value="I2pInboundLength" ValueChanged="I2pInboundLengthChanged" Min="0" Variant="Variant.Outlined" />
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="I2P outbound length (requires libtorrent >= 2.0)" Value="I2pOutboundLength" ValueChanged="I2pOutboundLengthChanged" Min="0" Variant="Variant.Outlined" />
|
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -14,7 +14,6 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
protected string? CurrentNetworkInterface { get; private set; }
|
protected string? CurrentNetworkInterface { get; private set; }
|
||||||
protected string? CurrentInterfaceAddress { get; private set; }
|
protected string? CurrentInterfaceAddress { get; private set; }
|
||||||
protected int SaveResumeDataInterval { get; private set; }
|
protected int SaveResumeDataInterval { get; private set; }
|
||||||
protected int SaveStatisticsInterval { 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 string? AppInstanceName { get; private set; }
|
protected string? AppInstanceName { get; private set; }
|
||||||
@@ -51,7 +50,6 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
protected bool IdnSupportEnabled { get; private set; }
|
protected bool IdnSupportEnabled { get; private set; }
|
||||||
protected bool EnableMultiConnectionsFromSameIp { get; private set; }
|
protected bool EnableMultiConnectionsFromSameIp { get; private set; }
|
||||||
protected bool ValidateHttpsTrackerCertificate { get; private set; }
|
protected bool ValidateHttpsTrackerCertificate { get; private set; }
|
||||||
protected bool IgnoreSslErrors { get; private set; }
|
|
||||||
protected bool SsrfMitigation { get; private set; }
|
protected bool SsrfMitigation { get; private set; }
|
||||||
protected bool BlockPeersOnPrivilegedPorts { get; private set; }
|
protected bool BlockPeersOnPrivilegedPorts { get; private set; }
|
||||||
protected bool EnableEmbeddedTracker { get; private set; }
|
protected bool EnableEmbeddedTracker { get; private set; }
|
||||||
@@ -64,13 +62,11 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
protected bool AnnounceToAllTrackers { get; private set; }
|
protected bool AnnounceToAllTrackers { get; private set; }
|
||||||
protected bool AnnounceToAllTiers { get; private set; }
|
protected bool AnnounceToAllTiers { get; private set; }
|
||||||
protected string? AnnounceIp { get; private set; }
|
protected string? AnnounceIp { get; private set; }
|
||||||
protected int AnnouncePort { get; private set; }
|
|
||||||
protected int MaxConcurrentHttpAnnounces { get; private set; }
|
protected int MaxConcurrentHttpAnnounces { get; private set; }
|
||||||
protected int StopTrackerTimeout { get; private set; }
|
protected int StopTrackerTimeout { get; private set; }
|
||||||
protected int PeerTurnover { get; private set; }
|
protected int PeerTurnover { get; private set; }
|
||||||
protected int PeerTurnoverCutoff { get; private set; }
|
protected int PeerTurnoverCutoff { get; private set; }
|
||||||
protected int PeerTurnoverInterval { get; private set; }
|
protected int PeerTurnoverInterval { get; private set; }
|
||||||
protected int HostnameCacheTtl { get; private set; }
|
|
||||||
protected int RequestQueueSize { get; private set; }
|
protected int RequestQueueSize { get; private set; }
|
||||||
protected string? DhtBootstrapNodes { get; private set; }
|
protected string? DhtBootstrapNodes { get; private set; }
|
||||||
protected int I2pInboundQuantity { get; private set; }
|
protected int I2pInboundQuantity { get; private set; }
|
||||||
@@ -99,7 +95,6 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
CurrentNetworkInterface = Preferences.CurrentNetworkInterface;
|
CurrentNetworkInterface = Preferences.CurrentNetworkInterface;
|
||||||
CurrentInterfaceAddress = Preferences.CurrentInterfaceAddress;
|
CurrentInterfaceAddress = Preferences.CurrentInterfaceAddress;
|
||||||
SaveResumeDataInterval = Preferences.SaveResumeDataInterval;
|
SaveResumeDataInterval = Preferences.SaveResumeDataInterval;
|
||||||
SaveStatisticsInterval = Preferences.SaveStatisticsInterval;
|
|
||||||
TorrentFileSizeLimit = Preferences.TorrentFileSizeLimit / 1024 / 1024;
|
TorrentFileSizeLimit = Preferences.TorrentFileSizeLimit / 1024 / 1024;
|
||||||
RecheckCompletedTorrents = Preferences.RecheckCompletedTorrents;
|
RecheckCompletedTorrents = Preferences.RecheckCompletedTorrents;
|
||||||
AppInstanceName = Preferences.AppInstanceName;
|
AppInstanceName = Preferences.AppInstanceName;
|
||||||
@@ -136,7 +131,6 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
IdnSupportEnabled = Preferences.IdnSupportEnabled;
|
IdnSupportEnabled = Preferences.IdnSupportEnabled;
|
||||||
EnableMultiConnectionsFromSameIp = Preferences.EnableMultiConnectionsFromSameIp;
|
EnableMultiConnectionsFromSameIp = Preferences.EnableMultiConnectionsFromSameIp;
|
||||||
ValidateHttpsTrackerCertificate = Preferences.ValidateHttpsTrackerCertificate;
|
ValidateHttpsTrackerCertificate = Preferences.ValidateHttpsTrackerCertificate;
|
||||||
IgnoreSslErrors = Preferences.IgnoreSslErrors;
|
|
||||||
SsrfMitigation = Preferences.SsrfMitigation;
|
SsrfMitigation = Preferences.SsrfMitigation;
|
||||||
BlockPeersOnPrivilegedPorts = Preferences.BlockPeersOnPrivilegedPorts;
|
BlockPeersOnPrivilegedPorts = Preferences.BlockPeersOnPrivilegedPorts;
|
||||||
EnableEmbeddedTracker = Preferences.EnableEmbeddedTracker;
|
EnableEmbeddedTracker = Preferences.EnableEmbeddedTracker;
|
||||||
@@ -149,13 +143,11 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
AnnounceToAllTrackers = Preferences.AnnounceToAllTrackers;
|
AnnounceToAllTrackers = Preferences.AnnounceToAllTrackers;
|
||||||
AnnounceToAllTiers = Preferences.AnnounceToAllTiers;
|
AnnounceToAllTiers = Preferences.AnnounceToAllTiers;
|
||||||
AnnounceIp = Preferences.AnnounceIp;
|
AnnounceIp = Preferences.AnnounceIp;
|
||||||
AnnouncePort = Preferences.AnnouncePort;
|
|
||||||
MaxConcurrentHttpAnnounces = Preferences.MaxConcurrentHttpAnnounces;
|
MaxConcurrentHttpAnnounces = Preferences.MaxConcurrentHttpAnnounces;
|
||||||
StopTrackerTimeout = Preferences.StopTrackerTimeout;
|
StopTrackerTimeout = Preferences.StopTrackerTimeout;
|
||||||
PeerTurnover = Preferences.PeerTurnover;
|
PeerTurnover = Preferences.PeerTurnover;
|
||||||
PeerTurnoverCutoff = Preferences.PeerTurnoverCutoff;
|
PeerTurnoverCutoff = Preferences.PeerTurnoverCutoff;
|
||||||
PeerTurnoverInterval = Preferences.PeerTurnoverInterval;
|
PeerTurnoverInterval = Preferences.PeerTurnoverInterval;
|
||||||
HostnameCacheTtl = Preferences.HostnameCacheTtl;
|
|
||||||
RequestQueueSize = Preferences.RequestQueueSize;
|
RequestQueueSize = Preferences.RequestQueueSize;
|
||||||
DhtBootstrapNodes = Preferences.DhtBootstrapNodes;
|
DhtBootstrapNodes = Preferences.DhtBootstrapNodes;
|
||||||
I2pInboundQuantity = Preferences.I2pInboundQuantity;
|
I2pInboundQuantity = Preferences.I2pInboundQuantity;
|
||||||
@@ -203,13 +195,6 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task SaveStatisticsIntervalChanged(int value)
|
|
||||||
{
|
|
||||||
SaveStatisticsInterval = value;
|
|
||||||
UpdatePreferences.SaveStatisticsInterval = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task TorrentFileSizeLimitChanged(int value)
|
protected async Task TorrentFileSizeLimitChanged(int value)
|
||||||
{
|
{
|
||||||
TorrentFileSizeLimit = value;
|
TorrentFileSizeLimit = value;
|
||||||
@@ -462,13 +447,6 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task IgnoreSslErrorsChanged(bool value)
|
|
||||||
{
|
|
||||||
IgnoreSslErrors = value;
|
|
||||||
UpdatePreferences.IgnoreSslErrors = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task SsrfMitigationChanged(bool value)
|
protected async Task SsrfMitigationChanged(bool value)
|
||||||
{
|
{
|
||||||
SsrfMitigation = value;
|
SsrfMitigation = value;
|
||||||
@@ -553,13 +531,6 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task AnnouncePortChanged(int value)
|
|
||||||
{
|
|
||||||
AnnouncePort = value;
|
|
||||||
UpdatePreferences.AnnouncePort = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task MaxConcurrentHttpAnnouncesChanged(int value)
|
protected async Task MaxConcurrentHttpAnnouncesChanged(int value)
|
||||||
{
|
{
|
||||||
MaxConcurrentHttpAnnounces = value;
|
MaxConcurrentHttpAnnounces = value;
|
||||||
@@ -588,13 +559,6 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task HostnameCacheTtlChanged(int value)
|
|
||||||
{
|
|
||||||
HostnameCacheTtl = value;
|
|
||||||
UpdatePreferences.HostnameCacheTtl = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task PeerTurnoverIntervalChanged(int value)
|
protected async Task PeerTurnoverIntervalChanged(int value)
|
||||||
{
|
{
|
||||||
PeerTurnoverInterval = value;
|
PeerTurnoverInterval = value;
|
||||||
@@ -644,4 +608,4 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@inherits Options
|
@inherits Options
|
||||||
|
|
||||||
<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>
|
||||||
@@ -29,13 +29,13 @@
|
|||||||
<FieldSwitch Label="Log file" Value="FileLogEnabled" ValueChanged="FileLogEnabledChanged" />
|
<FieldSwitch Label="Log file" Value="FileLogEnabled" ValueChanged="FileLogEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Save Path" Value="FileLogPath" ValueChanged="FileLogPathChanged" Disabled="@(!FileLogEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Save Path" Value="FileLogPath" ValueChanged="FileLogPathChanged" Disabled="@(!FileLogEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="3">
|
<MudItem xs="3">
|
||||||
<FieldSwitch Label="Backup the log after" Value="FileLogBackupEnabled" ValueChanged="FileLogBackupEnabledChanged" Disabled="@(!FileLogEnabled)" />
|
<FieldSwitch Label="Backup the log after" Value="FileLogBackupEnabled" ValueChanged="FileLogBackupEnabledChanged" Disabled="@(!FileLogEnabled)" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="9">
|
<MudItem xs="9">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Value="FileLogMaxSize" ValueChanged="FileLogMaxSizeChanged" Disabled="@(!FileLogEnabled)" Min="1" Max="1024000" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
<MudNumericField T="int" Value="FileLogMaxSize" ValueChanged="FileLogMaxSizeChanged" Disabled="@(!FileLogEnabled)" Min="1" Max="1024000" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="3">
|
<MudItem xs="3">
|
||||||
<FieldSwitch Label="Delete backups older than" Value="FileLogDeleteOld" ValueChanged="FileLogDeleteOldChanged" Disabled="@(!FileLogEnabled)" />
|
<FieldSwitch Label="Delete backups older than" Value="FileLogDeleteOld" ValueChanged="FileLogDeleteOldChanged" Disabled="@(!FileLogEnabled)" />
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
<MudItem xs="9">
|
<MudItem xs="9">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="9">
|
<MudItem xs="9">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Value="FileLogAge" ValueChanged="FileLogAgeChanged" Disabled="@(!FileLogEnabled)" Min="1" Max="365" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Value="FileLogAge" ValueChanged="FileLogAgeChanged" Disabled="@(!FileLogEnabled)" Min="1" Max="365" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="3">
|
<MudItem xs="3">
|
||||||
<MudSelect T="int" Value="FileLogAgeType" ValueChanged="FileLogAgeTypeChanged" Disabled="@(!FileLogEnabled)" Variant="Variant.Outlined">
|
<MudSelect T="int" Value="FileLogAgeType" ValueChanged="FileLogAgeTypeChanged" Disabled="@(!FileLogEnabled)" Variant="Variant.Outlined">
|
||||||
@@ -71,43 +71,4 @@
|
|||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
|
|
||||||
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
|
|
||||||
<MudCardHeader>
|
|
||||||
<CardHeaderContent>
|
|
||||||
<MudText Typo="Typo.subtitle2">Status Bar</MudText>
|
|
||||||
</CardHeaderContent>
|
|
||||||
</MudCardHeader>
|
|
||||||
<MudCardContent>
|
|
||||||
<MudGrid>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<FieldSwitch Label="Display current external IP address on status bar" Value="StatusBarExternalIp" ValueChanged="StatusBarExternalIpChanged" />
|
|
||||||
</MudItem>
|
|
||||||
</MudGrid>
|
|
||||||
</MudCardContent>
|
|
||||||
</MudCard>
|
|
||||||
|
|
||||||
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
|
|
||||||
<MudCardHeader>
|
|
||||||
<CardHeaderContent>
|
|
||||||
<MudText Typo="Typo.subtitle2">Confirmation</MudText>
|
|
||||||
</CardHeaderContent>
|
|
||||||
</MudCardHeader>
|
|
||||||
<MudCardContent>
|
|
||||||
<MudGrid>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<FieldSwitch Label="Confirm when deleting torrents" Value="ConfirmTorrentDeletion" ValueChanged="ConfirmTorrentDeletionChanged" />
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<FieldSwitch Label="Confirm when rechecking torrents" Value="ConfirmTorrentRecheck" ValueChanged="ConfirmTorrentRecheckChanged" />
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<FieldSwitch Label="Also delete torrent content when deleting torrents" Value="DeleteTorrentContentFiles" ValueChanged="DeleteTorrentContentFilesChanged" />
|
|
||||||
</MudItem>
|
|
||||||
</MudGrid>
|
|
||||||
</MudCardContent>
|
|
||||||
</MudCard>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -20,14 +20,6 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
|
|
||||||
protected bool PerformanceWarning { get; set; }
|
protected bool PerformanceWarning { get; set; }
|
||||||
|
|
||||||
protected bool StatusBarExternalIp { get; set; }
|
|
||||||
|
|
||||||
protected bool ConfirmTorrentDeletion { get; set; }
|
|
||||||
|
|
||||||
protected bool ConfirmTorrentRecheck { get; set; }
|
|
||||||
|
|
||||||
protected bool DeleteTorrentContentFiles { get; set; }
|
|
||||||
|
|
||||||
protected override bool SetOptions()
|
protected override bool SetOptions()
|
||||||
{
|
{
|
||||||
if (Preferences is null)
|
if (Preferences is null)
|
||||||
@@ -43,10 +35,6 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
FileLogAge = Preferences.FileLogAge;
|
FileLogAge = Preferences.FileLogAge;
|
||||||
FileLogAgeType = Preferences.FileLogAgeType;
|
FileLogAgeType = Preferences.FileLogAgeType;
|
||||||
PerformanceWarning = Preferences.PerformanceWarning;
|
PerformanceWarning = Preferences.PerformanceWarning;
|
||||||
StatusBarExternalIp = Preferences.StatusBarExternalIp;
|
|
||||||
ConfirmTorrentDeletion = Preferences.ConfirmTorrentDeletion;
|
|
||||||
ConfirmTorrentRecheck = Preferences.ConfirmTorrentRecheck;
|
|
||||||
DeleteTorrentContentFiles = Preferences.DeleteTorrentContentFiles;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -107,33 +95,5 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
UpdatePreferences.PerformanceWarning = value;
|
UpdatePreferences.PerformanceWarning = value;
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task StatusBarExternalIpChanged(bool value)
|
|
||||||
{
|
|
||||||
StatusBarExternalIp = value;
|
|
||||||
UpdatePreferences.StatusBarExternalIp = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task ConfirmTorrentDeletionChanged(bool value)
|
|
||||||
{
|
|
||||||
ConfirmTorrentDeletion = value;
|
|
||||||
UpdatePreferences.ConfirmTorrentDeletion = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task ConfirmTorrentRecheckChanged(bool value)
|
|
||||||
{
|
|
||||||
ConfirmTorrentRecheck = value;
|
|
||||||
UpdatePreferences.ConfirmTorrentRecheck = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task DeleteTorrentContentFilesChanged(bool value)
|
|
||||||
{
|
|
||||||
DeleteTorrentContentFiles = value;
|
|
||||||
UpdatePreferences.DeleteTorrentContentFiles = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@inherits Options
|
@inherits Options
|
||||||
|
|
||||||
<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>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
<MudCardContent Class="pt-0">
|
<MudCardContent Class="pt-0">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Max active checking torrents" Value="MaxActiveCheckingTorrents" ValueChanged="MaxActiveCheckingTorrentsChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Max active checking torrents" Value="MaxActiveCheckingTorrents" ValueChanged="MaxActiveCheckingTorrentsChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -56,28 +56,25 @@
|
|||||||
<FieldSwitch Label="Queueing enabled" Value="QueueingEnabled" ValueChanged="QueueingEnabledChanged" />
|
<FieldSwitch Label="Queueing enabled" Value="QueueingEnabled" ValueChanged="QueueingEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Maximum active downloads" Value="MaxActiveDownloads" ValueChanged="MaxActiveDownloadsChanged" Min="-1" Disabled="@(!QueueingEnabled)" Variant="Variant.Outlined" Validation="MaxActiveDownloadsValidation" />
|
<MudNumericField T="int" Label="Maximum active downloads" Value="MaxActiveDownloads" ValueChanged="MaxActiveDownloadsChanged" Min="-1" Disabled="@(!QueueingEnabled)" Variant="Variant.Outlined" Validation="MaxActiveDownloadsValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Maximum active uploads" Value="MaxActiveUploads" ValueChanged="MaxActiveUploadsChanged" Min="-1" Disabled="@(!QueueingEnabled)" Variant="Variant.Outlined" Validation="MaxActiveUploadsValidation" />
|
<MudNumericField T="int" Label="Maximum active uploads" Value="MaxActiveUploads" ValueChanged="MaxActiveUploadsChanged" Min="-1" Disabled="@(!QueueingEnabled)" Variant="Variant.Outlined" Validation="MaxActiveUploadsValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Maximum active torrents" Value="MaxActiveTorrents" ValueChanged="MaxActiveTorrentsChanged" Min="-1" Disabled="@(!QueueingEnabled)" Variant="Variant.Outlined" Validation="MaxActiveTorrentsValidation" />
|
<MudNumericField T="int" Label="Maximum active torrents" Value="MaxActiveTorrents" ValueChanged="MaxActiveTorrentsChanged" Min="-1" Disabled="@(!QueueingEnabled)" Variant="Variant.Outlined" Validation="MaxActiveTorrentsValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Do not count slow torrents in these limits" Value="DontCountSlowTorrents" ValueChanged="DontCountSlowTorrentsChanged" Disabled="@(!QueueingEnabled)" />
|
<FieldSwitch Label="Do not count slow torrents in these limits" Value="DontCountSlowTorrents" ValueChanged="DontCountSlowTorrentsChanged" Disabled="@(!QueueingEnabled)" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Merge trackers from different torrents" Value="MergeTrackers" ValueChanged="MergeTrackersChanged" />
|
<MudNumericField T="int" Label="Download rate threshold" Value="SlowTorrentDlRateThreshold" ValueChanged="SlowTorrentDlRateThresholdChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" Validation="SlowTorrentDlRateThresholdValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Download rate threshold" Value="SlowTorrentDlRateThreshold" ValueChanged="SlowTorrentDlRateThresholdChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" Validation="SlowTorrentDlRateThresholdValidation" />
|
<MudNumericField T="int" Label="Upload rate threshold" Value="SlowTorrentUlRateThreshold" ValueChanged="SlowTorrentUlRateThresholdChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" Validation="SlowTorrentUlRateThresholdValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Upload rate threshold" Value="SlowTorrentUlRateThreshold" ValueChanged="SlowTorrentUlRateThresholdChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" Validation="SlowTorrentUlRateThresholdValidation" />
|
<MudNumericField T="int" Label="Torrent inactivity timer" Value="SlowTorrentInactiveTimer" ValueChanged="SlowTorrentInactiveTimerChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" Validation="SlowTorrentInactiveTimerValidation" />
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Torrent inactivity timer" Value="SlowTorrentInactiveTimer" ValueChanged="SlowTorrentInactiveTimerChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="s" Validation="SlowTorrentInactiveTimerValidation" />
|
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -95,7 +92,7 @@
|
|||||||
<FieldSwitch Label="When ratio reaches" Value="MaxRatioEnabled" ValueChanged="MaxRatioEnabledChanged" />
|
<FieldSwitch Label="When ratio reaches" Value="MaxRatioEnabled" ValueChanged="MaxRatioEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="9">
|
<MudItem xs="9">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="float" Label="" Value="MaxRatio" ValueChanged="MaxRatioChanged"
|
<MudNumericField T="float" Label="" Value="MaxRatio" ValueChanged="MaxRatioChanged"
|
||||||
Disabled="@(!MaxRatioEnabled)" Min="0" Max="9998" Variant="Variant.Outlined"
|
Disabled="@(!MaxRatioEnabled)" Min="0" Max="9998" Variant="Variant.Outlined"
|
||||||
Validation="MaxRatioValidation" />
|
Validation="MaxRatioValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
@@ -103,13 +100,13 @@
|
|||||||
<FieldSwitch Label="When total seeding time reaches" Value="MaxSeedingTimeEnabled" ValueChanged="MaxSeedingTimeEnabledChanged" />
|
<FieldSwitch Label="When total seeding time reaches" Value="MaxSeedingTimeEnabled" ValueChanged="MaxSeedingTimeEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="9">
|
<MudItem xs="9">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="minutes" Value="MaxSeedingTime" ValueChanged="MaxSeedingTimeChanged" Disabled="@(!MaxSeedingTimeEnabled)" Min="0" Max="525600" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="minutes" Validation="MaxSeedingTimeValidation" />
|
<MudNumericField T="int" Label="minutes" Value="MaxSeedingTime" ValueChanged="MaxSeedingTimeChanged" Disabled="@(!MaxSeedingTimeEnabled)" Min="0" Max="525600" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="minutes" Validation="MaxSeedingTimeValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="3">
|
<MudItem xs="3">
|
||||||
<FieldSwitch Label="When inactive seeding time reaches" Value="MaxInactiveSeedingTimeEnabled" ValueChanged="MaxInactiveSeedingTimeEnabledChanged" />
|
<FieldSwitch Label="When inactive seeding time reaches" Value="MaxInactiveSeedingTimeEnabled" ValueChanged="MaxInactiveSeedingTimeEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="9">
|
<MudItem xs="9">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="minutes" Value="MaxInactiveSeedingTime" ValueChanged="MaxInactiveSeedingTimeChanged" Disabled="@(!MaxInactiveSeedingTimeEnabled)" Min="0" Max="525600" Variant="Variant.Outlined" Validation="MaxInactiveSeedingTimeValidation" />
|
<MudNumericField T="int" Label="minutes" Value="MaxInactiveSeedingTime" ValueChanged="MaxInactiveSeedingTimeChanged" Disabled="@(!MaxInactiveSeedingTimeEnabled)" Min="0" Max="525600" Variant="Variant.Outlined" Validation="MaxInactiveSeedingTimeValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudSelect T="int" Value="MaxRatioAct" ValueChanged="MaxRatioActChanged" Disabled="@(!MaxRatioEnabled && !MaxSeedingTimeEnabled && !MaxInactiveSeedingTimeEnabled)" Variant="Variant.Outlined">
|
<MudSelect T="int" Value="MaxRatioAct" ValueChanged="MaxRatioActChanged" Disabled="@(!MaxRatioEnabled && !MaxSeedingTimeEnabled && !MaxInactiveSeedingTimeEnabled)" Variant="Variant.Outlined">
|
||||||
@@ -126,29 +123,17 @@
|
|||||||
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
|
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
|
||||||
<MudCardHeader>
|
<MudCardHeader>
|
||||||
<CardHeaderContent>
|
<CardHeaderContent>
|
||||||
<MudText Typo="Typo.subtitle2">Trackers</MudText>
|
<MudText Typo="Typo.subtitle2">Seeding Limits</MudText>
|
||||||
</CardHeaderContent>
|
</CardHeaderContent>
|
||||||
</MudCardHeader>
|
</MudCardHeader>
|
||||||
<MudCardContent Class="pt-0">
|
<MudCardContent Class="pt-0">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Automatically add these trackers to new torrents" Value="AddTrackersEnabled" ValueChanged="AddTrackersEnabledChanged" />
|
<FieldSwitch Label="Automatically add these trackers to new downloads" Value="AddTrackersEnabled" ValueChanged="AddTrackersEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Trackers" Value="AddTrackers" ValueChanged="AddTrackersChanged" Lines="5" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Trackers" Value="AddTrackers" ValueChanged="AddTrackersChanged" Lines="5" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<FieldSwitch Label="Fetch additional trackers from URL" Value="AddTrackersFromUrlEnabled" ValueChanged="AddTrackersFromUrlEnabledChanged" />
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Trackers URL" Value="AddTrackersUrl" ValueChanged="AddTrackersUrlChanged" Disabled="@(!AddTrackersFromUrlEnabled)" Variant="Variant.Outlined" />
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12">
|
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Last fetched trackers" Value="AddTrackersUrlList" ValueChanged="AddTrackersUrlListChanged" Disabled="@(!AddTrackersFromUrlEnabled)" Lines="5" Variant="Variant.Outlined" />
|
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -25,10 +25,6 @@
|
|||||||
protected int MaxInactiveSeedingTime { get; private set; }
|
protected int MaxInactiveSeedingTime { get; private set; }
|
||||||
protected bool AddTrackersEnabled { get; private set; }
|
protected bool AddTrackersEnabled { get; private set; }
|
||||||
protected string? AddTrackers { get; private set; }
|
protected string? AddTrackers { get; private set; }
|
||||||
protected bool AddTrackersFromUrlEnabled { get; private set; }
|
|
||||||
protected string? AddTrackersUrl { get; private set; }
|
|
||||||
protected string? AddTrackersUrlList { get; private set; }
|
|
||||||
protected bool MergeTrackers { get; private set; }
|
|
||||||
|
|
||||||
protected Func<int, string?> MaxActiveDownloadsValidation = value =>
|
protected Func<int, string?> MaxActiveDownloadsValidation = value =>
|
||||||
{
|
{
|
||||||
@@ -170,10 +166,6 @@
|
|||||||
|
|
||||||
AddTrackersEnabled = Preferences.AddTrackersEnabled;
|
AddTrackersEnabled = Preferences.AddTrackersEnabled;
|
||||||
AddTrackers = Preferences.AddTrackers;
|
AddTrackers = Preferences.AddTrackers;
|
||||||
AddTrackersFromUrlEnabled = Preferences.AddTrackersFromUrlEnabled;
|
|
||||||
AddTrackersUrl = Preferences.AddTrackersUrl;
|
|
||||||
AddTrackersUrlList = Preferences.AddTrackersUrlList;
|
|
||||||
MergeTrackers = Preferences.MergeTrackers;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -338,33 +330,5 @@
|
|||||||
UpdatePreferences.AddTrackers = value;
|
UpdatePreferences.AddTrackers = value;
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task AddTrackersFromUrlEnabledChanged(bool value)
|
|
||||||
{
|
|
||||||
AddTrackersFromUrlEnabled = value;
|
|
||||||
UpdatePreferences.AddTrackersFromUrlEnabled = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task AddTrackersUrlChanged(string value)
|
|
||||||
{
|
|
||||||
AddTrackersUrl = value;
|
|
||||||
UpdatePreferences.AddTrackersUrl = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task AddTrackersUrlListChanged(string value)
|
|
||||||
{
|
|
||||||
AddTrackersUrlList = value;
|
|
||||||
UpdatePreferences.AddTrackersUrlList = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task MergeTrackersChanged(bool value)
|
|
||||||
{
|
|
||||||
MergeTrackers = value;
|
|
||||||
UpdatePreferences.MergeTrackers = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
@inherits Options
|
@inherits Options
|
||||||
|
|
||||||
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4 mt-4">
|
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4 mt-4">
|
||||||
<MudCardContent>
|
<MudCardContent>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudSelect T="int" Label="Peer connection protocol" Value="BittorrentProtocol" ValueChanged="BittorrentProtocolChanged" Variant="Variant.Outlined">
|
<MudSelect T="int" Label="Peer connection protocol" Value="BittorrentProtocol" ValueChanged="BittorrentProtocolChanged" Variant="Variant.Outlined">
|
||||||
<MudSelectItem T="int" Value="0">TCP and <EFBFBD>TP</MudSelectItem>
|
<MudSelectItem T="int" Value="0">TCP and μTP</MudSelectItem>
|
||||||
<MudSelectItem T="int" Value="1">TCP</MudSelectItem>
|
<MudSelectItem T="int" Value="1">TCP</MudSelectItem>
|
||||||
<MudSelectItem T="int" Value="2"><EFBFBD>TP</MudSelectItem>
|
<MudSelectItem T="int" Value="2">μTP</MudSelectItem>
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
<MudCardContent Class="pt-0">
|
<MudCardContent Class="pt-0">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Port used for incoming connections" Value="ListenPort" ValueChanged="ListenPortChanged" Min="@MinNonNegativePortValue" Max="@MaxPortValue" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentIcon="@CustomIcons.Random" OnAdornmentClick="GenerateRandomPort" HelperText="Set to 0 to let your system pick an unused port" Validation="PortNonNegativeValidation" />
|
<MudNumericField T="int" Label="Port used for incoming connections" Value="ListenPort" ValueChanged="ListenPortChanged" Min="@MinNonNegativePortValue" Max="@MaxPortValue" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentIcon="@CustomIcons.Random" OnAdornmentClick="GenerateRandomPort" HelperText="Set to 0 to let your system pick an unused port" Validation="PortNonNegativeValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Use UPnp / NAT-PMP port forwarding from my router" Value="Upnp" ValueChanged="UpnpChanged" />
|
<FieldSwitch Label="Use UPnp / NAT-PMP port forwarding from my router" Value="Upnp" ValueChanged="UpnpChanged" />
|
||||||
@@ -44,25 +44,25 @@
|
|||||||
<FieldSwitch Label="Global maximum number of connections" Value="MaxConnecEnabled" ValueChanged="MaxConnecEnabledChanged" />
|
<FieldSwitch Label="Global maximum number of connections" Value="MaxConnecEnabled" ValueChanged="MaxConnecEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Connections" Value="MaxConnec" ValueChanged="MaxConnecChanged" Min="0" Disabled="@(!MaxConnecEnabled)" Variant="Variant.Outlined" Validation="MaxConnectValidation" />
|
<MudNumericField T="int" Label="Connections" Value="MaxConnec" ValueChanged="MaxConnecChanged" Min="0" Disabled="@(!MaxConnecEnabled)" Variant="Variant.Outlined" Validation="MaxConnectValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<FieldSwitch Label="Maximum number of connections per torrent" Value="MaxConnecPerTorrentEnabled" ValueChanged="MaxConnecPerTorrentEnabledChanged" />
|
<FieldSwitch Label="Maximum number of connections per torrent" Value="MaxConnecPerTorrentEnabled" ValueChanged="MaxConnecPerTorrentEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Connections" Value="MaxConnecPerTorrent" ValueChanged="MaxConnecPerTorrentChanged" Min="0" Disabled="@(!MaxConnecPerTorrentEnabled)" Variant="Variant.Outlined" Validation="MaxConnecPerTorrentValidation" />
|
<MudNumericField T="int" Label="Connections" Value="MaxConnecPerTorrent" ValueChanged="MaxConnecPerTorrentChanged" Min="0" Disabled="@(!MaxConnecPerTorrentEnabled)" Variant="Variant.Outlined" Validation="MaxConnecPerTorrentValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<FieldSwitch Label="Global maximum number of upload slots" Value="MaxUploadsEnabled" ValueChanged="MaxUploadsEnabledChanged" />
|
<FieldSwitch Label="Global maximum number of upload slots" Value="MaxUploadsEnabled" ValueChanged="MaxUploadsEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Slots" Value="MaxUploads" ValueChanged="MaxUploadsChanged" Min="0" Disabled="@(!MaxUploadsEnabled)" Variant="Variant.Outlined" Validation="MaxUploadsValidation" />
|
<MudNumericField T="int" Label="Slots" Value="MaxUploads" ValueChanged="MaxUploadsChanged" Min="0" Disabled="@(!MaxUploadsEnabled)" Variant="Variant.Outlined" Validation="MaxUploadsValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<FieldSwitch Label="Maximum number of upload slots per torrent" Value="MaxUploadsPerTorrentEnabled" ValueChanged="MaxUploadsPerTorrentEnabledChanged" />
|
<FieldSwitch Label="Maximum number of upload slots per torrent" Value="MaxUploadsPerTorrentEnabled" ValueChanged="MaxUploadsPerTorrentEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Slots" Value="MaxUploadsPerTorrent" ValueChanged="MaxUploadsPerTorrentChanged" Min="0" Disabled="@(!MaxUploadsPerTorrentEnabled)" Variant="Variant.Outlined" Validation="MaxUploadsPerTorrentValidation" />
|
<MudNumericField T="int" Label="Slots" Value="MaxUploadsPerTorrent" ValueChanged="MaxUploadsPerTorrentChanged" Min="0" Disabled="@(!MaxUploadsPerTorrentEnabled)" Variant="Variant.Outlined" Validation="MaxUploadsPerTorrentValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -75,10 +75,10 @@
|
|||||||
<FieldSwitch Label="I2P (Experimental)" Value="I2pEnabled" ValueChanged="I2pEnabledChanged" />
|
<FieldSwitch Label="I2P (Experimental)" Value="I2pEnabled" ValueChanged="I2pEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Host" Value="I2pAddress" ValueChanged="I2pAddressChanged" Disabled="@(!I2pEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Host" Value="I2pAddress" ValueChanged="I2pAddressChanged" Disabled="@(!I2pEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Slots" Value="I2pPort" ValueChanged="I2pPortChanged" Min="0" Max="65535" Disabled="@(!I2pEnabled)" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Slots" Value="I2pPort" ValueChanged="I2pPortChanged" Min="0" Max="65535" Disabled="@(!I2pEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Mixed mode" Value="I2pMixedMode" ValueChanged="I2pMixedModeChanged" Disabled="@(!I2pEnabled)" HelperText="If "mixed mode" is enabled, I2P torrents are allowed to also get peers from other sources than the tracker, and connect to regular IPs, not providing any anonymization. This may be useful if the user is not interested in the anonymization of I2P, but still wants to be able to connect to I2P peers." />
|
<FieldSwitch Label="Mixed mode" Value="I2pMixedMode" ValueChanged="I2pMixedModeChanged" Disabled="@(!I2pEnabled)" HelperText="If "mixed mode" is enabled, I2P torrents are allowed to also get peers from other sources than the tracker, and connect to regular IPs, not providing any anonymization. This may be useful if the user is not interested in the anonymization of I2P, but still wants to be able to connect to I2P peers." />
|
||||||
@@ -104,10 +104,10 @@
|
|||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="4">
|
<MudItem xs="12" md="4">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Host" Value="ProxyIp" ValueChanged="ProxyIpChanged" Disabled="ProxyDisabled" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Host" Value="ProxyIp" ValueChanged="ProxyIpChanged" Disabled="ProxyDisabled" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="4">
|
<MudItem xs="12" md="4">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Port" Value="ProxyPort" ValueChanged="ProxyPortChanged" Min="1" Max="@ConnectionOptions.MaxPortValue" Disabled="ProxyDisabled" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Port" Value="ProxyPort" ValueChanged="ProxyPortChanged" Min="1" Max="@ConnectionOptions.MaxPortValue" Disabled="ProxyDisabled" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Perform hostname lookup via proxy" Value="ProxyHostnameLookup" ValueChanged="ProxyHostnameLookupChanged" HelperText="If checked, hostname lookups are done via the proxy." />
|
<FieldSwitch Label="Perform hostname lookup via proxy" Value="ProxyHostnameLookup" ValueChanged="ProxyHostnameLookupChanged" HelperText="If checked, hostname lookups are done via the proxy." />
|
||||||
@@ -116,10 +116,10 @@
|
|||||||
<FieldSwitch Label="Authentication" Value="ProxyAuthEnabled" ValueChanged="ProxyAuthEnabledChanged" Disabled="@(ProxyDisabled || ProxySocks4)" />
|
<FieldSwitch Label="Authentication" Value="ProxyAuthEnabled" ValueChanged="ProxyAuthEnabledChanged" Disabled="@(ProxyDisabled || ProxySocks4)" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Username" Value="ProxyUsername" ValueChanged="ProxyUsernameChanged" Disabled="@(ProxyDisabled || ProxySocks4)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Username" Value="ProxyUsername" ValueChanged="ProxyUsernameChanged" Disabled="@(ProxyDisabled || ProxySocks4)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Password" Value="ProxyPassword" ValueChanged="ProxyPasswordChanged" Disabled="@(ProxyDisabled || ProxySocks4)" Variant="Variant.Outlined " HelperText="Info: The password is saved unencrypted" />
|
<MudTextField T="string" Label="Password" Value="ProxyPassword" ValueChanged="ProxyPasswordChanged" Disabled="@(ProxyDisabled || ProxySocks4)" Variant="Variant.Outlined " HelperText="Info: The password is saved unencrypted" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
@@ -150,17 +150,14 @@
|
|||||||
<FieldSwitch Label="IP Filter" Value="IpFilterEnabled" ValueChanged="IpFilterEnabledChanged" />
|
<FieldSwitch Label="IP Filter" Value="IpFilterEnabled" ValueChanged="IpFilterEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Filter path (.dat, .p2p, .p2b)" Value="IpFilterPath" ValueChanged="IpFilterPathChanged" Disabled="@(!IpFilterEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Filter path (.dat, .p2p, .p2b)" Value="IpFilterPath" ValueChanged="IpFilterPathChanged" Disabled="@(!IpFilterEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Apply to trackers" Value="IpFilterTrackers" ValueChanged="IpFilterTrackersChanged" />
|
<FieldSwitch Label="Apply to trackers" Value="IpFilterTrackers" ValueChanged="IpFilterTrackersChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Manually banned IP addresses" Value="BannedIPs" ValueChanged="BannedIPsChanged" Lines="5" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Manually banned IP addresses" Value="BannedIPs" ValueChanged="BannedIPsChanged" Lines="5" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@inherits Options
|
@inherits Options
|
||||||
|
|
||||||
<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>
|
||||||
@@ -29,11 +29,7 @@
|
|||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudSelect T="int" Label="Delete .torrent files afterwards" Value="AutoDeleteMode" ValueChanged="AutoDeleteModeChanged" Variant="Variant.Outlined">
|
<FieldSwitch Label="Delete .torrent files afterwards" Value="AutoDeleteMode" ValueChanged="AutoDeleteModeChanged" />
|
||||||
<MudSelectItem Value="0">Never</MudSelectItem>
|
|
||||||
<MudSelectItem Value="1">If added successfully</MudSelectItem>
|
|
||||||
<MudSelectItem Value="2">Always</MudSelectItem>
|
|
||||||
</MudSelect>
|
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -93,7 +89,7 @@
|
|||||||
<FieldSwitch Label="Use Subcategories" Value="UseSubcategories" ValueChanged="UseSubcategoriesChanged" />
|
<FieldSwitch Label="Use Subcategories" Value="UseSubcategories" ValueChanged="UseSubcategoriesChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Default Save Path" Value="SavePath" ValueChanged="SavePathChanged" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Default Save Path" Value="SavePath" ValueChanged="SavePathChanged" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
@@ -101,7 +97,7 @@
|
|||||||
<FieldSwitch Label="Keep incomplete torrents in" Value="TempPathEnabled" ValueChanged="TempPathEnabledChanged" />
|
<FieldSwitch Label="Keep incomplete torrents in" Value="TempPathEnabled" ValueChanged="TempPathEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" sm="6" md="9">
|
<MudItem xs="12" sm="6" md="9">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Path" Value="TempPath" ValueChanged="TempPathChanged" Disabled="@(!TempPathEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Path" Value="TempPath" ValueChanged="TempPathChanged" Disabled="@(!TempPathEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
@@ -111,7 +107,7 @@
|
|||||||
<FieldSwitch Label="Copy .torrent files to" Value="ExportDirEnabled" ValueChanged="ExportDirEnabledChanged" />
|
<FieldSwitch Label="Copy .torrent files to" Value="ExportDirEnabled" ValueChanged="ExportDirEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" sm="6" md="9">
|
<MudItem xs="12" sm="6" md="9">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Path" Value="ExportDir" ValueChanged="ExportDirChanged" Disabled="@(!TempPathEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Path" Value="ExportDir" ValueChanged="ExportDirChanged" Disabled="@(!TempPathEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
@@ -121,7 +117,7 @@
|
|||||||
<FieldSwitch Label="Copy .torrent files for finished downloads to" Value="ExportDirFinEnabled" ValueChanged="ExportDirFinEnabledChanged" />
|
<FieldSwitch Label="Copy .torrent files for finished downloads to" Value="ExportDirFinEnabled" ValueChanged="ExportDirFinEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" sm="6" md="9">
|
<MudItem xs="12" sm="6" md="9">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Path" Value="ExportDirFin" ValueChanged="ExportDirFinChanged" Disabled="@(!TempPathEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Path" Value="ExportDirFin" ValueChanged="ExportDirFinChanged" Disabled="@(!TempPathEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
@@ -148,7 +144,7 @@
|
|||||||
{
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Path" Value="@item.Key" ValueChanged="@(v => ScanDirsKeyChanged(item.Key, v))" Validation="IsValidNewKey" />
|
<MudTextField T="string" Label="Path" Value="@item.Key" ValueChanged="@(v => ScanDirsKeyChanged(item.Key, v))" Validation="IsValidNewKey" />
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
@@ -162,7 +158,7 @@
|
|||||||
@if (item.Value.SavePath is not null)
|
@if (item.Value.SavePath is not null)
|
||||||
{
|
{
|
||||||
<MudItem xs="8">
|
<MudItem xs="8">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Path" Value="@item.Value.SavePath" ValueChanged="@(v => ScanDirsValueChanged(item.Key, v))" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Path" Value="@item.Value.SavePath" ValueChanged="@(v => ScanDirsValueChanged(item.Key, v))" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
}
|
}
|
||||||
<MudItem xs="1">
|
<MudItem xs="1">
|
||||||
@@ -181,7 +177,7 @@
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Path" Value="@item.Key" ValueChanged="@(v => AddedScanDirsKeyChanged(index, v))" Validation="IsValidNewKey" />
|
<MudTextField T="string" Label="Path" Value="@item.Key" ValueChanged="@(v => AddedScanDirsKeyChanged(index, v))" Validation="IsValidNewKey" />
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
@@ -195,7 +191,7 @@
|
|||||||
@if (item.Value.SavePath is not null)
|
@if (item.Value.SavePath is not null)
|
||||||
{
|
{
|
||||||
<MudItem xs="@(isLast ? 8 : 9)">
|
<MudItem xs="@(isLast ? 8 : 9)">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Path" Value="@item.Value.SavePath" ValueChanged="@(v => AddedScanDirsValueChanged(index, v))" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Path" Value="@item.Value.SavePath" ValueChanged="@(v => AddedScanDirsValueChanged(index, v))" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
}
|
}
|
||||||
<MudItem xs="1">
|
<MudItem xs="1">
|
||||||
@@ -229,7 +225,7 @@
|
|||||||
<FieldSwitch Label="Excluded file names" Value="ExcludedFileNamesEnabled" ValueChanged="ExcludedFileNamesEnabledChanged" />
|
<FieldSwitch Label="Excluded file names" Value="ExcludedFileNamesEnabled" ValueChanged="ExcludedFileNamesEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Excluded files names" Value="ExcludedFileNames" ValueChanged="ExcludedFileNamesChanged" Lines="5" Disabled="@(!ExcludedFileNamesEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Excluded files names" Value="ExcludedFileNames" ValueChanged="ExcludedFileNamesChanged" Lines="5" Disabled="@(!ExcludedFileNamesEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -247,13 +243,13 @@
|
|||||||
<FieldSwitch Label="Email notification upon download completion" Value="MailNotificationEnabled" ValueChanged="MailNotificationEnabledChanged" />
|
<FieldSwitch Label="Email notification upon download completion" Value="MailNotificationEnabled" ValueChanged="MailNotificationEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="From" Value="MailNotificationSender" ValueChanged="MailNotificationSenderChanged" Disabled="@(!MailNotificationEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="From" Value="MailNotificationSender" ValueChanged="MailNotificationSenderChanged" Disabled="@(!MailNotificationEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="To" Value="MailNotificationEmail" ValueChanged="MailNotificationEmailChanged" Disabled="@(!MailNotificationEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="To" Value="MailNotificationEmail" ValueChanged="MailNotificationEmailChanged" Disabled="@(!MailNotificationEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="SMTP server" Value="MailNotificationSmtp" ValueChanged="MailNotificationSmtpChanged" Disabled="@(!MailNotificationEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="SMTP server" Value="MailNotificationSmtp" ValueChanged="MailNotificationSmtpChanged" Disabled="@(!MailNotificationEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="This server requires a secure connection (SSL)" Value="MailNotificationSslEnabled" ValueChanged="MailNotificationSslEnabledChanged" Disabled="@(!MailNotificationEnabled)" />
|
<FieldSwitch Label="This server requires a secure connection (SSL)" Value="MailNotificationSslEnabled" ValueChanged="MailNotificationSslEnabledChanged" Disabled="@(!MailNotificationEnabled)" />
|
||||||
@@ -262,10 +258,10 @@
|
|||||||
<FieldSwitch Label="Authentication" Value="MailNotificationAuthEnabled" ValueChanged="MailNotificationAuthEnabledChanged" Disabled="@(!MailNotificationEnabled)" />
|
<FieldSwitch Label="Authentication" Value="MailNotificationAuthEnabled" ValueChanged="MailNotificationAuthEnabledChanged" Disabled="@(!MailNotificationEnabled)" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Username" Value="MailNotificationUsername" ValueChanged="MailNotificationUsernameChanged" Disabled="@(!(MailNotificationEnabled && MailNotificationAuthEnabled))" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Username" Value="MailNotificationUsername" ValueChanged="MailNotificationUsernameChanged" Disabled="@(!(MailNotificationEnabled && MailNotificationAuthEnabled))" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Password" Value="MailNotificationPassword" ValueChanged="MailNotificationPasswordChanged" Disabled="@(!(MailNotificationEnabled && MailNotificationAuthEnabled))" InputType="InputType.Password" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Password" Value="MailNotificationPassword" ValueChanged="MailNotificationPasswordChanged" Disabled="@(!(MailNotificationEnabled && MailNotificationAuthEnabled))" InputType="InputType.Password" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -283,13 +279,13 @@
|
|||||||
<FieldSwitch Label="Run external program on torrent added" Value="AutorunOnTorrentAddedEnabled" ValueChanged="AutorunOnTorrentAddedEnabledChanged" />
|
<FieldSwitch Label="Run external program on torrent added" Value="AutorunOnTorrentAddedEnabled" ValueChanged="AutorunOnTorrentAddedEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="External program" Value="AutorunOnTorrentAddedProgram" ValueChanged="AutorunOnTorrentAddedProgramChanged" Disabled="@(!AutorunOnTorrentAddedEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="External program" Value="AutorunOnTorrentAddedProgram" ValueChanged="AutorunOnTorrentAddedProgramChanged" Disabled="@(!AutorunOnTorrentAddedEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Run external program on torrent finished" Value="AutorunEnabled" ValueChanged="AutorunEnabledChanged" />
|
<FieldSwitch Label="Run external program on torrent finished" Value="AutorunEnabled" ValueChanged="AutorunEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="External program" Value="AutorunProgram" ValueChanged="AutorunProgramChanged" Disabled="@(!AutorunEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="External program" Value="AutorunProgram" ValueChanged="AutorunProgramChanged" Disabled="@(!AutorunEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudText>Supported parameters (case sensitive):</MudText>
|
<MudText>Supported parameters (case sensitive):</MudText>
|
||||||
@@ -310,7 +306,4 @@
|
|||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
protected bool AddToTopOfQueue { get; set; }
|
protected bool AddToTopOfQueue { get; set; }
|
||||||
protected bool StartPausedEnabled { get; set; }
|
protected bool StartPausedEnabled { get; set; }
|
||||||
protected string? TorrentStopCondition { get; set; }
|
protected string? TorrentStopCondition { get; set; }
|
||||||
protected int AutoDeleteMode { get; set; }
|
protected bool AutoDeleteMode { get; set; }
|
||||||
protected bool PreallocateAll { get; set; }
|
protected bool PreallocateAll { get; set; }
|
||||||
protected bool IncompleteFilesExt { get; set; }
|
protected bool IncompleteFilesExt { get; set; }
|
||||||
protected bool AutoTmmEnabled { get; set; }
|
protected bool AutoTmmEnabled { get; set; }
|
||||||
@@ -51,9 +51,9 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
// when adding a torrent
|
// when adding a torrent
|
||||||
TorrentContentLayout = Preferences.TorrentContentLayout;
|
TorrentContentLayout = Preferences.TorrentContentLayout;
|
||||||
AddToTopOfQueue = Preferences.AddToTopOfQueue;
|
AddToTopOfQueue = Preferences.AddToTopOfQueue;
|
||||||
StartPausedEnabled = Preferences.AddStoppedEnabled || Preferences.StartPausedEnabled;
|
StartPausedEnabled = Preferences.StartPausedEnabled;
|
||||||
TorrentStopCondition = Preferences.TorrentStopCondition;
|
TorrentStopCondition = Preferences.TorrentStopCondition;
|
||||||
AutoDeleteMode = Preferences.AutoDeleteMode is >= 0 and <= 2 ? Preferences.AutoDeleteMode : 0;
|
AutoDeleteMode = Preferences.AutoDeleteMode == 1;
|
||||||
PreallocateAll = Preferences.PreallocateAll;
|
PreallocateAll = Preferences.PreallocateAll;
|
||||||
IncompleteFilesExt = Preferences.IncompleteFilesExt;
|
IncompleteFilesExt = Preferences.IncompleteFilesExt;
|
||||||
|
|
||||||
@@ -120,7 +120,6 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
{
|
{
|
||||||
StartPausedEnabled = value;
|
StartPausedEnabled = value;
|
||||||
UpdatePreferences.StartPausedEnabled = value;
|
UpdatePreferences.StartPausedEnabled = value;
|
||||||
UpdatePreferences.AddStoppedEnabled = value;
|
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,10 +130,10 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task AutoDeleteModeChanged(int value)
|
protected async Task AutoDeleteModeChanged(bool value)
|
||||||
{
|
{
|
||||||
AutoDeleteMode = value;
|
AutoDeleteMode = value;
|
||||||
UpdatePreferences.AutoDeleteMode = value;
|
UpdatePreferences.AutoDeleteMode = value ? 1 : 0;
|
||||||
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
await PreferencesChanged.InvokeAsync(UpdatePreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,4 +410,4 @@ namespace Lantean.QBTMud.Components.Options
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@inherits Options
|
@inherits Options
|
||||||
|
|
||||||
<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>
|
||||||
@@ -12,10 +12,10 @@
|
|||||||
<FieldSwitch Label="Enable fetching RSS feeds" Value="RssProcessingEnabled" ValueChanged="RssProcessingEnabledChanged" />
|
<FieldSwitch Label="Enable fetching RSS feeds" Value="RssProcessingEnabled" ValueChanged="RssProcessingEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Feeds refresh interval" Value="RssRefreshInterval" ValueChanged="RssRefreshIntervalChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="min" />
|
<MudNumericField T="int" Label="Feeds refresh interval" Value="RssRefreshInterval" ValueChanged="RssRefreshIntervalChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="min" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Maximum number of articles per feed" Value="RssMaxArticlesPerFeed" ValueChanged="RssMaxArticlesPerFeedChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Maximum number of articles per feed" Value="RssMaxArticlesPerFeed" ValueChanged="RssMaxArticlesPerFeedChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -51,11 +51,8 @@
|
|||||||
<FieldSwitch Label="Download REPACK/PROPER episodes" Value="RssDownloadRepackProperEpisodes" ValueChanged="RssDownloadRepackProperEpisodesChanged" />
|
<FieldSwitch Label="Download REPACK/PROPER episodes" Value="RssDownloadRepackProperEpisodes" ValueChanged="RssDownloadRepackProperEpisodesChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Filters" Value="RssSmartEpisodeFilters" ValueChanged="RssSmartEpisodeFiltersChanged" Lines="5" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Filters" Value="RssSmartEpisodeFilters" ValueChanged="RssSmartEpisodeFiltersChanged" Lines="5" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@inherits Options
|
@inherits Options
|
||||||
|
|
||||||
<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>
|
||||||
@@ -9,10 +9,10 @@
|
|||||||
<MudCardContent Class="pt-0">
|
<MudCardContent Class="pt-0">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Upload" Value="UpLimit" ValueChanged="UpLimitChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" HelperText="0 means unlimited" Validation="UpLimitValidation" />
|
<MudNumericField T="int" Label="Upload" Value="UpLimit" ValueChanged="UpLimitChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" HelperText="0 means unlimited" Validation="UpLimitValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Download" Value="DlLimit" ValueChanged="DlLimitChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" HelperText="0 means unlimited" Validation="DlLimitValidation" />
|
<MudNumericField T="int" Label="Download" Value="DlLimit" ValueChanged="DlLimitChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" HelperText="0 means unlimited" Validation="DlLimitValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -27,10 +27,10 @@
|
|||||||
<MudCardContent Class="pt-0">
|
<MudCardContent Class="pt-0">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Upload" Value="AltUpLimit" ValueChanged="AltUpLimitChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" HelperText="0 means unlimited" Validation="AltUpLimitValidation" />
|
<MudNumericField T="int" Label="Upload" Value="AltUpLimit" ValueChanged="AltUpLimitChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" HelperText="0 means unlimited" Validation="AltUpLimitValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Download" Value="AltDlLimit" ValueChanged="AltDlLimitChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" HelperText="0 means unlimited" Validation="AltDlLimitValidation" />
|
<MudNumericField T="int" Label="Download" Value="AltDlLimit" ValueChanged="AltDlLimitChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="KiB/s" HelperText="0 means unlimited" Validation="AltDlLimitValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Schedule the use of alternative rate limits" Value="SchedulerEnabled" ValueChanged="SchedulerEnabledChanged" />
|
<FieldSwitch Label="Schedule the use of alternative rate limits" Value="SchedulerEnabled" ValueChanged="SchedulerEnabledChanged" />
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
<MudCardContent Class="pt-0">
|
<MudCardContent Class="pt-0">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Apply rate limit to <EFBFBD>TP protocol" Value="LimitUtpRate" ValueChanged="LimitUtpRateChanged" />
|
<FieldSwitch Label="Apply rate limit to µTP protocol" Value="LimitUtpRate" ValueChanged="LimitUtpRateChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Apply rate limit to transport overhead" Value="LimitTcpOverhead" ValueChanged="LimitTcpOverheadChanged" />
|
<FieldSwitch Label="Apply rate limit to transport overhead" Value="LimitTcpOverhead" ValueChanged="LimitTcpOverheadChanged" />
|
||||||
@@ -78,6 +78,4 @@
|
|||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@inherits Options
|
@inherits Options
|
||||||
|
|
||||||
<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>
|
||||||
@@ -9,10 +9,10 @@
|
|||||||
<MudCardContent Class="pt-0">
|
<MudCardContent Class="pt-0">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12" md="8">
|
<MudItem xs="12" md="8">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Host" Value="WebUiAddress" ValueChanged="WebUiAddressChanged" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Host" Value="WebUiAddress" ValueChanged="WebUiAddressChanged" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="4">
|
<MudItem xs="12" md="4">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Port" Value="WebUiPort" ValueChanged="WebUiPortChanged" Min="1" Max="@Options.MaxPortValue" Variant="Variant.Outlined" Validation="WebUiPortValidation" />
|
<MudNumericField T="int" Label="Port" Value="WebUiPort" ValueChanged="WebUiPortChanged" Min="1" Max="@Options.MaxPortValue" Variant="Variant.Outlined" Validation="WebUiPortValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Use UPnP / NAT-PMP to forward the port from my router" Value="WebUiUpnp" ValueChanged="WebUiUpnpChanged" />
|
<FieldSwitch Label="Use UPnP / NAT-PMP to forward the port from my router" Value="WebUiUpnp" ValueChanged="WebUiUpnpChanged" />
|
||||||
@@ -33,10 +33,10 @@
|
|||||||
<FieldSwitch Label="Use HTTPS instead of HTTP" Value="UseHttps" ValueChanged="UseHttpsChanged" />
|
<FieldSwitch Label="Use HTTPS instead of HTTP" Value="UseHttps" ValueChanged="UseHttpsChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Certificate" Value="WebUiHttpsCertPath" ValueChanged="WebUiHttpsCertPathChanged" Disabled="@(!UseHttps)" Variant="Variant.Outlined" Validation="WebUiHttpsCertPathValidation" />
|
<MudTextField T="string" Label="Certificate" Value="WebUiHttpsCertPath" ValueChanged="WebUiHttpsCertPathChanged" Disabled="@(!UseHttps)" Variant="Variant.Outlined" Validation="WebUiHttpsCertPathValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Key" Value="WebUiHttpsKeyPath" ValueChanged="WebUiHttpsKeyPathChanged" Disabled="@(!UseHttps)" Variant="Variant.Outlined" Validation="WebUiHttpsKeyPathValidation" />
|
<MudTextField T="string" Label="Key" Value="WebUiHttpsKeyPath" ValueChanged="WebUiHttpsKeyPathChanged" Disabled="@(!UseHttps)" Variant="Variant.Outlined" Validation="WebUiHttpsKeyPathValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -51,10 +51,10 @@
|
|||||||
<MudCardContent Class="pt-0">
|
<MudCardContent Class="pt-0">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Username" Value="WebUiUsername" ValueChanged="WebUiUsernameChanged" Variant="Variant.Outlined" Validation="WebUiUsernameValidation" />
|
<MudTextField T="string" Label="Username" Value="WebUiUsername" ValueChanged="WebUiUsernameChanged" Variant="Variant.Outlined" Validation="WebUiUsernameValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Password" Value="WebUiPassword" ValueChanged="WebUiPasswordChanged" InputType="InputType.Password" Variant="Variant.Outlined" Validation="WebUiPasswordValidation" />
|
<MudTextField T="string" Label="Password" Value="WebUiPassword" ValueChanged="WebUiPasswordChanged" InputType="InputType.Password" Variant="Variant.Outlined" Validation="WebUiPasswordValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<FieldSwitch Label="Bypass authentication for clients on localhost" Value="BypassLocalAuth" ValueChanged="BypassLocalAuthChanged" />
|
<FieldSwitch Label="Bypass authentication for clients on localhost" Value="BypassLocalAuth" ValueChanged="BypassLocalAuthChanged" />
|
||||||
@@ -63,16 +63,16 @@
|
|||||||
<FieldSwitch Label="Bypass authentication for clients in whitelisted IP subnets" Value="BypassAuthSubnetWhitelistEnabled" ValueChanged="BypassAuthSubnetWhitelistEnabledChanged" />
|
<FieldSwitch Label="Bypass authentication for clients in whitelisted IP subnets" Value="BypassAuthSubnetWhitelistEnabled" ValueChanged="BypassAuthSubnetWhitelistEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Trackers" Value="BypassAuthSubnetWhitelist" ValueChanged="BypassAuthSubnetWhitelistChanged" Lines="5" Disabled="@(!BypassAuthSubnetWhitelistEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Trackers" Value="BypassAuthSubnetWhitelist" ValueChanged="BypassAuthSubnetWhitelistChanged" Lines="5" Disabled="@(!BypassAuthSubnetWhitelistEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Ban client after consecutive failures" Value="WebUiMaxAuthFailCount" ValueChanged="WebUiMaxAuthFailCountChanged" Min="0" Variant="Variant.Outlined" />
|
<MudNumericField T="int" Label="Ban client after consecutive failures" Value="WebUiMaxAuthFailCount" ValueChanged="WebUiMaxAuthFailCountChanged" Min="0" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="ban for" Value="WebUiBanDuration" ValueChanged="WebUiBanDurationChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="seconds" />
|
<MudNumericField T="int" Label="ban for" Value="WebUiBanDuration" ValueChanged="WebUiBanDurationChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="seconds" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudNumericField Immediate="true" DebounceInterval="250" T="int" Label="Session timeout" Value="WebUiSessionTimeout" ValueChanged="WebUiSessionTimeoutChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="seconds" />
|
<MudNumericField T="int" Label="Session timeout" Value="WebUiSessionTimeout" ValueChanged="WebUiSessionTimeoutChanged" Min="0" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="seconds" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
<FieldSwitch Label="Use alternative Web UI" Value="AlternativeWebuiEnabled" ValueChanged="AlternativeWebuiEnabledChanged" />
|
<FieldSwitch Label="Use alternative Web UI" Value="AlternativeWebuiEnabled" ValueChanged="AlternativeWebuiEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Files location" Value="AlternativeWebuiPath" ValueChanged="AlternativeWebuiPathChanged" Variant="Variant.Outlined" Validation="AlternativeWebuiPathValidation" />
|
<MudTextField T="string" Label="Files location" Value="AlternativeWebuiPath" ValueChanged="AlternativeWebuiPathChanged" Variant="Variant.Outlined" Validation="AlternativeWebuiPathValidation" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
<FieldSwitch Label="Enable Host header validation" Value="WebUiHostHeaderValidationEnabled" ValueChanged="WebUiHostHeaderValidationEnabledChanged" />
|
<FieldSwitch Label="Enable Host header validation" Value="WebUiHostHeaderValidationEnabled" ValueChanged="WebUiHostHeaderValidationEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Server domains" Value="WebUiDomainList" ValueChanged="WebUiDomainListChanged" Lines="5" Disabled="@(!WebUiHostHeaderValidationEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Server domains" Value="WebUiDomainList" ValueChanged="WebUiDomainListChanged" Lines="5" Disabled="@(!WebUiHostHeaderValidationEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
<FieldSwitch Label="Enable Host header validation" Value="WebUiHostHeaderValidationEnabled" ValueChanged="WebUiHostHeaderValidationEnabledChanged" />
|
<FieldSwitch Label="Enable Host header validation" Value="WebUiHostHeaderValidationEnabled" ValueChanged="WebUiHostHeaderValidationEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Server domains" Value="WebUiDomainList" ValueChanged="WebUiDomainListChanged" Lines="5" Disabled="@(!WebUiHostHeaderValidationEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Server domains" Value="WebUiDomainList" ValueChanged="WebUiDomainListChanged" Lines="5" Disabled="@(!WebUiHostHeaderValidationEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -162,7 +162,7 @@
|
|||||||
<FieldSwitch Label="Add custom HTTP headers" Value="WebUiUseCustomHttpHeadersEnabled" ValueChanged="WebUiUseCustomHttpHeadersEnabledChanged" />
|
<FieldSwitch Label="Add custom HTTP headers" Value="WebUiUseCustomHttpHeadersEnabled" ValueChanged="WebUiUseCustomHttpHeadersEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Server domains" Value="WebUiCustomHttpHeaders" ValueChanged="WebUiCustomHttpHeadersChanged" Lines="5" Disabled="@(!WebUiUseCustomHttpHeadersEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Server domains" Value="WebUiCustomHttpHeaders" ValueChanged="WebUiCustomHttpHeadersChanged" Lines="5" Disabled="@(!WebUiUseCustomHttpHeadersEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -180,7 +180,7 @@
|
|||||||
<FieldSwitch Label="Enable reverse proxy support" Value="WebUiReverseProxyEnabled" ValueChanged="WebUiReverseProxyEnabledChanged" />
|
<FieldSwitch Label="Enable reverse proxy support" Value="WebUiReverseProxyEnabled" ValueChanged="WebUiReverseProxyEnabledChanged" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Trusted proxies list" Value="WebUiReverseProxiesList" ValueChanged="WebUiReverseProxiesListChanged" Lines="5" Disabled="@(!WebUiReverseProxyEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Trusted proxies list" Value="WebUiReverseProxiesList" ValueChanged="WebUiReverseProxiesListChanged" Lines="5" Disabled="@(!WebUiReverseProxyEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
@@ -207,17 +207,14 @@
|
|||||||
<MudButton OnClick="RegisterDyndnsService" Disabled="@(!DyndnsEnabled)" Variant="Variant.Filled">Register</MudButton>
|
<MudButton OnClick="RegisterDyndnsService" Disabled="@(!DyndnsEnabled)" Variant="Variant.Filled">Register</MudButton>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Domain name" Value="DyndnsDomain" ValueChanged="DyndnsDomainChanged" Disabled="@(!DyndnsEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Domain name" Value="DyndnsDomain" ValueChanged="DyndnsDomainChanged" Disabled="@(!DyndnsEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Username" Value="DyndnsUsername" ValueChanged="DyndnsUsernameChanged" Disabled="@(!DyndnsEnabled)" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Username" Value="DyndnsUsername" ValueChanged="DyndnsUsernameChanged" Disabled="@(!DyndnsEnabled)" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudTextField Immediate="true" DebounceInterval="250" T="string" Label="Password" Value="DyndnsPassword" ValueChanged="DyndnsPasswordChanged" Disabled="@(!DyndnsEnabled)" InputType="InputType.Password" Variant="Variant.Outlined" />
|
<MudTextField T="string" Label="Password" Value="DyndnsPassword" ValueChanged="DyndnsPasswordChanged" Disabled="@(!DyndnsEnabled)" InputType="InputType.Password" Variant="Variant.Outlined" />
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,24 +1,30 @@
|
|||||||
<ContextMenu @ref="ContextMenu" Dense="true">
|
<MudMenu @ref="ContextMenu" Dense="true" PositionAtCursor="true" ListClass="unselectable" PopoverClass="unselectable">
|
||||||
<MudMenuItem Icon="@Icons.Material.Filled.AddCircle" IconColor="Color.Info" OnClick="AddPeer">Add peer</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Filled.AddCircle" IconColor="Color.Info" OnClick="AddPeer">Add peer</MudMenuItem>
|
||||||
@if (ContextMenuItem is not null)
|
@if (ContextMenuItem is not null)
|
||||||
{
|
{
|
||||||
<MudMenuItem Icon="@Icons.Material.Filled.DisabledByDefault" IconColor="Color.Info" OnClick="BanPeerContextMenu">Ban peer</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Filled.DisabledByDefault" IconColor="Color.Info" OnClick="BanPeerContextMenu">Ban peer</MudMenuItem>
|
||||||
}
|
}
|
||||||
</ContextMenu>
|
</MudMenu>
|
||||||
|
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.AddCircle" Color="Color.Info" OnClick="AddPeer">Add peer</MudIconButton>
|
<div class="content-panel__toolbar">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.DisabledByDefault" Color="Color.Error" OnClick="BanPeerToolbar" Disabled="@(SelectedItem is null)">Ban peer</MudIconButton>
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudDivider Vertical="true" />
|
<MudIconButton Icon="@Icons.Material.Filled.AddCircle" Color="Color.Info" OnClick="AddPeer">Add peer</MudIconButton>
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.ViewColumn" Color="Color.Inherit" OnClick="ColumnOptions" title="Choose Columns" />
|
<MudIconButton Icon="@Icons.Material.Filled.DisabledByDefault" Color="Color.Error" OnClick="BanPeerToolbar" Disabled="@(SelectedItem is null)">Ban peer</MudIconButton>
|
||||||
</MudToolBar>
|
<MudDivider Vertical="true" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Outlined.ViewColumn" Color="Color.Inherit" OnClick="ColumnOptions" title="Choose Columns" />
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
|
||||||
<DynamicTable T="Peer"
|
<div class="content-panel__body">
|
||||||
ColumnDefinitions="Columns"
|
<DynamicTable T="Peer"
|
||||||
Items="Peers"
|
ColumnDefinitions="Columns"
|
||||||
MultiSelection="false"
|
Items="Peers"
|
||||||
SelectOnRowClick="true"
|
MultiSelection="false"
|
||||||
OnTableDataLongPress="TableDataLongPress"
|
SelectOnRowClick="true"
|
||||||
OnTableDataContextMenu="TableDataContextMenu"
|
OnTableDataLongPress="TableDataLongPress"
|
||||||
SelectedItemChanged="SelectedItemChanged"
|
OnTableDataContextMenu="TableDataContextMenu"
|
||||||
Class="details-list" />
|
SelectedItemChanged="SelectedItemChanged"
|
||||||
|
Class="details-list content-panel__table" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -52,7 +52,7 @@ namespace Lantean.QBTMud.Components
|
|||||||
|
|
||||||
protected Peer? SelectedItem { get; set; }
|
protected Peer? SelectedItem { get; set; }
|
||||||
|
|
||||||
protected ContextMenu? ContextMenu { get; set; }
|
protected MudMenu? ContextMenu { get; set; }
|
||||||
|
|
||||||
protected DynamicTable<Peer>? Table { get; set; }
|
protected DynamicTable<Peer>? Table { get; set; }
|
||||||
|
|
||||||
@@ -153,7 +153,9 @@ namespace Lantean.QBTMud.Components
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ContextMenu.ToggleMenuAsync(eventArgs);
|
var normalizedEventArgs = eventArgs.NormalizeForContextMenu();
|
||||||
|
|
||||||
|
await ContextMenu.OpenMenuAsync(normalizedEventArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void SelectedItemChanged(Peer peer)
|
protected void SelectedItemChanged(Peer peer)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<ContextMenu @ref="ContextMenu" Dense="true">
|
<MudMenu @ref="ContextMenu" Dense="true" PositionAtCursor="true" ListClass="unselectable" PopoverClass="unselectable">
|
||||||
<MudMenuItem Icon="@Icons.Material.Filled.AddCircle" IconColor="Color.Info" OnClick="AddTracker">Add trackers</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Filled.AddCircle" IconColor="Color.Info" OnClick="AddTracker">Add trackers</MudMenuItem>
|
||||||
@if (ContextMenuItem is not null)
|
@if (ContextMenuItem is not null)
|
||||||
{
|
{
|
||||||
@@ -6,27 +6,33 @@
|
|||||||
<MudMenuItem Icon="@Icons.Material.Filled.Delete" IconColor="Color.Error" OnClick="RemoveTrackerContextMenu">Remove tracker</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Filled.Delete" IconColor="Color.Error" OnClick="RemoveTrackerContextMenu">Remove tracker</MudMenuItem>
|
||||||
<MudMenuItem Icon="@Icons.Material.Filled.FolderCopy" IconColor="Color.Info" OnClick="CopyTrackerUrlContextMenu">Copy tracker url</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Filled.FolderCopy" IconColor="Color.Info" OnClick="CopyTrackerUrlContextMenu">Copy tracker url</MudMenuItem>
|
||||||
}
|
}
|
||||||
</ContextMenu>
|
</MudMenu>
|
||||||
|
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.AddCircle" Color="Color.Info" OnClick="AddTracker">Add trackers</MudIconButton>
|
<div class="content-panel__toolbar">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Edit" Color="Color.Info" OnClick="EditTrackerToolbar" Disabled="@(SelectedItem is null)">Edit tracker URL</MudIconButton>
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Delete" Color="Color.Error" OnClick="RemoveTrackerToolbar" Disabled="@(SelectedItem is null)">Remove tracker</MudIconButton>
|
<MudIconButton Icon="@Icons.Material.Filled.AddCircle" Color="Color.Info" OnClick="AddTracker">Add trackers</MudIconButton>
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.FolderCopy" Color="Color.Info" OnClick="CopyTrackerUrlToolbar" Disabled="@(SelectedItem is null)">Copy tracker url</MudIconButton>
|
<MudIconButton Icon="@Icons.Material.Filled.Edit" Color="Color.Info" OnClick="EditTrackerToolbar" Disabled="@(SelectedItem is null)">Edit tracker URL</MudIconButton>
|
||||||
<MudDivider Vertical="true" />
|
<MudIconButton Icon="@Icons.Material.Filled.Delete" Color="Color.Error" OnClick="RemoveTrackerToolbar" Disabled="@(SelectedItem is null)">Remove tracker</MudIconButton>
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.ViewColumn" Color="Color.Inherit" OnClick="ColumnOptions" title="Choose Columns" />
|
<MudIconButton Icon="@Icons.Material.Filled.FolderCopy" Color="Color.Info" OnClick="CopyTrackerUrlToolbar" Disabled="@(SelectedItem is null)">Copy tracker url</MudIconButton>
|
||||||
</MudToolBar>
|
<MudDivider Vertical="true" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Outlined.ViewColumn" Color="Color.Inherit" OnClick="ColumnOptions" title="Choose Columns" />
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
|
||||||
<DynamicTable @ref="Table"
|
<div class="content-panel__body">
|
||||||
T="Lantean.QBitTorrentClient.Models.TorrentTracker"
|
<DynamicTable @ref="Table"
|
||||||
ColumnDefinitions="Columns"
|
T="Lantean.QBitTorrentClient.Models.TorrentTracker"
|
||||||
Items="Trackers"
|
ColumnDefinitions="Columns"
|
||||||
MultiSelection="false"
|
Items="Trackers"
|
||||||
SelectOnRowClick="false"
|
MultiSelection="false"
|
||||||
PreSorted="true"
|
SelectOnRowClick="false"
|
||||||
SortDirectionChanged="SortDirectionChanged"
|
PreSorted="true"
|
||||||
SortColumnChanged="SortColumnChanged"
|
SortDirectionChanged="SortDirectionChanged"
|
||||||
OnTableDataLongPress="TableDataLongPress"
|
SortColumnChanged="SortColumnChanged"
|
||||||
OnTableDataContextMenu="TableDataContextMenu"
|
OnTableDataLongPress="TableDataLongPress"
|
||||||
SelectedItemChanged="SelectedItemChanged"
|
OnTableDataContextMenu="TableDataContextMenu"
|
||||||
Class="file-list" />
|
SelectedItemChanged="SelectedItemChanged"
|
||||||
|
Class="file-list content-panel__table" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -52,7 +52,7 @@ namespace Lantean.QBTMud.Components
|
|||||||
|
|
||||||
protected TorrentTracker? SelectedItem { get; set; }
|
protected TorrentTracker? SelectedItem { get; set; }
|
||||||
|
|
||||||
protected ContextMenu? ContextMenu { get; set; }
|
protected MudMenu? ContextMenu { get; set; }
|
||||||
|
|
||||||
protected DynamicTable<TorrentTracker>? Table { get; set; }
|
protected DynamicTable<TorrentTracker>? Table { get; set; }
|
||||||
|
|
||||||
@@ -148,7 +148,9 @@ namespace Lantean.QBTMud.Components
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ContextMenu.ToggleMenuAsync(eventArgs);
|
var normalizedEventArgs = eventArgs.NormalizeForContextMenu();
|
||||||
|
|
||||||
|
await ContextMenu.OpenMenuAsync(normalizedEventArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void SelectedItemChanged(TorrentTracker torrentTracker)
|
protected void SelectedItemChanged(TorrentTracker torrentTracker)
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
@inherits MudComponentBase
|
|
||||||
|
|
||||||
<MudMenu @ref="FakeMenu" Style="display: none" OpenChanged="FakeOpenChanged"></MudMenu>
|
|
||||||
|
|
||||||
@* The portal has to include the cascading values inside, because it's not able to teletransport the cascade *@
|
|
||||||
<MudPopover tracker="@Id"
|
|
||||||
Open="@_open"
|
|
||||||
Class="unselectable"
|
|
||||||
MaxHeight="@MaxHeight"
|
|
||||||
AnchorOrigin="@AnchorOrigin"
|
|
||||||
TransformOrigin="@TransformOrigin"
|
|
||||||
RelativeWidth="@RelativeWidth"
|
|
||||||
OverflowBehavior="OverflowBehavior.FlipAlways"
|
|
||||||
Style="@_popoverStyle"
|
|
||||||
@ontouchend:preventDefault>
|
|
||||||
<CascadingValue Value="@(FakeMenu)">
|
|
||||||
@if (_showChildren)
|
|
||||||
{
|
|
||||||
<MudList T="object" Class="unselectable" Dense="@Dense">
|
|
||||||
@ChildContent
|
|
||||||
</MudList>
|
|
||||||
}
|
|
||||||
</CascadingValue>
|
|
||||||
</MudPopover>
|
|
||||||
|
|
||||||
<MudOverlay Visible="@(_open)" LockScroll="@LockScroll" AutoClose="true" OnClosed="@CloseMenuAsync" />
|
|
||||||
@@ -1,290 +0,0 @@
|
|||||||
using Lantean.QBTMud.Interop;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using Microsoft.AspNetCore.Components.Web;
|
|
||||||
using Microsoft.JSInterop;
|
|
||||||
using MudBlazor;
|
|
||||||
using MudBlazor.Utilities;
|
|
||||||
|
|
||||||
namespace Lantean.QBTMud.Components.UI
|
|
||||||
{
|
|
||||||
public partial class ContextMenu : MudComponentBase
|
|
||||||
{
|
|
||||||
private bool _open;
|
|
||||||
private bool _showChildren;
|
|
||||||
private string? _popoverStyle;
|
|
||||||
private string? _id;
|
|
||||||
|
|
||||||
private double _x;
|
|
||||||
private double _y;
|
|
||||||
private bool _isResized = false;
|
|
||||||
|
|
||||||
private const double _diff = 64;
|
|
||||||
|
|
||||||
private string Id
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
_id ??= Guid.NewGuid().ToString();
|
|
||||||
|
|
||||||
return _id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Inject]
|
|
||||||
public IJSRuntime JSRuntime { get; set; } = default!;
|
|
||||||
|
|
||||||
[Inject]
|
|
||||||
public IPopoverService PopoverService { get; set; } = default!;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, compact vertical padding will be applied to all menu items.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
|
||||||
public bool Dense { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set to true if you want to prevent page from scrolling when the menu is open
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
|
||||||
public bool LockScroll { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, the list menu will be same width as the parent.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
|
||||||
public DropdownWidth RelativeWidth { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the max height the menu can have when open.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
|
||||||
public int? MaxHeight { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set the anchor origin point to determine where the popover will open from.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
|
||||||
public Origin AnchorOrigin { get; set; } = Origin.TopLeft;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the transform origin point for the popover.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Menu.PopupAppearance)]
|
|
||||||
public Origin TransformOrigin { get; set; } = Origin.TopLeft;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If true, menu will be disabled.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Menu.Behavior)]
|
|
||||||
public bool Disabled { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets whether to show a ripple effect when the user clicks the button. Default is true.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Menu.Appearance)]
|
|
||||||
public bool Ripple { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines whether the component has a drop-shadow. Default is true
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Menu.Appearance)]
|
|
||||||
public bool DropShadow { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add menu items here
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Menu.PopupBehavior)]
|
|
||||||
public RenderFragment? ChildContent { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fired when the menu <see cref="Open"/> property changes.
|
|
||||||
/// </summary>
|
|
||||||
[Parameter]
|
|
||||||
[Category(CategoryTypes.Menu.PopupBehavior)]
|
|
||||||
public EventCallback<bool> OpenChanged { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public int AdjustmentX { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public int AdjustmentY { get; set; }
|
|
||||||
|
|
||||||
protected MudMenu? FakeMenu { get; set; }
|
|
||||||
|
|
||||||
protected void FakeOpenChanged(bool value)
|
|
||||||
{
|
|
||||||
if (!value)
|
|
||||||
{
|
|
||||||
_open = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens the menu.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="args">
|
|
||||||
/// The arguments of the calling mouse/pointer event.
|
|
||||||
/// </param>
|
|
||||||
public async Task OpenMenuAsync(EventArgs args)
|
|
||||||
{
|
|
||||||
if (Disabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// long press on iOS triggers selection, so clear it
|
|
||||||
await JSRuntime.ClearSelection();
|
|
||||||
|
|
||||||
if (args is not LongPressEventArgs)
|
|
||||||
{
|
|
||||||
_showChildren = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_open = true;
|
|
||||||
_isResized = false;
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
var (x, y) = GetPositionFromArgs(args);
|
|
||||||
_x = x;
|
|
||||||
_y = y;
|
|
||||||
|
|
||||||
SetPopoverStyle(x, y);
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
await OpenChanged.InvokeAsync(_open);
|
|
||||||
|
|
||||||
// long press on iOS triggers selection, so clear it
|
|
||||||
await JSRuntime.ClearSelection();
|
|
||||||
|
|
||||||
if (args is LongPressEventArgs)
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
_showChildren = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Closes the menu.
|
|
||||||
/// </summary>
|
|
||||||
public Task CloseMenuAsync()
|
|
||||||
{
|
|
||||||
_open = false;
|
|
||||||
_popoverStyle = null;
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
return OpenChanged.InvokeAsync(_open);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetPopoverStyle(double x, double y)
|
|
||||||
{
|
|
||||||
_popoverStyle = $"margin-top: {y.ToPx()}; margin-left: {x.ToPx()};";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Toggle the visibility of the menu.
|
|
||||||
/// </summary>
|
|
||||||
public async Task ToggleMenuAsync(EventArgs args)
|
|
||||||
{
|
|
||||||
if (Disabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_open)
|
|
||||||
{
|
|
||||||
await CloseMenuAsync();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await OpenMenuAsync(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Task OnAfterRenderAsync(bool firstRender)
|
|
||||||
{
|
|
||||||
if (!_isResized)
|
|
||||||
{
|
|
||||||
//await DeterminePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
//private async Task DeterminePosition()
|
|
||||||
//{
|
|
||||||
// var mainContentSize = await JSRuntime.GetInnerDimensions(".mud-main-content");
|
|
||||||
// double? contextMenuHeight = null;
|
|
||||||
// double? contextMenuWidth = null;
|
|
||||||
|
|
||||||
// var popoverHolder = PopoverService.ActivePopovers.FirstOrDefault(p => p.UserAttributes.ContainsKey("tracker") && (string?)p.UserAttributes["tracker"] == Id);
|
|
||||||
|
|
||||||
// var popoverSize = await JSRuntime.GetBoundingClientRect($"#popovercontent-{popoverHolder?.Id}");
|
|
||||||
// if (popoverSize.Height > 0)
|
|
||||||
// {
|
|
||||||
// contextMenuHeight = popoverSize.Height;
|
|
||||||
// contextMenuWidth = popoverSize.Width;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // the bottom position of the popover will be rendered off screen
|
|
||||||
// if (_y - _diff + contextMenuHeight.Value >= mainContentSize.Height)
|
|
||||||
// {
|
|
||||||
// // adjust the top of the context menu
|
|
||||||
// var overshoot = Math.Abs(mainContentSize.Height - (_y - _diff + contextMenuHeight.Value));
|
|
||||||
// _y -= overshoot;
|
|
||||||
|
|
||||||
// if (_y - _diff + contextMenuHeight >= mainContentSize.Height)
|
|
||||||
// {
|
|
||||||
// MaxHeight = (int)(mainContentSize.Height - _y + _diff);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (_x + contextMenuWidth.Value > mainContentSize.Width)
|
|
||||||
// {
|
|
||||||
// var overshoot = Math.Abs(mainContentSize.Width - (_x + contextMenuWidth.Value));
|
|
||||||
// _x -= overshoot;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// SetPopoverStyle(_x, _y);
|
|
||||||
// _isResized = true;
|
|
||||||
// await InvokeAsync(StateHasChanged);
|
|
||||||
//}
|
|
||||||
|
|
||||||
private (double x, double y) GetPositionFromArgs(EventArgs eventArgs)
|
|
||||||
{
|
|
||||||
double x, y;
|
|
||||||
if (eventArgs is MouseEventArgs mouseEventArgs)
|
|
||||||
{
|
|
||||||
x = mouseEventArgs.ClientX;
|
|
||||||
y = mouseEventArgs.ClientY;
|
|
||||||
}
|
|
||||||
else if (eventArgs is LongPressEventArgs longPressEventArgs)
|
|
||||||
{
|
|
||||||
x = longPressEventArgs.ClientX;
|
|
||||||
y = longPressEventArgs.ClientY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("Invalid eventArgs type.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (x + AdjustmentX, y + AdjustmentY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<div class="@Classname">
|
<div class="@Classname">
|
||||||
<div @onclick="this.AsNonRenderingEventHandler<MouseEventArgs>(OnClickHandler)" class="@LinkClassname" @onlongpress="OnLongPressInternal" @oncontextmenu="OnContextMenuInternal" @oncontextmenu:preventDefault>
|
<div @onclick="this.AsNonRenderingEventHandler<MouseEventArgs>(OnClickHandler)" class="@LinkClassname" @onlongpress="OnLongPressInternal" @onlongpress:preventDefault @oncontextmenu="OnContextMenuInternal" @oncontextmenu:preventDefault>
|
||||||
@if (!string.IsNullOrEmpty(Icon))
|
@if (!string.IsNullOrEmpty(Icon))
|
||||||
{
|
{
|
||||||
<MudIcon Icon="@Icon" Color="@IconColor" Class="@IconClassname" />
|
<MudIcon Icon="@Icon" Color="@IconColor" Class="@IconClassname" />
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ namespace Lantean.QBTMud.Components.UI
|
|||||||
new CssBuilder("mud-nav-link")
|
new CssBuilder("mud-nav-link")
|
||||||
.AddClass($"mud-nav-link-disabled", Disabled)
|
.AddClass($"mud-nav-link-disabled", Disabled)
|
||||||
.AddClass("active", Active)
|
.AddClass("active", Active)
|
||||||
|
.AddClass("unselectable", OnLongPress.HasDelegate || OnContextMenu.HasDelegate)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
protected string IconClassname =>
|
protected string IconClassname =>
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ namespace Lantean.QBTMud.Components.UI
|
|||||||
|
|
||||||
protected HashSet<string> SelectedColumns { get; set; } = [];
|
protected HashSet<string> SelectedColumns { get; set; } = [];
|
||||||
|
|
||||||
|
private static readonly IReadOnlyList<ColumnDefinition<T>> EmptyColumns = Array.Empty<ColumnDefinition<T>>();
|
||||||
|
|
||||||
private Dictionary<string, int?> _columnWidths = [];
|
private Dictionary<string, int?> _columnWidths = [];
|
||||||
|
|
||||||
private Dictionary<string, int> _columnOrder = [];
|
private Dictionary<string, int> _columnOrder = [];
|
||||||
@@ -89,8 +91,16 @@ namespace Lantean.QBTMud.Components.UI
|
|||||||
|
|
||||||
private SortDirection _sortDirection;
|
private SortDirection _sortDirection;
|
||||||
|
|
||||||
|
private DateTimeOffset? _suppressRowClickUntil;
|
||||||
|
|
||||||
private readonly Dictionary<string, TdExtended> _tds = [];
|
private readonly Dictionary<string, TdExtended> _tds = [];
|
||||||
|
|
||||||
|
private IReadOnlyList<ColumnDefinition<T>> _visibleColumns = EmptyColumns;
|
||||||
|
|
||||||
|
private bool _columnsDirty = true;
|
||||||
|
|
||||||
|
private IEnumerable<ColumnDefinition<T>>? _lastColumnDefinitions;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
HashSet<string> selectedColumns;
|
HashSet<string> selectedColumns;
|
||||||
@@ -109,6 +119,13 @@ namespace Lantean.QBTMud.Components.UI
|
|||||||
SelectedColumns = selectedColumns;
|
SelectedColumns = selectedColumns;
|
||||||
await SelectedColumnsChanged.InvokeAsync(SelectedColumns);
|
await SelectedColumnsChanged.InvokeAsync(SelectedColumns);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelectedColumns = selectedColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastColumnDefinitions = ColumnDefinitions;
|
||||||
|
MarkColumnsDirty();
|
||||||
|
|
||||||
string? sortColumn;
|
string? sortColumn;
|
||||||
SortDirection sortDirection;
|
SortDirection sortDirection;
|
||||||
@@ -137,11 +154,24 @@ namespace Lantean.QBTMud.Components.UI
|
|||||||
await SortDirectionChanged.InvokeAsync(_sortDirection);
|
await SortDirectionChanged.InvokeAsync(_sortDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MarkColumnsDirty();
|
||||||
|
|
||||||
var storedColumnsWidths = await LocalStorage.GetItemAsync<Dictionary<string, int?>>(_columnWidthsStorageKey);
|
var storedColumnsWidths = await LocalStorage.GetItemAsync<Dictionary<string, int?>>(_columnWidthsStorageKey);
|
||||||
if (storedColumnsWidths is not null)
|
if (storedColumnsWidths is not null)
|
||||||
{
|
{
|
||||||
_columnWidths = storedColumnsWidths;
|
_columnWidths = storedColumnsWidths;
|
||||||
}
|
}
|
||||||
|
MarkColumnsDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnParametersSet()
|
||||||
|
{
|
||||||
|
base.OnParametersSet();
|
||||||
|
if (!ReferenceEquals(_lastColumnDefinitions, ColumnDefinitions))
|
||||||
|
{
|
||||||
|
_lastColumnDefinitions = ColumnDefinitions;
|
||||||
|
MarkColumnsDirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<T>? GetOrderedItems()
|
private IEnumerable<T>? GetOrderedItems()
|
||||||
@@ -165,39 +195,74 @@ namespace Lantean.QBTMud.Components.UI
|
|||||||
return Items.OrderByDirection(_sortDirection, sortSelector);
|
return Items.OrderByDirection(_sortDirection, sortSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IEnumerable<ColumnDefinition<T>> GetColumns()
|
protected IReadOnlyList<ColumnDefinition<T>> GetColumns()
|
||||||
{
|
{
|
||||||
var filteredColumns = ColumnDefinitions.Where(c => SelectedColumns.Contains(c.Id)).Where(ColumnFilter);
|
if (!_columnsDirty)
|
||||||
if (_columnOrder.Count == 0)
|
|
||||||
{
|
{
|
||||||
foreach (var column in filteredColumns)
|
return _visibleColumns;
|
||||||
{
|
|
||||||
if (_columnWidths.TryGetValue(column.Id, out var value))
|
|
||||||
{
|
|
||||||
column.Width = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return column;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var columnDictionary = filteredColumns.ToDictionary(c => c.Id);
|
_visibleColumns = BuildVisibleColumns();
|
||||||
foreach (var columnId in _columnOrder.OrderBy(c => c.Value).Select(c => c.Key))
|
_columnsDirty = false;
|
||||||
|
|
||||||
|
return _visibleColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IReadOnlyList<ColumnDefinition<T>> BuildVisibleColumns()
|
||||||
|
{
|
||||||
|
var filteredColumns = ColumnDefinitions
|
||||||
|
.Where(c => SelectedColumns.Contains(c.Id))
|
||||||
|
.Where(ColumnFilter)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (filteredColumns.Count == 0)
|
||||||
{
|
{
|
||||||
if (!columnDictionary.TryGetValue(columnId, out var column))
|
return EmptyColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ColumnDefinition<T>> orderedColumns;
|
||||||
|
if (_columnOrder.Count == 0)
|
||||||
|
{
|
||||||
|
orderedColumns = filteredColumns;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var orderLookup = _columnOrder.OrderBy(entry => entry.Value).ToList();
|
||||||
|
var columnDictionary = filteredColumns.ToDictionary(c => c.Id);
|
||||||
|
orderedColumns = new List<ColumnDefinition<T>>(filteredColumns.Count);
|
||||||
|
|
||||||
|
foreach (var (columnId, _) in orderLookup)
|
||||||
{
|
{
|
||||||
continue;
|
if (!columnDictionary.TryGetValue(columnId, out var column))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
orderedColumns.Add(column);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (orderedColumns.Count != filteredColumns.Count)
|
||||||
|
{
|
||||||
|
var existingIds = new HashSet<string>(orderedColumns.Select(c => c.Id));
|
||||||
|
foreach (var column in filteredColumns)
|
||||||
|
{
|
||||||
|
if (existingIds.Add(column.Id))
|
||||||
|
{
|
||||||
|
orderedColumns.Add(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var column in orderedColumns)
|
||||||
|
{
|
||||||
if (_columnWidths.TryGetValue(column.Id, out var value))
|
if (_columnWidths.TryGetValue(column.Id, out var value))
|
||||||
{
|
{
|
||||||
column.Width = value;
|
column.Width = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return orderedColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SetSort(string columnId, SortDirection sortDirection)
|
private async Task SetSort(string columnId, SortDirection sortDirection)
|
||||||
@@ -223,6 +288,17 @@ namespace Lantean.QBTMud.Components.UI
|
|||||||
|
|
||||||
protected async Task OnRowClickInternal(TableRowClickEventArgs<T> eventArgs)
|
protected async Task OnRowClickInternal(TableRowClickEventArgs<T> eventArgs)
|
||||||
{
|
{
|
||||||
|
if (_suppressRowClickUntil is not null)
|
||||||
|
{
|
||||||
|
if (DateTimeOffset.UtcNow <= _suppressRowClickUntil.Value)
|
||||||
|
{
|
||||||
|
_suppressRowClickUntil = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_suppressRowClickUntil = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (eventArgs.Item is null)
|
if (eventArgs.Item is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -298,6 +374,7 @@ namespace Lantean.QBTMud.Components.UI
|
|||||||
|
|
||||||
protected Task OnLongPressInternal(LongPressEventArgs eventArgs, string columnId, T item)
|
protected Task OnLongPressInternal(LongPressEventArgs eventArgs, string columnId, T item)
|
||||||
{
|
{
|
||||||
|
_suppressRowClickUntil = DateTimeOffset.UtcNow.AddMilliseconds(500);
|
||||||
var data = _tds[columnId];
|
var data = _tds[columnId];
|
||||||
return OnTableDataLongPress.InvokeAsync(new TableDataLongPressEventArgs<T>(eventArgs, data, item));
|
return OnTableDataLongPress.InvokeAsync(new TableDataLongPressEventArgs<T>(eventArgs, data, item));
|
||||||
}
|
}
|
||||||
@@ -316,18 +393,21 @@ namespace Lantean.QBTMud.Components.UI
|
|||||||
SelectedColumns = result.SelectedColumns;
|
SelectedColumns = result.SelectedColumns;
|
||||||
await LocalStorage.SetItemAsync(_columnSelectionStorageKey, SelectedColumns);
|
await LocalStorage.SetItemAsync(_columnSelectionStorageKey, SelectedColumns);
|
||||||
await SelectedColumnsChanged.InvokeAsync(SelectedColumns);
|
await SelectedColumnsChanged.InvokeAsync(SelectedColumns);
|
||||||
|
MarkColumnsDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DictionaryEqual(_columnWidths, result.ColumnWidths))
|
if (!DictionaryEqual(_columnWidths, result.ColumnWidths))
|
||||||
{
|
{
|
||||||
_columnWidths = result.ColumnWidths;
|
_columnWidths = result.ColumnWidths;
|
||||||
await LocalStorage.SetItemAsync(_columnWidthsStorageKey, _columnWidths);
|
await LocalStorage.SetItemAsync(_columnWidthsStorageKey, _columnWidths);
|
||||||
|
MarkColumnsDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DictionaryEqual(_columnOrder, result.ColumnOrder))
|
if (!DictionaryEqual(_columnOrder, result.ColumnOrder))
|
||||||
{
|
{
|
||||||
_columnOrder = result.ColumnOrder;
|
_columnOrder = result.ColumnOrder;
|
||||||
await LocalStorage.SetItemAsync(_columnOrderStorageKey, _columnOrder);
|
await LocalStorage.SetItemAsync(_columnOrderStorageKey, _columnOrder);
|
||||||
|
MarkColumnsDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,17 +448,34 @@ namespace Lantean.QBTMud.Components.UI
|
|||||||
|
|
||||||
if (column.Width.HasValue)
|
if (column.Width.HasValue)
|
||||||
{
|
{
|
||||||
className = $"overflow-cell {className}";
|
className = string.IsNullOrWhiteSpace(className)
|
||||||
|
? "overflow-cell"
|
||||||
|
: $"overflow-cell {className}";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OnTableDataContextMenu.HasDelegate)
|
if (OnTableDataContextMenu.HasDelegate)
|
||||||
{
|
{
|
||||||
className = $"no-default-context-menu {className}";
|
className = string.IsNullOrWhiteSpace(className)
|
||||||
|
? "no-default-context-menu"
|
||||||
|
: $"no-default-context-menu {className}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OnTableDataLongPress.HasDelegate)
|
||||||
|
{
|
||||||
|
className = string.IsNullOrWhiteSpace(className)
|
||||||
|
? "unselectable"
|
||||||
|
: $"unselectable {className}";
|
||||||
}
|
}
|
||||||
|
|
||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MarkColumnsDirty()
|
||||||
|
{
|
||||||
|
_columnsDirty = true;
|
||||||
|
_visibleColumns = EmptyColumns;
|
||||||
|
}
|
||||||
|
|
||||||
private sealed record SortData
|
private sealed record SortData
|
||||||
{
|
{
|
||||||
public SortData(string sortColumn, SortDirection sortDirection)
|
public SortData(string sortColumn, SortDirection sortDirection)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@inherits MudTd
|
@inherits MudTd
|
||||||
|
|
||||||
<td data-label="@DataLabel" style="@Style" class="@Classname" @attributes="@UserAttributes" @onlongpress="OnLongPressInternal" @oncontextmenu="OnContextMenuInternal" @oncontextmenu:preventDefault>
|
<td data-label="@DataLabel" style="@Style" class="@Classname" @attributes="@UserAttributes" @onlongpress="OnLongPressInternal" @onlongpress:preventDefault @oncontextmenu="OnContextMenuInternal" @oncontextmenu:preventDefault>
|
||||||
@ChildContent
|
@ChildContent
|
||||||
</td>
|
</td>
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
<DynamicTable T="Lantean.QBitTorrentClient.Models.WebSeed"
|
<div class="content-panel">
|
||||||
ColumnDefinitions="Columns"
|
<div class="content-panel__body">
|
||||||
Items="WebSeeds"
|
<DynamicTable T="Lantean.QBitTorrentClient.Models.WebSeed"
|
||||||
MultiSelection="false"
|
ColumnDefinitions="Columns"
|
||||||
SelectOnRowClick="false"
|
Items="WebSeeds"
|
||||||
Class="details-list" />
|
MultiSelection="false"
|
||||||
|
SelectOnRowClick="false"
|
||||||
|
Class="details-list content-panel__table" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -83,7 +83,6 @@ namespace Lantean.QBTMud.Helpers
|
|||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Formats a file size in bytes into an appropriate unit based on the size.
|
/// Formats a file size in bytes into an appropriate unit based on the size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
40
Lantean.QBTMud/Helpers/EventArgsExtensions.cs
Normal file
40
Lantean.QBTMud/Helpers/EventArgsExtensions.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
|
|
||||||
|
namespace Lantean.QBTMud.Helpers
|
||||||
|
{
|
||||||
|
public static class EventArgsExtensions
|
||||||
|
{
|
||||||
|
public static EventArgs NormalizeForContextMenu(this EventArgs eventArgs)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(eventArgs);
|
||||||
|
|
||||||
|
if (eventArgs is LongPressEventArgs longPressEventArgs)
|
||||||
|
{
|
||||||
|
return longPressEventArgs.ToMouseEventArgs();
|
||||||
|
}
|
||||||
|
|
||||||
|
return eventArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MouseEventArgs ToMouseEventArgs(this LongPressEventArgs longPressEventArgs)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(longPressEventArgs);
|
||||||
|
|
||||||
|
return new MouseEventArgs
|
||||||
|
{
|
||||||
|
Button = 2,
|
||||||
|
Buttons = 2,
|
||||||
|
ClientX = longPressEventArgs.ClientX,
|
||||||
|
ClientY = longPressEventArgs.ClientY,
|
||||||
|
OffsetX = longPressEventArgs.OffsetX,
|
||||||
|
OffsetY = longPressEventArgs.OffsetY,
|
||||||
|
PageX = longPressEventArgs.PageX,
|
||||||
|
PageY = longPressEventArgs.PageY,
|
||||||
|
ScreenX = longPressEventArgs.ScreenX,
|
||||||
|
ScreenY = longPressEventArgs.ScreenY,
|
||||||
|
Type = longPressEventArgs.Type ?? "contextmenu",
|
||||||
|
Detail = -1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -128,6 +128,7 @@ namespace Lantean.QBTMud.Helpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (string.IsNullOrEmpty(torrent.Category))
|
if (string.IsNullOrEmpty(torrent.Category))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
|
namespace Lantean.QBTMud.Helpers
|
||||||
namespace Lantean.QBTMud.Helpers
|
|
||||||
{
|
{
|
||||||
internal static class VersionHelper
|
internal static class VersionHelper
|
||||||
{
|
{
|
||||||
@@ -31,4 +30,4 @@ namespace Lantean.QBTMud.Helpers
|
|||||||
return _version.Value;
|
return _version.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,10 +12,10 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
|
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
|
||||||
<PackageReference Include="ByteSize" Version="2.1.2" />
|
<PackageReference Include="ByteSize" Version="2.1.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.5" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.10" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.5" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.10" PrivateAssets="all" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.10" />
|
||||||
<PackageReference Include="MudBlazor" Version="8.7.0" />
|
<PackageReference Include="MudBlazor" Version="8.13.0" />
|
||||||
<PackageReference Include="MudBlazor.ThemeManager" Version="3.0.0" />
|
<PackageReference Include="MudBlazor.ThemeManager" Version="3.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
@inherits LayoutComponentBase
|
@inherits LayoutComponentBase
|
||||||
@layout LoggedInLayout
|
@layout LoggedInLayout
|
||||||
|
|
||||||
<MudDrawer Open="DrawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2" Overlay="false">
|
<div class="app-shell__body">
|
||||||
<TorrentsListNav Torrents="Torrents" SelectedTorrent="@SelectedTorrent" SortDirection="SortDirection" SortColumn="@SortColumn" />
|
<MudDrawer Open="DrawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2" Overlay="false" Class="app-shell__sidebar">
|
||||||
</MudDrawer>
|
<TorrentsListNav Torrents="Torrents" SelectedTorrent="@SelectedTorrent" SortDirection="SortDirection" SortColumn="@SortColumn" />
|
||||||
<MudMainContent>
|
</MudDrawer>
|
||||||
@Body
|
<MudMainContent Class="app-shell__main">
|
||||||
</MudMainContent>
|
@Body
|
||||||
|
</MudMainContent>
|
||||||
|
</div>
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
@inherits LayoutComponentBase
|
@inherits LayoutComponentBase
|
||||||
@layout LoggedInLayout
|
@layout LoggedInLayout
|
||||||
|
|
||||||
<MudDrawer Open="DrawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2" Overlay="false">
|
<div class="app-shell__body">
|
||||||
<FiltersNav CategoryChanged="CategoryChanged" StatusChanged="StatusChanged" TagChanged="TagChanged" TrackerChanged="TrackerChanged" />
|
<MudDrawer Open="DrawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2" Overlay="false" Class="app-shell__sidebar">
|
||||||
</MudDrawer>
|
<FiltersNav CategoryChanged="CategoryChanged" StatusChanged="StatusChanged" TagChanged="TagChanged" TrackerChanged="TrackerChanged" />
|
||||||
<MudMainContent>
|
</MudDrawer>
|
||||||
<CascadingValue Value="SearchTermChanged" Name="SearchTermChanged">
|
<MudMainContent Class="app-shell__main">
|
||||||
@Body
|
<CascadingValue Value="SearchTermChanged" Name="SearchTermChanged">
|
||||||
</CascadingValue>
|
@Body
|
||||||
</MudMainContent>
|
</CascadingValue>
|
||||||
|
</MudMainContent>
|
||||||
|
</div>
|
||||||
@@ -10,20 +10,53 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
<CascadingValue Value="Torrents">
|
<CascadingValue Value="Torrents">
|
||||||
<CascadingValue Value="MainData">
|
<CascadingValue Value="_torrentsVersion" Name="TorrentsVersion">
|
||||||
<CascadingValue Value="Preferences">
|
<CascadingValue Value="MainData">
|
||||||
<CascadingValue Value="SortColumnChanged" Name="SortColumnChanged">
|
<CascadingValue Value="Preferences">
|
||||||
<CascadingValue Value="SortColumn" Name="SortColumn">
|
<CascadingValue Value="SortColumnChanged" Name="SortColumnChanged">
|
||||||
<CascadingValue Value="SortDirectionChanged" Name="SortDirectionChanged">
|
<CascadingValue Value="SortColumn" Name="SortColumn">
|
||||||
<CascadingValue Value="SortDirection" Name="SortDirection">
|
<CascadingValue Value="SortDirectionChanged" Name="SortDirectionChanged">
|
||||||
<CascadingValue Value="CategoryChanged" Name="CategoryChanged">
|
<CascadingValue Value="SortDirection" Name="SortDirection">
|
||||||
<CascadingValue Value="StatusChanged" Name="StatusChanged">
|
<CascadingValue Value="CategoryChanged" Name="CategoryChanged">
|
||||||
<CascadingValue Value="TagChanged" Name="TagChanged">
|
<CascadingValue Value="StatusChanged" Name="StatusChanged">
|
||||||
<CascadingValue Value="TrackerChanged" Name="TrackerChanged">
|
<CascadingValue Value="TagChanged" Name="TagChanged">
|
||||||
<CascadingValue Value="SearchTermChanged" Name="SearchTermChanged">
|
<CascadingValue Value="TrackerChanged" Name="TrackerChanged">
|
||||||
<CascadingValue Value="@(MainData?.LostConnection ?? false)" Name="LostConnection">
|
<CascadingValue Value="SearchTermChanged" Name="SearchTermChanged">
|
||||||
<CascadingValue Value="Version" Name="Version">
|
<CascadingValue Value="@(MainData?.LostConnection ?? false)" Name="LostConnection">
|
||||||
@Body
|
<CascadingValue Value="Version" Name="Version">
|
||||||
|
<div class="app-shell">
|
||||||
|
@Body
|
||||||
|
<MudAppBar Bottom="true" Elevation="0" Dense="true" Class="app-shell__status-bar">
|
||||||
|
@if (MainData?.LostConnection == true)
|
||||||
|
{
|
||||||
|
<MudText Class="mx-2 mb-1 d-none d-sm-flex" Color="Color.Error">qBittorrent client is not reachable</MudText>
|
||||||
|
}
|
||||||
|
<MudSpacer />
|
||||||
|
<MudText Class="mx-2 mb-1 d-none d-sm-flex">@DisplayHelpers.Size(MainData?.ServerState.FreeSpaceOnDisk, "Free space: ")</MudText>
|
||||||
|
<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>
|
||||||
|
<MudDivider Vertical="true" Class="d-none d-sm-flex" />
|
||||||
|
@{
|
||||||
|
var (icon, colour) = GetConnectionIcon(MainData?.ServerState.ConnectionStatus);
|
||||||
|
}
|
||||||
|
<MudIcon Class="mx-1 mb-1" Icon="@icon" Color="@colour" Title="@MainData?.ServerState.ConnectionStatus" />
|
||||||
|
<MudDivider Vertical="true" Class="" />
|
||||||
|
<MudIcon Class="mx-1 mb-1" Icon="@Icons.Material.Outlined.Speed" Color="@((MainData?.ServerState.UseAltSpeedLimits ?? false) ? Color.Error : Color.Success)" />
|
||||||
|
<MudDivider Vertical="true" Class="" />
|
||||||
|
<MudIcon Class="ml-1 mb-1" Icon="@Icons.Material.Filled.KeyboardDoubleArrowDown" Color="Color.Success" />
|
||||||
|
<MudText Class="mr-1 mb-1">
|
||||||
|
@DisplayHelpers.Size(MainData?.ServerState.DownloadInfoSpeed, null, "/s")
|
||||||
|
@DisplayHelpers.Size(MainData?.ServerState.DownloadInfoData, "(", ")")
|
||||||
|
</MudText>
|
||||||
|
<MudDivider Vertical="true" />
|
||||||
|
<MudIcon Class="ml-1 mb-1" Icon="@Icons.Material.Filled.KeyboardDoubleArrowUp" Color="Color.Info" />
|
||||||
|
<MudText Class="mr-1 mb-1">
|
||||||
|
@DisplayHelpers.Size(MainData?.ServerState.UploadInfoSpeed, null, "/s")
|
||||||
|
@DisplayHelpers.Size(MainData?.ServerState.UploadInfoData, "(", ")")
|
||||||
|
</MudText>
|
||||||
|
</MudAppBar>
|
||||||
|
</div>
|
||||||
|
</CascadingValue>
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
@@ -36,34 +69,5 @@
|
|||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
<MudAppBar Bottom="true" Fixed="true" Elevation="0" Dense="true" Style="background-color: var(--mud-palette-dark-lighten); z-index: 900">
|
|
||||||
@if (MainData?.LostConnection == true)
|
|
||||||
{
|
|
||||||
<MudText Class="mx-2 mb-1 d-none d-sm-flex" Color="Color.Error">qBittorrent client is not reachable</MudText>
|
|
||||||
}
|
|
||||||
<MudSpacer />
|
|
||||||
<MudText Class="mx-2 mb-1 d-none d-sm-flex">@DisplayHelpers.Size(MainData?.ServerState.FreeSpaceOnDisk, "Free space: ")</MudText>
|
|
||||||
<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>
|
|
||||||
<MudDivider Vertical="true" Class="d-none d-sm-flex" />
|
|
||||||
@{
|
|
||||||
var (icon, colour) = GetConnectionIcon(MainData?.ServerState.ConnectionStatus);
|
|
||||||
}
|
|
||||||
<MudIcon Class="mx-1 mb-1" Icon="@icon" Color="@colour" Title="MainData?.ServerState.ConnectionStatus" />
|
|
||||||
<MudDivider Vertical="true" Class="" />
|
|
||||||
<MudIcon Class="mx-1 mb-1" Icon="@Icons.Material.Outlined.Speed" Color="@((MainData?.ServerState.UseAltSpeedLimits ?? false) ? Color.Error : Color.Success)" />
|
|
||||||
<MudDivider Vertical="true" Class="" />
|
|
||||||
<MudIcon Class="ml-1 mb-1" Icon="@Icons.Material.Filled.KeyboardDoubleArrowDown" Color="Color.Success" />
|
|
||||||
<MudText Class="mr-1 mb-1">
|
|
||||||
@DisplayHelpers.Size(MainData?.ServerState.DownloadInfoSpeed, null, "/s")
|
|
||||||
@DisplayHelpers.Size(MainData?.ServerState.DownloadInfoData, "(", ")")
|
|
||||||
</MudText>
|
|
||||||
<MudDivider Vertical="true" />
|
|
||||||
<MudIcon Class="ml-1 mb-1" Icon="@Icons.Material.Filled.KeyboardDoubleArrowUp" Color="Color.Info" />
|
|
||||||
<MudText Class="mr-1 mb-1">
|
|
||||||
@DisplayHelpers.Size(MainData?.ServerState.UploadInfoSpeed, null, "/s")
|
|
||||||
@DisplayHelpers.Size(MainData?.ServerState.UploadInfoData, "(", ")")
|
|
||||||
</MudText>
|
|
||||||
</MudAppBar>
|
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
@@ -52,22 +52,36 @@ namespace Lantean.QBTMud.Layout
|
|||||||
|
|
||||||
protected string? SearchText { get; set; }
|
protected string? SearchText { get; set; }
|
||||||
|
|
||||||
protected IEnumerable<Torrent> Torrents => GetTorrents();
|
protected IReadOnlyList<Torrent> Torrents => GetTorrents();
|
||||||
|
|
||||||
protected bool IsAuthenticated { get; set; }
|
protected bool IsAuthenticated { get; set; }
|
||||||
|
|
||||||
protected bool LostConnection { get; set; }
|
protected bool LostConnection { get; set; }
|
||||||
|
|
||||||
private List<Torrent> GetTorrents()
|
private IReadOnlyList<Torrent> _visibleTorrents = Array.Empty<Torrent>();
|
||||||
|
|
||||||
|
private bool _torrentsDirty = true;
|
||||||
|
private int _torrentsVersion;
|
||||||
|
|
||||||
|
private IReadOnlyList<Torrent> GetTorrents()
|
||||||
{
|
{
|
||||||
|
if (!_torrentsDirty)
|
||||||
|
{
|
||||||
|
return _visibleTorrents;
|
||||||
|
}
|
||||||
|
|
||||||
if (MainData is null)
|
if (MainData is null)
|
||||||
{
|
{
|
||||||
return [];
|
_visibleTorrents = Array.Empty<Torrent>();
|
||||||
|
_torrentsDirty = false;
|
||||||
|
return _visibleTorrents;
|
||||||
}
|
}
|
||||||
|
|
||||||
var filterState = new FilterState(Category, Status, Tag, Tracker, MainData.ServerState.UseSubcategories, SearchText);
|
var filterState = new FilterState(Category, Status, Tag, Tracker, MainData.ServerState.UseSubcategories, SearchText);
|
||||||
|
_visibleTorrents = MainData.Torrents.Values.Filter(filterState).ToList();
|
||||||
|
_torrentsDirty = false;
|
||||||
|
|
||||||
return MainData.Torrents.Values.Filter(filterState).ToList();
|
return _visibleTorrents;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
@@ -84,6 +98,7 @@ namespace Lantean.QBTMud.Layout
|
|||||||
Version = await ApiClient.GetApplicationVersion();
|
Version = await ApiClient.GetApplicationVersion();
|
||||||
var data = await ApiClient.GetMainData(_requestId);
|
var data = await ApiClient.GetMainData(_requestId);
|
||||||
MainData = DataManager.CreateMainData(data, Version);
|
MainData = DataManager.CreateMainData(data, Version);
|
||||||
|
MarkTorrentsDirty();
|
||||||
|
|
||||||
_requestId = data.ResponseId;
|
_requestId = data.ResponseId;
|
||||||
_refreshInterval = MainData.ServerState.RefreshInterval;
|
_refreshInterval = MainData.ServerState.RefreshInterval;
|
||||||
@@ -126,32 +141,51 @@ namespace Lantean.QBTMud.Layout
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var shouldRender = false;
|
||||||
|
|
||||||
if (MainData is null || data.FullUpdate)
|
if (MainData is null || data.FullUpdate)
|
||||||
{
|
{
|
||||||
MainData = DataManager.CreateMainData(data, Version);
|
MainData = DataManager.CreateMainData(data, Version);
|
||||||
|
MarkTorrentsDirty();
|
||||||
|
shouldRender = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DataManager.MergeMainData(data, MainData);
|
var dataChanged = DataManager.MergeMainData(data, MainData, out var filterChanged);
|
||||||
|
if (filterChanged)
|
||||||
|
{
|
||||||
|
MarkTorrentsDirty();
|
||||||
|
}
|
||||||
|
else if (dataChanged)
|
||||||
|
{
|
||||||
|
IncrementTorrentsVersion();
|
||||||
|
}
|
||||||
|
shouldRender = dataChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
_refreshInterval = MainData.ServerState.RefreshInterval;
|
if (MainData is not null)
|
||||||
|
{
|
||||||
|
_refreshInterval = MainData.ServerState.RefreshInterval;
|
||||||
|
}
|
||||||
_requestId = data.ResponseId;
|
_requestId = data.ResponseId;
|
||||||
await InvokeAsync(StateHasChanged);
|
if (shouldRender)
|
||||||
|
{
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EventCallback<string> CategoryChanged => EventCallback.Factory.Create<string>(this, category => Category = category);
|
protected EventCallback<string> CategoryChanged => EventCallback.Factory.Create<string>(this, OnCategoryChanged);
|
||||||
|
|
||||||
protected EventCallback<Status> StatusChanged => EventCallback.Factory.Create<Status>(this, status => Status = status);
|
protected EventCallback<Status> StatusChanged => EventCallback.Factory.Create<Status>(this, OnStatusChanged);
|
||||||
|
|
||||||
protected EventCallback<string> TagChanged => EventCallback.Factory.Create<string>(this, tag => Tag = tag);
|
protected EventCallback<string> TagChanged => EventCallback.Factory.Create<string>(this, OnTagChanged);
|
||||||
|
|
||||||
protected EventCallback<string> TrackerChanged => EventCallback.Factory.Create<string>(this, tracker => Tracker = tracker);
|
protected EventCallback<string> TrackerChanged => EventCallback.Factory.Create<string>(this, OnTrackerChanged);
|
||||||
|
|
||||||
protected EventCallback<string> SearchTermChanged => EventCallback.Factory.Create<string>(this, term => SearchText = term);
|
protected EventCallback<string> SearchTermChanged => EventCallback.Factory.Create<string>(this, OnSearchTermChanged);
|
||||||
|
|
||||||
protected EventCallback<string> SortColumnChanged => EventCallback.Factory.Create<string>(this, columnId => SortColumn = columnId);
|
protected EventCallback<string> SortColumnChanged => EventCallback.Factory.Create<string>(this, columnId => SortColumn = columnId);
|
||||||
|
|
||||||
@@ -159,12 +193,81 @@ namespace Lantean.QBTMud.Layout
|
|||||||
|
|
||||||
protected static (string, Color) GetConnectionIcon(string? status)
|
protected static (string, Color) GetConnectionIcon(string? status)
|
||||||
{
|
{
|
||||||
if (status is null)
|
return status switch
|
||||||
{
|
{
|
||||||
return (Icons.Material.Outlined.SignalWifiOff, Color.Warning);
|
"firewalled" => (Icons.Material.Outlined.SignalWifiStatusbarConnectedNoInternet4, Color.Warning),
|
||||||
|
"connected" => (Icons.Material.Outlined.SignalWifi4Bar, Color.Success),
|
||||||
|
_ => (Icons.Material.Outlined.SignalWifiOff, Color.Error),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCategoryChanged(string category)
|
||||||
|
{
|
||||||
|
if (Category == category)
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (Icons.Material.Outlined.SignalWifi4Bar, Color.Success);
|
Category = category;
|
||||||
|
MarkTorrentsDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStatusChanged(Status status)
|
||||||
|
{
|
||||||
|
if (Status == status)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = status;
|
||||||
|
MarkTorrentsDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTagChanged(string tag)
|
||||||
|
{
|
||||||
|
if (Tag == tag)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag = tag;
|
||||||
|
MarkTorrentsDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTrackerChanged(string tracker)
|
||||||
|
{
|
||||||
|
if (Tracker == tracker)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tracker = tracker;
|
||||||
|
MarkTorrentsDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSearchTermChanged(string term)
|
||||||
|
{
|
||||||
|
if (SearchText == term)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchText = term;
|
||||||
|
MarkTorrentsDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MarkTorrentsDirty()
|
||||||
|
{
|
||||||
|
_torrentsDirty = true;
|
||||||
|
IncrementTorrentsVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IncrementTorrentsVersion()
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
_torrentsVersion++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
@inherits LayoutComponentBase
|
@inherits LayoutComponentBase
|
||||||
@layout LoggedInLayout
|
@layout LoggedInLayout
|
||||||
|
|
||||||
<MudDrawer Open="DrawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2" Overlay="false">
|
<div class="app-shell__body">
|
||||||
<MudNavMenu>
|
<MudDrawer Open="DrawerOpen" ClipMode="DrawerClipMode.Always" Elevation="2" Overlay="false" Class="app-shell__sidebar">
|
||||||
<ApplicationActions IsMenu="false" Preferences="Preferences" />
|
<MudNavMenu>
|
||||||
</MudNavMenu>
|
<ApplicationActions IsMenu="false" Preferences="Preferences" />
|
||||||
</MudDrawer>
|
</MudNavMenu>
|
||||||
<MudMainContent>
|
</MudDrawer>
|
||||||
@Body
|
<MudMainContent Class="app-shell__main">
|
||||||
</MudMainContent>
|
@Body
|
||||||
|
</MudMainContent>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -16,6 +16,5 @@
|
|||||||
StalledDownloading,
|
StalledDownloading,
|
||||||
Checking,
|
Checking,
|
||||||
Errored,
|
Errored,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using Lantean.QBitTorrentClient.Models;
|
namespace Lantean.QBTMud.Models
|
||||||
|
|
||||||
namespace Lantean.QBTMud.Models
|
|
||||||
{
|
{
|
||||||
public record TorrentOptions
|
public record TorrentOptions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
@page "/about"
|
@page "/about"
|
||||||
@layout OtherLayout
|
@layout OtherLayout
|
||||||
|
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel">
|
||||||
@if (!DrawerOpen)
|
<div class="content-panel__toolbar">
|
||||||
{
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
@if (!DrawerOpen)
|
||||||
<MudDivider Vertical="true" />
|
{
|
||||||
}
|
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
||||||
<MudText Class="px-5 no-wrap">About</MudText>
|
<MudDivider Vertical="true" />
|
||||||
</MudToolBar>
|
}
|
||||||
|
<MudText Class="px-5 no-wrap">About</MudText>
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
|
||||||
<MudTabs Elevation="2" ApplyEffectsToContainer="true">
|
<div class="content-panel__body">
|
||||||
<MudTabPanel Text="About">
|
<MudTabs Elevation="2" ApplyEffectsToContainer="true">
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3">
|
<MudTabPanel Text="About">
|
||||||
|
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3 content-panel__container options-tab-contents">
|
||||||
<MudGrid Class="mt-0 mb-4">
|
<MudGrid Class="mt-0 mb-4">
|
||||||
<MudItem xs="12" sm="3" md="2" lg="2" xl="1" Class="d-flex justify-center">
|
<MudItem xs="12" sm="3" md="2" lg="2" xl="1" Class="d-flex justify-center">
|
||||||
<MudImage Src="images/mascot.png" Alt="Mascot" Class="ma-6"
|
<MudImage Src="images/mascot.png" Alt="Mascot" Class="ma-6"
|
||||||
@@ -60,7 +64,7 @@
|
|||||||
</MudContainer>
|
</MudContainer>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
<MudTabPanel Text="Authors">
|
<MudTabPanel Text="Authors">
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3">
|
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3 options-tab-contents">
|
||||||
<MudText Typo="Typo.h5" Class="py-1">Current maintainer</MudText>
|
<MudText Typo="Typo.h5" Class="py-1">Current maintainer</MudText>
|
||||||
|
|
||||||
<MudGrid Class="mt-0 mb-4">
|
<MudGrid Class="mt-0 mb-4">
|
||||||
@@ -108,7 +112,7 @@
|
|||||||
</MudContainer>
|
</MudContainer>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
<MudTabPanel Text="Special Thanks">
|
<MudTabPanel Text="Special Thanks">
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3">
|
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3 options-tab-contents">
|
||||||
<MudText Typo="Typo.body1" Class="py-1">I would first like to thank sourceforge.net for hosting qBittorrent project and for their support.</MudText>
|
<MudText Typo="Typo.body1" Class="py-1">I would first like to thank sourceforge.net for hosting qBittorrent project and for their support.</MudText>
|
||||||
<MudText Typo="Typo.body1" Class="py-1">I am pleased that people from all over the world are contributing to qBittorrent: Ishan Arora (India), Arnaud Demaizière (France) and Stephanos Antaris (Greece). Their help is greatly appreciated</MudText>
|
<MudText Typo="Typo.body1" Class="py-1">I am pleased that people from all over the world are contributing to qBittorrent: Ishan Arora (India), Arnaud Demaizière (France) and Stephanos Antaris (Greece). Their help is greatly appreciated</MudText>
|
||||||
<MudText Typo="Typo.body1" Class="py-1">I also want to thank Στέφανος Αντάρης (santaris@csd.auth.gr) and Mirco Chinelli (infinity89@fastwebmail.it) for working on Mac OS X packaging.</MudText>
|
<MudText Typo="Typo.body1" Class="py-1">I also want to thank Στέφανος Αντάρης (santaris@csd.auth.gr) and Mirco Chinelli (infinity89@fastwebmail.it) for working on Mac OS X packaging.</MudText>
|
||||||
@@ -118,7 +122,7 @@
|
|||||||
</MudContainer>
|
</MudContainer>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
<MudTabPanel Text="Translators">
|
<MudTabPanel Text="Translators">
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3">
|
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3 options-tab-contents">
|
||||||
<MudText Typo="Typo.body1" Class="py-1">
|
<MudText Typo="Typo.body1" Class="py-1">
|
||||||
I would like to thank the people who volunteered to Circle qBittorrent.<br>
|
I would like to thank the people who volunteered to Circle qBittorrent.<br>
|
||||||
Most of them Circled via <MudLink Target="https://www.transifex.com/sledgehammer999/qbittorrent/" Href="https://www.transifex.com/sledgehammer999/qbittorrent/">Transifex</MudLink> and some of them are mentioned below:<br>
|
Most of them Circled via <MudLink Target="https://www.transifex.com/sledgehammer999/qbittorrent/" Href="https://www.transifex.com/sledgehammer999/qbittorrent/">Transifex</MudLink> and some of them are mentioned below:<br>
|
||||||
@@ -168,7 +172,7 @@
|
|||||||
</MudContainer>
|
</MudContainer>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
<MudTabPanel Text="Licence">
|
<MudTabPanel Text="Licence">
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3">
|
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3 options-tab-contents">
|
||||||
<MudText Typo="Typo.body1" Class="py-1">
|
<MudText Typo="Typo.body1" Class="py-1">
|
||||||
The qBittorrent source code is licensed under the GNU General Public License, version 2 or (at your option) any later version (GPLv2+).
|
The qBittorrent source code is licensed under the GNU General Public License, version 2 or (at your option) any later version (GPLv2+).
|
||||||
However, this binary distribution is licensed under GNU General Public License, version 3 or (at your option) any later version (GPLv3+),
|
However, this binary distribution is licensed under GNU General Public License, version 3 or (at your option) any later version (GPLv3+),
|
||||||
@@ -1061,7 +1065,7 @@
|
|||||||
</MudContainer>
|
</MudContainer>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
<MudTabPanel Text="Software Used">
|
<MudTabPanel Text="Software Used">
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3 mb-3">
|
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3 mb-3 options-tab-contents">
|
||||||
<MudText Typo="Typo.body1" Class="py-1">qBittorrent was built with the following libraries:</MudText>
|
<MudText Typo="Typo.body1" Class="py-1">qBittorrent was built with the following libraries:</MudText>
|
||||||
|
|
||||||
<MudGrid Class="mt-1 mb-4">
|
<MudGrid Class="mt-1 mb-4">
|
||||||
@@ -1104,4 +1108,6 @@
|
|||||||
<MudText Typo="Typo.body1" Class="py-1">The free IP to Country Lite database by DB-IP is used for resolving the countries of peers. The database is licensed under the Creative Commons Attribution 4.0 International License (<MudLink Target="https://db-ip.com/" Href="https://db-ip.com/" rel="noopener ">https://db-ip.com/</MudLink>)</MudText>
|
<MudText Typo="Typo.body1" Class="py-1">The free IP to Country Lite database by DB-IP is used for resolving the countries of peers. The database is licensed under the Creative Commons Attribution 4.0 International License (<MudLink Target="https://db-ip.com/" Href="https://db-ip.com/" rel="noopener ">https://db-ip.com/</MudLink>)</MudText>
|
||||||
</MudContainer>
|
</MudContainer>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
</MudTabs>
|
</MudTabs>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,36 +1,41 @@
|
|||||||
@page "/blocks"
|
@page "/blocks"
|
||||||
@layout OtherLayout
|
@layout OtherLayout
|
||||||
|
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel">
|
||||||
@if (!DrawerOpen)
|
<div class="content-panel__toolbar">
|
||||||
{
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
@if (!DrawerOpen)
|
||||||
<MudDivider Vertical="true" />
|
{
|
||||||
}
|
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
||||||
<MudDivider Vertical="true" />
|
<MudDivider Vertical="true" />
|
||||||
<MudText Class="pl-5 no-wrap">Blocked IPs</MudText>
|
}
|
||||||
</MudToolBar>
|
<MudDivider Vertical="true" />
|
||||||
|
<MudText Class="pl-5 no-wrap">Blocked IPs</MudText>
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
<div class="content-panel__body">
|
||||||
|
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
|
||||||
|
<MudCardContent>
|
||||||
|
<EditForm Model="Model" OnSubmit="Submit">
|
||||||
|
<MudGrid>
|
||||||
|
<MudItem md="10">
|
||||||
|
<MudTextField T="string" Label="Criteria" @bind-Value="Model.Criteria" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem md="2">
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" FullWidth="true" Color="Color.Primary" EndIcon="@Icons.Material.Filled.Search" Variant="Variant.Filled" Class="mt-6">Filter</MudButton>
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
</EditForm>
|
||||||
|
</MudCardContent>
|
||||||
|
</MudCard>
|
||||||
|
|
||||||
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
|
<DynamicTable @ref="Table"
|
||||||
<MudCardContent>
|
T="Lantean.QBitTorrentClient.Models.PeerLog"
|
||||||
<EditForm Model="Model" OnSubmit="Submit">
|
ColumnDefinitions="Columns"
|
||||||
<MudGrid>
|
Items="Results"
|
||||||
<MudItem md="10">
|
MultiSelection="false"
|
||||||
<MudTextField T="string" Label="Criteria" @bind-Value="Model.Criteria" Variant="Variant.Outlined" />
|
SelectOnRowClick="false"
|
||||||
</MudItem>
|
RowClassFunc="RowClass"
|
||||||
<MudItem md="2">
|
Class="search-list content-panel__table" />
|
||||||
<MudButton ButtonType="ButtonType.Submit" FullWidth="true" Color="Color.Primary" EndIcon="@Icons.Material.Filled.Search" Variant="Variant.Filled" Class="mt-6">Filter</MudButton>
|
</div>
|
||||||
</MudItem>
|
</div>
|
||||||
</MudGrid>
|
|
||||||
</EditForm>
|
|
||||||
</MudCardContent>
|
|
||||||
</MudCard>
|
|
||||||
|
|
||||||
<DynamicTable @ref="Table"
|
|
||||||
T="Lantean.QBitTorrentClient.Models.PeerLog"
|
|
||||||
ColumnDefinitions="Columns"
|
|
||||||
Items="Results"
|
|
||||||
MultiSelection="false"
|
|
||||||
SelectOnRowClick="false"
|
|
||||||
RowClassFunc="RowClass"
|
|
||||||
Class="search-list" />
|
|
||||||
@@ -1,24 +1,30 @@
|
|||||||
@page "/categories"
|
@page "/categories"
|
||||||
@layout OtherLayout
|
@layout OtherLayout
|
||||||
|
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel">
|
||||||
@if (!DrawerOpen)
|
<div class="content-panel__toolbar">
|
||||||
{
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
@if (!DrawerOpen)
|
||||||
<MudDivider Vertical="true" />
|
{
|
||||||
}
|
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
||||||
<MudText Class="px-5 no-wrap">Categories</MudText>
|
<MudDivider Vertical="true" />
|
||||||
<MudDivider Vertical="true" />
|
}
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.PlaylistAdd" OnClick="AddCategory" title="Add Category" />
|
<MudText Class="px-5 no-wrap">Categories</MudText>
|
||||||
</MudToolBar>
|
<MudDivider Vertical="true" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.PlaylistAdd" OnClick="AddCategory" title="Add Category" />
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
|
||||||
<DynamicTable @ref="Table"
|
<div class="content-panel__body">
|
||||||
T="Category"
|
<DynamicTable @ref="Table"
|
||||||
ColumnDefinitions="Columns"
|
T="Category"
|
||||||
Items="Results"
|
ColumnDefinitions="Columns"
|
||||||
MultiSelection="false"
|
Items="Results"
|
||||||
SelectOnRowClick="false"
|
MultiSelection="false"
|
||||||
Class="details-list" />
|
SelectOnRowClick="false"
|
||||||
|
Class="details-list content-panel__table" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private RenderFragment<RowContext<Category>> ActionsColumn
|
private RenderFragment<RowContext<Category>> ActionsColumn
|
||||||
|
|||||||
@@ -1,41 +1,45 @@
|
|||||||
@page "/details/{hash}"
|
@page "/details/{hash}"
|
||||||
@layout DetailsLayout
|
@layout DetailsLayout
|
||||||
|
|
||||||
<div style="overflow-x: auto; white-space: nowrap; width: 100%;">
|
<div class="content-panel">
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel__toolbar content-panel__toolbar--scroll">
|
||||||
@if (!DrawerOpen)
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
{
|
@if (!DrawerOpen)
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
{
|
||||||
<MudDivider Vertical="true" />
|
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
||||||
}
|
<MudDivider Vertical="true" />
|
||||||
@if (Hash is not null)
|
}
|
||||||
{
|
@if (Hash is not null)
|
||||||
<TorrentActions RenderType="RenderType.InitialIconsOnly" Hashes="@([Hash])" Torrents="MainData.Torrents" Preferences="Preferences" />
|
{
|
||||||
}
|
<TorrentActions RenderType="RenderType.InitialIconsOnly" Hashes="@([Hash])" Torrents="MainData.Torrents" Preferences="Preferences" />
|
||||||
<MudDivider Vertical="true" />
|
}
|
||||||
<MudText Class="pl-5 no-wrap">@Name</MudText>
|
<MudDivider Vertical="true" />
|
||||||
</MudToolBar>
|
<MudText Class="pl-5 no-wrap">@Name</MudText>
|
||||||
</div>
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
|
||||||
@if (ShowTabs)
|
<div class="content-panel__body">
|
||||||
{
|
@if (ShowTabs)
|
||||||
<CascadingValue Value="RefreshInterval" Name="RefreshInterval">
|
{
|
||||||
<MudTabs Elevation="2" ApplyEffectsToContainer="true" @bind-ActivePanelIndex="ActiveTab" KeepPanelsAlive="true" Border="true">
|
<CascadingValue Value="RefreshInterval" Name="RefreshInterval">
|
||||||
<MudTabPanel Text="General">
|
<MudTabs Elevation="2" ApplyEffectsToContainer="true" @bind-ActivePanelIndex="ActiveTab" KeepPanelsAlive="true" Border="true">
|
||||||
<GeneralTab Hash="@Hash" Active="@(ActiveTab == 0)" />
|
<MudTabPanel Text="General">
|
||||||
</MudTabPanel>
|
<GeneralTab Hash="@Hash" Active="@(ActiveTab == 0)" />
|
||||||
<MudTabPanel Text="Trackers">
|
</MudTabPanel>
|
||||||
<TrackersTab Hash="@Hash" Active="@(ActiveTab == 1)" />
|
<MudTabPanel Text="Trackers">
|
||||||
</MudTabPanel>
|
<TrackersTab Hash="@Hash" Active="@(ActiveTab == 1)" />
|
||||||
<MudTabPanel Text="Peers">
|
</MudTabPanel>
|
||||||
<PeersTab Hash="@Hash" Active="@(ActiveTab == 2)" />
|
<MudTabPanel Text="Peers">
|
||||||
</MudTabPanel>
|
<PeersTab Hash="@Hash" Active="@(ActiveTab == 2)" />
|
||||||
<MudTabPanel Text="HTTP Sources">
|
</MudTabPanel>
|
||||||
<WebSeedsTab Hash="@Hash" Active="@(ActiveTab == 3)" />
|
<MudTabPanel Text="HTTP Sources">
|
||||||
</MudTabPanel>
|
<WebSeedsTab Hash="@Hash" Active="@(ActiveTab == 3)" />
|
||||||
<MudTabPanel Text="Content">
|
</MudTabPanel>
|
||||||
<FilesTab Hash="@Hash" Active="@(ActiveTab == 4)" />
|
<MudTabPanel Text="Content">
|
||||||
</MudTabPanel>
|
<FilesTab Hash="@Hash" Active="@(ActiveTab == 4)" />
|
||||||
</MudTabs>
|
</MudTabPanel>
|
||||||
</CascadingValue>
|
</MudTabs>
|
||||||
}
|
</CascadingValue>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,44 +1,49 @@
|
|||||||
@page "/log"
|
@page "/log"
|
||||||
@layout OtherLayout
|
@layout OtherLayout
|
||||||
|
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel">
|
||||||
@if (!DrawerOpen)
|
<div class="content-panel__toolbar">
|
||||||
{
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
@if (!DrawerOpen)
|
||||||
<MudDivider Vertical="true" />
|
{
|
||||||
}
|
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
||||||
<MudDivider Vertical="true" />
|
<MudDivider Vertical="true" />
|
||||||
<MudText Class="pl-5 no-wrap">Execution Log</MudText>
|
}
|
||||||
</MudToolBar>
|
<MudDivider Vertical="true" />
|
||||||
|
<MudText Class="pl-5 no-wrap">Execution Log</MudText>
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
<div class="content-panel__body">
|
||||||
|
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
|
||||||
|
<MudCardContent>
|
||||||
|
<EditForm Model="Model" OnSubmit="Submit">
|
||||||
|
<MudGrid>
|
||||||
|
<MudItem md="7">
|
||||||
|
<MudTextField T="string" Label="Criteria" @bind-Value="Model.Criteria" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem md="3">
|
||||||
|
<MudSelect @ref="CategoryMudSelect" T="string" Label="Categories" SelectedValues="Model.SelectedTypes" SelectedValuesChanged="SelectedValuesChanged" Variant="Variant.Outlined" MultiSelection="true" MultiSelectionTextFunc="GenerateSelectedText" SelectAll="true">
|
||||||
|
<MudSelectItem Value="@("Normal")">Normal</MudSelectItem>
|
||||||
|
<MudSelectItem Value="@("Info")">Info</MudSelectItem>
|
||||||
|
<MudSelectItem Value="@("Warning")">Warning</MudSelectItem>
|
||||||
|
<MudSelectItem Value="@("Critical")">Critical</MudSelectItem>
|
||||||
|
</MudSelect>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem md="2">
|
||||||
|
<MudButton ButtonType="ButtonType.Submit" FullWidth="true" Color="Color.Primary" EndIcon="@Icons.Material.Filled.Search" Variant="Variant.Filled" Class="mt-6">Filter</MudButton>
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
</EditForm>
|
||||||
|
</MudCardContent>
|
||||||
|
</MudCard>
|
||||||
|
|
||||||
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
|
<DynamicTable @ref="Table"
|
||||||
<MudCardContent>
|
T="Lantean.QBitTorrentClient.Models.Log"
|
||||||
<EditForm Model="Model" OnSubmit="Submit">
|
ColumnDefinitions="Columns"
|
||||||
<MudGrid>
|
Items="Results"
|
||||||
<MudItem md="7">
|
MultiSelection="false"
|
||||||
<MudTextField T="string" Label="Criteria" @bind-Value="Model.Criteria" Variant="Variant.Outlined" />
|
SelectOnRowClick="false"
|
||||||
</MudItem>
|
RowClassFunc="RowClass"
|
||||||
<MudItem md="3">
|
Class="search-list content-panel__table" />
|
||||||
<MudSelect @ref="CategoryMudSelect" T="string" Label="Categories" SelectedValues="Model.SelectedTypes" SelectedValuesChanged="SelectedValuesChanged" Variant="Variant.Outlined" MultiSelection="true" MultiSelectionTextFunc="GenerateSelectedText" SelectAll="true">
|
</div>
|
||||||
<MudSelectItem Value="@("Normal")">Normal</MudSelectItem>
|
</div>
|
||||||
<MudSelectItem Value="@("Info")">Info</MudSelectItem>
|
|
||||||
<MudSelectItem Value="@("Warning")">Warning</MudSelectItem>
|
|
||||||
<MudSelectItem Value="@("Critical")">Critical</MudSelectItem>
|
|
||||||
</MudSelect>
|
|
||||||
</MudItem>
|
|
||||||
<MudItem md="2">
|
|
||||||
<MudButton ButtonType="ButtonType.Submit" FullWidth="true" Color="Color.Primary" EndIcon="@Icons.Material.Filled.Search" Variant="Variant.Filled" Class="mt-6">Filter</MudButton>
|
|
||||||
</MudItem>
|
|
||||||
</MudGrid>
|
|
||||||
</EditForm>
|
|
||||||
</MudCardContent>
|
|
||||||
</MudCard>
|
|
||||||
|
|
||||||
<DynamicTable @ref="Table"
|
|
||||||
T="Lantean.QBitTorrentClient.Models.Log"
|
|
||||||
ColumnDefinitions="Columns"
|
|
||||||
Items="Results"
|
|
||||||
MultiSelection="false"
|
|
||||||
SelectOnRowClick="false"
|
|
||||||
RowClassFunc="RowClass"
|
|
||||||
Class="search-list" />
|
|
||||||
@@ -3,41 +3,63 @@
|
|||||||
|
|
||||||
<NavigationLock ConfirmExternalNavigation="@(UpdatePreferences is not null)" OnBeforeInternalNavigation="ValidateExit" />
|
<NavigationLock ConfirmExternalNavigation="@(UpdatePreferences is not null)" OnBeforeInternalNavigation="ValidateExit" />
|
||||||
|
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel">
|
||||||
@if (!DrawerOpen)
|
<div class="content-panel__toolbar">
|
||||||
{
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" />
|
@if (!DrawerOpen)
|
||||||
<MudDivider Vertical="true" />
|
{
|
||||||
}
|
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" />
|
||||||
<MudText Class="px-5 no-wrap">Settings</MudText>
|
<MudDivider Vertical="true" />
|
||||||
<MudDivider Vertical="true" />
|
}
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.Save" OnClick="Save" Disabled="@(LostConnection || UpdatePreferences is null)" />
|
<MudText Class="px-5 no-wrap">Settings</MudText>
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.Undo" OnClick="Undo" Disabled="@(LostConnection || UpdatePreferences is null)" />
|
<MudDivider Vertical="true" />
|
||||||
</MudToolBar>
|
<MudIconButton Icon="@Icons.Material.Outlined.Save" OnClick="Save" Disabled="@(LostConnection || UpdatePreferences is null)" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Outlined.Undo" OnClick="Undo" Disabled="@(LostConnection || UpdatePreferences is null)" />
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
|
||||||
<MudTabs Elevation="2" ApplyEffectsToContainer="true" @bind-ActivePanelIndex="ActiveTab" Border="true">
|
<div class="content-panel__body">
|
||||||
<MudTabPanel Text="Behaviour">
|
<MudTabs Elevation="2" ApplyEffectsToContainer="true" @bind-ActivePanelIndex="ActiveTab" Border="true">
|
||||||
<BehaviourOptions @ref="BehaviourOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
<MudTabPanel Text="Behaviour">
|
||||||
</MudTabPanel>
|
<div class="options-tab-contents">
|
||||||
<MudTabPanel Text="Downloads">
|
<BehaviourOptions @ref="BehaviourOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
||||||
<DownloadsOptions @ref="DownloadsOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
</div>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
<MudTabPanel Text="Connection">
|
<MudTabPanel Text="Downloads">
|
||||||
<ConnectionOptions @ref="ConnectionOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
<div class="options-tab-contents">
|
||||||
</MudTabPanel>
|
<DownloadsOptions @ref="DownloadsOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
||||||
<MudTabPanel Text="Speed">
|
</div>
|
||||||
<SpeedOptions @ref="SpeedOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
</MudTabPanel>
|
||||||
</MudTabPanel>
|
<MudTabPanel Text="Connection">
|
||||||
<MudTabPanel Text="BitTorrent">
|
<div class="options-tab-contents">
|
||||||
<BitTorrentOptions @ref="BitTorrentOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
<ConnectionOptions @ref="ConnectionOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
||||||
</MudTabPanel>
|
</div>
|
||||||
<MudTabPanel Text="RSS">
|
</MudTabPanel>
|
||||||
<RSSOptions @ref="RSSOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
<MudTabPanel Text="Speed">
|
||||||
</MudTabPanel>
|
<div class="options-tab-contents">
|
||||||
<MudTabPanel Text="Web UI">
|
<SpeedOptions @ref="SpeedOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
||||||
<WebUIOptions @ref="WebUIOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
</div>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
<MudTabPanel Text="Advanced">
|
<MudTabPanel Text="BitTorrent">
|
||||||
<AdvancedOptions @ref="AdvancedOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
<div class="options-tab-contents">
|
||||||
</MudTabPanel>
|
<BitTorrentOptions @ref="BitTorrentOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
||||||
</MudTabs>
|
</div>
|
||||||
|
</MudTabPanel>
|
||||||
|
<MudTabPanel Text="RSS">
|
||||||
|
<div class="options-tab-contents">
|
||||||
|
<RSSOptions @ref="RSSOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
||||||
|
</div>
|
||||||
|
</MudTabPanel>
|
||||||
|
<MudTabPanel Text="Web UI">
|
||||||
|
<div class="options-tab-contents">
|
||||||
|
<WebUIOptions @ref="WebUIOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
||||||
|
</div>
|
||||||
|
</MudTabPanel>
|
||||||
|
<MudTabPanel Text="Advanced">
|
||||||
|
<div class="options-tab-contents">
|
||||||
|
<AdvancedOptions @ref="AdvancedOptions" Preferences="Preferences" UpdatePreferences="@UpdatePreferences" PreferencesChanged="PreferencesChanged" />
|
||||||
|
</div>
|
||||||
|
</MudTabPanel>
|
||||||
|
</MudTabs>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,73 +1,79 @@
|
|||||||
@page "/rss"
|
@page "/rss"
|
||||||
@layout OtherLayout
|
@layout OtherLayout
|
||||||
|
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel">
|
||||||
@if (!DrawerOpen)
|
<div class="content-panel__toolbar">
|
||||||
{
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
@if (!DrawerOpen)
|
||||||
<MudDivider Vertical="true" />
|
|
||||||
}
|
|
||||||
<MudText Class="px-5 no-wrap">RSS</MudText>
|
|
||||||
<MudDivider Vertical="true" />
|
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.Subscriptions" OnClick="NewSubscription" title="New subscription" />
|
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.MarkEmailRead" OnClick="MarkAsRead" Disabled="@(SelectedFeed is null)" title="Mark items read" />
|
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.Update" OnClick="UpdateAll" title="Update all" />
|
|
||||||
<MudDivider Vertical="true" />
|
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.DownloadForOffline" OnClick="EditDownloadRules" title="Edit auto downloading rules" />
|
|
||||||
</MudToolBar>
|
|
||||||
|
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge">
|
|
||||||
<MudGrid Class="rss-contents">
|
|
||||||
<MudItem xs="4" Style="height: 100%">
|
|
||||||
<MudList T="string" SelectionMode="SelectionMode.SingleSelection" SelectedValue="SelectedFeed" SelectedValueChanged="SelectedFeedChanged" Dense>
|
|
||||||
<MudListItem Icon="@Icons.Material.Filled.MarkEmailUnread" Text="@($"Unread ({UnreadCount})")" Value="@("unread")" />
|
|
||||||
@foreach (var (key, feed) in Feeds)
|
|
||||||
{
|
|
||||||
<MudListItem Icon="@(feed.IsLoading ? Icons.Material.Filled.Sync : Icons.Material.Filled.Wifi)" Class="@(feed.IsLoading ? "spin-animation" : "")" Text="@($"{feed.Title} ({feed.UnreadCount})")" Value="@key" />
|
|
||||||
}
|
|
||||||
</MudList>
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="4" Style="height: 100%; overflow: auto">
|
|
||||||
@if (Articles.Count > 0)
|
|
||||||
{
|
{
|
||||||
<MudList T="string" SelectionMode="SelectionMode.SingleSelection" SelectedValue="SelectedArticle" SelectedValueChanged="SelectedArticleChanged" Dense>
|
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
||||||
@foreach (var article in Articles)
|
<MudDivider Vertical="true" />
|
||||||
|
}
|
||||||
|
<MudText Class="px-5 no-wrap">RSS</MudText>
|
||||||
|
<MudDivider Vertical="true" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Outlined.Subscriptions" OnClick="NewSubscription" title="New subscription" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Outlined.MarkEmailRead" OnClick="MarkAsRead" Disabled="@(SelectedFeed is null)" title="Mark items read" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Outlined.Update" OnClick="UpdateAll" title="Update all" />
|
||||||
|
<MudDivider Vertical="true" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Outlined.DownloadForOffline" OnClick="EditDownloadRules" title="Edit auto downloading rules" />
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-panel__body">
|
||||||
|
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="content-panel__container">
|
||||||
|
<MudGrid Class="rss-contents">
|
||||||
|
<MudItem xs="4" Style="height: 100%">
|
||||||
|
<MudList T="string" SelectionMode="SelectionMode.SingleSelection" SelectedValue="SelectedFeed" SelectedValueChanged="SelectedFeedChanged" Dense>
|
||||||
|
<MudListItem Icon="@Icons.Material.Filled.MarkEmailUnread" Text="@($"Unread ({UnreadCount})")" Value="@("unread")" />
|
||||||
|
@foreach (var (key, feed) in Feeds)
|
||||||
|
{
|
||||||
|
<MudListItem Icon="@(feed.IsLoading ? Icons.Material.Filled.Sync : Icons.Material.Filled.Wifi)" Class="@(feed.IsLoading ? "spin-animation" : "")" Text="@($"{feed.Title} ({feed.UnreadCount})")" Value="@key" />
|
||||||
|
}
|
||||||
|
</MudList>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="4" Style="height: 100%; overflow: auto">
|
||||||
|
@if (Articles.Count > 0)
|
||||||
{
|
{
|
||||||
<MudListItem Text="@article.Title" Value="article.Id" Icon="@Icons.Material.Filled.Check" IconColor="@(article.IsRead ? Color.Success : Color.Transparent)" />
|
<MudList T="string" SelectionMode="SelectionMode.SingleSelection" SelectedValue="SelectedArticle" SelectedValueChanged="SelectedArticleChanged" Dense>
|
||||||
|
@foreach (var article in Articles)
|
||||||
|
{
|
||||||
|
<MudListItem Text="@article.Title" Value="article.Id" Icon="@Icons.Material.Filled.Check" IconColor="@(article.IsRead ? Color.Success : Color.Transparent)" />
|
||||||
|
}
|
||||||
|
</MudList>
|
||||||
}
|
}
|
||||||
</MudList>
|
else
|
||||||
}
|
{
|
||||||
else
|
<MudSkeleton SkeletonType="SkeletonType.Rectangle" Height="100%" Animation="Animation.False" Width="100%" />
|
||||||
{
|
}
|
||||||
<MudSkeleton SkeletonType="SkeletonType.Rectangle" Height="100%" Animation="Animation.False" Width="100%" />
|
</MudItem>
|
||||||
}
|
<MudItem xs="4" Style="height: 100%">
|
||||||
</MudItem>
|
@if (Article is not null)
|
||||||
<MudItem xs="4" Style="height: 100%">
|
{
|
||||||
@if (Article is not null)
|
<MudCard>
|
||||||
{
|
<MudCardHeader>
|
||||||
<MudCard>
|
<CardHeaderContent>
|
||||||
<MudCardHeader>
|
<MudText Typo="Typo.h6" Style="overflow-wrap: anywhere">@Article.Title</MudText>
|
||||||
<CardHeaderContent>
|
</CardHeaderContent>
|
||||||
<MudText Typo="Typo.h6" Style="overflow-wrap: anywhere">@Article.Title</MudText>
|
<CardHeaderActions>
|
||||||
</CardHeaderContent>
|
<MudMenu Icon="@Icons.Material.Filled.MoreVert" Dense>
|
||||||
<CardHeaderActions>
|
<MudMenuItem Icon="@Icons.Material.Filled.Download" OnClick="c => DownloadItem(Article.TorrentURL)" title="Download">Download</MudMenuItem>
|
||||||
<MudMenu Icon="@Icons.Material.Filled.MoreVert" Dense>
|
<MudMenuItem Icon="@Icons.Material.Filled.Link" Href="@Article.TorrentURL" Target="@Article.TorrentURL" title="Download">Open torrent URL</MudMenuItem>
|
||||||
<MudMenuItem Icon="@Icons.Material.Filled.Download" OnClick="c => DownloadItem(Article.TorrentURL)" title="Download">Download</MudMenuItem>
|
</MudMenu>
|
||||||
<MudMenuItem Icon="@Icons.Material.Filled.Link" Href="@Article.TorrentURL" Target="@Article.TorrentURL" title="Download">Open torrent URL</MudMenuItem>
|
</CardHeaderActions>
|
||||||
</MudMenu>
|
</MudCardHeader>
|
||||||
</CardHeaderActions>
|
|
||||||
</MudCardHeader>
|
|
||||||
|
|
||||||
<MudCardContent>
|
<MudCardContent>
|
||||||
<MudText Typo="Typo.subtitle2">@Article.Date</MudText>
|
<MudText Typo="Typo.subtitle2">@Article.Date</MudText>
|
||||||
<MudText Typo="Typo.body1">@Article.Description</MudText>
|
<MudText Typo="Typo.body1">@Article.Description</MudText>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<MudSkeleton SkeletonType="SkeletonType.Rectangle" Height="100%" Animation="Animation.False" Width="100%" />
|
<MudSkeleton SkeletonType="SkeletonType.Rectangle" Height="100%" Animation="Animation.False" Width="100%" />
|
||||||
}
|
}
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudContainer>
|
</MudContainer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,62 +1,67 @@
|
|||||||
@page "/search"
|
@page "/search"
|
||||||
@layout OtherLayout
|
@layout OtherLayout
|
||||||
|
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel">
|
||||||
@if (!DrawerOpen)
|
<div class="content-panel__toolbar">
|
||||||
{
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
@if (!DrawerOpen)
|
||||||
<MudDivider Vertical="true" />
|
{
|
||||||
}
|
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
||||||
<MudDivider Vertical="true" />
|
<MudDivider Vertical="true" />
|
||||||
<MudText Class="pl-5 no-wrap">Search</MudText>
|
}
|
||||||
</MudToolBar>
|
<MudDivider Vertical="true" />
|
||||||
|
<MudText Class="pl-5 no-wrap">Search</MudText>
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
<div class="content-panel__body">
|
||||||
|
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
|
||||||
|
<MudCardContent>
|
||||||
|
<EditForm Model="Model" OnValidSubmit="DoSearch">
|
||||||
|
<MudGrid>
|
||||||
|
<MudItem xs="12" md="4">
|
||||||
|
<MudTextField T="string" Label="Criteria" @bind-Value="Model.SearchText" Variant="Variant.Outlined" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" md="3">
|
||||||
|
<MudSelect T="string" Label="Categories" @bind-Value="Model.SelectedCategory" Variant="Variant.Outlined">
|
||||||
|
@foreach (var (value, name) in Categories)
|
||||||
|
{
|
||||||
|
<MudSelectItem Value="value">@name</MudSelectItem>
|
||||||
|
if (value == "all")
|
||||||
|
{
|
||||||
|
<MudDivider />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</MudSelect>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" md="3">
|
||||||
|
<MudSelect T="string" Label="Plugins" @bind-Value="Model.SelectedPlugin" Variant="Variant.Outlined">
|
||||||
|
<MudSelectItem Value="@("all")">All</MudSelectItem>
|
||||||
|
@if (Plugins.Count > 0)
|
||||||
|
{
|
||||||
|
<MudDivider />
|
||||||
|
|
||||||
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
|
}
|
||||||
<MudCardContent>
|
@foreach (var (value, name) in Plugins)
|
||||||
<EditForm Model="Model" OnValidSubmit="DoSearch">
|
{
|
||||||
<MudGrid>
|
<MudSelectItem Value="value">@name</MudSelectItem>
|
||||||
<MudItem xs="12" md="4">
|
}
|
||||||
<MudTextField T="string" Label="Criteria" @bind-Value="Model.SearchText" Variant="Variant.Outlined" />
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" md="3">
|
<MudItem xs="12" md="2">
|
||||||
<MudSelect T="string" Label="Categories" @bind-Value="Model.SelectedCategory" Variant="Variant.Outlined">
|
<MudButton ButtonType="ButtonType.Submit" FullWidth="true" Color="Color.Primary" EndIcon="@Icons.Material.Filled.Search" Variant="Variant.Filled" Class="mt-6">@(_searchId is null ? "Search" : "Stop")</MudButton>
|
||||||
@foreach (var (value, name) in Categories)
|
</MudItem>
|
||||||
{
|
|
||||||
<MudSelectItem Value="value">@name</MudSelectItem>
|
</MudGrid>
|
||||||
if (value == "all")
|
</EditForm>
|
||||||
{
|
</MudCardContent>
|
||||||
<MudDivider />
|
</MudCard>
|
||||||
}
|
|
||||||
}
|
|
||||||
</MudSelect>
|
|
||||||
</MudItem>
|
|
||||||
<MudItem xs="12" md="3">
|
|
||||||
<MudSelect T="string" Label="Plugins" @bind-Value="Model.SelectedPlugin" Variant="Variant.Outlined">
|
|
||||||
<MudSelectItem Value="@("all")">All</MudSelectItem>
|
|
||||||
@if (Plugins.Count > 0)
|
|
||||||
{
|
|
||||||
<MudDivider />
|
|
||||||
|
|
||||||
}
|
<DynamicTable @ref="Table"
|
||||||
@foreach (var (value, name) in Plugins)
|
T="Lantean.QBitTorrentClient.Models.SearchResult"
|
||||||
{
|
ColumnDefinitions="Columns"
|
||||||
<MudSelectItem Value="value">@name</MudSelectItem>
|
Items="Results"
|
||||||
}
|
MultiSelection="false"
|
||||||
</MudSelect>
|
SelectOnRowClick="false"
|
||||||
</MudItem>
|
Class="search-list content-panel__table" />
|
||||||
<MudItem xs="12" md="2">
|
</div>
|
||||||
<MudButton ButtonType="ButtonType.Submit" FullWidth="true" Color="Color.Primary" EndIcon="@Icons.Material.Filled.Search" Variant="Variant.Filled" Class="mt-6">@(_searchId is null ? "Search" : "Stop")</MudButton>
|
</div>
|
||||||
</MudItem>
|
|
||||||
|
|
||||||
</MudGrid>
|
|
||||||
</EditForm>
|
|
||||||
</MudCardContent>
|
|
||||||
</MudCard>
|
|
||||||
|
|
||||||
<DynamicTable @ref="Table"
|
|
||||||
T="Lantean.QBitTorrentClient.Models.SearchResult"
|
|
||||||
ColumnDefinitions="Columns"
|
|
||||||
Items="Results"
|
|
||||||
MultiSelection="false"
|
|
||||||
SelectOnRowClick="false"
|
|
||||||
Class="search-list" />
|
|
||||||
@@ -1,62 +1,68 @@
|
|||||||
@page "/statistics"
|
@page "/statistics"
|
||||||
@layout OtherLayout
|
@layout OtherLayout
|
||||||
|
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel">
|
||||||
@if (!DrawerOpen)
|
<div class="content-panel__toolbar">
|
||||||
{
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
@if (!DrawerOpen)
|
||||||
<MudDivider Vertical="true" />
|
{
|
||||||
}
|
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
||||||
<MudDivider Vertical="true" />
|
<MudDivider Vertical="true" />
|
||||||
<MudText Class="pl-5 no-wrap">Statistics</MudText>
|
}
|
||||||
</MudToolBar>
|
<MudDivider Vertical="true" />
|
||||||
|
<MudText Class="pl-5 no-wrap">Statistics</MudText>
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="details-tab-contents">
|
<div class="content-panel__body">
|
||||||
<MudText Typo="Typo.subtitle2" Class="pt-6">User statistics</MudText>
|
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="details-tab-contents content-panel__container">
|
||||||
<MudGrid>
|
<MudText Typo="Typo.subtitle2" Class="pt-6">User statistics</MudText>
|
||||||
<MudItem xs="12">
|
<MudGrid>
|
||||||
<MudField Label="All-time uploaded">@DisplayHelpers.Size(ServerState?.AllTimeUploaded)</MudField>
|
<MudItem xs="12">
|
||||||
</MudItem>
|
<MudField Label="All-time uploaded">@DisplayHelpers.Size(ServerState?.AllTimeUploaded)</MudField>
|
||||||
<MudItem xs="12">
|
</MudItem>
|
||||||
<MudField Label="All-time downloaded">@DisplayHelpers.Size(ServerState?.AllTimeDownloaded)</MudField>
|
<MudItem xs="12">
|
||||||
</MudItem>
|
<MudField Label="All-time downloaded">@DisplayHelpers.Size(ServerState?.AllTimeDownloaded)</MudField>
|
||||||
<MudItem xs="12">
|
</MudItem>
|
||||||
<MudField Label="All-time share ratio">@DisplayHelpers.EmptyIfNull(ServerState?.GlobalRatio, format: "0.00")</MudField>
|
<MudItem xs="12">
|
||||||
</MudItem>
|
<MudField Label="All-time share ratio">@DisplayHelpers.EmptyIfNull(ServerState?.GlobalRatio, format: "0.00")</MudField>
|
||||||
<MudItem xs="12">
|
</MudItem>
|
||||||
<MudField Label="Session waste">@DisplayHelpers.Size(ServerState?.TotalWastedSession)</MudField>
|
<MudItem xs="12">
|
||||||
</MudItem>
|
<MudField Label="Session waste">@DisplayHelpers.Size(ServerState?.TotalWastedSession)</MudField>
|
||||||
<MudItem xs="12">
|
</MudItem>
|
||||||
<MudField Label="Connected peers">@DisplayHelpers.EmptyIfNull(ServerState?.TotalPeerConnections)</MudField>
|
<MudItem xs="12">
|
||||||
</MudItem>
|
<MudField Label="Connected peers">@DisplayHelpers.EmptyIfNull(ServerState?.TotalPeerConnections)</MudField>
|
||||||
</MudGrid>
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
|
||||||
<MudText Typo="Typo.subtitle2" Class="pt-6">Cache statistics</MudText>
|
<MudText Typo="Typo.subtitle2" Class="pt-6">Cache statistics</MudText>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudField Label="Read cache hits">@DisplayHelpers.Percentage(ServerState?.ReadCacheHits)</MudField>
|
<MudField Label="Read cache hits">@DisplayHelpers.Percentage(ServerState?.ReadCacheHits)</MudField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudField Label="Total buffer size">@DisplayHelpers.Size(ServerState?.TotalBuffersSize)</MudField>
|
<MudField Label="Total buffer size">@DisplayHelpers.Size(ServerState?.TotalBuffersSize)</MudField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
|
|
||||||
<MudText Typo="Typo.subtitle2" Class="pt-6">Performance statistics</MudText>
|
<MudText Typo="Typo.subtitle2" Class="pt-6">Performance statistics</MudText>
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudField Label="Write cache overload">@DisplayHelpers.Percentage(ServerState?.WriteCacheOverload)</MudField>
|
<MudField Label="Write cache overload">@DisplayHelpers.Percentage(ServerState?.WriteCacheOverload)</MudField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudField Label="Read cache overload">@DisplayHelpers.Percentage(ServerState?.ReadCacheOverload)</MudField>
|
<MudField Label="Read cache overload">@DisplayHelpers.Percentage(ServerState?.ReadCacheOverload)</MudField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudField Label="Queued I/O jobs">@DisplayHelpers.EmptyIfNull(ServerState?.QueuedIOJobs)</MudField>
|
<MudField Label="Queued I/O jobs">@DisplayHelpers.EmptyIfNull(ServerState?.QueuedIOJobs)</MudField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudField Label="Average time in queue">@DisplayHelpers.EmptyIfNull(ServerState?.AverageTimeQueue, suffix: "ms")</MudField>
|
<MudField Label="Average time in queue">@DisplayHelpers.EmptyIfNull(ServerState?.AverageTimeQueue, suffix: "ms")</MudField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
<MudField Label="Total queued size">@DisplayHelpers.Size(ServerState?.TotalQueuedSize)</MudField>
|
<MudField Label="Total queued size">@DisplayHelpers.Size(ServerState?.TotalQueuedSize)</MudField>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudContainer>
|
</MudContainer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,24 +1,30 @@
|
|||||||
@page "/tags"
|
@page "/tags"
|
||||||
@layout OtherLayout
|
@layout OtherLayout
|
||||||
|
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel">
|
||||||
@if (!DrawerOpen)
|
<div class="content-panel__toolbar">
|
||||||
{
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
@if (!DrawerOpen)
|
||||||
<MudDivider Vertical="true" />
|
{
|
||||||
}
|
<MudIconButton Icon="@Icons.Material.Outlined.NavigateBefore" OnClick="NavigateBack" title="Back to torrent list" />
|
||||||
<MudText Class="px-5 no-wrap">Tags</MudText>
|
<MudDivider Vertical="true" />
|
||||||
<MudDivider Vertical="true" />
|
}
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.NewLabel" OnClick="AddTag" title="Add Tag" />
|
<MudText Class="px-5 no-wrap">Tags</MudText>
|
||||||
</MudToolBar>
|
<MudDivider Vertical="true" />
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.NewLabel" OnClick="AddTag" title="Add Tag" />
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
|
||||||
<DynamicTable @ref="Table"
|
<div class="content-panel__body">
|
||||||
T="string"
|
<DynamicTable @ref="Table"
|
||||||
ColumnDefinitions="Columns"
|
T="string"
|
||||||
Items="Results"
|
ColumnDefinitions="Columns"
|
||||||
MultiSelection="false"
|
Items="Results"
|
||||||
SelectOnRowClick="false"
|
MultiSelection="false"
|
||||||
Class="details-list" />
|
SelectOnRowClick="false"
|
||||||
|
Class="details-list content-panel__table" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private RenderFragment<RowContext<string>> ActionsColumn
|
private RenderFragment<RowContext<string>> ActionsColumn
|
||||||
|
|||||||
@@ -1,44 +1,47 @@
|
|||||||
@page "/"
|
@page "/"
|
||||||
@layout ListLayout
|
@layout ListLayout
|
||||||
|
|
||||||
<ContextMenu @ref="ContextMenu" Dense="true" RelativeWidth="DropdownWidth.Ignore" AdjustmentX="-242" AdjustmentY="0">
|
<MudMenu @ref="ContextMenu" Dense="true" RelativeWidth="DropdownWidth.Ignore" PositionAtCursor="true" ListClass="unselectable" PopoverClass="unselectable">
|
||||||
<MudMenuItem Icon="@Icons.Material.Outlined.Info" IconColor="Color.Inherit" OnClick="ShowTorrentContextMenu">View torrent details</MudMenuItem>
|
<MudMenuItem Icon="@Icons.Material.Outlined.Info" IconColor="Color.Inherit" OnClick="ShowTorrentContextMenu">View torrent details</MudMenuItem>
|
||||||
<MudDivider />
|
<MudDivider />
|
||||||
<TorrentActions RenderType="RenderType.MenuItems" Hashes="GetContextMenuTargetHashes()" PrimaryHash="@(ContextMenuItem?.Hash)" Torrents="MainData.Torrents" Preferences="Preferences" />
|
<TorrentActions RenderType="RenderType.MenuItems" Hashes="GetContextMenuTargetHashes()" PrimaryHash="@(ContextMenuItem?.Hash)" Torrents="MainData.Torrents" Preferences="Preferences" />
|
||||||
</ContextMenu>
|
</MudMenu>
|
||||||
|
|
||||||
<div style="overflow-x: auto; white-space: nowrap; width: 100%;">
|
<div class="content-panel">
|
||||||
<MudToolBar Gutters="false" Dense="true">
|
<div class="content-panel__toolbar content-panel__toolbar--scroll">
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.AddLink" OnClick="AddTorrentLink" title="Add torrent link" />
|
<MudToolBar Gutters="false" Dense="true">
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.AddCircle" OnClick="AddTorrentFile" title="Add torrent file" />
|
<MudIconButton Icon="@Icons.Material.Outlined.AddLink" OnClick="AddTorrentLink" title="Add torrent link" />
|
||||||
<MudDivider Vertical="true" />
|
<MudIconButton Icon="@Icons.Material.Outlined.AddCircle" OnClick="AddTorrentFile" title="Add torrent file" />
|
||||||
<TorrentActions RenderType="RenderType.InitialIconsOnly" Hashes="GetSelectedTorrentsHashes()" Torrents="MainData.Torrents" Preferences="Preferences" />
|
<MudDivider Vertical="true" />
|
||||||
<MudDivider Vertical="true" />
|
<TorrentActions RenderType="RenderType.InitialIconsOnly" Hashes="GetSelectedTorrentsHashes()" Torrents="MainData.Torrents" Preferences="Preferences" />
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.Info" Color="Color.Inherit" Disabled="@(!ToolbarButtonsEnabled)" OnClick="ShowTorrentToolbar" title="View torrent details" />
|
<MudDivider Vertical="true" />
|
||||||
<MudIconButton Icon="@Icons.Material.Outlined.ViewColumn" Color="Color.Inherit" OnClick="ColumnOptions" title="Choose Columns" />
|
<MudIconButton Icon="@Icons.Material.Outlined.Info" Color="Color.Inherit" Disabled="@(!ToolbarButtonsEnabled)" OnClick="ShowTorrentToolbar" title="View torrent details" />
|
||||||
<MudSpacer />
|
<MudIconButton Icon="@Icons.Material.Outlined.ViewColumn" Color="Color.Inherit" OnClick="ColumnOptions" title="Choose Columns" />
|
||||||
<MudTextField Value="SearchText" TextChanged="SearchTextChanged" Immediate="true" DebounceInterval="1000" Placeholder="Filter torrent list" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
|
<MudSpacer />
|
||||||
</MudToolBar>
|
<MudTextField Value="SearchText" TextChanged="SearchTextChanged" Immediate="true" DebounceInterval="1000" Placeholder="Filter torrent list" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
|
||||||
|
</MudToolBar>
|
||||||
|
</div>
|
||||||
|
<div class="content-panel__body">
|
||||||
|
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="ma-0 pa-0 content-panel__container">
|
||||||
|
<DynamicTable
|
||||||
|
@ref="Table"
|
||||||
|
T="Torrent"
|
||||||
|
Class="torrent-list content-panel__table"
|
||||||
|
ColumnDefinitions="Columns"
|
||||||
|
Items="Torrents"
|
||||||
|
OnRowClick="RowClick"
|
||||||
|
MultiSelection="true"
|
||||||
|
SelectOnRowClick="true"
|
||||||
|
SelectedItemsChanged="SelectedItemsChanged"
|
||||||
|
SortColumnChanged="SortColumnChangedHandler"
|
||||||
|
SortDirectionChanged="SortDirectionChangedHandler"
|
||||||
|
OnTableDataContextMenu="TableDataContextMenu"
|
||||||
|
OnTableDataLongPress="TableDataLongPress"
|
||||||
|
/>
|
||||||
|
</MudContainer>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="ma-0 pa-0">
|
|
||||||
<DynamicTable
|
|
||||||
@ref="Table"
|
|
||||||
T="Torrent"
|
|
||||||
Class="torrent-list"
|
|
||||||
ColumnDefinitions="Columns"
|
|
||||||
Items="Torrents"
|
|
||||||
OnRowClick="RowClick"
|
|
||||||
MultiSelection="true"
|
|
||||||
SelectOnRowClick="true"
|
|
||||||
SelectedItemsChanged="SelectedItemsChanged"
|
|
||||||
SortColumnChanged="SortColumnChangedHandler"
|
|
||||||
SortDirectionChanged="SortDirectionChangedHandler"
|
|
||||||
OnTableDataContextMenu="TableDataContextMenu"
|
|
||||||
OnTableDataLongPress="TableDataLongPress"
|
|
||||||
/>
|
|
||||||
</MudContainer>
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private static RenderFragment<RowContext<Torrent>> ProgressBarColumn
|
private static RenderFragment<RowContext<Torrent>> ProgressBarColumn
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,11 +35,17 @@ namespace Lantean.QBTMud.Pages
|
|||||||
public QBitTorrentClient.Models.Preferences? Preferences { get; set; }
|
public QBitTorrentClient.Models.Preferences? Preferences { get; set; }
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
public IEnumerable<Torrent>? Torrents { get; set; }
|
public IReadOnlyList<Torrent>? Torrents { get; set; }
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
public MainData MainData { get; set; } = default!;
|
public MainData MainData { get; set; } = default!;
|
||||||
|
|
||||||
|
[CascadingParameter(Name = "LostConnection")]
|
||||||
|
public bool LostConnection { get; set; }
|
||||||
|
|
||||||
|
[CascadingParameter(Name = "TorrentsVersion")]
|
||||||
|
public int TorrentsVersion { get; set; }
|
||||||
|
|
||||||
[CascadingParameter(Name = "SearchTermChanged")]
|
[CascadingParameter(Name = "SearchTermChanged")]
|
||||||
public EventCallback<string> SearchTermChanged { get; set; }
|
public EventCallback<string> SearchTermChanged { get; set; }
|
||||||
|
|
||||||
@@ -56,13 +62,23 @@ namespace Lantean.QBTMud.Pages
|
|||||||
|
|
||||||
protected HashSet<Torrent> SelectedItems { get; set; } = [];
|
protected HashSet<Torrent> SelectedItems { get; set; } = [];
|
||||||
|
|
||||||
protected bool ToolbarButtonsEnabled => SelectedItems.Count > 0;
|
protected bool ToolbarButtonsEnabled => _toolbarButtonsEnabled;
|
||||||
|
|
||||||
protected DynamicTable<Torrent>? Table { get; set; }
|
protected DynamicTable<Torrent>? Table { get; set; }
|
||||||
|
|
||||||
protected Torrent? ContextMenuItem { get; set; }
|
protected Torrent? ContextMenuItem { get; set; }
|
||||||
|
|
||||||
protected ContextMenu? ContextMenu { get; set; }
|
protected MudMenu? ContextMenu { get; set; }
|
||||||
|
|
||||||
|
private object? _lastRenderedTorrents;
|
||||||
|
private QBitTorrentClient.Models.Preferences? _lastPreferences;
|
||||||
|
private bool _lastLostConnection;
|
||||||
|
private bool _hasRendered;
|
||||||
|
private int _lastSelectionCount;
|
||||||
|
private int _lastTorrentsVersion = -1;
|
||||||
|
private bool _pendingSelectionChange;
|
||||||
|
|
||||||
|
private bool _toolbarButtonsEnabled;
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
@@ -73,9 +89,81 @@ namespace Lantean.QBTMud.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool ShouldRender()
|
||||||
|
{
|
||||||
|
if (!_hasRendered)
|
||||||
|
{
|
||||||
|
_hasRendered = true;
|
||||||
|
_lastRenderedTorrents = Torrents;
|
||||||
|
_lastPreferences = Preferences;
|
||||||
|
_lastLostConnection = LostConnection;
|
||||||
|
_lastTorrentsVersion = TorrentsVersion;
|
||||||
|
_lastSelectionCount = SelectedItems.Count;
|
||||||
|
_toolbarButtonsEnabled = _lastSelectionCount > 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pendingSelectionChange)
|
||||||
|
{
|
||||||
|
_pendingSelectionChange = false;
|
||||||
|
_lastSelectionCount = SelectedItems.Count;
|
||||||
|
_toolbarButtonsEnabled = _lastSelectionCount > 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastTorrentsVersion != TorrentsVersion)
|
||||||
|
{
|
||||||
|
_lastTorrentsVersion = TorrentsVersion;
|
||||||
|
_lastRenderedTorrents = Torrents;
|
||||||
|
_lastPreferences = Preferences;
|
||||||
|
_lastLostConnection = LostConnection;
|
||||||
|
_lastSelectionCount = SelectedItems.Count;
|
||||||
|
_toolbarButtonsEnabled = _lastSelectionCount > 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ReferenceEquals(_lastRenderedTorrents, Torrents))
|
||||||
|
{
|
||||||
|
_lastRenderedTorrents = Torrents;
|
||||||
|
_lastPreferences = Preferences;
|
||||||
|
_lastLostConnection = LostConnection;
|
||||||
|
_lastSelectionCount = SelectedItems.Count;
|
||||||
|
_toolbarButtonsEnabled = _lastSelectionCount > 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ReferenceEquals(_lastPreferences, Preferences))
|
||||||
|
{
|
||||||
|
_lastPreferences = Preferences;
|
||||||
|
_lastSelectionCount = SelectedItems.Count;
|
||||||
|
_toolbarButtonsEnabled = _lastSelectionCount > 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastLostConnection != LostConnection)
|
||||||
|
{
|
||||||
|
_lastLostConnection = LostConnection;
|
||||||
|
_lastSelectionCount = SelectedItems.Count;
|
||||||
|
_toolbarButtonsEnabled = _lastSelectionCount > 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastSelectionCount != SelectedItems.Count)
|
||||||
|
{
|
||||||
|
_lastSelectionCount = SelectedItems.Count;
|
||||||
|
_toolbarButtonsEnabled = _lastSelectionCount > 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected void SelectedItemsChanged(HashSet<Torrent> selectedItems)
|
protected void SelectedItemsChanged(HashSet<Torrent> selectedItems)
|
||||||
{
|
{
|
||||||
SelectedItems = selectedItems;
|
SelectedItems = selectedItems;
|
||||||
|
_toolbarButtonsEnabled = SelectedItems.Count > 0;
|
||||||
|
_pendingSelectionChange = true;
|
||||||
|
InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task SortDirectionChangedHandler(SortDirection sortDirection)
|
protected async Task SortDirectionChangedHandler(SortDirection sortDirection)
|
||||||
@@ -185,7 +273,9 @@ namespace Lantean.QBTMud.Pages
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ContextMenu.ToggleMenuAsync(eventArgs);
|
var normalizedEventArgs = eventArgs.NormalizeForContextMenu();
|
||||||
|
|
||||||
|
await ContextMenu.OpenMenuAsync(normalizedEventArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IEnumerable<ColumnDefinition<Torrent>> Columns => ColumnsDefinitions.Where(c => c.Id != "#" || Preferences?.QueueingEnabled == true);
|
protected IEnumerable<ColumnDefinition<Torrent>> Columns => ColumnsDefinitions.Where(c => c.Id != "#" || Preferences?.QueueingEnabled == true);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Blazored.LocalStorage;
|
using Blazored.LocalStorage;
|
||||||
using Lantean.QBitTorrentClient;
|
using Lantean.QBitTorrentClient;
|
||||||
using Lantean.QBTMud.Services;
|
using Lantean.QBTMud.Services;
|
||||||
using Microsoft.AspNetCore.Components.Web;
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ namespace Lantean.QBTMud.Services
|
|||||||
|
|
||||||
Torrent CreateTorrent(string hash, QBitTorrentClient.Models.Torrent torrent);
|
Torrent CreateTorrent(string hash, QBitTorrentClient.Models.Torrent torrent);
|
||||||
|
|
||||||
void MergeMainData(QBitTorrentClient.Models.MainData mainData, MainData torrentList);
|
bool MergeMainData(QBitTorrentClient.Models.MainData mainData, MainData torrentList, out bool filterChanged);
|
||||||
|
|
||||||
PeerList CreatePeerList(QBitTorrentClient.Models.TorrentPeers torrentPeers);
|
PeerList CreatePeerList(QBitTorrentClient.Models.TorrentPeers torrentPeers);
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ namespace Lantean.QBTMud.Services
|
|||||||
|
|
||||||
Dictionary<string, ContentItem> CreateContentsList(IReadOnlyList<QBitTorrentClient.Models.FileData> files);
|
Dictionary<string, ContentItem> CreateContentsList(IReadOnlyList<QBitTorrentClient.Models.FileData> files);
|
||||||
|
|
||||||
void MergeContentsList(IReadOnlyList<QBitTorrentClient.Models.FileData> files, Dictionary<string, ContentItem> contents);
|
bool MergeContentsList(IReadOnlyList<QBitTorrentClient.Models.FileData> files, Dictionary<string, ContentItem> contents);
|
||||||
|
|
||||||
QBitTorrentClient.Models.UpdatePreferences MergePreferences(QBitTorrentClient.Models.UpdatePreferences? original, QBitTorrentClient.Models.UpdatePreferences changed);
|
QBitTorrentClient.Models.UpdatePreferences MergePreferences(QBitTorrentClient.Models.UpdatePreferences? original, QBitTorrentClient.Models.UpdatePreferences changed);
|
||||||
|
|
||||||
|
|||||||
@@ -65,15 +65,11 @@ code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mud-appbar.mud-appbar-fixed-bottom {
|
.mud-appbar.mud-appbar-fixed-bottom {
|
||||||
height: 35px;
|
height: calc(var(--app-status-bar-height) + env(safe-area-inset-bottom, 0px));
|
||||||
}
|
|
||||||
|
|
||||||
.mud-main-content {
|
|
||||||
padding-bottom: 35px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mud-drawer-fixed.mud-drawer-mini.mud-drawer-clipped-always, .mud-drawer-fixed.mud-drawer-persistent:not(.mud-drawer-clipped-never), .mud-drawer-fixed.mud-drawer-responsive.mud-drawer-clipped-always, .mud-drawer-fixed.mud-drawer-temporary.mud-drawer-clipped-always {
|
.mud-drawer-fixed.mud-drawer-mini.mud-drawer-clipped-always, .mud-drawer-fixed.mud-drawer-persistent:not(.mud-drawer-clipped-never), .mud-drawer-fixed.mud-drawer-responsive.mud-drawer-clipped-always, .mud-drawer-fixed.mud-drawer-temporary.mud-drawer-clipped-always {
|
||||||
height: calc(100% - var(--mud-appbar-height) - 35px);
|
height: calc(100% - var(--mud-appbar-height) - (var(--app-status-bar-height) + env(safe-area-inset-bottom, 0px)));
|
||||||
}
|
}
|
||||||
|
|
||||||
.w-100 {
|
.w-100 {
|
||||||
@@ -154,25 +150,91 @@ code {
|
|||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.torrent-list .mud-table-container {
|
/*. Layout helpers */
|
||||||
height: calc(100vh - 160px);
|
.content-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-list .mud-table-container {
|
.content-panel__toolbar {
|
||||||
height: calc(100vh - 245px);
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.details-list .mud-table-container {
|
.content-panel__toolbar--scroll {
|
||||||
height: calc(100vh - 200px);
|
overflow-x: auto;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.details-tab-contents {
|
.content-panel__body {
|
||||||
height: calc(100vh - 200px);
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-panel__container {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-panel__table {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-panel__table .mud-table-container {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-panel__body > .mud-tabs {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-top: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-panel__body > .mud-tabs .mud-tabs-tabbar {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-panel__body > .mud-tabs .mud-tabs-panels {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-top: 0;
|
||||||
|
margin-top: -1px;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-panel__body .mud-tabs .mud-tabs-panels .mud-tab-panel {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.torrent-list .mud-table-container,
|
||||||
|
.file-list .mud-table-container,
|
||||||
|
.details-list .mud-table-container,
|
||||||
.search-list .mud-table-container {
|
.search-list .mud-table-container {
|
||||||
height: calc(100vh - 260px);
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.details-tab-contents,
|
||||||
|
.options-tab-contents,
|
||||||
|
.rss-contents {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.log-normal td {
|
tr.log-normal td {
|
||||||
@@ -220,10 +282,6 @@ td .folder-button {
|
|||||||
padding: 6px 16px 6px 16px !important;
|
padding: 6px 16px 6px 16px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rss-contents {
|
|
||||||
height: calc(100vh - 149px);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
0% {
|
0% {
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
@@ -255,4 +313,117 @@ td .folder-button {
|
|||||||
|
|
||||||
.mud-popover .mud-divider:last-child {
|
.mud-popover .mud-divider:last-child {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
:root {
|
||||||
|
--app-viewport-height: 100vh;
|
||||||
|
--app-status-bar-height: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (height: 100svh) {
|
||||||
|
:root {
|
||||||
|
--app-viewport-height: 100svh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports ((height: 100dvh) and (not (height: 100svh))) {
|
||||||
|
:root {
|
||||||
|
--app-viewport-height: 100dvh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: var(--app-viewport-height);
|
||||||
|
min-height: var(--app-viewport-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
overscroll-behavior: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app,
|
||||||
|
.mud-layout {
|
||||||
|
height: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-shell {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: var(--app-viewport-height);
|
||||||
|
min-height: var(--app-viewport-height);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-shell__body {
|
||||||
|
display: flex;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-shell__sidebar {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-shell__main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: var(--mud-appbar-height) 0 calc(var(--app-status-bar-height) + env(safe-area-inset-bottom, 0px));
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-shell__status-bar.mud-appbar {
|
||||||
|
flex: 0 0 calc(var(--app-status-bar-height) + env(safe-area-inset-bottom, 0px));
|
||||||
|
height: calc(var(--app-status-bar-height) + env(safe-area-inset-bottom, 0px));
|
||||||
|
width: 100%;
|
||||||
|
background-color: var(--mud-palette-dark-lighten);
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-shell__status-bar .mud-toolbar {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding-bottom: env(safe-area-inset-bottom, 0px);
|
||||||
|
background-color: inherit;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (-webkit-touch-callout: none) {
|
||||||
|
:root {
|
||||||
|
--app-viewport-height: -webkit-fill-available;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: -webkit-fill-available;
|
||||||
|
min-height: -webkit-fill-available;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-shell {
|
||||||
|
height: -webkit-fill-available;
|
||||||
|
min-height: -webkit-fill-available;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Tab bar gap fix */
|
||||||
|
.content-panel__body > .mud-tabs .mud-tabs-tabbar {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
border-bottom-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-panel__body > .mud-tabs .mud-tabs-tabbar .mud-tabs-wrapper {
|
||||||
|
margin-bottom: -1px;
|
||||||
|
}
|
||||||
|
.content-panel__body > .mud-tabs .mud-tabs-tabbar .mud-tabs-slider {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,4 +37,4 @@
|
|||||||
<script src="./js/interop.js"></script>
|
<script src="./js/interop.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -5,4 +5,4 @@
|
|||||||
// * @author John Doherty <www.johndoherty.info>
|
// * @author John Doherty <www.johndoherty.info>
|
||||||
// * @license MIT
|
// * @license MIT
|
||||||
// */
|
// */
|
||||||
!function (e, t) { "use strict"; var n = null, a = "PointerEvent" in e || e.navigator && "msPointerEnabled" in e.navigator, i = "ontouchstart" in e || navigator.MaxTouchPoints > 0 || navigator.msMaxTouchPoints > 0, o = a ? "pointerdown" : i ? "touchstart" : "mousedown", r = a ? "pointerup" : i ? "touchend" : "mouseup", m = a ? "pointermove" : i ? "touchmove" : "mousemove", u = a ? "pointerleave" : i ? "touchleave" : "mouseleave", s = 0, c = 0, l = 10, v = 10; function f(e) { p(), e = function (e) { if (void 0 !== e.changedTouches) return e.changedTouches[0]; return e }(e), this.dispatchEvent(new CustomEvent("longpress", { bubbles: !0, cancelable: !0, detail: { clientX: e.clientX, clientY: e.clientY, offsetX: e.offsetX, offsetY: e.offsetY, pageX: e.pageX, pageY: e.pageY }, clientX: e.clientX, clientY: e.clientY, offsetX: e.offsetX, offsetY: e.offsetY, pageX: e.pageX, pageY: e.pageY, screenX: e.screenX, screenY: e.screenY })) || t.addEventListener("click", function e(n) { t.removeEventListener("click", e, !0), function (e) { e.stopImmediatePropagation(), e.preventDefault(), e.stopPropagation() }(n) }, !0) } function d(a) { p(a); var i = a.target, o = parseInt(function (e, n, a) { for (; e && e !== t.documentElement;) { var i = e.getAttribute(n); if (i) return i; e = e.parentNode } return a }(i, "data-long-press-delay", "400"), 10); n = function (t, n) { if (!(e.requestAnimationFrame || e.webkitRequestAnimationFrame || e.mozRequestAnimationFrame && e.mozCancelRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame)) return e.setTimeout(t, n); var a = (new Date).getTime(), i = {}, o = function () { (new Date).getTime() - a >= n ? t.call() : i.value = requestAnimFrame(o) }; return i.value = requestAnimFrame(o), i }(f.bind(i, a), o) } function p(t) { var a; (a = n) && (e.cancelAnimationFrame ? e.cancelAnimationFrame(a.value) : e.webkitCancelAnimationFrame ? e.webkitCancelAnimationFrame(a.value) : e.webkitCancelRequestAnimationFrame ? e.webkitCancelRequestAnimationFrame(a.value) : e.mozCancelRequestAnimationFrame ? e.mozCancelRequestAnimationFrame(a.value) : e.oCancelRequestAnimationFrame ? e.oCancelRequestAnimationFrame(a.value) : e.msCancelRequestAnimationFrame ? e.msCancelRequestAnimationFrame(a.value) : clearTimeout(a)), n = null } "function" != typeof e.CustomEvent && (e.CustomEvent = function (e, n) { n = n || { bubbles: !1, cancelable: !1, detail: void 0 }; var a = t.createEvent("CustomEvent"); return a.initCustomEvent(e, n.bubbles, n.cancelable, n.detail), a }, e.CustomEvent.prototype = e.Event.prototype), e.requestAnimFrame = e.requestAnimationFrame || e.webkitRequestAnimationFrame || e.mozRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame || function (t) { e.setTimeout(t, 1e3 / 60) }, t.addEventListener(r, p, !0), t.addEventListener(u, p, !0), t.addEventListener(m, function (e) { var t = Math.abs(s - e.clientX), n = Math.abs(c - e.clientY); (t >= l || n >= v) && p() }, !0), t.addEventListener("wheel", p, !0), t.addEventListener("scroll", p, !0), t.addEventListener(o, function (e) { s = e.clientX, c = e.clientY, d(e) }, !0) }(window, document);
|
!function (e, t) { "use strict"; var n = null, a = "PointerEvent" in e || e.navigator && "msPointerEnabled" in e.navigator, i = "ontouchstart" in e || navigator.MaxTouchPoints > 0 || navigator.msMaxTouchPoints > 0, o = a ? "pointerdown" : i ? "touchstart" : "mousedown", r = a ? "pointerup" : i ? "touchend" : "mouseup", m = a ? "pointermove" : i ? "touchmove" : "mousemove", u = a ? "pointerleave" : i ? "touchleave" : "mouseleave", s = 0, c = 0, l = 10, v = 10; function f(e) { p(), e = function (e) { if (void 0 !== e.changedTouches) return e.changedTouches[0]; return e }(e); var n = new CustomEvent("longpress", { bubbles: !0, cancelable: !0, detail: { clientX: e.clientX, clientY: e.clientY, offsetX: e.offsetX, offsetY: e.offsetY, pageX: e.pageX, pageY: e.pageY }, clientX: e.clientX, clientY: e.clientY, offsetX: e.offsetX, offsetY: e.offsetY, pageX: e.pageX, pageY: e.pageY, screenX: e.screenX, screenY: e.screenY }); n.__longPress = !0, this.dispatchEvent(n) || t.addEventListener("click", function e(n) { t.removeEventListener("click", e, !0), function (e) { e.stopImmediatePropagation(), e.preventDefault(), e.stopPropagation() }(n) }, !0) } function d(a) { p(a); var i = a.target, o = parseInt(function (e, n, a) { for (; e && e !== t.documentElement;) { var i = e.getAttribute(n); if (i) return i; e = e.parentNode } return a }(i, "data-long-press-delay", "400"), 10); n = function (t, n) { if (!(e.requestAnimationFrame || e.webkitRequestAnimationFrame || e.mozRequestAnimationFrame && e.mozCancelRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame)) return e.setTimeout(t, n); var a = (new Date).getTime(), i = {}, o = function () { (new Date).getTime() - a >= n ? t.call() : i.value = requestAnimFrame(o) }; return i.value = requestAnimFrame(o), i }(f.bind(i, a), o) } function p(t) { var a; (a = n) && (e.cancelAnimationFrame ? e.cancelAnimationFrame(a.value) : e.webkitCancelAnimationFrame ? e.webkitCancelAnimationFrame(a.value) : e.webkitCancelRequestAnimationFrame ? e.webkitCancelRequestAnimationFrame(a.value) : e.mozCancelRequestAnimationFrame ? e.mozCancelRequestAnimationFrame(a.value) : e.oCancelRequestAnimationFrame ? e.oCancelRequestAnimationFrame(a.value) : e.msCancelRequestAnimationFrame ? e.msCancelRequestAnimationFrame(a.value) : clearTimeout(a)), n = null } "function" != typeof e.CustomEvent && (e.CustomEvent = function (e, n) { n = n || { bubbles: !1, cancelable: !1, detail: void 0 }; var a = t.createEvent("CustomEvent"); return a.initCustomEvent(e, n.bubbles, n.cancelable, n.detail), a }, e.CustomEvent.prototype = e.Event.prototype), e.requestAnimFrame = e.requestAnimationFrame || e.webkitRequestAnimationFrame || e.mozRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame || function (t) { e.setTimeout(t, 1e3 / 60) }, t.addEventListener(r, p, !0), t.addEventListener(u, p, !0), t.addEventListener(m, function (e) { var t = Math.abs(s - e.clientX), n = Math.abs(c - e.clientY); (t >= l || n >= v) && p() }, !0), t.addEventListener("wheel", p, !0), t.addEventListener("scroll", p, !0), t.addEventListener(o, function (e) { s = e.clientX, c = e.clientY, d(e) }, !0) }(window, document);
|
||||||
@@ -7,6 +7,11 @@ namespace Lantean.QBitTorrentClient.Converters
|
|||||||
{
|
{
|
||||||
public override IReadOnlyList<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
public override IReadOnlyList<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
{
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.Null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (reader.TokenType != JsonTokenType.String)
|
if (reader.TokenType != JsonTokenType.String)
|
||||||
{
|
{
|
||||||
throw new JsonException("Must be of type string.");
|
throw new JsonException("Must be of type string.");
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Lantean.QBitTorrentClient.Converters
|
|||||||
{
|
{
|
||||||
writer.WriteNumberValue(0);
|
writer.WriteNumberValue(0);
|
||||||
}
|
}
|
||||||
else if (value.IsDefaltFolder)
|
else if (value.IsDefaultFolder)
|
||||||
{
|
{
|
||||||
writer.WriteNumberValue(1);
|
writer.WriteNumberValue(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,13 +24,13 @@
|
|||||||
public bool? UseDownloadPath { get; set; }
|
public bool? UseDownloadPath { get; set; }
|
||||||
|
|
||||||
public string? Category { get; set; }
|
public string? Category { get; set; }
|
||||||
|
|
||||||
public IEnumerable<string>? Tags { get; set; }
|
public IEnumerable<string>? Tags { get; set; }
|
||||||
|
|
||||||
public string? RenameTorrent { get; set; }
|
public string? RenameTorrent { get; set; }
|
||||||
|
|
||||||
public long? UploadLimit { get; set; }
|
public long? UploadLimit { get; set; }
|
||||||
|
|
||||||
public long? DownloadLimit { get; set; }
|
public long? DownloadLimit { get; set; }
|
||||||
|
|
||||||
public float? RatioLimit { get; set; }
|
public float? RatioLimit { get; set; }
|
||||||
|
|||||||
@@ -429,24 +429,12 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("add_to_top_of_queue")]
|
[JsonPropertyName("add_to_top_of_queue")]
|
||||||
public bool AddToTopOfQueue { get; }
|
public bool AddToTopOfQueue { get; }
|
||||||
|
|
||||||
[JsonPropertyName("add_stopped_enabled")]
|
|
||||||
public bool AddStoppedEnabled { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("add_trackers")]
|
[JsonPropertyName("add_trackers")]
|
||||||
public string AddTrackers { get; }
|
public string AddTrackers { get; }
|
||||||
|
|
||||||
[JsonPropertyName("add_trackers_enabled")]
|
[JsonPropertyName("add_trackers_enabled")]
|
||||||
public bool AddTrackersEnabled { get; }
|
public bool AddTrackersEnabled { get; }
|
||||||
|
|
||||||
[JsonPropertyName("add_trackers_from_url_enabled")]
|
|
||||||
public bool AddTrackersFromUrlEnabled { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("add_trackers_url")]
|
|
||||||
public string? AddTrackersUrl { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("add_trackers_url_list")]
|
|
||||||
public string? AddTrackersUrlList { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("alt_dl_limit")]
|
[JsonPropertyName("alt_dl_limit")]
|
||||||
public int AltDlLimit { get; }
|
public int AltDlLimit { get; }
|
||||||
|
|
||||||
@@ -462,9 +450,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("announce_ip")]
|
[JsonPropertyName("announce_ip")]
|
||||||
public string AnnounceIp { get; }
|
public string AnnounceIp { get; }
|
||||||
|
|
||||||
[JsonPropertyName("announce_port")]
|
|
||||||
public int AnnouncePort { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("announce_to_all_tiers")]
|
[JsonPropertyName("announce_to_all_tiers")]
|
||||||
public bool AnnounceToAllTiers { get; }
|
public bool AnnounceToAllTiers { get; }
|
||||||
|
|
||||||
@@ -525,12 +510,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("category_changed_tmm_enabled")]
|
[JsonPropertyName("category_changed_tmm_enabled")]
|
||||||
public bool CategoryChangedTmmEnabled { get; }
|
public bool CategoryChangedTmmEnabled { get; }
|
||||||
|
|
||||||
[JsonPropertyName("confirm_torrent_deletion")]
|
|
||||||
public bool ConfirmTorrentDeletion { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("confirm_torrent_recheck")]
|
|
||||||
public bool ConfirmTorrentRecheck { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("checking_memory_use")]
|
[JsonPropertyName("checking_memory_use")]
|
||||||
public int CheckingMemoryUse { get; }
|
public int CheckingMemoryUse { get; }
|
||||||
|
|
||||||
@@ -546,9 +525,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("current_network_interface")]
|
[JsonPropertyName("current_network_interface")]
|
||||||
public string CurrentNetworkInterface { get; }
|
public string CurrentNetworkInterface { get; }
|
||||||
|
|
||||||
[JsonPropertyName("delete_torrent_content_files")]
|
|
||||||
public bool DeleteTorrentContentFiles { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("dht")]
|
[JsonPropertyName("dht")]
|
||||||
public bool Dht { get; }
|
public bool Dht { get; }
|
||||||
|
|
||||||
@@ -657,9 +633,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("hashing_threads")]
|
[JsonPropertyName("hashing_threads")]
|
||||||
public int HashingThreads { get; }
|
public int HashingThreads { get; }
|
||||||
|
|
||||||
[JsonPropertyName("hostname_cache_ttl")]
|
|
||||||
public int HostnameCacheTtl { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("i2p_address")]
|
[JsonPropertyName("i2p_address")]
|
||||||
public string I2pAddress { get; }
|
public string I2pAddress { get; }
|
||||||
|
|
||||||
@@ -687,9 +660,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("idn_support_enabled")]
|
[JsonPropertyName("idn_support_enabled")]
|
||||||
public bool IdnSupportEnabled { get; }
|
public bool IdnSupportEnabled { get; }
|
||||||
|
|
||||||
[JsonPropertyName("ignore_ssl_errors")]
|
|
||||||
public bool IgnoreSslErrors { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("incomplete_files_ext")]
|
[JsonPropertyName("incomplete_files_ext")]
|
||||||
public bool IncompleteFilesExt { get; }
|
public bool IncompleteFilesExt { get; }
|
||||||
|
|
||||||
@@ -918,9 +888,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("save_resume_data_interval")]
|
[JsonPropertyName("save_resume_data_interval")]
|
||||||
public int SaveResumeDataInterval { get; }
|
public int SaveResumeDataInterval { get; }
|
||||||
|
|
||||||
[JsonPropertyName("save_statistics_interval")]
|
|
||||||
public int SaveStatisticsInterval { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("scan_dirs")]
|
[JsonPropertyName("scan_dirs")]
|
||||||
public Dictionary<string, SaveLocation> ScanDirs { get; }
|
public Dictionary<string, SaveLocation> ScanDirs { get; }
|
||||||
|
|
||||||
@@ -969,21 +936,12 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("socket_send_buffer_size")]
|
[JsonPropertyName("socket_send_buffer_size")]
|
||||||
public int SocketSendBufferSize { get; }
|
public int SocketSendBufferSize { get; }
|
||||||
|
|
||||||
[JsonPropertyName("ssl_enabled")]
|
|
||||||
public bool SslEnabled { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("ssl_listen_port")]
|
|
||||||
public int SslListenPort { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("ssrf_mitigation")]
|
[JsonPropertyName("ssrf_mitigation")]
|
||||||
public bool SsrfMitigation { get; }
|
public bool SsrfMitigation { get; }
|
||||||
|
|
||||||
[JsonPropertyName("start_paused_enabled")]
|
[JsonPropertyName("start_paused_enabled")]
|
||||||
public bool StartPausedEnabled { get; }
|
public bool StartPausedEnabled { get; }
|
||||||
|
|
||||||
[JsonPropertyName("status_bar_external_ip")]
|
|
||||||
public bool StatusBarExternalIp { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("stop_tracker_timeout")]
|
[JsonPropertyName("stop_tracker_timeout")]
|
||||||
public int StopTrackerTimeout { get; }
|
public int StopTrackerTimeout { get; }
|
||||||
|
|
||||||
@@ -999,9 +957,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("torrent_content_layout")]
|
[JsonPropertyName("torrent_content_layout")]
|
||||||
public string TorrentContentLayout { get; }
|
public string TorrentContentLayout { get; }
|
||||||
|
|
||||||
[JsonPropertyName("torrent_content_remove_option")]
|
|
||||||
public string? TorrentContentRemoveOption { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("torrent_file_size_limit")]
|
[JsonPropertyName("torrent_file_size_limit")]
|
||||||
public int TorrentFileSizeLimit { get; }
|
public int TorrentFileSizeLimit { get; }
|
||||||
|
|
||||||
@@ -1032,9 +987,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("use_subcategories")]
|
[JsonPropertyName("use_subcategories")]
|
||||||
public bool UseSubcategories { get; }
|
public bool UseSubcategories { get; }
|
||||||
|
|
||||||
[JsonPropertyName("use_unwanted_folder")]
|
|
||||||
public bool UseUnwantedFolder { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("utp_tcp_mixed_mode")]
|
[JsonPropertyName("utp_tcp_mixed_mode")]
|
||||||
public int UtpTcpMixedMode { get; }
|
public int UtpTcpMixedMode { get; }
|
||||||
|
|
||||||
@@ -1044,9 +996,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("web_ui_address")]
|
[JsonPropertyName("web_ui_address")]
|
||||||
public string WebUiAddress { get; }
|
public string WebUiAddress { get; }
|
||||||
|
|
||||||
[JsonPropertyName("web_ui_api_key")]
|
|
||||||
public string? WebUiApiKey { get; init; }
|
|
||||||
|
|
||||||
[JsonPropertyName("web_ui_ban_duration")]
|
[JsonPropertyName("web_ui_ban_duration")]
|
||||||
public int WebUiBanDuration { get; }
|
public int WebUiBanDuration { get; }
|
||||||
|
|
||||||
@@ -1101,4 +1050,4 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("web_ui_password")]
|
[JsonPropertyName("web_ui_password")]
|
||||||
public string WebUiPassword { get; }
|
public string WebUiPassword { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
{
|
{
|
||||||
public bool IsWatchedFolder { get; set; }
|
public bool IsWatchedFolder { get; set; }
|
||||||
|
|
||||||
public bool IsDefaltFolder { get; set; }
|
public bool IsDefaultFolder { get; set; }
|
||||||
|
|
||||||
public string? SavePath { get; set; }
|
public string? SavePath { get; set; }
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
{
|
{
|
||||||
return new SaveLocation
|
return new SaveLocation
|
||||||
{
|
{
|
||||||
IsDefaltFolder = true
|
IsDefaultFolder = true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
{
|
{
|
||||||
return new SaveLocation
|
return new SaveLocation
|
||||||
{
|
{
|
||||||
IsDefaltFolder = true
|
IsDefaultFolder = true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (IsDefaltFolder)
|
else if (IsDefaultFolder)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
long downloadLimit,
|
long downloadLimit,
|
||||||
long downloadSpeed,
|
long downloadSpeed,
|
||||||
long downloadSpeedAverage,
|
long downloadSpeedAverage,
|
||||||
int estimatedTimeOfArrival,
|
long estimatedTimeOfArrival,
|
||||||
long lastSeen,
|
long lastSeen,
|
||||||
int connections,
|
int connections,
|
||||||
int connectionsLimit,
|
int connectionsLimit,
|
||||||
@@ -104,7 +104,7 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
public long DownloadSpeedAverage { get; }
|
public long DownloadSpeedAverage { get; }
|
||||||
|
|
||||||
[JsonPropertyName("eta")]
|
[JsonPropertyName("eta")]
|
||||||
public int EstimatedTimeOfArrival { get; }
|
public long EstimatedTimeOfArrival { get; }
|
||||||
|
|
||||||
[JsonPropertyName("last_seen")]
|
[JsonPropertyName("last_seen")]
|
||||||
public long LastSeen { get; }
|
public long LastSeen { get; }
|
||||||
|
|||||||
@@ -7,24 +7,12 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("add_to_top_of_queue")]
|
[JsonPropertyName("add_to_top_of_queue")]
|
||||||
public bool? AddToTopOfQueue { get; set; }
|
public bool? AddToTopOfQueue { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("add_stopped_enabled")]
|
|
||||||
public bool? AddStoppedEnabled { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("add_trackers")]
|
[JsonPropertyName("add_trackers")]
|
||||||
public string? AddTrackers { get; set; }
|
public string? AddTrackers { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("add_trackers_enabled")]
|
[JsonPropertyName("add_trackers_enabled")]
|
||||||
public bool? AddTrackersEnabled { get; set; }
|
public bool? AddTrackersEnabled { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("add_trackers_from_url_enabled")]
|
|
||||||
public bool? AddTrackersFromUrlEnabled { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("add_trackers_url")]
|
|
||||||
public string? AddTrackersUrl { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("add_trackers_url_list")]
|
|
||||||
public string? AddTrackersUrlList { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("alt_dl_limit")]
|
[JsonPropertyName("alt_dl_limit")]
|
||||||
public int? AltDlLimit { get; set; }
|
public int? AltDlLimit { get; set; }
|
||||||
|
|
||||||
@@ -40,9 +28,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("announce_ip")]
|
[JsonPropertyName("announce_ip")]
|
||||||
public string? AnnounceIp { get; set; }
|
public string? AnnounceIp { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("announce_port")]
|
|
||||||
public int? AnnouncePort { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("announce_to_all_tiers")]
|
[JsonPropertyName("announce_to_all_tiers")]
|
||||||
public bool? AnnounceToAllTiers { get; set; }
|
public bool? AnnounceToAllTiers { get; set; }
|
||||||
|
|
||||||
@@ -103,12 +88,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("category_changed_tmm_enabled")]
|
[JsonPropertyName("category_changed_tmm_enabled")]
|
||||||
public bool? CategoryChangedTmmEnabled { get; set; }
|
public bool? CategoryChangedTmmEnabled { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("confirm_torrent_deletion")]
|
|
||||||
public bool? ConfirmTorrentDeletion { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("confirm_torrent_recheck")]
|
|
||||||
public bool? ConfirmTorrentRecheck { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("checking_memory_use")]
|
[JsonPropertyName("checking_memory_use")]
|
||||||
public int? CheckingMemoryUse { get; set; }
|
public int? CheckingMemoryUse { get; set; }
|
||||||
|
|
||||||
@@ -124,9 +103,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("current_network_interface")]
|
[JsonPropertyName("current_network_interface")]
|
||||||
public string? CurrentNetworkInterface { get; set; }
|
public string? CurrentNetworkInterface { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("delete_torrent_content_files")]
|
|
||||||
public bool? DeleteTorrentContentFiles { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("dht")]
|
[JsonPropertyName("dht")]
|
||||||
public bool? Dht { get; set; }
|
public bool? Dht { get; set; }
|
||||||
|
|
||||||
@@ -235,9 +211,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("hashing_threads")]
|
[JsonPropertyName("hashing_threads")]
|
||||||
public int? HashingThreads { get; set; }
|
public int? HashingThreads { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("hostname_cache_ttl")]
|
|
||||||
public int? HostnameCacheTtl { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("i2p_address")]
|
[JsonPropertyName("i2p_address")]
|
||||||
public string? I2pAddress { get; set; }
|
public string? I2pAddress { get; set; }
|
||||||
|
|
||||||
@@ -265,9 +238,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("idn_support_enabled")]
|
[JsonPropertyName("idn_support_enabled")]
|
||||||
public bool? IdnSupportEnabled { get; set; }
|
public bool? IdnSupportEnabled { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("ignore_ssl_errors")]
|
|
||||||
public bool? IgnoreSslErrors { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("incomplete_files_ext")]
|
[JsonPropertyName("incomplete_files_ext")]
|
||||||
public bool? IncompleteFilesExt { get; set; }
|
public bool? IncompleteFilesExt { get; set; }
|
||||||
|
|
||||||
@@ -496,9 +466,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("save_resume_data_interval")]
|
[JsonPropertyName("save_resume_data_interval")]
|
||||||
public int? SaveResumeDataInterval { get; set; }
|
public int? SaveResumeDataInterval { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("save_statistics_interval")]
|
|
||||||
public int? SaveStatisticsInterval { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("scan_dirs")]
|
[JsonPropertyName("scan_dirs")]
|
||||||
public Dictionary<string, SaveLocation>? ScanDirs { get; set; }
|
public Dictionary<string, SaveLocation>? ScanDirs { get; set; }
|
||||||
|
|
||||||
@@ -547,21 +514,12 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("socket_send_buffer_size")]
|
[JsonPropertyName("socket_send_buffer_size")]
|
||||||
public int? SocketSendBufferSize { get; set; }
|
public int? SocketSendBufferSize { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("ssl_enabled")]
|
|
||||||
public bool? SslEnabled { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("ssl_listen_port")]
|
|
||||||
public int? SslListenPort { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("ssrf_mitigation")]
|
[JsonPropertyName("ssrf_mitigation")]
|
||||||
public bool? SsrfMitigation { get; set; }
|
public bool? SsrfMitigation { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("start_paused_enabled")]
|
[JsonPropertyName("start_paused_enabled")]
|
||||||
public bool? StartPausedEnabled { get; set; }
|
public bool? StartPausedEnabled { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("status_bar_external_ip")]
|
|
||||||
public bool? StatusBarExternalIp { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("stop_tracker_timeout")]
|
[JsonPropertyName("stop_tracker_timeout")]
|
||||||
public int? StopTrackerTimeout { get; set; }
|
public int? StopTrackerTimeout { get; set; }
|
||||||
|
|
||||||
@@ -577,9 +535,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("torrent_content_layout")]
|
[JsonPropertyName("torrent_content_layout")]
|
||||||
public string? TorrentContentLayout { get; set; }
|
public string? TorrentContentLayout { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("torrent_content_remove_option")]
|
|
||||||
public string? TorrentContentRemoveOption { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("torrent_file_size_limit")]
|
[JsonPropertyName("torrent_file_size_limit")]
|
||||||
public int? TorrentFileSizeLimit { get; set; }
|
public int? TorrentFileSizeLimit { get; set; }
|
||||||
|
|
||||||
@@ -610,9 +565,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("use_subcategories")]
|
[JsonPropertyName("use_subcategories")]
|
||||||
public bool? UseSubcategories { get; set; }
|
public bool? UseSubcategories { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("use_unwanted_folder")]
|
|
||||||
public bool? UseUnwantedFolder { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("utp_tcp_mixed_mode")]
|
[JsonPropertyName("utp_tcp_mixed_mode")]
|
||||||
public int? UtpTcpMixedMode { get; set; }
|
public int? UtpTcpMixedMode { get; set; }
|
||||||
|
|
||||||
@@ -622,9 +574,6 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("web_ui_address")]
|
[JsonPropertyName("web_ui_address")]
|
||||||
public string? WebUiAddress { get; set; }
|
public string? WebUiAddress { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("web_ui_api_key")]
|
|
||||||
public string? WebUiApiKey { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("web_ui_ban_duration")]
|
[JsonPropertyName("web_ui_ban_duration")]
|
||||||
public int? WebUiBanDuration { get; set; }
|
public int? WebUiBanDuration { get; set; }
|
||||||
|
|
||||||
@@ -679,4 +628,4 @@ namespace Lantean.QBitTorrentClient.Models
|
|||||||
[JsonPropertyName("web_ui_password")]
|
[JsonPropertyName("web_ui_password")]
|
||||||
public string? WebUiPassword { get; set; }
|
public string? WebUiPassword { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
5
global.json
Normal file
5
global.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "9.0.306"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user