CommandPalette WIP

This commit is contained in:
2023-05-22 09:29:41 +02:00
parent 2fe362ad6e
commit 0ed161c819
59 changed files with 536 additions and 276 deletions

View File

@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>FileTime.App.CommandPalette</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview8" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,8 @@
namespace FileTime.App.CommandPalette.Models;
public interface ICommandPaletteEntry
{
string Identifier { get; }
string Title { get; }
}

View File

@@ -0,0 +1,12 @@
using FileTime.App.CommandPalette.Models;
using FileTime.App.CommandPalette.ViewModels;
namespace FileTime.App.CommandPalette.Services;
public interface ICommandPaletteService
{
IObservable<bool> ShowWindow { get; }
void OpenCommandPalette();
IReadOnlyList<ICommandPaletteEntry> GetCommands();
ICommandPaletteViewModel? CurrentModal { get; }
}

View File

@@ -0,0 +1,7 @@
namespace FileTime.App.CommandPalette.ViewModels;
public interface ICommandPaletteEntryViewModel
{
string Identifier { get; set; }
string Title { get; set; }
}

View File

@@ -0,0 +1,14 @@
using Avalonia.Input;
using FileTime.App.Core.ViewModels;
namespace FileTime.App.CommandPalette.ViewModels;
public interface ICommandPaletteViewModel : IModalViewModel
{
IObservable<bool> ShowWindow { get; }
List<ICommandPaletteEntryViewModel> FilteredMatches { get; }
string SearchText { get; set; }
ICommandPaletteEntryViewModel SelectedItem { get; set; }
void Close();
void HandleKeyDown(KeyEventArgs keyEventArgs);
}

View File

@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\FileTime.App.CommandPalette.Abstractions\FileTime.App.CommandPalette.Abstractions.csproj" />
<ProjectReference Include="..\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
<PackageReference Include="PropertyChanged.SourceGenerator" Version="1.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Reactive" Version="6.0.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,13 @@
namespace FileTime.App.CommandPalette.Models;
public class CommandPaletteEntry : ICommandPaletteEntry
{
public string Identifier { get; }
public string Title { get; }
public CommandPaletteEntry(string identifier, string title)
{
Identifier = identifier;
Title = title;
}
}

View File

@@ -0,0 +1,37 @@
using System.Reactive.Linq;
using System.Reactive.Subjects;
using FileTime.App.CommandPalette.Models;
using FileTime.App.CommandPalette.ViewModels;
using FileTime.App.Core.Services;
using PropertyChanged.SourceGenerator;
namespace FileTime.App.CommandPalette.Services;
public partial class CommandPaletteService : ICommandPaletteService
{
private readonly IModalService _modalService;
private readonly IIdentifiableUserCommandService _identifiableUserCommandService;
private readonly BehaviorSubject<bool> _showWindow = new(false);
IObservable<bool> ICommandPaletteService.ShowWindow => _showWindow.AsObservable();
[Notify] ICommandPaletteViewModel? _currentModal;
public CommandPaletteService(
IModalService modalService,
IIdentifiableUserCommandService identifiableUserCommandService)
{
_modalService = modalService;
_identifiableUserCommandService = identifiableUserCommandService;
}
public void OpenCommandPalette()
{
_showWindow.OnNext(true);
CurrentModal = _modalService.OpenModal<ICommandPaletteViewModel>();
}
public IReadOnlyList<ICommandPaletteEntry> GetCommands() =>
_identifiableUserCommandService
.GetCommandIdentifiers()
.Select(c => new CommandPaletteEntry(c, c))
.ToList()
.AsReadOnly();
}

View File

@@ -0,0 +1,16 @@
using FileTime.App.CommandPalette.Services;
using FileTime.App.CommandPalette.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace FileTime.App.CommandPalette;
public static class Startup
{
public static IServiceCollection AddCommandPalette(this IServiceCollection services)
{
services.TryAddTransient<ICommandPaletteViewModel, CommandPaletteViewModel>();
services.TryAddSingleton<ICommandPaletteService, CommandPaletteService>();
return services;
}
}

View File

@@ -0,0 +1,16 @@
using MvvmGen;
namespace FileTime.App.CommandPalette.ViewModels;
[ViewModel]
public partial class CommandPaletteEntryViewModel : ICommandPaletteEntryViewModel
{
[Property] private string _identifier;
[Property] private string _title;
public CommandPaletteEntryViewModel(string identifier, string title)
{
_identifier = identifier;
_title = title;
}
}

View File

@@ -0,0 +1,59 @@
using Avalonia.Input;
using FileTime.App.CommandPalette.Services;
using FileTime.App.Core.ViewModels;
using MvvmGen;
namespace FileTime.App.CommandPalette.ViewModels;
[ViewModel]
[Inject(typeof(ICommandPaletteService), "_commandPaletteService")]
public partial class CommandPaletteViewModel : ICommandPaletteViewModel
{
private string _searchText;
[Property] private IObservable<bool> _showWindow;
[Property] private List<ICommandPaletteEntryViewModel> _filteredMatches;
[Property] private ICommandPaletteEntryViewModel? _selectedItem;
string IModalViewModel.Name => "CommandPalette";
public string SearchText
{
get => _searchText;
set
{
if (_searchText == value) return;
_searchText = value;
OnPropertyChanged();
UpdateFilteredMatches();
}
}
public void Close() => throw new NotImplementedException();
public void HandleKeyDown(KeyEventArgs keyEventArgs) => throw new NotImplementedException();
partial void OnInitialize()
{
ShowWindow = _commandPaletteService.ShowWindow;
UpdateFilteredMatches();
}
private void UpdateFilteredMatches()
{
FilteredMatches = _commandPaletteService
.GetCommands()
.Select(c =>
(ICommandPaletteEntryViewModel) new CommandPaletteEntryViewModel(c.Identifier, c.Title))
.Take(30) // TODO remove magic number
.OrderBy(c => c.Title)
.ToList();
if (SelectedItem != null && FilteredMatches.Contains(SelectedItem)) return;
SelectedItem = FilteredMatches.Count > 0
? FilteredMatches[0]
: null;
}
}

View File

@@ -1,5 +1,3 @@
using System.Collections.ObjectModel;
namespace FileTime.App.Core.Extensions;
public static class DisposableExtensions

View File

@@ -6,4 +6,5 @@ public interface IIdentifiableUserCommandService
{
void AddIdentifiableUserCommandFactory(string identifier, Func<IIdentifiableUserCommand> commandFactory);
IIdentifiableUserCommand GetCommand(string identifier);
IReadOnlyCollection<string> GetCommandIdentifiers();
}

View File

@@ -3,4 +3,5 @@ namespace FileTime.App.Core.UserCommand;
public interface IIdentifiableUserCommand : IUserCommand
{
string UserCommandID { get; }
//string Title { get; }
}

View File

@@ -0,0 +1,13 @@
namespace FileTime.App.Core.UserCommand;
public class OpenCommandPaletteCommand : IIdentifiableUserCommand
{
public const string CommandName = "open_command_palette";
public static OpenCommandPaletteCommand Instance { get; } = new ();
private OpenCommandPaletteCommand()
{
}
public string UserCommandID => CommandName;
}

View File

@@ -1,6 +1,5 @@
using DynamicData;
using FileTime.App.Core.Models;
using FileTime.Core.Models;
using FileTime.Core.Services;
using InitableService;

View File

@@ -1,5 +1,4 @@
using FileTime.Core.Models;
using FileTime.Core.Timeline;
namespace FileTime.App.Core.ViewModels.Timeline;

View File

@@ -23,6 +23,8 @@
<ProjectReference Include="..\..\Core\FileTime.Core.Models\FileTime.Core.Models.csproj" />
<ProjectReference Include="..\..\Providers\FileTime.Providers.Local.Abstractions\FileTime.Providers.Local.Abstractions.csproj" />
<ProjectReference Include="..\..\Tools\FileTime.Tools\FileTime.Tools.csproj" />
<ProjectReference Include="..\FileTime.App.CommandPalette.Abstractions\FileTime.App.CommandPalette.Abstractions.csproj" />
<ProjectReference Include="..\FileTime.App.CommandPalette\FileTime.App.CommandPalette.csproj" />
<ProjectReference Include="..\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
<ProjectReference Include="..\..\Core\FileTime.Core.Command\FileTime.Core.Command.csproj" />
<ProjectReference Include="..\FileTime.App.FrequencyNavigation.Abstractions\FileTime.App.FrequencyNavigation.Abstractions.csproj" />

View File

@@ -3,7 +3,6 @@ using FileTime.App.Core.ViewModels;
using FileTime.App.Core.ViewModels.ItemPreview;
using FileTime.Core.Models;
using InitableService;
using Microsoft.Extensions.DependencyInjection;
namespace FileTime.App.Core.Services;

View File

@@ -16,4 +16,6 @@ public class IdentifiableUserCommandService : IIdentifiableUserCommandService
return _identifiableUserCommands[identifier].Invoke();
}
public IReadOnlyCollection<string> GetCommandIdentifiers() => _identifiableUserCommands.Keys.ToList();
}

View File

@@ -1,5 +1,4 @@
using System.Reactive.Linq;
using FileTime.App.Core.Models;
using FileTime.App.Core.Models.Enums;
using FileTime.App.Core.UserCommand;
using FileTime.App.Core.ViewModels;

View File

