mirror of
				https://github.com/lantean-code/qbtmud.git
				synced 2025-10-31 12:03:42 +00:00 
			
		
		
		
	Compare commits
	
		
			11 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | a29e64fc1b | ||
|  | e55955c75e | ||
|  | aa80396862 | ||
|  | 30ced3293c | ||
|  | c54f73a517 | ||
|  | bad509e40f | ||
|  | 6a0796ef20 | ||
|  | dc4b515763 | ||
|  | 938702a7b3 | ||
|  | 6ca1c6edd4 | ||
|  | 24eb5cf5e9 | 
							
								
								
									
										4
									
								
								.github/workflows/dotnet.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/dotnet.yml
									
									
									
									
										vendored
									
									
								
							| @@ -21,12 +21,12 @@ jobs: | |||||||
|       - name: Setup .NET |       - name: Setup .NET | ||||||
|         uses: actions/setup-dotnet@v4 |         uses: actions/setup-dotnet@v4 | ||||||
|         with: |         with: | ||||||
|           dotnet-version: '8.0.x' |           dotnet-version: '9.0.x' | ||||||
|  |  | ||||||
|       - name: Install GitVersion |       - name: Install GitVersion | ||||||
|         uses: gittools/actions/gitversion/setup@v3.0.0 |         uses: gittools/actions/gitversion/setup@v3.0.0 | ||||||
|         with: |         with: | ||||||
|           versionSpec: '6.x' |           versionSpec: '6.0.0' | ||||||
|  |  | ||||||
|       - name: Determine Version |       - name: Determine Version | ||||||
|         id: gitversion |         id: gitversion | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| <Project Sdk="Microsoft.NET.Sdk"> | <Project Sdk="Microsoft.NET.Sdk"> | ||||||
|  |  | ||||||
|   <PropertyGroup> |   <PropertyGroup> | ||||||
|     <TargetFramework>net8.0</TargetFramework> |     <TargetFramework>net9.0</TargetFramework> | ||||||
|     <ImplicitUsings>enable</ImplicitUsings> |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
|     <Nullable>enable</Nullable> |     <Nullable>enable</Nullable> | ||||||
|  |  | ||||||
| @@ -10,11 +10,14 @@ | |||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="FluentAssertions" Version="6.12.1" /> | 	<PackageReference Include="FluentAssertions" Version="7.1.0" AllowedVersions="[5.0.0,7.*.*)" /> | ||||||
|     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" /> |     <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.1" /> | ||||||
|  |     <PackageReference Include="Microsoft.Extensions.Http" Version="9.0.1" /> | ||||||
|  |     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" /> | ||||||
|  |     <PackageReference Include="MudBlazor" Version="8.2.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.2" /> |     <PackageReference Include="xunit" Version="2.9.3" /> | ||||||
|     <PackageReference Include="xunit.runner.visualstudio" Version="2.8.2"> |     <PackageReference Include="xunit.runner.visualstudio" Version="3.0.1"> | ||||||
|       <PrivateAssets>all</PrivateAssets> |       <PrivateAssets>all</PrivateAssets> | ||||||
|       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> |       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||||||
|     </PackageReference> |     </PackageReference> | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|     public partial class AddPeerDialog |     public partial class AddPeerDialog | ||||||
|     { |     { | ||||||
|         [CascadingParameter] |         [CascadingParameter] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         public IMudDialogInstance MudDialog { get; set; } = default!; | ||||||
|  |  | ||||||
|         protected HashSet<PeerId> Peers { get; } = []; |         protected HashSet<PeerId> Peers { get; } = []; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|         protected IDialogService DialogService { get; set; } = default!; |         protected IDialogService DialogService { get; set; } = default!; | ||||||
|  |  | ||||||
|         [CascadingParameter] |         [CascadingParameter] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         IMudDialogInstance MudDialog { get; set; } = default!; | ||||||
|  |  | ||||||
|         [Parameter] |         [Parameter] | ||||||
|         public string? Url { get; set; } |         public string? Url { get; set; } | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| <MudGrid> | <MudGrid> | ||||||
|     <MudItem xs="12"> |     <MudItem xs="12"> | ||||||
|         <MudSwitch Label="Additional Options" @bind-Value="Expanded" LabelPosition="LabelPosition.End" /> |         <MudSwitch Label="Additional Options" @bind-Value="Expanded" LabelPlacement="Placement.End" /> | ||||||
|     </MudItem> |     </MudItem> | ||||||
| </MudGrid> | </MudGrid> | ||||||
| <MudCollapse Expanded="Expanded"> | <MudCollapse Expanded="Expanded"> | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| 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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         IMudDialogInstance MudDialog { get; set; } = default!; | ||||||
|  |  | ||||||
|         [Inject] |         [Inject] | ||||||
|         protected IApiClient ApiClient { get; set; } = default!; |         protected IApiClient ApiClient { get; set; } = default!; | ||||||
|   | |||||||
| @@ -5,12 +5,13 @@ | |||||||
|     <DialogContent> |     <DialogContent> | ||||||
|         <MudCard Class="w-100" Elevation="0"> |         <MudCard Class="w-100" Elevation="0"> | ||||||
|             <MudGrid> |             <MudGrid> | ||||||
|                 @for (var i = 0; i < Columns.Count; i++) |                 @for (var i = 0; i < OrderedColumns.Length; i++) | ||||||
|                 { |                 { | ||||||
|                     var column = Columns[i]; |                     var item = OrderedColumns[i]; | ||||||
|  |                     var column = Columns.First(c => c.Id == item); | ||||||
|                     var index = i; |                     var index = i; | ||||||
|                     <MudItem xs="7"> |                     <MudItem xs="7"> | ||||||
|                             <MudCheckBox T="bool" ValueChanged="@(c => SetSelected(c, column.Id))" Label="@column.Header" LabelPosition="LabelPosition.End" Value="@(SelectedColumnsInternal.Contains(column.Id))" /> |                         <MudCheckBox T="bool" ValueChanged="@(c => SetSelected(c, column.Id))" Label="@column.Header" LabelPlacement="Placement.End" Value="@(SelectedColumnsInternal.Contains(column.Id))" /> | ||||||
|                     </MudItem> |                     </MudItem> | ||||||
|                     <MudItem xs="3"> |                     <MudItem xs="3"> | ||||||
|                         <MudTextField T="string" Value="@(GetValue(column.Width, column.Id))" ValueChanged="@(c => SetWidth(c, column.Id))" Label="Width" Variant="Variant.Text" HelperText="px" Adornment="Adornment.End" AdornmentIcon="@Icons.Material.Outlined.WidthNormal" OnAdornmentClick="@(c => SetWidth("auto", column.Id))" /> |                         <MudTextField T="string" Value="@(GetValue(column.Width, column.Id))" ValueChanged="@(c => SetWidth(c, column.Id))" Label="Width" Variant="Variant.Text" HelperText="px" Adornment="Adornment.End" AdornmentIcon="@Icons.Material.Outlined.WidthNormal" OnAdornmentClick="@(c => SetWidth("auto", column.Id))" /> | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|     public partial class ColumnOptionsDialog<T> |     public partial class ColumnOptionsDialog<T> | ||||||
|     { |     { | ||||||
|         [CascadingParameter] |         [CascadingParameter] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         private IMudDialogInstance MudDialog { get; set; } = default!; | ||||||
|  |  | ||||||
|         [Parameter] |         [Parameter] | ||||||
|         [EditorRequired] |         [EditorRequired] | ||||||
| @@ -20,10 +20,15 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|         [Parameter] |         [Parameter] | ||||||
|         public Dictionary<string, int?> Widths { get; set; } = []; |         public Dictionary<string, int?> Widths { get; set; } = []; | ||||||
|  |  | ||||||
|  |         [Parameter] | ||||||
|  |         public Dictionary<string, int> Order { get; set; } = []; | ||||||
|  |  | ||||||
|         protected HashSet<string> SelectedColumnsInternal { get; set; } = []; |         protected HashSet<string> SelectedColumnsInternal { get; set; } = []; | ||||||
|  |  | ||||||
|         protected Dictionary<string, int?> WidthsInternal { get; set; } = []; |         protected Dictionary<string, int?> WidthsInternal { get; set; } = []; | ||||||
|  |  | ||||||
|  |         protected Dictionary<string, int> OrderInternal { get; set; } = []; | ||||||
|  |  | ||||||
|         protected override void OnParametersSet() |         protected override void OnParametersSet() | ||||||
|         { |         { | ||||||
|             if (SelectedColumnsInternal.Count == 0) |             if (SelectedColumnsInternal.Count == 0) | ||||||
| @@ -51,6 +56,25 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|                     WidthsInternal[width.Key] = width.Value; |                     WidthsInternal[width.Key] = width.Value; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             if (OrderInternal.Count == 0) | ||||||
|  |             { | ||||||
|  |                 if (Order.Count == 0) | ||||||
|  |                 { | ||||||
|  |                     for (int i = 0; i < Columns.Count; i++) | ||||||
|  |                     { | ||||||
|  |                         var column = Columns[i]; | ||||||
|  |                         OrderInternal.Add(column.Id, i); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     foreach (var order in Order) | ||||||
|  |                     { | ||||||
|  |                         OrderInternal[order.Key] = order.Value; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         protected void SetSelected(bool selected, string id) |         protected void SetSelected(bool selected, string id) | ||||||
| @@ -101,7 +125,15 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             (Columns[index], Columns[index - 1]) = (Columns[index - 1], Columns[index]); |             var currentId = OrderInternal.FirstOrDefault(o => o.Value == index).Key; | ||||||
|  |             var otherId = OrderInternal.FirstOrDefault(o => o.Value == index - 1).Key; | ||||||
|  |  | ||||||
|  |             OrderInternal[otherId] = index; | ||||||
|  |             OrderInternal[currentId] = index - 1; | ||||||
|  |  | ||||||
|  |             //(Columns[index], Columns[index - 1]) = (Columns[index - 1], Columns[index]); | ||||||
|  |  | ||||||
|  |             StateHasChanged(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         protected void MoveDown(int index) |         protected void MoveDown(int index) | ||||||
| @@ -111,7 +143,15 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             (Columns[index], Columns[index + 1]) = (Columns[index + 1], Columns[index]); |             var currentId = OrderInternal.FirstOrDefault(o => o.Value == index).Key; | ||||||
|  |             var otherId = OrderInternal.FirstOrDefault(o => o.Value == index + 1).Key; | ||||||
|  |  | ||||||
|  |             OrderInternal[otherId] = index; | ||||||
|  |             OrderInternal[currentId] = index + 1; | ||||||
|  |  | ||||||
|  |             //(Columns[index], Columns[index + 1]) = (Columns[index + 1], Columns[index]); | ||||||
|  |  | ||||||
|  |             StateHasChanged(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         protected string GetValue(int? value, string columnId) |         protected string GetValue(int? value, string columnId) | ||||||
| @@ -134,6 +174,13 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|             return value.Value.ToString(); |             return value.Value.ToString(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         private string[] OrderedColumns => GetOrderedColumns(); | ||||||
|  |  | ||||||
|  |         private string[] GetOrderedColumns() | ||||||
|  |         { | ||||||
|  |             return OrderInternal.OrderBy(x => x.Value).Select(x => x.Key).ToArray(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         protected void Cancel() |         protected void Cancel() | ||||||
|         { |         { | ||||||
|             MudDialog.Cancel(); |             MudDialog.Cancel(); | ||||||
| @@ -141,7 +188,7 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|  |  | ||||||
|         protected void Submit() |         protected void Submit() | ||||||
|         { |         { | ||||||
|             MudDialog.Close(DialogResult.Ok((SelectedColumnsInternal, WidthsInternal))); |             MudDialog.Close(DialogResult.Ok((SelectedColumnsInternal, WidthsInternal, OrderInternal))); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         protected override Task Submit(KeyboardEvent keyboardEvent) |         protected override Task Submit(KeyboardEvent keyboardEvent) | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|     public partial class ConfirmDialog |     public partial class ConfirmDialog | ||||||
|     { |     { | ||||||
|         [CascadingParameter] |         [CascadingParameter] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         IMudDialogInstance MudDialog { get; set; } = default!; | ||||||
|  |  | ||||||
|         [Parameter] |         [Parameter] | ||||||
|         public string Content { get; set; } = default!; |         public string Content { get; set; } = default!; | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
|  |  | ||||||
|         <MudGrid> |         <MudGrid> | ||||||
|             <MudItem xs="12"> |             <MudItem xs="12"> | ||||||
|                 <MudCheckBox Label="Also permanently delete the files" @bind-Value="DeleteFiles" LabelPosition="LabelPosition.End" /> |                 <MudCheckBox Label="Also permanently delete the files" @bind-Value="DeleteFiles" LabelPlacement="Placement.End" /> | ||||||
|             </MudItem> |             </MudItem> | ||||||
|         </MudGrid> |         </MudGrid> | ||||||
|     </DialogContent> |     </DialogContent> | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|     public partial class DeleteDialog |     public partial class DeleteDialog | ||||||
|     { |     { | ||||||
|         [CascadingParameter] |         [CascadingParameter] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         IMudDialogInstance MudDialog { get; set; } = default!; | ||||||
|  |  | ||||||
|         [Parameter] |         [Parameter] | ||||||
|         public string? Label { get; set; } |         public string? Label { get; set; } | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ using Lantean.QBTMud.Services; | |||||||
| using Microsoft.AspNetCore.Components; | using Microsoft.AspNetCore.Components; | ||||||
| using MudBlazor; | using MudBlazor; | ||||||
| using System.Collections.ObjectModel; | using System.Collections.ObjectModel; | ||||||
| using static MudBlazor.Colors; |  | ||||||
|  |  | ||||||
| namespace Lantean.QBTMud.Components.Dialogs | namespace Lantean.QBTMud.Components.Dialogs | ||||||
| { | { | ||||||
| @@ -31,7 +30,7 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|         protected ILocalStorageService LocalStorage { get; set; } = default!; |         protected ILocalStorageService LocalStorage { get; set; } = default!; | ||||||
|  |  | ||||||
|         [CascadingParameter] |         [CascadingParameter] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         IMudDialogInstance MudDialog { get; set; } = default!; | ||||||
|  |  | ||||||
|         [Parameter] |         [Parameter] | ||||||
|         public string? Hash { get; set; } |         public string? Hash { get; set; } | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ namespace Lantean.QBTMud.Components.Dialogs | |||||||
|         private readonly List<string> _unsavedRuleNames = []; |         private readonly List<string> _unsavedRuleNames = []; | ||||||
|  |  | ||||||
|         [CascadingParameter] |         [CascadingParameter] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         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] | ||||||
|         public MudDialogInstance MudDialog { get; set; } = default!; |         IMudDialogInstance MudDialog { get; set; } = default!; | ||||||
|  |  | ||||||
|         [Parameter] |         [Parameter] | ||||||
|         [EditorRequired] |         [EditorRequired] | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
|     <MudMenuItem Icon="@Icons.Material.Filled.DriveFileRenameOutline" OnClick="RenameFileContextMenu">Rename</MudMenuItem> |     <MudMenuItem Icon="@Icons.Material.Filled.DriveFileRenameOutline" OnClick="RenameFileContextMenu">Rename</MudMenuItem> | ||||||
| </ContextMenu> | </ContextMenu> | ||||||
|  |  | ||||||
|  | <div style="overflow-x: auto; white-space: nowrap; width: 100%;"> | ||||||
| <MudToolBar Gutters="false" Dense="true"> | <MudToolBar Gutters="false" Dense="true"> | ||||||
|     <MudIconButton Icon="@Icons.Material.Filled.DriveFileRenameOutline" OnClick="RenameFileToolbar" title="Rename" /> |     <MudIconButton Icon="@Icons.Material.Filled.DriveFileRenameOutline" OnClick="RenameFileToolbar" title="Rename" /> | ||||||
|     <MudDivider Vertical="true" /> |     <MudDivider Vertical="true" /> | ||||||
| @@ -22,6 +23,7 @@ | |||||||
|     <MudSpacer /> |     <MudSpacer /> | ||||||
|     <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> |     <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> | </MudToolBar> | ||||||
|  | </div> | ||||||
|  |  | ||||||
| <DynamicTable | <DynamicTable | ||||||
|     @ref="Table" |     @ref="Table" | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| <ContextMenu @ref="StatusContextMenu" Dense="true" AdjustmentY="-60"> | <ContextMenu @ref="StatusContextMenu" Dense="true" AdjustmentY="-60">  | ||||||
|     @TorrentControls(_statusType) |     @TorrentControls(_statusType) | ||||||
| </ContextMenu> | </ContextMenu> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -191,13 +191,13 @@ else if (RenderType == RenderType.MenuItems) | |||||||
|  |  | ||||||
|                 if (!action.Children.Any()) |                 if (!action.Children.Any()) | ||||||
|                 { |                 { | ||||||
|                     <MudMenuItem Icon="@action.Icon" IconColor="action.Color" OnClick="action.Callback" Disabled="Disabled"> |                     <MudMenuItem Icon="@action.Icon" IconColor="action.Color" OnClick="action.Callback" Disabled="Disabled" Class="icon-menu-dense"> | ||||||
|                         @action.Text |                         @action.Text | ||||||
|                     </MudMenuItem> |                     </MudMenuItem> | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     <MudMenuItem Icon="@action.Icon" IconColor="action.Color" OnClick="@(t => SubMenuTouch(action))"> |                     <MudMenuItem Icon="@action.Icon" IconColor="action.Color" OnClick="@(t => SubMenuTouch(action))" Class="icon-menu-dense"> | ||||||
|                         <MudMenu ListClass="unselectable" Dense="true" AnchorOrigin="Origin.TopRight" TransformOrigin="Origin.TopLeft" ActivationEvent="MouseEvent.MouseOver" Icon="@Icons.Material.Filled.ArrowDropDown" Ripple="false" Class="sub-menu"> |                         <MudMenu ListClass="unselectable" Dense="true" AnchorOrigin="Origin.TopRight" TransformOrigin="Origin.TopLeft" ActivationEvent="MouseEvent.MouseOver" Icon="@Icons.Material.Filled.ArrowDropDown" Ripple="false" Class="sub-menu"> | ||||||
|                             <ActivatorContent> |                             <ActivatorContent> | ||||||
|                                 @action.Text |                                 @action.Text | ||||||
|   | |||||||
| @@ -63,7 +63,7 @@ namespace Lantean.QBTMud.Components | |||||||
|         public QBitTorrentClient.Models.Preferences? Preferences { get; set; } |         public QBitTorrentClient.Models.Preferences? Preferences { get; set; } | ||||||
|  |  | ||||||
|         [Parameter] |         [Parameter] | ||||||
|         public MudDialogInstance? MudDialog { get; set; } |         public IMudDialogInstance? MudDialog { get; set; } | ||||||
|  |  | ||||||
|         [Parameter] |         [Parameter] | ||||||
|         public UIAction? ParentAction { get; set; } |         public UIAction? ParentAction { get; set; } | ||||||
| @@ -104,7 +104,7 @@ namespace Lantean.QBTMud.Components | |||||||
|             _actions = |             _actions = | ||||||
|             [ |             [ | ||||||
|                 new("start", "Start", Icons.Material.Filled.PlayArrow, Color.Success, CreateCallback(Resume)), |                 new("start", "Start", Icons.Material.Filled.PlayArrow, Color.Success, CreateCallback(Resume)), | ||||||
|                 new("pause", "Pause", Icons.Material.Filled.Pause, Color.Warning, CreateCallback(Pause)), |                 new("pause", "Pause", MajorVersion < 5 ? Icons.Material.Filled.Pause : Icons.Material.Filled.Stop, Color.Warning, CreateCallback(Pause)), | ||||||
|                 new("forceStart", "Force start", Icons.Material.Filled.Forward, Color.Warning, CreateCallback(ForceStart)), |                 new("forceStart", "Force start", Icons.Material.Filled.Forward, Color.Warning, CreateCallback(ForceStart)), | ||||||
|                 new("delete", "Remove", Icons.Material.Filled.Delete, Color.Error, CreateCallback(Remove), separatorBefore: true), |                 new("delete", "Remove", Icons.Material.Filled.Delete, Color.Error, CreateCallback(Remove), separatorBefore: true), | ||||||
|                 new("setLocation", "Set location", Icons.Material.Filled.MyLocation, Color.Info, CreateCallback(SetLocation), separatorBefore: true), |                 new("setLocation", "Set location", Icons.Material.Filled.MyLocation, Color.Info, CreateCallback(SetLocation), separatorBefore: true), | ||||||
| @@ -441,7 +441,7 @@ namespace Lantean.QBTMud.Components | |||||||
|                     thereAreFirstLastPiecePrio = true; |                     thereAreFirstLastPiecePrio = true; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (torrent.Progress != 1.0) // not downloaded |                 if (torrent.Progress > 0.999999) // not downloaded | ||||||
|                 { |                 { | ||||||
|                     allAreDownloaded = false; |                     allAreDownloaded = false; | ||||||
|                 } |                 } | ||||||
|   | |||||||
| @@ -8,19 +8,17 @@ | |||||||
|             Class="unselectable" |             Class="unselectable" | ||||||
|             MaxHeight="@MaxHeight" |             MaxHeight="@MaxHeight" | ||||||
|             AnchorOrigin="@AnchorOrigin" |             AnchorOrigin="@AnchorOrigin" | ||||||
|             TransformOrigin="TransformOrigin" |             TransformOrigin="@TransformOrigin" | ||||||
|             RelativeWidth="@FullWidth" |             RelativeWidth="@RelativeWidth" | ||||||
|             OverflowBehavior="OverflowBehavior.FlipAlways" |             OverflowBehavior="OverflowBehavior.FlipAlways" | ||||||
|             Style="@_popoverStyle" |             Style="@_popoverStyle" | ||||||
|             @ontouchend:preventDefault> |             @ontouchend:preventDefault> | ||||||
|     <CascadingValue Value="@(FakeMenu)"> |     <CascadingValue Value="@(FakeMenu)"> | ||||||
|         @if (_showChildren) |         @if (_showChildren) | ||||||
|         { |         { | ||||||
|             <MudList T="object" |             <MudList T="object" Class="unselectable"  Dense="@Dense"> | ||||||
|             Class="unselectable" |  | ||||||
|                  Dense="@Dense"> |  | ||||||
|                 @ChildContent |                 @ChildContent | ||||||
|         </MudList> |             </MudList> | ||||||
|         } |         } | ||||||
|     </CascadingValue> |     </CascadingValue> | ||||||
| </MudPopover> | </MudPopover> | ||||||
|   | |||||||
| @@ -7,12 +7,6 @@ using MudBlazor.Utilities; | |||||||
|  |  | ||||||
| namespace Lantean.QBTMud.Components.UI | namespace Lantean.QBTMud.Components.UI | ||||||
| { | { | ||||||
|     // This is a very hacky approach but works for now. |  | ||||||
|     // This needs to inherit from MudMenu because MudMenuItem needs a MudMenu passed to it to control the close of the menu when an item is clicked. |  | ||||||
|     // MudPopover isn't ideal for this because that is designed to be used relative to an activator which in these cases it isn't. |  | ||||||
|     // Ideally this should be changed to use something like the way the DialogService works. |  | ||||||
|  |  | ||||||
|     // Or - rework this to have a hidden MudMenu and hook into the OpenChanged event to monitor when the MudMenuItem closes it. |  | ||||||
|     public partial class ContextMenu : MudComponentBase |     public partial class ContextMenu : MudComponentBase | ||||||
|     { |     { | ||||||
|         private bool _open; |         private bool _open; | ||||||
| @@ -61,7 +55,7 @@ namespace Lantean.QBTMud.Components.UI | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         [Parameter] |         [Parameter] | ||||||
|         [Category(CategoryTypes.Menu.PopupAppearance)] |         [Category(CategoryTypes.Menu.PopupAppearance)] | ||||||
|         public bool FullWidth { get; set; } |         public DropdownWidth RelativeWidth { get; set; } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Sets the max height the menu can have when open. |         /// Sets the max height the menu can have when open. | ||||||
| @@ -219,56 +213,58 @@ namespace Lantean.QBTMud.Components.UI | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         protected override async Task OnAfterRenderAsync(bool firstRender) |         protected override Task OnAfterRenderAsync(bool firstRender) | ||||||
|         { |         { | ||||||
|             if (!_isResized) |             if (!_isResized) | ||||||
|             { |             { | ||||||
|                 await DeterminePosition(); |                 //await DeterminePosition(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             return Task.CompletedTask; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private async Task DeterminePosition() |         //private async Task DeterminePosition() | ||||||
|         { |         //{ | ||||||
|             var mainContentSize = await JSRuntime.GetInnerDimensions(".mud-main-content"); |         //    var mainContentSize = await JSRuntime.GetInnerDimensions(".mud-main-content"); | ||||||
|             double? contextMenuHeight = null; |         //    double? contextMenuHeight = null; | ||||||
|             double? contextMenuWidth = null; |         //    double? contextMenuWidth = null; | ||||||
|  |  | ||||||
|             var popoverHolder = PopoverService.ActivePopovers.FirstOrDefault(p => p.UserAttributes.ContainsKey("tracker") && (string?)p.UserAttributes["tracker"] == Id); |         //    var popoverHolder = PopoverService.ActivePopovers.FirstOrDefault(p => p.UserAttributes.ContainsKey("tracker") && (string?)p.UserAttributes["tracker"] == Id); | ||||||
|  |  | ||||||
|             var popoverSize = await JSRuntime.GetBoundingClientRect($"#popovercontent-{popoverHolder?.Id}"); |         //    var popoverSize = await JSRuntime.GetBoundingClientRect($"#popovercontent-{popoverHolder?.Id}"); | ||||||
|             if (popoverSize.Height > 0) |         //    if (popoverSize.Height > 0) | ||||||
|             { |         //    { | ||||||
|                 contextMenuHeight = popoverSize.Height; |         //        contextMenuHeight = popoverSize.Height; | ||||||
|                 contextMenuWidth = popoverSize.Width; |         //        contextMenuWidth = popoverSize.Width; | ||||||
|             } |         //    } | ||||||
|             else |         //    else | ||||||
|             { |         //    { | ||||||
|                 return; |         //        return; | ||||||
|             } |         //    } | ||||||
|  |  | ||||||
|             // the bottom position of the popover will be rendered off screen |         //    // the bottom position of the popover will be rendered off screen | ||||||
|             if (_y - _diff + contextMenuHeight.Value >= mainContentSize.Height) |         //    if (_y - _diff + contextMenuHeight.Value >= mainContentSize.Height) | ||||||
|             { |         //    { | ||||||
|                 // adjust the top of the context menu |         //        // adjust the top of the context menu | ||||||
|                 var overshoot = Math.Abs(mainContentSize.Height - (_y - _diff + contextMenuHeight.Value)); |         //        var overshoot = Math.Abs(mainContentSize.Height - (_y - _diff + contextMenuHeight.Value)); | ||||||
|                 _y -= overshoot; |         //        _y -= overshoot; | ||||||
|  |  | ||||||
|                 if (_y - _diff + contextMenuHeight >= mainContentSize.Height) |         //        if (_y - _diff + contextMenuHeight >= mainContentSize.Height) | ||||||
|                 { |         //        { | ||||||
|                     MaxHeight = (int)(mainContentSize.Height - _y + _diff); |         //            MaxHeight = (int)(mainContentSize.Height - _y + _diff); | ||||||
|                 } |         //        } | ||||||
|             } |         //    } | ||||||
|  |  | ||||||
|             if (_x + contextMenuWidth.Value > mainContentSize.Width) |         //    if (_x + contextMenuWidth.Value > mainContentSize.Width) | ||||||
|             { |         //    { | ||||||
|                 var overshoot = Math.Abs(mainContentSize.Width - (_x + contextMenuWidth.Value)); |         //        var overshoot = Math.Abs(mainContentSize.Width - (_x + contextMenuWidth.Value)); | ||||||
|                 _x -= overshoot; |         //        _x -= overshoot; | ||||||
|             } |         //    } | ||||||
|  |  | ||||||
|             SetPopoverStyle(_x, _y); |         //    SetPopoverStyle(_x, _y); | ||||||
|             _isResized = true; |         //    _isResized = true; | ||||||
|             await InvokeAsync(StateHasChanged); |         //    await InvokeAsync(StateHasChanged); | ||||||
|         } |         //} | ||||||
|  |  | ||||||
|         private (double x, double y) GetPositionFromArgs(EventArgs eventArgs) |         private (double x, double y) GetPositionFromArgs(EventArgs eventArgs) | ||||||
|         { |         { | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| <div class="@Classname"> | <div class="@Classname"> | ||||||
|     <div @onclick="EventUtil.AsNonRenderingEventHandler<MouseEventArgs>(OnClickHandler)" class="@LinkClassname" @onlongpress="OnLongPressInternal" @oncontextmenu="OnContextMenuInternal" @oncontextmenu:preventDefault> |     <div @onclick="this.AsNonRenderingEventHandler<MouseEventArgs>(OnClickHandler)" class="@LinkClassname" @onlongpress="OnLongPressInternal" @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" /> | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ namespace Lantean.QBTMud.Components.UI | |||||||
|         private readonly string _columnSelectionStorageKey = $"DynamicTable{_typeName}.ColumnSelection"; |         private readonly string _columnSelectionStorageKey = $"DynamicTable{_typeName}.ColumnSelection"; | ||||||
|         private readonly string _columnSortStorageKey = $"DynamicTable{_typeName}.ColumnSort"; |         private readonly string _columnSortStorageKey = $"DynamicTable{_typeName}.ColumnSort"; | ||||||
|         private readonly string _columnWidthsStorageKey = $"DynamicTable{_typeName}.ColumnWidths"; |         private readonly string _columnWidthsStorageKey = $"DynamicTable{_typeName}.ColumnWidths"; | ||||||
|  |         private readonly string _columnOrderStorageKey = $"DynamicTable{_typeName}.ColumnOrder"; | ||||||
|  |  | ||||||
|         [Inject] |         [Inject] | ||||||
|         public ILocalStorageService LocalStorage { get; set; } = default!; |         public ILocalStorageService LocalStorage { get; set; } = default!; | ||||||
| @@ -82,6 +83,8 @@ namespace Lantean.QBTMud.Components.UI | |||||||
|  |  | ||||||
|         private Dictionary<string, int?> _columnWidths = []; |         private Dictionary<string, int?> _columnWidths = []; | ||||||
|  |  | ||||||
|  |         private Dictionary<string, int> _columnOrder = []; | ||||||
|  |  | ||||||
|         private string? _sortColumn; |         private string? _sortColumn; | ||||||
|  |  | ||||||
|         private SortDirection _sortDirection; |         private SortDirection _sortDirection; | ||||||
| @@ -165,8 +168,29 @@ namespace Lantean.QBTMud.Components.UI | |||||||
|         protected IEnumerable<ColumnDefinition<T>> GetColumns() |         protected IEnumerable<ColumnDefinition<T>> GetColumns() | ||||||
|         { |         { | ||||||
|             var filteredColumns = ColumnDefinitions.Where(c => SelectedColumns.Contains(c.Id)).Where(ColumnFilter); |             var filteredColumns = ColumnDefinitions.Where(c => SelectedColumns.Contains(c.Id)).Where(ColumnFilter); | ||||||
|             foreach (var column in filteredColumns) |             if (_columnOrder.Count == 0) | ||||||
|             { |             { | ||||||
|  |                 foreach (var column in filteredColumns) | ||||||
|  |                 { | ||||||
|  |                     if (_columnWidths.TryGetValue(column.Id, out var value)) | ||||||
|  |                     { | ||||||
|  |                         column.Width = value; | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     yield return column; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 yield break; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var columnDictionary = filteredColumns.ToDictionary(c => c.Id); | ||||||
|  |             foreach (var columnId in _columnOrder.OrderBy(c => c.Value).Select(c => c.Key)) | ||||||
|  |             { | ||||||
|  |                 if (!columnDictionary.TryGetValue(columnId, out var column)) | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                 if (_columnWidths.TryGetValue(column.Id, out var value)) |                 if (_columnWidths.TryGetValue(column.Id, out var value)) | ||||||
|                 { |                 { | ||||||
|                     column.Width = value; |                     column.Width = value; | ||||||
| @@ -280,7 +304,7 @@ namespace Lantean.QBTMud.Components.UI | |||||||
|  |  | ||||||
|         public async Task ShowColumnOptionsDialog() |         public async Task ShowColumnOptionsDialog() | ||||||
|         { |         { | ||||||
|             var result = await DialogService.ShowColumnsOptionsDialog(ColumnDefinitions.Where(ColumnFilter).ToList(), SelectedColumns, _columnWidths); |             var result = await DialogService.ShowColumnsOptionsDialog(ColumnDefinitions.Where(ColumnFilter).ToList(), SelectedColumns, _columnWidths, _columnOrder); | ||||||
|  |  | ||||||
|             if (result == default) |             if (result == default) | ||||||
|             { |             { | ||||||
| @@ -299,11 +323,17 @@ namespace Lantean.QBTMud.Components.UI | |||||||
|                 _columnWidths = result.ColumnWidths; |                 _columnWidths = result.ColumnWidths; | ||||||
|                 await LocalStorage.SetItemAsync(_columnWidthsStorageKey, _columnWidths); |                 await LocalStorage.SetItemAsync(_columnWidthsStorageKey, _columnWidths); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             if (!DictionaryEqual(_columnOrder, result.ColumnOrder)) | ||||||
|  |             { | ||||||
|  |                 _columnOrder = result.ColumnOrder; | ||||||
|  |                 await LocalStorage.SetItemAsync(_columnOrderStorageKey, _columnOrder); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private static bool DictionaryEqual(Dictionary<string, int?> left, Dictionary<string, int?> right) |         private static bool DictionaryEqual<TKey, TValue>(Dictionary<TKey, TValue> left, Dictionary<TKey, TValue> right) where TKey : notnull | ||||||
|         { |         { | ||||||
|             return left.Keys.Count == right.Keys.Count && left.Keys.All(k => right.ContainsKey(k) && left[k] == right[k]); |             return left.Keys.Count == right.Keys.Count && left.Keys.All(k => right.ContainsKey(k) && Equals(left[k], right[k])); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private static string? GetColumnStyle(ColumnDefinition<T> column) |         private static string? GetColumnStyle(ColumnDefinition<T> column) | ||||||
|   | |||||||
| @@ -328,13 +328,14 @@ namespace Lantean.QBTMud.Helpers | |||||||
|             return tags; |             return tags; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static async Task<(HashSet<string> SelectedColumns, Dictionary<string, int?> ColumnWidths)> ShowColumnsOptionsDialog<T>(this IDialogService dialogService, List<ColumnDefinition<T>> columnDefinitions, HashSet<string> selectedColumns, Dictionary<string, int?> widths) |         public static async Task<(HashSet<string> SelectedColumns, Dictionary<string, int?> ColumnWidths, Dictionary<string, int> ColumnOrder)> ShowColumnsOptionsDialog<T>(this IDialogService dialogService, List<ColumnDefinition<T>> columnDefinitions, HashSet<string> selectedColumns, Dictionary<string, int?> widths, Dictionary<string, int> order) | ||||||
|         { |         { | ||||||
|             var parameters = new DialogParameters |             var parameters = new DialogParameters | ||||||
|             { |             { | ||||||
|                 { nameof(ColumnOptionsDialog<T>.Columns), columnDefinitions }, |                 { nameof(ColumnOptionsDialog<T>.Columns), columnDefinitions }, | ||||||
|                 { nameof(ColumnOptionsDialog<T>.SelectedColumns), selectedColumns }, |                 { nameof(ColumnOptionsDialog<T>.SelectedColumns), selectedColumns }, | ||||||
|                 { nameof(ColumnOptionsDialog<T>.Widths), widths }, |                 { nameof(ColumnOptionsDialog<T>.Widths), widths }, | ||||||
|  |                 { nameof(ColumnOptionsDialog<T>.Order), order }, | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             var reference = await dialogService.ShowAsync<ColumnOptionsDialog<T>>("Column Options", parameters, FormDialogOptions); |             var reference = await dialogService.ShowAsync<ColumnOptionsDialog<T>>("Column Options", parameters, FormDialogOptions); | ||||||
| @@ -344,7 +345,7 @@ namespace Lantean.QBTMud.Helpers | |||||||
|                 return default; |                 return default; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return ((HashSet<string>, Dictionary<string, int?>))dialogResult.Data; |             return ((HashSet<string>, Dictionary<string, int?>, Dictionary<string, int>))dialogResult.Data; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static async Task<bool> ShowConfirmDialog(this IDialogService dialogService, string title, string content) |         public static async Task<bool> ShowConfirmDialog(this IDialogService dialogService, string title, string content) | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| <Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> | <Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> | ||||||
|  |  | ||||||
|   <PropertyGroup> |   <PropertyGroup> | ||||||
|     <TargetFramework>net8.0</TargetFramework> |     <TargetFramework>net9.0</TargetFramework> | ||||||
|     <Nullable>enable</Nullable> |     <Nullable>enable</Nullable> | ||||||
|     <ImplicitUsings>enable</ImplicitUsings> |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
| 	<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | 	<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||||||
| @@ -12,13 +12,13 @@ | |||||||
|   <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="8.0.10" /> | 	<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.1" /> | ||||||
| 	<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.10" PrivateAssets="all" /> | 	<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.1" PrivateAssets="all" /> | ||||||
| 	<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" /> | 	<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.1" /> | ||||||
| 	<PackageReference Include="MudBlazor" Version="7.15.0" /> | 	<PackageReference Include="MudBlazor" Version="8.2.0" /> | ||||||
| 	<PackageReference Include="MudBlazor.ThemeManager" Version="2.1.0" /> | 	<PackageReference Include="MudBlazor.ThemeManager" Version="3.0.0" /> | ||||||
|     <!-- added to fix vuln in dependency --> |     <!-- added to fix vuln in dependency --> | ||||||
| 	<PackageReference Include="System.Text.Json" Version="8.0.5" /> | 	<PackageReference Include="System.Text.Json" Version="9.0.1" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|   | |||||||
| @@ -36,23 +36,23 @@ | |||||||
|                 </CascadingValue> |                 </CascadingValue> | ||||||
|             </CascadingValue> |             </CascadingValue> | ||||||
|         </CascadingValue> |         </CascadingValue> | ||||||
|         <MudAppBar Bottom="true" Fixed="true" Elevation="0" Dense="true" Style="background-color: var(--mud-palette-dark-lighten);"> |         <MudAppBar Bottom="true" Fixed="true" Elevation="0" Dense="true" Style="background-color: var(--mud-palette-dark-lighten); z-index: 900"> | ||||||
|             @if (MainData?.LostConnection == true) |             @if (MainData?.LostConnection == true) | ||||||
|             { |             { | ||||||
|                 <MudText Class="mx-2 mb-1" Color="Color.Error">qBittorrent client is not reachable</MudText> |                 <MudText Class="mx-2 mb-1 d-none d-sm-flex" Color="Color.Error">qBittorrent client is not reachable</MudText> | ||||||
|             } |             } | ||||||
|             <MudSpacer /> |             <MudSpacer /> | ||||||
|             <MudText Class="mx-2 mb-1">@DisplayHelpers.Size(MainData?.ServerState.FreeSpaceOnDisk, "Free space: ")</MudText> |             <MudText Class="mx-2 mb-1 d-none d-sm-flex">@DisplayHelpers.Size(MainData?.ServerState.FreeSpaceOnDisk, "Free space: ")</MudText> | ||||||
|             <MudDivider Vertical="true" /> |             <MudDivider Vertical="true" Class="d-none d-sm-flex" /> | ||||||
|             <MudText Class="mx-2 mb-1">DHT @(MainData?.ServerState.DHTNodes ?? 0) nodes</MudText> |             <MudText Class="mx-2 mb-1 d-none d-sm-flex">DHT @(MainData?.ServerState.DHTNodes ?? 0) nodes</MudText> | ||||||
|             <MudDivider Vertical="true" /> |             <MudDivider Vertical="true" Class="d-none d-sm-flex" /> | ||||||
|             @{ |             @{ | ||||||
|                 var (icon, colour) = GetConnectionIcon(MainData?.ServerState.ConnectionStatus); |                 var (icon, colour) = GetConnectionIcon(MainData?.ServerState.ConnectionStatus); | ||||||
|             } |             } | ||||||
|             <MudIcon Class="mx-1 mb-1" Icon="@icon" Color="@colour" Title="MainData?.ServerState.ConnectionStatus" /> |             <MudIcon Class="mx-1 mb-1" Icon="@icon" Color="@colour" Title="MainData?.ServerState.ConnectionStatus" /> | ||||||
|             <MudDivider Vertical="true" /> |             <MudDivider Vertical="true" Class="" /> | ||||||
|             <MudIcon Class="mx-1 mb-1" Icon="@Icons.Material.Outlined.Speed" Color="@((MainData?.ServerState.UseAltSpeedLimits ?? false) ? Color.Error : Color.Success)" /> |             <MudIcon Class="mx-1 mb-1" Icon="@Icons.Material.Outlined.Speed" Color="@((MainData?.ServerState.UseAltSpeedLimits ?? false) ? Color.Error : Color.Success)" /> | ||||||
|             <MudDivider Vertical="true" /> |             <MudDivider Vertical="true" Class="" /> | ||||||
|             <MudIcon Class="ml-1 mb-1" Icon="@Icons.Material.Filled.KeyboardDoubleArrowDown" Color="Color.Success" /> |             <MudIcon Class="ml-1 mb-1" Icon="@Icons.Material.Filled.KeyboardDoubleArrowDown" Color="Color.Success" /> | ||||||
|             <MudText Class="mr-1 mb-1"> |             <MudText Class="mr-1 mb-1"> | ||||||
|                 @DisplayHelpers.Size(MainData?.ServerState.DownloadInfoSpeed, null, "/s") |                 @DisplayHelpers.Size(MainData?.ServerState.DownloadInfoSpeed, null, "/s") | ||||||
|   | |||||||
| @@ -20,16 +20,18 @@ | |||||||
|                         <MudIconButton Icon="@Icons.Material.Filled.Error" Color="Color.Default" OnClick="ToggleErrorDrawer" /> |                         <MudIconButton Icon="@Icons.Material.Filled.Error" Color="Color.Default" OnClick="ToggleErrorDrawer" /> | ||||||
|                     </MudBadge> |                     </MudBadge> | ||||||
|                 } |                 } | ||||||
|                 <MudSwitch T="bool" Label="Dark Mode" LabelPosition="LabelPosition.End" Value="IsDarkMode" ValueChanged="DarkModeChanged" Class="pl-3" /> |                 <MudSwitch T="bool" Label="Dark Mode" LabelPlacement="Placement.End" Value="IsDarkMode" ValueChanged="DarkModeChanged" Class="pl-3" /> | ||||||
|                 <Menu @ref="Menu" /> |                 <Menu @ref="Menu" /> | ||||||
|             </MudAppBar> |             </MudAppBar> | ||||||
|             <MudDrawer Open="ErrorDrawerOpen" ClipMode="DrawerClipMode.Docked" Elevation="2" Anchor="Anchor.Right"> |             <MudDrawer @bind-Open="ErrorDrawerOpen" ClipMode="DrawerClipMode.Docked" Elevation="2" Anchor="Anchor.Right"> | ||||||
|                 <ErrorDisplay ErrorBoundary="ErrorBoundary" /> |                 <ErrorDisplay ErrorBoundary="ErrorBoundary" /> | ||||||
|             </MudDrawer> |             </MudDrawer> | ||||||
|             <CascadingValue Value="Theme"> |             <CascadingValue Value="Theme"> | ||||||
|                 <CascadingValue Value="IsDarkMode" Name="IsDarkMode"> |                 <CascadingValue Value="IsDarkMode" Name="IsDarkMode"> | ||||||
|                     <CascadingValue Value="Menu"> |                     <CascadingValue Value="Menu"> | ||||||
|                         @Body |                         <CascadingValue Value="DrawerOpen" Name="DrawerOpen"> | ||||||
|  |                             @Body | ||||||
|  |                         </CascadingValue> | ||||||
|                     </CascadingValue> |                     </CascadingValue> | ||||||
|                 </CascadingValue> |                 </CascadingValue> | ||||||
|             </CascadingValue> |             </CascadingValue> | ||||||
|   | |||||||
| @@ -90,9 +90,9 @@ namespace Lantean.QBTMud.Layout | |||||||
|             return Task.CompletedTask; |             return Task.CompletedTask; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public Task NotifyBrowserViewportChangeAsync(BrowserViewportEventArgs browserViewportEventArgs) |         public async Task NotifyBrowserViewportChangeAsync(BrowserViewportEventArgs browserViewportEventArgs) | ||||||
|         { |         { | ||||||
|             if (browserViewportEventArgs.Breakpoint == Breakpoint.Sm && DrawerOpen) |             if (browserViewportEventArgs.Breakpoint <= Breakpoint.Sm) | ||||||
|             { |             { | ||||||
|                 DrawerOpen = false; |                 DrawerOpen = false; | ||||||
|             } |             } | ||||||
| @@ -101,7 +101,17 @@ namespace Lantean.QBTMud.Layout | |||||||
|                 DrawerOpen = true; |                 DrawerOpen = true; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return Task.CompletedTask; |             if (ErrorBoundary?.Errors.Count > 0) | ||||||
|  |             { | ||||||
|  |                 ErrorDrawerOpen = true; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 await Task.Delay(250); | ||||||
|  |                 ErrorDrawerOpen = false; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             await InvokeAsync(StateHasChanged); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         protected void ToggleErrorDrawer() |         protected void ToggleErrorDrawer() | ||||||
|   | |||||||
| @@ -12,89 +12,96 @@ | |||||||
|  |  | ||||||
| <MudTabs Elevation="2" ApplyEffectsToContainer="true"> | <MudTabs Elevation="2" ApplyEffectsToContainer="true"> | ||||||
|     <MudTabPanel Text="About"> |     <MudTabPanel Text="About"> | ||||||
|         <div class="d-flex gap-4"> |         <MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3"> | ||||||
|             <MudImage Src="images/mascot.png" Alt="Mascot" Class="ma-6" Fluid ObjectFit="ObjectFit.None" ObjectPosition="ObjectPosition.LeftTop" Height="162" Width="94" /> |             <MudGrid Class="mt-0 mb-4"> | ||||||
|             <MudGrid Class="mx-0 mt-0 mb-3"> |                 <MudItem xs="12" sm="3" md="2" lg="2" xl="1" Class="d-flex justify-center"> | ||||||
|                 <MudItem xs="12"> |                     <MudImage Src="images/mascot.png" Alt="Mascot" Class="ma-6" | ||||||
|                     <div class="d-flex gap-3"> |                               Fluid ObjectFit="ObjectFit.None" ObjectPosition="ObjectPosition.LeftTop" | ||||||
|                         <MudImage Src="images/qbittorrent32.png" Fluid ObjectFit="ObjectFit.None" Alt="QBT" Height="32" Width="32"  /><MudText Typo="Typo.h6">qBittorrent @QBittorrentVersion</MudText> |                               Height="162" Width="94" /> | ||||||
|  |                 </MudItem> | ||||||
|  |  | ||||||
|  |                 <MudItem xs="12" sm="9" md="10" lg="10" xl="11"> | ||||||
|  |                     <div class="d-flex flex-column gap-2"> | ||||||
|  |                         <div class="d-flex gap-3 align-items-center"> | ||||||
|  |                             <MudImage Src="images/qbittorrent32.png" Fluid ObjectFit="ObjectFit.None" | ||||||
|  |                                       Alt="QBT" Height="32" Width="32" /> | ||||||
|  |                             <MudText Typo="Typo.h6">qBittorrent @QBittorrentVersion</MudText> | ||||||
|  |                         </div> | ||||||
|  |  | ||||||
|  |                         <MudText Typo="Typo.body1"> | ||||||
|  |                             An advanced BitTorrent client programmed in C++, based on Qt toolkit and libtorrent-rasterbar. | ||||||
|  |                         </MudText> | ||||||
|  |  | ||||||
|  |                         <MudText Typo="Typo.body1">Copyright © 2006-2024 The qBittorrent project</MudText> | ||||||
|  |  | ||||||
|  |                         <div class="d-flex flex-wrap"> | ||||||
|  |                             <MudText Typo="Typo.body1" Class="fw-bold">Home Page: </MudText> | ||||||
|  |                             <MudLink Href="https://www.qbittorrent.org" Target="_blank" Class="ms-2"> | ||||||
|  |                                 qbittorrent.org | ||||||
|  |                             </MudLink> | ||||||
|  |                         </div> | ||||||
|  |  | ||||||
|  |                         <div class="d-flex flex-wrap"> | ||||||
|  |                             <MudText Typo="Typo.body1" Class="fw-bold">Bug Tracker: </MudText> | ||||||
|  |                             <MudLink Href="https://bugs.qbittorrent.org" Target="_blank" Class="ms-2"> | ||||||
|  |                                 bugs.qbittorrent.org | ||||||
|  |                             </MudLink> | ||||||
|  |                         </div> | ||||||
|  |  | ||||||
|  |                         <div class="d-flex flex-wrap"> | ||||||
|  |                             <MudText Typo="Typo.body1" Class="fw-bold">Forum: </MudText> | ||||||
|  |                             <MudLink Href="https://forum.qbittorrent.org" Target="_blank" Class="ms-2"> | ||||||
|  |                                 forum.qbittorrent.org | ||||||
|  |                             </MudLink> | ||||||
|  |                         </div> | ||||||
|                     </div> |                     </div> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|  |  | ||||||
|                 <MudItem xs="12"> |  | ||||||
|                     <MudText Typo="Typo.body1">An advanced BitTorrent client programmed in C++, based on Qt toolkit and libtorrent-rasterbar.</MudText> |  | ||||||
|                 </MudItem> |  | ||||||
|  |  | ||||||
|                 <MudItem xs="12"> |  | ||||||
|                     <MudText Typo="Typo.body1">Copyright © 2006-2024 The qBittorrent project</MudText> |  | ||||||
|                 </MudItem> |  | ||||||
|  |  | ||||||
|                 <MudItem xs="2"> |  | ||||||
|                     <MudText Typo="Typo.body1">Home Page</MudText> |  | ||||||
|                 </MudItem> |  | ||||||
|                 <MudItem xs="10"> |  | ||||||
|                     <MudLink Href="https://www.qbittorrent.org" Target="https://www.qbittorrent.org">https://www.qbittorrent.org</MudLink> |  | ||||||
|                 </MudItem> |  | ||||||
|  |  | ||||||
|                 <MudItem xs="2"> |  | ||||||
|                     <MudText Typo="Typo.body1">Bug Tracker</MudText> |  | ||||||
|                 </MudItem> |  | ||||||
|                 <MudItem xs="10"> |  | ||||||
|                     <MudLink Href="https://bugs.qbittorrent.org" Target="https://bugs.qbittorrent.org">https://bugs.qbittorrent.org</MudLink> |  | ||||||
|                 </MudItem> |  | ||||||
|  |  | ||||||
|                 <MudItem xs="2"> |  | ||||||
|                     <MudText Typo="Typo.body1">Forum</MudText> |  | ||||||
|                 </MudItem> |  | ||||||
|                 <MudItem xs="10"> |  | ||||||
|                     <MudLink Href="https://forum.qbittorrent.org" Target="https://forum.qbittorrent.org">https://forum.qbittorrent.org</MudLink> |  | ||||||
|                 </MudItem> |  | ||||||
|             </MudGrid> |             </MudGrid> | ||||||
|         </div> |         </MudContainer> | ||||||
|     </MudTabPanel> |     </MudTabPanel> | ||||||
|     <MudTabPanel Text="Authors"> |     <MudTabPanel Text="Authors"> | ||||||
|         <MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3"> |         <MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="mt-3"> | ||||||
|             <MudText Typo="Typo.body1" 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"> | ||||||
|                 <MudItem xs="2"> |                 <MudItem xs="12" md="2"> | ||||||
|                     <MudText Typo="Typo.body1">Name</MudText> |                     <MudText Typo="Typo.h6">Name</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="10"> |                 <MudItem xs="12" md="10"> | ||||||
|                     <MudText Typo="Typo.body1">Sledgehammer999</MudText> |                     <MudText Typo="Typo.body1">Sledgehammer999</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="2"> |                 <MudItem xs="12" md="2"> | ||||||
|                     <MudText Typo="Typo.body1">Nationality</MudText> |                     <MudText Typo="Typo.h6">Nationality</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="10"> |                 <MudItem xs="12" md="10"> | ||||||
|                     <MudText Typo="Typo.body1">Greece</MudText> |                     <MudText Typo="Typo.body1">Greece</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="2"> |                 <MudItem xs="12" md="2"> | ||||||
|                     <MudText Typo="Typo.body1">E-mail</MudText> |                     <MudText Typo="Typo.h6">E-mail</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="10"> |                 <MudItem xs="12" md="10"> | ||||||
|                     <MudLink Href="mailto:sledgehammer999@qbittorrent.org">sledgehammer999@qbittorrent.org</MudLink> |                     <MudLink Href="mailto:sledgehammer999@qbittorrent.org">sledgehammer999@qbittorrent.org</MudLink> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|             </MudGrid> |             </MudGrid> | ||||||
|  |  | ||||||
|             <MudText Typo="Typo.body1" Class="py-1">Original author</MudText> |             <MudText Typo="Typo.h5" Class="py-1">Original author</MudText> | ||||||
|             <MudGrid Class="mt-0 mb-4"> |             <MudGrid Class="mt-0 mb-4"> | ||||||
|                 <MudItem xs="2"> |                 <MudItem xs="12" md="2"> | ||||||
|                     <MudText Typo="Typo.body1">Name</MudText> |                     <MudText Typo="Typo.h6">Name</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="10"> |                 <MudItem xs="12" md="10"> | ||||||
|                     <MudText Typo="Typo.body1">Christophe Dumez</MudText> |                     <MudText Typo="Typo.body1">Christophe Dumez</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="2"> |                 <MudItem xs="12" md="2"> | ||||||
|                     <MudText Typo="Typo.body1">Nationality</MudText> |                     <MudText Typo="Typo.h6">Nationality</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="10"> |                 <MudItem xs="12" md="10"> | ||||||
|                     <MudText Typo="Typo.body1">France</MudText> |                     <MudText Typo="Typo.body1">France</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="2"> |                 <MudItem xs="12" md="2"> | ||||||
|                     <MudText Typo="Typo.body1">E-mail</MudText> |                     <MudText Typo="Typo.h6">E-mail</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="10"> |                 <MudItem xs="12" md="10"> | ||||||
|                     <MudLink Href="mailto:chris@qbittorrent.org">chris@qbittorrent.org</MudLink> |                     <MudLink Href="mailto:chris@qbittorrent.org">chris@qbittorrent.org</MudLink> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|             </MudGrid> |             </MudGrid> | ||||||
| @@ -118,7 +125,7 @@ | |||||||
|                 (the list might not be up to date) |                 (the list might not be up to date) | ||||||
|             </MudText> |             </MudText> | ||||||
|             <MudList T="string" ReadOnly> |             <MudList T="string" ReadOnly> | ||||||
|                 <MudListItem Icon="@Icons.Material.Filled.Circle" IconColor="Color.Info"><u>Arabic:</u> SDERAWI (abz8868@msn.com), sn51234 (nesseyan@gmail.com) and Ibrahim Saed ibraheem_alex(Transifex)</MudListItem> |                 <MudListItem Icon="@Icons.Material.Filled.Circle"><u>Arabic:</u> SDERAWI (abz8868@msn.com), sn51234 (nesseyan@gmail.com) and Ibrahim Saed ibraheem_alex(Transifex)</MudListItem> | ||||||
|                 <MudListItem Icon="@Icons.Material.Filled.Circle"><u>Armenian:</u> Hrant Ohanyan (hrantohanyan@mail.am)</MudListItem> |                 <MudListItem Icon="@Icons.Material.Filled.Circle"><u>Armenian:</u> Hrant Ohanyan (hrantohanyan@mail.am)</MudListItem> | ||||||
|                 <MudListItem Icon="@Icons.Material.Filled.Circle"><u>Basque:</u> Xabier Aramendi (azpidatziak@gmail.com)</MudListItem> |                 <MudListItem Icon="@Icons.Material.Filled.Circle"><u>Basque:</u> Xabier Aramendi (azpidatziak@gmail.com)</MudListItem> | ||||||
|                 <MudListItem Icon="@Icons.Material.Filled.Circle"><u>Belarusian:</u> Mihas Varantsou (meequz@gmail.com)</MudListItem> |                 <MudListItem Icon="@Icons.Material.Filled.Circle"><u>Belarusian:</u> Mihas Varantsou (meequz@gmail.com)</MudListItem> | ||||||
| @@ -1058,38 +1065,38 @@ | |||||||
|             <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"> | ||||||
|                 <MudItem xs="2"> |                 <MudItem xs="3"> | ||||||
|                     <MudText Typo="Typo.body1">Qt</MudText> |                     <MudText Typo="Typo.body1">Qt</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="10"> |                 <MudItem xs="9"> | ||||||
|                     <MudText Typo="Typo.body1">@QtVersion</MudText> |                     <MudText Typo="Typo.body1">@QtVersion</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|  |  | ||||||
|                 <MudItem xs="2"> |                 <MudItem xs="3"> | ||||||
|                     <MudText Typo="Typo.body1">Libtorrent</MudText> |                     <MudText Typo="Typo.body1">Libtorrent</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="10"> |                 <MudItem xs="9"> | ||||||
|                     <MudText Typo="Typo.body1">@LibtorrentVersion</MudText> |                     <MudText Typo="Typo.body1">@LibtorrentVersion</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|  |  | ||||||
|                 <MudItem xs="2"> |                 <MudItem xs="3"> | ||||||
|                     <MudText Typo="Typo.body1">Boost</MudText> |                     <MudText Typo="Typo.body1">Boost</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="10"> |                 <MudItem xs="9"> | ||||||
|                     <MudText Typo="Typo.body1">@BoostVersion</MudText> |                     <MudText Typo="Typo.body1">@BoostVersion</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|  |  | ||||||
|                 <MudItem xs="2"> |                 <MudItem xs="3"> | ||||||
|                     <MudText Typo="Typo.body1">OpenSSL</MudText> |                     <MudText Typo="Typo.body1">OpenSSL</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="10"> |                 <MudItem xs="9"> | ||||||
|                     <MudText Typo="Typo.body1">@OpensslVersion</MudText> |                     <MudText Typo="Typo.body1">@OpensslVersion</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|  |  | ||||||
|                 <MudItem xs="2"> |                 <MudItem xs="3"> | ||||||
|                     <MudText Typo="Typo.body1">zlib</MudText> |                     <MudText Typo="Typo.body1">zlib</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="10"> |                 <MudItem xs="9"> | ||||||
|                     <MudText Typo="Typo.body1">@ZlibVersion</MudText> |                     <MudText Typo="Typo.body1">@ZlibVersion</MudText> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|             </MudGrid> |             </MudGrid> | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| @page "/details/{hash}" | @page "/details/{hash}" | ||||||
| @layout DetailsLayout | @layout DetailsLayout | ||||||
|  |  | ||||||
|  | <div style="overflow-x: auto; white-space: nowrap; width: 100%;"> | ||||||
| <MudToolBar Gutters="false" Dense="true"> | <MudToolBar Gutters="false" Dense="true"> | ||||||
|     @if (!DrawerOpen) |     @if (!DrawerOpen) | ||||||
|     { |     { | ||||||
| @@ -14,6 +15,7 @@ | |||||||
|     <MudDivider Vertical="true" /> |     <MudDivider Vertical="true" /> | ||||||
|     <MudText Class="pl-5 no-wrap">@Name</MudText> |     <MudText Class="pl-5 no-wrap">@Name</MudText> | ||||||
| </MudToolBar> | </MudToolBar> | ||||||
|  | </div> | ||||||
|  |  | ||||||
| @if (ShowTabs) | @if (ShowTabs) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ namespace Lantean.QBTMud.Pages | |||||||
|  |  | ||||||
|         protected override Task OnInitializedAsync() |         protected override Task OnInitializedAsync() | ||||||
|         { |         { | ||||||
|             return DoLogin("admin", "eBGJzbjkJ"); |             return DoLogin("admin", "5FUM5pATq"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ | |||||||
|                 <MudItem xs="12" md="4"> |                 <MudItem xs="12" md="4"> | ||||||
|                     <MudTextField T="string" Label="Criteria" @bind-Value="Model.SearchText" Variant="Variant.Outlined" /> |                     <MudTextField T="string" Label="Criteria" @bind-Value="Model.SearchText" Variant="Variant.Outlined" /> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="2" md="3"> |                 <MudItem xs="12" md="3"> | ||||||
|                     <MudSelect T="string" Label="Categories" @bind-Value="Model.SelectedCategory" Variant="Variant.Outlined"> |                     <MudSelect T="string" Label="Categories" @bind-Value="Model.SelectedCategory" Variant="Variant.Outlined"> | ||||||
|                         @foreach (var (value, name) in Categories) |                         @foreach (var (value, name) in Categories) | ||||||
|                         { |                         { | ||||||
| @@ -30,17 +30,21 @@ | |||||||
|                         } |                         } | ||||||
|                     </MudSelect> |                     </MudSelect> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="2" md="3"> |                 <MudItem xs="12" md="3"> | ||||||
|                     <MudSelect T="string" Label="Plugins" @bind-Value="Model.SelectedPlugin" Variant="Variant.Outlined"> |                     <MudSelect T="string" Label="Plugins" @bind-Value="Model.SelectedPlugin" Variant="Variant.Outlined"> | ||||||
|                         <MudSelectItem Value="@("all")">All</MudSelectItem> |                         <MudSelectItem Value="@("all")">All</MudSelectItem> | ||||||
|                         <MudDivider /> |                         @if (Plugins.Count > 0) | ||||||
|  |                         { | ||||||
|  |                             <MudDivider /> | ||||||
|  |  | ||||||
|  |                         } | ||||||
|                         @foreach (var (value, name) in Plugins) |                         @foreach (var (value, name) in Plugins) | ||||||
|                         { |                         { | ||||||
|                             <MudSelectItem Value="value">@name</MudSelectItem> |                             <MudSelectItem Value="value">@name</MudSelectItem> | ||||||
|                         } |                         } | ||||||
|                     </MudSelect> |                     </MudSelect> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|                 <MudItem xs="2" md="2"> |                 <MudItem xs="12" md="2"> | ||||||
|                     <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> |                     <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> | ||||||
|                 </MudItem> |                 </MudItem> | ||||||
|              |              | ||||||
|   | |||||||
| @@ -1,12 +1,13 @@ | |||||||
| @page "/" | @page "/" | ||||||
| @layout ListLayout | @layout ListLayout | ||||||
|  |  | ||||||
| <ContextMenu @ref="ContextMenu" Dense="true" AdjustmentX="@(DrawerOpen ? -235 : 0)"> | <ContextMenu @ref="ContextMenu" Dense="true" RelativeWidth="DropdownWidth.Ignore" AdjustmentX="-242" AdjustmentY="0"> | ||||||
|     <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> | </ContextMenu> | ||||||
|  |  | ||||||
|  | <div style="overflow-x: auto; white-space: nowrap; width: 100%;"> | ||||||
| <MudToolBar Gutters="false" Dense="true"> | <MudToolBar Gutters="false" Dense="true"> | ||||||
|     <MudIconButton Icon="@Icons.Material.Outlined.AddLink" OnClick="AddTorrentLink" title="Add torrent link" /> |     <MudIconButton Icon="@Icons.Material.Outlined.AddLink" OnClick="AddTorrentLink" title="Add torrent link" /> | ||||||
|     <MudIconButton Icon="@Icons.Material.Outlined.AddCircle" OnClick="AddTorrentFile" title="Add torrent file" /> |     <MudIconButton Icon="@Icons.Material.Outlined.AddCircle" OnClick="AddTorrentFile" title="Add torrent file" /> | ||||||
| @@ -18,6 +19,7 @@ | |||||||
|     <MudSpacer /> |     <MudSpacer /> | ||||||
|     <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> |     <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> | </MudToolBar> | ||||||
|  | </div> | ||||||
|  |  | ||||||
| <MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="ma-0 pa-0"> | <MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="ma-0 pa-0"> | ||||||
|     <DynamicTable |     <DynamicTable | ||||||
|   | |||||||
| @@ -193,7 +193,7 @@ namespace Lantean.QBTMud.Pages | |||||||
|         public static List<ColumnDefinition<Torrent>> ColumnsDefinitions { get; } = |         public static List<ColumnDefinition<Torrent>> ColumnsDefinitions { get; } = | ||||||
|         [ |         [ | ||||||
|             ColumnDefinitionHelper.CreateColumnDefinition<Torrent>("#", t => t.Priority), |             ColumnDefinitionHelper.CreateColumnDefinition<Torrent>("#", t => t.Priority), | ||||||
|             ColumnDefinitionHelper.CreateColumnDefinition("Icon", t => t.State, IconColumn, iconOnly: true, width: 25), |             ColumnDefinitionHelper.CreateColumnDefinition("Icon", t => t.State, IconColumn, iconOnly: true, width: 25, tdClass: "table-icon"), | ||||||
|             ColumnDefinitionHelper.CreateColumnDefinition<Torrent>("Name", t => t.Name, width: 400), |             ColumnDefinitionHelper.CreateColumnDefinition<Torrent>("Name", t => t.Name, width: 400), | ||||||
|             ColumnDefinitionHelper.CreateColumnDefinition<Torrent>("Size", t => t.Size, t => DisplayHelpers.Size(t.Size)), |             ColumnDefinitionHelper.CreateColumnDefinition<Torrent>("Size", t => t.Size, t => DisplayHelpers.Size(t.Size)), | ||||||
|             ColumnDefinitionHelper.CreateColumnDefinition<Torrent>("Total Size", t => t.TotalSize, t => DisplayHelpers.Size(t.TotalSize), enabled: false), |             ColumnDefinitionHelper.CreateColumnDefinition<Torrent>("Total Size", t => t.TotalSize, t => DisplayHelpers.Size(t.TotalSize), enabled: false), | ||||||
|   | |||||||
| @@ -155,7 +155,7 @@ code { | |||||||
| } | } | ||||||
|  |  | ||||||
| .torrent-list .mud-table-container { | .torrent-list .mud-table-container { | ||||||
|     height: calc(100vh - 149px); |     height: calc(100vh - 160px); | ||||||
| } | } | ||||||
|  |  | ||||||
| .file-list .mud-table-container { | .file-list .mud-table-container { | ||||||
| @@ -240,4 +240,19 @@ td .folder-button { | |||||||
|  |  | ||||||
| .mud-dialog .mud-dialog-content { | .mud-dialog .mud-dialog-content { | ||||||
|     padding-top: 4px !important; |     padding-top: 4px !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .icon-menu-dense { | ||||||
|  |     padding-top: 2px; | ||||||
|  |     padding-bottom: 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .table-icon { | ||||||
|  |     width: 25px; | ||||||
|  |     max-width: 25px; | ||||||
|  |     padding: 0 8px !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .mud-popover .mud-divider:last-child { | ||||||
|  |     display: none; | ||||||
| } | } | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| <Project Sdk="Microsoft.NET.Sdk"> | <Project Sdk="Microsoft.NET.Sdk"> | ||||||
|  |  | ||||||
|   <PropertyGroup> |   <PropertyGroup> | ||||||
|     <TargetFramework>net8.0</TargetFramework> |     <TargetFramework>net9.0</TargetFramework> | ||||||
|     <ImplicitUsings>enable</ImplicitUsings> |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
|     <Nullable>enable</Nullable> |     <Nullable>enable</Nullable> | ||||||
| 	<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | 	<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								nuget.config
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								nuget.config
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | <configuration> | ||||||
|  |   <packageSources> | ||||||
|  |     <!-- Define package sources here --> | ||||||
|  |   </packageSources> | ||||||
|  |   <packageSourceMapping> | ||||||
|  |     <!-- Optional source mapping --> | ||||||
|  |   </packageSourceMapping> | ||||||
|  |   <packageVersionOverride> | ||||||
|  |     <package id="FluentAssertions" allowedVersions="[7.0.0,8.0.0)" /> | ||||||
|  |   </packageVersionOverride> | ||||||
|  | </configuration> | ||||||
		Reference in New Issue
	
	Block a user