refactor: replace Key constants with KeyCode for improved clarity and performance

This commit is contained in:
HueByte
2026-07-16 19:40:18 +02:00
parent 4f2cffa372
commit 2157884e61
+93 -88
View File
@@ -11,6 +11,7 @@ using Serilog;
using Terminal.Gui.App; using Terminal.Gui.App;
using Terminal.Gui.Configuration; using Terminal.Gui.Configuration;
using Terminal.Gui.Drawing; using Terminal.Gui.Drawing;
using Terminal.Gui.Drivers;
using Terminal.Gui.Input; using Terminal.Gui.Input;
using Terminal.Gui.Text; using Terminal.Gui.Text;
using Terminal.Gui.ViewBase; using Terminal.Gui.ViewBase;
@@ -41,23 +42,24 @@ public sealed partial class MainWindow : Runnable
private bool _usersPanelVisible = true; private bool _usersPanelVisible = true;
private const int UsersPanelWidth = 22; private const int UsersPanelWidth = 22;
private const string DefaultInputTitle = "Message │ Enter=send │ Tab=complete │ Ctrl+K=search │ F6=pick message"; private const string DefaultInputTitle = "Message │ Enter=send │ Tab=complete │ Ctrl+K=search │ F6=pick message";
private static readonly Key F2Key = Key.F2; private const KeyCode F2Key = KeyCode.F2;
private bool _hasStagedAttachments; private bool _hasStagedAttachments;
internal static readonly string AppVersion = internal static readonly string AppVersion =
typeof(MainWindow).Assembly.GetName().Version?.ToString(3) ?? "?"; typeof(MainWindow).Assembly.GetName().Version?.ToString(3) ?? "?";
// Cached Key constants compare via .KeyCode to avoid Key.Equals (which also checks Handled) // Key bindings as KeyCode constants: comparing raw KeyCodes avoids Key.Equals (which also
private static readonly Key EnterKey = Key.Enter; // checks Handled), and constants make them usable as switch case labels.
private static readonly Key NewlineKey = Key.N.WithCtrl; private const KeyCode EnterKey = KeyCode.Enter;
private static readonly Key AltQKey = Key.Q.WithAlt; private const KeyCode NewlineKey = KeyCode.N | KeyCode.CtrlMask;
private static readonly Key TabKey = Key.Tab; private const KeyCode AltQKey = KeyCode.Q | KeyCode.AltMask;
private static readonly Key CtrlKKey = Key.K.WithCtrl; private const KeyCode TabKey = KeyCode.Tab;
private static readonly Key CtrlVKey = Key.V.WithCtrl; private const KeyCode CtrlKKey = KeyCode.K | KeyCode.CtrlMask;
private static readonly Key CtrlXKey = Key.X.WithCtrl; private const KeyCode CtrlVKey = KeyCode.V | KeyCode.CtrlMask;
private static readonly Key CtrlCKey = Key.C.WithCtrl; private const KeyCode CtrlXKey = KeyCode.X | KeyCode.CtrlMask;
private static readonly Key CtrlYKey = Key.Y.WithCtrl; private const KeyCode CtrlCKey = KeyCode.C | KeyCode.CtrlMask;
private static readonly Key F6Key = Key.F6; private const KeyCode CtrlYKey = KeyCode.Y | KeyCode.CtrlMask;
private const KeyCode F6Key = KeyCode.F6;
// Available slash commands for Tab autocomplete // Available slash commands for Tab autocomplete
private static readonly string[] SlashCommands = private static readonly string[] SlashCommands =
@@ -569,7 +571,7 @@ public sealed partial class MainWindow : Runnable
private void OnMessageListKeyDown(object? sender, Key e) private void OnMessageListKeyDown(object? sender, Key e)
{ {
// F6 returns focus to the input box. // F6 returns focus to the input box.
if (e.KeyCode == F6Key.KeyCode) if (e.KeyCode == F6Key)
{ {
_inputField.SetFocus(); _inputField.SetFocus();
e.Handled = true; e.Handled = true;
@@ -715,70 +717,69 @@ public sealed partial class MainWindow : Runnable
private void OnInputKeyDown(object? sender, Key e) private void OnInputKeyDown(object? sender, Key e)
{ {
if (e.KeyCode == TabKey.KeyCode) switch (e.KeyCode)
{ {
TryAutocompleteCommand(); case TabKey:
e.Handled = true; TryAutocompleteCommand();
} break;
else if (e.KeyCode == NewlineKey.KeyCode)
{ case NewlineKey:
_inputField.InsertText("\n"); _inputField.InsertText("\n");
e.Handled = true; break;
}
else if (e.KeyCode == EnterKey.KeyCode) case EnterKey:
{ var text = _inputField.Text?.Trim() ?? string.Empty;
var text = _inputField.Text?.Trim() ?? string.Empty; // Send when there's text, or when only attachments are staged (empty caption).
// Send when there's text, or when only attachments are staged (empty caption). if ((!string.IsNullOrEmpty(text) || _hasStagedAttachments)
if ((!string.IsNullOrEmpty(text) || _hasStagedAttachments) && !string.IsNullOrEmpty(_messageManager.CurrentChannel))
&& !string.IsNullOrEmpty(_messageManager.CurrentChannel)) {
{ OnMessageSubmitted?.Invoke(_messageManager.CurrentChannel, text);
OnMessageSubmitted?.Invoke(_messageManager.CurrentChannel, text); _inputField.Text = string.Empty;
_inputField.Text = string.Empty; }
} break;
e.Handled = true;
} case AltQKey:
else if (e.KeyCode == AltQKey.KeyCode) _app.RequestStop();
{ break;
_app.RequestStop();
e.Handled = true; case CtrlKKey:
} ShowSearchDialog();
else if (e.KeyCode == CtrlKKey.KeyCode) break;
{
ShowSearchDialog(); case F6Key:
e.Handled = true; // Move focus into the message list so you can select a message (arrows) and
} // delete it (Delete). F6 again returns focus here. (Esc is the app quit key.)
else if (e.KeyCode == F6Key.KeyCode) FocusMessageList();
{ break;
// Move focus into the message list so you can select a message (arrows) and
// delete it (Delete). F6 again returns focus here. (Esc is the app quit key.) case CtrlVKey:
FocusMessageList(); case CtrlYKey:
e.Handled = true; // Discord-style paste priority. Copied files in the OS file manager put a file
} // list (not text) on the clipboard — attach them all. Copied image data (browser
else if (e.KeyCode == CtrlVKey.KeyCode || e.KeyCode == CtrlYKey.KeyCode) // right-click copy, screenshot tools) is attached as a PNG. Otherwise paste text.
{ // Terminals never deliver either of the first two as text, so this is the only path.
// Discord-style paste priority. Copied files in the OS file manager put a file if (ClipboardFiles.TryGetFiles(out var pastedFiles))
// list (not text) on the clipboard — attach them all. Copied image data (browser StageFiles(pastedFiles);
// right-click copy, screenshot tools) is attached as a PNG. Otherwise paste text. else if (!string.IsNullOrEmpty(_messageManager.CurrentChannel)
// Terminals never deliver either of the first two as text, so this is the only path. && ClipboardImage.TryGetPng(out var pastedPng))
if (ClipboardFiles.TryGetFiles(out var pastedFiles)) OnImagePasted?.Invoke(_messageManager.CurrentChannel, pastedPng);
StageFiles(pastedFiles); else
else if (!string.IsNullOrEmpty(_messageManager.CurrentChannel) GuardedClipboardAction(() => _inputField.Paste(), "paste");
&& ClipboardImage.TryGetPng(out var pastedPng)) break;
OnImagePasted?.Invoke(_messageManager.CurrentChannel, pastedPng);
else case CtrlXKey:
GuardedClipboardAction(() => _inputField.Paste(), "paste"); GuardedClipboardAction(() => _inputField.Cut(), "cut");
e.Handled = true; break;
}
else if (e.KeyCode == CtrlXKey.KeyCode) case CtrlCKey:
{ GuardedClipboardAction(() => _inputField.Copy(), "copy");
GuardedClipboardAction(() => _inputField.Cut(), "cut"); break;
e.Handled = true;
} default:
else if (e.KeyCode == CtrlCKey.KeyCode) return; // not one of ours — leave e.Handled false so the key types normally
{
GuardedClipboardAction(() => _inputField.Copy(), "copy");
e.Handled = true;
} }
e.Handled = true;
} }
/// <summary> /// <summary>
@@ -913,21 +914,25 @@ public sealed partial class MainWindow : Runnable
private void OnWindowKeyDown(object? sender, Key e) private void OnWindowKeyDown(object? sender, Key e)
{ {
if (e.KeyCode == AltQKey.KeyCode) switch (e.KeyCode)
{ {
_app.RequestStop(); case AltQKey:
e.Handled = true; _app.RequestStop();
} break;
else if (e.KeyCode == F2Key.KeyCode)
{ case F2Key:
ToggleUsersPanel(); ToggleUsersPanel();
e.Handled = true; break;
}
else if (e.KeyCode == CtrlKKey.KeyCode) case CtrlKKey:
{ ShowSearchDialog();
ShowSearchDialog(); break;
e.Handled = true;
default:
return;
} }
e.Handled = true;
} }
private void ShowSearchDialog() private void ShowSearchDialog()