Search improvements, bugfix

This commit is contained in:
2022-02-22 14:37:14 +01:00
parent 92f8e828b5
commit 5734126c31
16 changed files with 69 additions and 40 deletions

View File

@@ -42,6 +42,10 @@ namespace FileTime.Core.Components
if (_currentLocation != null) if (_currentLocation != null)
{ {
_currentLocation.Refreshed.Remove(HandleCurrentLocationRefresh); _currentLocation.Refreshed.Remove(HandleCurrentLocationRefresh);
if(_currentLocation is SearchContainer searchContainer)
{
searchContainer.SearchTaskBase.Cancel();
}
} }
_currentLocation = value; _currentLocation = value;

View File

@@ -0,0 +1,8 @@
namespace FileTime.Core.Models
{
public interface IFile : IElement
{
string Attributes { get; }
DateTime CreatedAt { get; }
}
}

View File

@@ -5,12 +5,15 @@ namespace FileTime.Core.Search
{ {
public class ChildSearchElement : AbstractElement<IContentProvider> public class ChildSearchElement : AbstractElement<IContentProvider>
{ {
public ChildSearchElement(SearchContainer searchContainer, IContentProvider provider, IContainer parent, string name, string displayName, List<ItemNamePart> searchDisplayName) : base(provider, parent, name) public IElement BaseElement { get; }
public ChildSearchElement(SearchContainer searchContainer, IContentProvider provider, IContainer parent, IElement baseElement, string name, List<ItemNamePart> searchDisplayName) : base(provider, parent, name)
{ {
DisplayName = displayName; DisplayName = baseElement.DisplayName;
NativePath = FullName; NativePath = FullName;
SearchContainer = searchContainer; SearchContainer = searchContainer;
SearchDisplayName = searchDisplayName; SearchDisplayName = searchDisplayName;
BaseElement = baseElement;
} }
public SearchContainer SearchContainer { get; } public SearchContainer SearchContainer { get; }
@@ -24,9 +27,9 @@ namespace FileTime.Core.Search
public override Task<IContentWriter> GetContentWriterAsync() => throw new NotSupportedException(); public override Task<IContentWriter> GetContentWriterAsync() => throw new NotSupportedException();
public override Task<long?> GetElementSize(CancellationToken token = default) => Task.FromResult((long?)null); public override async Task<long?> GetElementSize(CancellationToken token = default) => await BaseElement.GetElementSize(token);
public override string GetPrimaryAttributeText() => ""; public override string GetPrimaryAttributeText() => BaseElement.GetPrimaryAttributeText();
public override Task Rename(string newName) => throw new NotSupportedException(); public override Task Rename(string newName) => throw new NotSupportedException();
} }

View File

@@ -16,6 +16,6 @@ namespace FileTime.Core.Search
protected override Task<bool> IsItemMatch(IItem item) => Task.FromResult(item.Name.Contains(_name)); protected override Task<bool> IsItemMatch(IItem item) => Task.FromResult(item.Name.Contains(_name));
public override List<ItemNamePart> GetDisplayName(IItem item) => _itemNameConverterService.GetDisplayName(item, _name); public override List<ItemNamePart> GetDisplayName(IItem item) => _itemNameConverterService.GetDisplayName(item.DisplayName, _name);
} }
} }

View File

@@ -15,7 +15,7 @@ namespace FileTime.Core.Search
private readonly IReadOnlyList<IContainer> _containersReadOnly; private readonly IReadOnlyList<IContainer> _containersReadOnly;
private readonly IReadOnlyList<IElement> _elementsReadOnly; private readonly IReadOnlyList<IElement> _elementsReadOnly;
private readonly SearchTaskBase _searchTaskBase; public SearchTaskBase SearchTaskBase { get; }
public IContainer SearchBaseContainer { get; } public IContainer SearchBaseContainer { get; }
public override bool IsExists => throw new NotImplementedException(); public override bool IsExists => throw new NotImplementedException();
@@ -25,7 +25,7 @@ namespace FileTime.Core.Search
SearchBaseContainer = searchBaseContainer; SearchBaseContainer = searchBaseContainer;
_containers = new List<IContainer>(); _containers = new List<IContainer>();
_elements = new List<IElement>(); _elements = new List<IElement>();
_searchTaskBase = searchTaskBase; SearchTaskBase = searchTaskBase;
_containersReadOnly = _containers.AsReadOnly(); _containersReadOnly = _containers.AsReadOnly();
_elementsReadOnly = _elements.AsReadOnly(); _elementsReadOnly = _elements.AsReadOnly();
@@ -52,14 +52,14 @@ namespace FileTime.Core.Search
public async Task AddContainer(IContainer container) public async Task AddContainer(IContainer container)
{ {
var childContainer = new ChildSearchContainer(this, Provider, container, "container" + _childContainerCounter++, container.DisplayName, _searchTaskBase.GetDisplayName(container)); var childContainer = new ChildSearchContainer(this, Provider, container, "container" + _childContainerCounter++, container.DisplayName, SearchTaskBase.GetDisplayName(container));
_containers.Add(childContainer); _containers.Add(childContainer);
await UpdateChildren(); await UpdateChildren();
} }
public async Task AddElement(IElement element) public async Task AddElement(IElement element)
{ {
var childElement = new ChildSearchElement(this, Provider, element.GetParent()!, "element" + _childElementCounter++, element.DisplayName, _searchTaskBase.GetDisplayName(element)); var childElement = new ChildSearchElement(this, Provider, element.GetParent()!, element, "element" + _childElementCounter++, SearchTaskBase.GetDisplayName(element));
_elements.Add(childElement); _elements.Add(childElement);
await UpdateChildren(); await UpdateChildren();
} }
@@ -95,7 +95,7 @@ namespace FileTime.Core.Search
public override Task<ContainerEscapeResult> HandleEscape() public override Task<ContainerEscapeResult> HandleEscape()
{ {
if (_searchTaskBase.Cancel()) return Task.FromResult(new ContainerEscapeResult(true)); if (SearchTaskBase.Cancel()) return Task.FromResult(new ContainerEscapeResult(true));
return Task.FromResult(new ContainerEscapeResult(SearchBaseContainer)); return Task.FromResult(new ContainerEscapeResult(SearchBaseContainer));
} }

View File

