Keyboard shortcuts dialog.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.KeyboardShortcutDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:data="using:Wino.Core.ViewModels.Data"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:local="using:Wino.Dialogs"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Title="{x:Bind domain:Translator.KeyboardShortcuts_Add}"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonClick="SaveClicked"
|
||||
PrimaryButtonText="{x:Bind domain:Translator.Buttons_Save}"
|
||||
SecondaryButtonText="{x:Bind domain:Translator.Buttons_Cancel}"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid MinWidth="400" MinHeight="300">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Mail Operation -->
|
||||
<StackPanel Grid.Row="0" Margin="0,0,0,16">
|
||||
<TextBlock
|
||||
Margin="0,0,0,4"
|
||||
Style="{ThemeResource BodyStrongTextBlockStyle}"
|
||||
Text="{x:Bind domain:Translator.KeyboardShortcuts_MailoperationAction}" />
|
||||
<ComboBox
|
||||
x:Name="MailOperationComboBox"
|
||||
HorizontalAlignment="Stretch"
|
||||
DisplayMemberPath="DisplayName"
|
||||
ItemsSource="{x:Bind AvailableMailOperations}"
|
||||
SelectedItem="{x:Bind SelectedMailOperation, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Key Input -->
|
||||
<StackPanel Grid.Row="1" Margin="0,0,0,16">
|
||||
<TextBlock
|
||||
Margin="0,0,0,4"
|
||||
Style="{ThemeResource BodyStrongTextBlockStyle}"
|
||||
Text="{x:Bind domain:Translator.KeyboardShortcuts_KeyCombination}" />
|
||||
<TextBox
|
||||
x:Name="KeyInputTextBox"
|
||||
IsReadOnly="True"
|
||||
PlaceholderText="{x:Bind domain:Translator.KeyboardShortcuts_PressKeysHere}"
|
||||
PreviewKeyDown="KeyInputTextBox_PreviewKeyDown" />
|
||||
<TextBlock
|
||||
Margin="0,4,0,0"
|
||||
Opacity="0.7"
|
||||
Style="{ThemeResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind domain:Translator.KeyboardShortcuts_FocusArea}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Modifiers -->
|
||||
<StackPanel Grid.Row="2" Margin="0,0,0,16">
|
||||
<TextBlock
|
||||
Margin="0,0,0,8"
|
||||
Style="{ThemeResource BodyStrongTextBlockStyle}"
|
||||
Text="{x:Bind domain:Translator.KeyboardShortcuts_Modifiers}" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="16">
|
||||
<CheckBox Content="Ctrl" IsChecked="{x:Bind IsControlPressed, Mode=TwoWay}" />
|
||||
<CheckBox Content="Alt" IsChecked="{x:Bind IsAltPressed, Mode=TwoWay}" />
|
||||
<CheckBox Content="Shift" IsChecked="{x:Bind IsShiftPressed, Mode=TwoWay}" />
|
||||
<CheckBox Content="Win" IsChecked="{x:Bind IsWindowsPressed, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Error Message -->
|
||||
<TextBlock
|
||||
x:Name="ErrorTextBlock"
|
||||
Grid.Row="3"
|
||||
Foreground="{ThemeResource SystemErrorTextColor}"
|
||||
Style="{ThemeResource CaptionTextBlockStyle}"
|
||||
Visibility="Collapsed" />
|
||||
</Grid>
|
||||
</ContentDialog>
|
||||
@@ -0,0 +1,145 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models;
|
||||
using Wino.Core.ViewModels.Data;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public sealed partial class KeyboardShortcutDialog : ContentDialog
|
||||
{
|
||||
public KeyboardShortcutDialogResult Result { get; private set; } = KeyboardShortcutDialogResult.Canceled();
|
||||
|
||||
public List<MailOperationViewModel> AvailableMailOperations { get; }
|
||||
|
||||
public MailOperationViewModel SelectedMailOperation { get; set; }
|
||||
public bool IsControlPressed { get; set; }
|
||||
public bool IsAltPressed { get; set; }
|
||||
public bool IsShiftPressed { get; set; }
|
||||
public bool IsWindowsPressed { get; set; }
|
||||
|
||||
public KeyboardShortcutDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
AvailableMailOperations = GetAvailableMailOperations();
|
||||
SelectedMailOperation = AvailableMailOperations.FirstOrDefault();
|
||||
}
|
||||
|
||||
public KeyboardShortcutDialog(KeyboardShortcut existingShortcut) : this()
|
||||
{
|
||||
if (existingShortcut != null)
|
||||
{
|
||||
KeyInputTextBox.Text = existingShortcut.Key;
|
||||
SelectedMailOperation = AvailableMailOperations.FirstOrDefault(x => x.Operation == existingShortcut.MailOperation);
|
||||
|
||||
var modifiers = existingShortcut.ModifierKeys;
|
||||
IsControlPressed = modifiers.HasFlag(ModifierKeys.Control);
|
||||
IsAltPressed = modifiers.HasFlag(ModifierKeys.Alt);
|
||||
IsShiftPressed = modifiers.HasFlag(ModifierKeys.Shift);
|
||||
IsWindowsPressed = modifiers.HasFlag(ModifierKeys.Windows);
|
||||
|
||||
Title = "Edit Keyboard Shortcut";
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
// Clear any previous error
|
||||
ErrorTextBlock.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
|
||||
|
||||
// Validate input
|
||||
if (string.IsNullOrWhiteSpace(KeyInputTextBox.Text))
|
||||
{
|
||||
ShowError("Please enter a key for the shortcut.");
|
||||
args.Cancel = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (SelectedMailOperation == null || SelectedMailOperation.Operation == MailOperation.None)
|
||||
{
|
||||
ShowError("Please select a mail operation for the shortcut.");
|
||||
args.Cancel = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Get modifier keys
|
||||
var modifierKeys = GetSelectedModifierKeys();
|
||||
|
||||
// Create successful result
|
||||
Result = KeyboardShortcutDialogResult.Success(KeyInputTextBox.Text, modifierKeys, SelectedMailOperation.Operation);
|
||||
}
|
||||
|
||||
private void KeyInputTextBox_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
|
||||
{
|
||||
// Clear error when user starts typing
|
||||
ErrorTextBlock.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
|
||||
|
||||
var key = e.Key.ToString();
|
||||
|
||||
// Update modifier states based on current key press
|
||||
IsControlPressed = Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.Control).HasFlag(Windows.UI.Core.CoreVirtualKeyStates.Down);
|
||||
IsAltPressed = Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.Menu).HasFlag(Windows.UI.Core.CoreVirtualKeyStates.Down);
|
||||
IsShiftPressed = Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.Shift).HasFlag(Windows.UI.Core.CoreVirtualKeyStates.Down);
|
||||
IsWindowsPressed = Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.LeftWindows).HasFlag(Windows.UI.Core.CoreVirtualKeyStates.Down) ||
|
||||
Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(Windows.System.VirtualKey.RightWindows).HasFlag(Windows.UI.Core.CoreVirtualKeyStates.Down);
|
||||
|
||||
// Set the key (ignore modifier keys themselves)
|
||||
if (key != "Control" && key != "Menu" && key != "Shift" && key != "LeftWindows" && key != "RightWindows")
|
||||
{
|
||||
KeyInputTextBox.Text = key;
|
||||
}
|
||||
|
||||
// Prevent the key from being processed further
|
||||
// e.Handled = true;
|
||||
}
|
||||
|
||||
private ModifierKeys GetSelectedModifierKeys()
|
||||
{
|
||||
var modifiers = ModifierKeys.None;
|
||||
|
||||
if (IsControlPressed) modifiers |= ModifierKeys.Control;
|
||||
if (IsAltPressed) modifiers |= ModifierKeys.Alt;
|
||||
if (IsShiftPressed) modifiers |= ModifierKeys.Shift;
|
||||
if (IsWindowsPressed) modifiers |= ModifierKeys.Windows;
|
||||
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
private void ShowError(string message)
|
||||
{
|
||||
ErrorTextBlock.Text = message;
|
||||
ErrorTextBlock.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
|
||||
}
|
||||
|
||||
private static List<MailOperationViewModel> GetAvailableMailOperations()
|
||||
{
|
||||
var operations = new List<MailOperationViewModel>();
|
||||
|
||||
// Add commonly used mail operations that make sense for keyboard shortcuts
|
||||
var validOperations = new[]
|
||||
{
|
||||
MailOperation.Archive,
|
||||
MailOperation.UnArchive,
|
||||
MailOperation.SoftDelete,
|
||||
MailOperation.Move,
|
||||
MailOperation.MoveToJunk,
|
||||
MailOperation.SetFlag,
|
||||
MailOperation.ClearFlag,
|
||||
MailOperation.MarkAsRead,
|
||||
MailOperation.MarkAsUnread,
|
||||
MailOperation.Reply,
|
||||
MailOperation.ReplyAll,
|
||||
MailOperation.Forward
|
||||
};
|
||||
|
||||
foreach (var operation in validOperations)
|
||||
{
|
||||
operations.Add(new MailOperationViewModel(operation));
|
||||
}
|
||||
|
||||
return operations.OrderBy(x => x.DisplayName).ToList();
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
<Identity
|
||||
Name="58272BurakKSE.WinoMailPreview"
|
||||
Publisher="CN=51FBDAF3-E212-4149-89A2-A2636B3BC911"
|
||||
Version="0.0.3.0" />
|
||||
Version="0.0.4.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="3879fcfb-a561-4599-9103-e0c9b35a271f" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ using Wino.Core.Domain.Entities.Mail;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models;
|
||||
using Wino.Core.Domain.Models.Accounts;
|
||||
using Wino.Core.Domain.Models.Folders;
|
||||
using Wino.Core.Domain.Models.Synchronization;
|
||||
@@ -194,4 +195,18 @@ public class DialogService : DialogServiceBase, IMailDialogService
|
||||
|
||||
await HandleDialogPresentationAsync(accountReorderDialog);
|
||||
}
|
||||
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
public async Task<KeyboardShortcutDialogResult> ShowKeyboardShortcutDialogAsync(KeyboardShortcut existingShortcut = null)
|
||||
#pragma warning restore CS8625
|
||||
{
|
||||
var dialog = new KeyboardShortcutDialog(existingShortcut)
|
||||
{
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
await HandleDialogPresentationAsync(dialog);
|
||||
|
||||
return dialog.Result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.WinUI;
|
||||
using Wino.Core.WinUI.Services;
|
||||
using Wino.Core.WinUI.Interfaces;
|
||||
using Wino.Core.WinUI.Services;
|
||||
using Wino.Helpers;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Mail.ViewModels.Messages;
|
||||
@@ -59,6 +59,7 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
||||
WinoPage.AliasManagementPage => typeof(AliasManagementPage),
|
||||
WinoPage.LanguageTimePage => typeof(LanguageTimePage),
|
||||
WinoPage.EditAccountDetailsPage => typeof(EditAccountDetailsPage),
|
||||
WinoPage.KeyboardShortcutsPage => typeof(KeyboardShortcutsPage),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
|
||||
using Wino.Core.ViewModels;
|
||||
using Wino.Views.Abstract;
|
||||
|
||||
namespace Wino.Mail.WinUI.Views.Abstract;
|
||||
|
||||
public abstract class KeyboardShortcutsPageAbstract : SettingsPageBase<KeyboardShortcutsPageViewModel>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<abstract:KeyboardShortcutsPageAbstract
|
||||
x:Class="Wino.Views.Settings.KeyboardShortcutsPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:abstract="using:Wino.Mail.WinUI.Views.Abstract"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:data="using:Wino.Core.ViewModels.Data"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
x:Name="root"
|
||||
Title="{x:Bind domain:Translator.Settings_KeyboardShortcuts_Title}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<!-- Main Content -->
|
||||
<Grid Grid.Row="0">
|
||||
<!-- Shortcuts List -->
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Margin="0,0,0,12"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Margin="0,0,8,0"
|
||||
Command="{x:Bind ViewModel.StartAddingShortcutCommand}"
|
||||
Content="{x:Bind domain:Translator.KeyboardShortcuts_Add}" />
|
||||
<Button
|
||||
Command="{x:Bind ViewModel.ResetToDefaultsCommand}"
|
||||
Content="{x:Bind domain:Translator.KeyboardShortcuts_ResetToDefaults}"
|
||||
Style="{ThemeResource AccentButtonStyle}" />
|
||||
</StackPanel>
|
||||
|
||||
<ListView
|
||||
Grid.Row="1"
|
||||
ItemsSource="{x:Bind ViewModel.Shortcuts, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="data:KeyboardShortcutViewModel">
|
||||
<Border
|
||||
Margin="0,4"
|
||||
Padding="16,12"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock
|
||||
Margin="0,0,0,4"
|
||||
Style="{ThemeResource BodyStrongTextBlockStyle}"
|
||||
Text="{x:Bind MailOperationDisplayName}" />
|
||||
<TextBlock
|
||||
Opacity="0.8"
|
||||
Style="{ThemeResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind DisplayName}" />
|
||||
</StackPanel>
|
||||
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Margin="4,0"
|
||||
Command="{Binding ViewModel.StartEditingShortcutCommand, ElementName=root}"
|
||||
CommandParameter="{x:Bind}"
|
||||
Content=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Style="{ThemeResource SubtleButtonStyle}"
|
||||
ToolTipService.ToolTip="Edit" />
|
||||
|
||||
<Button
|
||||
Grid.Column="3"
|
||||
Margin="4,0"
|
||||
Command="{Binding ViewModel.DeleteShortcutCommand, ElementName=root}"
|
||||
CommandParameter="{x:Bind}"
|
||||
Content=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Style="{ThemeResource SubtleButtonStyle}"
|
||||
ToolTipService.ToolTip="Delete" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</abstract:KeyboardShortcutsPageAbstract>
|
||||
@@ -0,0 +1,11 @@
|
||||
using Wino.Mail.WinUI.Views.Abstract;
|
||||
|
||||
namespace Wino.Views.Settings;
|
||||
|
||||
public sealed partial class KeyboardShortcutsPage : KeyboardShortcutsPageAbstract
|
||||
{
|
||||
public KeyboardShortcutsPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -259,12 +259,13 @@
|
||||
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed>
|
||||
<GenerateTemporaryStoreCertificate>True</GenerateTemporaryStoreCertificate>
|
||||
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
||||
<AppxPackageSigningEnabled>False</AppxPackageSigningEnabled>
|
||||
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
|
||||
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
|
||||
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
|
||||
<GenerateTestArtifacts>True</GenerateTestArtifacts>
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<AppxBundlePlatforms>x64</AppxBundlePlatforms>
|
||||
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
|
||||
<PackageCertificateThumbprint>2661584A2F31D3419FFF8AA09A2C16B1991B8290</PackageCertificateThumbprint>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user