@@ -1,3 +1,4 @@
using FileTime.App.CommandPalette.Services;
using FileTime.App.Core.Extensions;
using FileTime.App.Core.Models.Enums;
using FileTime.App.Core.UserCommand;
@@ -22,6 +23,7 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase
private readonly ITimelessContentProvider _timelessContentProvider;
private readonly IUserCommunicationService _userCommunicationService;
private readonly IFrequencyNavigationService _frequencyNavigationService;
private readonly ICommandPaletteService _commandPaletteService;
private ITabViewModel? _selectedTab;
private IContainer? _currentLocation;
private IItemViewModel? _currentSelectedItem;
@@ -35,7 +37,8 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase
IUserCommandHandlerService userCommandHandlerService,
ITimelessContentProvider timelessContentProvider,
IUserCommunicationService userCommunicationService,
IFrequencyNavigationService frequencyNavigationService) : base(appState)
IFrequencyNavigationService frequencyNavigationService,
ICommandPaletteService commandPaletteService) : base(appState)
{
_appState = appState;
_serviceProvider = serviceProvider;
@@ -44,6 +47,7 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase
_timelessContentProvider = timelessContentProvider;
_userCommunicationService = userCommunicationService;
_frequencyNavigationService = frequencyNavigationService;
_commandPaletteService = commandPaletteService;
SaveSelectedTab(t => _selectedTab = t);
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
@@ -69,6 +73,7 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase
new TypeUserCommandHandler<MoveCursorToLastCommand>(MoveCursorToLast),
new TypeUserCommandHandler<MoveCursorUpCommand>(MoveCursorUp),
new TypeUserCommandHandler<MoveCursorUpPageCommand>(MoveCursorUpPage),
new TypeUserCommandHandler<OpenCommandPaletteCommand>(OpenCommandPalette),
new TypeUserCommandHandler<OpenContainerCommand>(OpenContainer),
new TypeUserCommandHandler<OpenSelectedCommand>(OpenSelected),
new TypeUserCommandHandler<RefreshCommand>(Refresh),
@@ -76,6 +81,12 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase
});
}
private Task OpenCommandPalette()
{
_commandPaletteService.OpenCommandPalette();
return Task.CompletedTask;
}
private Task GoByFrequency()
{
_frequencyNavigationService.OpenNavigationWindow();

View File

@@ -1,6 +1,4 @@
using System.Diagnostics;
using System.Security.Cryptography;
using System.Text;
using FileTime.App.Core.UserCommand;
using FileTime.App.Core.ViewModels;
using FileTime.App.Search;

View File

@@ -1,3 +1,4 @@
using FileTime.App.CommandPalette.ViewModels;
using FileTime.App.Core.Services;
using FileTime.App.Core.Services.UserCommandHandler;
using FileTime.App.Core.StartupServices;
@@ -25,6 +26,7 @@ public static class Startup
serviceCollection.TryAddSingleton<IIdentifiableUserCommandService, IdentifiableUserCommandService>();
serviceCollection.TryAddSingleton<IItemPreviewService, ItemPreviewService>();
serviceCollection.TryAddSingleton<ITimelineViewModel, TimelineViewModel>();
serviceCollection.TryAddSingleton<ICommandPaletteViewModel, CommandPaletteViewModel>();
return serviceCollection
.AddCommandHandlers()

View File

@@ -5,11 +5,11 @@ namespace FileTime.App.Core.StartupServices;
public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler
{
private readonly IIdentifiableUserCommandService _service;
private readonly IIdentifiableUserCommandService _userCommandHandlerService;
public DefaultIdentifiableCommandHandlerRegister(IIdentifiableUserCommandService service)
public DefaultIdentifiableCommandHandlerRegister(IIdentifiableUserCommandService userCommandHandlerService)
{
_service = service;
_userCommandHandlerService = userCommandHandlerService;
AddUserCommand(CloseTabCommand.Instance);
AddUserCommand(CopyCommand.Instance);
@@ -34,6 +34,7 @@ public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler
AddUserCommand(MoveCursorToLastCommand.Instance);
AddUserCommand(MoveCursorUpCommand.Instance);
AddUserCommand(MoveCursorUpPageCommand.Instance);
AddUserCommand(OpenCommandPaletteCommand.Instance);
AddUserCommand(OpenInDefaultFileExplorerCommand.Instance);
AddUserCommand(OpenSelectedCommand.Instance);
AddUserCommand(PasteCommand.Merge);
@@ -58,5 +59,5 @@ public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler
public Task InitAsync() => Task.CompletedTask;
private void AddUserCommand(IIdentifiableUserCommand command)
=> _service.AddIdentifiableUserCommandFactory(command.UserCommandID, () => command);
=> _userCommandHandlerService.AddIdentifiableUserCommandFactory(command.UserCommandID, () => command);
}

View File

@@ -2,7 +2,6 @@ using System.Reactive.Linq;
using DynamicData;
using DynamicData.Binding;
using FileTime.App.Core.Extensions;
using FileTime.App.Core.Models;
using FileTime.App.Core.Models.Enums;
using FileTime.App.Core.Services;
using FileTime.Core.Enums;

View File

@@ -19,7 +19,7 @@ public partial class FrequencyNavigationViewModel : IFrequencyNavigationViewMode
[Property] private IObservable<bool> _showWindow;
[Property] private List<string> _filteredMatches;
[Property] private string _selectedItem;
[Property] private string? _selectedItem;
public string SearchText
{
@@ -68,12 +68,12 @@ public partial class FrequencyNavigationViewModel : IFrequencyNavigationViewMode
}
partial void OnInitialize()
=> _showWindow = _frequencyNavigationService.ShowWindow;
=> ShowWindow = _frequencyNavigationService.ShowWindow;
private void UpdateFilteredMatches()
{
FilteredMatches = new List<string>(_frequencyNavigationService.GetMatchingContainers(_searchText));
if (FilteredMatches.Contains(SelectedItem)) return;
if (SelectedItem != null && FilteredMatches.Contains(SelectedItem)) return;
SelectedItem = FilteredMatches.Count > 0
? FilteredMatches[0]

View File

@@ -1,8 +1,6 @@
using System.Reactive.Linq;
using DynamicData;
using FileTime.Core.ContentAccess;
using FileTime.Core.Enums;
using FileTime.Core.Extensions;
using FileTime.Core.Models;
using FileTime.Core.Timeline;

View File

@@ -1,5 +1,3 @@
using FileTime.Core.Timeline;
namespace FileTime.Core.Command;
public interface ICommandRunner

View File

@@ -1,5 +1,3 @@
using FileTime.Core.Timeline;
namespace FileTime.Core.Command;
public interface IExecutableCommand : ICommand

View File

@@ -1,4 +1,3 @@
using System.Reactive.Linq;
using DynamicData;
using FileTime.Core.ContentAccess;
using FileTime.Core.Enums;

View File

@@ -1,5 +1,4 @@
using FileTime.Core.Models;
using FileTime.Core.Services;
namespace FileTime.Core.Timeline;

View File

@@ -1,5 +1,4 @@
using FileTime.Core.Enums;
using FileTime.Core.Extensions;
using FileTime.Core.Models;
using FileTime.Core.Timeline;

View File

@@ -1,6 +1,5 @@
using FileTime.Core.ContentAccess;
using FileTime.Core.Enums;
using FileTime.Core.Extensions;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
using InitableService;

View File

@@ -1,5 +1,4 @@
using FileTime.Core.ContentAccess;
using FileTime.Core.Extensions;
using FileTime.Core.Models;
using FileTime.Core.Timeline;

View File

@@ -1,4 +1,3 @@
using FileTime.Core.Extensions;
using FileTime.Core.Models;
namespace FileTime.Core.Command;

View File

@@ -1,7 +1,6 @@
using FileTime.Core.Command;
using FileTime.Core.Command.Copy;
using FileTime.Core.ContentAccess;
using FileTime.Core.Extensions;
using FileTime.Core.Models;
namespace FileTime.Core.CommandHandlers;

View File

@@ -71,6 +71,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.App.Search", "AppC
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.App.Search.Abstractions", "AppCommon\FileTime.App.Search.Abstractions\FileTime.App.Search.Abstractions.csproj", "{D8D4A5C3-14B5-49E7-B029-D6E5D9574388}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.App.CommandPalette", "AppCommon\FileTime.App.CommandPalette\FileTime.App.CommandPalette.csproj", "{D0CC03DA-4705-48BD-9C4F-B11545D8BC83}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.App.CommandPalette.Abstractions", "AppCommon\FileTime.App.CommandPalette.Abstractions\FileTime.App.CommandPalette.Abstractions.csproj", "{5B3D2008-371F-485C-92C0-127F6CD64F64}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -181,6 +185,14 @@ Global
{D8D4A5C3-14B5-49E7-B029-D6E5D9574388}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8D4A5C3-14B5-49E7-B029-D6E5D9574388}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8D4A5C3-14B5-49E7-B029-D6E5D9574388}.Release|Any CPU.Build.0 = Release|Any CPU
{D0CC03DA-4705-48BD-9C4F-B11545D8BC83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D0CC03DA-4705-48BD-9C4F-B11545D8BC83}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D0CC03DA-4705-48BD-9C4F-B11545D8BC83}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D0CC03DA-4705-48BD-9C4F-B11545D8BC83}.Release|Any CPU.Build.0 = Release|Any CPU
{5B3D2008-371F-485C-92C0-127F6CD64F64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B3D2008-371F-485C-92C0-127F6CD64F64}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B3D2008-371F-485C-92C0-127F6CD64F64}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B3D2008-371F-485C-92C0-127F6CD64F64}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -213,6 +225,8 @@ Global
{C1CA8B7E-F8E6-40AB-A45B-5EBEF6996290} = {A5291117-3001-498B-AC8B-E14F71F72570}
{0D3C3584-242F-4DD6-A04A-2225A8AB6746} = {A5291117-3001-498B-AC8B-E14F71F72570}
{D8D4A5C3-14B5-49E7-B029-D6E5D9574388} = {A5291117-3001-498B-AC8B-E14F71F72570}
{D0CC03DA-4705-48BD-9C4F-B11545D8BC83} = {A5291117-3001-498B-AC8B-E14F71F72570}
{5B3D2008-371F-485C-92C0-127F6CD64F64} = {A5291117-3001-498B-AC8B-E14F71F72570}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {859FB3DF-C60A-46B1-82E5-90274905D1EF}