@@ -4,12 +4,11 @@ namespace FileTime.Core.Services
{ {
public class ItemNameConverterService public class ItemNameConverterService
{ {
public List<ItemNamePart> GetDisplayName(IItem item, string? searchText) public List<ItemNamePart> GetDisplayName(string name, string? searchText)
{ {
var nameParts = new List<ItemNamePart>(); var nameParts = new List<ItemNamePart>();
searchText = searchText?.ToLower(); searchText = searchText?.ToLower();
var name = item is IElement ? GetFileName(item.DisplayName) : item.DisplayName;
if (!string.IsNullOrEmpty(searchText)) if (!string.IsNullOrEmpty(searchText))
{ {
var nameLeft = name; var nameLeft = name;

View File

@@ -218,13 +218,13 @@ namespace FileTime.Avalonia.Application
else if (currentSelectenItem.Item is ChildSearchContainer searchContainer) else if (currentSelectenItem.Item is ChildSearchContainer searchContainer)
{ {
var searchContainerPreview = _serviceProvider.GetService<SearchContainerPreview>()!; var searchContainerPreview = _serviceProvider.GetService<SearchContainerPreview>()!;
await searchContainerPreview.Init(searchContainer, _currentLocation.Container); searchContainerPreview.Init(searchContainer, _currentLocation.Container);
preview = searchContainerPreview; preview = searchContainerPreview;
} }
else if (currentSelectenItem.Item is ChildSearchElement searchElement) else if (currentSelectenItem.Item is ChildSearchElement searchElement)
{ {
var searchElementPreview = _serviceProvider.GetService<SearchElementPreview>()!; var searchElementPreview = _serviceProvider.GetService<SearchElementPreview>()!;
await searchElementPreview.Init(searchElement, _currentLocation.Container); searchElementPreview.Init(searchElement, _currentLocation.Container);
preview = searchElementPreview; preview = searchElementPreview;
} }
else if (currentSelectenItem is ElementViewModel elementViewModel) else if (currentSelectenItem is ElementViewModel elementViewModel)

View File

@@ -3,6 +3,7 @@ using System.Globalization;
using Avalonia.Data.Converters; using Avalonia.Data.Converters;
using FileTime.Avalonia.Models; using FileTime.Avalonia.Models;
using FileTime.Avalonia.ViewModels; using FileTime.Avalonia.ViewModels;
using FileTime.Core.Models;
using FileTime.Providers.Local; using FileTime.Providers.Local;
namespace FileTime.Avalonia.Converters namespace FileTime.Avalonia.Converters
@@ -12,7 +13,9 @@ namespace FileTime.Avalonia.Converters
public bool Invert { get; set; } public bool Invert { get; set; }
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{ {
var result = parameter is AttibuteType targetAttribute && GetAttibuteType(value) == targetAttribute; var attributeType = GetAttibuteType(value);
if (parameter == null) return attributeType;
var result = parameter is AttibuteType targetAttribute && attributeType == targetAttribute;
if (Invert && parameter is AttibuteType) result = !result; if (Invert && parameter is AttibuteType) result = !result;
return result; return result;
} }
@@ -21,9 +24,9 @@ namespace FileTime.Avalonia.Converters
{ {
if (value is ElementViewModel elementVM) if (value is ElementViewModel elementVM)
{ {
if (elementVM.Element is LocalFile) if (elementVM.BaseElement is IFile)
{ {
return AttibuteType.LocalFile; return AttibuteType.File;
} }
return AttibuteType.Element; return AttibuteType.Element;
} }

View File

@@ -2,7 +2,7 @@ namespace FileTime.Avalonia.Models
{ {
public enum AttibuteType public enum AttibuteType
{ {
LocalFile, File,
Element, Element,
Container Container
} }

View File

@@ -13,6 +13,7 @@ using System.Threading.Tasks;
using FileTime.Avalonia.Application; using FileTime.Avalonia.Application;
using System.Threading; using System.Threading;
using FileTime.Core.Services; using FileTime.Core.Services;
using FileTime.Core.Search;
namespace FileTime.Avalonia.ViewModels namespace FileTime.Avalonia.ViewModels
{ {
@@ -29,6 +30,9 @@ namespace FileTime.Avalonia.ViewModels
[Property] [Property]
private IContainer _container; private IContainer _container;
[Property]
private IContainer _baseContainer;
[Property] [Property]
private bool _isSelected; private bool _isSelected;
@@ -45,6 +49,7 @@ namespace FileTime.Avalonia.ViewModels
private List<Exception> _exceptions; private List<Exception> _exceptions;
public IItem Item => _container; public IItem Item => _container;
public IItem BaseItem => _baseContainer;
private ObservableCollection<ContainerViewModel> _containers = new(); private ObservableCollection<ContainerViewModel> _containers = new();
@@ -70,7 +75,7 @@ namespace FileTime.Avalonia.ViewModels
_ => ItemViewMode.Default _ => ItemViewMode.Default
}; };
public List<ItemNamePart> DisplayName => ItemNameConverterService.GetDisplayName(Item, AppState.ViewMode == Application.ViewMode.RapidTravel ? AppState.RapidTravelText : null); public List<ItemNamePart> DisplayName => ItemNameConverterService.GetDisplayName(Item.DisplayName, AppState.ViewMode == Application.ViewMode.RapidTravel ? AppState.RapidTravelText : null);
public Task Containers => GetContainers(); public Task Containers => GetContainers();
public Task Elements => GetElements(); public Task Elements => GetElements();
@@ -127,6 +132,7 @@ namespace FileTime.Avalonia.ViewModels
Parent = parent; Parent = parent;
Container = container; Container = container;
BaseContainer = container is ChildSearchContainer childSearchContainer ? childSearchContainer.BaseContainer : container;
Container.Refreshed.Add(Container_Refreshed); Container.Refreshed.Add(Container_Refreshed);
Container.LazyLoadingChanged.Add(Container_LazyLoadingChanged); Container.LazyLoadingChanged.Add(Container_LazyLoadingChanged);
} }

View File

@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using FileTime.Avalonia.Application; using FileTime.Avalonia.Application;
using FileTime.Core.Services; using FileTime.Core.Services;
using FileTime.Core.Search;
namespace FileTime.Avalonia.ViewModels namespace FileTime.Avalonia.ViewModels
{ {
@@ -15,10 +16,14 @@ namespace FileTime.Avalonia.ViewModels
public partial class ElementViewModel : IItemViewModel public partial class ElementViewModel : IItemViewModel
{ {
public IItem Item => _element; public IItem Item => _element;
public IItem BaseItem => _baseElement;
[Property] [Property]
private IElement _element; private IElement _element;
[Property]
private IElement _baseElement;
[Property] [Property]
private bool _isSelected; private bool _isSelected;
@@ -48,11 +53,12 @@ namespace FileTime.Avalonia.ViewModels
_ => ItemViewMode.Default _ => ItemViewMode.Default
}; };
public List<ItemNamePart> DisplayName => ItemNameConverterService.GetDisplayName(Item, AppState.ViewMode == Application.ViewMode.RapidTravel ? AppState.RapidTravelText : null); public List<ItemNamePart> DisplayName => ItemNameConverterService.GetDisplayName(ItemNameConverterService.GetFileName(Item.DisplayName), AppState.ViewMode == Application.ViewMode.RapidTravel ? AppState.RapidTravelText : null);
public ElementViewModel(IElement element, ContainerViewModel parent, ItemNameConverterService itemNameConverterService, AppState appState) : this(itemNameConverterService, appState) public ElementViewModel(IElement element, ContainerViewModel parent, ItemNameConverterService itemNameConverterService, AppState appState) : this(itemNameConverterService, appState)
{ {
Element = element; Element = element;
BaseElement = element is ChildSearchElement childSearchElement ? childSearchElement.BaseElement : element;
Parent = parent; Parent = parent;
} }

View File

@@ -7,6 +7,7 @@ namespace FileTime.Avalonia.ViewModels
public interface IItemViewModel public interface IItemViewModel
{ {
IItem Item { get; } IItem Item { get; }
IItem BaseItem { get; }
bool IsSelected { get; set; } bool IsSelected { get; set; }
bool IsAlternative { get; set; } bool IsAlternative { get; set; }

View File

@@ -23,11 +23,11 @@ namespace FileTime.Avalonia.ViewModels.ItemPreview
[Property] [Property]
private string? _realtiveParentPath; private string? _realtiveParentPath;
public async Task Init(ChildSearchContainer container, IContainer currentLocation) public void Init(ChildSearchContainer container, IContainer currentLocation)
{ {
var pathCommonPath = PathHelper.GetCommonPath(currentLocation.FullName!, container.FullName!); var pathCommonPath = PathHelper.GetCommonPath(currentLocation.FullName!, container.FullName!);
RealtiveParentPath = new AbsolutePath(null!, container.FullName!.Substring(pathCommonPath.Length).Trim(Constants.SeparatorChar), AbsolutePathType.Unknown, null).GetParentPath(); RealtiveParentPath = new AbsolutePath(null!, container.FullName!.Substring(pathCommonPath.Length).Trim(Constants.SeparatorChar), AbsolutePathType.Unknown, null).GetParentPath();
ItemNameParts = await Task.Run(async () => await Dispatcher.UIThread.InvokeAsync(() => container.SearchDisplayName.Select(p => new ItemNamePartViewModel(p.Text, p.IsSpecial ? TextDecorations.Underline : null)).ToList())); Task.Run(async () => ItemNameParts = await Dispatcher.UIThread.InvokeAsync(() => container.SearchDisplayName.ConvertAll(p => new ItemNamePartViewModel(p.Text, p.IsSpecial ? TextDecorations.Underline : null))));
} }
} }
} }

View File

@@ -25,11 +25,11 @@ namespace FileTime.Avalonia.ViewModels.ItemPreview
[Property] [Property]
private string? _realtiveParentPath; private string? _realtiveParentPath;
public async Task Init(ChildSearchElement element, IContainer currentLocation) public void Init(ChildSearchElement element, IContainer currentLocation)
{ {
var pathCommonPath = PathHelper.GetCommonPath(currentLocation.FullName!, element.FullName!); var pathCommonPath = PathHelper.GetCommonPath(currentLocation.FullName!, element.FullName!);
RealtiveParentPath = new AbsolutePath(null!, element.FullName!.Substring(pathCommonPath.Length).Trim(Constants.SeparatorChar), AbsolutePathType.Unknown, null).GetParentPath(); RealtiveParentPath = new AbsolutePath(null!, element.FullName!.Substring(pathCommonPath.Length).Trim(Constants.SeparatorChar), AbsolutePathType.Unknown, null).GetParentPath();
ItemNameParts = await Task.Run(async () => await Dispatcher.UIThread.InvokeAsync(() => element.SearchDisplayName.Select(p => new ItemNamePartViewModel(p.Text, p.IsSpecial ? TextDecorations.Underline : null)).ToList())); Task.Run(async () => ItemNameParts = await Dispatcher.UIThread.InvokeAsync(() => element.SearchDisplayName.ConvertAll(p => new ItemNamePartViewModel(p.Text, p.IsSpecial ? TextDecorations.Underline : null))));
} }
} }
} }

View File

@@ -5,7 +5,7 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="FileTime.Avalonia.Views.ItemView" x:Class="FileTime.Avalonia.Views.ItemView"
xmlns:models="using:FileTime.Avalonia.Models" xmlns:models="using:FileTime.Avalonia.Models"
x:Name="ItemRoot" x:Name="ItemRoot"
HorizontalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Background="{Binding ViewMode,Converter={StaticResource ItemViewModeToBackgroundConverter}}"> Background="{Binding ViewMode,Converter={StaticResource ItemViewModeToBackgroundConverter}}">
@@ -55,29 +55,28 @@
<Grid Grid.Column="2" IsVisible="{Binding ShowAttributes,ElementName=ItemRoot}"> <Grid Grid.Column="2" IsVisible="{Binding ShowAttributes,ElementName=ItemRoot}">
<Grid ColumnDefinitions="50,50,90,40,45" <Grid ColumnDefinitions="50,50,90,40,45"
HorizontalAlignment="Right" HorizontalAlignment="Right"
IsVisible="{Binding Converter={StaticResource ItemViewModelIsAttibuteTypeConverter},ConverterParameter={x:Static models:AttibuteType.LocalFile}}"> IsVisible="{Binding Converter={StaticResource ItemViewModelIsAttibuteTypeConverter},ConverterParameter={x:Static models:AttibuteType.File}}">
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Text="{Binding Item.Name, Converter={StaticResource GetFileExtensionConverter}}"/> <TextBlock HorizontalAlignment="Right" Classes="SmallText" Text="{Binding BaseItem.DisplayName, Converter={StaticResource GetFileExtensionConverter}}"/>
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="1" Text="{Binding Size, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}"/> <TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="1" Text="{Binding Size, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}"/>
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="2" Text="{Binding Item.CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=yyyy-MM-dd}"/> <TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="2" Text="{Binding BaseItem.CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=yyyy-MM-dd}"/>
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="3" Text="{Binding Item.CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=hh:mm}"/> <TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="3" Text="{Binding BaseItem.CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=hh:mm}"/>
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="4" Text="{Binding Item.Attributes}"/> <TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="4" Text="{Binding BaseItem.Attributes}"/>
</Grid> </Grid>
<Grid ColumnDefinitions="90,40,45" <Grid ColumnDefinitions="90,40,45"
HorizontalAlignment="Right" HorizontalAlignment="Right"
IsVisible="{Binding Converter={StaticResource ItemViewModelIsAttibuteTypeConverter},ConverterParameter={x:Static models:AttibuteType.Container}}"> IsVisible="{Binding Converter={StaticResource ItemViewModelIsAttibuteTypeConverter},ConverterParameter={x:Static models:AttibuteType.Container}}">
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Text="{Binding Item.CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=yyyy-MM-dd}"/> <TextBlock HorizontalAlignment="Right" Classes="SmallText" Text="{Binding Item.CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=yyyy-MM-dd}"/>
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="1" Text="{Binding Item.CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=hh:mm}"/> <TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="1" Text="{Binding BaseItem.CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=hh:mm}"/>
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="2" Text="{Binding Item.Attributes}"/> <TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="2" Text="{Binding BaseItem.Attributes}"/>
</Grid> </Grid>
<Grid ColumnDefinitions="90,40,45" <Grid ColumnDefinitions="50,50"
HorizontalAlignment="Right" HorizontalAlignment="Right"
IsVisible="{Binding Converter={StaticResource ItemViewModelIsAttibuteTypeConverter},ConverterParameter={x:Static models:AttibuteType.Element}}"> IsVisible="{Binding Converter={StaticResource ItemViewModelIsAttibuteTypeConverter},ConverterParameter={x:Static models:AttibuteType.Element}}">
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Text="{Binding Item.CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=yyyy-MM-dd}"/> <TextBlock HorizontalAlignment="Right" Classes="SmallText" Text="{Binding BaseItem.DisplayName, Converter={StaticResource GetFileExtensionConverter}}"/>
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="1" Text="{Binding Item.CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=hh:mm}"/> <TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="1" Text="{Binding Size, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}"/>
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="2" Text="{Binding Item.Attributes}"/>
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>

View File

@@ -7,7 +7,7 @@ using Mono.Unix;
namespace FileTime.Providers.Local namespace FileTime.Providers.Local
{ {
public class LocalFile : IElement public class LocalFile : IFile
{ {
public FileInfo File { get; } public FileInfo File { get; }