Optimalization, file name&extension

This commit is contained in:
2022-02-08 09:53:20 +01:00
parent 2b5ab06b57
commit 755793c85c
22 changed files with 268 additions and 85 deletions

View File

@@ -18,6 +18,8 @@ namespace FileTime.Core.Components
public int CurrentSelectedIndex { get; private set; } public int CurrentSelectedIndex { get; private set; }
public bool AutoRefresh { get; set; }
public AsyncEventHandler CurrentLocationChanged = new(); public AsyncEventHandler CurrentLocationChanged = new();
public AsyncEventHandler CurrentSelectedItemChanged = new(); public AsyncEventHandler CurrentSelectedItemChanged = new();
@@ -54,39 +56,47 @@ namespace FileTime.Core.Components
return Task.FromResult(_currentSelectedItem); return Task.FromResult(_currentSelectedItem);
} }
public async Task SetCurrentSelectedItem(IItem? value, bool secondary = false) public async Task<bool> SetCurrentSelectedItem(IItem? value, bool secondary = false, CancellationToken token = default)
{ {
if (_currentlySelecting) return; if (_currentlySelecting) return false;
if (_currentSelectedItem != value) if (_currentSelectedItem == value) return false;
IItem? itemToSelect = null;
if (value != null)
{ {
IItem? itemToSelect = null; itemToSelect = (await _currentLocation.GetItems(token))?.FirstOrDefault(i =>
if (value != null) i.FullName == null && value?.FullName == null
{ ? i.Name == value?.Name
itemToSelect = (await _currentLocation.GetItems())?.FirstOrDefault(i => : i.FullName == value?.FullName);
i.FullName == null && value?.FullName == null if (itemToSelect == null) throw new IndexOutOfRangeException($"Provided item ({value.FullName ?? "unknwon"}) does not exists in the current container ({_currentLocation.FullName ?? "unknwon"}).");
? i.Name == value?.Name }
: i.FullName == value?.FullName);
if (itemToSelect == null) throw new IndexOutOfRangeException($"Provided item ({value.FullName ?? "unknwon"}) does not exists in the current container ({_currentLocation.FullName ?? "unknwon"}).");
}
CancellationToken newToken; CancellationToken newToken;
lock (_guardSetCurrentSelectedItemCTS) lock (_guardSetCurrentSelectedItemCTS)
{
if (token.IsCancellationRequested) return false;
_setCurrentSelectedItemCTS?.Cancel();
if (token.IsCancellationRequested)
{ {
_setCurrentSelectedItemCTS?.Cancel();
_setCurrentSelectedItemCTS = new CancellationTokenSource(); _setCurrentSelectedItemCTS = new CancellationTokenSource();
newToken = _setCurrentSelectedItemCTS.Token; newToken = _setCurrentSelectedItemCTS.Token;
} }
else
_currentSelectedItem = itemToSelect; {
_lastPath = GetCommonPath(_lastPath, itemToSelect?.FullName); _setCurrentSelectedItemCTS = new CancellationTokenSource();
newToken = CancellationTokenSource.CreateLinkedTokenSource(_setCurrentSelectedItemCTS.Token, token).Token;
var newCurrentSelectedIndex = await GetItemIndex(itemToSelect, newToken); }
if (newToken.IsCancellationRequested) return;
CurrentSelectedIndex = newCurrentSelectedIndex;
await CurrentSelectedItemChanged.InvokeAsync(this, AsyncEventArgs.Empty, newToken);
} }
_currentSelectedItem = itemToSelect;
_lastPath = GetCommonPath(_lastPath, itemToSelect?.FullName);
var newCurrentSelectedIndex = await GetItemIndex(itemToSelect, CancellationToken.None);
CurrentSelectedIndex = newCurrentSelectedIndex;
await CurrentSelectedItemChanged.InvokeAsync(this, AsyncEventArgs.Empty, newToken);
return !newToken.IsCancellationRequested;
} }
public async Task<IItem?> GetItemByLastPath(IContainer? container = null) public async Task<IItem?> GetItemByLastPath(IContainer? container = null)
{ {
@@ -94,7 +104,6 @@ namespace FileTime.Core.Components
var containerFullName = container.FullName; var containerFullName = container.FullName;
if (_lastPath == null if (_lastPath == null
|| !container.IsLoaded
|| (containerFullName != null && !_lastPath.StartsWith(containerFullName)) || (containerFullName != null && !_lastPath.StartsWith(containerFullName))
) )
{ {
@@ -154,53 +163,60 @@ namespace FileTime.Core.Components
} }
} }
public async Task SelectFirstItem() public async Task SelectFirstItem(CancellationToken token = default)
{ {
var currentLocationItems = (await (await GetCurrentLocation()).GetItems())!; var currentLocationItems = (await (await GetCurrentLocation(token)).GetItems(token))!;
if (currentLocationItems.Count > 0) if (currentLocationItems.Count > 0)
{ {
await SetCurrentSelectedItem(currentLocationItems[0]); await SetCurrentSelectedItem(currentLocationItems[0], token: token);
} }
} }
public async Task SelectLastItem() public async Task SelectLastItem(CancellationToken token = default)
{ {
var currentLocationItems = (await (await GetCurrentLocation()).GetItems())!; var currentLocationItems = (await (await GetCurrentLocation(token)).GetItems(token))!;
if (currentLocationItems.Count > 0) if (currentLocationItems.Count > 0)
{ {
await SetCurrentSelectedItem(currentLocationItems[currentLocationItems.Count - 1]); await SetCurrentSelectedItem(currentLocationItems[currentLocationItems.Count - 1], token: token);
} }
} }
public async Task SelectPreviousItem(int skip = 0) public async Task SelectPreviousItem(int skip = 0, CancellationToken token = default)
{ {
var currentLocationItems = (await (await GetCurrentLocation()).GetItems())!; var currentLocationItems = (await (await GetCurrentLocation(token)).GetItems(token))!;
var possibleItemsToSelect = currentLocationItems.Take(CurrentSelectedIndex).Reverse().Skip(skip).ToList(); var possibleItemsToSelect = currentLocationItems.Take(CurrentSelectedIndex).Reverse().Skip(skip).ToList();
if (possibleItemsToSelect.Count == 0) possibleItemsToSelect = currentLocationItems.ToList(); if (possibleItemsToSelect.Count == 0) possibleItemsToSelect = currentLocationItems.ToList();
await SelectItem(possibleItemsToSelect); await SelectItem(possibleItemsToSelect, token);
} }
public async Task SelectNextItem(int skip = 0) public async Task SelectNextItem(int skip = 0, CancellationToken token = default)
{ {
var currentLocationItems = (await (await GetCurrentLocation()).GetItems())!; var currentLocationItems = (await (await GetCurrentLocation(token)).GetItems(token))!;
var possibleItemsToSelect = currentLocationItems.Skip(CurrentSelectedIndex + 1 + skip).ToList(); var possibleItemsToSelect = currentLocationItems.Skip(CurrentSelectedIndex + 1 + skip).ToList();
if (possibleItemsToSelect.Count == 0) possibleItemsToSelect = currentLocationItems.Reverse().ToList(); if (possibleItemsToSelect.Count == 0) possibleItemsToSelect = currentLocationItems.Reverse().ToList();
await SelectItem(possibleItemsToSelect); await SelectItem(possibleItemsToSelect, token);
} }
private async Task SelectItem(IEnumerable<IItem> currentPossibleItems) private async Task SelectItem(IEnumerable<IItem> currentPossibleItems, CancellationToken token = default)
{ {
if (!currentPossibleItems.Any()) return; if (!currentPossibleItems.Any()) return;
var currentLocation = await GetCurrentLocation(); if (token.IsCancellationRequested) return;
var currentLocationItems = (await currentLocation.GetItems())!; var currentLocation = await GetCurrentLocation(token);
var currentLocationItems = (await currentLocation.GetItems(token))!;
if (await GetCurrentSelectedItem() != null) if (await GetCurrentSelectedItem() != null)
{ {
if (token.IsCancellationRequested) return;
_currentlySelecting = true; _currentlySelecting = true;
currentLocation?.RefreshAsync(); if (AutoRefresh && currentLocation != null)
{
await currentLocation.RefreshAsync(token);
if (token.IsCancellationRequested) return;
}
IItem? newSelectedItem = null; IItem? newSelectedItem = null;
foreach (var item in currentPossibleItems) foreach (var item in currentPossibleItems)
@@ -215,15 +231,15 @@ namespace FileTime.Core.Components
if (newSelectedItem != null) if (newSelectedItem != null)
{ {
newSelectedItem = (await (await GetCurrentLocation()).GetItems())?.FirstOrDefault(i => i.Name == newSelectedItem.Name); newSelectedItem = (await (await GetCurrentLocation(token)).GetItems(token))?.FirstOrDefault(i => i.Name == newSelectedItem.Name);
} }
_currentlySelecting = false; _currentlySelecting = false;
await SetCurrentSelectedItem(newSelectedItem ?? (currentLocationItems.Count > 0 ? currentLocationItems[0] : null)); await SetCurrentSelectedItem(newSelectedItem ?? (currentLocationItems.Count > 0 ? currentLocationItems[0] : null), token: token);
} }
else else
{ {
await SetCurrentSelectedItem(currentLocationItems.Count > 0 ? currentLocationItems[0] : null); await SetCurrentSelectedItem(currentLocationItems.Count > 0 ? currentLocationItems[0] : null, token: token);
} }
} }
@@ -269,7 +285,7 @@ namespace FileTime.Core.Components
await SetCurrentSelectedItem(newCurrentLocation); await SetCurrentSelectedItem(newCurrentLocation);
} }
foreach(var lastLocationItem in currentLocationItems.OfType<IContainer>()) foreach (var lastLocationItem in currentLocationItems.OfType<IContainer>())
{ {
lastLocationItem.Dispose(); lastLocationItem.Dispose();
} }

