mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-09 22:06:51 +01:00
Compare commits
1 Commits
khmyznikov
...
leilzh/add
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a0abecba2 |
1
.github/actions/spell-check/expect.txt
vendored
1
.github/actions/spell-check/expect.txt
vendored
@@ -1383,7 +1383,6 @@ RIGHTSCROLLBAR
|
||||
riid
|
||||
RKey
|
||||
RNumber
|
||||
Rns
|
||||
rop
|
||||
ROUNDSMALL
|
||||
ROWSETEXT
|
||||
|
||||
@@ -38,11 +38,6 @@ parameters:
|
||||
displayName: "Build Using Visual Studio Preview"
|
||||
default: false
|
||||
|
||||
- name: enableAOT
|
||||
type: boolean
|
||||
displayName: "Enable AOT (Ahead-of-Time) Compilation for CmdPal"
|
||||
default: true
|
||||
|
||||
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
|
||||
|
||||
variables:
|
||||
@@ -100,7 +95,7 @@ extends:
|
||||
useManagedIdentity: $(SigningUseManagedIdentity)
|
||||
clientId: $(SigningOriginalClientId)
|
||||
# Have msbuild use the release nuget config profile
|
||||
additionalBuildOptions: /p:RestoreConfigFile="$(Build.SourcesDirectory)\.pipelines\release-nuget.config" /p:EnableCmdPalAOT=${{ parameters.enableAOT }}
|
||||
additionalBuildOptions: /p:RestoreConfigFile="$(Build.SourcesDirectory)\.pipelines\release-nuget.config"
|
||||
beforeBuildSteps:
|
||||
# Sets versions for all PowerToy created DLLs
|
||||
- pwsh: |-
|
||||
|
||||
@@ -19,7 +19,7 @@ Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude *UITest*,MouseJum
|
||||
# Temporarily exclude All UI-Test, Fuzzer-Test projects because of Appium.WebDriver dependencies
|
||||
$depsJsonFullFileName = $_.FullName
|
||||
|
||||
if ($depsJsonFullFileName -like "*CmdPal*" -or $depsJsonFullFileName -like "*CommandPalette*") {
|
||||
if ($depsJsonFullFileName -like "*CmdPal*") {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.Markdown" Version="7.1.2" />
|
||||
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" Version="0.1.250703-build.2173" />
|
||||
<PackageVersion Include="ControlzEx" Version="6.0.0" />
|
||||
<PackageVersion Include="HelixToolkit" Version="2.24.0" />
|
||||
<PackageVersion Include="HelixToolkit.Core.Wpf" Version="2.24.0" />
|
||||
|
||||
@@ -1497,7 +1497,6 @@ SOFTWARE.
|
||||
- Appium.WebDriver 4.4.5
|
||||
- Azure.AI.OpenAI 1.0.0-beta.17
|
||||
- CommunityToolkit.Common 8.4.0
|
||||
- CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock 0.1.250703-build.2173
|
||||
- CommunityToolkit.Mvvm 8.4.0
|
||||
- CommunityToolkit.WinUI.Animations 8.2.250402
|
||||
- CommunityToolkit.WinUI.Collections 8.2.250402
|
||||
@@ -1580,3 +1579,4 @@ SOFTWARE.
|
||||
- WinUIEx 2.2.0
|
||||
- WPF-UI 3.0.5
|
||||
- WyHash 1.0.5
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ Welcome to the PowerToys developer documentation. This documentation provides in
|
||||
|
||||
- [Coding Guidelines](development/guidelines.md) - Development guidelines and best practices
|
||||
- [Coding Style](development/style.md) - Code formatting and style conventions
|
||||
- [UI Testing](UITests.md) - How to write UI tests for PowerToys
|
||||
- [UI Testing](development/ui-tests.md) - How to write UI tests for PowerToys
|
||||
- [Debugging](development/debugging.md) - Techniques for debugging PowerToys
|
||||
|
||||
## Tools
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="PowerToysPublicDependencies" value="https://pkgs.dev.azure.com/shine-oss/PowerToys/_packaging/PowerToysPublicDependencies/nuget/v3/index.json" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
<packageSourceMapping>
|
||||
<packageSource key="PowerToysPublicDependencies">
|
||||
<packageSource key="nuget.org">
|
||||
<package pattern="*" />
|
||||
</packageSource>
|
||||
</packageSourceMapping>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
<CsWinRTAotWarningLevel>2</CsWinRTAotWarningLevel>
|
||||
|
||||
<!-- Suppress DynamicallyAccessedMemberTypes.PublicParameterlessConstructor in fallback code path of Windows SDK projection -->
|
||||
<!-- Suppress CA1416 for Windows-specific APIs that are used in PowerToys which only runs on Windows 10.0.19041.0+ -->
|
||||
<WarningsNotAsErrors>IL2081;CsWinRT1028;CA1416;$(WarningsNotAsErrors)</WarningsNotAsErrors>
|
||||
<WarningsNotAsErrors>IL2081;CsWinRT1028;$(WarningsNotAsErrors)</WarningsNotAsErrors>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -122,23 +122,31 @@ namespace Microsoft.PowerToys.UITest
|
||||
public void StartExe(string appPath, string[]? args = null)
|
||||
{
|
||||
var opts = new AppiumOptions();
|
||||
opts.AddAdditionalCapability("app", appPath);
|
||||
|
||||
if (args != null && args.Length > 0)
|
||||
if (scope == PowerToysModule.PowerToysSettings)
|
||||
{
|
||||
// Build command line arguments string
|
||||
string argsString = string.Join(" ", args.Select(arg =>
|
||||
TryLaunchPowerToysSettings(opts);
|
||||
}
|
||||
else
|
||||
{
|
||||
opts.AddAdditionalCapability("app", appPath);
|
||||
|
||||
if (args != null && args.Length > 0)
|
||||
{
|
||||
// Quote arguments that contain spaces
|
||||
if (arg.Contains(' '))
|
||||
// Build command line arguments string
|
||||
string argsString = string.Join(" ", args.Select(arg =>
|
||||
{
|
||||
return $"\"{arg}\"";
|
||||
}
|
||||
// Quote arguments that contain spaces
|
||||
if (arg.Contains(' '))
|
||||
{
|
||||
return $"\"{arg}\"";
|
||||
}
|
||||
|
||||
return arg;
|
||||
}));
|
||||
return arg;
|
||||
}));
|
||||
|
||||
opts.AddAdditionalCapability("appArguments", argsString);
|
||||
opts.AddAdditionalCapability("appArguments", argsString);
|
||||
}
|
||||
}
|
||||
|
||||
this.Driver = NewWindowsDriver(opts);
|
||||
|
||||
@@ -249,19 +249,7 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext
|
||||
|
||||
public interface IPageContext
|
||||
{
|
||||
void ShowException(Exception ex, string? extensionHint = null);
|
||||
public void ShowException(Exception ex, string? extensionHint = null);
|
||||
|
||||
TaskScheduler Scheduler { get; }
|
||||
}
|
||||
|
||||
public interface IPageViewModelFactoryService
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the page view model for the given page type.
|
||||
/// </summary>
|
||||
/// <param name="page">The page for which to create the view model.</param>
|
||||
/// <param name="nested">Indicates whether the page is not the top-level page.</param>
|
||||
/// <param name="host">The command palette host that will host the page (for status messages)</param>
|
||||
/// <returns>A new instance of the page view model.</returns>
|
||||
PageViewModel? TryCreatePageViewModel(IPage page, bool nested, CommandPaletteHost host);
|
||||
public TaskScheduler Scheduler { get; }
|
||||
}
|
||||
|
||||
@@ -1,27 +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 Microsoft.CommandPalette.Extensions;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public class PageViewModelFactory : IPageViewModelFactoryService
|
||||
{
|
||||
private readonly TaskScheduler _scheduler;
|
||||
|
||||
public PageViewModelFactory(TaskScheduler scheduler)
|
||||
{
|
||||
_scheduler = scheduler;
|
||||
}
|
||||
|
||||
public PageViewModel? TryCreatePageViewModel(IPage page, bool nested, CommandPaletteHost host)
|
||||
{
|
||||
return page switch
|
||||
{
|
||||
IListPage listPage => new ListViewModel(listPage, _scheduler, host) { IsNested = nested },
|
||||
IContentPage contentPage => new ContentPageViewModel(contentPage, _scheduler, host),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ public partial class ShellViewModel : ObservableObject,
|
||||
{
|
||||
private readonly IRootPageService _rootPageService;
|
||||
private readonly TaskScheduler _scheduler;
|
||||
private readonly IPageViewModelFactoryService _pageViewModelFactory;
|
||||
private readonly Lock _invokeLock = new();
|
||||
private Task? _handleInvokeTask;
|
||||
|
||||
@@ -66,9 +65,8 @@ public partial class ShellViewModel : ObservableObject,
|
||||
|
||||
public bool IsNested { get => _isNested; }
|
||||
|
||||
public ShellViewModel(TaskScheduler scheduler, IRootPageService rootPageService, IPageViewModelFactoryService pageViewModelFactory)
|
||||
public ShellViewModel(TaskScheduler scheduler, IRootPageService rootPageService)
|
||||
{
|
||||
_pageViewModelFactory = pageViewModelFactory;
|
||||
_scheduler = scheduler;
|
||||
_rootPageService = rootPageService;
|
||||
_currentPage = new LoadingPageViewModel(null, _scheduler);
|
||||
@@ -254,7 +252,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
_isNested = !isMainPage;
|
||||
|
||||
// Construct our ViewModel of the appropriate type and pass it the UI Thread context.
|
||||
var pageViewModel = _pageViewModelFactory.TryCreatePageViewModel(page, _isNested, host);
|
||||
var pageViewModel = GetViewModelForPage(page, _isNested, host);
|
||||
if (pageViewModel == null)
|
||||
{
|
||||
Logger.LogError($"Failed to create ViewModel for page {page.GetType().Name}");
|
||||
@@ -399,6 +397,19 @@ public partial class ShellViewModel : ObservableObject,
|
||||
}
|
||||
}
|
||||
|
||||
private PageViewModel? GetViewModelForPage(IPage page, bool nested, CommandPaletteHost host)
|
||||
{
|
||||
return page switch
|
||||
{
|
||||
IListPage listPage => new ListViewModel(listPage, _scheduler, host)
|
||||
{
|
||||
IsNested = nested,
|
||||
},
|
||||
IContentPage contentPage => new ContentPageViewModel(contentPage, _scheduler, host),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
public void SetActiveExtension(IExtensionWrapper? extension)
|
||||
{
|
||||
if (extension != _activeExtension)
|
||||
|
||||
@@ -104,14 +104,14 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
List<TopLevelViewModel> commands = [];
|
||||
foreach (var item in commandProvider.TopLevelItems)
|
||||
{
|
||||
commands.Add(item);
|
||||
TopLevelCommands.Add(item);
|
||||
}
|
||||
|
||||
foreach (var item in commandProvider.FallbackItems)
|
||||
{
|
||||
if (item.IsEnabled)
|
||||
{
|
||||
commands.Add(item);
|
||||
TopLevelCommands.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,6 @@ public partial class App : Application
|
||||
|
||||
// ViewModels
|
||||
services.AddSingleton<ShellViewModel>();
|
||||
services.AddSingleton<IPageViewModelFactoryService, PageViewModelFactory>();
|
||||
|
||||
return services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Microsoft.CmdPal.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:labToolkit="using:CommunityToolkit.Labs.WinUI.MarkdownTextBlock"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
|
||||
x:Name="ShortcutContentControl"
|
||||
mc:Ignorable="d">
|
||||
<Grid MinWidth="498" MinHeight="220">
|
||||
@@ -66,7 +66,7 @@
|
||||
IsTabStop="{Binding ElementName=ShortcutContentControl, Path=IsWarningAltGr, Mode=OneWay}"
|
||||
Severity="Warning" />
|
||||
</Grid>
|
||||
<labToolkit:MarkdownTextBlock
|
||||
<tk7controls:MarkdownTextBlock
|
||||
x:Uid="InvalidShortcutWarningLabel"
|
||||
Background="Transparent"
|
||||
FontSize="12"
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Microsoft.CmdPal.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:labToolkit="using:CommunityToolkit.Labs.WinUI.MarkdownTextBlock"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="400"
|
||||
mc:Ignorable="d">
|
||||
@@ -36,7 +36,7 @@
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<labToolkit:MarkdownTextBlock
|
||||
<tk7controls:MarkdownTextBlock
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Background="Transparent"
|
||||
|
||||
@@ -10,9 +10,7 @@
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:labToolkit="using:CommunityToolkit.Labs.WinUI.MarkdownTextBlock"
|
||||
xmlns:local="using:Microsoft.CmdPal.UI"
|
||||
xmlns:markdownTextBlockRns="using:CommunityToolkit.WinUI.Controls.MarkdownTextBlockRns"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:toolkit="using:CommunityToolkit.WinUI.UI.Controls"
|
||||
xmlns:viewModels="using:Microsoft.CmdPal.UI.ViewModels"
|
||||
@@ -21,12 +19,6 @@
|
||||
|
||||
<Page.Resources>
|
||||
<ResourceDictionary>
|
||||
<markdownTextBlockRns:MarkdownThemes
|
||||
x:Key="DefaultMarkdownThemeConfig"
|
||||
H3FontSize="12"
|
||||
H3FontWeight="Normal" />
|
||||
<labToolkit:MarkdownConfig x:Key="DefaultMarkdownConfig" Themes="{StaticResource DefaultMarkdownThemeConfig}" />
|
||||
|
||||
<StackLayout
|
||||
x:Name="VerticalStackLayout"
|
||||
Orientation="Vertical"
|
||||
@@ -51,9 +43,12 @@
|
||||
|
||||
<DataTemplate x:Key="MarkdownContentTemplate" x:DataType="viewModels:ContentMarkdownViewModel">
|
||||
<Grid Margin="0,4,4,4" Padding="12,8,8,8">
|
||||
<labToolkit:MarkdownTextBlock
|
||||
<toolkit:MarkdownTextBlock
|
||||
Background="Transparent"
|
||||
Config="{StaticResource DefaultMarkdownConfig}"
|
||||
Header3FontSize="12"
|
||||
Header3FontWeight="Normal"
|
||||
Header3Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
Text="{x:Bind Body, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
@@ -66,9 +61,12 @@
|
||||
|
||||
<DataTemplate x:Key="NestedMarkdownContentTemplate" x:DataType="viewModels:ContentMarkdownViewModel">
|
||||
<Grid>
|
||||
<labToolkit:MarkdownTextBlock
|
||||
<toolkit:MarkdownTextBlock
|
||||
Background="Transparent"
|
||||
Config="{StaticResource DefaultMarkdownConfig}"
|
||||
Header3FontSize="12"
|
||||
Header3FontWeight="Normal"
|
||||
Header3Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
Text="{x:Bind Body, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="..\..\..\Common.Dotnet.AotCompatibility.props" />
|
||||
<Import Project="..\..\..\CmdPalVersion.props" />
|
||||
<Import Project="CmdPal.pre.props" />
|
||||
<Import Project="CmdPal.Branding.props" />
|
||||
@@ -24,13 +23,6 @@
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(EnableCmdPalAOT)' == 'true'">
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>false</PublishSingleFile>
|
||||
<DisableRuntimeMarshalling>false</DisableRuntimeMarshalling>
|
||||
<PublishAot>true</PublishAot>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(CIBuild)'=='true'">
|
||||
<GenerateAppxPackageOnBuild>true</GenerateAppxPackageOnBuild>
|
||||
</PropertyGroup>
|
||||
@@ -79,7 +71,7 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Animations" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Markdown" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
|
||||
@@ -22,6 +22,7 @@ SetActiveWindow
|
||||
MonitorFromWindow
|
||||
GetMonitorInfo
|
||||
GetDpiForMonitor
|
||||
CoAllowSetForegroundWindow
|
||||
WM_HOTKEY
|
||||
WM_NCLBUTTONDBLCLK
|
||||
|
||||
|
||||
@@ -9,10 +9,8 @@
|
||||
xmlns:cpcontrols="using:Microsoft.CmdPal.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:help="using:Microsoft.CmdPal.UI.Helpers"
|
||||
xmlns:labToolkit="using:CommunityToolkit.Labs.WinUI.MarkdownTextBlock"
|
||||
xmlns:markdownTextBlockRns="using:CommunityToolkit.WinUI.Controls.MarkdownTextBlockRns"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:toolkit="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:toolkit="using:CommunityToolkit.WinUI.UI.Controls"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
xmlns:viewModels="using:Microsoft.CmdPal.UI.ViewModels"
|
||||
Background="Transparent"
|
||||
@@ -146,11 +144,6 @@
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<markdownTextBlockRns:MarkdownThemes
|
||||
x:Key="DefaultMarkdownThemeConfig"
|
||||
H3FontSize="12"
|
||||
H3FontWeight="Normal" />
|
||||
<labToolkit:MarkdownConfig x:Key="DefaultMarkdownConfig" Themes="{StaticResource DefaultMarkdownThemeConfig}" />
|
||||
</ResourceDictionary>
|
||||
</Page.Resources>
|
||||
|
||||
@@ -413,11 +406,14 @@
|
||||
TextWrapping="WrapWholeWords"
|
||||
Visibility="{x:Bind ViewModel.Details.Title, Converter={StaticResource StringNotEmptyToVisibilityConverter}, Mode=OneWay}" />
|
||||
|
||||
<labToolkit:MarkdownTextBlock
|
||||
<toolkit:MarkdownTextBlock
|
||||
Grid.Row="2"
|
||||
Margin="0,4,0,24"
|
||||
Background="Transparent"
|
||||
Config="{StaticResource DefaultMarkdownConfig}"
|
||||
Header3FontSize="12"
|
||||
Header3FontWeight="Normal"
|
||||
Header3Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
Text="{x:Bind ViewModel.Details.Body, Mode=OneWay}" />
|
||||
|
||||
<ItemsRepeater
|
||||
|
||||
@@ -13,7 +13,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<PublishSingleFile>False</PublishSingleFile>
|
||||
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun>
|
||||
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
|
||||
<PublishTrimmed Condition="'$(EnableCmdPalAOT)' == 'true'">True</PublishTrimmed>
|
||||
<PublishTrimmed Condition="'$(EnableCmdPalAOT)' != 'true'">False</PublishTrimmed>
|
||||
<PublishTrimmed Condition="'$(Configuration)' == 'Debug'">False</PublishTrimmed>
|
||||
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">False</PublishTrimmed>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -13,7 +13,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<PublishSingleFile>False</PublishSingleFile>
|
||||
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun>
|
||||
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
|
||||
<PublishTrimmed Condition="'$(EnableCmdPalAOT)' == 'true'">True</PublishTrimmed>
|
||||
<PublishTrimmed Condition="'$(EnableCmdPalAOT)' != 'true'">False</PublishTrimmed>
|
||||
<PublishTrimmed Condition="'$(Configuration)' == 'Debug'">False</PublishTrimmed>
|
||||
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">False</PublishTrimmed>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -2,12 +2,8 @@
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.CmdPal.Ext.Apps.Programs;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CmdPal.Ext.Apps.State;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
@@ -33,12 +29,9 @@ public partial class AllAppsCommandProvider : CommandProvider
|
||||
Subtitle = Resources.search_installed_apps,
|
||||
MoreCommands = [new CommandContextItem(AllAppsSettings.Instance.Settings.SettingsPage)],
|
||||
};
|
||||
|
||||
// Subscribe to pin state changes to refresh the command provider
|
||||
PinnedAppsManager.Instance.PinStateChanged += OnPinStateChanged;
|
||||
}
|
||||
|
||||
public override ICommandItem[] TopLevelCommands() => [_listItem, ..Page.GetPinnedApps()];
|
||||
public override ICommandItem[] TopLevelCommands() => [_listItem];
|
||||
|
||||
public ICommandItem? LookupApp(string displayName)
|
||||
{
|
||||
@@ -69,9 +62,4 @@ public partial class AllAppsCommandProvider : CommandProvider
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void OnPinStateChanged(object? sender, System.EventArgs e)
|
||||
{
|
||||
RaiseItemsChanged(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,14 @@
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
using Microsoft.CmdPal.Ext.Apps.Helpers;
|
||||
using Microsoft.CmdPal.Ext.Apps.Programs;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CmdPal.Ext.Apps.State;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
@@ -24,22 +18,16 @@ namespace Microsoft.CmdPal.Ext.Apps;
|
||||
public sealed partial class AllAppsPage : ListPage
|
||||
{
|
||||
private readonly Lock _listLock = new();
|
||||
|
||||
private AppItem[] allApps = [];
|
||||
private AppListItem[] unpinnedApps = [];
|
||||
private AppListItem[] pinnedApps = [];
|
||||
private AppListItem[] allAppsSection = [];
|
||||
|
||||
public AllAppsPage()
|
||||
{
|
||||
this.Name = Resources.all_apps;
|
||||
this.Icon = Icons.AllAppsIcon;
|
||||
this.Icon = IconHelpers.FromRelativePath("Assets\\AllApps.svg");
|
||||
this.ShowDetails = true;
|
||||
this.IsLoading = true;
|
||||
this.PlaceholderText = Resources.search_installed_apps_placeholder;
|
||||
|
||||
// Subscribe to pin state changes to refresh the command provider
|
||||
PinnedAppsManager.Instance.PinStateChanged += OnPinStateChanged;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
lock (_listLock)
|
||||
@@ -49,139 +37,89 @@ public sealed partial class AllAppsPage : ListPage
|
||||
});
|
||||
}
|
||||
|
||||
internal AppListItem[] GetPinnedApps()
|
||||
{
|
||||
BuildListItems();
|
||||
return pinnedApps;
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems()
|
||||
{
|
||||
// Build or update the list if needed
|
||||
BuildListItems();
|
||||
return pinnedApps.Concat(unpinnedApps).ToArray();
|
||||
if (allAppsSection.Length == 0 || AppCache.Instance.Value.ShouldReload())
|
||||
{
|
||||
lock (_listLock)
|
||||
{
|
||||
BuildListItems();
|
||||
}
|
||||
}
|
||||
|
||||
return allAppsSection;
|
||||
}
|
||||
|
||||
private void BuildListItems()
|
||||
{
|
||||
if (allApps.Length == 0 || AppCache.Instance.Value.ShouldReload())
|
||||
{
|
||||
lock (_listLock)
|
||||
{
|
||||
this.IsLoading = true;
|
||||
this.IsLoading = true;
|
||||
|
||||
Stopwatch stopwatch = new();
|
||||
stopwatch.Start();
|
||||
Stopwatch stopwatch = new();
|
||||
stopwatch.Start();
|
||||
|
||||
var apps = GetPrograms();
|
||||
this.allApps = apps.AllApps;
|
||||
this.pinnedApps = apps.PinnedItems;
|
||||
this.unpinnedApps = apps.UnpinnedItems;
|
||||
var apps = GetPrograms();
|
||||
|
||||
this.IsLoading = false;
|
||||
this.allAppsSection = apps
|
||||
.Select((app) => new AppListItem(app, true))
|
||||
.ToArray();
|
||||
|
||||
AppCache.Instance.Value.ResetReloadFlag();
|
||||
this.IsLoading = false;
|
||||
|
||||
stopwatch.Stop();
|
||||
Logger.LogTrace($"{nameof(AllAppsPage)}.{nameof(BuildListItems)} took: {stopwatch.ElapsedMilliseconds} ms");
|
||||
}
|
||||
}
|
||||
AppCache.Instance.Value.ResetReloadFlag();
|
||||
|
||||
stopwatch.Stop();
|
||||
Logger.LogTrace($"{nameof(AllAppsPage)}.{nameof(BuildListItems)} took: {stopwatch.ElapsedMilliseconds} ms");
|
||||
}
|
||||
|
||||
private AppItem[] GetAllApps()
|
||||
internal List<AppItem> GetPrograms()
|
||||
{
|
||||
var uwpResults = AppCache.Instance.Value.UWPs
|
||||
.Where((application) => application.Enabled)
|
||||
.Select(app => app.ToAppItem());
|
||||
.Where((application) => application.Enabled)
|
||||
.Select(UwpToAppItem);
|
||||
|
||||
var win32Results = AppCache.Instance.Value.Win32s
|
||||
.Where((application) => application.Enabled && application.Valid)
|
||||
.Select(app => app.ToAppItem());
|
||||
.Select(app =>
|
||||
{
|
||||
var icoPath = string.IsNullOrEmpty(app.IcoPath) ?
|
||||
(app.AppType == Win32Program.ApplicationType.InternetShortcutApplication ?
|
||||
app.IcoPath :
|
||||
app.FullPath) :
|
||||
app.IcoPath;
|
||||
|
||||
var allApps = uwpResults.Concat(win32Results).ToArray();
|
||||
return allApps;
|
||||
// icoPath = icoPath.EndsWith(".lnk", System.StringComparison.InvariantCultureIgnoreCase) ? (icoPath + ",0") : icoPath;
|
||||
icoPath = icoPath.EndsWith(".lnk", System.StringComparison.InvariantCultureIgnoreCase) ?
|
||||
app.FullPath :
|
||||
icoPath;
|
||||
return new AppItem()
|
||||
{
|
||||
Name = app.Name,
|
||||
Subtitle = app.Description,
|
||||
Type = app.Type(),
|
||||
IcoPath = icoPath,
|
||||
ExePath = !string.IsNullOrEmpty(app.LnkFilePath) ? app.LnkFilePath : app.FullPath,
|
||||
DirPath = app.Location,
|
||||
Commands = app.GetCommands(),
|
||||
};
|
||||
});
|
||||
|
||||
return uwpResults.Concat(win32Results).OrderBy(app => app.Name).ToList();
|
||||
}
|
||||
|
||||
internal (AppItem[] AllApps, AppListItem[] PinnedItems, AppListItem[] UnpinnedItems) GetPrograms()
|
||||
private AppItem UwpToAppItem(UWPApplication app)
|
||||
{
|
||||
var allApps = GetAllApps();
|
||||
var pinned = new List<AppListItem>();
|
||||
var unpinned = new List<AppListItem>();
|
||||
|
||||
foreach (var app in allApps)
|
||||
var iconPath = app.LogoType != LogoType.Error ? app.LogoPath : string.Empty;
|
||||
var item = new AppItem()
|
||||
{
|
||||
var isPinned = PinnedAppsManager.Instance.IsAppPinned(app.AppIdentifier);
|
||||
var appListItem = new AppListItem(app, true, isPinned);
|
||||
|
||||
if (isPinned)
|
||||
{
|
||||
appListItem.Tags = appListItem.Tags
|
||||
.Concat([new Tag() { Icon = Icons.PinIcon }])
|
||||
.ToArray();
|
||||
pinned.Add(appListItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
unpinned.Add(appListItem);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
allApps
|
||||
.ToArray(),
|
||||
pinned
|
||||
.OrderBy(app => app.Title)
|
||||
.ToArray(),
|
||||
unpinned
|
||||
.OrderBy(app => app.Title)
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
private void OnPinStateChanged(object? sender, PinStateChangedEventArgs e)
|
||||
{
|
||||
/*
|
||||
* Rebuilding all the lists is pretty expensive.
|
||||
* So, instead, we'll just compare pinned items to move existing
|
||||
* items between the two lists.
|
||||
*/
|
||||
var existingAppItem = allApps.FirstOrDefault(f => f.AppIdentifier == e.AppIdentifier);
|
||||
|
||||
if (existingAppItem != null)
|
||||
{
|
||||
var appListItem = new AppListItem(existingAppItem, true, e.IsPinned);
|
||||
|
||||
if (e.IsPinned)
|
||||
{
|
||||
// Remove it from the unpinned apps array
|
||||
this.unpinnedApps = this.unpinnedApps
|
||||
.Where(app => app.AppIdentifier != existingAppItem.AppIdentifier)
|
||||
.OrderBy(app => app.Title)
|
||||
.ToArray();
|
||||
|
||||
var newPinned = this.pinnedApps.ToList();
|
||||
newPinned.Add(appListItem);
|
||||
|
||||
this.pinnedApps = newPinned
|
||||
.OrderBy(app => app.Title)
|
||||
.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove it from the pinned apps array
|
||||
this.pinnedApps = this.pinnedApps
|
||||
.Where(app => app.AppIdentifier != existingAppItem.AppIdentifier)
|
||||
.OrderBy(app => app.Title)
|
||||
.ToArray();
|
||||
|
||||
var newUnpinned = this.unpinnedApps.ToList();
|
||||
newUnpinned.Add(appListItem);
|
||||
|
||||
this.unpinnedApps = newUnpinned
|
||||
.OrderBy(app => app.Title)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
RaiseItemsChanged(0);
|
||||
}
|
||||
Name = app.Name,
|
||||
Subtitle = app.Description,
|
||||
Type = UWPApplication.Type(),
|
||||
IcoPath = iconPath,
|
||||
DirPath = app.Location,
|
||||
UserModelId = app.UserModelId,
|
||||
IsPackaged = true,
|
||||
Commands = app.GetCommands(),
|
||||
};
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.CmdPal.Ext.Apps.Programs;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Apps;
|
||||
@@ -27,9 +26,7 @@ internal sealed class AppItem
|
||||
|
||||
public bool IsPackaged { get; set; }
|
||||
|
||||
public List<IContextItem>? Commands { get; set; }
|
||||
|
||||
public string AppIdentifier { get; set; } = string.Empty;
|
||||
public List<CommandContextItem>? Commands { get; set; }
|
||||
|
||||
public AppItem()
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.Storage.Streams;
|
||||
@@ -24,17 +23,14 @@ internal sealed partial class AppListItem : ListItem
|
||||
|
||||
public override IIconInfo? Icon { get => _icon.Value; set => base.Icon = value; }
|
||||
|
||||
public string AppIdentifier => _app.AppIdentifier;
|
||||
|
||||
public AppListItem(AppItem app, bool useThumbnails, bool isPinned)
|
||||
public AppListItem(AppItem app, bool useThumbnails)
|
||||
: base(new AppCommand(app))
|
||||
{
|
||||
_app = app;
|
||||
Title = app.Name;
|
||||
Subtitle = app.Subtitle;
|
||||
Tags = [_appTag];
|
||||
|
||||
MoreCommands = AddPinCommands(_app.Commands!, isPinned);
|
||||
MoreCommands = _app.Commands!.ToArray();
|
||||
|
||||
_details = new Lazy<Details>(() =>
|
||||
{
|
||||
@@ -125,37 +121,4 @@ internal sealed partial class AppListItem : ListItem
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private IContextItem[] AddPinCommands(List<IContextItem> commands, bool isPinned)
|
||||
{
|
||||
var newCommands = new List<IContextItem>();
|
||||
newCommands.AddRange(commands);
|
||||
|
||||
newCommands.Add(new SeparatorContextItem());
|
||||
|
||||
// 0x50 = P
|
||||
// Full key chord would be Ctrl+P
|
||||
var pinKeyChord = KeyChordHelpers.FromModifiers(true, false, false, false, 0x50, 0);
|
||||
|
||||
if (isPinned)
|
||||
{
|
||||
newCommands.Add(
|
||||
new CommandContextItem(
|
||||
new UnpinAppCommand(this.AppIdentifier))
|
||||
{
|
||||
RequestedShortcut = pinKeyChord,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
newCommands.Add(
|
||||
new CommandContextItem(
|
||||
new PinAppCommand(this.AppIdentifier))
|
||||
{
|
||||
RequestedShortcut = pinKeyChord,
|
||||
});
|
||||
}
|
||||
|
||||
return newCommands.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Ext.Apps.Helpers;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
@@ -14,12 +13,14 @@ namespace Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
|
||||
internal sealed partial class CopyPathCommand : InvokableCommand
|
||||
{
|
||||
private static readonly IconInfo TheIcon = new("\ue8c8");
|
||||
|
||||
private readonly string _target;
|
||||
|
||||
public CopyPathCommand(string target)
|
||||
{
|
||||
Name = Resources.copy_path;
|
||||
Icon = Icons.CopyIcon;
|
||||
Icon = TheIcon;
|
||||
|
||||
_target = target;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Ext.Apps.Helpers;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
@@ -14,12 +13,14 @@ namespace Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
|
||||
internal sealed partial class OpenInConsoleCommand : InvokableCommand
|
||||
{
|
||||
private static readonly IconInfo TheIcon = new("\ue838");
|
||||
|
||||
private readonly string _target;
|
||||
|
||||
public OpenInConsoleCommand(string target)
|
||||
{
|
||||
Name = Resources.open_path_in_console;
|
||||
Icon = Icons.OpenConsoleIcon;
|
||||
Icon = TheIcon;
|
||||
|
||||
_target = target;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Ext.Apps.Helpers;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
@@ -12,12 +11,14 @@ namespace Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
|
||||
internal sealed partial class OpenPathCommand : InvokableCommand
|
||||
{
|
||||
private static readonly IconInfo TheIcon = new("\ue838");
|
||||
|
||||
private readonly string _target;
|
||||
|
||||
public OpenPathCommand(string target)
|
||||
{
|
||||
Name = Resources.open_location;
|
||||
Icon = Icons.OpenPathIcon;
|
||||
Icon = TheIcon;
|
||||
|
||||
_target = target;
|
||||
}
|
||||
|
||||
@@ -1,29 +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.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.CmdPal.Ext.Apps.Helpers;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CmdPal.Ext.Apps.State;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
|
||||
internal sealed partial class PinAppCommand : InvokableCommand
|
||||
{
|
||||
private readonly string _appIdentifier;
|
||||
|
||||
public PinAppCommand(string appIdentifier)
|
||||
{
|
||||
_appIdentifier = appIdentifier;
|
||||
Name = Resources.pin_app;
|
||||
Icon = Icons.PinIcon;
|
||||
}
|
||||
|
||||
public override CommandResult Invoke()
|
||||
{
|
||||
PinnedAppsManager.Instance.PinApp(_appIdentifier);
|
||||
return CommandResult.KeepOpen();
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Ext.Apps.Helpers;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CmdPal.Ext.Apps.Utils;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
@@ -14,6 +13,8 @@ namespace Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
|
||||
internal sealed partial class RunAsAdminCommand : InvokableCommand
|
||||
{
|
||||
private static readonly IconInfo TheIcon = new("\uE7EF");
|
||||
|
||||
private readonly string _target;
|
||||
private readonly string _parentDir;
|
||||
private readonly bool _packaged;
|
||||
@@ -21,7 +22,7 @@ internal sealed partial class RunAsAdminCommand : InvokableCommand
|
||||
public RunAsAdminCommand(string target, string parentDir, bool packaged)
|
||||
{
|
||||
Name = Resources.run_as_administrator;
|
||||
Icon = Icons.RunAsIcon;
|
||||
Icon = TheIcon;
|
||||
|
||||
_target = target;
|
||||
_parentDir = parentDir;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Ext.Apps.Helpers;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CmdPal.Ext.Apps.Utils;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
@@ -14,19 +13,21 @@ namespace Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
|
||||
internal sealed partial class RunAsUserCommand : InvokableCommand
|
||||
{
|
||||
private static readonly IconInfo TheIcon = new("\uE7EE");
|
||||
|
||||
private readonly string _target;
|
||||
private readonly string _parentDir;
|
||||
|
||||
public RunAsUserCommand(string target, string parentDir)
|
||||
{
|
||||
Name = Resources.run_as_different_user;
|
||||
Icon = Icons.RunAsUserIcon;
|
||||
Icon = TheIcon;
|
||||
|
||||
_target = target;
|
||||
_parentDir = parentDir;
|
||||
}
|
||||
|
||||
internal static async Task RunAsUser(string target, string parentDir)
|
||||
internal static async Task RunAsAdmin(string target, string parentDir)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
@@ -38,7 +39,7 @@ internal sealed partial class RunAsUserCommand : InvokableCommand
|
||||
|
||||
public override CommandResult Invoke()
|
||||
{
|
||||
_ = RunAsUser(_target, _parentDir).ConfigureAwait(false);
|
||||
_ = RunAsAdmin(_target, _parentDir).ConfigureAwait(false);
|
||||
|
||||
return CommandResult.Dismiss();
|
||||
}
|
||||
|
||||
@@ -1,28 +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 Microsoft.CmdPal.Ext.Apps.Helpers;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CmdPal.Ext.Apps.State;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
|
||||
internal sealed partial class UnpinAppCommand : InvokableCommand
|
||||
{
|
||||
private readonly string _appIdentifier;
|
||||
|
||||
public UnpinAppCommand(string appIdentifier)
|
||||
{
|
||||
_appIdentifier = appIdentifier;
|
||||
Name = Resources.unpin_app;
|
||||
Icon = Icons.UnpinIcon;
|
||||
}
|
||||
|
||||
public override CommandResult Invoke()
|
||||
{
|
||||
PinnedAppsManager.Instance.UnpinApp(_appIdentifier);
|
||||
return CommandResult.KeepOpen();
|
||||
}
|
||||
}
|
||||
@@ -1,26 +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 Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Apps.Helpers;
|
||||
|
||||
public static partial class Icons
|
||||
{
|
||||
public static IconInfo UnpinIcon { get; } = new("\uE77A");
|
||||
|
||||
public static IconInfo PinIcon { get; } = new("\uE840");
|
||||
|
||||
public static IconInfo RunAsIcon { get; } = new("\uE7EF");
|
||||
|
||||
public static IconInfo RunAsUserIcon { get; } = new("\uE7EE");
|
||||
|
||||
public static IconInfo CopyIcon { get; } = new("\ue8c8");
|
||||
|
||||
public static IconInfo OpenConsoleIcon { get; } = new("\ue838");
|
||||
|
||||
public static IconInfo OpenPathIcon { get; } = new("\ue838");
|
||||
|
||||
public static IconInfo AllAppsIcon { get; } = IconHelpers.FromRelativePath("Assets\\AllApps.svg");
|
||||
}
|
||||
@@ -1,21 +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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Ext.Apps.State;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Apps;
|
||||
|
||||
[JsonSerializable(typeof(string))]
|
||||
[JsonSerializable(typeof(PinnedApps))]
|
||||
[JsonSerializable(typeof(List<string>), TypeInfoPropertyName = "StringList")]
|
||||
[JsonSourceGenerationOptions(UseStringEnumConverter = true, WriteIndented = true, IncludeFields = true, PropertyNameCaseInsensitive = true, AllowTrailingCommas = true)]
|
||||
internal sealed partial class JsonSerializationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
@@ -10,9 +10,7 @@ using System.Xml;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CmdPal.Ext.Apps.State;
|
||||
using Microsoft.CmdPal.Ext.Apps.Utils;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.System;
|
||||
using Windows.Win32;
|
||||
@@ -72,15 +70,9 @@ public class UWPApplication : IProgram
|
||||
return Resources.packaged_application;
|
||||
}
|
||||
|
||||
public string GetAppIdentifier()
|
||||
public List<CommandContextItem> GetCommands()
|
||||
{
|
||||
// Use UserModelId for UWP apps as it's unique
|
||||
return UserModelId;
|
||||
}
|
||||
|
||||
public List<IContextItem> GetCommands()
|
||||
{
|
||||
List<IContextItem> commands = [];
|
||||
List<CommandContextItem> commands = [];
|
||||
|
||||
if (CanRunElevated)
|
||||
{
|
||||
@@ -519,25 +511,6 @@ public class UWPApplication : IProgram
|
||||
}
|
||||
}
|
||||
|
||||
internal AppItem ToAppItem()
|
||||
{
|
||||
var app = this;
|
||||
var iconPath = app.LogoType != LogoType.Error ? app.LogoPath : string.Empty;
|
||||
var item = new AppItem()
|
||||
{
|
||||
Name = app.Name,
|
||||
Subtitle = app.Description,
|
||||
Type = UWPApplication.Type(),
|
||||
IcoPath = iconPath,
|
||||
DirPath = app.Location,
|
||||
UserModelId = app.UserModelId,
|
||||
IsPackaged = true,
|
||||
Commands = app.GetCommands(),
|
||||
AppIdentifier = app.GetAppIdentifier(),
|
||||
};
|
||||
return item;
|
||||
}
|
||||
|
||||
/*
|
||||
public ImageSource Logo()
|
||||
{
|
||||
|
||||
@@ -19,9 +19,7 @@ using System.Windows.Input;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CmdPal.Ext.Apps.State;
|
||||
using Microsoft.CmdPal.Ext.Apps.Utils;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Win32;
|
||||
using Windows.System;
|
||||
@@ -188,9 +186,9 @@ public class Win32Program : IProgram
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<IContextItem> GetCommands()
|
||||
public List<CommandContextItem> GetCommands()
|
||||
{
|
||||
List<IContextItem> commands = new List<IContextItem>();
|
||||
List<CommandContextItem> commands = new List<CommandContextItem>();
|
||||
|
||||
if (AppType != ApplicationType.InternetShortcutApplication && AppType != ApplicationType.Folder && AppType != ApplicationType.GenericFile)
|
||||
{
|
||||
@@ -233,12 +231,6 @@ public class Win32Program : IProgram
|
||||
return ExecutableName;
|
||||
}
|
||||
|
||||
public string GetAppIdentifier()
|
||||
{
|
||||
// Use a combination of name and path to create a unique identifier
|
||||
return $"{Name}|{FullPath}";
|
||||
}
|
||||
|
||||
private static Win32Program CreateWin32Program(string path)
|
||||
{
|
||||
try
|
||||
@@ -941,29 +933,4 @@ public class Win32Program : IProgram
|
||||
return Array.Empty<Win32Program>();
|
||||
}
|
||||
}
|
||||
|
||||
internal AppItem ToAppItem()
|
||||
{
|
||||
var app = this;
|
||||
var icoPath = string.IsNullOrEmpty(app.IcoPath) ?
|
||||
(app.AppType == Win32Program.ApplicationType.InternetShortcutApplication ?
|
||||
app.IcoPath :
|
||||
app.FullPath) :
|
||||
app.IcoPath;
|
||||
|
||||
icoPath = icoPath.EndsWith(".lnk", System.StringComparison.InvariantCultureIgnoreCase) ?
|
||||
app.FullPath :
|
||||
icoPath;
|
||||
return new AppItem()
|
||||
{
|
||||
Name = app.Name,
|
||||
Subtitle = app.Description,
|
||||
Type = app.Type(),
|
||||
IcoPath = icoPath,
|
||||
ExePath = !string.IsNullOrEmpty(app.LnkFilePath) ? app.LnkFilePath : app.FullPath,
|
||||
DirPath = app.Location,
|
||||
Commands = app.GetCommands(),
|
||||
AppIdentifier = app.GetAppIdentifier(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,15 +213,6 @@ namespace Microsoft.CmdPal.Ext.Apps.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Pin.
|
||||
/// </summary>
|
||||
internal static string pin_app {
|
||||
get {
|
||||
return ResourceManager.GetString("pin_app", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Run as administrator.
|
||||
/// </summary>
|
||||
@@ -276,15 +267,6 @@ namespace Microsoft.CmdPal.Ext.Apps.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unpin.
|
||||
/// </summary>
|
||||
internal static string unpin_app {
|
||||
get {
|
||||
return ResourceManager.GetString("unpin_app", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Experimental: When enabled, Command Palette will load thumbnails from the Windows Shell. Using thumbnails may cause the app to crash on launch.
|
||||
/// </summary>
|
||||
|
||||
@@ -199,10 +199,4 @@
|
||||
<value>Experimental: When enabled, Command Palette will load thumbnails from the Windows Shell. Using thumbnails may cause the app to crash on launch</value>
|
||||
<comment>A description for "use_thumbnails_setting_label"</comment>
|
||||
</data>
|
||||
<data name="pin_app" xml:space="preserve">
|
||||
<value>Pin</value>
|
||||
</data>
|
||||
<data name="unpin_app" xml:space="preserve">
|
||||
<value>Unpin</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,34 +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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Apps.State;
|
||||
|
||||
public class PinStateChangedEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the identifier of the application whose pin state has changed.
|
||||
/// </summary>
|
||||
public string AppIdentifier { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the specified app identifier was pinned or not.
|
||||
/// </summary>
|
||||
public bool IsPinned { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PinStateChangedEventArgs"/> class.
|
||||
/// </summary>
|
||||
/// <param name="appIdentifier">The identifier of the application whose pin state has changed.</param>
|
||||
public PinStateChangedEventArgs(string appIdentifier, bool isPinned)
|
||||
{
|
||||
AppIdentifier = appIdentifier ?? throw new ArgumentNullException(nameof(appIdentifier));
|
||||
IsPinned = isPinned;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +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.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Apps.State;
|
||||
|
||||
public sealed class PinnedApps
|
||||
{
|
||||
public List<string> PinnedAppIdentifiers { get; set; } = [];
|
||||
|
||||
public static PinnedApps ReadFromFile(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return new PinnedApps();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var jsonString = File.ReadAllText(path);
|
||||
var result = JsonSerializer.Deserialize<PinnedApps>(jsonString, JsonSerializationContext.Default.PinnedApps);
|
||||
return result ?? new PinnedApps();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new PinnedApps();
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteToFile(string path, PinnedApps data)
|
||||
{
|
||||
try
|
||||
{
|
||||
var jsonString = JsonSerializer.Serialize(data, JsonSerializationContext.Default.PinnedApps);
|
||||
File.WriteAllText(path, jsonString);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Silently fail - we don't want pinning issues to crash the extension
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,82 +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;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Apps.State;
|
||||
|
||||
public sealed class PinnedAppsManager
|
||||
{
|
||||
private static readonly Lazy<PinnedAppsManager> _instance = new(() => new PinnedAppsManager());
|
||||
private readonly string _pinnedAppsFilePath;
|
||||
|
||||
public static PinnedAppsManager Instance => _instance.Value;
|
||||
|
||||
private PinnedApps _pinnedApps = new();
|
||||
|
||||
// Add event for when pinning state changes
|
||||
public event EventHandler<PinStateChangedEventArgs>? PinStateChanged;
|
||||
|
||||
private PinnedAppsManager()
|
||||
{
|
||||
_pinnedAppsFilePath = GetPinnedAppsFilePath();
|
||||
LoadPinnedApps();
|
||||
}
|
||||
|
||||
public bool IsAppPinned(string appIdentifier)
|
||||
{
|
||||
return _pinnedApps.PinnedAppIdentifiers.Contains(appIdentifier, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public void PinApp(string appIdentifier)
|
||||
{
|
||||
if (!IsAppPinned(appIdentifier))
|
||||
{
|
||||
_pinnedApps.PinnedAppIdentifiers.Add(appIdentifier);
|
||||
SavePinnedApps();
|
||||
Logger.LogTrace($"Pinned app: {appIdentifier}");
|
||||
PinStateChanged?.Invoke(this, new PinStateChangedEventArgs(appIdentifier, true));
|
||||
}
|
||||
}
|
||||
|
||||
public string[] GetPinnedAppIdentifiers()
|
||||
{
|
||||
return _pinnedApps.PinnedAppIdentifiers.ToArray();
|
||||
}
|
||||
|
||||
public void UnpinApp(string appIdentifier)
|
||||
{
|
||||
var removed = _pinnedApps.PinnedAppIdentifiers.RemoveAll(id =>
|
||||
string.Equals(id, appIdentifier, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (removed > 0)
|
||||
{
|
||||
SavePinnedApps();
|
||||
Logger.LogTrace($"Unpinned app: {appIdentifier}");
|
||||
PinStateChanged?.Invoke(this, new PinStateChangedEventArgs(appIdentifier, false));
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadPinnedApps()
|
||||
{
|
||||
_pinnedApps = PinnedApps.ReadFromFile(_pinnedAppsFilePath);
|
||||
}
|
||||
|
||||
private void SavePinnedApps()
|
||||
{
|
||||
PinnedApps.WriteToFile(_pinnedAppsFilePath, _pinnedApps);
|
||||
}
|
||||
|
||||
private static string GetPinnedAppsFilePath()
|
||||
{
|
||||
var directory = Utilities.BaseSettingsPath("Microsoft.CmdPal");
|
||||
Directory.CreateDirectory(directory);
|
||||
return Path.Combine(directory, "apps.pinned.json");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user