|
5 | 5 | using Flow.Launcher.Plugin.ProcessKiller.ViewModels;
|
6 | 6 | using Flow.Launcher.Plugin.ProcessKiller.Views;
|
7 | 7 |
|
8 |
| -namespace Flow.Launcher.Plugin.ProcessKiller |
| 8 | +namespace Flow.Launcher.Plugin.ProcessKiller; |
| 9 | + |
| 10 | +public class Main : IPlugin, IPluginI18n, IContextMenu, ISettingProvider |
9 | 11 | {
|
10 |
| - public class Main : IPlugin, IPluginI18n, IContextMenu, ISettingProvider |
11 |
| - { |
12 |
| - private readonly ProcessHelper processHelper = new(); |
| 12 | + internal static PluginInitContext Context { get; private set; } |
13 | 13 |
|
14 |
| - private static PluginInitContext _context; |
| 14 | + internal static Settings Settings { get; private set; } |
15 | 15 |
|
16 |
| - internal Settings Settings; |
| 16 | + private readonly ProcessHelper processHelper = new(); |
17 | 17 |
|
18 |
| - private SettingsViewModel _viewModel; |
| 18 | + private SettingsViewModel _viewModel; |
19 | 19 |
|
20 |
| - public void Init(PluginInitContext context) |
21 |
| - { |
22 |
| - _context = context; |
23 |
| - Settings = context.API.LoadSettingJsonStorage<Settings>(); |
24 |
| - _viewModel = new SettingsViewModel(Settings); |
25 |
| - } |
| 20 | + public void Init(PluginInitContext context) |
| 21 | + { |
| 22 | + Context = context; |
| 23 | + Settings = context.API.LoadSettingJsonStorage<Settings>(); |
| 24 | + _viewModel = new SettingsViewModel(Settings); |
| 25 | + } |
26 | 26 |
|
27 |
| - public List<Result> Query(Query query) |
28 |
| - { |
29 |
| - return CreateResultsFromQuery(query); |
30 |
| - } |
| 27 | + public List<Result> Query(Query query) |
| 28 | + { |
| 29 | + return CreateResultsFromQuery(query); |
| 30 | + } |
31 | 31 |
|
32 |
| - public string GetTranslatedPluginTitle() |
33 |
| - { |
34 |
| - return _context.API.GetTranslation("flowlauncher_plugin_processkiller_plugin_name"); |
35 |
| - } |
| 32 | + public string GetTranslatedPluginTitle() |
| 33 | + { |
| 34 | + return Context.API.GetTranslation("flowlauncher_plugin_processkiller_plugin_name"); |
| 35 | + } |
36 | 36 |
|
37 |
| - public string GetTranslatedPluginDescription() |
38 |
| - { |
39 |
| - return _context.API.GetTranslation("flowlauncher_plugin_processkiller_plugin_description"); |
40 |
| - } |
| 37 | + public string GetTranslatedPluginDescription() |
| 38 | + { |
| 39 | + return Context.API.GetTranslation("flowlauncher_plugin_processkiller_plugin_description"); |
| 40 | + } |
41 | 41 |
|
42 |
| - public List<Result> LoadContextMenus(Result result) |
43 |
| - { |
44 |
| - var menuOptions = new List<Result>(); |
45 |
| - var processPath = result.SubTitle; |
| 42 | + public List<Result> LoadContextMenus(Result result) |
| 43 | + { |
| 44 | + var menuOptions = new List<Result>(); |
| 45 | + var processPath = result.SubTitle; |
46 | 46 |
|
47 |
| - // get all non-system processes whose file path matches that of the given result (processPath) |
48 |
| - var similarProcesses = processHelper.GetSimilarProcesses(processPath); |
| 47 | + // get all non-system processes whose file path matches that of the given result (processPath) |
| 48 | + var similarProcesses = processHelper.GetSimilarProcesses(processPath); |
49 | 49 |
|
50 |
| - if (similarProcesses.Any()) |
| 50 | + if (similarProcesses.Any()) |
| 51 | + { |
| 52 | + menuOptions.Add(new Result |
51 | 53 | {
|
52 |
| - menuOptions.Add(new Result |
| 54 | + Title = Context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_instances"), |
| 55 | + SubTitle = processPath, |
| 56 | + Action = _ => |
53 | 57 | {
|
54 |
| - Title = _context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_instances"), |
55 |
| - SubTitle = processPath, |
56 |
| - Action = _ => |
| 58 | + foreach (var p in similarProcesses) |
57 | 59 | {
|
58 |
| - foreach (var p in similarProcesses) |
59 |
| - { |
60 |
| - processHelper.TryKill(_context, p); |
61 |
| - } |
| 60 | + ProcessHelper.TryKill(p); |
| 61 | + } |
62 | 62 |
|
63 |
| - return true; |
64 |
| - }, |
65 |
| - IcoPath = processPath |
66 |
| - }); |
67 |
| - } |
| 63 | + return true; |
| 64 | + }, |
| 65 | + IcoPath = processPath |
| 66 | + }); |
| 67 | + } |
68 | 68 |
|
69 |
| - return menuOptions; |
| 69 | + return menuOptions; |
| 70 | + } |
| 71 | + |
| 72 | + private List<Result> CreateResultsFromQuery(Query query) |
| 73 | + { |
| 74 | + // Get all non-system processes |
| 75 | + var allPocessList = processHelper.GetMatchingProcesses(); |
| 76 | + if (!allPocessList.Any()) |
| 77 | + { |
| 78 | + return null; |
70 | 79 | }
|
71 | 80 |
|
72 |
| - private List<Result> CreateResultsFromQuery(Query query) |
| 81 | + // Filter processes based on search term |
| 82 | + var searchTerm = query.Search; |
| 83 | + var processlist = new List<ProcessResult>(); |
| 84 | + var processWindowTitle = |
| 85 | + Settings.ShowWindowTitle || Settings.PutVisibleWindowProcessesTop ? |
| 86 | + ProcessHelper.GetProcessesWithNonEmptyWindowTitle() : |
| 87 | + new Dictionary<int, string>(); |
| 88 | + if (string.IsNullOrWhiteSpace(searchTerm)) |
73 | 89 | {
|
74 |
| - // Get all non-system processes |
75 |
| - var allPocessList = processHelper.GetMatchingProcesses(); |
76 |
| - if (!allPocessList.Any()) |
| 90 | + foreach (var p in allPocessList) |
77 | 91 | {
|
78 |
| - return null; |
79 |
| - } |
| 92 | + var progressNameIdTitle = ProcessHelper.GetProcessNameIdTitle(p); |
80 | 93 |
|
81 |
| - // Filter processes based on search term |
82 |
| - var searchTerm = query.Search; |
83 |
| - var processlist = new List<ProcessResult>(); |
84 |
| - var processWindowTitle = |
85 |
| - Settings.ShowWindowTitle || Settings.PutVisibleWindowProcessesTop ? |
86 |
| - ProcessHelper.GetProcessesWithNonEmptyWindowTitle() : |
87 |
| - new Dictionary<int, string>(); |
88 |
| - if (string.IsNullOrWhiteSpace(searchTerm)) |
89 |
| - { |
90 |
| - foreach (var p in allPocessList) |
| 94 | + if (processWindowTitle.TryGetValue(p.Id, out var windowTitle)) |
| 95 | + { |
| 96 | + // Add score to prioritize processes with visible windows |
| 97 | + // Use window title for those processes if enabled |
| 98 | + processlist.Add(new ProcessResult( |
| 99 | + p, |
| 100 | + Settings.PutVisibleWindowProcessesTop ? 200 : 0, |
| 101 | + Settings.ShowWindowTitle ? windowTitle : progressNameIdTitle, |
| 102 | + null, |
| 103 | + progressNameIdTitle)); |
| 104 | + } |
| 105 | + else |
91 | 106 | {
|
92 |
| - var progressNameIdTitle = ProcessHelper.GetProcessNameIdTitle(p); |
| 107 | + processlist.Add(new ProcessResult( |
| 108 | + p, |
| 109 | + 0, |
| 110 | + progressNameIdTitle, |
| 111 | + null, |
| 112 | + progressNameIdTitle)); |
| 113 | + } |
| 114 | + } |
| 115 | + } |
| 116 | + else |
| 117 | + { |
| 118 | + foreach (var p in allPocessList) |
| 119 | + { |
| 120 | + var progressNameIdTitle = ProcessHelper.GetProcessNameIdTitle(p); |
93 | 121 |
|
94 |
| - if (processWindowTitle.TryGetValue(p.Id, out var windowTitle)) |
| 122 | + if (processWindowTitle.TryGetValue(p.Id, out var windowTitle)) |
| 123 | + { |
| 124 | + // Get max score from searching process name, window title and process id |
| 125 | + var windowTitleMatch = Context.API.FuzzySearch(searchTerm, windowTitle); |
| 126 | + var processNameIdMatch = Context.API.FuzzySearch(searchTerm, progressNameIdTitle); |
| 127 | + var score = Math.Max(windowTitleMatch.Score, processNameIdMatch.Score); |
| 128 | + if (score > 0) |
95 | 129 | {
|
96 | 130 | // Add score to prioritize processes with visible windows
|
97 |
| - // Use window title for those processes if enabled |
| 131 | + // Use window title for those processes |
| 132 | + if (Settings.PutVisibleWindowProcessesTop) |
| 133 | + { |
| 134 | + score += 200; |
| 135 | + } |
98 | 136 | processlist.Add(new ProcessResult(
|
99 | 137 | p,
|
100 |
| - Settings.PutVisibleWindowProcessesTop ? 200 : 0, |
| 138 | + score, |
101 | 139 | Settings.ShowWindowTitle ? windowTitle : progressNameIdTitle,
|
102 |
| - null, |
| 140 | + score == windowTitleMatch.Score ? windowTitleMatch : null, |
103 | 141 | progressNameIdTitle));
|
104 | 142 | }
|
105 |
| - else |
| 143 | + } |
| 144 | + else |
| 145 | + { |
| 146 | + var processNameIdMatch = Context.API.FuzzySearch(searchTerm, progressNameIdTitle); |
| 147 | + var score = processNameIdMatch.Score; |
| 148 | + if (score > 0) |
106 | 149 | {
|
107 | 150 | processlist.Add(new ProcessResult(
|
108 | 151 | p,
|
109 |
| - 0, |
| 152 | + score, |
110 | 153 | progressNameIdTitle,
|
111 |
| - null, |
| 154 | + processNameIdMatch, |
112 | 155 | progressNameIdTitle));
|
113 | 156 | }
|
114 | 157 | }
|
115 | 158 | }
|
116 |
| - else |
117 |
| - { |
118 |
| - foreach (var p in allPocessList) |
119 |
| - { |
120 |
| - var progressNameIdTitle = ProcessHelper.GetProcessNameIdTitle(p); |
121 |
| - |
122 |
| - if (processWindowTitle.TryGetValue(p.Id, out var windowTitle)) |
123 |
| - { |
124 |
| - // Get max score from searching process name, window title and process id |
125 |
| - var windowTitleMatch = _context.API.FuzzySearch(searchTerm, windowTitle); |
126 |
| - var processNameIdMatch = _context.API.FuzzySearch(searchTerm, progressNameIdTitle); |
127 |
| - var score = Math.Max(windowTitleMatch.Score, processNameIdMatch.Score); |
128 |
| - if (score > 0) |
129 |
| - { |
130 |
| - // Add score to prioritize processes with visible windows |
131 |
| - // Use window title for those processes |
132 |
| - if (Settings.PutVisibleWindowProcessesTop) |
133 |
| - { |
134 |
| - score += 200; |
135 |
| - } |
136 |
| - processlist.Add(new ProcessResult( |
137 |
| - p, |
138 |
| - score, |
139 |
| - Settings.ShowWindowTitle ? windowTitle : progressNameIdTitle, |
140 |
| - score == windowTitleMatch.Score ? windowTitleMatch : null, |
141 |
| - progressNameIdTitle)); |
142 |
| - } |
143 |
| - } |
144 |
| - else |
145 |
| - { |
146 |
| - var processNameIdMatch = _context.API.FuzzySearch(searchTerm, progressNameIdTitle); |
147 |
| - var score = processNameIdMatch.Score; |
148 |
| - if (score > 0) |
149 |
| - { |
150 |
| - processlist.Add(new ProcessResult( |
151 |
| - p, |
152 |
| - score, |
153 |
| - progressNameIdTitle, |
154 |
| - processNameIdMatch, |
155 |
| - progressNameIdTitle)); |
156 |
| - } |
157 |
| - } |
158 |
| - } |
159 |
| - } |
| 159 | + } |
160 | 160 |
|
161 |
| - var results = new List<Result>(); |
162 |
| - foreach (var pr in processlist) |
| 161 | + var results = new List<Result>(); |
| 162 | + foreach (var pr in processlist) |
| 163 | + { |
| 164 | + var p = pr.Process; |
| 165 | + var path = ProcessHelper.TryGetProcessFilename(p); |
| 166 | + results.Add(new Result() |
163 | 167 | {
|
164 |
| - var p = pr.Process; |
165 |
| - var path = processHelper.TryGetProcessFilename(p); |
166 |
| - results.Add(new Result() |
| 168 | + IcoPath = path, |
| 169 | + Title = pr.Title, |
| 170 | + TitleToolTip = pr.Tooltip, |
| 171 | + SubTitle = path, |
| 172 | + TitleHighlightData = pr.TitleMatch?.MatchData, |
| 173 | + Score = pr.Score, |
| 174 | + ContextData = p.ProcessName, |
| 175 | + AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword}{Plugin.Query.TermSeparator}{p.ProcessName}", |
| 176 | + Action = (c) => |
167 | 177 | {
|
168 |
| - IcoPath = path, |
169 |
| - Title = pr.Title, |
170 |
| - TitleToolTip = pr.Tooltip, |
171 |
| - SubTitle = path, |
172 |
| - TitleHighlightData = pr.TitleMatch?.MatchData, |
173 |
| - Score = pr.Score, |
174 |
| - ContextData = p.ProcessName, |
175 |
| - AutoCompleteText = $"{_context.CurrentPluginMetadata.ActionKeyword}{Plugin.Query.TermSeparator}{p.ProcessName}", |
176 |
| - Action = (c) => |
177 |
| - { |
178 |
| - processHelper.TryKill(_context, p); |
179 |
| - // Re-query to refresh process list |
180 |
| - _context.API.ReQuery(); |
181 |
| - return true; |
182 |
| - } |
183 |
| - }); |
184 |
| - } |
| 178 | + ProcessHelper.TryKill(p); |
| 179 | + // Re-query to refresh process list |
| 180 | + Context.API.ReQuery(); |
| 181 | + return true; |
| 182 | + } |
| 183 | + }); |
| 184 | + } |
185 | 185 |
|
186 |
| - // Order results by process name for processes without visible windows |
187 |
| - var sortedResults = results.OrderBy(x => x.Title).ToList(); |
| 186 | + // Order results by process name for processes without visible windows |
| 187 | + var sortedResults = results.OrderBy(x => x.Title).ToList(); |
188 | 188 |
|
189 |
| - // When there are multiple results AND all of them are instances of the same executable |
190 |
| - // add a quick option to kill them all at the top of the results. |
191 |
| - var firstResult = sortedResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.SubTitle)); |
192 |
| - if (processlist.Count > 1 && !string.IsNullOrEmpty(searchTerm) && sortedResults.All(r => r.SubTitle == firstResult?.SubTitle)) |
| 189 | + // When there are multiple results AND all of them are instances of the same executable |
| 190 | + // add a quick option to kill them all at the top of the results. |
| 191 | + var firstResult = sortedResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.SubTitle)); |
| 192 | + if (processlist.Count > 1 && !string.IsNullOrEmpty(searchTerm) && sortedResults.All(r => r.SubTitle == firstResult?.SubTitle)) |
| 193 | + { |
| 194 | + sortedResults.Insert(1, new Result() |
193 | 195 | {
|
194 |
| - sortedResults.Insert(1, new Result() |
| 196 | + IcoPath = firstResult?.IcoPath, |
| 197 | + Title = string.Format(Context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_all"), firstResult?.ContextData), |
| 198 | + SubTitle = string.Format(Context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_all_count"), processlist.Count), |
| 199 | + Score = 200, |
| 200 | + Action = (c) => |
195 | 201 | {
|
196 |
| - IcoPath = firstResult?.IcoPath, |
197 |
| - Title = string.Format(_context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_all"), firstResult?.ContextData), |
198 |
| - SubTitle = string.Format(_context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_all_count"), processlist.Count), |
199 |
| - Score = 200, |
200 |
| - Action = (c) => |
| 202 | + foreach (var p in processlist) |
201 | 203 | {
|
202 |
| - foreach (var p in processlist) |
203 |
| - { |
204 |
| - processHelper.TryKill(_context, p.Process); |
205 |
| - } |
206 |
| - // Re-query to refresh process list |
207 |
| - _context.API.ReQuery(); |
208 |
| - return true; |
| 204 | + ProcessHelper.TryKill(p.Process); |
209 | 205 | }
|
210 |
| - }); |
211 |
| - } |
212 |
| - |
213 |
| - return sortedResults; |
| 206 | + // Re-query to refresh process list |
| 207 | + Context.API.ReQuery(); |
| 208 | + return true; |
| 209 | + } |
| 210 | + }); |
214 | 211 | }
|
215 | 212 |
|
216 |
| - public Control CreateSettingPanel() |
217 |
| - { |
218 |
| - return new SettingsControl(_viewModel); |
219 |
| - } |
| 213 | + return sortedResults; |
| 214 | + } |
| 215 | + |
| 216 | + public Control CreateSettingPanel() |
| 217 | + { |
| 218 | + return new SettingsControl(_viewModel); |
220 | 219 | }
|
221 | 220 | }
|
0 commit comments