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,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;
}
}