mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-10 06:17:01 +01:00
Compare commits
1 Commits
leilzh/add
...
leilzh/Bgc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6b3baae96 |
@@ -43,7 +43,6 @@ stages:
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
runTests: true
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
timeoutInMinutes: 90
|
||||
|
||||
- stage: OneFuzz
|
||||
displayName: Fuzz ${{ parameters.platform }}
|
||||
|
||||
@@ -81,12 +81,6 @@ parameters:
|
||||
- 'src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj'
|
||||
- 'src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.csproj'
|
||||
- 'src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithUI.csproj'
|
||||
- name: timeoutInMinutes
|
||||
type: number
|
||||
default: 240
|
||||
- name: cancelTimeoutInMinutes
|
||||
type: number
|
||||
default: 1
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.jobName }}
|
||||
@@ -129,8 +123,8 @@ jobs:
|
||||
${{ else }}:
|
||||
RestoreAdditionalProjectSourcesArg: ''
|
||||
displayName: Build
|
||||
timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
|
||||
cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }}
|
||||
timeoutInMinutes: 240
|
||||
cancelTimeoutInMinutes: 1
|
||||
templateContext: # Required when this template is hosted in 1ES PT
|
||||
outputs:
|
||||
- output: pipelineArtifact
|
||||
|
||||
@@ -57,5 +57,4 @@ stages:
|
||||
useLatestWinAppSDK: ${{ parameters.useLatestWinAppSDK }}
|
||||
${{ if eq(parameters.useLatestWinAppSDK, true) }}:
|
||||
winAppSDKVersionNumber: ${{ parameters.winAppSDKVersionNumber }}
|
||||
useExperimentalVersion: ${{ parameters.useExperimentalVersion }}
|
||||
timeoutInMinutes: 90
|
||||
useExperimentalVersion: ${{ parameters.useExperimentalVersion }}
|
||||
@@ -56,7 +56,6 @@ stages:
|
||||
runTests: false
|
||||
buildTests: true
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
timeoutInMinutes: 90
|
||||
|
||||
- ${{ if eq(parameters.useLatestOfficialBuild, true) }}:
|
||||
- stage: BuildUITests_${{ platform }}
|
||||
|
||||
@@ -47,8 +47,6 @@ Contact the developers of a plugin directly for assistance with a specific plugi
|
||||
| [Weather](https://github.com/ruslanlap/PowerToysRun-Weather) | [ruslanlap](https://github.com/ruslanlap) | Get real-time weather information directly from PowerToys Run. |
|
||||
| [Pomodoro](https://github.com/ruslanlap/PowerToysRun-Pomodoro) | [ruslanlap](https://github.com/ruslanlap) | Manage Pomodoro productivity sessions directly from PowerToys Run. |
|
||||
| [Definition](https://github.com/ruslanlap/PowerToysRun-Definition) | [ruslanlap](https://github.com/ruslanlap) | Lookup word definitions, phonetics, and synonyms directly in PowerToys Run. |
|
||||
| [Hotkeys](https://github.com/ruslanlap/PowerToysRun-Hotkeys) | [ruslanlap](https://github.com/ruslanlap) | Create, manage, and trigger custom keyboard shortcuts directly from PowerToys Run. |
|
||||
| [RandomGen](https://github.com/ruslanlap/PowerToysRun-RandomGen) | [ruslanlap](https://github.com/ruslanlap) | 🎲 Generate random data instantly with a single keystroke. Perfect for developers, testers, designers, and anyone who needs quick access to random data. Features include secure passwords, PINs, names, business data, dates, numbers, GUIDs, color codes, and more. Especially useful for designers who need random color codes and placeholder content. |
|
||||
|
||||
## Extending software plugins
|
||||
|
||||
|
||||
@@ -122,31 +122,23 @@ namespace Microsoft.PowerToys.UITest
|
||||
public void StartExe(string appPath, string[]? args = null)
|
||||
{
|
||||
var opts = new AppiumOptions();
|
||||
opts.AddAdditionalCapability("app", appPath);
|
||||
|
||||
if (scope == PowerToysModule.PowerToysSettings)
|
||||
if (args != null && args.Length > 0)
|
||||
{
|
||||
TryLaunchPowerToysSettings(opts);
|
||||
}
|
||||
else
|
||||
{
|
||||
opts.AddAdditionalCapability("app", appPath);
|
||||
|
||||
if (args != null && args.Length > 0)
|
||||
// Build command line arguments string
|
||||
string argsString = string.Join(" ", args.Select(arg =>
|
||||
{
|
||||
// Build command line arguments string
|
||||
string argsString = string.Join(" ", args.Select(arg =>
|
||||
// Quote arguments that contain spaces
|
||||
if (arg.Contains(' '))
|
||||
{
|
||||
// Quote arguments that contain spaces
|
||||
if (arg.Contains(' '))
|
||||
{
|
||||
return $"\"{arg}\"";
|
||||
}
|
||||
return $"\"{arg}\"";
|
||||
}
|
||||
|
||||
return arg;
|
||||
}));
|
||||
return arg;
|
||||
}));
|
||||
|
||||
opts.AddAdditionalCapability("appArguments", argsString);
|
||||
}
|
||||
opts.AddAdditionalCapability("appArguments", argsString);
|
||||
}
|
||||
|
||||
this.Driver = NewWindowsDriver(opts);
|
||||
|
||||
@@ -19,13 +19,13 @@ public interface IExtensionService
|
||||
|
||||
Task SignalStopExtensionsAsync();
|
||||
|
||||
event TypedEventHandler<IExtensionService, IEnumerable<IExtensionWrapper>>? OnExtensionAdded;
|
||||
public event TypedEventHandler<IExtensionService, IEnumerable<IExtensionWrapper>>? OnExtensionAdded;
|
||||
|
||||
event TypedEventHandler<IExtensionService, IEnumerable<IExtensionWrapper>>? OnExtensionRemoved;
|
||||
public event TypedEventHandler<IExtensionService, IEnumerable<IExtensionWrapper>>? OnExtensionRemoved;
|
||||
|
||||
void EnableExtension(string extensionUniqueId);
|
||||
public void EnableExtension(string extensionUniqueId);
|
||||
|
||||
void DisableExtension(string extensionUniqueId);
|
||||
public void DisableExtension(string extensionUniqueId);
|
||||
|
||||
///// <summary>
|
||||
///// Gets a boolean indicating whether the extension was disabled due to the corresponding Windows optional feature
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.CmdPal.Common.Services;
|
||||
|
||||
public interface IRootPageService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the root page of the command palette. Return any IPage implementation that
|
||||
/// represents the root view of this instance of the command palette.
|
||||
/// </summary>
|
||||
Microsoft.CommandPalette.Extensions.IPage GetRootPage();
|
||||
|
||||
/// <summary>
|
||||
/// Pre-loads any necessary data or state before the root page is loaded.
|
||||
/// This will be awaited before the root page and the user can do anything,
|
||||
/// so ideally it should be quick and not block the UI thread for long.
|
||||
/// </summary>
|
||||
Task PreLoadAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Do any loading work that can be done after the root page is loaded and
|
||||
/// displayed to the user.
|
||||
/// This is run asynchronously, on a background thread.
|
||||
/// </summary>
|
||||
Task PostLoadRootPageAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Called when a top-level command is performed. The context is the
|
||||
/// sender context for the invoked command. This is typically the IListItem
|
||||
/// or ICommandContextItem that was used to invoke the command.
|
||||
/// </summary>
|
||||
void OnPerformTopLevelCommand(object? context);
|
||||
}
|
||||
@@ -9,9 +9,11 @@ using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Common.Services;
|
||||
using Microsoft.CmdPal.UI.ViewModels.MainPage;
|
||||
using Microsoft.CmdPal.UI.ViewModels.Messages;
|
||||
using Microsoft.CmdPal.UI.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using WinRT;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
@@ -19,7 +21,7 @@ namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
public partial class ShellViewModel : ObservableObject,
|
||||
IRecipient<PerformCommandMessage>
|
||||
{
|
||||
private readonly IRootPageService _rootPageService;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly TaskScheduler _scheduler;
|
||||
private readonly Lock _invokeLock = new();
|
||||
private Task? _handleInvokeTask;
|
||||
@@ -58,17 +60,17 @@ public partial class ShellViewModel : ObservableObject,
|
||||
}
|
||||
}
|
||||
|
||||
private IPage? _rootPage;
|
||||
private MainListPage? _mainListPage;
|
||||
|
||||
private IExtensionWrapper? _activeExtension;
|
||||
private bool _isNested;
|
||||
|
||||
public bool IsNested { get => _isNested; }
|
||||
|
||||
public ShellViewModel(TaskScheduler scheduler, IRootPageService rootPageService)
|
||||
public ShellViewModel(IServiceProvider serviceProvider, TaskScheduler scheduler)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_scheduler = scheduler;
|
||||
_rootPageService = rootPageService;
|
||||
_currentPage = new LoadingPageViewModel(null, _scheduler);
|
||||
|
||||
// Register to receive messages
|
||||
@@ -78,27 +80,24 @@ public partial class ShellViewModel : ObservableObject,
|
||||
[RelayCommand]
|
||||
public async Task<bool> LoadAsync()
|
||||
{
|
||||
// First, do any loading that the root page service needs to do before we can
|
||||
// display the root page. For example, this might include loading
|
||||
// the built-in commands, or loading the settings.
|
||||
await _rootPageService.PreLoadAsync();
|
||||
|
||||
var tlcManager = _serviceProvider.GetService<TopLevelCommandManager>();
|
||||
await tlcManager!.LoadBuiltinsAsync();
|
||||
IsLoaded = true;
|
||||
|
||||
// Now that the basics are set up, we can load the root page.
|
||||
_rootPage = _rootPageService.GetRootPage();
|
||||
// Built-ins have loaded. We can display our page at this point.
|
||||
_mainListPage = new MainListPage(_serviceProvider);
|
||||
WeakReferenceMessenger.Default.Send<PerformCommandMessage>(new(new ExtensionObject<ICommand>(_mainListPage)));
|
||||
|
||||
// This sends a message to us to load the root page view model.
|
||||
WeakReferenceMessenger.Default.Send<PerformCommandMessage>(new(new ExtensionObject<ICommand>(_rootPage)));
|
||||
|
||||
// Now that the root page is loaded, do any post-load work that the root page service needs to do.
|
||||
// This runs asynchronously, on a background thread.
|
||||
// This might include starting extensions, for example.
|
||||
// Note: We don't await this, so that we can return immediately.
|
||||
// This is important because we don't want to block the UI thread.
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await _rootPageService.PostLoadRootPageAsync();
|
||||
// After loading built-ins, and starting navigation, kick off a thread to load extensions.
|
||||
tlcManager.LoadExtensionsCommand.Execute(null);
|
||||
|
||||
await tlcManager.LoadExtensionsCommand.ExecutionTask!;
|
||||
if (tlcManager.LoadExtensionsCommand.ExecutionTask.Status != TaskStatus.RanToCompletion)
|
||||
{
|
||||
// TODO: Handle failure case
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
@@ -173,7 +172,15 @@ public partial class ShellViewModel : ObservableObject,
|
||||
|
||||
public void PerformTopLevelCommand(PerformCommandMessage message)
|
||||
{
|
||||
_rootPageService.OnPerformTopLevelCommand(message.Context);
|
||||
if (_mainListPage == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.Context is IListItem listItem)
|
||||
{
|
||||
_mainListPage.UpdateHistory(listItem);
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PerformCommandMessage message)
|
||||
@@ -248,11 +255,10 @@ public partial class ShellViewModel : ObservableObject,
|
||||
{
|
||||
Logger.LogDebug($"Navigating to page");
|
||||
|
||||
var isMainPage = command == _rootPage;
|
||||
_isNested = !isMainPage;
|
||||
var isMainPage = command is MainListPage;
|
||||
|
||||
// Construct our ViewModel of the appropriate type and pass it the UI Thread context.
|
||||
var pageViewModel = GetViewModelForPage(page, _isNested, host);
|
||||
var pageViewModel = GetViewModelForPage(page, !isMainPage, host);
|
||||
if (pageViewModel == null)
|
||||
{
|
||||
Logger.LogError($"Failed to create ViewModel for page {page.GetType().Name}");
|
||||
@@ -261,6 +267,8 @@ public partial class ShellViewModel : ObservableObject,
|
||||
|
||||
// Kick off async loading of our ViewModel
|
||||
LoadPageViewModel(pageViewModel);
|
||||
_isNested = !isMainPage;
|
||||
|
||||
OnUIThread(() => { WeakReferenceMessenger.Default.Send<UpdateCommandBarMessage>(new(null)); });
|
||||
WeakReferenceMessenger.Default.Send<NavigateToPageMessage>(new(pageViewModel, message.WithAnimation));
|
||||
|
||||
|
||||
@@ -144,7 +144,6 @@ public partial class App : Application
|
||||
services.AddSingleton<IExtensionService, ExtensionService>();
|
||||
services.AddSingleton<TrayIconService>();
|
||||
|
||||
services.AddSingleton<IRootPageService, PowerToysRootPageService>();
|
||||
services.AddSingleton(new TelemetryForwarder());
|
||||
|
||||
// ViewModels
|
||||
|
||||
@@ -162,6 +162,10 @@ public sealed partial class SearchBar : UserControl,
|
||||
CurrentPageViewModel.Filter = FilterBox.Text;
|
||||
}
|
||||
}
|
||||
else if (e.Key == VirtualKey.Left && altPressed)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send<NavigateBackMessage>(new());
|
||||
}
|
||||
|
||||
if (!e.Handled)
|
||||
{
|
||||
|
||||
@@ -107,7 +107,7 @@ public sealed partial class MainWindow : WindowEx,
|
||||
App.Current.Services.GetService<SettingsModel>()!.SettingsChanged += SettingsChangedHandler;
|
||||
|
||||
// Make sure that we update the acrylic theme when the OS theme changes
|
||||
RootShellPage.ActualThemeChanged += (s, e) => DispatcherQueue.TryEnqueue(UpdateAcrylic);
|
||||
RootShellPage.ActualThemeChanged += (s, e) => UpdateAcrylic();
|
||||
|
||||
// Hardcoding event name to avoid bringing in the PowerToys.interop dependency. Event name must match CMDPAL_SHOW_EVENT from shared_constants.h
|
||||
NativeEventWaiter.WaitForEventLoop("Local\\PowerToysCmdPal-ShowEvent-62336fcd-8611-4023-9b30-091a6af4cc5a", () =>
|
||||
@@ -175,8 +175,6 @@ public sealed partial class MainWindow : WindowEx,
|
||||
|
||||
private void UpdateAcrylic()
|
||||
{
|
||||
_acrylicController?.RemoveAllSystemBackdropTargets();
|
||||
|
||||
_acrylicController = GetAcrylicConfig(Content);
|
||||
|
||||
// Enable the system backdrop.
|
||||
|
||||
@@ -20,7 +20,6 @@ using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using DispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue;
|
||||
using VirtualKey = Windows.System.VirtualKey;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Pages;
|
||||
|
||||
@@ -82,7 +81,6 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
|
||||
WeakReferenceMessenger.Default.Register<ShowToastMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<NavigateToPageMessage>(this);
|
||||
|
||||
AddHandler(PreviewKeyDownEvent, new KeyEventHandler(ShellPage_OnPreviewKeyDown), true);
|
||||
AddHandler(PointerPressedEvent, new PointerEventHandler(ShellPage_OnPointerPressed), true);
|
||||
|
||||
RootFrame.Navigate(typeof(LoadingPage), ViewModel);
|
||||
@@ -449,14 +447,6 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
|
||||
}
|
||||
}
|
||||
|
||||
private void ShellPage_OnPreviewKeyDown(object sender, KeyRoutedEventArgs e)
|
||||
{
|
||||
if (e.Key == VirtualKey.Left && e.KeyStatus.IsMenuKeyDown)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send<NavigateBackMessage>(new());
|
||||
}
|
||||
}
|
||||
|
||||
private void ShellPage_OnPointerPressed(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Common.Services;
|
||||
using Microsoft.CmdPal.UI.ViewModels;
|
||||
using Microsoft.CmdPal.UI.ViewModels.MainPage;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
namespace Microsoft.CmdPal.UI;
|
||||
|
||||
internal sealed class PowerToysRootPageService : IRootPageService
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private Lazy<MainListPage> _mainListPage;
|
||||
|
||||
public PowerToysRootPageService(IServiceProvider serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
|
||||
_mainListPage = new Lazy<MainListPage>(() =>
|
||||
{
|
||||
return new MainListPage(_serviceProvider);
|
||||
});
|
||||
}
|
||||
|
||||
public async Task PreLoadAsync()
|
||||
{
|
||||
var tlcManager = _serviceProvider.GetService<TopLevelCommandManager>()!;
|
||||
await tlcManager.LoadBuiltinsAsync();
|
||||
}
|
||||
|
||||
public Microsoft.CommandPalette.Extensions.IPage GetRootPage()
|
||||
{
|
||||
return _mainListPage.Value;
|
||||
}
|
||||
|
||||
public async Task PostLoadRootPageAsync()
|
||||
{
|
||||
var tlcManager = _serviceProvider.GetService<TopLevelCommandManager>()!;
|
||||
|
||||
// After loading built-ins, and starting navigation, kick off a thread to load extensions.
|
||||
tlcManager.LoadExtensionsCommand.Execute(null);
|
||||
|
||||
await tlcManager.LoadExtensionsCommand.ExecutionTask!;
|
||||
if (tlcManager.LoadExtensionsCommand.ExecutionTask.Status != TaskStatus.RanToCompletion)
|
||||
{
|
||||
// TODO: Handle failure case
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPerformTopLevelCommand(object? context)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (context is IListItem listItem)
|
||||
{
|
||||
_mainListPage.Value.UpdateHistory(listItem);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed to update history in PowerToysRootPageService");
|
||||
Logger.LogError(ex.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,6 @@ internal sealed partial class FallbackOpenURLItem : FallbackCommandItem
|
||||
{
|
||||
if (!IsValidUrl(query))
|
||||
{
|
||||
_executeItem.Url = string.Empty;
|
||||
_executeItem.Name = string.Empty;
|
||||
Title = string.Empty;
|
||||
Subtitle = string.Empty;
|
||||
return;
|
||||
|
||||
@@ -23,31 +23,28 @@ internal sealed partial class WebSearchListPage : DynamicListPage
|
||||
private readonly SettingsManager _settingsManager;
|
||||
private static readonly CompositeFormat PluginInBrowserName = System.Text.CompositeFormat.Parse(Properties.Resources.plugin_in_browser_name);
|
||||
private static readonly CompositeFormat PluginOpen = System.Text.CompositeFormat.Parse(Properties.Resources.plugin_open);
|
||||
private List<ListItem> _allItems;
|
||||
private List<ListItem> allItems;
|
||||
|
||||
public WebSearchListPage(SettingsManager settingsManager)
|
||||
{
|
||||
Name = Resources.command_item_title;
|
||||
Title = Resources.command_item_title;
|
||||
PlaceholderText = Resources.plugin_description;
|
||||
Icon = IconHelpers.FromRelativePath("Assets\\WebSearch.png");
|
||||
_allItems = [];
|
||||
allItems = [new(new NoOpCommand())
|
||||
{
|
||||
Icon = IconHelpers.FromRelativePath("Assets\\WebSearch.png"),
|
||||
Title = Properties.Resources.plugin_description,
|
||||
Subtitle = string.Format(CultureInfo.CurrentCulture, PluginOpen, BrowserInfo.Name ?? BrowserInfo.MSEdgeName),
|
||||
}
|
||||
];
|
||||
Id = "com.microsoft.cmdpal.websearch";
|
||||
_settingsManager = settingsManager;
|
||||
_historyItems = _settingsManager.ShowHistory != Resources.history_none ? _settingsManager.LoadHistory() : null;
|
||||
if (_historyItems != null)
|
||||
{
|
||||
_allItems.AddRange(_historyItems);
|
||||
allItems.AddRange(_historyItems);
|
||||
}
|
||||
|
||||
// It just looks viewer to have string twice on the page, and default placeholder is good enough
|
||||
PlaceholderText = _allItems.Count > 0 ? Resources.plugin_description : string.Empty;
|
||||
|
||||
EmptyContent = new CommandItem(new NoOpCommand())
|
||||
{
|
||||
Icon = Icon,
|
||||
Title = Properties.Resources.plugin_description,
|
||||
Subtitle = string.Format(CultureInfo.CurrentCulture, PluginInBrowserName, BrowserInfo.Name ?? BrowserInfo.MSEdgeName),
|
||||
};
|
||||
}
|
||||
|
||||
public List<ListItem> Query(string query)
|
||||
@@ -62,7 +59,17 @@ internal sealed partial class WebSearchListPage : DynamicListPage
|
||||
|
||||
var results = new List<ListItem>();
|
||||
|
||||
if (!string.IsNullOrEmpty(query))
|
||||
// empty query
|
||||
if (string.IsNullOrEmpty(query))
|
||||
{
|
||||
results.Add(new ListItem(new SearchWebCommand(string.Empty, _settingsManager))
|
||||
{
|
||||
Title = Properties.Resources.plugin_description,
|
||||
Subtitle = string.Format(CultureInfo.CurrentCulture, PluginInBrowserName, BrowserInfo.Name ?? BrowserInfo.MSEdgeName),
|
||||
Icon = new IconInfo(_iconPath),
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
var searchTerm = query;
|
||||
var result = new ListItem(new SearchWebCommand(searchTerm, _settingsManager))
|
||||
@@ -84,9 +91,9 @@ internal sealed partial class WebSearchListPage : DynamicListPage
|
||||
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch)
|
||||
{
|
||||
_allItems = [.. Query(newSearch)];
|
||||
allItems = [.. Query(newSearch)];
|
||||
RaiseItemsChanged(0);
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems() => [.. _allItems];
|
||||
public override IListItem[] GetItems() => [.. allItems];
|
||||
}
|
||||
|
||||
@@ -90,12 +90,14 @@ namespace Peek.FilePreviewer.Previewers
|
||||
unsafe
|
||||
{
|
||||
// This runs the preview handler in a separate process (prevhost.exe)
|
||||
// TODO: Figure out how to get it to run in a low integrity level
|
||||
if (!HandlerFactories.TryGetValue(clsid, out var factory))
|
||||
{
|
||||
var hr = PInvoke_FilePreviewer.CoGetClassObject(clsid, CLSCTX.CLSCTX_LOCAL_SERVER, null, typeof(IClassFactory).GUID, out object pFactory);
|
||||
Marshal.ThrowExceptionForHR(hr);
|
||||
|
||||
// Storing the factory in memory helps makes the handlers load faster
|
||||
// TODO: Maybe free them after some inactivity or when Peek quits?
|
||||
factory = (IClassFactory)pFactory;
|
||||
factory.LockServer(true);
|
||||
HandlerFactories.AddOrUpdate(clsid, factory, (_, _) => factory);
|
||||
@@ -211,20 +213,6 @@ namespace Peek.FilePreviewer.Previewers
|
||||
return !string.IsNullOrEmpty(GetPreviewHandlerGuid(item.Extension));
|
||||
}
|
||||
|
||||
public static void ReleaseHandlerFactories()
|
||||
{
|
||||
foreach (var factory in HandlerFactories.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
Marshal.FinalReleaseComObject(factory);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string? GetPreviewHandlerGuid(string fileExt)
|
||||
{
|
||||
const string PreviewHandlerKeyPath = "shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}";
|
||||
|
||||
@@ -12,7 +12,6 @@ using Microsoft.UI.Xaml;
|
||||
using Peek.Common;
|
||||
using Peek.FilePreviewer;
|
||||
using Peek.FilePreviewer.Models;
|
||||
using Peek.FilePreviewer.Previewers;
|
||||
using Peek.UI.Native;
|
||||
using Peek.UI.Telemetry.Events;
|
||||
using Peek.UI.Views;
|
||||
@@ -112,7 +111,6 @@ namespace Peek.UI
|
||||
NativeEventWaiter.WaitForEventLoop(Constants.ShowPeekEvent(), OnPeekHotkey);
|
||||
NativeEventWaiter.WaitForEventLoop(Constants.TerminatePeekEvent(), () =>
|
||||
{
|
||||
ShellPreviewHandlerPreviewer.ReleaseHandlerFactories();
|
||||
EtwTrace?.Dispose();
|
||||
Environment.Exit(0);
|
||||
});
|
||||
|
||||
@@ -15,7 +15,6 @@ using Microsoft.UI.Xaml.Input;
|
||||
using Peek.Common.Constants;
|
||||
using Peek.Common.Extensions;
|
||||
using Peek.FilePreviewer.Models;
|
||||
using Peek.FilePreviewer.Previewers;
|
||||
using Peek.UI.Extensions;
|
||||
using Peek.UI.Helpers;
|
||||
using Peek.UI.Telemetry.Events;
|
||||
@@ -205,8 +204,6 @@ namespace Peek.UI
|
||||
ViewModel.ScalingFactor = 1;
|
||||
|
||||
this.Content.KeyUp -= Content_KeyUp;
|
||||
|
||||
ShellPreviewHandlerPreviewer.ReleaseHandlerFactories();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -405,19 +405,13 @@ public:
|
||||
{
|
||||
ResetEvent(m_hInvokeEvent);
|
||||
SetEvent(m_hTerminateEvent);
|
||||
|
||||
HANDLE hProcess = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE, m_processPid);
|
||||
if (WaitForSingleObject(hProcess, 1500) == WAIT_TIMEOUT)
|
||||
WaitForSingleObject(m_hProcess, 1500);
|
||||
auto result = TerminateProcess(m_hProcess, 1);
|
||||
if (result == 0)
|
||||
{
|
||||
auto result = TerminateProcess(hProcess, 1);
|
||||
if (result == 0)
|
||||
{
|
||||
int error = GetLastError();
|
||||
Logger::trace("Couldn't terminate the process. Last error: {}", error);
|
||||
}
|
||||
int error = GetLastError();
|
||||
Logger::trace("Couldn't terminate the process. Last error: {}", error);
|
||||
}
|
||||
|
||||
CloseHandle(hProcess);
|
||||
CloseHandle(m_hProcess);
|
||||
m_hProcess = 0;
|
||||
m_processPid = 0;
|
||||
|
||||
@@ -51,7 +51,6 @@ namespace PowerAccent.Core
|
||||
SR_CYRL,
|
||||
SV,
|
||||
TK,
|
||||
VI,
|
||||
}
|
||||
|
||||
internal sealed class Languages
|
||||
@@ -114,7 +113,6 @@ namespace PowerAccent.Core
|
||||
Language.SR_CYRL => GetDefaultLetterKeySRCyrillic(letter), // Serbian Cyrillic
|
||||
Language.SV => GetDefaultLetterKeySV(letter), // Swedish
|
||||
Language.TK => GetDefaultLetterKeyTK(letter), // Turkish
|
||||
Language.VI => GetDefaultLetterKeyVI(letter), // Vietnamese
|
||||
_ => throw new ArgumentException("The language {0} is not known in this context", lang.ToString()),
|
||||
});
|
||||
}
|
||||
@@ -170,7 +168,6 @@ namespace PowerAccent.Core
|
||||
.Union(GetDefaultLetterKeySRCyrillic(letter))
|
||||
.Union(GetDefaultLetterKeySV(letter))
|
||||
.Union(GetDefaultLetterKeyTK(letter))
|
||||
.Union(GetDefaultLetterKeyVI(letter))
|
||||
.Union(GetDefaultLetterKeySPECIAL(letter))
|
||||
.ToArray();
|
||||
|
||||
@@ -893,22 +890,6 @@ namespace PowerAccent.Core
|
||||
};
|
||||
}
|
||||
|
||||
// Vietnamese
|
||||
private static string[] GetDefaultLetterKeyVI(LetterKey letter)
|
||||
{
|
||||
return letter switch
|
||||
{
|
||||
LetterKey.VK_A => new[] { "à", "ả", "ã", "á", "ạ", "ă", "ằ", "ẳ", "ẵ", "ắ", "ặ", "â", "ầ", "ẩ", "ẫ", "ấ", "ậ" },
|
||||
LetterKey.VK_D => new[] { "đ" },
|
||||
LetterKey.VK_E => new[] { "è", "ẻ", "ẽ", "é", "ẹ", "ê", "ề", "ể", "ễ", "ế", "ệ" },
|
||||
LetterKey.VK_I => new[] { "ì", "ỉ", "ĩ", "í", "ị" },
|
||||
LetterKey.VK_O => new[] { "ò", "ỏ", "õ", "ó", "ọ", "ô", "ồ", "ổ", "ỗ", "ố", "ộ", "ơ", "ờ", "ở", "ỡ", "ớ", "ợ" },
|
||||
LetterKey.VK_U => new[] { "ù", "ủ", "ũ", "ú", "ụ", "ư", "ừ", "ử", "ữ", "ứ", "ự" },
|
||||
LetterKey.VK_Y => new[] { "ỳ", "ỷ", "ỹ", "ý", "ỵ" },
|
||||
_ => Array.Empty<string>(),
|
||||
};
|
||||
}
|
||||
|
||||
// IPA (International Phonetic Alphabet)
|
||||
private static string[] GetDefaultLetterKeyIPA(LetterKey letter)
|
||||
{
|
||||
|
||||
@@ -3566,9 +3566,6 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="QuickAccent_SelectedLanguage_Turkish" xml:space="preserve">
|
||||
<value>Turkish</value>
|
||||
</data>
|
||||
<data name="QuickAccent_SelectedLanguage_Vietnamese" xml:space="preserve">
|
||||
<value>Vietnamese</value>
|
||||
</data>
|
||||
<data name="QuickAccent_SelectedLanguage_Icelandic" xml:space="preserve">
|
||||
<value>Icelandic</value>
|
||||
</data>
|
||||
|
||||
@@ -67,7 +67,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
new PowerAccentLanguageModel("SR_CYRL", "QuickAccent_SelectedLanguage_Serbian_Cyrillic", LanguageGroup),
|
||||
new PowerAccentLanguageModel("SV", "QuickAccent_SelectedLanguage_Swedish", LanguageGroup),
|
||||
new PowerAccentLanguageModel("TK", "QuickAccent_SelectedLanguage_Turkish", LanguageGroup),
|
||||
new PowerAccentLanguageModel("VI", "QuickAccent_SelectedLanguage_Vietnamese", LanguageGroup),
|
||||
new PowerAccentLanguageModel("CY", "QuickAccent_SelectedLanguage_Welsh", LanguageGroup),
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user