Places (Windows only currently)
This commit is contained in:
@@ -12,4 +12,5 @@ public interface IGuiAppState : IAppState
|
|||||||
string? MessageBoxText { get; set; }
|
string? MessageBoxText { get; set; }
|
||||||
List<CommandBindingConfiguration> PossibleCommands { get; set; }
|
List<CommandBindingConfiguration> PossibleCommands { get; set; }
|
||||||
BindedCollection<RootDriveInfo, string> RootDriveInfos { get; set; }
|
BindedCollection<RootDriveInfo, string> RootDriveInfos { get; set; }
|
||||||
|
IReadOnlyList<PlaceInfo> Places { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using FileTime.Core.Models;
|
||||||
|
using FileTime.GuiApp.Models;
|
||||||
|
|
||||||
|
namespace FileTime.GuiApp.ViewModels;
|
||||||
|
|
||||||
|
public class PlaceInfo : IHaveFullPath
|
||||||
|
{
|
||||||
|
public IContainer Container { get; }
|
||||||
|
public string DisplayName { get; }
|
||||||
|
|
||||||
|
public PlaceInfo(IContainer container, string displayName)
|
||||||
|
{
|
||||||
|
if (container.FullName is null) throw new ArgumentNullException($"{nameof(container.FullName)} of container can not be null");
|
||||||
|
|
||||||
|
Container = container;
|
||||||
|
DisplayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FullName Path => Container.FullName!;
|
||||||
|
}
|
||||||
@@ -43,7 +43,8 @@ public static class Startup
|
|||||||
serviceCollection.TryAddSingleton<IInputInterface>(s => s.GetRequiredService<IDialogService>());
|
serviceCollection.TryAddSingleton<IInputInterface>(s => s.GetRequiredService<IDialogService>());
|
||||||
|
|
||||||
return serviceCollection
|
return serviceCollection
|
||||||
.AddSingleton<IStartupHandler, RootDriveInfoService>();
|
.AddSingleton<IStartupHandler, RootDriveInfoService>()
|
||||||
|
.AddSingleton<IStartupHandler, PlacesService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static IServiceCollection RegisterLogging(this IServiceCollection serviceCollection)
|
internal static IServiceCollection RegisterLogging(this IServiceCollection serviceCollection)
|
||||||
|
|||||||
@@ -19,5 +19,7 @@ public partial class GuiAppState : AppStateBase, IGuiAppState
|
|||||||
|
|
||||||
[Property] private BindedCollection<RootDriveInfo, string> _rootDriveInfos = new();
|
[Property] private BindedCollection<RootDriveInfo, string> _rootDriveInfos = new();
|
||||||
|
|
||||||
|
[Property] private IReadOnlyList<PlaceInfo> _places;
|
||||||
|
|
||||||
public List<KeyConfig> PreviousKeys { get; } = new();
|
public List<KeyConfig> PreviousKeys { get; } = new();
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using FileTime.App.Core.Services;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
using FileTime.Core.Timeline;
|
||||||
|
using FileTime.GuiApp.ViewModels;
|
||||||
|
using FileTime.Providers.Local;
|
||||||
|
using Syroot.Windows.IO;
|
||||||
|
|
||||||
|
namespace FileTime.GuiApp.Services;
|
||||||
|
|
||||||
|
public class PlacesService : IStartupHandler
|
||||||
|
{
|
||||||
|
private readonly ILocalContentProvider _localContentProvider;
|
||||||
|
private readonly IGuiAppState _guiAppState;
|
||||||
|
|
||||||
|
public PlacesService(
|
||||||
|
ILocalContentProvider localContentProvider,
|
||||||
|
IGuiAppState guiAppState)
|
||||||
|
{
|
||||||
|
_localContentProvider = localContentProvider;
|
||||||
|
_guiAppState = guiAppState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InitAsync()
|
||||||
|
{
|
||||||
|
var places = new List<PlaceInfo>();
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
var placesFolders = new List<KnownFolder>()
|
||||||
|
{
|
||||||
|
KnownFolders.Profile,
|
||||||
|
KnownFolders.Desktop,
|
||||||
|
KnownFolders.DocumentsLocalized,
|
||||||
|
KnownFolders.DownloadsLocalized,
|
||||||
|
KnownFolders.Music,
|
||||||
|
KnownFolders.Pictures,
|
||||||
|
KnownFolders.Videos,
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var placesFolder in placesFolders)
|
||||||
|
{
|
||||||
|
var possibleContainer = await _localContentProvider.GetItemByNativePathAsync(new NativePath(placesFolder.Path), PointInTime.Present);
|
||||||
|
if (possibleContainer is not IContainer container) continue;
|
||||||
|
|
||||||
|
|
||||||
|
places.Add(new PlaceInfo(container, placesFolder.DisplayName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_guiAppState.Places = places.AsReadOnly();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,23 +8,23 @@ using FileTime.Core.Models;
|
|||||||
using FileTime.Core.Timeline;
|
using FileTime.Core.Timeline;
|
||||||
using FileTime.GuiApp.ViewModels;
|
using FileTime.GuiApp.ViewModels;
|
||||||
using FileTime.Providers.Local;
|
using FileTime.Providers.Local;
|
||||||
using IContainer = FileTime.Core.Models.IContainer;
|
|
||||||
|
|
||||||
namespace FileTime.GuiApp.Services;
|
namespace FileTime.GuiApp.Services;
|
||||||
|
|
||||||
public class RootDriveInfoService : IStartupHandler
|
public class RootDriveInfoService : IStartupHandler
|
||||||
{
|
{
|
||||||
private readonly SourceList<DriveInfo> _rootDrives = new();
|
private readonly SourceList<DriveInfo> _rootDrives = new();
|
||||||
private readonly IObservable<IChangeSet<AbsolutePath, string>> _localContentProviderStream;
|
|
||||||
|
|
||||||
public RootDriveInfoService(IGuiAppState guiAppState, ILocalContentProvider localContentProvider,
|
public RootDriveInfoService(
|
||||||
|
IGuiAppState guiAppState,
|
||||||
|
ILocalContentProvider localContentProvider,
|
||||||
ITimelessContentProvider timelessContentProvider)
|
ITimelessContentProvider timelessContentProvider)
|
||||||
{
|
{
|
||||||
InitRootDrives();
|
InitRootDrives();
|
||||||
|
|
||||||
var localContentProviderAsList = new SourceCache<AbsolutePath, string>(i => i.Path.Path);
|
var localContentProviderAsList = new SourceCache<AbsolutePath, string>(i => i.Path.Path);
|
||||||
localContentProviderAsList.AddOrUpdate(new AbsolutePath(timelessContentProvider, localContentProvider));
|
localContentProviderAsList.AddOrUpdate(new AbsolutePath(timelessContentProvider, localContentProvider));
|
||||||
_localContentProviderStream = localContentProviderAsList.Connect();
|
var localContentProviderStream = localContentProviderAsList.Connect();
|
||||||
|
|
||||||
var rootDriveInfos = Observable.CombineLatest(
|
var rootDriveInfos = Observable.CombineLatest(
|
||||||
localContentProvider.Items,
|
localContentProvider.Items,
|
||||||
@@ -34,7 +34,7 @@ public class RootDriveInfoService : IStartupHandler
|
|||||||
return items is null
|
return items is null
|
||||||
? Observable.Empty<IChangeSet<(AbsolutePath Path, DriveInfo? Drive), string>>()
|
? Observable.Empty<IChangeSet<(AbsolutePath Path, DriveInfo? Drive), string>>()
|
||||||
: items!
|
: items!
|
||||||
.Or(new[] { _localContentProviderStream })
|
.Or(new[] { localContentProviderStream })
|
||||||
.Transform(i => (Path: i, Drive: drives.FirstOrDefault(d =>
|
.Transform(i => (Path: i, Drive: drives.FirstOrDefault(d =>
|
||||||
{
|
{
|
||||||
var containerPath = localContentProvider.GetNativePath(i.Path).Path;
|
var containerPath = localContentProvider.GetNativePath(i.Path).Path;
|
||||||
|
|||||||
@@ -140,7 +140,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!--Border Grid.Row="1" CornerRadius="10" Background="{DynamicResource ContainerBackgroundBrush}" Padding="0,10" Margin="10">
|
<Border Grid.Row="1" CornerRadius="10" Background="{DynamicResource ContainerBackgroundBrush}" Padding="0,10" Margin="10">
|
||||||
<Grid RowDefinitions="Auto,Auto">
|
<Grid RowDefinitions="Auto,Auto">
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
@@ -149,9 +149,9 @@
|
|||||||
|
|
||||||
<ItemsRepeater
|
<ItemsRepeater
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Items="{Binding Places}">
|
Items="{Binding AppState.Places}">
|
||||||
<ItemsRepeater.ItemTemplate>
|
<ItemsRepeater.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate x:DataType="vm:PlaceInfo">
|
||||||
<Grid Classes="SidebarContainerPresenter" PointerPressed="OnHasContainerPointerPressed" Cursor="Hand">
|
<Grid Classes="SidebarContainerPresenter" PointerPressed="OnHasContainerPointerPressed" Cursor="Hand">
|
||||||
<StackPanel Orientation="Horizontal" Margin="10,5" HorizontalAlignment="Stretch">
|
<StackPanel Orientation="Horizontal" Margin="10,5" HorizontalAlignment="Stretch">
|
||||||
<Image
|
<Image
|
||||||
@@ -163,7 +163,7 @@
|
|||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="5,0,0,0"
|
Margin="5,0,0,0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{Binding Name}" />
|
Text="{Binding DisplayName}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
@@ -172,7 +172,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<Border Grid.Row="2" CornerRadius="10" Background="{DynamicResource ContainerBackgroundBrush}" Padding="0,10" Margin="10">
|
<!--Border Grid.Row="2" CornerRadius="10" Background="{DynamicResource ContainerBackgroundBrush}" Padding="0,10" Margin="10">
|
||||||
<Grid RowDefinitions="Auto,Auto">
|
<Grid RowDefinitions="Auto,Auto">
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
|||||||
Reference in New Issue
Block a user