mirror of
				https://github.com/lantean-code/qbtmud.git
				synced 2025-11-04 05:53:22 +00:00 
			
		
		
		
	Compare commits
	
		
			11 Commits
		
	
	
		
			1.0.2
			...
			feature/fi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					fc51505e3f | ||
| 
						 | 
					1cf9f97187 | ||
| 
						 | 
					4f9129fd46 | ||
| 
						 | 
					9a9d2c2ee2 | ||
| 
						 | 
					736bc46745 | ||
| 
						 | 
					23ae19c4c7 | ||
| 
						 | 
					603470eb30 | ||
| 
						 | 
					27c2406340 | ||
| 
						 | 
					4578dcc11f | ||
| 
						 | 
					3215fa3936 | ||
| 
						 | 
					411c7f87cc | 
@@ -4,24 +4,20 @@
 | 
			
		||||
    <TargetFramework>net9.0</TargetFramework>
 | 
			
		||||
    <ImplicitUsings>enable</ImplicitUsings>
 | 
			
		||||
    <Nullable>enable</Nullable>
 | 
			
		||||
 | 
			
		||||
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
 | 
			
		||||
    <IsPackable>false</IsPackable>
 | 
			
		||||
    <IsTestProject>true</IsTestProject>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
	<PackageReference Include="FluentAssertions" Version="7.1.0" AllowedVersions="[5.0.0,7.*.*)" />
 | 
			
		||||
    <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="AwesomeAssertions" Version="9.2.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
 | 
			
		||||
    <PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
 | 
			
		||||
    <PackageReference Include="xunit" Version="2.9.3" />
 | 
			
		||||
    <PackageReference Include="xunit.runner.visualstudio" Version="3.0.1">
 | 
			
		||||
    <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
 | 
			
		||||
      <PrivateAssets>all</PrivateAssets>
 | 
			
		||||
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
 | 
			
		||||
    </PackageReference>
 | 
			
		||||
	  <PackageReference Include="System.Net.Http" Version="4.3.4" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ namespace Lantean.QBTMud.Test
 | 
			
		||||
            Test2(a => a.Name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void Test2(Expression<Func<TestClass, object>> expr)
 | 
			
		||||
        private void Test2(Expression<Func<TestClass, object?>> expr)
 | 
			
		||||
        {
 | 
			
		||||
            var body = expr.Body;
 | 
			
		||||
        }
 | 
			
		||||
@@ -38,7 +38,7 @@ namespace Lantean.QBTMud.Test
 | 
			
		||||
 | 
			
		||||
            var l = Expression.Lambda<Func<TestClass, object>>(convertExpression, expression);
 | 
			
		||||
 | 
			
		||||
            Expression<Func<TestClass, object>> expr2 = a => a.Name;
 | 
			
		||||
            Expression<Func<TestClass, object?>> expr2 = a => a.Name;
 | 
			
		||||
 | 
			
		||||
            var x = l.Compile();
 | 
			
		||||
            var res = (long)x(new TestClass { Name = "Name", Value = 12 });
 | 
			
		||||
@@ -58,9 +58,9 @@ namespace Lantean.QBTMud.Test
 | 
			
		||||
 | 
			
		||||
    public class TestClass
 | 
			
		||||
    {
 | 
			
		||||
        public string Name { get; set; }
 | 
			
		||||
        public string? Name { get; set; }
 | 
			
		||||
 | 
			
		||||
        public string Description { get; set; }
 | 
			
		||||
        public string? Description { get; set; }
 | 
			
		||||
 | 
			
		||||
        public long Value { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								Lantean.QBTMud/Components/Dialogs/SearchPluginsDialog.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								Lantean.QBTMud/Components/Dialogs/SearchPluginsDialog.razor
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
<MudDialog>
 | 
			
		||||
    <DialogContent>
 | 
			
		||||
        <MudGrid>
 | 
			
		||||
            <MudItem xs="12">
 | 
			
		||||
                <MudList T="string">
 | 
			
		||||
                    <MudListItem Icon="@Icons.Material.Filled.Add" IconColor="Color.Info" OnClick="AddCategory">Add</MudListItem>
 | 
			
		||||
                    <MudListItem Icon="@Icons.Material.Filled.Remove" IconColor="Color.Error" OnClick="RemoveCategory">Remove</MudListItem>
 | 
			
		||||
                    <MudDivider />
 | 
			
		||||
                    @foreach (var plugin in Plugins)
 | 
			
		||||
                    {
 | 
			
		||||
                        var pluginRef = plugin;
 | 
			
		||||
                        <MudListItem Icon="@GetIcon(pluginRef.FullName)" IconColor="Color.Default" OnClick="@(e => SetPlugin(pluginRef))">@pluginRef.Name</MudListItem>
 | 
			
		||||
                    }
 | 
			
		||||
                </MudList>
 | 
			
		||||
            </MudItem>
 | 
			
		||||
        </MudGrid>
 | 
			
		||||
    </DialogContent>
 | 
			
		||||
    <DialogActions>
 | 
			
		||||
    </DialogActions>
 | 
			
		||||
</MudDialog>
 | 
			
		||||
@@ -0,0 +1,72 @@
 | 
			
		||||
using Lantean.QBitTorrentClient;
 | 
			
		||||
using Lantean.QBitTorrentClient.Models;
 | 
			
		||||
using Lantean.QBTMud.Helpers;
 | 
			
		||||
using Microsoft.AspNetCore.Components;
 | 
			
		||||
using MudBlazor;
 | 
			
		||||
 | 
			
		||||
namespace Lantean.QBTMud.Components.Dialogs
 | 
			
		||||
{
 | 
			
		||||
    public partial class SearchPluginsDialog
 | 
			
		||||
    {
 | 
			
		||||
        [Inject]
 | 
			
		||||
        protected IApiClient ApiClient { get; set; } = default!;
 | 
			
		||||
 | 
			
		||||
        [Inject]
 | 
			
		||||
        protected IDialogService DialogService { get; set; } = default!;
 | 
			
		||||
 | 
			
		||||
        [CascadingParameter]
 | 
			
		||||
        IMudDialogInstance MudDialog { get; set; } = default!;
 | 
			
		||||
 | 
			
		||||
        protected HashSet<SearchPlugin> Plugins { get; set; } = [];
 | 
			
		||||
 | 
			
		||||
        protected IList<string> TorrentCategories { get; private set; } = [];
 | 
			
		||||
 | 
			
		||||
        protected override async Task OnInitializedAsync()
 | 
			
		||||
        {
 | 
			
		||||
            Plugins = [.. (await ApiClient.GetSearchPlugins())];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected string GetIcon(string tag)
 | 
			
		||||
        {
 | 
			
		||||
            return Icons.Material.Filled.PlusOne;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected async Task SetPlugin(QBitTorrentClient.Models.SearchPlugin plugin)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            await InvokeAsync(StateHasChanged);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected async Task AddCategory()
 | 
			
		||||
        {
 | 
			
		||||
            var addedCategoy = await DialogService.InvokeAddCategoryDialog(ApiClient);
 | 
			
		||||
            if (addedCategoy is null)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await ApiClient.SetTorrentCategory(addedCategoy, Hashes);
 | 
			
		||||
            Plugins.Add(addedCategoy);
 | 
			
		||||
            await GetTorrentCategories();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected async Task RemoveCategory()
 | 
			
		||||
        {
 | 
			
		||||
            await ApiClient.RemoveTorrentCategory(Hashes);
 | 
			
		||||
            await GetTorrentCategories();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected Task CloseDialog()
 | 
			
		||||
        {
 | 
			
		||||
            MudDialog.Close();
 | 
			
		||||
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void Cancel()
 | 
			
		||||
        {
 | 
			
		||||
            MudDialog.Cancel();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -12,10 +12,7 @@ namespace Lantean.QBTMud.Components
 | 
			
		||||
{
 | 
			
		||||
    public partial class TorrentActions : IAsyncDisposable
 | 
			
		||||
    {
 | 
			
		||||
        private const int _defaultVersion = 5;
 | 
			
		||||
 | 
			
		||||
        private bool _disposedValue;
 | 
			
		||||
        private int? _version;
 | 
			
		||||
 | 
			
		||||
        private List<UIAction>? _actions;
 | 
			
		||||
 | 
			
		||||
@@ -74,30 +71,7 @@ namespace Lantean.QBTMud.Components
 | 
			
		||||
 | 
			
		||||
        protected bool OverlayVisible { get; set; }
 | 
			
		||||
 | 
			
		||||
        protected int MajorVersion
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if (_version is not null)
 | 
			
		||||
                {
 | 
			
		||||
                    return _version.Value;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (string.IsNullOrEmpty(Version))
 | 
			
		||||
                {
 | 
			
		||||
                    return _defaultVersion;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!System.Version.TryParse(Version.Replace("v", ""), out var version))
 | 
			
		||||
                {
 | 
			
		||||
                    return _defaultVersion;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                _version = version.Major;
 | 
			
		||||
 | 
			
		||||
                return _version.Value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        protected int MajorVersion => VersionHelper.GetMajorVersion(Version);
 | 
			
		||||
 | 
			
		||||
        protected override void OnInitialized()
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -435,5 +435,22 @@ namespace Lantean.QBTMud.Helpers
 | 
			
		||||
 | 
			
		||||
            await dialogService.ShowAsync<SubMenuDialog>(parent.Text, parameters, FormDialogOptions);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task<QBitTorrentClient.Models.SearchPlugin?> ShowSearchPluginsDialog(this IDialogService dialogService)
 | 
			
		||||
        {
 | 
			
		||||
            var parameters = new DialogParameters
 | 
			
		||||
            {
 | 
			
		||||
                { nameof(SearchPluginsDialog.Hashes), "" },
 | 
			
		||||
            };
 | 
			
		||||
            
 | 
			
		||||
            var result = await dialogService.ShowAsync<SearchPluginsDialog>("Search Plugins", parameters, FormDialogOptions);
 | 
			
		||||
            var dialogResult = await result.Result;
 | 
			
		||||
            if (dialogResult is null || dialogResult.Canceled || dialogResult.Data is null)
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return (QBitTorrentClient.Models.SearchPlugin)dialogResult.Data;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -129,7 +129,7 @@ namespace Lantean.QBTMud.Helpers
 | 
			
		||||
                return "";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return Size(size);
 | 
			
		||||
            return Size(size, prefix, suffix);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								Lantean.QBTMud/Helpers/VersionHelper.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Lantean.QBTMud/Helpers/VersionHelper.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
 | 
			
		||||
namespace Lantean.QBTMud.Helpers
 | 
			
		||||
{
 | 
			
		||||
    internal static class VersionHelper
 | 
			
		||||
    {
 | 
			
		||||
        private static int? _version;
 | 
			
		||||
 | 
			
		||||
        private const int _defaultVersion = 5;
 | 
			
		||||
 | 
			
		||||
        public static int DefaultVersion => _defaultVersion;
 | 
			
		||||
 | 
			
		||||
        public static int GetMajorVersion(string? version)
 | 
			
		||||
        {
 | 
			
		||||
            if (_version is not null)
 | 
			
		||||
            {
 | 
			
		||||
                return _version.Value;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (string.IsNullOrEmpty(version))
 | 
			
		||||
            {
 | 
			
		||||
                return _defaultVersion;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!Version.TryParse(version?.Replace("v", ""), out var theVersion))
 | 
			
		||||
            {
 | 
			
		||||
                return _defaultVersion;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _version = theVersion.Major;
 | 
			
		||||
 | 
			
		||||
            return _version.Value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -4,21 +4,19 @@
 | 
			
		||||
    <TargetFramework>net9.0</TargetFramework>
 | 
			
		||||
    <Nullable>enable</Nullable>
 | 
			
		||||
    <ImplicitUsings>enable</ImplicitUsings>
 | 
			
		||||
	<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
 | 
			
		||||
	<CompressionEnabled>false</CompressionEnabled>
 | 
			
		||||
	<LangVersion>12</LangVersion>
 | 
			
		||||
	  <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
 | 
			
		||||
	  <CompressionEnabled>false</CompressionEnabled>
 | 
			
		||||
	  <LangVersion>12</LangVersion>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
	<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
 | 
			
		||||
	<PackageReference Include="ByteSize" Version="2.1.2" />
 | 
			
		||||
	<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.1" />
 | 
			
		||||
	<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.1" PrivateAssets="all" />
 | 
			
		||||
	<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.1" />
 | 
			
		||||
	<PackageReference Include="MudBlazor" Version="8.2.0" />
 | 
			
		||||
	<PackageReference Include="MudBlazor.ThemeManager" Version="3.0.0" />
 | 
			
		||||
    <!-- added to fix vuln in dependency -->
 | 
			
		||||
	<PackageReference Include="System.Text.Json" Version="9.0.1" />
 | 
			
		||||
	  <PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
 | 
			
		||||
	  <PackageReference Include="ByteSize" Version="2.1.2" />
 | 
			
		||||
	  <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.10" />
 | 
			
		||||
	  <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.10" PrivateAssets="all" />
 | 
			
		||||
	  <PackageReference Include="Microsoft.Extensions.Http" Version="9.0.10" />
 | 
			
		||||
	  <PackageReference Include="MudBlazor" Version="8.13.0" />
 | 
			
		||||
	  <PackageReference Include="MudBlazor.ThemeManager" Version="3.0.0" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
 
 | 
			
		||||
@@ -83,7 +83,7 @@ namespace Lantean.QBTMud.Layout
 | 
			
		||||
            Preferences = await ApiClient.GetApplicationPreferences();
 | 
			
		||||
            Version = await ApiClient.GetApplicationVersion();
 | 
			
		||||
            var data = await ApiClient.GetMainData(_requestId);
 | 
			
		||||
            MainData = DataManager.CreateMainData(data);
 | 
			
		||||
            MainData = DataManager.CreateMainData(data, Version);
 | 
			
		||||
 | 
			
		||||
            _requestId = data.ResponseId;
 | 
			
		||||
            _refreshInterval = MainData.ServerState.RefreshInterval;
 | 
			
		||||
@@ -128,7 +128,7 @@ namespace Lantean.QBTMud.Layout
 | 
			
		||||
 | 
			
		||||
                        if (MainData is null || data.FullUpdate)
 | 
			
		||||
                        {
 | 
			
		||||
                            MainData = DataManager.CreateMainData(data);
 | 
			
		||||
                            MainData = DataManager.CreateMainData(data, Version);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,6 @@ namespace Lantean.QBTMud.Layout
 | 
			
		||||
 | 
			
		||||
        private bool _disposedValue;
 | 
			
		||||
 | 
			
		||||
        [Inject]
 | 
			
		||||
        protected NavigationManager NavigationManager { get; set; } = default!;
 | 
			
		||||
 | 
			
		||||
        [Inject]
 | 
			
		||||
        private IBrowserViewportService BrowserViewportService { get; set; } = default!;
 | 
			
		||||
 | 
			
		||||
@@ -78,13 +75,13 @@ namespace Lantean.QBTMud.Layout
 | 
			
		||||
                {
 | 
			
		||||
                    IsDarkMode = isDarkMode.Value;
 | 
			
		||||
                }
 | 
			
		||||
                await MudThemeProvider.WatchSystemPreference(OnSystemPreferenceChanged);
 | 
			
		||||
                await MudThemeProvider.WatchSystemDarkModeAsync(OnSystemDarkModeChanged);
 | 
			
		||||
                await BrowserViewportService.SubscribeAsync(this, fireImmediately: true);
 | 
			
		||||
                await InvokeAsync(StateHasChanged);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected Task OnSystemPreferenceChanged(bool value)
 | 
			
		||||
        protected Task OnSystemDarkModeChanged(bool value)
 | 
			
		||||
        {
 | 
			
		||||
            IsDarkMode = value;
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,8 @@
 | 
			
		||||
            Dictionary<string, HashSet<string>> tagState,
 | 
			
		||||
            Dictionary<string, HashSet<string>> categoriesState,
 | 
			
		||||
            Dictionary<string, HashSet<string>> statusState,
 | 
			
		||||
            Dictionary<string, HashSet<string>> trackersState)
 | 
			
		||||
            Dictionary<string, HashSet<string>> trackersState,
 | 
			
		||||
            int majorVersion)
 | 
			
		||||
        {
 | 
			
		||||
            Torrents = torrents.ToDictionary();
 | 
			
		||||
            Tags = tags.ToHashSet();
 | 
			
		||||
@@ -22,6 +23,7 @@
 | 
			
		||||
            CategoriesState = categoriesState;
 | 
			
		||||
            StatusState = statusState;
 | 
			
		||||
            TrackersState = trackersState;
 | 
			
		||||
            MajorVersion = majorVersion;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Dictionary<string, Torrent> Torrents { get; }
 | 
			
		||||
@@ -36,5 +38,6 @@
 | 
			
		||||
        public Dictionary<string, HashSet<string>> TrackersState { get; }
 | 
			
		||||
        public string? SelectedTorrentHash { get; set; }
 | 
			
		||||
        public bool LostConnection { get; set; }
 | 
			
		||||
        public int MajorVersion { get; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
        Completed,
 | 
			
		||||
        Resumed,
 | 
			
		||||
        Paused,
 | 
			
		||||
        Stopped,
 | 
			
		||||
        Active,
 | 
			
		||||
        Inactive,
 | 
			
		||||
        Stalled,
 | 
			
		||||
@@ -15,6 +16,6 @@
 | 
			
		||||
        StalledDownloading,
 | 
			
		||||
        Checking,
 | 
			
		||||
        Errored,
 | 
			
		||||
        Stopped
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -9,6 +9,8 @@
 | 
			
		||||
    }
 | 
			
		||||
    <MudDivider Vertical="true" />
 | 
			
		||||
    <MudText Class="pl-5 no-wrap">Search</MudText>
 | 
			
		||||
    <MudDivider Vertical="true" />
 | 
			
		||||
    <MudIconButton Icon="@Icons.Material.Outlined.Settings" OnClick="ShowSearchPlugins" title="Search plugins" />
 | 
			
		||||
</MudToolBar>
 | 
			
		||||
 | 
			
		||||
<MudCard Elevation="1" Class="ml-4 mr-4 mb-4">
 | 
			
		||||
 
 | 
			
		||||
@@ -150,6 +150,11 @@ namespace Lantean.QBTMud.Pages
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected async Task ShowSearchPlugins()
 | 
			
		||||
        {
 | 
			
		||||
            await DialogService.ShowSearchPluginsDialog();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected IEnumerable<ColumnDefinition<QBitTorrentClient.Models.SearchResult>> Columns => ColumnsDefinitions;
 | 
			
		||||
 | 
			
		||||
        public static List<ColumnDefinition<QBitTorrentClient.Models.SearchResult>> ColumnsDefinitions { get; } =
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
{
 | 
			
		||||
    public class DataManager : IDataManager
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly Status[] _statuses = Enum.GetValues<Status>();
 | 
			
		||||
        private static Status[]? _statusArray = null;
 | 
			
		||||
 | 
			
		||||
        public PeerList CreatePeerList(QBitTorrentClient.Models.TorrentPeers torrentPeers)
 | 
			
		||||
        {
 | 
			
		||||
@@ -25,8 +25,9 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
            return peerList;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public MainData CreateMainData(QBitTorrentClient.Models.MainData mainData)
 | 
			
		||||
        public MainData CreateMainData(QBitTorrentClient.Models.MainData mainData, string version)
 | 
			
		||||
        {
 | 
			
		||||
            var majorVersion = VersionHelper.GetMajorVersion(version);
 | 
			
		||||
            var torrents = new Dictionary<string, Torrent>(mainData.Torrents?.Count ?? 0);
 | 
			
		||||
            if (mainData.Torrents is not null)
 | 
			
		||||
            {
 | 
			
		||||
@@ -87,8 +88,9 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
                categoriesState.Add(category, torrents.Values.Where(t => FilterHelper.FilterCategory(t, category, serverState.UseSubcategories)).ToHashesHashSet());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var statusState = new Dictionary<string, HashSet<string>>(_statuses.Length + 2);
 | 
			
		||||
            foreach (var status in _statuses)
 | 
			
		||||
            var statuses = GetStatuses(majorVersion).ToArray();
 | 
			
		||||
            var statusState = new Dictionary<string, HashSet<string>>(statuses.Length + 2);
 | 
			
		||||
            foreach (var status in statuses)
 | 
			
		||||
            {
 | 
			
		||||
                statusState.Add(status.ToString(), torrents.Values.Where(t => FilterHelper.FilterStatus(t, status)).ToHashesHashSet());
 | 
			
		||||
            }
 | 
			
		||||
@@ -101,7 +103,7 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
                trackersState.Add(tracker, torrents.Values.Where(t => FilterHelper.FilterTracker(t, tracker)).ToHashesHashSet());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var torrentList = new MainData(torrents, tags, categories, trackers, serverState, tagState, categoriesState, statusState, trackersState);
 | 
			
		||||
            var torrentList = new MainData(torrents, tags, categories, trackers, serverState, tagState, categoriesState, statusState, trackersState, majorVersion);
 | 
			
		||||
 | 
			
		||||
            return torrentList;
 | 
			
		||||
        }
 | 
			
		||||
@@ -206,7 +208,7 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
            {
 | 
			
		||||
                foreach (var (url, hashes) in mainData.Trackers)
 | 
			
		||||
                {
 | 
			
		||||
                    if (!torrentList.Trackers.TryGetValue(url, out var existingHashes))
 | 
			
		||||
                    if (!torrentList.Trackers.TryGetValue(url, out _))
 | 
			
		||||
                    {
 | 
			
		||||
                        torrentList.Trackers.Add(url, hashes);
 | 
			
		||||
                    }
 | 
			
		||||
@@ -225,7 +227,7 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
                    {
 | 
			
		||||
                        var newTorrent = CreateTorrent(hash, torrent);
 | 
			
		||||
                        torrentList.Torrents.Add(hash, newTorrent);
 | 
			
		||||
                        AddTorrentToStates(torrentList, hash);
 | 
			
		||||
                        AddTorrentToStates(torrentList, hash, torrentList.MajorVersion);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
@@ -241,7 +243,7 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static void AddTorrentToStates(MainData torrentList, string hash)
 | 
			
		||||
        private static void AddTorrentToStates(MainData torrentList, string hash, int version)
 | 
			
		||||
        {
 | 
			
		||||
            var torrent = torrentList.Torrents[hash];
 | 
			
		||||
 | 
			
		||||
@@ -271,7 +273,7 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
                value.AddIfTrue(hash, FilterHelper.FilterCategory(torrent, category, torrentList.ServerState.UseSubcategories));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var status in _statuses)
 | 
			
		||||
            foreach (var status in GetStatuses(version))
 | 
			
		||||
            {
 | 
			
		||||
                torrentList.StatusState[status.ToString()].AddIfTrue(hash, FilterHelper.FilterStatus(torrent, status));
 | 
			
		||||
            }
 | 
			
		||||
@@ -289,6 +291,25 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static Status[] GetStatuses(int version)
 | 
			
		||||
        {
 | 
			
		||||
            if (_statusArray is not null)
 | 
			
		||||
            {
 | 
			
		||||
                return _statusArray;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (version == 5)
 | 
			
		||||
            {
 | 
			
		||||
                _statusArray = Enum.GetValues<Status>().Where(s => s != Status.Paused).ToArray();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                _statusArray = Enum.GetValues<Status>().Where(s => s != Status.Stopped).ToArray();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return _statusArray;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static void UpdateTorrentStates(MainData torrentList, string hash)
 | 
			
		||||
        {
 | 
			
		||||
            var torrent = torrentList.Torrents[hash];
 | 
			
		||||
@@ -317,7 +338,7 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
                value.AddIfTrueOrRemove(hash, FilterHelper.FilterCategory(torrent, category, torrentList.ServerState.UseSubcategories));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var status in _statuses)
 | 
			
		||||
            foreach (var status in GetStatuses(torrentList.MajorVersion))
 | 
			
		||||
            {
 | 
			
		||||
                torrentList.StatusState[status.ToString()].AddIfTrueOrRemove(hash, FilterHelper.FilterStatus(torrent, status));
 | 
			
		||||
            }
 | 
			
		||||
@@ -361,7 +382,7 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
                categoryState.RemoveIfTrue(hash, FilterHelper.FilterCategory(torrent, category, torrentList.ServerState.UseSubcategories));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var status in _statuses)
 | 
			
		||||
            foreach (var status in GetStatuses(torrentList.MajorVersion))
 | 
			
		||||
            {
 | 
			
		||||
                if (!torrentList.StatusState.TryGetValue(status.ToString(), out var statusState))
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ namespace Lantean.QBTMud.Services
 | 
			
		||||
{
 | 
			
		||||
    public interface IDataManager
 | 
			
		||||
    {
 | 
			
		||||
        MainData CreateMainData(QBitTorrentClient.Models.MainData mainData);
 | 
			
		||||
        MainData CreateMainData(QBitTorrentClient.Models.MainData mainData, string version);
 | 
			
		||||
 | 
			
		||||
        Torrent CreateTorrent(string hash, QBitTorrentClient.Models.Torrent torrent);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,12 +9,12 @@
 | 
			
		||||
    <link rel="preconnect" href="https://fonts.googleapis.com">
 | 
			
		||||
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
 | 
			
		||||
    <link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&display=swap" rel="stylesheet">
 | 
			
		||||
    <link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
 | 
			
		||||
    <link rel="stylesheet" href="css/app.css" />
 | 
			
		||||
    <link href="./_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
 | 
			
		||||
    <link rel="stylesheet" href="./css/app.css" />
 | 
			
		||||
    <link rel="icon" type="image/png" href="images/qbittorrent32.png" />
 | 
			
		||||
    <link rel="icon" href="images/qbittorrent-tray.svg">
 | 
			
		||||
    <link rel="mask-icon" href="images/qbittorrent-tray.svg" color="#000000">
 | 
			
		||||
    <link rel="apple-touch-icon" href="images/qbittorrent32.png">
 | 
			
		||||
    <link rel="icon" href="./images/qbittorrent-tray.svg">
 | 
			
		||||
    <link rel="mask-icon" href="./images/qbittorrent-tray.svg" color="#000000">
 | 
			
		||||
    <link rel="apple-touch-icon" href="./images/qbittorrent32.png">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
@@ -31,10 +31,10 @@
 | 
			
		||||
        <a href="" class="reload">Reload</a>
 | 
			
		||||
        <a class="dismiss">🗙</a>
 | 
			
		||||
    </div>
 | 
			
		||||
    <script src="_framework/blazor.webassembly.js"></script>
 | 
			
		||||
    <script src="_content/MudBlazor/MudBlazor.min.js"></script>
 | 
			
		||||
    <script src="js/piecesbar.js"></script>
 | 
			
		||||
    <script src="js/interop.js"></script>
 | 
			
		||||
    <script src="./_framework/blazor.webassembly.js"></script>
 | 
			
		||||
    <script src="./_content/MudBlazor/MudBlazor.min.js"></script>
 | 
			
		||||
    <script src="./js/piecesbar.js"></script>
 | 
			
		||||
    <script src="./js/interop.js"></script>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
    <TargetFramework>net9.0</TargetFramework>
 | 
			
		||||
    <ImplicitUsings>enable</ImplicitUsings>
 | 
			
		||||
    <Nullable>enable</Nullable>
 | 
			
		||||
	<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
 | 
			
		||||
	  <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,11 @@ qbtmud replicates all core features of the qBittorrent WebUI, including:
 | 
			
		||||
- **Bandwidth Scheduler** – Schedule bandwidth limits.
 | 
			
		||||
- **WebUI Access** – Remotely manage torrents through the WebUI.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||

 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
For a detailed explanation of these features, refer to the [qBittorrent Options Guide](https://github.com/qbittorrent/qBittorrent/wiki/Explanation-of-Options-in-qBittorrent).
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user