Move common things to AppCore from GuiApp

This commit is contained in:
2023-08-07 12:06:34 +02:00
parent 3d0eda54fb
commit 936c3896b9
48 changed files with 427 additions and 187 deletions

View File

@@ -12,8 +12,4 @@
<ProjectReference Include="..\FileTime.App.FuzzyPanel.Abstraction\FileTime.App.FuzzyPanel.Abstraction.csproj" /> <ProjectReference Include="..\FileTime.App.FuzzyPanel.Abstraction\FileTime.App.FuzzyPanel.Abstraction.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.2" />
</ItemGroup>
</Project> </Project>

View File

@@ -1,4 +1,4 @@
using Avalonia.Input; using FileTime.App.Core.Models;
using FileTime.App.Core.ViewModels; using FileTime.App.Core.ViewModels;
using FileTime.App.FuzzyPanel; using FileTime.App.FuzzyPanel;
@@ -8,5 +8,5 @@ public interface ICommandPaletteViewModel : IFuzzyPanelViewModel<ICommandPalette
{ {
IObservable<bool> ShowWindow { get; } IObservable<bool> ShowWindow { get; }
void Close(); void Close();
Task<bool> HandleKeyUp(KeyEventArgs keyEventArgs); Task<bool> HandleKeyUp(GeneralKeyEventArgs keyEventArgs);
} }

View File

@@ -7,7 +7,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\GuiApp\Avalonia\FileTime.GuiApp.App.Abstractions\FileTime.GuiApp.App.Abstractions.csproj" />
<ProjectReference Include="..\FileTime.App.CommandPalette.Abstractions\FileTime.App.CommandPalette.Abstractions.csproj" /> <ProjectReference Include="..\FileTime.App.CommandPalette.Abstractions\FileTime.App.CommandPalette.Abstractions.csproj" />
<ProjectReference Include="..\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" /> <ProjectReference Include="..\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
<ProjectReference Include="..\FileTime.App.FuzzyPanel\FileTime.App.FuzzyPanel.csproj" /> <ProjectReference Include="..\FileTime.App.FuzzyPanel\FileTime.App.FuzzyPanel.csproj" />

View File

