RootDrives WIP
This commit is contained in:
@@ -7,11 +7,15 @@ namespace FileTime.App.Core.Models;
|
|||||||
|
|
||||||
public partial class BindedCollection<T> : IDisposable, INotifyPropertyChanged
|
public partial class BindedCollection<T> : IDisposable, INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
private readonly IDisposable _disposable;
|
private readonly IDisposable? _disposable;
|
||||||
private IDisposable? _innerDisposable;
|
private IDisposable? _innerDisposable;
|
||||||
|
|
||||||
[Notify] private ReadOnlyObservableCollection<T>? _collection;
|
[Notify] private ReadOnlyObservableCollection<T>? _collection;
|
||||||
|
|
||||||
|
public BindedCollection()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public BindedCollection(IObservable<IChangeSet<T>> dynamicList)
|
public BindedCollection(IObservable<IChangeSet<T>> dynamicList)
|
||||||
{
|
{
|
||||||
_disposable = dynamicList
|
_disposable = dynamicList
|
||||||
@@ -45,7 +49,7 @@ public partial class BindedCollection<T> : IDisposable, INotifyPropertyChanged
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_disposable.Dispose();
|
_disposable?.Dispose();
|
||||||
_innerDisposable?.Dispose();
|
_innerDisposable?.Dispose();
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace FileTime.App.Core.Services;
|
||||||
|
|
||||||
|
public interface IExitHandler
|
||||||
|
{
|
||||||
|
Task ExitAsync();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
namespace FileTime.App.Core.Services;
|
||||||
|
|
||||||
|
public interface IStartupHandler
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -19,4 +19,5 @@ public interface IContentProvider : IContainer, IOnContainerEnter
|
|||||||
ItemInitializationSettings itemInitializationSettings = default);
|
ItemInitializationSettings itemInitializationSettings = default);
|
||||||
|
|
||||||
Task<List<IAbsolutePath>> GetItemsByContainerAsync(FullName fullName);
|
Task<List<IAbsolutePath>> GetItemsByContainerAsync(FullName fullName);
|
||||||
|
NativePath GetNativePath(FullName fullName);
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ namespace FileTime.Core.Services;
|
|||||||
|
|
||||||
public abstract class ContentProviderBase : IContentProvider
|
public abstract class ContentProviderBase : IContentProvider
|
||||||
{
|
{
|
||||||
protected BehaviorSubject<IObservable<IChangeSet<IAbsolutePath>>?> Items { get; } = new (null);
|
protected BehaviorSubject<IObservable<IChangeSet<IAbsolutePath>>?> Items { get; } = new(null);
|
||||||
|
|
||||||
IObservable<IObservable<IChangeSet<IAbsolutePath>>?> IContainer.Items => Items;
|
IObservable<IObservable<IChangeSet<IAbsolutePath>>?> IContainer.Items => Items;
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ public abstract class ContentProviderBase : IContentProvider
|
|||||||
|
|
||||||
public string DisplayName { get; }
|
public string DisplayName { get; }
|
||||||
|
|
||||||
public FullName? FullName => null;
|
public FullName? FullName { get; }
|
||||||
|
|
||||||
public NativePath? NativePath => null;
|
public NativePath? NativePath => null;
|
||||||
|
|
||||||
@@ -47,20 +47,24 @@ public abstract class ContentProviderBase : IContentProvider
|
|||||||
protected ContentProviderBase(string name)
|
protected ContentProviderBase(string name)
|
||||||
{
|
{
|
||||||
DisplayName = Name = name;
|
DisplayName = Name = name;
|
||||||
|
FullName = new FullName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task OnEnter() => Task.CompletedTask;
|
public virtual Task OnEnter() => Task.CompletedTask;
|
||||||
|
|
||||||
public virtual async Task<IItem> GetItemByFullNameAsync(
|
public virtual async Task<IItem> GetItemByFullNameAsync(
|
||||||
FullName fullName,
|
FullName fullName,
|
||||||
bool forceResolve = false,
|
bool forceResolve = false,
|
||||||
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
||||||
ItemInitializationSettings itemInitializationSettings = default)
|
ItemInitializationSettings itemInitializationSettings = default)
|
||||||
=> await GetItemByNativePathAsync(GetNativePath(fullName), forceResolve, forceResolvePathType, itemInitializationSettings);
|
=> await GetItemByNativePathAsync(GetNativePath(fullName), forceResolve, forceResolvePathType, itemInitializationSettings);
|
||||||
|
|
||||||
public abstract Task<IItem> GetItemByNativePathAsync(
|
public abstract Task<IItem> GetItemByNativePathAsync(
|
||||||
NativePath nativePath,
|
NativePath nativePath,
|
||||||
bool forceResolve = false,
|
bool forceResolve = false,
|
||||||
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
||||||
ItemInitializationSettings itemInitializationSettings = default);
|
ItemInitializationSettings itemInitializationSettings = default);
|
||||||
|
|
||||||
public abstract Task<List<IAbsolutePath>> GetItemsByContainerAsync(FullName fullName);
|
public abstract Task<List<IAbsolutePath>> GetItemsByContainerAsync(FullName fullName);
|
||||||
public abstract NativePath GetNativePath(FullName fullName);
|
public abstract NativePath GetNativePath(FullName fullName);
|
||||||
}
|
}
|
||||||
@@ -13,10 +13,15 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="0.10.14" />
|
<PackageReference Include="Avalonia" Version="0.10.14" />
|
||||||
|
<PackageReference Include="PropertyChanged.SourceGenerator" Version="1.0.3">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
|
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\Core\FileTime.Core.Models\FileTime.Core.Models.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using FileTime.Core.Models;
|
||||||
|
|
||||||
|
namespace FileTime.GuiApp.Models;
|
||||||
|
|
||||||
|
public interface IHaveAbsolutePath
|
||||||
|
{
|
||||||
|
IAbsolutePath Path { get; }
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using FileTime.App.Core.Models;
|
||||||
using FileTime.App.Core.ViewModels;
|
using FileTime.App.Core.ViewModels;
|
||||||
using FileTime.GuiApp.Configuration;
|
using FileTime.GuiApp.Configuration;
|
||||||
|
|
||||||
@@ -10,4 +12,5 @@ public interface IGuiAppState : IAppState
|
|||||||
bool NoCommandFound { get; set; }
|
bool NoCommandFound { get; set; }
|
||||||
string? MessageBoxText { get; set; }
|
string? MessageBoxText { get; set; }
|
||||||
List<CommandBindingConfiguration> PossibleCommands { get; set; }
|
List<CommandBindingConfiguration> PossibleCommands { get; set; }
|
||||||
|
BindedCollection<RootDriveInfo> RootDriveInfos { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
using FileTime.GuiApp.Models;
|
||||||
|
using PropertyChanged.SourceGenerator;
|
||||||
|
using IContainer = FileTime.Core.Models.IContainer;
|
||||||
|
|
||||||
|
namespace FileTime.GuiApp.ViewModels;
|
||||||
|
|
||||||
|
public partial class RootDriveInfo : IHaveAbsolutePath, INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
private readonly DriveInfo _driveInfo;
|
||||||
|
|
||||||
|
[Notify] private string _name;
|
||||||
|
|
||||||
|
[Notify] private string _fullName;
|
||||||
|
|
||||||
|
[Notify] private string? _label;
|
||||||
|
|
||||||
|
[Notify] private long _size = 0;
|
||||||
|
|
||||||
|
[Notify] private long _free = 0;
|
||||||
|
|
||||||
|
[Notify] private long _used = 0;
|
||||||
|
|
||||||
|
[Notify] public long UsedPercentage => Size == 0 ? 0 : Used * 100 / Size;
|
||||||
|
|
||||||
|
public IAbsolutePath Path { get; }
|
||||||
|
|
||||||
|
public RootDriveInfo(DriveInfo driveInfo, IContainer container)
|
||||||
|
{
|
||||||
|
_driveInfo = driveInfo;
|
||||||
|
|
||||||
|
_name = container.Name;
|
||||||
|
|
||||||
|
_fullName = _name;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_fullName = container.FullName?.Path[(container.Provider.FullName!.Path.Length + 1)..] ?? _fullName;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Path = new AbsolutePath(container);
|
||||||
|
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Refresh()
|
||||||
|
{
|
||||||
|
Label = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? _driveInfo.VolumeLabel : null;
|
||||||
|
Size = _driveInfo.TotalSize;
|
||||||
|
Free = _driveInfo.AvailableFreeSpace;
|
||||||
|
Used = _driveInfo.TotalSize - _driveInfo.AvailableFreeSpace;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,8 @@ public static class Startup
|
|||||||
.AddSingleton<IDefaultModeKeyInputHandler, DefaultModeKeyInputHandler>()
|
.AddSingleton<IDefaultModeKeyInputHandler, DefaultModeKeyInputHandler>()
|
||||||
.AddSingleton<IKeyboardConfigurationService, KeyboardConfigurationService>()
|
.AddSingleton<IKeyboardConfigurationService, KeyboardConfigurationService>()
|
||||||
.AddSingleton<IRapidTravelModeKeyInputHandler, RapidTravelModeKeyInputHandler>()
|
.AddSingleton<IRapidTravelModeKeyInputHandler, RapidTravelModeKeyInputHandler>()
|
||||||
|
.AddSingleton<IStartupHandler, RootDriveInfoService>()
|
||||||
|
.AddSingleton<LifecycleService>()
|
||||||
.AddSingleton<IModalService, ModalService>();
|
.AddSingleton<IModalService, ModalService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using FileTime.App.Core.Models;
|
||||||
using FileTime.App.Core.ViewModels;
|
using FileTime.App.Core.ViewModels;
|
||||||
using FileTime.GuiApp.Configuration;
|
using FileTime.GuiApp.Configuration;
|
||||||
using MvvmGen;
|
using MvvmGen;
|
||||||
@@ -7,17 +9,15 @@ namespace FileTime.GuiApp.ViewModels;
|
|||||||
[ViewModel]
|
[ViewModel]
|
||||||
public partial class GuiAppState : AppStateBase, IGuiAppState
|
public partial class GuiAppState : AppStateBase, IGuiAppState
|
||||||
{
|
{
|
||||||
[Property]
|
[Property] private bool _isAllShortcutVisible;
|
||||||
private bool _isAllShortcutVisible;
|
|
||||||
|
|
||||||
[Property]
|
[Property] private bool _noCommandFound;
|
||||||
private bool _noCommandFound;
|
|
||||||
|
|
||||||
[Property]
|
[Property] private string? _messageBoxText;
|
||||||
private string? _messageBoxText;
|
|
||||||
|
|
||||||
[Property]
|
[Property] private List<CommandBindingConfiguration> _possibleCommands = new();
|
||||||
private List<CommandBindingConfiguration> _possibleCommands = new();
|
|
||||||
|
[Property] private BindedCollection<RootDriveInfo> _rootDriveInfos = new();
|
||||||
|
|
||||||
public List<KeyConfig> PreviousKeys { get; } = new();
|
public List<KeyConfig> PreviousKeys { get; } = new();
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using FileTime.App.Core.Services;
|
||||||
|
|
||||||
|
namespace FileTime.GuiApp.Services;
|
||||||
|
|
||||||
|
public class LifecycleService
|
||||||
|
{
|
||||||
|
private readonly IEnumerable<IExitHandler> _exitHandlers;
|
||||||
|
|
||||||
|
public LifecycleService(IEnumerable<IStartupHandler> startupHandlers, IEnumerable<IExitHandler> exitHandlers)
|
||||||
|
{
|
||||||
|
_exitHandlers = exitHandlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Exit()
|
||||||
|
{
|
||||||
|
foreach (var exitHandler in _exitHandlers)
|
||||||
|
{
|
||||||
|
await exitHandler.ExitAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
using System.Reactive.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using DynamicData;
|
||||||
|
using FileTime.App.Core.Models;
|
||||||
|
using FileTime.App.Core.Services;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
using FileTime.GuiApp.ViewModels;
|
||||||
|
using FileTime.Providers.Local;
|
||||||
|
using IContainer = FileTime.Core.Models.IContainer;
|
||||||
|
|
||||||
|
namespace FileTime.GuiApp.Services;
|
||||||
|
|
||||||
|
public class RootDriveInfoService : IStartupHandler
|
||||||
|
{
|
||||||
|
private readonly SourceList<DriveInfo> _rootDrives = new();
|
||||||
|
|
||||||
|
public RootDriveInfoService(IGuiAppState guiAppState, ILocalContentProvider localContentProvider)
|
||||||
|
{
|
||||||
|
InitRootDrives();
|
||||||
|
|
||||||
|
var rootDriveInfos = Observable.CombineLatest(
|
||||||
|
localContentProvider.Items,
|
||||||
|
_rootDrives.Connect().StartWithEmpty().ToCollection(),
|
||||||
|
(items, drives) =>
|
||||||
|
{
|
||||||
|
return items is null
|
||||||
|
? Observable.Empty<IChangeSet<(IAbsolutePath Path, DriveInfo? Drive)>>()
|
||||||
|
: items
|
||||||
|
.Transform(i => (Path: i, Drive: drives.FirstOrDefault(d =>
|
||||||
|
{
|
||||||
|
var asd1 = localContentProvider.GetNativePath(i.Path).Path;
|
||||||
|
var asd2 = d.Name.TrimEnd(Path.DirectorySeparatorChar);
|
||||||
|
return asd1 == asd2;
|
||||||
|
})))
|
||||||
|
.Filter(t => t.Drive is not null);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.Switch()
|
||||||
|
.TransformAsync(async t => (Item: await t.Path.ResolveAsyncSafe(), Drive: t.Drive!))
|
||||||
|
.Filter(t => t.Item is IContainer)
|
||||||
|
.Transform(t => (Container: (IContainer)t.Item!, t.Drive))
|
||||||
|
.Transform(t => new RootDriveInfo(t.Drive, t.Container));
|
||||||
|
|
||||||
|
guiAppState.RootDriveInfos = new BindedCollection<RootDriveInfo>(rootDriveInfos);
|
||||||
|
|
||||||
|
void InitRootDrives()
|
||||||
|
{
|
||||||
|
var driveInfos = new List<RootDriveInfo>();
|
||||||
|
IEnumerable<DriveInfo> drives = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
|
? DriveInfo.GetDrives().Where(d => d.DriveType == DriveType.Fixed)
|
||||||
|
: DriveInfo.GetDrives().Where(d =>
|
||||||
|
d.DriveType == DriveType.Fixed
|
||||||
|
&& d.DriveFormat != "pstorefs"
|
||||||
|
&& d.DriveFormat != "bpf_fs"
|
||||||
|
&& d.DriveFormat != "tracefs"
|
||||||
|
&& !d.RootDirectory.FullName.StartsWith("/snap/"));
|
||||||
|
|
||||||
|
_rootDrives.AddRange(drives);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using FileTime.App.Core;
|
using FileTime.App.Core;
|
||||||
|
using FileTime.App.Core.Services;
|
||||||
using FileTime.App.Core.ViewModels;
|
using FileTime.App.Core.ViewModels;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
using FileTime.Core.Services;
|
using FileTime.Core.Services;
|
||||||
@@ -19,6 +20,8 @@ namespace FileTime.GuiApp.ViewModels;
|
|||||||
[Inject(typeof(IServiceProvider), PropertyName = "_serviceProvider")]
|
[Inject(typeof(IServiceProvider), PropertyName = "_serviceProvider")]
|
||||||
[Inject(typeof(ILogger<MainWindowViewModel>), PropertyName = "_logger")]
|
[Inject(typeof(ILogger<MainWindowViewModel>), PropertyName = "_logger")]
|
||||||
[Inject(typeof(IKeyInputHandlerService), PropertyName = "_keyInputHandlerService")]
|
[Inject(typeof(IKeyInputHandlerService), PropertyName = "_keyInputHandlerService")]
|
||||||
|
[Inject(typeof(ICommandHandlerService), PropertyAccessModifier = AccessModifier.Public)]
|
||||||
|
[Inject(typeof(LifecycleService), PropertyName = "_lifecycleService")]
|
||||||
public partial class MainWindowViewModel : IMainWindowViewModelBase
|
public partial class MainWindowViewModel : IMainWindowViewModelBase
|
||||||
{
|
{
|
||||||
public bool Loading => false;
|
public bool Loading => false;
|
||||||
|
|||||||
@@ -26,11 +26,12 @@
|
|||||||
|
|
||||||
<Grid Background="{DynamicResource AppBackgroundBrush}">
|
<Grid Background="{DynamicResource AppBackgroundBrush}">
|
||||||
<Grid
|
<Grid
|
||||||
x:DataType="vm:MainWindowViewModel"
|
x:DataType="vm:MainWindowViewModel">
|
||||||
IsVisible="{Binding Loading, Converter={x:Static BoolConverters.Not}}">
|
|
||||||
<Grid
|
<Grid
|
||||||
ColumnDefinitions="250,*"
|
ColumnDefinitions="250,*"
|
||||||
RowDefinitions="Auto,*">
|
RowDefinitions="Auto,*"
|
||||||
|
IsVisible="{Binding Loading, Converter={x:Static BoolConverters.Not}}">
|
||||||
|
|
||||||
<Grid PointerPressed="HeaderPointerPressed">
|
<Grid PointerPressed="HeaderPointerPressed">
|
||||||
<Rectangle Fill="#01000000" />
|
<Rectangle Fill="#01000000" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
@@ -53,6 +54,179 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
<Grid Grid.Row="1" RowDefinitions="Auto,Auto,Auto,Auto">
|
||||||
|
|
||||||
|
<Border CornerRadius="10" Background="{DynamicResource ContainerBackgroundBrush}" Padding="10" Margin="10">
|
||||||
|
<Grid RowDefinitions="Auto,Auto">
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Margin="0,0,0,10"
|
||||||
|
Text="Drives" />
|
||||||
|
|
||||||
|
<ItemsRepeater
|
||||||
|
Grid.Row="1"
|
||||||
|
Items="{Binding AppState.RootDriveInfos.Collection}">
|
||||||
|
<ItemsRepeater.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="vm:RootDriveInfo">
|
||||||
|
<Grid Classes="SidebarContainerPresenter" PointerPressed="OnHasContainerPointerPressed" Cursor="Hand">
|
||||||
|
<Grid Margin="0,5" ColumnDefinitions="Auto,*,Auto" RowDefinitions="Auto,Auto">
|
||||||
|
<Image
|
||||||
|
Grid.RowSpan="2"
|
||||||
|
Width="20"
|
||||||
|
Height="20"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Source="{SvgImage /Assets/material/folder.svg}" />
|
||||||
|
|
||||||
|
<StackPanel
|
||||||
|
Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Orientation="Horizontal">
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0,0,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{Binding FullName}" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0,0,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Classes="ExtraSmallText"
|
||||||
|
Text="{Binding Label}" IsVisible="{Binding Label,Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Grid.Column="2"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
|
||||||
|
<TextBlock Classes="SmallText" VerticalAlignment="Center" Text="{Binding Free, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}">
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
|
<TextBlock Classes="SmallText" VerticalAlignment="Center" Text=" / ">
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
|
<TextBlock Classes="SmallText" VerticalAlignment="Center" Text="{Binding Size, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}">
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
Margin="5,0,0,0"
|
||||||
|
Grid.Column="1"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
Grid.Row="1"
|
||||||
|
MinWidth="100"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Maximum="100"
|
||||||
|
Value="{Binding UsedPercentage}" />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsRepeater.ItemTemplate>
|
||||||
|
</ItemsRepeater>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!--Border Grid.Row="1" CornerRadius="10" Background="{DynamicResource ContainerBackgroundBrush}" Padding="0,10" Margin="10">
|
||||||
|
<Grid RowDefinitions="Auto,Auto">
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Margin="10,0,10,10"
|
||||||
|
Text="Places" />
|
||||||
|
|
||||||
|
<ItemsRepeater
|
||||||
|
Grid.Row="1"
|
||||||
|
Items="{Binding Places}">
|
||||||
|
<ItemsRepeater.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Classes="SidebarContainerPresenter" PointerPressed="OnHasContainerPointerPressed" Cursor="Hand">
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="10,5" HorizontalAlignment="Stretch">
|
||||||
|
<Image
|
||||||
|
Width="20"
|
||||||
|
Height="20"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Source="{Binding Container,Converter={StaticResource ItemToImageConverter}}" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0,0,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{Binding Name}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsRepeater.ItemTemplate>
|
||||||
|
</ItemsRepeater>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Border Grid.Row="2" CornerRadius="10" Background="{DynamicResource ContainerBackgroundBrush}" Padding="0,10" Margin="10">
|
||||||
|
<Grid RowDefinitions="Auto,Auto">
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Margin="10,0,10,10"
|
||||||
|
Text="Favorites" />
|
||||||
|
|
||||||
|
<ItemsRepeater
|
||||||
|
Grid.Row="1"
|
||||||
|
Items="{Binding AppState.FavoriteElements}">
|
||||||
|
<ItemsRepeater.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Classes="SidebarContainerPresenter" PointerPressed="OnHasContainerPointerPressed" Cursor="Hand">
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="10,5" HorizontalAlignment="Stretch">
|
||||||
|
<Image
|
||||||
|
Width="20"
|
||||||
|
Height="20"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Source="{Binding Converter={StaticResource ItemToImageConverter}}" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0,0,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{Binding Name}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsRepeater.ItemTemplate>
|
||||||
|
</ItemsRepeater>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Border Grid.Row="3" CornerRadius="10" Background="{DynamicResource ContainerBackgroundBrush}" Padding="0,10" Margin="10">
|
||||||
|
<Grid RowDefinitions="Auto,Auto">
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Margin="10,0,10,10"
|
||||||
|
Text="History" />
|
||||||
|
|
||||||
|
<ItemsRepeater
|
||||||
|
Grid.Row="1"
|
||||||
|
Items="{Binding AppState.SelectedTab.History}">
|
||||||
|
<ItemsRepeater.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Classes="SidebarContainerPresenter" PointerPressed="OnHasContainerPointerPressed" Cursor="Hand">
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="10,5" HorizontalAlignment="Stretch">
|
||||||
|
<Image
|
||||||
|
Width="20"
|
||||||
|
Height="20"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Source="{Binding Container,Converter={StaticResource ItemToImageConverter}}" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Margin="5,0,0,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{Binding Name}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsRepeater.ItemTemplate>
|
||||||
|
</ItemsRepeater>
|
||||||
|
</Grid>
|
||||||
|
</Border-->
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.Threading;
|
||||||
|
using FileTime.Core.Models;
|
||||||
using FileTime.GuiApp.Models;
|
using FileTime.GuiApp.Models;
|
||||||
using FileTime.GuiApp.ViewModels;
|
using FileTime.GuiApp.ViewModels;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -68,4 +71,41 @@ public partial class MainWindow : Window
|
|||||||
BeginMoveDrag(e);
|
BeginMoveDrag(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void OnHasContainerPointerPressed(object sender, PointerPressedEventArgs e)
|
||||||
|
{
|
||||||
|
if (!e.Handled
|
||||||
|
&& ViewModel != null
|
||||||
|
&& e.GetCurrentPoint(this).Properties.IsLeftButtonPressed
|
||||||
|
&& sender is StyledElement control)
|
||||||
|
{
|
||||||
|
IAbsolutePath? path = null;
|
||||||
|
if (control.DataContext is IHaveAbsolutePath {Path: { }} haveAbsolutePath)
|
||||||
|
{
|
||||||
|
path = haveAbsolutePath.Path;
|
||||||
|
}
|
||||||
|
else if (control.DataContext is IAbsolutePath p)
|
||||||
|
{
|
||||||
|
path = p;
|
||||||
|
}
|
||||||
|
/*else if (control.DataContext is IElement element && element.GetParent() is IContainer parentContainer)
|
||||||
|
{
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
await ViewModel.AppState.SelectedTab.OpenContainer(parentContainer);
|
||||||
|
await ViewModel.AppState.SelectedTab.SetCurrentSelectedItem(element);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (path is null) return;
|
||||||
|
|
||||||
|
var resolvedItem = await path.ResolveAsync();
|
||||||
|
if (resolvedItem is not IContainer resolvedContainer) return;
|
||||||
|
//ViewModel.CommandHandlerService.HandleCommandAsync()
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user