Console size scan

This commit is contained in:
2023-08-28 21:29:15 +02:00
parent bc865011d3
commit ba06047a68
43 changed files with 567 additions and 279 deletions

View File

@@ -1,4 +1,5 @@
using DeclarativeProperty;
using FileTime.Core.Models;
namespace FileTime.App.ContainerSizeScanner;
@@ -7,7 +8,7 @@ public class ChildElementPreview : ISizePreviewItem
public ChildElementPreview(ISizeScanElement element)
{
Name = element.Name;
Size = element.Size;
Size = new DeclarativeProperty<long>(((IElement) element).Size);
}
public string Name { get; }

View File

@@ -18,6 +18,9 @@ public record SizeScanElement : ISizeScanElement
public required DateTime? ModifiedAt { get; init;}
public required IDeclarativeProperty<long> Size { get; init; }
long IElement.Size => Size.Value;
public bool IsHidden => false;
public bool IsExists => true;
public SupportsDelete CanDelete => SupportsDelete.False;

View File

@@ -1,7 +1,6 @@
using DeclarativeProperty;
using FileTime.Core.Enums;
using FileTime.Core.Models;
using FileTime.Core.Models.Extensions;
using FileTime.Core.Timeline;
using Microsoft.Extensions.Logging;
@@ -104,10 +103,7 @@ public class SizeScanTask : ISizeScanTask
{
if (_cancelled) return;
var fileExtension = element.GetExtension<FileExtension>();
var size = fileExtension?.Size ?? 0;
var sizeProperty = new DeclarativeProperty<long>(size);
var sizeProperty = new DeclarativeProperty<long>(element.Size);
var childName = sizeScanContainer.FullName!.GetChild(element.Name).Path;
var childElement = new SizeScanElement

View File

@@ -25,4 +25,9 @@
<ProjectReference Include="..\..\Library\GeneralInputKey\GeneralInputKey.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Models\Traits\" />
</ItemGroup>
</Project>

View File

@@ -7,8 +7,8 @@ namespace FileTime.App.Core.ViewModels;
public interface IElementViewModel :
IItemViewModel,
ISizeProvider,
IInitable<IElement, ITabViewModel, ItemViewModelType>
IInitable<IElement, ITabViewModel, ItemViewModelType>,
ISizeProvider
{
IElement? Element { get; }
}

View File

@@ -1,10 +0,0 @@
using FileTime.App.Core.Models.Enums;
using FileTime.Core.Models;
using FileTime.Core.Models.Extensions;
using InitableService;
namespace FileTime.App.Core.ViewModels;
public interface IFileViewModel : IElementViewModel, IInitable<IElement, FileExtension, ITabViewModel, ItemViewModelType>
{
}

View File

@@ -44,4 +44,5 @@
<ProjectReference Include="..\FileTime.App.Search\FileTime.App.Search.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
namespace FileTime.GuiApp.App.Helper;
namespace FileTime.App.Core.Helpers;
public static class ColorHelper
{

View File

@@ -0,0 +1,27 @@
using System.Collections.ObjectModel;
using FileTime.App.ContainerSizeScanner;
namespace FileTime.App.Core.Helpers;
public static class SizePreviewItemHelper
{
public static (byte r, byte g, byte b) GetItemColor(
ObservableCollection<ISizePreviewItem> items,
ISizePreviewItem currentItem,
double hueDiff = 0,
double lightness = 0.75
)
{
var i = 0;
for (; i < items.Count; i++)
{
if (items[i].Name == currentItem.Name) break;
}
var hue = (360d * i / (items.Count < 1 ? 1 : items.Count)) + hueDiff;
if (hue > 360) hue -= 360;
if (hue < 0) hue += 360;
return ColorHelper.HlsToRgb(hue, lightness, 1);
}
}

View File

@@ -321,7 +321,7 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase
{
if (_selectedTab is null || _currentItems?.Value is null) return Task.CompletedTask;
var newSelectedItem = getNewSelected(_currentItems.Value);
var newSelectedItem = getNewSelected(_currentItems.Value.ToArray());
if (newSelectedItem == null) return Task.CompletedTask;
if (_selectedTab.Tab is { } tab)

View File

@@ -18,7 +18,6 @@ public static class Startup
serviceCollection.TryAddTransient<ITabViewModel, TabViewModel>();
serviceCollection.TryAddTransient<IContainerViewModel, ContainerViewModel>();
serviceCollection.TryAddTransient<IElementViewModel, ElementViewModel>();
serviceCollection.TryAddTransient<IFileViewModel, FileViewModel>();
serviceCollection.TryAddTransient<IItemNameConverterService, ItemNameConverterService>();
serviceCollection.TryAddTransient<ElementPreviewViewModel>();
serviceCollection.TryAddSingleton<IUserCommandHandlerService, UserCommandHandlerService>();

View File

@@ -4,7 +4,7 @@ using FileTime.Core.Models;
namespace FileTime.App.Core.ViewModels;
public partial class ContainerViewModel : ItemViewModel, IContainerViewModel
public class ContainerViewModel : ItemViewModel, IContainerViewModel
{
public IContainer? Container => BaseItem as IContainer;

View File

@@ -5,8 +5,9 @@ using FileTime.Core.Models;
namespace FileTime.App.Core.ViewModels;
public partial class ElementViewModel : ItemViewModel, IElementViewModel
public class ElementViewModel : ItemViewModel, IElementViewModel
{
private readonly DeclarativeProperty<long> _size = new(0);
public IElement? Element => BaseItem as Element;
public ElementViewModel(IItemNameConverterService itemNameConverterService, IAppState appState) : base(itemNameConverterService, appState)
@@ -14,7 +15,10 @@ public partial class ElementViewModel : ItemViewModel, IElementViewModel
}
public void Init(IElement item, ITabViewModel parentTab, ItemViewModelType itemViewModelType)
=> Init((IItem)item, parentTab, itemViewModelType);
{
Init((IItem) item, parentTab, itemViewModelType);
_size.SetValueSafe(item.Size);
}
public IDeclarativeProperty<long> Size { get; protected set; } = new DeclarativeProperty<long>(0);
public IDeclarativeProperty<long> Size => _size;
}

View File

@@ -1,20 +0,0 @@
using DeclarativeProperty;
using FileTime.App.Core.Models.Enums;
using FileTime.App.Core.Services;
using FileTime.Core.Models;
using FileTime.Core.Models.Extensions;
namespace FileTime.App.Core.ViewModels;
public partial class FileViewModel : ElementViewModel, IFileViewModel
{
public FileViewModel(IItemNameConverterService itemNameConverterService, IAppState appState) : base(itemNameConverterService, appState)
{
}
public void Init(IElement item, FileExtension fileExtension, ITabViewModel parentTab, ItemViewModelType itemViewModelType)
{
Init(item, parentTab, itemViewModelType);
Size = new DeclarativeProperty<long>(fileExtension.Size ?? 0);
}
}

View File

@@ -7,7 +7,6 @@ using FileTime.App.Core.Models.Enums;
using FileTime.App.Core.Services;
using FileTime.Core.Enums;
using FileTime.Core.Models;
using FileTime.Core.Models.Extensions;
using FileTime.Core.Services;
using FileTime.Core.Timeline;
using InitableService;
@@ -205,19 +204,6 @@ public partial class TabViewModel : ITabViewModel
return containerViewModel;
}
else if (item is IElement element)
{
var fileExtension = element.GetExtension<FileExtension>();
if (fileExtension is not null)
{
var fileViewModel = _serviceProvider
.GetInitableResolver<IElement, FileExtension, ITabViewModel, ItemViewModelType>(
element, fileExtension, this, type)
.GetRequiredService<IFileViewModel>();
return fileViewModel;
}
else
{
var elementViewModel = _serviceProvider
.GetInitableResolver<IElement, ITabViewModel, ItemViewModelType>(element, this, type)
@@ -225,7 +211,6 @@ public partial class TabViewModel : ITabViewModel
return elementViewModel;
}
}
throw new ArgumentException($"{nameof(item)} is not {nameof(IContainer)} neither {nameof(IElement)}");
}

View File

@@ -1,7 +1,12 @@
using FileTime.App.Core.Models;
using System.Collections.ObjectModel;
using FileTime.App.ContainerSizeScanner;
using FileTime.App.Core.Helpers;
using FileTime.App.Core.Models;
using FileTime.App.Core.ViewModels.ItemPreview;
using FileTime.ConsoleUI.App.Preview;
using FileTime.ConsoleUI.App.Styling;
using Humanizer.Bytes;
using TerminalUI.Color;
using TerminalUI.Controls;
using TerminalUI.Extensions;
using TerminalUI.Models;
@@ -13,11 +18,18 @@ public class ItemPreviews
{
private readonly ITheme _theme;
private readonly IConsoleAppState _appState;
private readonly IColorProvider _colorProvider;
private ItemsControl<ContainerPreview, ISizePreviewItem> _sizePreviews;
public ItemPreviews(ITheme theme, IConsoleAppState appState)
public ItemPreviews(
ITheme theme,
IConsoleAppState appState,
IColorProvider colorProvider
)
{
_theme = theme;
_appState = appState;
_colorProvider = colorProvider;
}
public IView<IRootViewModel> View()
@@ -38,7 +50,11 @@ public class ItemPreviews
fallbackValue: false)),
ElementPreviews()
.WithDataContextBinding<IRootViewModel, IElementPreviewViewModel>(
dc => (IElementPreviewViewModel)dc.ItemPreviewService.ItemPreview.Value
dc => (IElementPreviewViewModel) dc.ItemPreviewService.ItemPreview.Value
),
SizeContainerPreview()
.WithDataContextBinding<IRootViewModel, ContainerPreview>(
dc => (ContainerPreview) dc.ItemPreviewService.ItemPreview.Value
)
}
};
@@ -46,6 +62,125 @@ public class ItemPreviews
return view;
}
private IView<ContainerPreview> SizeContainerPreview()
{
var sizePreviews = new ItemsControl<ContainerPreview, ISizePreviewItem>
{
Orientation = Orientation.Horizontal,
Margin = "0 0 0 1"
};
sizePreviews.Setup(c => c.Bind(
c,
dc => dc.TopItems,
c => c.ItemsSource));
_sizePreviews = sizePreviews;
sizePreviews.ItemTemplate = SizeContainerItem;
var root = new Grid<ContainerPreview>
{
RowDefinitionsObject = "Auto Auto",
ChildInitializer =
{
sizePreviews,
new ItemsControl<ContainerPreview, ISizePreviewItem>
{
Extensions = {new GridPositionExtension(0, 1)},
ItemTemplate = () =>
{
var root = new Grid<ISizePreviewItem>
{
ColumnDefinitionsObject = "5 11 *",
ChildInitializer =
{
new Rectangle<ISizePreviewItem>
{
Height = 1,
Width = 3
}
.Setup(r => r.Bind(
r,
dc => GenerateSizeBackground(_sizePreviews.DataContext.TopItems, dc),
r => r.Fill)),
new TextBlock<ISizePreviewItem>
{
Extensions = {new GridPositionExtension(1, 0)},
TextAlignment = TextAlignment.Right,
Margin = "0 0 1 0"
}
.Setup(t => t.Bind(
t,
dc => dc.Size.Value,
t => t.Text,
v => ByteSize.FromBytes(v).ToString())),
new TextBlock<ISizePreviewItem>
{
Extensions = {new GridPositionExtension(2, 0)}
}
.Setup(t => t.Bind(
t,
dc => dc.Name,
t => t.Text))
}
};
return root;
}
}
.Setup(c => c.Bind(
c,
dc => dc.TopItems,
c => c.ItemsSource))
}
};
root.Bind(
root,
dc => dc.Name == ContainerPreview.PreviewName,
r => r.IsVisible);
return root;
}
private Grid<ISizePreviewItem> SizeContainerItem()
{
var root = new Grid<ISizePreviewItem>
{
ChildInitializer =
{
new Rectangle<ISizePreviewItem>
{
Height = 1
}
.Setup(r => r.Bind(
r,
dc => GenerateSizeBackground(_sizePreviews.DataContext.TopItems, dc),
r => r.Fill))
}
};
root.Bind(
root,
dc => GetWidth(dc.Size.Value, _sizePreviews.DataContext.TopItems, _sizePreviews.ActualWidth),
r => r.Width);
return root;
}
private int? GetWidth(long sizeValue, ObservableCollection<ISizePreviewItem>? dataContextTopItems, int rootActualWidth)
=> dataContextTopItems is null
? 0
: (int) Math.Floor((double) rootActualWidth * sizeValue / dataContextTopItems.Select(i => i.Size.Value).Sum());
private IColor? GenerateSizeBackground(ObservableCollection<ISizePreviewItem> topItems, ISizePreviewItem? dc)
{
if (dc is null) return null;
var (r, g, b) = SizePreviewItemHelper.GetItemColor(topItems, dc);
return _colorProvider.FromRgb(new Rgb(r, g, b), ColorType.Background);
}
private IView<IElementPreviewViewModel> ElementPreviews()
{
var view = new Grid<IElementPreviewViewModel>
@@ -60,7 +195,6 @@ public class ItemPreviews
t,
dc => dc.Mode == ItemPreviewMode.Unknown,
t => t.IsVisible,
v => v,
fallbackValue: false)),
new TextBlock<IElementPreviewViewModel>
{
@@ -70,7 +204,6 @@ public class ItemPreviews
t,
dc => dc.Mode == ItemPreviewMode.Empty,
t => t.IsVisible,
v => v,
fallbackValue: false)),
new Grid<IElementPreviewViewModel>
{
@@ -120,7 +253,6 @@ public class ItemPreviews
t,
dc => dc.Mode == ItemPreviewMode.Text,
t => t.IsVisible,
v => v,
fallbackValue: false)),
}
};
@@ -128,8 +260,7 @@ public class ItemPreviews
view.Bind(
view,
dc => dc.Name == ElementPreviewViewModel.PreviewName,
v => v.IsVisible,
v => v
v => v.IsVisible
);
return view;

View File

@@ -20,6 +20,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\AppCommon\FileTime.App.ContainerSizeScanner\FileTime.App.ContainerSizeScanner.csproj" />
<ProjectReference Include="..\..\AppCommon\FileTime.App.Core\FileTime.App.Core.csproj" />
<ProjectReference Include="..\..\AppCommon\FileTime.App.FrequencyNavigation\FileTime.App.FrequencyNavigation.csproj" />
<ProjectReference Include="..\..\Library\TerminalUI\TerminalUI.csproj" />

View File

@@ -1,5 +1,6 @@
using System.Globalization;
using FileTime.App.Core.Models.Enums;
using FileTime.App.Core.Models.Traits;
using FileTime.App.Core.ViewModels;
using FileTime.ConsoleUI.App.Configuration;
using FileTime.ConsoleUI.App.Controls;
@@ -479,7 +480,9 @@ public class MainWindow
list.Bind(
list,
dc => dc.AppState.SelectedTab.Value.SelectedsChildren.Value.Count > 0,
dc =>
dc.AppState.SelectedTab.Value.SelectedsChildren.Value.Count > 0
&& dc.ItemPreviewService.ItemPreview.Value == null,
l => l.IsVisible,
fallbackValue: false);
@@ -544,28 +547,9 @@ public class MainWindow
if (!options.ShowAttributes) return;
t.Bind(
t,
dc => ((IContainer) dc.BaseItem).Items.Count,
tb => tb.Text,
t => $" {t}");
})
}
}
.Setup(s => s.Bind(
s,
dc => dc.BaseItem.Type == AbsolutePathType.Container,
s => s.IsVisible)),
new StackPanel<IItemViewModel>
{
Extensions = {new GridPositionExtension(1, 0)},
ChildInitializer =
{
new TextBlock<IItemViewModel>()
.Setup(t =>
{
if (!options.ShowAttributes) return;
t.Bind(
t,
dc => ((IElementViewModel) dc).Size.Value,
dc => dc is ISizeProvider
? ((ISizeProvider) dc).Size.Value
: ((ISizeProvider) dc.BaseItem).Size.Value,
tb => tb.Text,
v =>
{
@@ -573,13 +557,23 @@ public class MainWindow
return $"{b.LargestWholeNumberValue:0.#} " + b.GetLargestWholeNumberSymbol(NumberFormatInfo.CurrentInfo).First();
});
})
}
}
.Setup(s => s.Bind(
}),
/*new TextBlock<IItemViewModel>()
.Setup(t =>
{
if (!options.ShowAttributes) return;
t.Bind(
t,
dc => ((IContainer) dc.BaseItem).Items.Count,
tb => tb.Text,
t => $" {t,4}");
}).Setup(s => s.Bind(
s,
dc => dc.BaseItem.Type == AbsolutePathType.Element,
s => s.IsVisible))
dc => dc.BaseItem.Type == AbsolutePathType.Container,
s => s.IsVisible))*/
}
},
}
}
}

View File

@@ -1,6 +1,4 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using FileTime.App.Core;
using FileTime.App.Core.Configuration;
using FileTime.ConsoleUI;
@@ -52,7 +50,6 @@ try
}
finally
{
driver?.Clear();
driver?.SetCursorVisible(true);
driver?.Dispose();
}

View File

@@ -17,7 +17,7 @@ public static class Startup
{
public static readonly Dictionary<string, Func<IConsoleDriver>> Drivers = new()
{
["windows"] = () => new XTermDriver(),
["xterm"] = () => new XTermDriver(),
["dotnet"] = () => new DotnetDriver()
};
public static IServiceCollection AddConsoleDriver(this IServiceCollection serviceCollection)

View File

@@ -1,3 +0,0 @@
namespace FileTime.Core.Models.Extensions;
public record FileExtension(long? Size);

View File

@@ -2,5 +2,5 @@ namespace FileTime.Core.Models;
public interface IElement : IItem
{
long Size { get; }
}

View File

@@ -1,5 +1,4 @@
using FileTime.Core.Models;
using FileTime.Core.Models.Extensions;
using FileTime.Core.Timeline;
namespace FileTime.Core.Command.Copy;
@@ -20,7 +19,7 @@ public class CalculateStrategy : ICopyStrategy
public async Task CopyAsync(AbsolutePath from, AbsolutePath to, CopyCommandContext context)
{
var resolvedFrom = await from.ResolveAsync();
_operationStatuses.Add(new OperationProgress(from.Path.Path, (resolvedFrom as IElement)?.GetExtension<FileExtension>()?.Size ?? 0L));
_operationStatuses.Add(new OperationProgress(from.Path.Path, (resolvedFrom as IElement)?.Size ?? 0L));
}
public Task CreateContainerAsync(IContainer target, string name, PointInTime currentTime) => Task.CompletedTask;

View File

@@ -18,6 +18,7 @@ public record Element(
SupportsDelete CanDelete,
bool CanRename,
string? Attributes,
long Size,
IContentProvider Provider,
PointInTime PointInTime,
ObservableCollection<Exception> Exceptions,

View File

@@ -6,7 +6,6 @@ using DeclarativeProperty;
using DynamicData;
using FileTime.Core.Helper;
using FileTime.Core.Models;
using FileTime.Core.Models.Extensions;
using FileTime.Core.Timeline;
using ObservableComputations;
using IContainer = FileTime.Core.Models.IContainer;
@@ -178,12 +177,12 @@ public class Tab : ITab
private static long GetSize(IItem item)
{
if (item is IElement element && element.GetExtension<FileExtension>() is { } fileExtension)
if (item is IElement element)
{
return fileExtension.Size ?? -1;
return element.Size;
}
return -2;
return -1;
}
private static IItem MapItem(AbsolutePath item)

View File

@@ -3,7 +3,7 @@ using Avalonia.Data.Converters;
using Avalonia.Media;
using Avalonia.Threading;
using FileTime.App.ContainerSizeScanner;
using FileTime.GuiApp.App.Helper;
using FileTime.App.Core.Helpers;
namespace FileTime.GuiApp.App.Converters;
@@ -16,18 +16,12 @@ public class ItemSizeToBrushConverter : IMultiValueConverter
{
if (values is [ISizePreviewItem previewItem, ContainerPreview sizeContainerViewModel])
{
var items = sizeContainerViewModel.TopItems;
var i = 0;
for (; i < items.Count; i++)
{
if (items[i].Name == previewItem.Name) break;
}
var hue = (360d * i / (items.Count < 1 ? 1 : items.Count)) + HueDiff;
if (hue > 360) hue -= 360;
if (hue < 0) hue += 360;
var (r, g, b) = ColorHelper.HlsToRgb(hue, Lightness, 1);
var (r, g, b) = SizePreviewItemHelper.GetItemColor(
sizeContainerViewModel.TopItems,
previewItem,
HueDiff,
Lightness
);
var task = Dispatcher.UIThread.InvokeAsync(() => new SolidColorBrush(Color.FromRgb(r, g, b)));
task.Wait();

View File

@@ -1,48 +1,52 @@
<UserControl
Background="{Binding ViewMode.Value, Converter={StaticResource ItemViewModeToBackgroundConverter}}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d"
x:Class="FileTime.GuiApp.App.Views.ItemView"
x:CompileBindings="True"
x:DataType="appcore:IItemViewModel"
x:Name="ItemRoot"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:appcore="using:FileTime.App.Core.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:guiappvm="using:FileTime.GuiApp.App.ViewModels"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:traits="clr-namespace:FileTime.App.Core.Models.Traits;assembly=FileTime.App.Core.Abstraction"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
x:Name="ItemRoot"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True"
x:DataType="appcore:IItemViewModel"
Background="{Binding ViewMode.Value, Converter={StaticResource ItemViewModeToBackgroundConverter}}"
mc:Ignorable="d">
<Grid
ColumnDefinitions="20,*,Auto"
x:Name="RootGrid"
Margin="3"
x:Name="RootGrid">
ColumnDefinitions="20,*,Auto">
<Grid.Styles>
<Style Selector="TextBlock">
<Setter Property="Foreground" Value="{Binding DataContext.ViewMode.Value, Converter={StaticResource ItemViewModeToForegroundConverter}, ElementName=ItemRoot}" x:CompileBindings="False" />
<Setter x:CompileBindings="False" Property="Foreground" Value="{Binding DataContext.ViewMode.Value, Converter={StaticResource ItemViewModeToForegroundConverter}, ElementName=ItemRoot}" />
</Style>
</Grid.Styles>
<Image
Width="18"
Height="18"
HorizontalAlignment="Left"
Source="{Binding Converter={StaticResource ItemToImageConverter}}"
VerticalAlignment="Center"
Width="18" />
Source="{Binding Converter={StaticResource ItemToImageConverter}}" />
<ItemsControl
Grid.Column="1"
HorizontalAlignment="Stretch"
Margin="5,0,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center">
<ItemsControl.ItemsSource>
<MultiBinding Converter="{StaticResource NamePartShrinkerConverter}">
<MultiBinding.Bindings>
<Binding Path="DisplayName^" />
<Binding ElementName="RootGrid" Path="Bounds.Width" />
<Binding ElementName="ItemRoot" Path="ShowAttributes" />
<Binding
ElementName="RootGrid"
Path="Bounds.Width" />
<Binding
ElementName="ItemRoot"
Path="ShowAttributes" />
</MultiBinding.Bindings>
</MultiBinding>
</ItemsControl.ItemsSource>
@@ -54,52 +58,50 @@
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="guiappvm:ItemNamePartViewModel">
<Grid>
<TextBlock Text="{Binding Text}" TextDecorations="{Binding TextDecorations}" />
<TextBlock
Text="{Binding Text}"
TextDecorations="{Binding TextDecorations}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Grid Grid.Column="2" IsVisible="{Binding ShowAttributes, ElementName=ItemRoot}">
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Grid
Grid.Column="2"
IsVisible="{Binding ShowAttributes, ElementName=ItemRoot}">
<StackPanel
HorizontalAlignment="Right"
Orientation="Horizontal">
<TextBlock
Width="50"
Classes="SmallText"
IsVisible="{Binding Converter={StaticResource IsTypeConverter}, ConverterParameter={x:Type appcore:IElementViewModel}}"
Text="{Binding BaseItem.DisplayName, Converter={StaticResource GetFileExtensionConverter}}"
Width="50" />
<Grid DataContext="{Binding BaseItem}" IsVisible="{Binding Converter={StaticResource IsTypeConverter}, ConverterParameter={x:Type traits:ISizeProvider}}">
Text="{Binding BaseItem.DisplayName, Converter={StaticResource GetFileExtensionConverter}}" />
<Grid
DataContext="{Binding BaseItem}"
IsVisible="{Binding Converter={StaticResource IsTypeConverter}, ConverterParameter={x:Type traits:ISizeProvider}}">
<TextBlock
Width="60"
x:DataType="traits:ISizeProvider"
Classes="SmallText"
Text="{Binding Size.Value, Converter={StaticResource FormatSizeConverter}}"
TextAlignment="Right"
Width="60"
x:DataType="traits:ISizeProvider" />
</Grid>
<Grid IsVisible="{Binding BaseItem, Converter={StaticResource IsNotTypeConverter}, ConverterParameter={x:Type traits:ISizeProvider}}">
<TextBlock
Classes="SmallText"
IsVisible="{Binding Converter={StaticResource IsTypeConverter}, ConverterParameter={x:Type traits:ISizeProvider}}"
Text="{Binding Size.Value, Converter={StaticResource FormatSizeConverter}}"
TextAlignment="Right"
Width="60"
x:DataType="traits:ISizeProvider" />
TextAlignment="Right" />
</Grid>
<TextBlock
Width="95"
Classes="SmallText"
Text="{Binding ModifiedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=yyyy-MM-dd}"
TextAlignment="Right"
Width="95" />
TextAlignment="Right" />
<TextBlock
Width="35"
Classes="SmallText"
Text="{Binding ModifiedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter=hh:mm}"
TextAlignment="Right"
Width="35" />
TextAlignment="Right" />
<TextBlock
Width="45"
Classes="SmallText"
Text="{Binding BaseItem.Attributes}"
TextAlignment="Right"
Width="45" />
TextAlignment="Right" />
</StackPanel>

View File

@@ -58,6 +58,7 @@ public class ItemPreview
SupportsDelete.True,
true,
"attr",
0,
null!,
PointInTime.Present,
new ObservableCollection<Exception>(),

View File

@@ -10,7 +10,6 @@ using FileTime.GuiApp.App.Font;
using FileTime.GuiApp.App.ViewModels;
using FileTime.GuiApp.App.Views;
using FileTime.Server;
using FileTime.Server.Common;
using FileTime.Tools.Compression;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

View File

@@ -6,49 +6,24 @@ public class AnsiColorProvider : ColorProviderBase
{
var finalColor = ParseInternal(color, type);
finalColor ??= ParseHexColor(color, type);
finalColor ??= FromRgb(color, type);
if (finalColor is not null) return finalColor;
throw new NotSupportedException($"Color can not be parsed. {color}");
}
private static IColor? ParseHexColor(string color, ColorType colorType)
private IColor? FromRgb(string color, ColorType type)
{
if (!color.StartsWith("#")) return null;
if (color.Length == 4)
if (ParseHexColor(color) is var (r, g, b))
{
var r = ColorCharToColorByte(color[1]);
var g = ColorCharToColorByte(color[2]);
var b = ColorCharToColorByte(color[3]);
r += (byte) (r << 4);
g += (byte) (g << 4);
b += (byte) (b << 4);
return new ColorRgb(r, g, b, colorType);
return new ColorRgb(r, g, b, type);
}
if (color.Length == 7)
{
var r = (byte) (ColorCharToColorByte(color[1]) << 4 | ColorCharToColorByte(color[2]));
var g = (byte) (ColorCharToColorByte(color[3]) << 4 | ColorCharToColorByte(color[4]));
var b = (byte) (ColorCharToColorByte(color[5]) << 4 | ColorCharToColorByte(color[6]));
return new ColorRgb(r, g, b, colorType);
return null;
}
throw new NotSupportedException($"Hex color can not be parsed. {color}");
}
private static byte ColorCharToColorByte(char color) =>
color switch
{
>= '0' and <= '9' => (byte) (color - '0'),
>= 'A' and <= 'F' => (byte) (color - 'A' + 10),
>= 'a' and <= 'f' => (byte) (color - 'a' + 10),
_ => throw new NotSupportedException($"Hex color can not be parsed. {color}")
};
public override IColor FromRgb(Rgb rgb, ColorType type) => new ColorRgb(rgb.R, rgb.G, rgb.B, type);
public override IColor BlackForeground { get; } = new Color256(0, ColorType.Foreground);
public override IColor BlueForeground { get; } = new Color256(12, ColorType.Foreground);

View File

@@ -3,6 +3,44 @@
public abstract class ColorProviderBase : IColorProvider
{
public abstract IColor Parse(string color, ColorType type);
public abstract IColor FromRgb(Rgb rgb, ColorType type);
protected static Rgb? ParseHexColor(string color)
{
if (!color.StartsWith("#")) return null;
if (color.Length == 4)
{
var r = ColorCharToColorByte(color[1]);
var g = ColorCharToColorByte(color[2]);
var b = ColorCharToColorByte(color[3]);
r += (byte) (r << 4);
g += (byte) (g << 4);
b += (byte) (b << 4);
return new(r, g, b);
}
if (color.Length == 7)
{
var r = (byte) (ColorCharToColorByte(color[1]) << 4 | ColorCharToColorByte(color[2]));
var g = (byte) (ColorCharToColorByte(color[3]) << 4 | ColorCharToColorByte(color[4]));
var b = (byte) (ColorCharToColorByte(color[5]) << 4 | ColorCharToColorByte(color[6]));
return new(r, g, b);
}
return null;
}
private static byte ColorCharToColorByte(char color) =>
color switch
{
>= '0' and <= '9' => (byte) (color - '0'),
>= 'A' and <= 'F' => (byte) (color - 'A' + 10),
>= 'a' and <= 'f' => (byte) (color - 'a' + 10),
_ => throw new NotSupportedException($"Hex color can not be parsed. {color}")
};
protected IColor? ParseInternal(string color, ColorType type)
=> (color.ToLower(), type) switch

View File

@@ -7,8 +7,8 @@ public readonly record struct ColorRgb(byte R, byte G, byte B, ColorType Type) :
public string ToConsoleColor()
=> Type switch
{
ColorType.Foreground => $"\x1b[38;2;{R};{G};{B};m",
ColorType.Background => $"\x1b[48;2;{R};{G};{B};m",
ColorType.Foreground => $"\x1b[38;2;{R};{G};{B}m",
ColorType.Background => $"\x1b[48;2;{R};{G};{B}m",
_ => throw new InvalidEnumArgumentException(nameof(Type), (int) Type, typeof(ColorType))
};
public IColor AsForeground() => this with {Type = ColorType.Foreground};

View File

@@ -1,48 +1,143 @@
namespace TerminalUI.Color;
// ReSharper disable InconsistentNaming
namespace TerminalUI.Color;
public class ConsoleColorProvider : ColorProviderBase
{
private static readonly List<(Rgb, IColor)> Foregrounds;
private static readonly List<(Rgb, IColor)> Backgrounds;
static ConsoleColorProvider()
{
Foregrounds = new List<(Rgb, IColor)>
{
(new Rgb(0, 0, 0), _blackForeground),
(new Rgb(0, 0, 128), _darkBlueForeground),
(new Rgb(0, 128, 0), _darkGreenForeground),
(new Rgb(0, 128, 128), _darkCyanForeground),
(new Rgb(128, 0, 0), _darkRedForeground),
(new Rgb(128, 0, 128), _darkMagentaForeground),
(new Rgb(128, 128, 0), _darkYellowForeground),
(new Rgb(192, 192, 192), _grayForeground),
(new Rgb(128, 128, 128), _darkGrayForeground),
(new Rgb(0, 0, 255), _blueForeground),
(new Rgb(0, 255, 0), _greenForeground),
(new Rgb(0, 255, 255), _cyanForeground),
(new Rgb(255, 0, 0), _redForeground),
(new Rgb(255, 0, 255), _magentaForeground),
(new Rgb(255, 255, 0), _yellowForeground),
(new Rgb(255, 255, 255), _whiteForeground),
};
Backgrounds = new List<(Rgb, IColor)>
{
(new Rgb(0, 0, 0), _blackBackground),
(new Rgb(0, 0, 128), _darkBlueBackground),
(new Rgb(0, 128, 0), _darkGreenBackground),
(new Rgb(0, 128, 128), _darkCyanBackground),
(new Rgb(128, 0, 0), _darkRedBackground),
(new Rgb(128, 0, 128), _darkMagentaBackground),
(new Rgb(128, 128, 0), _darkYellowBackground),
(new Rgb(192, 192, 192), _grayBackground),
(new Rgb(128, 128, 128), _darkGrayBackground),
(new Rgb(0, 0, 255), _blueBackground),
(new Rgb(0, 255, 0), _greenBackground),
(new Rgb(0, 255, 255), _cyanBackground),
(new Rgb(255, 0, 0), _redBackground),
(new Rgb(255, 0, 255), _magentaBackground),
(new Rgb(255, 255, 0), _yellowBackground),
(new Rgb(255, 255, 255), _whiteBackground),
};
}
public override IColor Parse(string color, ColorType type)
{
var finalColor = ParseInternal(color, type);
if (finalColor is not null) return finalColor;
//TODO get closest color
var rgb = ParseHexColor(color);
if (rgb is null)
{
throw new NotSupportedException($"Color can not be parsed. {color}");
}
public override IColor BlackForeground { get; } = new ConsoleColor(System.ConsoleColor.Black, ColorType.Foreground);
public override IColor BlueForeground { get; } = new ConsoleColor(System.ConsoleColor.Blue, ColorType.Foreground);
public override IColor CyanForeground { get; } = new ConsoleColor(System.ConsoleColor.Cyan, ColorType.Foreground);
public override IColor DarkBlueForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkBlue, ColorType.Foreground);
public override IColor DarkCyanForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkCyan, ColorType.Foreground);
public override IColor DarkGrayForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkGray, ColorType.Foreground);
public override IColor DarkGreenForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkGreen, ColorType.Foreground);
public override IColor DarkMagentaForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkMagenta, ColorType.Foreground);
public override IColor DarkRedForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkRed, ColorType.Foreground);
public override IColor DarkYellowForeground { get; } = new ConsoleColor(System.ConsoleColor.DarkYellow, ColorType.Foreground);
public override IColor GrayForeground { get; } = new ConsoleColor(System.ConsoleColor.Gray, ColorType.Foreground);
public override IColor GreenForeground { get; } = new ConsoleColor(System.ConsoleColor.Green, ColorType.Foreground);
public override IColor MagentaForeground { get; } = new ConsoleColor(System.ConsoleColor.Magenta, ColorType.Foreground);
public override IColor RedForeground { get; } = new ConsoleColor(System.ConsoleColor.Red, ColorType.Foreground);
public override IColor WhiteForeground { get; } = new ConsoleColor(System.ConsoleColor.White, ColorType.Foreground);
public override IColor YellowForeground { get; } = new ConsoleColor(System.ConsoleColor.Yellow, ColorType.Foreground);
return FromRgb(rgb.Value, type);
}
public override IColor BlackBackground => new ConsoleColor(System.ConsoleColor.Black, ColorType.Background);
public override IColor BlueBackground => new ConsoleColor(System.ConsoleColor.Blue, ColorType.Background);
public override IColor CyanBackground => new ConsoleColor(System.ConsoleColor.Cyan, ColorType.Background);
public override IColor DarkBlueBackground => new ConsoleColor(System.ConsoleColor.DarkBlue, ColorType.Background);
public override IColor DarkCyanBackground => new ConsoleColor(System.ConsoleColor.DarkCyan, ColorType.Background);
public override IColor DarkGrayBackground => new ConsoleColor(System.ConsoleColor.DarkGray, ColorType.Background);
public override IColor DarkGreenBackground => new ConsoleColor(System.ConsoleColor.DarkGreen, ColorType.Background);
public override IColor DarkMagentaBackground => new ConsoleColor(System.ConsoleColor.DarkMagenta, ColorType.Background);
public override IColor DarkRedBackground => new ConsoleColor(System.ConsoleColor.DarkRed, ColorType.Background);
public override IColor DarkYellowBackground => new ConsoleColor(System.ConsoleColor.DarkYellow, ColorType.Background);
public override IColor GrayBackground => new ConsoleColor(System.ConsoleColor.Gray, ColorType.Background);
public override IColor GreenBackground => new ConsoleColor(System.ConsoleColor.Green, ColorType.Background);
public override IColor MagentaBackground => new ConsoleColor(System.ConsoleColor.Magenta, ColorType.Background);
public override IColor RedBackground => new ConsoleColor(System.ConsoleColor.Red, ColorType.Background);
public override IColor WhiteBackground => new ConsoleColor(System.ConsoleColor.White, ColorType.Background);
public override IColor YellowBackground => new ConsoleColor(System.ConsoleColor.Yellow, ColorType.Background);
public override IColor FromRgb(Rgb rgb, ColorType type)
=> type == ColorType.Background
? ApproximateColor(rgb, Backgrounds)
: ApproximateColor(rgb, Foregrounds);
protected IColor ApproximateColor(Rgb rgb, IEnumerable<(Rgb, IColor)> colors)
=> colors.MinBy(c => c.Item1 - rgb).Item2;
public override IColor BlackForeground => _blackForeground;
public override IColor BlueForeground => _blueForeground;
public override IColor CyanForeground => _cyanForeground;
public override IColor DarkBlueForeground => _darkBlueForeground;
public override IColor DarkCyanForeground => _darkCyanForeground;
public override IColor DarkGrayForeground => _darkGrayForeground;
public override IColor DarkGreenForeground => _darkGreenForeground;
public override IColor DarkMagentaForeground => _darkMagentaForeground;
public override IColor DarkRedForeground => _darkRedForeground;
public override IColor DarkYellowForeground => _darkYellowForeground;
public override IColor GrayForeground => _grayForeground;
public override IColor GreenForeground => _greenForeground;
public override IColor MagentaForeground => _magentaForeground;
public override IColor RedForeground => _redForeground;
public override IColor WhiteForeground => _whiteForeground;
public override IColor YellowForeground => _yellowForeground;
public override IColor BlackBackground => _blackBackground;
public override IColor BlueBackground => _blueBackground;
public override IColor CyanBackground => _cyanBackground;
public override IColor DarkBlueBackground => _darkBlueBackground;
public override IColor DarkCyanBackground => _darkCyanBackground;
public override IColor DarkGrayBackground => _darkGrayBackground;
public override IColor DarkGreenBackground => _darkGreenBackground;
public override IColor DarkMagentaBackground => _darkMagentaBackground;
public override IColor DarkRedBackground => _darkRedBackground;
public override IColor DarkYellowBackground => _darkYellowBackground;
public override IColor GrayBackground => _grayBackground;
public override IColor GreenBackground => _greenBackground;
public override IColor MagentaBackground => _magentaBackground;
public override IColor RedBackground => _redBackground;
public override IColor WhiteBackground => _whiteBackground;
public override IColor YellowBackground => _yellowBackground;
private static readonly IColor _blackForeground = new ConsoleColor(System.ConsoleColor.Black, ColorType.Foreground);
private static readonly IColor _blueForeground = new ConsoleColor(System.ConsoleColor.Blue, ColorType.Foreground);
private static readonly IColor _cyanForeground = new ConsoleColor(System.ConsoleColor.Cyan, ColorType.Foreground);
private static readonly IColor _darkBlueForeground = new ConsoleColor(System.ConsoleColor.DarkBlue, ColorType.Foreground);
private static readonly IColor _darkCyanForeground = new ConsoleColor(System.ConsoleColor.DarkCyan, ColorType.Foreground);
private static readonly IColor _darkGrayForeground = new ConsoleColor(System.ConsoleColor.DarkGray, ColorType.Foreground);
private static readonly IColor _darkGreenForeground = new ConsoleColor(System.ConsoleColor.DarkGreen, ColorType.Foreground);
private static readonly IColor _darkMagentaForeground = new ConsoleColor(System.ConsoleColor.DarkMagenta, ColorType.Foreground);
private static readonly IColor _darkRedForeground = new ConsoleColor(System.ConsoleColor.DarkRed, ColorType.Foreground);
private static readonly IColor _darkYellowForeground = new ConsoleColor(System.ConsoleColor.DarkYellow, ColorType.Foreground);
private static readonly IColor _grayForeground = new ConsoleColor(System.ConsoleColor.Gray, ColorType.Foreground);
private static readonly IColor _greenForeground = new ConsoleColor(System.ConsoleColor.Green, ColorType.Foreground);
private static readonly IColor _magentaForeground = new ConsoleColor(System.ConsoleColor.Magenta, ColorType.Foreground);
private static readonly IColor _redForeground = new ConsoleColor(System.ConsoleColor.Red, ColorType.Foreground);
private static readonly IColor _whiteForeground = new ConsoleColor(System.ConsoleColor.White, ColorType.Foreground);
private static readonly IColor _yellowForeground = new ConsoleColor(System.ConsoleColor.Yellow, ColorType.Foreground);
private static readonly IColor _blackBackground = new ConsoleColor(System.ConsoleColor.Black, ColorType.Background);
private static readonly IColor _blueBackground = new ConsoleColor(System.ConsoleColor.Blue, ColorType.Background);
private static readonly IColor _cyanBackground = new ConsoleColor(System.ConsoleColor.Cyan, ColorType.Background);
private static readonly IColor _darkBlueBackground = new ConsoleColor(System.ConsoleColor.DarkBlue, ColorType.Background);
private static readonly IColor _darkCyanBackground = new ConsoleColor(System.ConsoleColor.DarkCyan, ColorType.Background);
private static readonly IColor _darkGrayBackground = new ConsoleColor(System.ConsoleColor.DarkGray, ColorType.Background);
private static readonly IColor _darkGreenBackground = new ConsoleColor(System.ConsoleColor.DarkGreen, ColorType.Background);
private static readonly IColor _darkMagentaBackground = new ConsoleColor(System.ConsoleColor.DarkMagenta, ColorType.Background);
private static readonly IColor _darkRedBackground = new ConsoleColor(System.ConsoleColor.DarkRed, ColorType.Background);
private static readonly IColor _darkYellowBackground = new ConsoleColor(System.ConsoleColor.DarkYellow, ColorType.Background);
private static readonly IColor _grayBackground = new ConsoleColor(System.ConsoleColor.Gray, ColorType.Background);
private static readonly IColor _greenBackground = new ConsoleColor(System.ConsoleColor.Green, ColorType.Background);
private static readonly IColor _magentaBackground = new ConsoleColor(System.ConsoleColor.Magenta, ColorType.Background);
private static readonly IColor _redBackground = new ConsoleColor(System.ConsoleColor.Red, ColorType.Background);
private static readonly IColor _whiteBackground = new ConsoleColor(System.ConsoleColor.White, ColorType.Background);
private static readonly IColor _yellowBackground = new ConsoleColor(System.ConsoleColor.Yellow, ColorType.Background);
}

