136 lines
4.5 KiB
C#
136 lines
4.5 KiB
C#
using Avalonia.Controls;
|
|
using Avalonia.Input;
|
|
using Avalonia.Threading;
|
|
using LehrerApp.Desktop.Services;
|
|
using LehrerApp.Desktop.ViewModels;
|
|
using LehrerApp.Sync;
|
|
|
|
namespace LehrerApp.Desktop.Views;
|
|
|
|
public partial class MainWindow : Window
|
|
{
|
|
private static readonly TimeSpan FinalSyncDelay = TimeSpan.FromMilliseconds(350);
|
|
private SyncEngine? _syncEngine;
|
|
private bool _finalSyncStarted;
|
|
private bool _closeAfterFinalSync;
|
|
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
PointerMoved += (_, _) => NotifyActivity();
|
|
PointerPressed += (_, _) => NotifyActivity();
|
|
KeyDown += (_, _) => NotifyActivity();
|
|
KeyDown += OnWindowKeyDown;
|
|
}
|
|
|
|
private void OnWindowKeyDown(object? sender, KeyEventArgs e)
|
|
{
|
|
if (DataContext is not MainWindowViewModel vm) return;
|
|
|
|
var commandModifier = (e.KeyModifiers & (KeyModifiers.Control | KeyModifiers.Meta)) != 0;
|
|
if (commandModifier && e.Key == Key.K)
|
|
{
|
|
vm.OpenCommandPaletteCommand.Execute(null);
|
|
FocusCommandPalette();
|
|
e.Handled = true;
|
|
return;
|
|
}
|
|
|
|
if (!vm.IsCommandPaletteOpen) return;
|
|
if (e.Key == Key.Escape)
|
|
{
|
|
vm.CloseCommandPaletteCommand.Execute(null);
|
|
e.Handled = true;
|
|
}
|
|
else if (e.Key == Key.Enter)
|
|
{
|
|
vm.CommandPalette.ExecuteCommand.Execute(vm.CommandPalette.SelectedResult);
|
|
e.Handled = true;
|
|
}
|
|
else if (e.Key is Key.Down or Key.Up)
|
|
{
|
|
MoveCommandPaletteSelection(vm, e.Key == Key.Down ? 1 : -1);
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void OnOpenCommandPaletteClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
|
|
{
|
|
if (DataContext is MainWindowViewModel vm)
|
|
vm.OpenCommandPaletteCommand.Execute(null);
|
|
FocusCommandPalette();
|
|
}
|
|
|
|
private void FocusCommandPalette() => Dispatcher.UIThread.Post(() =>
|
|
{
|
|
if (this.FindControl<TextBox>("CommandPaletteSearchBox") is { } search)
|
|
{
|
|
search.Focus();
|
|
search.SelectAll();
|
|
}
|
|
});
|
|
|
|
private static void MoveCommandPaletteSelection(MainWindowViewModel vm, int delta)
|
|
{
|
|
var results = vm.CommandPalette.Results;
|
|
if (results.Count == 0) return;
|
|
var current = vm.CommandPalette.SelectedResult is { } selected ? results.IndexOf(selected) : -1;
|
|
vm.CommandPalette.SelectedResult = results[Math.Clamp(current + delta, 0, results.Count - 1)];
|
|
}
|
|
|
|
public void EnableFinalSync(SyncEngine syncEngine)
|
|
{
|
|
_syncEngine = syncEngine;
|
|
Closing += OnClosing;
|
|
}
|
|
|
|
/// <summary>Wendet die zuletzt gespeicherte Fenstergröße an und merkt sich die aktuelle beim
|
|
/// Schließen (14.6). Eigenständig von <see cref="EnableFinalSync"/> verdrahtet (mehrere
|
|
/// Closing-Handler sind unproblematisch) und immer aktiv, auch ohne konfigurierten
|
|
/// Sync-Server.</summary>
|
|
public void EnableWindowSizePersistence(WindowSettingsService settings)
|
|
{
|
|
var saved = settings.Load();
|
|
Width = saved.Width;
|
|
Height = saved.Height;
|
|
if (saved.IsMaximized) WindowState = WindowState.Maximized;
|
|
|
|
Closing += (_, _) =>
|
|
{
|
|
var current = settings.Load();
|
|
settings.Save(new WindowSettings
|
|
{
|
|
IsMaximized = WindowState == WindowState.Maximized,
|
|
// Im maximierten Zustand spiegeln Width/Height die Bildschirmgröße wider, nicht
|
|
// die zuletzt genutzte Normalgröße - dann den vorherigen Wert beibehalten statt
|
|
// ihn zu überschreiben.
|
|
Width = WindowState == WindowState.Normal ? Width : current.Width,
|
|
Height = WindowState == WindowState.Normal ? Height : current.Height,
|
|
});
|
|
};
|
|
}
|
|
|
|
private async void OnClosing(object? sender, WindowClosingEventArgs e)
|
|
{
|
|
if (_closeAfterFinalSync || _finalSyncStarted || _syncEngine is null)
|
|
return;
|
|
|
|
e.Cancel = true;
|
|
_finalSyncStarted = true;
|
|
await _syncEngine.SyncBeforeShutdownAsync(FinalSyncDelay);
|
|
_closeAfterFinalSync = true;
|
|
Close();
|
|
}
|
|
|
|
private void NotifyActivity()
|
|
{
|
|
if (DataContext is MainWindowViewModel vm) vm.AppLock.NotifyActivity();
|
|
}
|
|
|
|
private void OnLockScreenKeyDown(object? sender, KeyEventArgs e)
|
|
{
|
|
if (e.Key == Key.Enter && DataContext is MainWindowViewModel vm)
|
|
vm.AppLock.UnlockCommand.Execute(null);
|
|
}
|
|
}
|