View File

@@ -71,6 +71,8 @@ public static class MainConfiguration
new(MoveCursorToFirstCommand.CommandName, new[] {Key.G, Key.G}),
//new CommandBindingConfiguration(ConfigCommand.NextTimelineBlock, Key.L ),
//new CommandBindingConfiguration(ConfigCommand.NextTimelineCommand, Key.J ),
new(OpenCommandPaletteCommand.CommandName, new[] {Key.F1}),
new(OpenCommandPaletteCommand.CommandName, new[] {new KeyConfig(Key.P, ctrl: true, shift: true)}),
new(OpenInDefaultFileExplorerCommand.CommandName, new[] {Key.O, Key.E}),
new(PasteCommand.PasteMergeCommandName, new[] {Key.P, Key.P}),
new(PasteCommand.PasteOverwriteCommandName, new[] {Key.P, Key.O}),

View File

@@ -1,4 +1,3 @@
using FileTime.App.Core.Models;
using FileTime.Core.Interactions;
using FileTime.GuiApp.ViewModels;

View File

@@ -1,5 +1,4 @@
using System.Collections.ObjectModel;
using FileTime.App.Core.Models;
using FileTime.App.Core.ViewModels;
using FileTime.Core.Models;
using FileTime.GuiApp.Configuration;

View File

@@ -1,6 +1,7 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using FileTime.App.CommandPalette;
using FileTime.App.DependencyInjection;
using FileTime.App.FrequencyNavigation;
using FileTime.App.Search;
@@ -20,6 +21,7 @@ public partial class App : Application
DI.ServiceProvider = DependencyInjection
.RegisterDefaultServices()
.AddFrequencyNavigation()
.AddCommandPalette()
.AddSearch()
.AddConfiguration(configuration)
.ConfigureFont(configuration)

View File

@@ -38,6 +38,7 @@
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.CommandPalette\FileTime.App.CommandPalette.csproj" />
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core\FileTime.App.Core.csproj" />
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.DependencyInjection\FileTime.App.DependencyInjection.csproj" />
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.FrequencyNavigation\FileTime.App.FrequencyNavigation.csproj" />

View File

@@ -37,6 +37,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.CommandPalette.Abstractions\FileTime.App.CommandPalette.Abstractions.csproj" />
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.FrequencyNavigation.Abstractions\FileTime.App.FrequencyNavigation.Abstractions.csproj" />
<ProjectReference Include="..\..\..\Providers\FileTime.Providers.Local.Abstractions\FileTime.Providers.Local.Abstractions.csproj" />

View File

@@ -1,4 +1,3 @@
using System.Runtime.InteropServices;
using FileTime.Core.Models;
using FileTime.GuiApp.Models;
using FileTime.GuiApp.Services;

View File

@@ -1,6 +1,5 @@
using System.Reactive.Linq;
using Avalonia.Input;
using FileTime.App.Core.Models;
using FileTime.App.Core.Services;
using FileTime.App.Core.UserCommand;
using FileTime.App.Core.ViewModels;

View File

@@ -1,8 +1,6 @@
using System.Collections.ObjectModel;
using System.Reactive.Linq;
using Avalonia.Threading;
using DynamicData;
using FileTime.App.Core.Models;
using FileTime.App.Core.Services;
using FileTime.Core.Interactions;
using FileTime.GuiApp.ViewModels;

View File

@@ -1,4 +1,3 @@
using System.Collections.ObjectModel;
using FileTime.App.Core.UserCommand;
using FileTime.GuiApp.Configuration;
using Microsoft.Extensions.Options;

View File

@@ -1,5 +1,4 @@
using Avalonia.Input;
using FileTime.App.Core.Models;
using FileTime.App.Core.Services;
using FileTime.App.Core.UserCommand;
using FileTime.App.Core.ViewModels;

View File

@@ -1,12 +1,9 @@
using System.Reactive.Linq;
using System.Runtime.InteropServices;
using DynamicData;
using DynamicData.Binding;
using FileTime.App.Core.Models;
using FileTime.App.Core.Services;
using FileTime.Core.Extensions;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
using FileTime.GuiApp.ViewModels;
using FileTime.Providers.Local;

View File

@@ -1,5 +1,4 @@
using System.Runtime.InteropServices;
using FileTime.App.Core.Services;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
using FileTime.GuiApp.IconProviders;

View File

