[QuickAccent]Add setting to sort characters by use frequency (#22847)

* [Quick Accent] add toggle switch to sort characters by usage frequency

* [Quick Accent] if enabled, then sort by frequency for all toolbar triggers

* [Quick Accent] add "start selection from the left" toggle switch

* [Quick Accent] fix error SA1000: The keyword 'new' should not be followed by a space

* Fix C# analyzer build error
This commit is contained in:
Taras
2023-01-03 14:44:57 +02:00
committed by GitHub
parent b1c535a2ce
commit 14ad19e1e3
7 changed files with 178 additions and 3 deletions

View File

@@ -37,6 +37,8 @@ public class PowerAccent : IDisposable
private readonly KeyboardListener _keyboardListener;
private readonly CharactersUsageInfo _usageInfo;
public PowerAccent()
{
LoadUnicodeInfoCache();
@@ -44,6 +46,7 @@ public class PowerAccent : IDisposable
_keyboardListener = new KeyboardListener();
_keyboardListener.InitHook();
_settingService = new SettingsService(_keyboardListener);
_usageInfo = new CharactersUsageInfo();
SetEvents();
}
@@ -88,9 +91,9 @@ public class PowerAccent : IDisposable
private void ShowToolbar(LetterKey letterKey)
{
_visible = true;
_characters = (WindowsFunctions.IsCapsLockState() || WindowsFunctions.IsShiftState()) ? ToUpper(Languages.GetDefaultLetterKey(letterKey, _settingService.SelectedLang)) : Languages.GetDefaultLetterKey(letterKey, _settingService.SelectedLang);
_characterDescriptions = GetCharacterDescriptions(_characters);
_characters = GetCharacters(letterKey);
_characterDescriptions = GetCharacterDescriptions(_characters);
_showUnicodeDescription = _settingService.ShowUnicodeDescription;
Task.Delay(_settingService.InputTime).ContinueWith(
@@ -104,6 +107,28 @@ public class PowerAccent : IDisposable
TaskScheduler.FromCurrentSynchronizationContext());
}
private string[] GetCharacters(LetterKey letterKey)
{
var characters = Languages.GetDefaultLetterKey(letterKey, _settingService.SelectedLang);
if (_settingService.SortByUsageFrequency)
{
characters = characters.OrderByDescending(character => _usageInfo.GetUsageFrequency(character))
.ThenByDescending(character => _usageInfo.GetLastUsageTimestamp(character)).
ToArray<string>();
}
else if (!_usageInfo.Empty())
{
_usageInfo.Clear();
}
if (WindowsFunctions.IsCapsLockState() || WindowsFunctions.IsShiftState())
{
return ToUpper(characters);
}
return characters;
}
private string GetCharacterDescription(string character)
{
List<UnicodeCharInfo> unicodeList = new List<UnicodeCharInfo>();
@@ -180,6 +205,11 @@ public class PowerAccent : IDisposable
if (_selectedIndex != -1)
{
WindowsFunctions.Insert(_characters[_selectedIndex], true);
if (_settingService.SortByUsageFrequency)
{
_usageInfo.IncrementUsageFrequency(_characters[_selectedIndex]);
}
}
break;
@@ -205,7 +235,7 @@ public class PowerAccent : IDisposable
_selectedIndex = _characters.Length / 2;
}
if (triggerKey == TriggerKey.Space)
if (triggerKey == TriggerKey.Space || _settingService.StartSelectionFromTheLeft)
{
_selectedIndex = 0;
}

View File

@@ -92,6 +92,8 @@ public class SettingsService
}
ShowUnicodeDescription = settings.Properties.ShowUnicodeDescription;
SortByUsageFrequency = settings.Properties.SortByUsageFrequency;
StartSelectionFromTheLeft = settings.Properties.StartSelectionFromTheLeft;
}
}
catch (Exception ex)
@@ -191,6 +193,36 @@ public class SettingsService
_showUnicodeDescription = value;
}
}
private bool _sortByUsageFrequency;
public bool SortByUsageFrequency
{
get
{
return _sortByUsageFrequency;
}
set
{
_sortByUsageFrequency = value;
}
}
private bool _startSelectionFromTheLeft;
public bool StartSelectionFromTheLeft
{
get
{
return _startSelectionFromTheLeft;
}
set
{
_startSelectionFromTheLeft = value;
}
}
}
public enum Position

View File

@@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace PowerAccent.Core.Tools
{
public class CharactersUsageInfo
{
private Dictionary<string, uint> _characterUsageCounters = new Dictionary<string, uint>();
private Dictionary<string, long> _characterUsageTimestamp = new Dictionary<string, long>();
public bool Empty()
{
return _characterUsageCounters.Count == 0;
}
public void Clear()
{
_characterUsageCounters.Clear();
_characterUsageTimestamp.Clear();
}
public uint GetUsageFrequency(string character)
{
_characterUsageCounters.TryGetValue(character, out uint frequency);
return frequency;
}
public long GetLastUsageTimestamp(string character)
{
_characterUsageTimestamp.TryGetValue(character, out long timestamp);
return timestamp;
}
public void IncrementUsageFrequency(string character)
{
if (_characterUsageCounters.ContainsKey(character))
{
_characterUsageCounters[character]++;
}
else
{
_characterUsageCounters.Add(character, 1);
}
_characterUsageTimestamp[character] = DateTimeOffset.Now.ToUnixTimeSeconds();
}
}
}