Skip to content

Commit 445c17a

Browse files
committed
feat: 增加拼音搜索, 允许设置忽略大小写
1 parent bbab400 commit 445c17a

11 files changed

Lines changed: 103 additions & 45 deletions

File tree

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
namespace CurvaLauncher.Plugins.RunApplication;
22

3-
public abstract class AppInfo
3+
public abstract record class AppInfo
44
{
5+
private string? _queryRoot;
6+
57
public string Name { get; set; } = string.Empty;
8+
9+
public string QueryRoot { get => _queryRoot ?? Name; set => _queryRoot = value; }
10+
11+
public string[]? AlterQueryRoots { get; set; }
612
}

src/CurvaLauncher.Plugins.RunApplication/I18n/De.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@
88
<sys:String x:Key="StrWin32AppDistinctMode">Eindeutiger Modus für Win32-Anwendungen</sys:String>
99
<sys:String x:Key="StrCustomIndexFolders">Benutzerdefinierte Indexordner</sys:String>
1010
<sys:String x:Key="StrRegexsForExcludingApps">Regexs zum Ausschließen von Apps</sys:String>
11+
<sys:String x:Key="StrIgnoreCases">Groß- und Kleinschreibung ignorieren</sys:String>
12+
<sys:String x:Key="StrEnablePinyinSearch">Pinyin-Suche aktivieren</sys:String>
1113
</ResourceDictionary>

src/CurvaLauncher.Plugins.RunApplication/I18n/EnUs.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@
88
<sys:String x:Key="StrWin32AppDistinctMode">Win32 application distinct mode</sys:String>
99
<sys:String x:Key="StrCustomIndexFolders">Custom index folders</sys:String>
1010
<sys:String x:Key="StrRegexsForExcludingApps">Regexs for excluding apps</sys:String>
11+
<sys:String x:Key="StrIgnoreCases">Ignore cases</sys:String>
12+
<sys:String x:Key="StrEnablePinyinSearch">Enable pinyin search</sys:String>
1113
</ResourceDictionary>

src/CurvaLauncher.Plugins.RunApplication/I18n/JaJp.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@
88
<sys:String x:Key="StrWin32AppDistinctMode">Win32 アプリケーションの区分モード</sys:String>
99
<sys:String x:Key="StrCustomIndexFolders">カスタムインデックスフォルダ</sys:String>
1010
<sys:String x:Key="StrRegexsForExcludingApps">アプリを除外するための正規表現</sys:String>
11+
<sys:String x:Key="StrIgnoreCases">大文字小文字を無視</sys:String>
12+
<sys:String x:Key="StrEnablePinyinSearch">拼音検索を有効にする</sys:String>
1113
</ResourceDictionary>

src/CurvaLauncher.Plugins.RunApplication/I18n/ZhHans.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@
88
<sys:String x:Key="StrWin32AppDistinctMode">Win32 应用区分模式</sys:String>
99
<sys:String x:Key="StrCustomIndexFolders">自定义索引文件夹</sys:String>
1010
<sys:String x:Key="StrRegexsForExcludingApps">排除应用程序的正则表达式</sys:String>
11+
<sys:String x:Key="StrIgnoreCases">忽略大小写</sys:String>
12+
<sys:String x:Key="StrEnablePinyinSearch">启用拼音搜索</sys:String>
1113
</ResourceDictionary>

src/CurvaLauncher.Plugins.RunApplication/I18n/ZhHant.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@
88
<sys:String x:Key="StrWin32AppDistinctMode">Win32 應用區分模式</sys:String>
99
<sys:String x:Key="StrCustomFolders">自訂索引資料夾</sys:String>
1010
<sys:String x:Key="StrRegexsForExcludingApps">排除應用程式的正則表示式</sys:String>
11+
<sys:String x:Key="StrIgnoreCases">忽略大小寫</sys:String>
12+
<sys:String x:Key="StrEnablePinyinSearch">啟用拼音搜索</sys:String>
1113
</ResourceDictionary>

src/CurvaLauncher.Plugins.RunApplication/Pinyin/PinyinDictionary.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace CurvaLauncher.Plugins.RunApplication.Pinyin;
44