@@ -1,11 +1,10 @@
using System.Text; using System.Text;
using Avalonia.Input;
using FileTime.App.CommandPalette.Services; using FileTime.App.CommandPalette.Services;
using FileTime.App.Core.Configuration;
using FileTime.App.Core.Models;
using FileTime.App.Core.Services; using FileTime.App.Core.Services;
using FileTime.App.Core.ViewModels; using FileTime.App.Core.ViewModels;
using FileTime.App.FuzzyPanel; using FileTime.App.FuzzyPanel;
using FileTime.GuiApp.App.Configuration;
using FileTime.GuiApp.App.Services;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace FileTime.App.CommandPalette.ViewModels; namespace FileTime.App.CommandPalette.ViewModels;
@@ -89,7 +88,7 @@ public class CommandPaletteViewModel : FuzzyPanelViewModel<ICommandPaletteEntryV
.Select(k => k.Keys) .Select(k => k.Keys)
.ToList(); .ToList();
public override async Task<bool> HandleKeyDown(KeyEventArgs keyEventArgs) public override async Task<bool> HandleKeyDown(GeneralKeyEventArgs keyEventArgs)
{ {
if (keyEventArgs.Handled) return false; if (keyEventArgs.Handled) return false;
@@ -99,7 +98,7 @@ public class CommandPaletteViewModel : FuzzyPanelViewModel<ICommandPaletteEntryV
return true; return true;
} }
if (keyEventArgs.Key == Key.Escape) if (keyEventArgs.Key == Keys.Escape)
{ {
keyEventArgs.Handled = true; keyEventArgs.Handled = true;
Close(); Close();
@@ -109,11 +108,11 @@ public class CommandPaletteViewModel : FuzzyPanelViewModel<ICommandPaletteEntryV
return false; return false;
} }
public async Task<bool> HandleKeyUp(KeyEventArgs keyEventArgs) public async Task<bool> HandleKeyUp(GeneralKeyEventArgs keyEventArgs)
{ {
if (keyEventArgs.Handled) return false; if (keyEventArgs.Handled) return false;
if (keyEventArgs.Key == Key.Enter) if (keyEventArgs.Key == Keys.Enter)
{ {
if (SelectedItem is null) return false; if (SelectedItem is null) return false;

View File

@@ -1,6 +1,6 @@
using Avalonia.Input; using FileTime.App.Core.Models;
namespace FileTime.GuiApp.App.Configuration; namespace FileTime.App.Core.Configuration;
public class CommandBindingConfiguration public class CommandBindingConfiguration
{ {
@@ -24,19 +24,19 @@ public class CommandBindingConfiguration
public CommandBindingConfiguration(string command, KeyConfig key) public CommandBindingConfiguration(string command, KeyConfig key)
{ {
Keys = new List<KeyConfig>() { key }; Keys = new List<KeyConfig> { key };
Command = command; Command = command;
} }
public CommandBindingConfiguration(string command, IEnumerable<Key> keys) public CommandBindingConfiguration(string command, IEnumerable<Keys> keys)
{ {
Keys = keys.Select(k => new KeyConfig(k)).ToList(); Keys = keys.Select(k => new KeyConfig(k)).ToList();
Command = command; Command = command;
} }
public CommandBindingConfiguration(string command, Key key) public CommandBindingConfiguration(string command, Keys key)
{ {
Keys = new List<KeyConfig>() { new KeyConfig(key) }; Keys = new List<KeyConfig>() { new(key) };
Command = command; Command = command;
} }
@@ -61,7 +61,10 @@ public class CommandBindingConfiguration
return s; return s;
} }
private static string AddKeyWithCtrlOrAlt(KeyConfig key, string currentText, Func<KeyConfig, string, bool, string> keyProcessor) private static string AddKeyWithCtrlOrAlt(
KeyConfig key,
string currentText,
Func<KeyConfig, string, bool, string> keyProcessor)
{ {
var s = ""; var s = "";

View File

@@ -1,4 +1,4 @@
namespace FileTime.GuiApp.App.Configuration; namespace FileTime.App.Core.Configuration;
public class KeyBindingConfiguration public class KeyBindingConfiguration
{ {

View File

@@ -1,10 +1,10 @@
using Avalonia.Input; using FileTime.App.Core.Models;
namespace FileTime.GuiApp.App.Configuration; namespace FileTime.App.Core.Configuration;
public class KeyConfig public class KeyConfig
{ {
public Key Key { get; set; } public Keys Key { get; set; }
public bool Shift { get; set; } public bool Shift { get; set; }
public bool Alt { get; set; } public bool Alt { get; set; }
public bool Ctrl { get; set; } public bool Ctrl { get; set; }
@@ -12,7 +12,7 @@ public class KeyConfig
public KeyConfig() { } public KeyConfig() { }
public KeyConfig( public KeyConfig(
Key key, Keys key,
bool shift = false, bool shift = false,
bool alt = false, bool alt = false,
bool ctrl = false) bool ctrl = false)
@@ -24,7 +24,7 @@ public class KeyConfig
} }
public bool AreEquals(KeyConfig otherKeyConfig) => public bool AreEquals(KeyConfig otherKeyConfig) =>
Key == otherKeyConfig.Key Key.Equals(otherKeyConfig.Key)
&& Alt == otherKeyConfig.Alt && Alt == otherKeyConfig.Alt
&& Shift == otherKeyConfig.Shift && Shift == otherKeyConfig.Shift
&& Ctrl == otherKeyConfig.Ctrl; && Ctrl == otherKeyConfig.Ctrl;

View File

@@ -1,4 +1,4 @@
namespace FileTime.GuiApp.App.Configuration; namespace FileTime.App.Core.Configuration;
public class ProgramConfiguration public class ProgramConfiguration
{ {

View File

@@ -1,4 +1,4 @@
namespace FileTime.GuiApp.App.Configuration; namespace FileTime.App.Core.Configuration;
public class ProgramsConfiguration public class ProgramsConfiguration
{ {

View File

@@ -1,4 +1,4 @@
namespace FileTime.GuiApp.App.Configuration; namespace FileTime.App.Core.Configuration;
public static class SectionNames public static class SectionNames
{ {

View File

@@ -1,6 +1,6 @@
using FileTime.GuiApp.App.Configuration; using FileTime.App.Core.Configuration;
namespace FileTime.GuiApp.App.Extensions; namespace FileTime.App.Core.Extensions;
public static class KeyConfigExtensions public static class KeyConfigExtensions
{ {

View File

@@ -0,0 +1,26 @@
namespace FileTime.App.Core.Models;
public class GeneralKeyEventArgs
{
private readonly Action<bool> _handledChanged;
private bool _handled;
public required Keys Key { get; init; }
public bool Handled
{
get => _handled;
set
{
if (_handled != value)
{
_handled = value;
_handledChanged(value);
}
}
}
public GeneralKeyEventArgs(Action<bool> handledChanged)
{
_handledChanged = handledChanged;
}
}

View File

@@ -0,0 +1,58 @@
namespace FileTime.App.Core.Models;
public enum Keys
{
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
Up,
Down,
Left,
Right,
Enter,
Escape,
Back,
Space,
PageUp,
PageDown,
Comma,
Question,
Tab,
LWin,
RWin,
}

View File

@@ -0,0 +1,8 @@
using FileTime.App.Core.Models;
namespace FileTime.App.Core.Services;
public interface IAppKeyService<TKey>
{
Keys? MapKey(TKey key);
}

View File

@@ -1,6 +1,6 @@
using FileTime.GuiApp.App.Configuration; using FileTime.App.Core.Configuration;
namespace FileTime.GuiApp.App.Services; namespace FileTime.App.Core.Services;
public interface IKeyboardConfigurationService public interface IKeyboardConfigurationService
{ {

View File

@@ -0,0 +1,7 @@
namespace FileTime.App.Core.Services;
public interface ILifecycleService
{
Task InitStartupHandlersAsync();
Task ExitAsync();
}

View File

@@ -1,10 +1,10 @@
using Avalonia.Input; using FileTime.App.Core.Models;
using FileTime.App.Core.UserCommand; using FileTime.App.Core.UserCommand;
using FileTime.Providers.LocalAdmin; using FileTime.Providers.LocalAdmin;
namespace FileTime.GuiApp.App.Configuration; namespace FileTime.App.Core.Configuration;
public static class MainConfiguration public class MainConfiguration
{ {
private static readonly Lazy<List<CommandBindingConfiguration>> _defaultKeybindings = new(InitDefaultKeyBindings); private static readonly Lazy<List<CommandBindingConfiguration>> _defaultKeybindings = new(InitDefaultKeyBindings);
@@ -30,7 +30,7 @@ public static class MainConfiguration
var baseKey = basePath + $":[{i}]:"; var baseKey = basePath + $":[{i}]:";
var commandBindingConfig = commandBindingConfigs[i]; var commandBindingConfig = commandBindingConfigs[i];
configuration.Add(baseKey + nameof(CommandBindingConfiguration.Command), configuration.Add(baseKey + nameof(CommandBindingConfiguration.Command),
commandBindingConfig.Command.ToString()); commandBindingConfig.Command);
for (var j = 0; j < commandBindingConfig.Keys.Count; j++) for (var j = 0; j < commandBindingConfig.Keys.Count; j++)
{ {
@@ -47,93 +47,93 @@ public static class MainConfiguration
private static List<CommandBindingConfiguration> InitDefaultKeyBindings() => private static List<CommandBindingConfiguration> InitDefaultKeyBindings() =>
new List<CommandBindingConfiguration> new List<CommandBindingConfiguration>
{ {
//new CommandBindingConfiguration(ConfigCommand.AutoRefresh, new KeyConfig(Key.R, shift: true)), //new CommandBindingConfiguration(ConfigCommand.AutoRefresh, new KeyConfig(Keys.R, shift: true)),
//new CommandBindingConfiguration(ConfigCommand.ChangeTimelineMode, new[] { Key.T, Key.M }), //new CommandBindingConfiguration(ConfigCommand.ChangeTimelineMode, new[] { Keys.T, Keys.M }),
new(CloseTabCommand.CommandName, Key.Q), new(CloseTabCommand.CommandName, Keys.Q),
//new CommandBindingConfiguration(ConfigCommand.Compress, new[] { Key.Y, Key.C }), //new CommandBindingConfiguration(ConfigCommand.Compress, new[] { Keys.Y, Keys.C }),
new(CopyBase64Command.CommandName, new[] {Key.C, Key.B}), new(CopyBase64Command.CommandName, new[] {Keys.C, Keys.B}),
new(CopyCommand.CommandName, new[] {Key.Y, Key.Y}), new(CopyCommand.CommandName, new[] {Keys.Y, Keys.Y}),
//new CommandBindingConfiguration(ConfigCommand.CopyHash, new[] { Key.C, Key.H }), //new CommandBindingConfiguration(ConfigCommand.CopyHash, new[] { Keys.C, Keys.H }),
new(CopyNativePathCommand.CommandName, new[] {Key.C, Key.P}), new(CopyNativePathCommand.CommandName, new[] {Keys.C, Keys.P}),
new(CopyFilesToClipboardCommand.CommandName, new[] {Key.Y, Key.C}), new(CopyFilesToClipboardCommand.CommandName, new[] {Keys.Y, Keys.C}),
new(CreateContainer.CommandName, Key.F7), new(CreateContainer.CommandName, Keys.F7),
new(CreateContainer.CommandName, new[] {Key.C, Key.C}), new(CreateContainer.CommandName, new[] {Keys.C, Keys.C}),
new(CreateElementCommand.CommandName, new[] {Key.C, Key.E}), new(CreateElementCommand.CommandName, new[] {Keys.C, Keys.E}),
//new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Key.D, Key.D }), //new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Keys.D, Keys.D }),
//new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Key.F4)), //new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Keys.F4)),
new(EnterRapidTravelCommand.CommandName, new KeyConfig(Key.OemComma, shift: true)), new(EnterRapidTravelCommand.CommandName, new KeyConfig(Keys.Comma, shift: true)),
new(EnterRapidTravelCommand.CommandName, new KeyConfig(Key.OemQuestion, shift: true)), new(EnterRapidTravelCommand.CommandName, new KeyConfig(Keys.Question, shift: true)),
new(GoBackCommand.CommandName, new KeyConfig(Key.Left, alt: true)), new(GoBackCommand.CommandName, new KeyConfig(Keys.Left, alt: true)),
new(GoByFrequencyCommand.CommandName, Key.Z), new(GoByFrequencyCommand.CommandName, Keys.Z),
new(GoForwardCommand.CommandName, new KeyConfig(Key.Right, alt: true)), new(GoForwardCommand.CommandName, new KeyConfig(Keys.Right, alt: true)),
new(GoToHomeCommand.CommandName, new[] {Key.G, Key.H}), new(GoToHomeCommand.CommandName, new[] {Keys.G, Keys.H}),
new(GoToPathCommand.CommandName, new KeyConfig(Key.L, ctrl: true)), new(GoToPathCommand.CommandName, new KeyConfig(Keys.L, ctrl: true)),
new(GoToPathCommand.CommandName, new[] {Key.G, Key.P}), new(GoToPathCommand.CommandName, new[] {Keys.G, Keys.P}),
new(GoToProviderCommand.CommandName, new[] {Key.G, Key.T}), new(GoToProviderCommand.CommandName, new[] {Keys.G, Keys.T}),
new(GoToRootCommand.CommandName, new[] {Key.G, Key.R}), new(GoToRootCommand.CommandName, new[] {Keys.G, Keys.R}),
new(GoUpCommand.CommandName, Key.Left), new(GoUpCommand.CommandName, Keys.Left),
new(DeleteCommand.HardDeleteCommandName, new[] {new KeyConfig(Key.D, shift: true), new KeyConfig(Key.D, shift: true)}), new(DeleteCommand.HardDeleteCommandName, new[] {new KeyConfig(Keys.D, shift: true), new KeyConfig(Keys.D, shift: true)}),
new(MarkCommand.CommandName, Key.Space), new(MarkCommand.CommandName, Keys.Space),
new(MoveCursorToLastCommand.CommandName, new KeyConfig(Key.G, shift: true)), new(MoveCursorToLastCommand.CommandName, new KeyConfig(Keys.G, shift: true)),
new(MoveCursorToFirstCommand.CommandName, new[] {Key.G, Key.G}), new(MoveCursorToFirstCommand.CommandName, new[] {Keys.G, Keys.G}),
new(MoveCursorUpCommand.CommandName, Key.Up), new(MoveCursorUpCommand.CommandName, Keys.Up),
new(MoveCursorDownCommand.CommandName, Key.Down), new(MoveCursorDownCommand.CommandName, Keys.Down),
new(MoveCursorUpPageCommand.CommandName, Key.PageUp), new(MoveCursorUpPageCommand.CommandName, Keys.PageUp),
new(MoveCursorDownPageCommand.CommandName, Key.PageDown), new(MoveCursorDownPageCommand.CommandName, Keys.PageDown),
//new CommandBindingConfiguration(ConfigCommand.NextTimelineBlock, Key.L ), //new CommandBindingConfiguration(ConfigCommand.NextTimelineBlock, Keys.L ),
//new CommandBindingConfiguration(ConfigCommand.NextTimelineCommand, Key.J ), //new CommandBindingConfiguration(ConfigCommand.NextTimelineCommand, Keys.J ),
new(OpenSelectedCommand.CommandName, Key.Right), new(OpenSelectedCommand.CommandName, Keys.Right),
new(OpenCommandPaletteCommand.CommandName, new[] {Key.F1}), new(OpenCommandPaletteCommand.CommandName, new[] {Keys.F1}),
new(OpenCommandPaletteCommand.CommandName, new[] {new KeyConfig(Key.P, ctrl: true, shift: true)}), new(OpenCommandPaletteCommand.CommandName, new[] {new KeyConfig(Keys.P, ctrl: true, shift: true)}),
new(OpenInDefaultFileExplorerCommand.CommandName, new[] {Key.O, Key.E}), new(OpenInDefaultFileExplorerCommand.CommandName, new[] {Keys.O, Keys.E}),
new(PasteCommand.PasteMergeCommandName, new[] {Key.P, Key.P}), new(PasteCommand.PasteMergeCommandName, new[] {Keys.P, Keys.P}),
new(PasteCommand.PasteOverwriteCommandName, new[] {Key.P, Key.O}), new(PasteCommand.PasteOverwriteCommandName, new[] {Keys.P, Keys.O}),
new(PasteCommand.PasteSkipCommandName, new[] {Key.P, Key.S}), new(PasteCommand.PasteSkipCommandName, new[] {Keys.P, Keys.S}),
new(PasteFilesFromClipboardCommand.PasteMergeCommandName, new[] {new KeyConfig(Key.V, ctrl: true)}), new(PasteFilesFromClipboardCommand.PasteMergeCommandName, new[] {new KeyConfig(Keys.V, ctrl: true)}),
new(PasteFilesFromClipboardCommand.PasteOverwriteCommandName, new[] {new KeyConfig(Key.V, ctrl: true, shift: true)}), new(PasteFilesFromClipboardCommand.PasteOverwriteCommandName, new[] {new KeyConfig(Keys.V, ctrl: true, shift: true)}),
//new CommandBindingConfiguration(ConfigCommand.PinFavorite, new[] { Key.F, Key.P }), //new CommandBindingConfiguration(ConfigCommand.PinFavorite, new[] { Keys.F, Keys.P }),
//new CommandBindingConfiguration(ConfigCommand.PreviousTimelineBlock, Key.H ), //new CommandBindingConfiguration(ConfigCommand.PreviousTimelineBlock, Keys.H ),
//new CommandBindingConfiguration(ConfigCommand.PreviousTimelineCommand, Key.K ), //new CommandBindingConfiguration(ConfigCommand.PreviousTimelineCommand, Keys.K ),
new(RefreshCommand.CommandName, Key.R), new(RefreshCommand.CommandName, Keys.R),
new(RenameCommand.CommandName, Key.F2), new(RenameCommand.CommandName, Keys.F2),
new(RenameCommand.CommandName, new[] {Key.C, Key.W}), new(RenameCommand.CommandName, new[] {Keys.C, Keys.W}),
new(IdentifiableRunOrOpenCommand.CommandName, Key.Enter), new(IdentifiableRunOrOpenCommand.CommandName, Keys.Enter),
//new CommandBindingConfiguration(ConfigCommand.RunCommand, new KeyConfig(Key.D4, shift: true)), //new CommandBindingConfiguration(ConfigCommand.RunCommand, new KeyConfig(Keys.D4, shift: true)),
//new CommandBindingConfiguration(ConfigCommand.ScanContainerSize, new[] { Key.C, Key.S }), //new CommandBindingConfiguration(ConfigCommand.ScanContainerSize, new[] { Keys.C, Keys.S }),
//new CommandBindingConfiguration(ConfigCommand.ShowAllShortcut, Key.F1), //new CommandBindingConfiguration(ConfigCommand.ShowAllShortcut, Keys.F1),
new(DeleteCommand.SoftDeleteCommandName, new[] {new KeyConfig(Key.D), new KeyConfig(Key.D, shift: true)}), new(DeleteCommand.SoftDeleteCommandName, new[] {new KeyConfig(Keys.D), new KeyConfig(Keys.D, shift: true)}),
new(IdentifiableSearchCommand.SearchByNameContainsCommandName, new[] {Key.S, Key.N}), new(IdentifiableSearchCommand.SearchByNameContainsCommandName, new[] {Keys.S, Keys.N}),
new(SwitchToTabCommand.SwitchToLastTabCommandName, new[] {new KeyConfig(Key.D9, alt: true)}), new(SwitchToTabCommand.SwitchToLastTabCommandName, new[] {new KeyConfig(Keys.F9, alt: true)}),
new(SwitchToTabCommand.SwitchToTab1CommandName, new[] {new KeyConfig(Key.D1, alt: true)}), new(SwitchToTabCommand.SwitchToTab1CommandName, new[] {new KeyConfig(Keys.F1, alt: true)}),
new(SwitchToTabCommand.SwitchToTab2CommandName, new[] {new KeyConfig(Key.D2, alt: true)}), new(SwitchToTabCommand.SwitchToTab2CommandName, new[] {new KeyConfig(Keys.F2, alt: true)}),
new(SwitchToTabCommand.SwitchToTab3CommandName, new[] {new KeyConfig(Key.D3, alt: true)}), new(SwitchToTabCommand.SwitchToTab3CommandName, new[] {new KeyConfig(Keys.F3, alt: true)}),
new(SwitchToTabCommand.SwitchToTab4CommandName, new[] {new KeyConfig(Key.D4, alt: true)}), new(SwitchToTabCommand.SwitchToTab4CommandName, new[] {new KeyConfig(Keys.F4, alt: true)}),
new(SwitchToTabCommand.SwitchToTab5CommandName, new[] {new KeyConfig(Key.D5, alt: true)}), new(SwitchToTabCommand.SwitchToTab5CommandName, new[] {new KeyConfig(Keys.F5, alt: true)}),
new(SwitchToTabCommand.SwitchToTab6CommandName, new[] {new KeyConfig(Key.D6, alt: true)}), new(SwitchToTabCommand.SwitchToTab6CommandName, new[] {new KeyConfig(Keys.F6, alt: true)}),
new(SwitchToTabCommand.SwitchToTab7CommandName, new[] {new KeyConfig(Key.D7, alt: true)}), new(SwitchToTabCommand.SwitchToTab7CommandName, new[] {new KeyConfig(Keys.F7, alt: true)}),
new(SwitchToTabCommand.SwitchToTab8CommandName, new[] {new KeyConfig(Key.D8, alt: true)}), new(SwitchToTabCommand.SwitchToTab8CommandName, new[] {new KeyConfig(Keys.F8, alt: true)}),
new(PauseCommandSchedulerCommand.CommandName, new[] {Key.T, Key.P}), new(PauseCommandSchedulerCommand.CommandName, new[] {Keys.T, Keys.P}),
//new CommandBindingConfiguration(ConfigCommand.TimelineRefresh, new[] { Key.T, Key.R }), //new CommandBindingConfiguration(ConfigCommand.TimelineRefresh, new[] { Keys.T, Keys.R }),
new(StartCommandSchedulerCommand.CommandName, new[] {Key.T, Key.S}), new(StartCommandSchedulerCommand.CommandName, new[] {Keys.T, Keys.S}),
//new CommandBindingConfiguration(ConfigCommand.ToggleAdvancedIcons, new[] { Key.Z, Key.I }), //new CommandBindingConfiguration(ConfigCommand.ToggleAdvancedIcons, new[] { Keys.Z, Keys.I }),
}; };
private static void PopulateDefaultEditorPrograms(Dictionary<string, string?> configuration) private static void PopulateDefaultEditorPrograms(Dictionary<string, string?> configuration)
{ {
var editorPrograms = new List<ProgramConfiguration>() var editorPrograms = new List<ProgramConfiguration>()
{ {
new ProgramConfiguration(@"c:\Program Files\Notepad++\notepad++.exe"), new(@"c:\Program Files\Notepad++\notepad++.exe"),
new ProgramConfiguration("notepad.exe"), new("notepad.exe"),
}; };
for (var i = 0; i < editorPrograms.Count; i++) for (var i = 0; i < editorPrograms.Count; i++)
{ {
if (editorPrograms[i].Path is not string path) continue; if (editorPrograms[i].Path is not { } path) continue;
configuration.Add( configuration.Add(
$"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}", $"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}",
path); path);
if (editorPrograms[i].Arguments is string arguments) if (editorPrograms[i].Arguments is { } arguments)
{ {
configuration.Add( configuration.Add(
$"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}", $"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}",

View File

@@ -12,6 +12,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0" />
<PackageReference Include="morelinq" Version="3.4.2" /> <PackageReference Include="morelinq" Version="3.4.2" />
<PackageReference Include="MvvmGen" Version="1.2.1" /> <PackageReference Include="MvvmGen" Version="1.2.1" />
<PackageReference Include="ObservableComputations" Version="2.3.0" /> <PackageReference Include="ObservableComputations" Version="2.3.0" />
@@ -24,6 +25,7 @@
<ProjectReference Include="..\..\Core\FileTime.Core.Models\FileTime.Core.Models.csproj" /> <ProjectReference Include="..\..\Core\FileTime.Core.Models\FileTime.Core.Models.csproj" />
<ProjectReference Include="..\..\Library\Defer\Defer.csproj" /> <ProjectReference Include="..\..\Library\Defer\Defer.csproj" />
<ProjectReference Include="..\..\Providers\FileTime.Providers.Local.Abstractions\FileTime.Providers.Local.Abstractions.csproj" /> <ProjectReference Include="..\..\Providers\FileTime.Providers.Local.Abstractions\FileTime.Providers.Local.Abstractions.csproj" />
<ProjectReference Include="..\..\Providers\FileTime.Providers.LocalAdmin.Abstractions\FileTime.Providers.LocalAdmin.Abstractions.csproj" />
<ProjectReference Include="..\..\Tools\FileTime.Tools\FileTime.Tools.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.Abstractions\FileTime.App.CommandPalette.Abstractions.csproj" />
<ProjectReference Include="..\FileTime.App.CommandPalette\FileTime.App.CommandPalette.csproj" /> <ProjectReference Include="..\FileTime.App.CommandPalette\FileTime.App.CommandPalette.csproj" />

View File

@@ -1,8 +1,8 @@
using FileTime.App.Core.Configuration;
using FileTime.App.Core.UserCommand; using FileTime.App.Core.UserCommand;
using FileTime.GuiApp.App.Configuration;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace FileTime.GuiApp.App.Services; namespace FileTime.App.Core.Services;
public class KeyboardConfigurationService : IKeyboardConfigurationService public class KeyboardConfigurationService : IKeyboardConfigurationService
{ {
@@ -48,8 +48,7 @@ public class KeyboardConfigurationService : IKeyboardConfigurationService
} }
private static bool IsUniversal(CommandBindingConfiguration keyMapping) private static bool IsUniversal(CommandBindingConfiguration keyMapping)
{ => keyMapping.Command is
return keyMapping.Command is
GoUpCommand.CommandName GoUpCommand.CommandName
or OpenSelectedCommand.CommandName or OpenSelectedCommand.CommandName
or MoveCursorDownCommand.CommandName or MoveCursorDownCommand.CommandName
@@ -57,5 +56,4 @@ public class KeyboardConfigurationService : IKeyboardConfigurationService
or MoveCursorUpCommand.CommandName or MoveCursorUpCommand.CommandName
or MoveCursorUpPageCommand.CommandName or MoveCursorUpPageCommand.CommandName
or IdentifiableRunOrOpenCommand.CommandName; or IdentifiableRunOrOpenCommand.CommandName;
}
} }

View File

@@ -1,10 +1,9 @@
using FileTime.App.Core.Services;
using FileTime.Core.Extensions; using FileTime.Core.Extensions;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace FileTime.GuiApp.App.Services; namespace FileTime.App.Core.Services;
public class LifecycleService public class LifecycleService : ILifecycleService
{ {
private readonly IEnumerable<IExitHandler> _exitHandlers; private readonly IEnumerable<IExitHandler> _exitHandlers;
private readonly IEnumerable<IStartupHandler> _startupHandlers; private readonly IEnumerable<IStartupHandler> _startupHandlers;

View File

@@ -1,9 +1,8 @@
using DynamicData; using DynamicData;
using FileTime.App.Core.Services;
using FileTime.App.Core.ViewModels; using FileTime.App.Core.ViewModels;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace FileTime.GuiApp.App.Services; namespace FileTime.App.Core.Services;
public class ModalService : IModalService public class ModalService : IModalService
{ {

View File

@@ -26,6 +26,8 @@ public static class Startup
serviceCollection.TryAddSingleton<ITimelineViewModel, TimelineViewModel>(); serviceCollection.TryAddSingleton<ITimelineViewModel, TimelineViewModel>();
serviceCollection.TryAddSingleton<IRefreshSmoothnessCalculator, RefreshSmoothnessCalculator>(); serviceCollection.TryAddSingleton<IRefreshSmoothnessCalculator, RefreshSmoothnessCalculator>();
serviceCollection.TryAddSingleton<IItemPreviewProvider, ElementPreviewProvider>(); serviceCollection.TryAddSingleton<IItemPreviewProvider, ElementPreviewProvider>();
serviceCollection.TryAddSingleton<ILifecycleService, LifecycleService>();
serviceCollection.TryAddSingleton<IModalService, ModalService>();
return serviceCollection return serviceCollection
.AddCommandHandlers() .AddCommandHandlers()

View File

@@ -12,8 +12,4 @@
<ProjectReference Include="..\FileTime.App.FuzzyPanel.Abstraction\FileTime.App.FuzzyPanel.Abstraction.csproj" /> <ProjectReference Include="..\FileTime.App.FuzzyPanel.Abstraction\FileTime.App.FuzzyPanel.Abstraction.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.2" />
</ItemGroup>
</Project> </Project>

View File

@@ -1,4 +1,4 @@
using Avalonia.Input; using FileTime.App.Core.Models;
using FileTime.App.Core.ViewModels; using FileTime.App.Core.ViewModels;
using FileTime.App.FuzzyPanel; using FileTime.App.FuzzyPanel;
@@ -8,5 +8,5 @@ public interface IFrequencyNavigationViewModel : IFuzzyPanelViewModel<string>, I
{ {
IObservable<bool> ShowWindow { get; } IObservable<bool> ShowWindow { get; }
void Close(); void Close();
Task<bool> HandleKeyUp(KeyEventArgs keyEventArgs); Task<bool> HandleKeyUp(GeneralKeyEventArgs keyEventArgs);
} }

View File

@@ -1,4 +1,4 @@
using Avalonia.Input; using FileTime.App.Core.Models;
using FileTime.App.Core.Services; using FileTime.App.Core.Services;
using FileTime.App.Core.UserCommand; using FileTime.App.Core.UserCommand;
using FileTime.App.Core.ViewModels; using FileTime.App.Core.ViewModels;
@@ -30,11 +30,11 @@ public class FrequencyNavigationViewModel : FuzzyPanelViewModel<string>, IFreque
public void Close() public void Close()
=> _frequencyNavigationService.CloseNavigationWindow(); => _frequencyNavigationService.CloseNavigationWindow();
public async Task<bool> HandleKeyUp(KeyEventArgs keyEventArgs) public async Task<bool> HandleKeyUp(GeneralKeyEventArgs keyEventArgs)
{ {
if (keyEventArgs.Handled) return false; if (keyEventArgs.Handled) return false;
if (keyEventArgs.Key == Key.Enter) if (keyEventArgs.Key == Keys.Enter)
{ {
keyEventArgs.Handled = true; keyEventArgs.Handled = true;
var targetContainer = await _timelessContentProvider.GetItemByFullNameAsync(new FullName(SelectedItem), PointInTime.Present); var targetContainer = await _timelessContentProvider.GetItemByFullNameAsync(new FullName(SelectedItem), PointInTime.Present);
@@ -47,14 +47,14 @@ public class FrequencyNavigationViewModel : FuzzyPanelViewModel<string>, IFreque
return false; return false;
} }
public override async Task<bool> HandleKeyDown(KeyEventArgs keyEventArgs) public override async Task<bool> HandleKeyDown(GeneralKeyEventArgs keyEventArgs)
{ {
if (keyEventArgs.Handled) return false; if (keyEventArgs.Handled) return false;
var handled = await base.HandleKeyDown(keyEventArgs); var handled = await base.HandleKeyDown(keyEventArgs);
if (handled) return true; if (handled) return true;
if (keyEventArgs.Key == Key.Escape) if (keyEventArgs.Key == Keys.Escape)
{ {
keyEventArgs.Handled = true; keyEventArgs.Handled = true;
Close(); Close();

View File

@@ -8,7 +8,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.2" /> <ProjectReference Include="..\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,4 +1,4 @@
using Avalonia.Input; using FileTime.App.Core.Models;
namespace FileTime.App.FuzzyPanel; namespace FileTime.App.FuzzyPanel;
@@ -8,5 +8,5 @@ public interface IFuzzyPanelViewModel<TItem> where TItem : class
TItem? SelectedItem { get; } TItem? SelectedItem { get; }
string SearchText { get; set; } string SearchText { get; set; }
void UpdateFilteredMatches(); void UpdateFilteredMatches();
Task<bool> HandleKeyDown(KeyEventArgs keyEventArgs); Task<bool> HandleKeyDown(GeneralKeyEventArgs keyEventArgs);
} }

View File

@@ -7,7 +7,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.2" />
<PackageReference Include="PropertyChanged.SourceGenerator" Version="1.0.8"> <PackageReference Include="PropertyChanged.SourceGenerator" Version="1.0.8">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -1,5 +1,5 @@
using System.ComponentModel; using System.ComponentModel;
using Avalonia.Input; using FileTime.App.Core.Models;
using PropertyChanged.SourceGenerator; using PropertyChanged.SourceGenerator;
namespace FileTime.App.FuzzyPanel; namespace FileTime.App.FuzzyPanel;
@@ -44,9 +44,9 @@ public abstract partial class FuzzyPanelViewModel<TItem> : IFuzzyPanelViewModel<
public abstract void UpdateFilteredMatches(); public abstract void UpdateFilteredMatches();
public virtual Task<bool> HandleKeyDown(KeyEventArgs keyEventArgs) public virtual Task<bool> HandleKeyDown(GeneralKeyEventArgs keyEventArgs)
{ {
if (keyEventArgs.Key == Key.Down) if (keyEventArgs.Key == Keys.Down)
{ {
var nextItem = SelectedItem is null var nextItem = SelectedItem is null
? FilteredMatches.FirstOrDefault() ? FilteredMatches.FirstOrDefault()
@@ -60,7 +60,7 @@ public abstract partial class FuzzyPanelViewModel<TItem> : IFuzzyPanelViewModel<
return Task.FromResult(true); return Task.FromResult(true);
} }
else if (keyEventArgs.Key == Key.Up) else if (keyEventArgs.Key == Keys.Up)
{ {
var previousItem = SelectedItem is null var previousItem = SelectedItem is null
? FilteredMatches.LastOrDefault() ? FilteredMatches.LastOrDefault()

View File

@@ -2,7 +2,7 @@
using System.Collections; using System.Collections;
namespace CircularBuffer; namespace FileTime.Core.Collections;
#if (NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER) #if (NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER)
/// <summary> /// <summary>
@@ -490,7 +490,7 @@ public class CircularBuffer<T> : ICircularBuffer<T>
throw new ArgumentNullException(nameof(array)); throw new ArgumentNullException(nameof(array));
if (array.Length < _size) if (array.Length < _size)
throw new ArgumentException($"The number of elements in the source {nameof(CircularBuffer)} is greater than the available " + throw new ArgumentException($"The number of elements in the source {nameof(CircularBuffer<int>)} is greater than the available " +
"number of elements of the destination array.", nameof(array)); "number of elements of the destination array.", nameof(array));
CopyToInternal(array, 0); CopyToInternal(array, 0);
@@ -506,7 +506,7 @@ public class CircularBuffer<T> : ICircularBuffer<T>
throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} is less than the lower bound of {nameof(array)}."); throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} is less than the lower bound of {nameof(array)}.");
if (array.Length - index < _size) if (array.Length - index < _size)
throw new ArgumentException($"The number of elements in the source {nameof(CircularBuffer)} is greater than the available " + throw new ArgumentException($"The number of elements in the source {nameof(CircularBuffer<int>)} is greater than the available " +
"number of elements from index to the end of the destination array.", nameof(array)); "number of elements from index to the end of the destination array.", nameof(array));
CopyToInternal(array, index); CopyToInternal(array, index);
@@ -522,7 +522,7 @@ public class CircularBuffer<T> : ICircularBuffer<T>
throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} is less than the lower bound of {nameof(array)}."); throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} is less than the lower bound of {nameof(array)}.");
if (array.LongLength - index < _size) if (array.LongLength - index < _size)
throw new ArgumentException($"The number of elements in the source {nameof(CircularBuffer)} is greater than the available " + throw new ArgumentException($"The number of elements in the source {nameof(CircularBuffer<int>)} is greater than the available " +
"number of elements from index to the end of the destination array.", nameof(array)); "number of elements from index to the end of the destination array.", nameof(array));
CopyToInternal(array, index); CopyToInternal(array, index);
@@ -534,7 +534,7 @@ public class CircularBuffer<T> : ICircularBuffer<T>
public void CopyTo(Memory<T> memory) public void CopyTo(Memory<T> memory)
{ {
if (memory.Length < _size) if (memory.Length < _size)
throw new ArgumentException($"The number of elements in the source {nameof(CircularBuffer)} is greater than the available " + throw new ArgumentException($"The number of elements in the source {nameof(CircularBuffer<int>)} is greater than the available " +
"number of elements of the destination Memory.", nameof(memory)); "number of elements of the destination Memory.", nameof(memory));
CopyToInternal(memory); CopyToInternal(memory);
@@ -544,7 +544,7 @@ public class CircularBuffer<T> : ICircularBuffer<T>
public void CopyTo(Span<T> span) public void CopyTo(Span<T> span)
{ {
if (span.Length < _size) if (span.Length < _size)
throw new ArgumentException($"The number of elements in the source {nameof(CircularBuffer)} is greater than the available " + throw new ArgumentException($"The number of elements in the source {nameof(CircularBuffer<int>)} is greater than the available " +
"number of elements of the destination Span.", nameof(span)); "number of elements of the destination Span.", nameof(span));
CopyToInternal(span); CopyToInternal(span);

View File

@@ -1,8 +1,8 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using CircularBuffer;
using DeclarativeProperty; using DeclarativeProperty;
using DynamicData; using DynamicData;
using FileTime.App.Core.Services; using FileTime.App.Core.Services;
using FileTime.Core.Collections;
using FileTime.Core.Helper; using FileTime.Core.Helper;
using FileTime.Core.Models; using FileTime.Core.Models;
using FileTime.Core.Timeline; using FileTime.Core.Timeline;

View File

@@ -115,6 +115,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.App.ContainerSizeS
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.App.ContainerSizeScanner.Abstractions", "AppCommon\FileTime.App.ContainerSizeScanner.Abstractions\FileTime.App.ContainerSizeScanner.Abstractions.csproj", "{826AFD32-E36B-48BA-BC1E-1476B393CF24}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.App.ContainerSizeScanner.Abstractions", "AppCommon\FileTime.App.ContainerSizeScanner.Abstractions\FileTime.App.ContainerSizeScanner.Abstractions.csproj", "{826AFD32-E36B-48BA-BC1E-1476B393CF24}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.ConsoleUI.App.Abstractions", "ConsoleApp\FileTime.ConsoleUI.App.Abstractions\FileTime.ConsoleUI.App.Abstractions.csproj", "{81F44BBB-6F89-41B4-89F1-4A3204843DB5}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -309,6 +311,10 @@ Global
{826AFD32-E36B-48BA-BC1E-1476B393CF24}.Debug|Any CPU.Build.0 = Debug|Any CPU {826AFD32-E36B-48BA-BC1E-1476B393CF24}.Debug|Any CPU.Build.0 = Debug|Any CPU
{826AFD32-E36B-48BA-BC1E-1476B393CF24}.Release|Any CPU.ActiveCfg = Release|Any CPU {826AFD32-E36B-48BA-BC1E-1476B393CF24}.Release|Any CPU.ActiveCfg = Release|Any CPU
{826AFD32-E36B-48BA-BC1E-1476B393CF24}.Release|Any CPU.Build.0 = Release|Any CPU {826AFD32-E36B-48BA-BC1E-1476B393CF24}.Release|Any CPU.Build.0 = Release|Any CPU
{81F44BBB-6F89-41B4-89F1-4A3204843DB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{81F44BBB-6F89-41B4-89F1-4A3204843DB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81F44BBB-6F89-41B4-89F1-4A3204843DB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81F44BBB-6F89-41B4-89F1-4A3204843DB5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -362,6 +368,7 @@ Global
{EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44} = {8C3CFEFE-78A5-4940-B388-D15FCE02ECE9} {EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44} = {8C3CFEFE-78A5-4940-B388-D15FCE02ECE9}
{E5FD38ED-6E4B-42AA-850B-470B939B836B} = {A5291117-3001-498B-AC8B-E14F71F72570} {E5FD38ED-6E4B-42AA-850B-470B939B836B} = {A5291117-3001-498B-AC8B-E14F71F72570}
{826AFD32-E36B-48BA-BC1E-1476B393CF24} = {A5291117-3001-498B-AC8B-E14F71F72570} {826AFD32-E36B-48BA-BC1E-1476B393CF24} = {A5291117-3001-498B-AC8B-E14F71F72570}
{81F44BBB-6F89-41B4-89F1-4A3204843DB5} = {CAEEAD3C-41EB-405C-ACA9-BA1E4C352549}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {859FB3DF-C60A-46B1-82E5-90274905D1EF} SolutionGuid = {859FB3DF-C60A-46B1-82E5-90274905D1EF}

View File

@@ -0,0 +1,13 @@
using Avalonia.Input;
namespace FileTime.GuiApp.App.Models;
public class KeyNotSupportedException : Exception
{
private readonly Key _key;
public KeyNotSupportedException(Key key) : base($"Key {key} is not supported.")
{
_key = key;
}
}

View File

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

View File

@@ -1,7 +1,6 @@
using System.Globalization; using System.Globalization;
using Avalonia.Data.Converters; using Avalonia.Data.Converters;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Threading;
using FileTime.Core.Models; using FileTime.Core.Models;
using FileTime.GuiApp.App.ViewModels; using FileTime.GuiApp.App.ViewModels;

View File

@@ -0,0 +1,18 @@
using Avalonia.Input;
using FileTime.App.Core.Models;
using FileTime.App.Core.Services;
namespace FileTime.GuiApp.App.Extensions;
public static class KeyEventArgsExtension
{
public static GeneralKeyEventArgs? ToGeneralKeyEventArgs(this KeyEventArgs args, IAppKeyService<Key> appKeyService)
{
var maybeKey = appKeyService.MapKey(args.Key);
if (maybeKey is not {} key1) return null;
return new GeneralKeyEventArgs(h => args.Handled = h)
{
Key = key1
};
}
}

View File

@@ -5,12 +5,13 @@ using FileTime.App.Core.ViewModels;
using FileTime.Core.Extensions; using FileTime.Core.Extensions;
using FileTime.Core.Models; using FileTime.Core.Models;
using FileTime.Core.Models.Extensions; using FileTime.Core.Models.Extensions;
using FileTime.GuiApp.App.Configuration;
using FileTime.GuiApp.App.Extensions;
using FileTime.GuiApp.App.Models; using FileTime.GuiApp.App.Models;
using FileTime.GuiApp.App.ViewModels; using FileTime.GuiApp.App.ViewModels;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using DeclarativeProperty; using DeclarativeProperty;
using FileTime.App.Core.Configuration;
using FileTime.App.Core.Extensions;
using FileTime.App.Core.Models;
namespace FileTime.GuiApp.App.Services; namespace FileTime.GuiApp.App.Services;
@@ -24,6 +25,7 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
private readonly ILogger<DefaultModeKeyInputHandler> _logger; private readonly ILogger<DefaultModeKeyInputHandler> _logger;
private readonly IUserCommandHandlerService _userCommandHandlerService; private readonly IUserCommandHandlerService _userCommandHandlerService;
private readonly IIdentifiableUserCommandService _identifiableUserCommandService; private readonly IIdentifiableUserCommandService _identifiableUserCommandService;
private readonly IAppKeyService<Key> _appKeyService;
private readonly BindedCollection<IModalViewModel> _openModals; private readonly BindedCollection<IModalViewModel> _openModals;
public DefaultModeKeyInputHandler( public DefaultModeKeyInputHandler(
@@ -32,10 +34,12 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
IKeyboardConfigurationService keyboardConfigurationService, IKeyboardConfigurationService keyboardConfigurationService,
ILogger<DefaultModeKeyInputHandler> logger, ILogger<DefaultModeKeyInputHandler> logger,
IUserCommandHandlerService userCommandHandlerService, IUserCommandHandlerService userCommandHandlerService,
IIdentifiableUserCommandService identifiableUserCommandService) IIdentifiableUserCommandService identifiableUserCommandService,
IAppKeyService<Key> appKeyService)
{ {
_appState = appState; _appState = appState;
_identifiableUserCommandService = identifiableUserCommandService; _identifiableUserCommandService = identifiableUserCommandService;
_appKeyService = appKeyService;
_keyboardConfigurationService = keyboardConfigurationService; _keyboardConfigurationService = keyboardConfigurationService;
_logger = logger; _logger = logger;
_modalService = modalService; _modalService = modalService;
@@ -47,25 +51,26 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
_openModals = modalService.OpenModals.ToBindedCollection(); _openModals = modalService.OpenModals.ToBindedCollection();
_keysToSkip.Add(new[] {new KeyConfig(Key.Up)}); _keysToSkip.Add(new[] {new KeyConfig(Keys.Up)});
_keysToSkip.Add(new[] {new KeyConfig(Key.Down)}); _keysToSkip.Add(new[] {new KeyConfig(Keys.Down)});
_keysToSkip.Add(new[] {new KeyConfig(Key.Tab)}); _keysToSkip.Add(new[] {new KeyConfig(Keys.Tab)});
_keysToSkip.Add(new[] {new KeyConfig(Key.PageDown)}); _keysToSkip.Add(new[] {new KeyConfig(Keys.PageDown)});
_keysToSkip.Add(new[] {new KeyConfig(Key.PageUp)}); _keysToSkip.Add(new[] {new KeyConfig(Keys.PageUp)});
_keysToSkip.Add(new[] {new KeyConfig(Key.F4, alt: true)}); _keysToSkip.Add(new[] {new KeyConfig(Keys.F4, alt: true)});
_keysToSkip.Add(new[] {new KeyConfig(Key.LWin)}); _keysToSkip.Add(new[] {new KeyConfig(Keys.LWin)});
_keysToSkip.Add(new[] {new KeyConfig(Key.RWin)}); _keysToSkip.Add(new[] {new KeyConfig(Keys.RWin)});
} }
public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action<bool> setHandled) public async Task HandleInputKey(Key key2, SpecialKeysStatus specialKeysStatus, Action<bool> setHandled)
{ {
if (_appKeyService.MapKey(key2) is not { } key) return;
var keyWithModifiers = new KeyConfig(key, shift: specialKeysStatus.IsShiftPressed, alt: specialKeysStatus.IsAltPressed, ctrl: specialKeysStatus.IsCtrlPressed); var keyWithModifiers = new KeyConfig(key, shift: specialKeysStatus.IsShiftPressed, alt: specialKeysStatus.IsAltPressed, ctrl: specialKeysStatus.IsCtrlPressed);
_appState.PreviousKeys.Add(keyWithModifiers); _appState.PreviousKeys.Add(keyWithModifiers);
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys)); var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
selectedCommandBinding ??= _keyboardConfigurationService.CommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys)); selectedCommandBinding ??= _keyboardConfigurationService.CommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
if (key == Key.Escape) if (key == Keys.Escape)
{ {
var doGeneralReset = _appState.PreviousKeys.Count > 1 || _appState.IsAllShortcutVisible; var doGeneralReset = _appState.PreviousKeys.Count > 1 || _appState.IsAllShortcutVisible;

View File

@@ -0,0 +1,83 @@
using System.Collections.ObjectModel;
using Avalonia.Input;
using FileTime.App.Core.Models;
using FileTime.App.Core.Services;
using FileTime.GuiApp.App.Models;
namespace FileTime.GuiApp.App.Services;
public class GuiAppKeyService : IAppKeyService<Key>
{
private static readonly Dictionary<Key, Keys> KeyMapping;
//TODO: write test for this. Test if every enum value is present in the dictionary.
public static ReadOnlyDictionary<Key, Keys> KeyMappingReadOnly { get; }
static GuiAppKeyService()
{
KeyMapping = new Dictionary<Key, Keys>
{
{Key.A, Keys.A},
{Key.B, Keys.B},
{Key.C, Keys.C},
{Key.D, Keys.D},
{Key.E, Keys.E},
{Key.F, Keys.F},
{Key.G, Keys.G},
{Key.H, Keys.H},
{Key.I, Keys.I},
{Key.J, Keys.J},
{Key.K, Keys.K},
{Key.L, Keys.L},
{Key.M, Keys.M},
{Key.N, Keys.N},
{Key.O, Keys.O},
{Key.P, Keys.P},
{Key.Q, Keys.Q},
{Key.R, Keys.R},
{Key.S, Keys.S},
{Key.T, Keys.T},
{Key.U, Keys.U},
{Key.V, Keys.V},
{Key.W, Keys.W},
{Key.X, Keys.X},
{Key.Y, Keys.Y},
{Key.Z, Keys.Z},
{Key.F1, Keys.F1},
{Key.F2, Keys.F2},
{Key.F3, Keys.F3},
{Key.F4, Keys.F4},
{Key.F5, Keys.F5},
{Key.F6, Keys.F6},
{Key.F7, Keys.F7},
{Key.F8, Keys.F8},
{Key.F9, Keys.F9},
{Key.F10, Keys.F10},
{Key.F11, Keys.F11},
{Key.F12, Keys.F12},
{Key.Up, Keys.Up},
{Key.Down, Keys.Down},
{Key.Left, Keys.Left},
{Key.Right, Keys.Right},
{Key.Enter, Keys.Enter},
{Key.Escape, Keys.Escape},
{Key.Back, Keys.Back},
{Key.Space, Keys.Space},
{Key.PageUp, Keys.PageUp},
{Key.PageDown, Keys.PageDown},
{Key.OemComma, Keys.Comma},
{Key.OemQuestion, Keys.Question},
{Key.Tab, Keys.Tab},
{Key.LWin, Keys.LWin},
{Key.RWin, Keys.RWin},
};
KeyMappingReadOnly = new(KeyMapping);
}
public Keys? MapKey(Key key)
{
if (!KeyMapping.TryGetValue(key, out var mappedKey)) return null;
return mappedKey;
}
}

View File

@@ -1,12 +1,12 @@
using Avalonia.Input; using Avalonia.Input;
using FileTime.App.Core.Configuration;
using FileTime.App.Core.Extensions;
using FileTime.App.Core.Models;
using FileTime.App.Core.Services; using FileTime.App.Core.Services;
using FileTime.App.Core.UserCommand; using FileTime.App.Core.UserCommand;
using FileTime.App.Core.ViewModels; using FileTime.App.Core.ViewModels;
using FileTime.Core.Extensions; using FileTime.Core.Extensions;
using FileTime.Core.Models; using FileTime.Core.Models;
using FileTime.Core.Services;
using FileTime.GuiApp.App.Configuration;
using FileTime.GuiApp.App.Extensions;
using FileTime.GuiApp.App.Models; using FileTime.GuiApp.App.Models;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -22,6 +22,7 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
private readonly IUserCommandHandlerService _userCommandHandlerService; private readonly IUserCommandHandlerService _userCommandHandlerService;
private readonly ILogger<RapidTravelModeKeyInputHandler> _logger; private readonly ILogger<RapidTravelModeKeyInputHandler> _logger;
private readonly IIdentifiableUserCommandService _identifiableUserCommandService; private readonly IIdentifiableUserCommandService _identifiableUserCommandService;
private readonly IAppKeyService<Key> _appKeyService;
private readonly BindedCollection<IModalViewModel> _openModals; private readonly BindedCollection<IModalViewModel> _openModals;
private ITabViewModel? _selectedTab; private ITabViewModel? _selectedTab;
@@ -31,7 +32,8 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
IKeyboardConfigurationService keyboardConfigurationService, IKeyboardConfigurationService keyboardConfigurationService,
IUserCommandHandlerService userCommandHandlerService, IUserCommandHandlerService userCommandHandlerService,
ILogger<RapidTravelModeKeyInputHandler> logger, ILogger<RapidTravelModeKeyInputHandler> logger,
IIdentifiableUserCommandService identifiableUserCommandService) IIdentifiableUserCommandService identifiableUserCommandService,
IAppKeyService<Key> appKeyService)
{ {
_appState = appState; _appState = appState;
_modalService = modalService; _modalService = modalService;
@@ -39,6 +41,7 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
_userCommandHandlerService = userCommandHandlerService; _userCommandHandlerService = userCommandHandlerService;
_logger = logger; _logger = logger;
_identifiableUserCommandService = identifiableUserCommandService; _identifiableUserCommandService = identifiableUserCommandService;
_appKeyService = appKeyService;
_appState.SelectedTab.Subscribe(t => _selectedTab = t); _appState.SelectedTab.Subscribe(t => _selectedTab = t);
@@ -56,11 +59,12 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
}); });
} }
public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action<bool> setHandled) public async Task HandleInputKey(Key key2, SpecialKeysStatus specialKeysStatus, Action<bool> setHandled)
{ {
if (_appKeyService.MapKey(key2) is not { } key) return;
var keyString = key.ToString(); var keyString = key.ToString();
if (key == Key.Escape) if (key == Keys.Escape)
{ {
setHandled(true); setHandled(true);
if ((_openModals.Collection?.Count ?? 0) > 0) if ((_openModals.Collection?.Count ?? 0) > 0)
@@ -72,7 +76,7 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
await CallCommandAsync(ExitRapidTravelCommand.Instance); await CallCommandAsync(ExitRapidTravelCommand.Instance);
} }
} }
else if (key == Key.Back) else if (key == Keys.Back)
{ {
if (_appState.RapidTravelText.Value!.Length > 0) if (_appState.RapidTravelText.Value!.Length > 0)
{ {
@@ -91,7 +95,7 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
} }
else else
{ {
var currentKeyAsList = new List<KeyConfig>() {new KeyConfig(key)}; var currentKeyAsList = new List<KeyConfig> {new(key)};
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(currentKeyAsList)); var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(currentKeyAsList));
if (selectedCommandBinding != null) if (selectedCommandBinding != null)
{ {

View File

@@ -1,5 +1,4 @@
using DeclarativeProperty; using FileTime.App.CommandPalette.Services;
using FileTime.App.CommandPalette.Services;
using FileTime.App.Core.Services; using FileTime.App.Core.Services;
using FileTime.App.Core.ViewModels; using FileTime.App.Core.ViewModels;
using FileTime.App.FrequencyNavigation.Services; using FileTime.App.FrequencyNavigation.Services;

View File

@@ -24,7 +24,7 @@ namespace FileTime.GuiApp.App.ViewModels;
[Inject(typeof(ILogger<MainWindowViewModel>), PropertyName = "_logger")] [Inject(typeof(ILogger<MainWindowViewModel>), PropertyName = "_logger")]
[Inject(typeof(IKeyInputHandlerService), PropertyName = "_keyInputHandlerService")] [Inject(typeof(IKeyInputHandlerService), PropertyName = "_keyInputHandlerService")]
[Inject(typeof(IUserCommandHandlerService), PropertyAccessModifier = AccessModifier.Public)] [Inject(typeof(IUserCommandHandlerService), PropertyAccessModifier = AccessModifier.Public)]
[Inject(typeof(LifecycleService), PropertyName = "_lifecycleService")] [Inject(typeof(ILifecycleService), PropertyName = "_lifecycleService")]
[Inject(typeof(IItemPreviewService), PropertyAccessModifier = AccessModifier.Public)] [Inject(typeof(IItemPreviewService), PropertyAccessModifier = AccessModifier.Public)]
[Inject(typeof(IDialogService), PropertyAccessModifier = AccessModifier.Public)] [Inject(typeof(IDialogService), PropertyAccessModifier = AccessModifier.Public)]
[Inject(typeof(ITimelessContentProvider), PropertyName = "_timelessContentProvider")] [Inject(typeof(ITimelessContentProvider), PropertyName = "_timelessContentProvider")]

View File

@@ -2,11 +2,16 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using FileTime.App.CommandPalette.ViewModels; using FileTime.App.CommandPalette.ViewModels;
using FileTime.App.Core.Services;
using FileTime.GuiApp.App.Extensions;
using Microsoft.Extensions.DependencyInjection;
namespace FileTime.GuiApp.App.Views; namespace FileTime.GuiApp.App.Views;
public partial class CommandPalette : UserControl public partial class CommandPalette : UserControl
{ {
private readonly Lazy<IAppKeyService<Key>> _appKeyService = new(() => DI.ServiceProvider.GetRequiredService<IAppKeyService<Key>>());
public CommandPalette() public CommandPalette()
{ {
InitializeComponent(); InitializeComponent();
@@ -34,14 +39,18 @@ public partial class CommandPalette : UserControl
} }
else else
{ {
viewModel.HandleKeyDown(e); if (e.ToGeneralKeyEventArgs(_appKeyService.Value) is not { } eventArgs) return;
viewModel.HandleKeyDown(eventArgs);
} }
} }
private void Search_OnKeyUp(object? sender, KeyEventArgs e) private void Search_OnKeyUp(object? sender, KeyEventArgs e)
{ {
if (e.Handled) return; if (e.Handled
if (DataContext is not ICommandPaletteViewModel viewModel) return; || DataContext is not ICommandPaletteViewModel viewModel) return;
viewModel.HandleKeyUp(e);
if (e.ToGeneralKeyEventArgs(_appKeyService.Value) is not { } eventArgs) return;
viewModel.HandleKeyUp(eventArgs);
} }
} }

View File

@@ -1,12 +1,17 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using FileTime.App.Core.Services;
using FileTime.App.FrequencyNavigation.ViewModels; using FileTime.App.FrequencyNavigation.ViewModels;
using FileTime.GuiApp.App.Extensions;
using Microsoft.Extensions.DependencyInjection;
namespace FileTime.GuiApp.App.Views; namespace FileTime.GuiApp.App.Views;
public partial class FrequencyNavigation : UserControl public partial class FrequencyNavigation : UserControl
{ {
private readonly Lazy<IAppKeyService<Key>> _appKeyService = new(() => DI.ServiceProvider.GetRequiredService<IAppKeyService<Key>>());
public FrequencyNavigation() public FrequencyNavigation()
{ {
InitializeComponent(); InitializeComponent();
@@ -34,14 +39,18 @@ public partial class FrequencyNavigation : UserControl
} }
else else
{ {
viewModel.HandleKeyDown(e); if (e.ToGeneralKeyEventArgs(_appKeyService.Value) is not { } eventArgs) return;
viewModel.HandleKeyDown(eventArgs);
} }
} }
private void Search_OnKeyUp(object? sender, KeyEventArgs e) private void Search_OnKeyUp(object? sender, KeyEventArgs e)
{ {
if (e.Handled) return; if (e.Handled
if (DataContext is not IFrequencyNavigationViewModel viewModel) return; || DataContext is not IFrequencyNavigationViewModel viewModel) return;
viewModel.HandleKeyUp(e);
if (e.ToGeneralKeyEventArgs(_appKeyService.Value) is not { } eventArgs) return;
viewModel.HandleKeyUp(eventArgs);
} }
} }

View File

@@ -23,6 +23,7 @@
xmlns:appCoreModels="using:FileTime.App.Core.Models" xmlns:appCoreModels="using:FileTime.App.Core.Models"
xmlns:appInteractions="using:FileTime.App.Core.Interactions" xmlns:appInteractions="using:FileTime.App.Core.Interactions"
xmlns:config="using:FileTime.GuiApp.App.Configuration" xmlns:config="using:FileTime.GuiApp.App.Configuration"
xmlns:configuration="clr-namespace:FileTime.App.Core.Configuration;assembly=FileTime.App.Core.Abstraction"
xmlns:corevm="using:FileTime.App.Core.ViewModels" xmlns:corevm="using:FileTime.App.Core.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity" xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"
@@ -764,7 +765,7 @@
<ItemsRepeater Grid.Row="1" ItemsSource="{Binding AppState.PossibleCommands}"> <ItemsRepeater Grid.Row="1" ItemsSource="{Binding AppState.PossibleCommands}">
<ItemsRepeater.ItemTemplate> <ItemsRepeater.ItemTemplate>
<DataTemplate x:DataType="config:CommandBindingConfiguration"> <DataTemplate x:DataType="configuration:CommandBindingConfiguration">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="200" /> <ColumnDefinition Width="200" />

View File

@@ -1,9 +1,10 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Reactive.Subjects; using System.Reactive.Subjects;
using Avalonia.Input;
using FileTime.App.Core.Configuration;
using FileTime.App.Core.ViewModels; using FileTime.App.Core.ViewModels;
using FileTime.App.Core.ViewModels.Timeline; using FileTime.App.Core.ViewModels.Timeline;
using FileTime.GuiApp.App.Configuration;
using FileTime.GuiApp.App.Models; using FileTime.GuiApp.App.Models;
using FileTime.GuiApp.App.ViewModels; using FileTime.GuiApp.App.ViewModels;
using MvvmGen; using MvvmGen;

View File

@@ -3,7 +3,7 @@ using FileTime.GuiApp.App.Services;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace FileTime.GuiApp.Font; namespace FileTime.GuiApp.App.Font;
public static class Startup public static class Startup
{ {

View File

@@ -6,9 +6,9 @@ using FileTime.App.DependencyInjection;
using FileTime.App.FrequencyNavigation; using FileTime.App.FrequencyNavigation;
using FileTime.App.Search; using FileTime.App.Search;
using FileTime.GuiApp.App; using FileTime.GuiApp.App;
using FileTime.GuiApp.App.Font;
using FileTime.GuiApp.App.ViewModels; using FileTime.GuiApp.App.ViewModels;
using FileTime.GuiApp.App.Views; using FileTime.GuiApp.App.Views;
using FileTime.GuiApp.Font;
using FileTime.Server.Common; using FileTime.Server.Common;
using FileTime.Tools.Compression; using FileTime.Tools.Compression;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;

View File

@@ -1,5 +1,7 @@
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Avalonia.Input;
using FileTime.App.Core.Configuration;
using FileTime.App.Core.Services; using FileTime.App.Core.Services;
using FileTime.App.Core.ViewModels; using FileTime.App.Core.ViewModels;
using FileTime.Core.Interactions; using FileTime.Core.Interactions;
@@ -54,14 +56,13 @@ public static class Startup
serviceCollection.TryAddSingleton<IDefaultModeKeyInputHandler, DefaultModeKeyInputHandler>(); serviceCollection.TryAddSingleton<IDefaultModeKeyInputHandler, DefaultModeKeyInputHandler>();
serviceCollection.TryAddSingleton<IKeyboardConfigurationService, KeyboardConfigurationService>(); serviceCollection.TryAddSingleton<IKeyboardConfigurationService, KeyboardConfigurationService>();
serviceCollection.TryAddSingleton<IRapidTravelModeKeyInputHandler, RapidTravelModeKeyInputHandler>(); serviceCollection.TryAddSingleton<IRapidTravelModeKeyInputHandler, RapidTravelModeKeyInputHandler>();
serviceCollection.TryAddSingleton<LifecycleService>();
serviceCollection.TryAddSingleton<IIconProvider, MaterialIconProvider>(); serviceCollection.TryAddSingleton<IIconProvider, MaterialIconProvider>();
serviceCollection.TryAddSingleton<IModalService, ModalService>();
serviceCollection.TryAddSingleton<IDialogService, DialogService>(); serviceCollection.TryAddSingleton<IDialogService, DialogService>();
serviceCollection.TryAddSingleton<SystemClipboardService>(); serviceCollection.TryAddSingleton<SystemClipboardService>();
serviceCollection.TryAddSingleton<ISystemClipboardService>(sp => sp.GetRequiredService<SystemClipboardService>()); serviceCollection.TryAddSingleton<ISystemClipboardService>(sp => sp.GetRequiredService<SystemClipboardService>());
serviceCollection.TryAddSingleton<ToastMessageSink>(); serviceCollection.TryAddSingleton<ToastMessageSink>();
serviceCollection.TryAddSingleton<IUserCommunicationService>(s => s.GetRequiredService<IDialogService>()); serviceCollection.TryAddSingleton<IUserCommunicationService>(s => s.GetRequiredService<IDialogService>());
serviceCollection.TryAddSingleton<IAppKeyService<Key>, GuiAppKeyService>();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {