Fix filter crash on files and add local storage for column sorts and filter nav

This commit is contained in:
ahjephson
2024-05-13 12:01:07 +01:00
parent 10eeeb9060
commit baa80220e4
10 changed files with 161 additions and 76 deletions

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Rendering;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Runtime.ExceptionServices;
namespace Lantean.QBTMudBlade.Components namespace Lantean.QBTMudBlade.Components
{ {
@@ -13,10 +14,18 @@ namespace Lantean.QBTMudBlade.Components
[Parameter] [Parameter]
public EventCallback OnClear { get; set; } public EventCallback OnClear { get; set; }
[Parameter]
public bool Disabled { get; set; }
protected override Task OnErrorAsync(Exception exception) protected override Task OnErrorAsync(Exception exception)
{ {
_exceptions.Add(exception); _exceptions.Add(exception);
if (Disabled)
{
ExceptionDispatchInfo.Capture(exception).Throw();
}
return Task.CompletedTask; return Task.CompletedTask;
} }

View File

@@ -26,7 +26,8 @@
OnRowClick="RowClick" OnRowClick="RowClick"
RowStyleFunc="RowStyle" RowStyleFunc="RowStyle"
RowClassFunc="RowClass" RowClassFunc="RowClass"
AllowUnsorted="false"> AllowUnsorted="false"
Virtualize="true">
<ColGroup> <ColGroup>
<col style="width: 30px" /> <col style="width: 30px" />
@foreach (var column in GetColumns()) @foreach (var column in GetColumns())
@@ -41,7 +42,7 @@
<MudTh> <MudTh>
@if (column.SortSelector is not null) @if (column.SortSelector is not null)
{ {
<MudTableSortLabel T="Torrent" SortDirectionChanged="@(c => SetSort(column.SortSelector, c))" InitialDirection="column.InitialDirection">@column.Header</MudTableSortLabel> <MudTableSortLabel T="ContentItem" SortDirectionChanged="@(c => SetSort(column.Id, c))" InitialDirection="column.InitialDirection">@column.Header</MudTableSortLabel>
} }
else else
{ {

View File

@@ -16,14 +16,15 @@ namespace Lantean.QBTMudBlade.Components
{ {
private readonly bool _refreshEnabled = true; private readonly bool _refreshEnabled = true;
private const string _columnStorageKey = "FilesTab.Columns"; private const string _columnSelectionStorageKey = "FilesTab.ColumnSelection";
private const string _columnSortStorageKey = "FilesTab.ColumnSort";
private readonly CancellationTokenSource _timerCancellationToken = new(); private readonly CancellationTokenSource _timerCancellationToken = new();
private bool _disposedValue; private bool _disposedValue;
private Func<ContentItem, object?> SortSelector { get; set; } = c => c.Name; private string? _sortColumn;
private SortDirection SortDirection { get; set; } = SortDirection.Ascending; private SortDirection _sortDirection = SortDirection.Ascending;
[Parameter] [Parameter]
public bool Active { get; set; } public bool Active { get; set; }
@@ -55,6 +56,7 @@ namespace Lantean.QBTMudBlade.Components
protected HashSet<ContentItem> SelectedItems { get; set; } = []; protected HashSet<ContentItem> SelectedItems { get; set; } = [];
protected List<ColumnDefinition<ContentItem>> _columns = []; protected List<ColumnDefinition<ContentItem>> _columns = [];
private List<PropertyFilterDefinition<ContentItem>>? _filterDefinitions;
protected ContentItem? SelectedItem { get; set; } protected ContentItem? SelectedItem { get; set; }
@@ -80,18 +82,18 @@ namespace Lantean.QBTMudBlade.Components
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (!await LocalStorage.ContainKeyAsync(_columnStorageKey)) var selectedColumns = await LocalStorage.GetItemAsync<HashSet<string>>(_columnSelectionStorageKey);
if (selectedColumns is not null)
{ {
return; SelectedColumns = selectedColumns;
} }
var selectedColumns = await LocalStorage.GetItemAsync<HashSet<string>>(_columnStorageKey); var columnSort = await LocalStorage.GetItemAsync<Tuple<string, SortDirection>>(_columnSortStorageKey);
if (selectedColumns is null) if (columnSort is not null)
{ {
return; _sortColumn = columnSort.Item1;
_sortDirection = columnSort.Item2;
} }
SelectedColumns = selectedColumns;
} }
protected IEnumerable<ColumnDefinition<ContentItem>> GetColumns() protected IEnumerable<ColumnDefinition<ContentItem>> GetColumns()
@@ -116,14 +118,14 @@ namespace Lantean.QBTMudBlade.Components
SelectedColumns = (HashSet<string>)result.Data; SelectedColumns = (HashSet<string>)result.Data;
await LocalStorage.SetItemAsync(_columnStorageKey, SelectedColumns); await LocalStorage.SetItemAsync(_columnSelectionStorageKey, SelectedColumns);
} }
protected async Task ShowFilterDialog() protected async Task ShowFilterDialog()
{ {
var parameters = new DialogParameters var parameters = new DialogParameters
{ {
{ nameof(FilterOptionsDialog<ContentItem>.FilterDefinitions), Filters }, { nameof(FilterOptionsDialog<ContentItem>.FilterDefinitions), _filterDefinitions },
}; };
var result = await DialogService.ShowAsync<FilterOptionsDialog<ContentItem>>("Filters", parameters, DialogHelper.FormDialogOptions); var result = await DialogService.ShowAsync<FilterOptionsDialog<ContentItem>>("Filters", parameters, DialogHelper.FormDialogOptions);
@@ -134,14 +136,15 @@ namespace Lantean.QBTMudBlade.Components
return; return;
} }
var filterDefinitions = (List<PropertyFilterDefinition<ContentItem>>?)dialogResult.Data; _filterDefinitions = (List<PropertyFilterDefinition<ContentItem>>?)dialogResult.Data;
if (filterDefinitions is null) if (_filterDefinitions is null)
{ {
Filters = null;
return; return;
} }
var filters = new List<Func<ContentItem, bool>>(); var filters = new List<Func<ContentItem, bool>>();
foreach (var filterDefinition in filterDefinitions) foreach (var filterDefinition in _filterDefinitions)
{ {
var expression = Filter.FilterExpressionGenerator.GenerateExpression(filterDefinition, false); var expression = Filter.FilterExpressionGenerator.GenerateExpression(filterDefinition, false);
filters.Add(expression.Compile()); filters.Add(expression.Compile());
@@ -154,6 +157,11 @@ namespace Lantean.QBTMudBlade.Components
{ {
Filters = null; Filters = null;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
if (FileList is null)
{
return;
}
SelectedItems = FileList.Values.Where(f => f.Priority != Priority.DoNotDownload).ToHashSet();
} }
public async ValueTask DisposeAsync() public async ValueTask DisposeAsync()
@@ -378,10 +386,12 @@ namespace Lantean.QBTMudBlade.Components
} }
} }
private void SetSort(Func<ContentItem, object?> sortSelector, SortDirection sortDirection) private async Task SetSort(string columnId, SortDirection sortDirection)
{ {
SortSelector = sortSelector; _sortColumn = columnId;
SortDirection = sortDirection; _sortDirection = sortDirection;
await LocalStorage.SetItemAsync(_columnSortStorageKey, new Tuple<string, SortDirection>(columnId, sortDirection));
} }
protected void ToggleNode(ContentItem contentItem, MouseEventArgs args) protected void ToggleNode(ContentItem contentItem, MouseEventArgs args)
@@ -411,11 +421,19 @@ namespace Lantean.QBTMudBlade.Components
return Files.Where(f => f.Name.StartsWith(contentItem.Name + Extensions.DirectorySeparator) && !f.IsFolder); return Files.Where(f => f.Name.StartsWith(contentItem.Name + Extensions.DirectorySeparator) && !f.IsFolder);
} }
private Func<ContentItem, object?> GetSortSelector()
{
var sortSelector = _columns.Find(c => c.Id == _sortColumn)?.SortSelector;
return sortSelector ?? (i => i.Name);
}
private IEnumerable<ContentItem> GetDescendants(ContentItem folder, int level) private IEnumerable<ContentItem> GetDescendants(ContentItem folder, int level)
{ {
level++; level++;
var descendantsKey = folder.GetDescendantsKey(level); var descendantsKey = folder.GetDescendantsKey(level);
foreach (var item in FileList!.Values.Where(f => f.Name.StartsWith(descendantsKey)).OrderByDirection(SortDirection, SortSelector))
foreach (var item in FileList!.Values.Where(f => f.Name.StartsWith(descendantsKey)).OrderByDirection(_sortDirection, GetSortSelector()))
{ {
if (item.IsFolder) if (item.IsFolder)
{ {
@@ -474,12 +492,12 @@ namespace Lantean.QBTMudBlade.Components
// this is a flat file structure // this is a flat file structure
if (maxLevel == 0) if (maxLevel == 0)
{ {
return FileList.Values.Where(FilterContentItem).OrderByDirection(SortDirection, SortSelector).ToList().AsReadOnly(); return FileList.Values.Where(FilterContentItem).OrderByDirection(_sortDirection, GetSortSelector()).ToList().AsReadOnly();
} }
var list = new List<ContentItem>(); var list = new List<ContentItem>();
var folders = FileList.Values.Where(c => c.IsFolder && c.Level == 0).OrderByDirection(SortDirection, SortSelector).ToList(); var folders = FileList.Values.Where(c => c.IsFolder && c.Level == 0).OrderByDirection(_sortDirection, GetSortSelector()).ToList();
foreach (var folder in folders) foreach (var folder in folders)
{ {
list.Add(folder); list.Add(folder);

View File

@@ -1,4 +1,5 @@
using Lantean.QBTMudBlade.Models; using Blazored.LocalStorage;
using Lantean.QBTMudBlade.Models;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using MudBlazor; using MudBlazor;
@@ -6,6 +7,11 @@ namespace Lantean.QBTMudBlade.Components
{ {
public partial class FiltersNav public partial class FiltersNav
{ {
private const string _statusSelectionStorageKey = "FiltersNav.Selection.Status";
private const string _categorySelectionStorageKey = "FiltersNav.Selection.Category";
private const string _tagSelectionStorageKey = "FiltersNav.Selection.Tag";
private const string _trackerSelectionStorageKey = "FiltersNav.Selection.Tracker";
private bool _statusExpanded = true; private bool _statusExpanded = true;
private bool _categoriesExpanded = true; private bool _categoriesExpanded = true;
private bool _tagsExpanded = true; private bool _tagsExpanded = true;
@@ -19,6 +25,9 @@ namespace Lantean.QBTMudBlade.Components
protected string Tracker { get; set; } = FilterHelper.TRACKER_ALL; protected string Tracker { get; set; } = FilterHelper.TRACKER_ALL;
[Inject]
public ILocalStorageService LocalStorage { get; set; } = default!;
[CascadingParameter] [CascadingParameter]
public MainData? MainData { get; set; } public MainData? MainData { get; set; }
@@ -42,28 +51,55 @@ namespace Lantean.QBTMudBlade.Components
public Dictionary<string, int> Statuses => MainData?.StatusState.ToDictionary(d => d.Key, d => d.Value.Count) ?? []; public Dictionary<string, int> Statuses => MainData?.StatusState.ToDictionary(d => d.Key, d => d.Value.Count) ?? [];
protected override async Task OnInitializedAsync()
{
if (await LocalStorage.ContainKeyAsync(_statusSelectionStorageKey))
{
Status = await LocalStorage.GetItemAsStringAsync(_statusSelectionStorageKey) ?? Models.Status.All.ToString();
}
if (await LocalStorage.ContainKeyAsync(_categorySelectionStorageKey))
{
Category = await LocalStorage.GetItemAsStringAsync(_categorySelectionStorageKey) ?? FilterHelper.CATEGORY_ALL;
}
if (await LocalStorage.ContainKeyAsync(_tagSelectionStorageKey))
{
Tag = await LocalStorage.GetItemAsStringAsync(_tagSelectionStorageKey) ?? FilterHelper.TAG_ALL;
}
if (await LocalStorage.ContainKeyAsync(_trackerSelectionStorageKey))
{
Tracker = await LocalStorage.GetItemAsStringAsync(_trackerSelectionStorageKey) ?? FilterHelper.TRACKER_ALL;
}
}
protected async Task StatusValueChanged(string value) protected async Task StatusValueChanged(string value)
{ {
Status = value; Status = value;
await StatusChanged.InvokeAsync(Enum.Parse<Status>(value)); await StatusChanged.InvokeAsync(Enum.Parse<Status>(value));
await LocalStorage.SetItemAsStringAsync(_statusSelectionStorageKey, value);
} }
protected async Task CategoryValueChanged(string value) protected async Task CategoryValueChanged(string value)
{ {
Category = value; Category = value;
await CategoryChanged.InvokeAsync(value); await CategoryChanged.InvokeAsync(value);
await LocalStorage.SetItemAsStringAsync(_categorySelectionStorageKey, value);
} }
protected async Task TagValueChanged(string value) protected async Task TagValueChanged(string value)
{ {
Tag = value; Tag = value;
await TagChanged.InvokeAsync(value); await TagChanged.InvokeAsync(value);
await LocalStorage.SetItemAsStringAsync(_tagSelectionStorageKey, value);
} }
protected async Task TrackerValueChanged(string value) protected async Task TrackerValueChanged(string value)
{ {
Tracker = value; Tracker = value;
await TrackerChanged.InvokeAsync(value); await TrackerChanged.InvokeAsync(value);
await LocalStorage.SetItemAsStringAsync(_trackerSelectionStorageKey, value);
} }
protected static string GetHostName(string tracker) protected static string GetHostName(string tracker)
@@ -78,7 +114,5 @@ namespace Lantean.QBTMudBlade.Components
return tracker; return tracker;
} }
} }
} }
} }

View File

@@ -28,6 +28,11 @@ namespace Lantean.QBTMudBlade
return "∞"; return "∞";
} }
if (seconds < 60)
{
return "< 1m";
}
var time = TimeSpan.FromSeconds(seconds.Value); var time = TimeSpan.FromSeconds(seconds.Value);
var sb = new StringBuilder(); var sb = new StringBuilder();
if (prefix is not null) if (prefix is not null)
@@ -85,6 +90,11 @@ namespace Lantean.QBTMudBlade
return ""; return "";
} }
if (size < 0)
{
size = 0;
}
var stringBuilder = new StringBuilder(); var stringBuilder = new StringBuilder();
if (prefix is not null) if (prefix is not null)
{ {
@@ -275,6 +285,11 @@ namespace Lantean.QBTMudBlade
return ""; return "";
} }
if (value < 0)
{
value = 0;
}
if (value == 0) if (value == 0)
{ {
return "0%"; return "0%";

View File

@@ -30,17 +30,17 @@ namespace Lantean.QBTMudBlade.Filter
return filter.Operator switch return filter.Operator switch
{ {
FilterOperator.String.Contains => FilterOperator.String.Contains =>
propertyExpression.Modify<T>((Expression<Func<string?, bool>>)(x => x != null && value != null && x.Contains(value, stringComparer))), propertyExpression.Modify<T>((Expression<Func<object?, bool>>)(x => (string?)x != null && value != null && ((string)x).Contains(value, stringComparer))),
FilterOperator.String.NotContains => FilterOperator.String.NotContains =>
propertyExpression.Modify<T>((Expression<Func<string?, bool>>)(x => x != null && value != null && !x.Contains(value, stringComparer))), propertyExpression.Modify<T>((Expression<Func<object?, bool>>)(x => (string?)x != null && value != null && !((string)x).Contains(value, stringComparer))),
FilterOperator.String.Equal => FilterOperator.String.Equal =>
propertyExpression.Modify<T>((Expression<Func<string?, bool>>)(x => x != null && x.Equals(value, stringComparer))), propertyExpression.Modify<T>((Expression<Func<object?, bool>>)(x => (string?)x != null && ((string)x).Equals(value, stringComparer))),
FilterOperator.String.NotEqual => FilterOperator.String.NotEqual =>
propertyExpression.Modify<T>((Expression<Func<string?, bool>>)(x => x != null && !x.Equals(value, stringComparer))), propertyExpression.Modify<T>((Expression<Func<object?, bool>>)(x => (string?)x != null && !((string)x).Equals(value, stringComparer))),
FilterOperator.String.StartsWith => FilterOperator.String.StartsWith =>
propertyExpression.Modify<T>((Expression<Func<string?, bool>>)(x => x != null && value != null && x.StartsWith(value, stringComparer))), propertyExpression.Modify<T>((Expression<Func<object?, bool>>)(x => (string?)x != null && value != null && ((string)x).StartsWith(value, stringComparer))),
FilterOperator.String.EndsWith => FilterOperator.String.EndsWith =>
propertyExpression.Modify<T>((Expression<Func<string?, bool>>)(x => x != null && value != null && x.EndsWith(value, stringComparer))), propertyExpression.Modify<T>((Expression<Func<object?, bool>>)(x => (string?)x != null && value != null && ((string)x).EndsWith(value, stringComparer))),
FilterOperator.String.Empty => propertyExpression.Modify<T>((Expression<Func<string?, bool>>)(x => string.IsNullOrWhiteSpace(x))), FilterOperator.String.Empty => propertyExpression.Modify<T>((Expression<Func<string?, bool>>)(x => string.IsNullOrWhiteSpace(x))),
FilterOperator.String.NotEmpty => propertyExpression.Modify<T>((Expression<Func<string?, bool>>)(x => !string.IsNullOrWhiteSpace(x))), FilterOperator.String.NotEmpty => propertyExpression.Modify<T>((Expression<Func<string?, bool>>)(x => !string.IsNullOrWhiteSpace(x))),
_ => x => true _ => x => true

View File

@@ -1,33 +1,36 @@
@inherits LayoutComponentBase @inherits LayoutComponentBase
<EnhancedErrorBoundary @ref="ErrorBoundary" OnClear="Cleared"> <EnhancedErrorBoundary @ref="ErrorBoundary" OnClear="Cleared">
<MudThemeProvider />
<MudDialogProvider /> </EnhancedErrorBoundary>
<MudSnackbarProvider />
<PageTitle>qBittorrent Web UI</PageTitle> <MudThemeProvider />
<MudDialogProvider />
<MudSnackbarProvider />
<MudLayout> <PageTitle>qBittorrent Web UI</PageTitle>
<MudAppBar Elevation="1">
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="ToggleDrawer" /> <MudLayout>
<MudText Typo="Typo.h5" Class="ml-3">qBittorrent Web UI</MudText> <MudAppBar Elevation="1">
<MudSpacer /> <MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="ToggleDrawer" />
@if (ErrorBoundary?.Errors.Count > 0) <MudText Typo="Typo.h5" Class="ml-3">qBittorrent Web UI</MudText>
{ <MudSpacer />
<MudBadge Content="@(ErrorBoundary?.Errors.Count ?? 0)" Color="Color.Error" Overlap="true"> @if (ErrorBoundary?.Errors.Count > 0)
<MudIconButton Icon="@Icons.Material.Filled.Error" Color="Color.Default" OnClick="ToggleErrorDrawer" /> {
</MudBadge> <MudBadge Content="@(ErrorBoundary?.Errors.Count ?? 0)" Color="Color.Error" Overlap="true">
} <MudIconButton Icon="@Icons.Material.Filled.Error" Color="Color.Default" OnClick="ToggleErrorDrawer" />
@if (ShowMenu) </MudBadge>
{ }
<Menu /> @if (ShowMenu)
} {
</MudAppBar> <Menu />
<MudDrawer Open="ErrorDrawerOpen" ClipMode="DrawerClipMode.Docked" Elevation="2" Anchor="Anchor.Right"> }
<ErrorDisplay ErrorBoundary="ErrorBoundary" /> </MudAppBar>
</MudDrawer> <MudDrawer Open="ErrorDrawerOpen" ClipMode="DrawerClipMode.Docked" Elevation="2" Anchor="Anchor.Right">
<CascadingValue Value="DrawerOpen" Name="DrawerOpen"> <ErrorDisplay ErrorBoundary="ErrorBoundary" />
@Body </MudDrawer>
</CascadingValue> <CascadingValue Value="DrawerOpen" Name="DrawerOpen">
</MudLayout> @Body
</EnhancedErrorBoundary> </CascadingValue>
</MudLayout>

View File

@@ -49,7 +49,7 @@ namespace Lantean.QBTMudBlade.Pages
#if DEBUG #if DEBUG
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
await DoLogin("admin", "a8hbfvNP2"); await DoLogin("admin", "pdqYws6EQ");
} }
#endif #endif
} }

View File

@@ -48,7 +48,7 @@
<MudTh> <MudTh>
@if (column.SortSelector is not null) @if (column.SortSelector is not null)
{ {
<MudTableSortLabel T="Torrent" SortDirectionChanged="@(c => SetSort(column.SortSelector, c))">@column.Header</MudTableSortLabel> <MudTableSortLabel T="Torrent" SortDirectionChanged="@(c => SetSort(column.Id, c))">@column.Header</MudTableSortLabel>
} }
else else
{ {

View File

@@ -10,7 +10,8 @@ namespace Lantean.QBTMudBlade.Pages
{ {
public partial class TorrentList public partial class TorrentList
{ {
private const string _columnStorageKey = "TorrentList.Columns"; private const string _columnSelectionStorageKey = "TorrentList.ColumnSelection";
private const string _columnSortStorageKey = "TorrentList.ColumnSort";
[Inject] [Inject]
protected IApiClient ApiClient { get; set; } = default!; protected IApiClient ApiClient { get; set; } = default!;
@@ -45,18 +46,18 @@ namespace Lantean.QBTMudBlade.Pages
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (!await LocalStorage.ContainKeyAsync(_columnStorageKey)) var selectedColumns = await LocalStorage.GetItemAsync<HashSet<string>>(_columnSelectionStorageKey);
if (selectedColumns is not null)
{ {
return; SelectedColumns = selectedColumns;
} }
var selectedColumns = await LocalStorage.GetItemAsync<HashSet<string>>(_columnStorageKey); var columnSort = await LocalStorage.GetItemAsync<Tuple<string, SortDirection>>(_columnSortStorageKey);
if (selectedColumns is null) if (columnSort is not null)
{ {
return; _sortColumn = columnSort.Item1;
_sortDirection = columnSort.Item2;
} }
SelectedColumns = selectedColumns;
} }
protected override void OnParametersSet() protected override void OnParametersSet()
@@ -69,7 +70,7 @@ namespace Lantean.QBTMudBlade.Pages
SelectedColumns.Remove("#"); SelectedColumns.Remove("#");
} }
} }
_sortSelector ??= _columns.First(c => c.Enabled).SortSelector; _sortColumn ??= _columns.First(c => c.Enabled).Id;
if (SelectedTorrent is not null && Torrents is not null && !Torrents.Contains(SelectedTorrent)) if (SelectedTorrent is not null && Torrents is not null && !Torrents.Contains(SelectedTorrent))
{ {
@@ -84,7 +85,9 @@ namespace Lantean.QBTMudBlade.Pages
return null; return null;
} }
return Torrents.OrderByDirection(_sortDirection, _sortSelector ?? (t => t.Priority)); var sortSelector = _columns.Find(c => c.Id == _sortColumn)?.SortSelector;
return Torrents.OrderByDirection(_sortDirection, sortSelector ?? (t => t.Priority));
} }
protected void SelectedItemsChanged(HashSet<Torrent> selectedItems) protected void SelectedItemsChanged(HashSet<Torrent> selectedItems)
@@ -214,7 +217,7 @@ namespace Lantean.QBTMudBlade.Pages
SelectedColumns = (HashSet<string>)result.Data; SelectedColumns = (HashSet<string>)result.Data;
await LocalStorage.SetItemAsync(_columnStorageKey, SelectedColumns); await LocalStorage.SetItemAsync(_columnSelectionStorageKey, SelectedColumns);
} }
protected void ShowTorrent() protected void ShowTorrent()
@@ -243,10 +246,12 @@ namespace Lantean.QBTMudBlade.Pages
return _columns.Where(c => SelectedColumns.Contains(c.Id)); return _columns.Where(c => SelectedColumns.Contains(c.Id));
} }
private void SetSort(Func<Torrent, object?> sortSelector, SortDirection sortDirection) private async Task SetSort(string columnId, SortDirection sortDirection)
{ {
_sortSelector = sortSelector; _sortColumn = columnId;
_sortDirection = sortDirection; _sortDirection = sortDirection;
await LocalStorage.SetItemAsync(_columnSortStorageKey, new Tuple<string, SortDirection>(columnId, sortDirection));
} }
protected List<ColumnDefinition<Torrent>> _columns = protected List<ColumnDefinition<Torrent>> _columns =
@@ -286,7 +291,7 @@ namespace Lantean.QBTMudBlade.Pages
//CreateColumnDefinition("Reannounce In", t => t.Reannounce, enabled: false), //CreateColumnDefinition("Reannounce In", t => t.Reannounce, enabled: false),
]; ];
private Func<Torrent, object?>? _sortSelector; private string? _sortColumn;
private SortDirection _sortDirection; private SortDirection _sortDirection;
private static ColumnDefinition<Torrent> CreateColumnDefinition(string name, Func<Torrent, object?> selector, RenderFragment<RowContext<Torrent>> rowTemplate, int? width = null, string? tdClass = null, bool enabled = true) private static ColumnDefinition<Torrent> CreateColumnDefinition(string name, Func<Torrent, object?> selector, RenderFragment<RowContext<Torrent>> rowTemplate, int? width = null, string? tdClass = null, bool enabled = true)