@@ -1,10 +1,10 @@
using System.Reactive.Linq;
using System.Reflection;
using Avalonia.Input;
using FileTime.App.CommandPalette.Services;
using FileTime.App.Core.Services;
using FileTime.App.Core.UserCommand;
using FileTime.App.FrequencyNavigation.Services;
using FileTime.App.FrequencyNavigation.ViewModels;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
using FileTime.GuiApp.Services;
@@ -27,6 +27,7 @@ namespace FileTime.GuiApp.ViewModels;
[Inject(typeof(ITimelessContentProvider), PropertyName = "_timelessContentProvider")]
[Inject(typeof(IFontService), "_fontService")]
[Inject(typeof(IFrequencyNavigationService), PropertyAccessModifier = AccessModifier.Public)]
[Inject(typeof(ICommandPaletteService), PropertyAccessModifier = AccessModifier.Public)]
public partial class MainWindowViewModel : IMainWindowViewModelBase
{
public bool Loading => false;

View File

@@ -0,0 +1,32 @@
<UserControl
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d"
x:Class="FileTime.GuiApp.Views.CommandPalette"
xmlns="https://github.com/avaloniaui"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Styles>
<StyleInclude Source="avares://FileTime.GuiApp/Resources/Styles.axaml" />
</UserControl.Styles>
<Grid RowDefinitions="Auto,*">
<TextBox
Focusable="True"
KeyDown="Search_OnKeyDown"
Text="{Binding SearchText, Mode=TwoWay}" />
<ListBox
Classes="CommandPalette"
Grid.Row="1"
ItemsSource="{Binding FilteredMatches}"
SelectedItem="{Binding SelectedItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<TextBlock Text="{Binding Identifier}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>

View File

@@ -0,0 +1,33 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using FileTime.App.FrequencyNavigation.ViewModels;
namespace FileTime.GuiApp.Views;
public partial class CommandPalette : UserControl
{
public CommandPalette()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void Search_OnKeyDown(object? sender, KeyEventArgs e)
{
if (DataContext is not IFrequencyNavigationViewModel viewModel) return;
if (e.Key == Key.Escape)
{
viewModel.Close();
}
else
{
viewModel.HandleKeyDown(e);
}
}
}

View File

@@ -1,4 +1,3 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Markup.Xaml;

View File

@@ -1,7 +1,23 @@
<Window
Background="Transparent"
Closed="OnWindowClosed"
ExtendClientAreaToDecorationsHint="True"
FontFamily="{Binding MainFont^, Mode=OneWay}"
Icon="/Assets/filetime.ico"
KeyDown="OnKeyDown"
MinHeight="600"
MinWidth="800"
Opened="OnWindowOpened"
RequestedThemeVariant="Dark"
Title="FileTime"
TransparencyLevelHint="Blur"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d"
x:Class="FileTime.GuiApp.Views.MainWindow"
x:CompileBindings="True"
x:DataType="vm:IMainWindowViewModelBase"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:appCoreModels="using:FileTime.App.Core.Models"
xmlns:config="using:FileTime.GuiApp.Configuration"
xmlns:corevm="using:FileTime.App.Core.ViewModels"
@@ -10,23 +26,7 @@
xmlns:local="using:FileTime.GuiApp.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:FileTime.GuiApp.ViewModels"
Title="FileTime"
MinWidth="800"
MinHeight="600"
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True"
x:DataType="vm:IMainWindowViewModelBase"
Background="Transparent"
Closed="OnWindowClosed"
ExtendClientAreaToDecorationsHint="True"
FontFamily="{Binding MainFont^, Mode=OneWay}"
Icon="/Assets/filetime.ico"
KeyDown="OnKeyDown"
Opened="OnWindowOpened"
RequestedThemeVariant="Dark"
TransparencyLevelHint="Blur"
mc:Ignorable="d">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
@@ -41,54 +41,36 @@
</Window.Styles>
<Grid Background="{DynamicResource AppBackgroundBrush}">
<Grid
x:DataType="vm:MainWindowViewModel"
IsVisible="{Binding Loading, Converter={x:Static BoolConverters.Not}, FallbackValue=False}">
<Grid IsVisible="{Binding Loading, Converter={x:Static BoolConverters.Not}, FallbackValue=False}" x:DataType="vm:MainWindowViewModel">
<Grid
ColumnDefinitions="250,*"
RowDefinitions="Auto,*">
<Grid ColumnDefinitions="250,*" RowDefinitions="Auto,*">
<Grid PointerPressed="HeaderPointerPressed">
<Rectangle Fill="#01000000" />
<TextBlock
Margin="15,10"
Text="{Binding Title}" />
<TextBlock Margin="15,10" Text="{Binding Title}" />
</Grid>
<Grid
Grid.Column="1"
PointerPressed="HeaderPointerPressed">
<Grid Grid.Column="1" PointerPressed="HeaderPointerPressed">
<Rectangle Fill="#01000000" />
<StackPanel
Margin="20,10"
Orientation="Horizontal">
<StackPanel Margin="20,10" Orientation="Horizontal">
<local:PathPresenter DataContext="{Binding AppState.SelectedTab^.CurrentLocation^.FullName.Path, Converter={StaticResource PathPreformatter}}" />
<TextBlock
Foreground="{StaticResource AccentBrush}"
Text="{Binding AppState.SelectedTab^.CurrentSelectedItem^.DisplayNameText}" />
<TextBlock Foreground="{StaticResource AccentBrush}" Text="{Binding AppState.SelectedTab^.CurrentSelectedItem^.DisplayNameText}" />
</StackPanel>
</Grid>
<Grid
Grid.Row="1"
RowDefinitions="Auto,Auto,Auto,Auto">
<Grid Grid.Row="1" RowDefinitions="Auto,Auto,Auto,Auto">
<Border
Margin="10"
Padding="10"
Background="{DynamicResource ContainerBackgroundBrush}"
CornerRadius="10">
CornerRadius="10"
Margin="10"
Padding="10">
<Grid RowDefinitions="Auto,Auto">
<TextBlock
Margin="0,0,0,10"
Text="Drives" />
<TextBlock Margin="0,0,0,10" Text="Drives" />
<ItemsRepeater
Grid.Row="1"
ItemsSource="{Binding AppState.RootDriveInfos.Collection}">
<ItemsRepeater Grid.Row="1" ItemsSource="{Binding AppState.RootDriveInfos.Collection}">
<ItemsRepeater.ItemTemplate>
<DataTemplate x:DataType="vm:RootDriveInfo">
<Grid
@@ -96,66 +78,66 @@
Cursor="Hand"
PointerPressed="OnHasContainerPointerPressed">
<Grid
Margin="0,5"
ColumnDefinitions="Auto,*,Auto"
Margin="0,5"
RowDefinitions="Auto,Auto">
<Image
Grid.RowSpan="2"
Width="20"
Height="20"
HorizontalAlignment="Left"
Source="{SvgImage /Assets/material/folder.svg}"
VerticalAlignment="Center"
Source="{SvgImage /Assets/material/folder.svg}" />
Width="20" />
<StackPanel
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Orientation="Horizontal">
Orientation="Horizontal"
VerticalAlignment="Center">
<TextBlock
Margin="5,0,0,0"
VerticalAlignment="Center"
Text="{Binding FullName}" />
Text="{Binding FullName}"
VerticalAlignment="Center" />
<TextBlock
Margin="5,0,0,0"
VerticalAlignment="Center"
Classes="ExtraSmallText"
IsVisible="{Binding Label, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
Text="{Binding Label}" />
Margin="5,0,0,0"
Text="{Binding Label}"
VerticalAlignment="Center" />
</StackPanel>
<StackPanel
Grid.Column="2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Orientation="Horizontal">
Orientation="Horizontal"
VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
Classes="SmallText"
Text="{Binding Free, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}" />
Text="{Binding Free, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}"
VerticalAlignment="Center" />
<TextBlock
VerticalAlignment="Center"
Classes="SmallText"
Text=" / " />
Text=" / "
VerticalAlignment="Center" />
<TextBlock
VerticalAlignment="Center"
Classes="SmallText"
Text="{Binding Size, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}" />
Text="{Binding Size, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}"
VerticalAlignment="Center" />
</StackPanel>
<ProgressBar
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2"
MinWidth="100"
Margin="5,0,0,0"
Grid.Row="1"
HorizontalAlignment="Stretch"
Margin="5,0,0,0"
Maximum="100"
MinWidth="100"
Value="{Binding UsedPercentage}" />
</Grid>
</Grid>
@@ -166,20 +148,16 @@
</Border>
<Border
Background="{DynamicResource ContainerBackgroundBrush}"
CornerRadius="10"
Grid.Row="1"
Margin="10"
Padding="0,10"
Background="{DynamicResource ContainerBackgroundBrush}"
CornerRadius="10">
Padding="0,10">
<Grid RowDefinitions="Auto,Auto">
<TextBlock
Margin="10,0,10,10"
Text="Places" />
<TextBlock Margin="10,0,10,10" Text="Places" />
<ItemsRepeater
Grid.Row="1"
ItemsSource="{Binding AppState.Places}">
<ItemsRepeater Grid.Row="1" ItemsSource="{Binding AppState.Places}">
<ItemsRepeater.ItemTemplate>
<DataTemplate x:DataType="vm:PlaceInfo">
<Grid
@@ -187,19 +165,19 @@
Cursor="Hand"
PointerPressed="OnHasContainerPointerPressed">
<StackPanel
Margin="10,5"
HorizontalAlignment="Stretch"
Margin="10,5"
Orientation="Horizontal">
<Image
Width="20"
Height="20"
Source="{Binding Container, Converter={StaticResource ItemToImageConverter}}"
VerticalAlignment="Center"
Source="{Binding Container, Converter={StaticResource ItemToImageConverter}}" />
Width="20" />
<TextBlock
Margin="5,0,0,0"
VerticalAlignment="Center"
Text="{Binding DisplayName}" />
Text="{Binding DisplayName}"
VerticalAlignment="Center" />
</StackPanel>
</Grid>
</DataTemplate>
@@ -275,8 +253,8 @@
</Grid>
<Grid
Grid.Row="1"
Grid.Column="1"
Grid.Row="1"
RowDefinitions="Auto,40,*,Auto">
<Grid>
@@ -289,18 +267,16 @@
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border
MaxHeight="200"
Margin="0,0,10,0"
Padding="5"
Background="{DynamicResource ContainerBackgroundColor}"
CornerRadius="10">
CornerRadius="10"
Margin="0,0,10,0"
MaxHeight="200"
Padding="5">
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Commands.Collection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border
BorderThickness="1"
Classes.SelectedTimelineCommand="{Binding IsSelected}">
<Border BorderThickness="1" Classes.SelectedTimelineCommand="{Binding IsSelected}">
<StackPanel>
<TextBlock Text="{Binding DisplayLabel^}" />
<ProgressBar
@@ -319,9 +295,7 @@
</ItemsControl>
</Grid>
<ItemsControl
Grid.Row="1"
ItemsSource="{Binding AppState.Tabs}">
<ItemsControl Grid.Row="1" ItemsSource="{Binding AppState.Tabs}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
@@ -330,42 +304,36 @@
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid RowDefinitions="Auto,1">
<StackPanel
Margin="20,0,20,0"
Orientation="Horizontal">
<StackPanel Margin="20,0,20,0" Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
Text="{Binding TabNumber, StringFormat=({0})}" />
<TextBlock Text="{Binding TabNumber, StringFormat=({0})}" VerticalAlignment="Center" />
<TextBlock
Margin="5,0,0,0"
VerticalAlignment="Center"
Text="{Binding CurrentLocation^.Name, FallbackValue=Loading...}" />
Text="{Binding CurrentLocation^.Name, FallbackValue=Loading...}"
VerticalAlignment="Center" />
</StackPanel>
<Rectangle
Grid.Row="1"
Fill="{DynamicResource ForegroundBrush}"
Grid.Row="1"
IsVisible="{Binding IsSelected^}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Grid
Grid.Row="2"
Margin="20,0,0,0">
<Grid Grid.Row="2" Margin="20,0,0,0">
<Grid ColumnDefinitions="15*,10,40*,10,45*">
<ListBox
x:CompileBindings="False"
AutoScrollToSelectedItem="True"
Classes="ContentListView"
IsTabStop="True"
ItemsSource="{Binding AppState.SelectedTab^.ParentsChildrenCollection.Collection}"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Visible">
ScrollViewer.VerticalScrollBarVisibility="Visible"
x:CompileBindings="False">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="corevm:IItemViewModel">
<local:ItemView
@@ -377,22 +345,20 @@
</ListBox>
<Rectangle
Fill="{DynamicResource ContentSeparatorBrush}"
Grid.Column="1"
Width="1"
Margin="0,10,0,10"
HorizontalAlignment="Center"
Margin="0,10,0,10"
VerticalAlignment="Stretch"
Fill="{DynamicResource ContentSeparatorBrush}" />
Width="1" />
<Grid
Grid.Column="2"
RowDefinitions="Auto,*">
<Grid Grid.Column="2" RowDefinitions="Auto,*">
<Grid IsVisible="{Binding AppState.SelectedTab^.CurrentLocation^.IsLoading^, FallbackValue=False}">
<Image
Width="40"
Height="40"
Classes="LoadingAnimation"
Source="{SvgImage /Assets/loading.svg}">
Height="40"
Source="{SvgImage /Assets/loading.svg}"
Width="40">
<!-- https://github.com/AvaloniaUI/Avalonia/issues/8791 -->
<!-- Has to explicitly set RotateTransform or animation does not work -->
<Image.RenderTransform>
@@ -403,55 +369,53 @@
</Image>
</Grid>
<ListBox
x:Name="CurrentItems"
Grid.Row="1"
AutoScrollToSelectedItem="True"
Classes="ContentListView"
Grid.Row="1"
IsTabStop="True"
ItemsSource="{Binding AppState.SelectedTab^.CurrentItemsCollection.Collection}"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectedItem="{Binding AppState.SelectedTab^.CurrentSelectedItem^}">
SelectedItem="{Binding AppState.SelectedTab^.CurrentSelectedItem^}"
x:Name="CurrentItems">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="corevm:IItemViewModel">
<local:ItemView
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch" />
<local:ItemView HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock
x:Name="CurrentEmpty"
Grid.Row="1"
Margin="10"
HorizontalAlignment="Center"
x:CompileBindings="False"
FontWeight="Bold"
Foreground="{DynamicResource ErrorBrush}"
IsVisible="{Binding AppState.SelectedTab^.CurrentItemsCollection.Collection.Count, Converter={StaticResource EqualityConverter}, ConverterParameter=0}">
Grid.Row="1"
HorizontalAlignment="Center"
IsVisible="{Binding AppState.SelectedTab^.CurrentItemsCollection.Collection.Count, Converter={StaticResource EqualityConverter}, ConverterParameter=0}"
Margin="10"
x:CompileBindings="False"
x:Name="CurrentEmpty">
Empty
</TextBlock>
</Grid>
<Rectangle
Fill="{DynamicResource ContentSeparatorBrush}"
Grid.Column="3"
Width="1"
Margin="0,10,0,10"
HorizontalAlignment="Center"
Margin="0,10,0,10"
VerticalAlignment="Stretch"
Fill="{DynamicResource ContentSeparatorBrush}" />
Width="1" />
<Grid Grid.Column="4">
<Grid IsVisible="{Binding ItemPreviewService.ItemPreview^, Converter={x:Static ObjectConverters.IsNull}}">
<Grid IsVisible="{Binding AppState.SelectedTab^.SelectedsChildrenCollection.Collection, Converter={x:Static ObjectConverters.IsNotNull}, FallbackValue=False}">
<ListBox
x:Name="ChildItems"
x:CompileBindings="False"
AutoScrollToSelectedItem="True"
Classes="ContentListView"
IsVisible="{Binding AppState.SelectedTab^.SelectedsChildrenCollection.Collection.Count, Converter={StaticResource NotEqualsConverter}, ConverterParameter=0}"
ItemsSource="{Binding AppState.SelectedTab^.SelectedsChildrenCollection.Collection}">
ItemsSource="{Binding AppState.SelectedTab^.SelectedsChildrenCollection.Collection}"
x:CompileBindings="False"
x:Name="ChildItems">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="corevm:IItemViewModel">
<local:ItemView />
@@ -460,35 +424,29 @@
</ListBox>
<TextBlock
x:Name="ChildEmpty"
Margin="10"
HorizontalAlignment="Center"
x:CompileBindings="False"
FontWeight="Bold"
Foreground="{DynamicResource ErrorBrush}"
IsVisible="{Binding AppState.SelectedTab^.SelectedsChildrenCollection.Collection.Count, Converter={StaticResource EqualityConverter}, ConverterParameter=0}">
HorizontalAlignment="Center"
IsVisible="{Binding AppState.SelectedTab^.SelectedsChildrenCollection.Collection.Count, Converter={StaticResource EqualityConverter}, ConverterParameter=0}"
Margin="10"
x:CompileBindings="False"
x:Name="ChildEmpty">
Empty
</TextBlock>
</Grid>
<Grid
IsVisible="{Binding AppState.SelectedTab^.SelectedsChildrenCollection, Converter={x:Static ObjectConverters.IsNull}, ConverterParameter=0, FallbackValue=False}"
RowDefinitions="Auto, Auto">
<Grid IsVisible="{Binding AppState.SelectedTab^.SelectedsChildrenCollection, Converter={x:Static ObjectConverters.IsNull}, ConverterParameter=0, FallbackValue=False}" RowDefinitions="Auto, Auto">
<TextBlock
Margin="0,0,0,10"
HorizontalAlignment="Center"
Foreground="{DynamicResource ErrorBrush}"
HorizontalAlignment="Center"
Margin="0,0,0,10"
Text="There were some errors while opening container."
TextWrapping="Wrap" />
<ItemsRepeater
Grid.Row="1"
ItemsSource="{Binding AppState.SelectedTab^.CurrentSelectedItem^.BaseItem.Exceptions^}">
<ItemsRepeater Grid.Row="1" ItemsSource="{Binding AppState.SelectedTab^.CurrentSelectedItem^.BaseItem.Exceptions^}">
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<TextBlock
Margin="5,0,5,10"
Text="{Binding Converter={StaticResource ExceptionToStringConverter}}" />
<TextBlock Margin="5,0,5,10" Text="{Binding Converter={StaticResource ExceptionToStringConverter}}" />
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
@@ -505,20 +463,20 @@
Text="Empty" />
<ScrollViewer IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Text}, FallbackValue={x:Static appCoreModels:ItemPreviewMode.Unknown}}">
<TextBox
x:CompileBindings="False"
IsReadOnly="True"
Text="{Binding ItemPreviewService.ItemPreview^.TextContent}" />
Text="{Binding ItemPreviewService.ItemPreview^.TextContent}"
x:CompileBindings="False" />
</ScrollViewer>
</Grid>
</Grid>
</Grid>
<ItemsRepeater
Margin="0,0,0,20"
HorizontalAlignment="Center"
VerticalAlignment="Top"
IsVisible="{Binding AppState.PopupTexts.Count, Converter={StaticResource NotEqualsConverter}, ConverterParameter=0}"
ItemsSource="{Binding AppState.PopupTexts}">
ItemsSource="{Binding AppState.PopupTexts}"
Margin="0,0,0,20"
VerticalAlignment="Top">
<ItemsRepeater.Styles>
<Style Selector="TextBlock">
<Style.Animations>
@@ -536,12 +494,12 @@
<ItemsRepeater.ItemTemplate>
<DataTemplate x:DataType="x:String">
<Border
Background="{DynamicResource ContainerGradientBackgroundBrush}"
Margin="5"
Padding="5"
Background="{DynamicResource ContainerGradientBackgroundBrush}">
Padding="5">
<TextBlock
HorizontalAlignment="Center"
Foreground="{DynamicResource AccentComplementBrush}"
HorizontalAlignment="Center"
Text="{Binding}" />
</Border>
</DataTemplate>
@@ -550,25 +508,21 @@
</Grid>
<Grid Grid.Row="3">
<Grid
IsVisible="{Binding AppState.ViewMode^, Converter={StaticResource EqualityConverter}, ConverterParameter=RapidTravel}"
RowDefinitions="1,Auto">
<Grid IsVisible="{Binding AppState.ViewMode^, Converter={StaticResource EqualityConverter}, ConverterParameter=RapidTravel}" RowDefinitions="1,Auto">
<Rectangle
Fill="{DynamicResource ContentSeparatorBrush}"
Height="1"
Margin="10,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Fill="{DynamicResource ContentSeparatorBrush}" />
Margin="10,0"
VerticalAlignment="Center" />
<StackPanel
Grid.Row="1"
Margin="30,10,10,10"
Orientation="Horizontal">
<TextBlock
Margin="0,0,30,0"
Text="Rapid travel mode" />
<TextBlock Margin="0,0,30,0" Text="Rapid travel mode" />
<TextBlock Text="Filter " />
@@ -583,15 +537,13 @@
</Grid.RowDefinitions>
<Rectangle
Fill="{DynamicResource ContentSeparatorBrush}"
Height="1"
Margin="10,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Fill="{DynamicResource ContentSeparatorBrush}" />
Margin="10,0"
VerticalAlignment="Center" />
<ItemsRepeater
Grid.Row="1"
ItemsSource="{Binding AppState.PossibleCommands}">
<ItemsRepeater Grid.Row="1" ItemsSource="{Binding AppState.PossibleCommands}">
<ItemsRepeater.ItemTemplate>
<DataTemplate x:DataType="config:CommandBindingConfiguration">
<Grid>
@@ -601,9 +553,7 @@
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding KeysDisplayText}" />
<TextBlock
Grid.Column="1"
Text="{Binding Command, Converter={StaticResource CommandToCommandNameConverter}}" />
<TextBlock Grid.Column="1" Text="{Binding Command, Converter={StaticResource CommandToCommandNameConverter}}" />
</Grid>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
@@ -614,49 +564,47 @@
</Grid>
<Border
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{DynamicResource BarelyTransparentBackgroundColor}"
IsVisible="{Binding DialogService.ReadInput^, Converter={x:Static ObjectConverters.IsNotNull}}">
HorizontalAlignment="Stretch"
IsVisible="{Binding DialogService.ReadInput^, Converter={x:Static ObjectConverters.IsNotNull}}"
VerticalAlignment="Stretch">
<Border
Padding="20"
Background="{DynamicResource ContainerBackgroundBrush}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="{DynamicResource ContainerBackgroundBrush}">
Padding="20"
VerticalAlignment="Center">
<Grid RowDefinitions="Auto,Auto">
<ItemsControl
x:Name="InputList"
ItemsSource="{Binding DialogService.ReadInput^.Inputs}">
<ItemsControl ItemsSource="{Binding DialogService.ReadInput^.Inputs}" x:Name="InputList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid
x:Name="ItemRoot"
MinWidth="500"
ColumnDefinitions="250,*"
Margin="10,5"
ColumnDefinitions="250,*">
MinWidth="500"
x:Name="ItemRoot">
<TextBlock
HorizontalAlignment="Left"
VerticalAlignment="Top"
Text="{Binding Label}" />
Text="{Binding Label}"
VerticalAlignment="Top" />
<Grid Grid.Column="1">
<TextBox
VerticalAlignment="Top"
x:DataType="interactions:TextInputElement"
IsVisible="{Binding Type, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Text}}"
Text="{Binding Value, Mode=TwoWay}" />
<TextBox
Text="{Binding Value, Mode=TwoWay}"
VerticalAlignment="Top"
x:DataType="interactions:PasswordInputElement"
x:DataType="interactions:TextInputElement" />
<TextBox
IsVisible="{Binding Type, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Password}}"
PasswordChar="{Binding PasswordChar}"
Text="{Binding Value, Mode=TwoWay}" />
Text="{Binding Value, Mode=TwoWay}"
VerticalAlignment="Top"
x:DataType="interactions:PasswordInputElement" />
<ListBox
x:DataType="interactions:IOptionsInputElement"
Classes="RadioButtonListBox"
IsVisible="{Binding Type, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Options}}"
ItemsSource="{Binding Options}"
SelectedItem="{Binding Value}" />
SelectedItem="{Binding Value}"
x:DataType="interactions:IOptionsInputElement" />
</Grid>
</Grid>
</DataTemplate>
@@ -668,32 +616,32 @@
Margin="0,10,0,0"
Orientation="Horizontal">
<Button
Width="80"
HorizontalContentAlignment="Center"
Command="{Binding ProcessCommand}"
Content="Ok" />
<Button
Width="80"
Margin="10,0,0,0"
Content="Ok"
HorizontalContentAlignment="Center"
Width="80" />
<Button
Command="{Binding CancelCommand}"
Content="Cancel" />
Content="Cancel"
HorizontalContentAlignment="Center"
Margin="10,0,0,0"
Width="80" />
</StackPanel>
</Grid>
</Border>
</Border>
<Border
Background="{DynamicResource BarelyTransparentBackgroundColor}"
DataContext="{Binding DialogService.LastMessageBox^}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{DynamicResource BarelyTransparentBackgroundColor}"
IsVisible="{Binding Converter={x:Static ObjectConverters.IsNotNull}, FallbackValue=False}">
IsVisible="{Binding Converter={x:Static ObjectConverters.IsNotNull}, FallbackValue=False}"
VerticalAlignment="Stretch">
<Border
Padding="20"
Background="{DynamicResource ContainerBackgroundBrush}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="{DynamicResource ContainerBackgroundBrush}">
Padding="20"
VerticalAlignment="Center">
<Grid RowDefinitions="Auto,Auto">
<TextBlock Text="{Binding Text}" />
@@ -702,44 +650,53 @@
Margin="0,10,0,0"
Orientation="Horizontal">
<Button
Width="80"
HorizontalContentAlignment="Center"
Command="{Binding OkCommand}"
Content="Yes" />
<Button
Width="80"
Margin="10,0,0,0"
Content="Yes"
HorizontalContentAlignment="Center"
Width="80" />
<Button
Command="{Binding CancelCommand}"
Content="No" />
Content="No"
HorizontalContentAlignment="Center"
Margin="10,0,0,0"
Width="80" />
</StackPanel>
</Grid>
</Border>
</Border>
<Border
Background="{DynamicResource BarelyTransparentBackgroundColor}"
DataContext="{Binding FrequencyNavigationService.CurrentModal}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{DynamicResource BarelyTransparentBackgroundColor}"
IsVisible="{Binding ShowWindow^, FallbackValue=False}">
IsVisible="{Binding ShowWindow^, FallbackValue=False}"
VerticalAlignment="Stretch">
<Grid Margin="100">
<local:FrequencyNavigation />
</Grid>
</Border>
<Border
Background="{DynamicResource BarelyTransparentBackgroundColor}"
DataContext="{Binding CommandPaletteService.CurrentModal}"
HorizontalAlignment="Stretch"
IsVisible="{Binding ShowWindow^, FallbackValue=False}"
VerticalAlignment="Stretch">
<Grid Margin="100">
<local:CommandPalette />
</Grid>
</Border>
</Grid>
<Grid IsVisible="{Binding Loading}">
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Image
Width="128"
Height="128"
Source="/Assets/filetime.ico" />
Source="/Assets/filetime.ico"
Width="128" />
<TextBlock
Margin="50"
HorizontalAlignment="Center"
Margin="50"
Text="Loading..." />
</StackPanel>
</Grid>

View File

@@ -1,6 +1,4 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace FileTime.GuiApp.Views;

View File

@@ -1,5 +1,4 @@
using FileTime.Core.ContentAccess;
using FileTime.Core.Services;
namespace FileTime.Providers.Local;

View File

@@ -1,4 +1,3 @@
using System.Reactive.Linq;
using System.Runtime.InteropServices;
using DynamicData;
using FileTime.Core.ContentAccess;