View File

@@ -18,6 +18,7 @@ namespace FileTime.Core.Models
Task<IContainer> Clone(); Task<IContainer> Clone();
Task<bool> CanOpen(); Task<bool> CanOpen();
void Unload();
bool IsLoaded { get; } bool IsLoaded { get; }
bool SupportsDirectoryLevelSoftDelete { get; } bool SupportsDirectoryLevelSoftDelete { get; }

View File

@@ -175,5 +175,10 @@ namespace FileTime.Core.Models
{ {
BaseContainer.Dispose(); BaseContainer.Dispose();
} }
public void Unload()
{
BaseContainer.Unload();
}
} }
} }

View File

@@ -72,5 +72,7 @@ namespace FileTime.Core.Providers
public Task<bool> CanOpen() => Task.FromResult(true); public Task<bool> CanOpen() => Task.FromResult(true);
public void Dispose() { } public void Dispose() { }
public void Unload() { }
} }
} }

View File

@@ -125,5 +125,6 @@ namespace FileTime.Core.Timeline
public Task<bool> CanOpen() => Task.FromResult(true); public Task<bool> CanOpen() => Task.FromResult(true);
public void Dispose() => IsDisposed = true; public void Dispose() => IsDisposed = true;
public void Unload() { }
} }
} }

View File

