Keyboard shortcuts dialog.

This commit is contained in:
Burak Kaan Köse
2025-10-29 16:26:46 +01:00
parent abaab18eb7
commit b44fb5c45a
25 changed files with 1112 additions and 4 deletions
@@ -0,0 +1,86 @@
using System;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
namespace Wino.Core.ViewModels.Data;
/// <summary>
/// ViewModel wrapper for KeyboardShortcut entity.
/// </summary>
public partial class KeyboardShortcutViewModel : ObservableObject
{
[ObservableProperty]
private bool isEnabled;
public Guid Id { get; }
public string Key { get; }
public ModifierKeys ModifierKeys { get; }
public MailOperation MailOperation { get; }
public DateTime CreatedAt { get; }
public string DisplayName
{
get
{
var modifierText = string.Empty;
if (ModifierKeys.HasFlag(ModifierKeys.Control))
modifierText += "Ctrl+";
if (ModifierKeys.HasFlag(ModifierKeys.Alt))
modifierText += "Alt+";
if (ModifierKeys.HasFlag(ModifierKeys.Shift))
modifierText += "Shift+";
if (ModifierKeys.HasFlag(ModifierKeys.Windows))
modifierText += "Win+";
return modifierText + Key;
}
}
public string MailOperationDisplayName
{
get
{
return MailOperation switch
{
MailOperation.Archive => "Archive",
MailOperation.UnArchive => "Unarchive",
MailOperation.SoftDelete => "Delete",
MailOperation.Move => "Move",
MailOperation.MoveToJunk => "Move to Junk",
MailOperation.SetFlag => "Set Flag",
MailOperation.ClearFlag => "Clear Flag",
MailOperation.MarkAsRead => "Mark as Read",
MailOperation.MarkAsUnread => "Mark as Unread",
MailOperation.Reply => "Reply",
MailOperation.ReplyAll => "Reply All",
MailOperation.Forward => "Forward",
_ => MailOperation.ToString()
};
}
}
public KeyboardShortcutViewModel(KeyboardShortcut shortcut)
{
Id = shortcut.Id;
Key = shortcut.Key;
ModifierKeys = shortcut.ModifierKeys;
MailOperation = shortcut.MailOperation;
CreatedAt = shortcut.CreatedAt;
IsEnabled = shortcut.IsEnabled;
}
public KeyboardShortcut ToEntity()
{
return new KeyboardShortcut
{
Id = Id,
Key = Key,
ModifierKeys = ModifierKeys,
MailOperation = MailOperation,
CreatedAt = CreatedAt,
IsEnabled = IsEnabled
};
}
}
@@ -0,0 +1,42 @@
using Wino.Core.Domain;
using Wino.Core.Domain.Enums;
namespace Wino.Core.ViewModels.Data;
/// <summary>
/// ViewModel for displaying mail operations in dropdowns/lists.
/// </summary>
public class MailOperationViewModel
{
public MailOperation Operation { get; }
public string DisplayName
{
get
{
return Operation switch
{
MailOperation.Archive => "Archive",
MailOperation.UnArchive => "Unarchive",
MailOperation.SoftDelete => "Delete",
MailOperation.Move => "Move",
MailOperation.MoveToJunk => "Move to Junk",
MailOperation.SetFlag => "Set Flag",
MailOperation.ClearFlag => "Clear Flag",
MailOperation.MarkAsRead => "Mark as Read",
MailOperation.MarkAsUnread => "Mark as Unread",
MailOperation.Reply => "Reply",
MailOperation.ReplyAll => "Reply All",
MailOperation.Forward => "Forward",
_ => Operation.ToString()
};
}
}
public MailOperationViewModel(MailOperation operation)
{
Operation = operation;
}
public override string ToString() => DisplayName;
}
@@ -0,0 +1,179 @@
using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Navigation;
using Wino.Core.ViewModels.Data;
namespace Wino.Core.ViewModels;
/// <summary>
/// ViewModel for managing keyboard shortcuts settings.
/// </summary>
public partial class KeyboardShortcutsPageViewModel : CoreBaseViewModel
{
private readonly IKeyboardShortcutService _keyboardShortcutService;
private readonly IMailDialogService _dialogService;
[ObservableProperty]
public partial ObservableCollection<KeyboardShortcutViewModel> Shortcuts { get; set; } = new();
public KeyboardShortcutsPageViewModel(IKeyboardShortcutService keyboardShortcutService,
IMailDialogService dialogService)
{
_keyboardShortcutService = keyboardShortcutService;
_dialogService = dialogService;
}
public override async void OnNavigatedTo(NavigationMode mode, object parameters)
{
base.OnNavigatedTo(mode, parameters);
await LoadShortcutsAsync();
}
[RelayCommand]
private async Task LoadShortcutsAsync()
{
try
{
var keyboardShortcuts = await _keyboardShortcutService.GetKeyboardShortcutsAsync();
Shortcuts.Clear();
foreach (var shortcut in keyboardShortcuts)
{
Shortcuts.Add(new KeyboardShortcutViewModel(shortcut));
}
}
catch (Exception ex)
{
await _dialogService.ShowMessageAsync(
Translator.KeyboardShortcuts_FailedToLoad,
Translator.GeneralTitle_Error,
WinoCustomMessageDialogIcon.Error);
}
}
[RelayCommand]
private async Task StartAddingShortcutAsync()
{
var result = await _dialogService.ShowKeyboardShortcutDialogAsync();
if (result.IsSuccess)
{
try
{
// Check if key combination is already in use
var isInUse = await _keyboardShortcutService.IsKeyCombinationInUseAsync(result.Key, result.ModifierKeys, null);
if (isInUse)
{
await _dialogService.ShowMessageAsync(Translator.KeyboardShortcuts_ShortcutInUse, Translator.GeneralTitle_Error, WinoCustomMessageDialogIcon.Error);
return;
}
// Create new shortcut
var shortcut = new KeyboardShortcut
{
Key = result.Key,
ModifierKeys = result.ModifierKeys,
MailOperation = result.MailOperation,
IsEnabled = true
};
await _keyboardShortcutService.SaveKeyboardShortcutAsync(shortcut);
await LoadShortcutsAsync();
}
catch (Exception ex)
{
await _dialogService.ShowMessageAsync(
Translator.KeyboardShortcuts_FailedToSave,
Translator.GeneralTitle_Error,
WinoCustomMessageDialogIcon.Error);
}
}
}
[RelayCommand]
private async Task StartEditingShortcutAsync(KeyboardShortcutViewModel shortcut)
{
if (shortcut == null) return;
var dialogService = _dialogService as IMailDialogService;
if (dialogService == null) return;
var existingShortcut = shortcut.ToEntity();
var result = await dialogService.ShowKeyboardShortcutDialogAsync(existingShortcut);
if (result.IsSuccess)
{
try
{
// Check if key combination is already in use (excluding current shortcut)
var isInUse = await _keyboardShortcutService.IsKeyCombinationInUseAsync(result.Key, result.ModifierKeys, shortcut.Id);
if (isInUse)
{
await _dialogService.ShowMessageAsync(Translator.KeyboardShortcuts_ShortcutInUse, Translator.GeneralTitle_Error, WinoCustomMessageDialogIcon.Error);
return;
}
// Update existing shortcut
var updatedShortcut = shortcut.ToEntity();
updatedShortcut.Key = result.Key;
updatedShortcut.ModifierKeys = result.ModifierKeys;
updatedShortcut.MailOperation = result.MailOperation;
await _keyboardShortcutService.SaveKeyboardShortcutAsync(updatedShortcut);
await LoadShortcutsAsync();
}
catch (Exception ex)
{
await _dialogService.ShowMessageAsync(
Translator.KeyboardShortcuts_FailedToUpdate,
Translator.GeneralTitle_Error,
WinoCustomMessageDialogIcon.Error);
}
}
}
[RelayCommand]
private async Task DeleteShortcutAsync(KeyboardShortcutViewModel shortcut)
{
if (shortcut == null) return;
try
{
await _keyboardShortcutService.DeleteKeyboardShortcutAsync(shortcut.Id);
await LoadShortcutsAsync();
}
catch (Exception ex)
{
await _dialogService.ShowMessageAsync(
Translator.KeyboardShortcuts_FailedToDelete,
Translator.GeneralTitle_Error,
WinoCustomMessageDialogIcon.Error);
}
}
[RelayCommand]
private async Task ResetToDefaultsAsync()
{
try
{
await _keyboardShortcutService.ResetToDefaultShortcutsAsync();
await LoadShortcutsAsync();
}
catch (Exception ex)
{
await _dialogService.ShowMessageAsync(
Translator.KeyboardShortcuts_FailedToReset,
Translator.GeneralTitle_Error,
WinoCustomMessageDialogIcon.Error);
}
}
}
@@ -38,6 +38,7 @@ public partial class SettingOptionsPageViewModel : CoreBaseViewModel
WinoPage.LanguageTimePage => Translator.SettingsLanguageTime_Title,
WinoPage.AppPreferencesPage => Translator.SettingsAppPreferences_Title,
WinoPage.CalendarSettingsPage => Translator.SettingsCalendarSettings_Title,
WinoPage.KeyboardShortcutsPage => "Keyboard Shortcuts",
_ => throw new NotImplementedException()
};