mirror of
				https://github.com/lantean-code/qbtmud.git
				synced 2025-10-31 20:13:31 +00:00 
			
		
		
		
	Compare commits
	
		
			18 Commits
		
	
	
		
			1.0.0
			...
			feature/fi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | fc51505e3f | ||
|  | 1cf9f97187 | ||
|  | 4f9129fd46 | ||
|  | 9a9d2c2ee2 | ||
|  | 736bc46745 | ||
|  | 23ae19c4c7 | ||
|  | 603470eb30 | ||
|  | 27c2406340 | ||
|  | 4578dcc11f | ||
|  | 3215fa3936 | ||
|  | 78e62f31d0 | ||
|  | e23842fcb0 | ||
|  | 411c7f87cc | ||
|  | 4098f8f5a9 | ||
|  | 12f81c5978 | ||
|  | 717738d720 | ||
|  | 885c34c8cf | ||
|  | ef3c68a6aa | 
| @@ -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() | ||||
|         { | ||||
| @@ -441,7 +415,7 @@ namespace Lantean.QBTMud.Components | ||||
|                     thereAreFirstLastPiecePrio = true; | ||||
|                 } | ||||
|  | ||||
|                 if (torrent.Progress > 0.999999) // not downloaded | ||||
|                 if (torrent.Progress < 0.999999) // not downloaded | ||||
|                 { | ||||
|                     allAreDownloaded = false; | ||||
|                 } | ||||
|   | ||||
| @@ -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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -37,7 +37,7 @@ namespace Lantean.QBTMud.Helpers | ||||
|             { | ||||
|                 time = TimeSpan.FromSeconds(seconds.Value); | ||||
|             } | ||||
|             catch (OverflowException) | ||||
|             catch | ||||
|             { | ||||
|                 return "∞"; | ||||
|             } | ||||
| @@ -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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -12,13 +12,11 @@ | ||||
|   <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="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" /> | ||||
|     <!-- added to fix vuln in dependency --> | ||||
| 	<PackageReference Include="System.Text.Json" Version="9.0.1" /> | ||||
|   </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> | ||||
|   | ||||
							
								
								
									
										92
									
								
								readme.md
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								readme.md
									
									
									
									
									
								
							| @@ -1,14 +1,82 @@ | ||||
| # qbt-mud | ||||
| # qbtmud | ||||
|  | ||||
| ## To-Do | ||||
| qbtmud is a drop-in replacement for qBittorrent's default WebUI, implementing all of its functionality with a modern and user-friendly interface. | ||||
|  | ||||
| - Rename multiple files dialog | ||||
| - ~~RSS feeds and dialogs~~ | ||||
| - ~~About~~ | ||||
| - ~~Context menu for files list/trackers list/peers list~~ | ||||
| - ~~Tag management page~~ | ||||
| - ~~Category management page~~ | ||||
| - ~~Update all tables to use DynamicTable~~ | ||||
|   - ~~Log~~ | ||||
|   - ~~Blocks~~ | ||||
|   - ~~Search~~ | ||||
| ## Features | ||||
|  | ||||
| qbtmud replicates all core features of the qBittorrent WebUI, including: | ||||
|  | ||||
| - **Torrent Management** – Add, remove, and control torrents. | ||||
| - **Tracker Control** – View and manage trackers. | ||||
| - **Peer Management** – Monitor and manage peers connected to torrents. | ||||
| - **File Prioritization** – Select and prioritize specific files within a torrent. | ||||
| - **Speed Limits** – Set global and per-torrent speed limits. | ||||
| - **RSS Integration** – Subscribe to RSS feeds for automated torrent downloads. | ||||
| - **Search Functionality** – Integrated torrent search. | ||||
| - **Sequential Downloading** – Download files in order for media streaming. | ||||
| - **Super Seeding Mode** – Efficiently distribute torrents as an initial seeder. | ||||
| - **IP Filtering** – Improve security by filtering specific IP addresses. | ||||
| - **IPv6 Support** – Full support for IPv6 networks. | ||||
| - **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). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Installation | ||||
|  | ||||
| To install qbtmud without building from source: | ||||
|  | ||||
| ### 1. Download the Latest Release | ||||
| - Go to the [qbtmud Releases](https://github.com/lantean-code/qbtmud/releases) page. | ||||
| - Download the latest release archive for your operating system. | ||||
|  | ||||
| ### 2. Extract the Archive | ||||
| - Extract the contents of the downloaded archive to a directory of your choice. | ||||
|  | ||||
| ### 3. Configure qBittorrent to Use qbtmud | ||||
| - Open qBittorrent and navigate to `Tools` > `Options` > `Web UI`. | ||||
| - Enable the option **"Use alternative WebUI"**. | ||||
| - Set the **"Root Folder"** to the directory where you extracted qbtmud. | ||||
| - Click **OK** to save the settings. | ||||
|  | ||||
| ### 4. Access qbtmud | ||||
| - Open your web browser and go to `http://localhost:8080` (or the port configured in qBittorrent). | ||||
|  | ||||
| For more detailed instructions, refer to the [Alternate WebUI Usage Guide](https://github.com/qbittorrent/qBittorrent/wiki/Alternate-WebUI-usage). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Building from Source | ||||
|  | ||||
| To build qbtmud from source, you need to have the **.NET 9.0 SDK** installed on your system. | ||||
|  | ||||
| ### 1. Clone the Repository | ||||
| ```sh | ||||
| git clone https://github.com/lantean-code/qbtmud.git | ||||
| cd qbtmud | ||||
| ``` | ||||
|  | ||||
| ### 2. Restore Dependencies | ||||
| ```sh | ||||
| dotnet restore | ||||
| ``` | ||||
|  | ||||
| ### 3. Build the Application | ||||
| ```sh | ||||
| dotnet build --configuration Release | ||||
| ``` | ||||
|  | ||||
| ### 4. Configure qBittorrent to Use qbtmud | ||||
| Follow the same steps as in the **Installation** section to set qbtmud as your WebUI. | ||||
|  | ||||
| ### 5. Run qbtmud | ||||
| Navigate to the directory containing the built files and run the application using the appropriate command for your OS. | ||||
|  | ||||
| By following these steps, you can set up qbtmud to manage your qBittorrent server with an improved web interface, offering better functionality and usability. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user