View File

@@ -3,6 +3,7 @@
public interface IColorProvider
{
IColor Parse(string color, ColorType type);
IColor FromRgb(Rgb rgb, ColorType type);
IColor BlackForeground { get; }
IColor BlueForeground { get; }

View File

@@ -0,0 +1,33 @@
using System.Diagnostics;
namespace TerminalUI.Color;
[DebuggerDisplay("R = {R}, G = {G}, B = {B}")]
public readonly struct Rgb
{
public readonly byte R;
public readonly byte G;
public readonly byte B;
public Rgb(byte r, byte g, byte b)
{
R = r;
G = g;
B = b;
}
public static double operator -(Rgb left, Rgb right)
{
var r = Math.Abs(left.R - right.R);
var g = Math.Abs(left.G - right.G);
var b = Math.Abs(left.B - right.B);
return (double)(r + g + b) / 3;
}
public void Deconstruct(out byte r, out byte g, out byte b)
{
r = R;
g = G;
b = B;
}
}

View File

@@ -36,6 +36,7 @@ public sealed class XTermDriver : DotnetDriver
public override void ResetStyle()
{
Write("\x1b[0m");
base.ResetStyle();
}
public override void SetBackgroundColor(IColor background)

View File

@@ -127,11 +127,18 @@ public sealed class Grid<T> : ChildCollectionView<Grid<T>, T>, IVisibilityChange
protected override Size CalculateSize()
{
return WithCalculatedSize(
if (Width.HasValue && Height.HasValue)
{
return new Size(Width.Value, Height.Value);
}
var size = WithCalculatedSize(
RenderContext.Empty,
new Option<Size>(new Size(0, 0), false),
CalculateSizeInternal);
return new Size(Width ?? size.Width, Height ?? size.Height);
Size CalculateSizeInternal(in RenderContext _, ReadOnlySpan<int> columnWidths, ReadOnlySpan<int> rowHeights)
{
var width = 0;
@@ -153,11 +160,14 @@ public sealed class Grid<T> : ChildCollectionView<Grid<T>, T>, IVisibilityChange
protected override bool DefaultRenderer(in RenderContext renderContext, Position position, Size size)
{
if (size.Width == 0 || size.Height == 0) return false;
var width = Width ?? size.Width;
var height = Height ?? size.Height;
if (width == 0 || height == 0) return false;
return WithCalculatedSize(
renderContext,
new Option<Size>(size, true),
new Option<Size>(new Size(width, height), true),
DefaultRendererInternal
);

View File

@@ -26,7 +26,8 @@ public sealed partial class Rectangle<T> : View<Rectangle<T>, T>, IDisplayView
protected override bool DefaultRenderer(in RenderContext renderContext, Position position, Size size)
{
var fillColor = Fill ?? Background ?? renderContext.Background;
var renderState = new RenderState(position, size, fillColor);
var renderSize = new Size(Width ?? size.Width, Height ?? size.Height);
var renderState = new RenderState(position, renderSize, fillColor);
var skipRender = !renderContext.ForceRerender && !NeedsRerender(renderState);
_lastRenderState = renderState;
@@ -41,7 +42,7 @@ public sealed partial class Rectangle<T> : View<Rectangle<T>, T>, IDisplayView
RenderEmpty(
renderContext,
position,
size,
renderSize,
skipRender,
false
);

View File

@@ -146,8 +146,8 @@ public abstract partial class View<TConcrete, T> : IView<T> where TConcrete : Vi
if (!IsVisible) return false;
ActualWidth = size.Width;
ActualHeight = size.Height;
ActualWidth = Width ?? size.Width;
ActualHeight = Height ?? size.Height;
if (RenderMethod is null)
{
@@ -167,10 +167,14 @@ public abstract partial class View<TConcrete, T> : IView<T> where TConcrete : Vi
);
size = new Size(
size.Width - Margin.Left - Margin.Right,
size.Height - Margin.Top - Margin.Bottom
ActualWidth - Margin.Left - Margin.Right,
ActualHeight - Margin.Top - Margin.Bottom
);
}
else if (Width.HasValue || Height.HasValue)
{
size = new Size(ActualWidth, ActualHeight);
}
bool renderResult;
if (Background != null || Foreground != null)

View File

@@ -31,6 +31,8 @@ public class BinaryTracker : ExpressionTrackerBase
ExpressionType.GreaterThanOrEqual => (v1, v2) => Comparer.Default.Compare(v1, v2) >= 0,
ExpressionType.LessThan => (v1, v2) => Comparer.Default.Compare(v1, v2) < 0,
ExpressionType.LessThanOrEqual => (v1, v2) => Comparer.Default.Compare(v1, v2) <= 0,
ExpressionType.AndAlso => (v1, v2) => v1 is true && v2 is true,
ExpressionType.OrElse => (v1, v2) => v1 is true || v2 is true,
_ => throw new NotImplementedException()
};

View File

@@ -0,0 +1,26 @@
using System.Linq.Expressions;
namespace TerminalUI.ExpressionTrackers;
public class TypeBinaryTracker : ExpressionTrackerBase
{
private readonly IExpressionTracker _childExpressionTracker;
private readonly Func<object?, bool> _computer;
public TypeBinaryTracker(TypeBinaryExpression typeBinaryExpression, IExpressionTracker childExpressionTracker)
{
_childExpressionTracker = childExpressionTracker;
ArgumentNullException.ThrowIfNull(childExpressionTracker);
SubscribeToValueChanges = false;
SubscribeToTracker(childExpressionTracker);
_computer = typeBinaryExpression.NodeType switch
{
ExpressionType.TypeIs => o => o is not null && typeBinaryExpression.TypeOperand.IsInstanceOfType(o),
_ => throw new NotImplementedException()
};
}
protected override object? ComputeValue()
=> _computer(_childExpressionTracker.GetValue());
}

View File

@@ -80,10 +80,11 @@ public abstract class PropertyTrackerBase<TSource, TExpressionResult>
{
return new ConstantTracker(constantExpression.Value);
}
/*else if (expression is not ConstantExpression)
else if (expression is TypeBinaryExpression typeBinaryExpression)
{
Debug.Assert(false, "Unknown expression type " + expression.GetType());
}*/
var childExpression = FindReactiveProperties(typeBinaryExpression.Expression, parameters);
return new TypeBinaryTracker(typeBinaryExpression, childExpression);
}
throw new NotSupportedException();
}

View File

@@ -4,7 +4,6 @@ using DynamicData;
using FileTime.Core.ContentAccess;
using FileTime.Core.Enums;
using FileTime.Core.Models;
using FileTime.Core.Models.Extensions;
using FileTime.Core.Timeline;
using Microsoft.Extensions.DependencyInjection;
@@ -356,11 +355,6 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
var parent = new AbsolutePath(_timelessContentProvider, pointInTime, parentFullName,
AbsolutePathType.Container);
var extensions = new ExtensionCollection()
{
new FileExtension(fileInfo.Length)
};
return new Element(
fileInfo.Name,
fileInfo.Name,
@@ -374,10 +368,11 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
SupportsDelete.True,
true,
GetFileAttributes(fileInfo),
fileInfo.Length,
this,
pointInTime,
new ObservableCollection<Exception>(),
extensions.AsReadOnly()
new ExtensionCollection().AsReadOnly()
);
}