55
public class PinyinDictionary
66
{
7-
private readonly FrozenDictionary<char, IReadOnlyList<string>> _charsPinyin = new Dictionary<char, IReadOnlyList<string>>(21000)
7+
private readonly Dictionary<char, IReadOnlyList<string>> _charsPinyin = new Dictionary<char, IReadOnlyList<string>>(21000)
88
{
99
['○'] = ["ling"],
1010
['一'] = ["yi"],
@@ -20783,9 +20783,9 @@ public class PinyinDictionary
2078320783
['龢'] = ["he"],
2078420784
['龣'] = ["jiao"],
2078520785
['龤'] = ["xie"],
20786-
}.ToFrozenDictionary();
20786+
};
2078720787

20788-
public FrozenDictionary<char, IReadOnlyList<string>> Storage => _charsPinyin;
20788+
public Dictionary<char, IReadOnlyList<string>> Storage => _charsPinyin;
2078920789

2079020790
public IEnumerable<IEnumerable<string>> GetAllPinyins(string str)
2079120791
{

src/CurvaLauncher.Plugins.RunApplication/RunApplicationPlugin.cs

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
using System.Runtime.InteropServices;
1010
using System.Diagnostics;
1111
using CurvaLauncher.Plugins.RunApplication.RegistryHelper;
12+
using CurvaLauncher.Plugins.RunApplication.Pinyin;
1213

1314
namespace CurvaLauncher.Plugins.RunApplication;
1415

15-
public class RunApplicationPlugin : SyncI18nPlugin
16+
public class RunApplicationPlugin : AsyncI18nPlugin
1617
{
1718
char[] displayNameBuffer = new char[260];
1819

@@ -23,6 +24,9 @@ public class RunApplicationPlugin : SyncI18nPlugin
2324
[PluginI18nOption("StrResultCount")]
2425
public int ResultCount { get; set; } = 5;
2526

27+
[PluginI18nOption("StrIgnoreCases")]
28+
public bool IgnoreCases { get; set; } = true;
29+
2630
[PluginI18nOption("StrEnablePinyinSearch")]
2731
public bool EnablePinyinSearch { get; set; } = false;
2832

@@ -54,21 +58,33 @@ public class RunApplicationPlugin : SyncI18nPlugin
5458

5559
private HashSet<string>? _uwpRepositorySubKeyNames = null;
5660

61+
private PinyinDictionary? _pinyinDictionary = null;
62+
5763

5864
public RunApplicationPlugin(CurvaLauncherContext context) : base(context)
5965
{
6066
Icon = HostContext.ImageApi.CreateFromSvg(Resources.IconSvg)!;
6167
}
6268

63-
public override void Initialize()
69+
public override Task InitializeAsync()
6470
{
65-
_apps = new();
71+
return Task.Run(() =>
72+
{
73+
_apps = new();
74+
75+
if (EnablePinyinSearch)
76+
{
77+
_pinyinDictionary = new();
78+
}
79+
80+
InitializeWin32();
81+
InitializeUwp();
6682

67-
InitializeWin32();
68-
InitializeUwp();
83+
InitializeWin32Watch();
84+
InitializeUwpWatch();
6985

70-
InitializeWin32Watch();
71-
InitializeUwpWatch();
86+
_pinyinDictionary = null;
87+
});
7288
}
7389

7490
private Win32AppInfo? GetWin32App(string shortcut)
@@ -146,6 +162,7 @@ private void InitializeWin32()
146162
}
147163
}
148164

165+
149166
foreach (var shortcut in allShotcutsInStartMenu)
150167
{
151168
if (GetWin32App(shortcut) is Win32AppInfo newApp &&
@@ -155,6 +172,18 @@ private void InitializeWin32()
155172
continue;
156173

157174
_apps.Add(newApp);
175+
176+
if (EnablePinyinSearch)
177+
{
178+
newApp.AlterQueryRoots = _pinyinDictionary!.GetAllPinyins(newApp.Name)
179+
.Select(pinyin => string.Concat(pinyin))
180+
.ToArray();
181+
}
182+
183+
if (IgnoreCases)
184+
{
185+
newApp.QueryRoot = newApp.Name.ToLower();
186+
}
158187
}
159188
}
160189
}
@@ -449,7 +478,22 @@ private void InitializeUwp()
449478
continue;
450479

451480
foreach (var app in GetUwpApps(subKey))
481+
{
452482
_apps.Add(app);
483+
484+
if (EnablePinyinSearch)
485+
{
486+
app.AlterQueryRoots = _pinyinDictionary!.GetAllPinyins(app.Name)
487+
.Select(pinyin => string.Concat(pinyin))
488+
.ToArray();
489+
}
490+
491+
if (IgnoreCases)
492+
{
493+
app.QueryRoot = app.Name.ToLower();
494+
}
495+
}
496+
453497
}
454498

