From 6ef0cf9e1c9296f862fb130697125816a63f0c1f Mon Sep 17 00:00:00 2001 From: rabbitism Date: Wed, 6 Nov 2024 14:38:39 +0800 Subject: [PATCH 1/2] feat: support paste. --- src/Ursa/Controls/PinCode/PinCode.cs | 24 ++++- .../Controls/PinCodeTests/PasteTest.cs | 89 +++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 tests/HeadlessTest.Ursa/Controls/PinCodeTests/PasteTest.cs diff --git a/src/Ursa/Controls/PinCode/PinCode.cs b/src/Ursa/Controls/PinCode/PinCode.cs index 1f6d2fa..4c9bc62 100644 --- a/src/Ursa/Controls/PinCode/PinCode.cs +++ b/src/Ursa/Controls/PinCode/PinCode.cs @@ -159,8 +159,30 @@ public class PinCode: TemplatedControl }; } - protected void OnPreviewKeyDown(KeyEventArgs e) + protected async void OnPreviewKeyDown(KeyEventArgs e) { + TextBox b = new TextBox(); + var pasteKeys = Application.Current?.PlatformSettings.HotkeyConfiguration.Paste; + if (pasteKeys?.Any(a => a.Matches(e)) == true) + { + var clipboard = TopLevel.GetTopLevel(this)?.Clipboard; + var text = await clipboard.GetTextAsync(); + if (text is not null) + { + var newText = text.Where(c => Valid(c, Mode)).Take(Count).ToArray(); + for (int i = 0; i < newText.Length; i++) + { + Digits[i] = newText[i].ToString(); + var presenter = _itemsControl?.ContainerFromIndex(i) as PinCodeItem; + if (presenter is not null) + { + presenter.Focus(); + presenter.Text = newText[i].ToString(); + } + } + } + return; + } if (e.Key == Key.Tab && e.Source is PinCodeItem) { _currentIndex = MathHelpers.SafeClamp(_currentIndex, 0, Count - 1); diff --git a/tests/HeadlessTest.Ursa/Controls/PinCodeTests/PasteTest.cs b/tests/HeadlessTest.Ursa/Controls/PinCodeTests/PasteTest.cs new file mode 100644 index 0000000..dc72db7 --- /dev/null +++ b/tests/HeadlessTest.Ursa/Controls/PinCodeTests/PasteTest.cs @@ -0,0 +1,89 @@ +using Avalonia.Controls; +using Avalonia.Headless; +using Avalonia.Headless.XUnit; +using Avalonia.Input; +using Avalonia.Threading; +using Ursa.Controls; + +namespace HeadlessTest.Ursa.Controls.PinCodeTests; + +public class PasteTest +{ + [AvaloniaFact] + public async void Paste_Should_Insert_Text() + { + var window = new Window(); + var pinCode = new PinCode() + { + Count = 4, + }; + window.Content = pinCode; + window.Show(); + var clipboard = window.Clipboard; + Assert.NotNull(clipboard); + await clipboard.SetTextAsync("abcd"); + pinCode.Focus(); + window.KeyPressQwerty(PhysicalKey.V, RawInputModifiers.Control); + // add await for clipboard processing. + await Task.Delay(1); + Assert.Equal("abcd", string.Join("", pinCode.Digits)); + } + + [AvaloniaFact] + public async void Paste_Should_Insert_Text_When_Text_Is_Shorter() + { + var window = new Window(); + var pinCode = new PinCode() + { + Count = 4, + }; + window.Content = pinCode; + window.Show(); + var clipboard = window.Clipboard; + Assert.NotNull(clipboard); + await clipboard.SetTextAsync("abc"); + pinCode.Focus(); + window.KeyPressQwerty(PhysicalKey.V, RawInputModifiers.Control); + await Task.Delay(1); + Assert.Equal("abc", string.Join("", pinCode.Digits)); + } + + [AvaloniaFact] + public async void Paste_Should_Insert_Text_When_Text_Is_Longer() + { + var window = new Window(); + var pinCode = new PinCode() + { + Count = 4, + }; + window.Content = pinCode; + window.Show(); + var clipboard = window.Clipboard; + Assert.NotNull(clipboard); + await clipboard.SetTextAsync("abcde"); + pinCode.Focus(); + window.KeyPressQwerty(PhysicalKey.V, RawInputModifiers.Control); + await Task.Delay(1); + Assert.Equal("abcd", string.Join("", pinCode.Digits)); + } + + [AvaloniaFact] + public async void Paste_Should_Not_Insert_Text_When_Text_Is_In_Invalid_Mode() + { + var window = new Window(); + var pinCode = new PinCode() + { + Count = 4, + Mode = PinCodeMode.Digit, + }; + window.Content = pinCode; + window.Show(); + var clipboard = window.Clipboard; + Assert.NotNull(clipboard); + await clipboard.SetTextAsync("abcde"); + pinCode.Focus(); + window.KeyPressQwerty(PhysicalKey.V, RawInputModifiers.Control); + await Task.Delay(1); + Assert.Equal("", string.Join("", pinCode.Digits)); + } +} \ No newline at end of file From 186424b84858a5851bcd855e33a30188b31f6062 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Wed, 6 Nov 2024 18:44:49 +0800 Subject: [PATCH 2/2] fix: fix warnings in test related code. --- src/Ursa/Controls/PinCode/PinCode.cs | 3 ++- .../Controls/UrsaWindowTests/UrsaWindowTest.cs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Ursa/Controls/PinCode/PinCode.cs b/src/Ursa/Controls/PinCode/PinCode.cs index 4c9bc62..a04fb6d 100644 --- a/src/Ursa/Controls/PinCode/PinCode.cs +++ b/src/Ursa/Controls/PinCode/PinCode.cs @@ -162,10 +162,11 @@ public class PinCode: TemplatedControl protected async void OnPreviewKeyDown(KeyEventArgs e) { TextBox b = new TextBox(); - var pasteKeys = Application.Current?.PlatformSettings.HotkeyConfiguration.Paste; + var pasteKeys = Application.Current?.PlatformSettings?.HotkeyConfiguration.Paste; if (pasteKeys?.Any(a => a.Matches(e)) == true) { var clipboard = TopLevel.GetTopLevel(this)?.Clipboard; + if (clipboard is null) return; var text = await clipboard.GetTextAsync(); if (text is not null) { diff --git a/tests/HeadlessTest.Ursa/Controls/UrsaWindowTests/UrsaWindowTest.cs b/tests/HeadlessTest.Ursa/Controls/UrsaWindowTests/UrsaWindowTest.cs index 101e2d6..b0825c7 100644 --- a/tests/HeadlessTest.Ursa/Controls/UrsaWindowTests/UrsaWindowTest.cs +++ b/tests/HeadlessTest.Ursa/Controls/UrsaWindowTests/UrsaWindowTest.cs @@ -17,7 +17,7 @@ public class UrsaWindowTest } [AvaloniaFact] - public async void Inferenced_Window_Closing_Called_Once_When_Yes() + public void Inferenced_Window_Closing_Called_Once_When_Yes() { var window = new UrsaWindowWithCloseInference(); window.Show(); @@ -29,7 +29,7 @@ public class UrsaWindowTest } [AvaloniaFact] - public async void Inferenced_Window_Closing_Called_Once_When_No() + public void Inferenced_Window_Closing_Called_Once_When_No() { var window = new UrsaWindowWithCloseInference(); window.Show();