@@ -94,5 +94,7 @@ namespace FileTime.Core.Timeline
public Task<bool> CanOpen() => Task.FromResult(true); public Task<bool> CanOpen() => Task.FromResult(true);
public void Dispose() { } public void Dispose() { }
public void Unload() { }
} }
} }

View File

@@ -132,6 +132,8 @@
<converters:DateTimeConverter x:Key="DateTimeConverter"/> <converters:DateTimeConverter x:Key="DateTimeConverter"/>
<converters:IsTypeConverter x:Key="IsTypeConverter"/> <converters:IsTypeConverter x:Key="IsTypeConverter"/>
<converters:ItemViewModelIsAttibuteTypeConverter x:Key="ItemViewModelIsAttibuteTypeConverter"/> <converters:ItemViewModelIsAttibuteTypeConverter x:Key="ItemViewModelIsAttibuteTypeConverter"/>
<converters:ItemViewModelIsAttibuteTypeConverter x:Key="ItemViewModelIsNotAttibuteTypeConverter" Invert="true"/>
<converters:GetFileExtensionConverter x:Key="GetFileExtensionConverter"/>
</ResourceDictionary> </ResourceDictionary>
</Application.Resources> </Application.Resources>

View File

@@ -21,6 +21,8 @@ namespace FileTime.Avalonia.Application
public partial class TabContainer : INewItemProcessor public partial class TabContainer : INewItemProcessor
{ {
private bool _updateFromCode; private bool _updateFromCode;
private CancellationTokenSource? _moveCancellationTokenSource;
[Property] [Property]
private TabState _tabState; private TabState _tabState;
@@ -70,6 +72,10 @@ namespace FileTime.Avalonia.Application
{ {
if (_selectedItem != value) if (_selectedItem != value)
{ {
if(_selectedItem is ContainerViewModel containerVM)
{
containerVM.Unload(unloadParent: false);
}
_selectedItem = value; _selectedItem = value;
if (value is ElementViewModel elementViewModel) if (value is ElementViewModel elementViewModel)
@@ -83,8 +89,10 @@ namespace FileTime.Avalonia.Application
ElementPreview = null; ElementPreview = null;
} }
await Tab.SetCurrentSelectedItem(SelectedItem?.Item, fromDataBinding); if (await Tab.SetCurrentSelectedItem(SelectedItem?.Item, fromDataBinding))
OnPropertyChanged(nameof(SelectedItem)); {
OnPropertyChanged(nameof(SelectedItem));
}
} }
} }
@@ -131,6 +139,7 @@ namespace FileTime.Avalonia.Application
private async Task Tab_CurrentLocationChanged(object? sender, AsyncEventArgs e, CancellationToken token = default) private async Task Tab_CurrentLocationChanged(object? sender, AsyncEventArgs e, CancellationToken token = default)
{ {
CurrentLocation.Unload(true);
var currentLocation = await Tab.GetCurrentLocation(token); var currentLocation = await Tab.GetCurrentLocation(token);
var parent = GenerateParent(currentLocation); var parent = GenerateParent(currentLocation);
CurrentLocation = new ContainerViewModel(this, parent, currentLocation, ItemNameConverterService); CurrentLocation = new ContainerViewModel(this, parent, currentLocation, ItemNameConverterService);
@@ -270,6 +279,13 @@ namespace FileTime.Avalonia.Application
} }
} }
private CancellationToken CancelAndGenerateNextMovementToken()
{
if(_moveCancellationTokenSource != null) _moveCancellationTokenSource.Cancel();
_moveCancellationTokenSource = new CancellationTokenSource();
return _moveCancellationTokenSource.Token;
}
public async Task Open() public async Task Open()
{ {
if (ChildContainer != null) if (ChildContainer != null)
@@ -285,32 +301,32 @@ namespace FileTime.Avalonia.Application
public async Task MoveCursorDown() public async Task MoveCursorDown()
{ {
await RunFromCode(async () => await Tab.SelectNextItem()); await RunFromCode(async () => await Tab.SelectNextItem(token: CancelAndGenerateNextMovementToken()));
} }
public async Task MoveCursorDownPage() public async Task MoveCursorDownPage()
{ {
await RunFromCode(async () => await Tab.SelectNextItem(10)); await RunFromCode(async () => await Tab.SelectNextItem(10, token: CancelAndGenerateNextMovementToken()));
} }
public async Task MoveCursorUp() public async Task MoveCursorUp()
{ {
await RunFromCode(async () => await Tab.SelectPreviousItem()); await RunFromCode(async () => await Tab.SelectPreviousItem(token: CancelAndGenerateNextMovementToken()));
} }
public async Task MoveCursorUpPage() public async Task MoveCursorUpPage()
{ {
await RunFromCode(async () => await Tab.SelectPreviousItem(10)); await RunFromCode(async () => await Tab.SelectPreviousItem(10, token: CancelAndGenerateNextMovementToken()));
} }
public async Task MoveCursorToFirst() public async Task MoveCursorToFirst()
{ {
await RunFromCode(Tab.SelectFirstItem); await RunFromCode(async () => await Tab.SelectFirstItem(token: CancelAndGenerateNextMovementToken()));
} }
public async Task MoveCursorToLast() public async Task MoveCursorToLast()
{ {
await RunFromCode(Tab.SelectLastItem); await RunFromCode(async () => await Tab.SelectLastItem(token: CancelAndGenerateNextMovementToken()));
} }
public async Task GotToProvider() public async Task GotToProvider()

View File

@@ -10,14 +10,12 @@ namespace FileTime.Avalonia.Converters
{ {
public class ContextMenuGenerator : IValueConverter public class ContextMenuGenerator : IValueConverter
{ {
private readonly IContextMenuProvider _contextMenuProvider; private IContextMenuProvider? _contextMenuProvider;
public ContextMenuGenerator()
{
_contextMenuProvider = App.ServiceProvider.GetService<IContextMenuProvider>() ?? throw new Exception($"No {nameof(IContextMenuProvider)} is registered.");
}
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{ {
_contextMenuProvider ??= App.ServiceProvider.GetService<IContextMenuProvider>() ?? throw new Exception($"No {nameof(IContextMenuProvider)} is registered.");
if (value is ContainerViewModel containerViewModel) if (value is ContainerViewModel containerViewModel)
{ {
return _contextMenuProvider.GetContextMenuForFolder(containerViewModel.Container); return _contextMenuProvider.GetContextMenuForFolder(containerViewModel.Container);

View File

@@ -0,0 +1,25 @@
using System;
using System.Globalization;
using Avalonia.Data.Converters;
using FileTime.Avalonia.Services;
using Microsoft.Extensions.DependencyInjection;
namespace FileTime.Avalonia.Converters
{
public class GetFileExtensionConverter : IValueConverter
{
private ItemNameConverterService? _itemNameConverterService;
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is not string fullName) return value;
_itemNameConverterService ??= App.ServiceProvider.GetService<ItemNameConverterService>() ?? throw new Exception($"No {nameof(ItemNameConverterService)} is registered.");;
return _itemNameConverterService.GetFileExtension(fullName);
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -9,9 +9,12 @@ namespace FileTime.Avalonia.Converters
{ {
public class ItemViewModelIsAttibuteTypeConverter : IValueConverter public class ItemViewModelIsAttibuteTypeConverter : IValueConverter
{ {
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)
{ {
return parameter is AttibuteType targetAttribute && GetAttibuteType(value) == targetAttribute; var result = parameter is AttibuteType targetAttribute && GetAttibuteType(value) == targetAttribute;
if (Invert && parameter is AttibuteType) result = !result;
return result;
} }
private static AttibuteType? GetAttibuteType(object? value) private static AttibuteType? GetAttibuteType(object? value)

View File

@@ -2,6 +2,7 @@
using FileTime.Avalonia.Application; using FileTime.Avalonia.Application;
using FileTime.Avalonia.Models; using FileTime.Avalonia.Models;
using FileTime.Avalonia.ViewModels; using FileTime.Avalonia.ViewModels;
using FileTime.Core.Models;
using MvvmGen; using MvvmGen;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -17,9 +18,10 @@ namespace FileTime.Avalonia.Services
var nameParts = new List<ItemNamePart>(); var nameParts = new List<ItemNamePart>();
var rapidTravelText = AppState.RapidTravelText.ToLower(); var rapidTravelText = AppState.RapidTravelText.ToLower();
var name = itemViewModel.Item is IElement ? GetFileName(itemViewModel.Item.Name) : itemViewModel.Item.Name;
if (AppState.ViewMode == ViewMode.RapidTravel && rapidTravelText.Length > 0) if (AppState.ViewMode == ViewMode.RapidTravel && rapidTravelText.Length > 0)
{ {
var nameLeft = itemViewModel.Item.Name; var nameLeft = name;
while (nameLeft.ToLower().IndexOf(rapidTravelText, StringComparison.Ordinal) is int rapidTextStart && rapidTextStart != -1) while (nameLeft.ToLower().IndexOf(rapidTravelText, StringComparison.Ordinal) is int rapidTextStart && rapidTextStart != -1)
{ {
@@ -43,9 +45,22 @@ namespace FileTime.Avalonia.Services
} }
else else
{ {
nameParts.Add(new ItemNamePart(itemViewModel.Item.Name)); nameParts.Add(new ItemNamePart(name));
} }
return nameParts; return nameParts;
} }
public string GetFileName(string fullName)
{
var parts = fullName.Split('.');
var fileName = string.Join('.', parts[..^1]);
return fileName == "." ? fullName : fileName;
}
public string GetFileExtension(string fullName)
{
var parts = fullName.Split('.');
return parts.Length > 1 ? parts[^1] : "";
}
} }
} }

View File

@@ -72,7 +72,7 @@ namespace FileTime.Avalonia.ViewModels
{ {
get get
{ {
if (!_isInitialized) Task.Run(Refresh); if (!_isInitialized) Task.Run(Refresh).Wait();
return _containers; return _containers;
} }
set set
@@ -90,7 +90,7 @@ namespace FileTime.Avalonia.ViewModels
{ {
get get
{ {
if (!_isInitialized) Task.Run(Refresh); if (!_isInitialized) Task.Run(Refresh).Wait();
return _elements; return _elements;
} }
set set
@@ -107,7 +107,7 @@ namespace FileTime.Avalonia.ViewModels
{ {
get get
{ {
if (!_isInitialized) Task.Run(Refresh); if (!_isInitialized) Task.Run(Refresh).Wait();
return _items; return _items;
} }
set set
@@ -139,15 +139,15 @@ namespace FileTime.Avalonia.ViewModels
private async Task Container_Refreshed(object? sender, AsyncEventArgs e, CancellationToken token = default) private async Task Container_Refreshed(object? sender, AsyncEventArgs e, CancellationToken token = default)
{ {
await Refresh(false, false, token); await Refresh(false, false, token: token);
} }
[Obsolete($"Use the parametrizable version of {nameof(Refresh)}.")] [Obsolete($"Use the parametrizable version of {nameof(Refresh)}.")]
private async Task Refresh() private async Task Refresh()
{ {
await Refresh(true); await Refresh(true, silent: true);
} }
private async Task Refresh(bool initializeChildren, bool alloweReuse = true, CancellationToken token = default) private async Task Refresh(bool initializeChildren, bool alloweReuse = true, bool silent = false, CancellationToken token = default)
{ {
if (_isRefreshing) return; if (_isRefreshing) return;
@@ -169,9 +169,9 @@ namespace FileTime.Avalonia.ViewModels
} }
} }
if(await _container.GetElements() is IReadOnlyList<IElement> elements) if (await _container.GetElements() is IReadOnlyList<IElement> elements)
{ {
foreach(var element in elements) foreach (var element in elements)
{ {
var generator = async (IElement e) => var generator = async (IElement e) =>
{ {
@@ -203,9 +203,18 @@ namespace FileTime.Avalonia.ViewModels
containerToRemove?.Dispose(); containerToRemove?.Dispose();
} }
Containers = new ObservableCollection<ContainerViewModel>(newContainers); if (silent)
Elements = new ObservableCollection<ElementViewModel>(newElements); {
Items = new ObservableCollection<IItemViewModel>(newContainers.Cast<IItemViewModel>().Concat(newElements)); _containers = new ObservableCollection<ContainerViewModel>(newContainers);
_elements = new ObservableCollection<ElementViewModel>(newElements);
_items = new ObservableCollection<IItemViewModel>(newContainers.Cast<IItemViewModel>().Concat(newElements));
}
else
{
Containers = new ObservableCollection<ContainerViewModel>(newContainers);
Elements = new ObservableCollection<ElementViewModel>(newElements);
Items = new ObservableCollection<IItemViewModel>(newContainers.Cast<IItemViewModel>().Concat(newElements));
}
for (var i = 0; i < Items.Count; i++) for (var i = 0; i < Items.Count; i++)
{ {
@@ -260,19 +269,35 @@ namespace FileTime.Avalonia.ViewModels
return await generator(item); return await generator(item);
} }
public void Unload(bool recursive = true) public void Unload(bool recursive = true, bool unloadParent = true, bool unloadEvents = false)
{ {
_isInitialized = false; _isInitialized = false;
if (recursive) if (recursive)
{ {
foreach (var container in _containers) foreach (var container in _containers)
{ {
container.Unload(true); container.Unload(true, false, true);
container.Dispose(); container.Dispose();
container.ChildrenToAdopt.Clear(); container.ChildrenToAdopt.Clear();
} }
} }
if (unloadParent)
{
var parent = Parent;
while (parent != null)
{
var lastParent = parent;
parent = parent.Parent;
lastParent.Unload();
}
}
if(unloadEvents)
{
Container.Refreshed.Remove(Container_Refreshed);
}
_containers.Clear(); _containers.Clear();
_elements.Clear(); _elements.Clear();
_items.Clear(); _items.Clear();

View File

@@ -34,7 +34,14 @@ namespace FileTime.Avalonia.ViewModels
} }
else if (elementSize < MAXTEXTPREVIEWSIZE) else if (elementSize < MAXTEXTPREVIEWSIZE)
{ {
TextContent = await element.GetContent(); try
{
TextContent = await element.GetContent();
}
catch(Exception e)
{
TextContent = $"Error while getting content of {element.FullName}. " + e.ToString();
}
Mode = ElementPreviewMode.Text; Mode = ElementPreviewMode.Text;
} }
else else

View File

@@ -202,7 +202,9 @@ namespace FileTime.Avalonia.ViewModels
} }
places.Add(new PlaceInfo(name, container)); places.Add(new PlaceInfo(name, container));
} }
} }
LocalContentProvider.Unload();
} }
else else
{ {
@@ -972,6 +974,22 @@ namespace FileTime.Avalonia.ViewModels
} }
} }
private Task ToggleAutoRefresh()
{
var tab = AppState.SelectedTab.TabState.Tab;
tab.AutoRefresh = !tab.AutoRefresh;
var text = "Auto refresh is: " + (tab.AutoRefresh ? "ON" : "OFF");
_popupTexts.Add(text);
Task.Run(async () =>
{
await Task.Delay(5000);
await Dispatcher.UIThread.InvokeAsync(() => _popupTexts.Remove(text));
});
return Task.CompletedTask;
}
[Command] [Command]
public async void ProcessInputs() public async void ProcessInputs()
{ {
@@ -1438,6 +1456,11 @@ namespace FileTime.Avalonia.ViewModels
FileTime.App.Core.Command.Commands.Dummy, FileTime.App.Core.Command.Commands.Dummy,
new KeyWithModifiers[] { new KeyWithModifiers(Key.T), new KeyWithModifiers(Key.M) }, new KeyWithModifiers[] { new KeyWithModifiers(Key.T), new KeyWithModifiers(Key.M) },
ChangeTimelineMode), ChangeTimelineMode),
new CommandBinding(
"toggle auto refresh",
FileTime.App.Core.Command.Commands.Dummy,
new KeyWithModifiers[] { new KeyWithModifiers(Key.R, shift: true) },
ToggleAutoRefresh),
//TODO REMOVE //TODO REMOVE
new CommandBinding( new CommandBinding(
"open in default file browser", "open in default file browser",

View File

@@ -21,6 +21,7 @@
Source="{Binding Converter={StaticResource ItemToImageConverter}}" /> Source="{Binding Converter={StaticResource ItemToImageConverter}}" />
<ItemsControl <ItemsControl
Margin="5,0,0,0"
Grid.Column="1" Grid.Column="1"
VerticalAlignment="Center" VerticalAlignment="Center"
Items="{Binding DisplayName}"> Items="{Binding DisplayName}">
@@ -41,13 +42,14 @@
</ItemsControl> </ItemsControl>
<Grid Grid.Column="2" IsVisible="{Binding ShowAttributes,ElementName=ItemRoot}"> <Grid Grid.Column="2" IsVisible="{Binding ShowAttributes,ElementName=ItemRoot}">
<Grid ColumnDefinitions="90,90,40,45" <Grid ColumnDefinitions="30,50,90,40,45"
IsVisible="{Binding Converter={StaticResource ItemViewModelIsAttibuteTypeConverter},ConverterParameter={x:Static models:AttibuteType.LocalFile}}"> IsVisible="{Binding Converter={StaticResource ItemViewModelIsAttibuteTypeConverter},ConverterParameter={x:Static models:AttibuteType.LocalFile}}">
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Text="{Binding Size, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}"/> <TextBlock HorizontalAlignment="Right" Classes="SmallText" Text="{Binding Item.Name, Converter={StaticResource GetFileExtensionConverter}}"/>
<TextBlock HorizontalAlignment="Right" Classes="SmallText" Grid.Column="1" Text="{Binding Item.CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=yyyy-MM-dd}"/> <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=hh:mm}"/> <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="3" Text="{Binding Item.Attributes}"/> <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="4" Text="{Binding Item.Attributes}"/>
</Grid> </Grid>
<Grid ColumnDefinitions="90,40,45" <Grid ColumnDefinitions="90,40,45"
IsVisible="{Binding Converter={StaticResource ItemViewModelIsAttibuteTypeConverter},ConverterParameter={x:Static models:AttibuteType.Container}}"> IsVisible="{Binding Converter={StaticResource ItemViewModelIsAttibuteTypeConverter},ConverterParameter={x:Static models:AttibuteType.Container}}">

View File

@@ -103,6 +103,20 @@ namespace FileTime.Providers.Local
public Task Rename(string newName) => throw new NotSupportedException(); public Task Rename(string newName) => throw new NotSupportedException();
public Task<bool> CanOpen() => Task.FromResult(true); public Task<bool> CanOpen() => Task.FromResult(true);
public void Dispose() { } public void Dispose()
{
foreach (var c in _rootContainers)
{
c.Unload();
}
}
public void Unload()
{
foreach (var c in _rootContainers)
{
c.Unload();
}
}
} }
} }

View File

@@ -27,7 +27,7 @@ namespace FileTime.Providers.Local
public SupportsDelete CanDelete { get; } public SupportsDelete CanDelete { get; }
public bool CanRename => true; public bool CanRename => true;
public AsyncEventHandler Refreshed { get; } = new(); public AsyncEventHandler Refreshed { get; private set; } = new();
public string Attributes => GetAttributes(); public string Attributes => GetAttributes();
@@ -191,6 +191,14 @@ namespace FileTime.Providers.Local
_containers = null; _containers = null;
_elements = null; _elements = null;
IsDisposed = true; IsDisposed = true;
Refreshed = new AsyncEventHandler();
}
public void Unload()
{
_items = null;
_containers = null;
_elements = null;
} }
} }
} }

View File

@@ -106,5 +106,7 @@ namespace FileTime.Providers.Smb
public Task<bool> CanOpen() => Task.FromResult(true); public Task<bool> CanOpen() => Task.FromResult(true);
public void Dispose() { } public void Dispose() { }
public void Unload() { }
} }
} }

View File

@@ -119,21 +119,28 @@ namespace FileTime.Providers.Smb
public async Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default) public async Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default)
{ {
if (_items == null) await RefreshAsync(); if (_items == null) await RefreshAsync(token);
return _items; return _items;
} }
public async Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default) public async Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default)
{ {
if (_containers == null) await RefreshAsync(); if (_containers == null) await RefreshAsync(token);
return _containers; return _containers;
} }
public async Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default) public async Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default)
{ {
if (_elements == null) await RefreshAsync(); if (_elements == null) await RefreshAsync(token);
return _elements; return _elements;
} }
public Task<bool> CanOpen() => Task.FromResult(true); public Task<bool> CanOpen() => Task.FromResult(true);
public void Dispose() => IsDisposed = true; public void Dispose() => IsDisposed = true;
public void Unload()
{
_items = null;
_containers = null;
_elements = null;
}
} }
} }

View File

@@ -194,5 +194,7 @@ namespace FileTime.Providers.Smb
public Task<bool> CanOpen() => Task.FromResult(true); public Task<bool> CanOpen() => Task.FromResult(true);
public void Dispose() { } public void Dispose() { }
public void Unload() { }
} }
} }

View File

@@ -172,5 +172,12 @@ namespace FileTime.Providers.Smb
public Task<bool> CanOpen() => Task.FromResult(true); public Task<bool> CanOpen() => Task.FromResult(true);
public void Dispose() { } public void Dispose() { }
public void Unload()
{
_items = null;
_containers = null;
_elements = null;
}
} }
} }