455499
}
@@ -527,39 +571,49 @@ private void UwpRegistryMonitor_RegChanged(object? sender, EventArgs e)
527571
_uwpRepositorySubKeyNames = newUwpRepositorySubKeyNames;
528572
}
529573

530-
public override void Finish()
574+
public override Task FinishAsync()
531575
{
532576
if (_win32FileSystemWatchers != null)
533577
foreach (var watcher in _win32FileSystemWatchers)
534578
watcher.Dispose();
535579

536580
_apps = null;
537581
_win32FileSystemWatchers = null;
582+
583+
return Task.CompletedTask;
538584
}
539585

540-
public override IEnumerable<IQueryResult> Query(string query)
586+
public override async IAsyncEnumerable<IQueryResult> QueryAsync(string query)
541587
{
542588
if (string.IsNullOrWhiteSpace(query))
543589
yield break;
544590
if (_apps == null)
545591
yield break;
546592

547593
IEnumerable<(AppInfo App, float Weight)> results;
594+
var realQuery = IgnoreCases ? query.ToLower() : query;
548595

549596
lock (_apps)
550597
{
551598
results = _apps
552-
.Select(app => (App: app, Weight: HostContext.StringApi.Match(app.Name.ToLower(), query.ToLower())))
599+
.Select(app => (App: app, Weight: GetAppWeight(app, realQuery)))
553600
.OrderByDescending(kvw => kvw.Weight)
554601
.Take(ResultCount);
602+
603+
foreach (var result in results)
604+
{
605+
if (result.App is Win32AppInfo win32AppInfo)
606+
yield return new RunWin32ApplicationQueryResult(HostContext, win32AppInfo, result.Weight);
607+
else if (result.App is UwpAppInfo uwpAppInfo)
608+
yield return new RunUwpApplicationQueryResult(HostContext, uwpAppInfo, result.Weight);
609+
}
555610
}
556611

557-
foreach (var result in results)
612+
float GetAppWeight(AppInfo appInfo, string realQuery)
558613
{
559-
if (result.App is Win32AppInfo win32AppInfo)
560-
yield return new RunWin32ApplicationQueryResult(HostContext, win32AppInfo, result.Weight);
561-
else if (result.App is UwpAppInfo uwpAppInfo)
562-
yield return new RunUwpApplicationQueryResult(HostContext, uwpAppInfo, result.Weight);
614+
return Math.Max(
615+
HostContext.StringApi.Match(appInfo.QueryRoot, realQuery),
616+
appInfo.AlterQueryRoots?.Max(altName => HostContext.StringApi.Match(altName, realQuery)) ?? 0);
563617
}
564618
}
565619

src/CurvaLauncher.Plugins.RunApplication/RunWin32ApplicationQueryResult.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,20 @@ public RunWin32ApplicationQueryResult(CurvaLauncherContext context, Win32AppInfo
3232
{
3333
var iconPath = appInfo.IconPath ?? appInfo.FilePath;
3434

35-
if (!iconPath.EndsWith(".ico"))
35+
try
3636
{
37-
var iconIndex = appInfo.IconIndex;
38-
icon = context.ImageApi.GetEmbededIconImage(iconPath, context.RequiredIconSize, iconIndex);
39-
}
40-
else
41-
{
42-
if (File.Exists(iconPath))
43-
icon = new BitmapImage(new Uri(iconPath));
37+
if (!iconPath.EndsWith(".ico"))
38+
{
39+
var iconIndex = appInfo.IconIndex;
40+
icon = context.ImageApi.GetEmbededIconImage(iconPath, context.RequiredIconSize, iconIndex);
41+
}
42+
else
43+
{
44+
if (File.Exists(iconPath))
45+
icon = new BitmapImage(new Uri(iconPath));
46+
}
4447
}
48+
catch { }
4549
});
4650
}
4751

src/CurvaLauncher.Plugins.RunApplication/UwpAppInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace CurvaLauncher.Plugins.RunApplication;
44

5-
public class UwpAppInfo : AppInfo
5+
public record class UwpAppInfo : AppInfo
66
{
77
public string PackageId { get; set; } = string.Empty;
88
public string FamilyID { get; set; } = string.Empty;

0 commit comments

Comments
 (0)