Compare commits

...

33 Commits

Author SHA1 Message Date
Mike Griese
e5442f88f1 nits 2025-07-16 15:39:31 -05:00
Mike Griese
2522cdcc47 Merge remote-tracking branch 'origin/main' into dev/migrie/40113/core-control 2025-07-16 15:39:17 -05:00
Mike Griese
f3a58d3058 make build again 2025-07-15 16:18:00 -05:00
Mike Griese
af9b955993 Merge remote-tracking branch 'origin/main' into dev/migrie/40113/core-control 2025-07-15 14:36:15 -05:00
Mike Griese
8c16c63a68 some nits 2025-07-15 06:52:55 -05:00
Mike Griese
31f362ab66 Okay the Core app does build and run, so that's cool 2025-07-11 16:04:16 -05:00
Mike Griese
bd9cc00c79 stand up a .Core.Control project 2025-07-11 14:31:39 -05:00
Mike Griese
630e7e0ac8 Remove ManagedCommon from core.viewmodels 2025-07-11 10:19:37 -05:00
Mike Griese
1a2406671d Merge branch 'dev/migrie/40113/new-core-project' into dev/migrie/40113/extension-hosts-try-2 2025-07-11 09:23:11 -05:00
Mike Griese
b59f2875f4 Merge branch 'dev/migrie/40113/viewmodel-factory' into dev/migrie/40113/new-core-project 2025-07-11 09:22:52 -05:00
Mike Griese
129c10a0a2 Merge branch 'dev/migrie/40113/remove-mainlistpage-from-shellvm' into dev/migrie/40113/viewmodel-factory 2025-07-11 09:22:21 -05:00
Mike Griese
8d342b4b32 Merge remote-tracking branch 'origin/main' into dev/migrie/40113/remove-mainlistpage-from-shellvm 2025-07-11 09:21:50 -05:00
Mike Griese
89ac05a8cd cleanup comments 2025-07-11 09:17:55 -05:00
Mike Griese
a10a79ecc8 cleanup comments 2025-07-11 09:13:48 -05:00
Mike Griese
d7eb61d57e Move the extension FG handler to the PT RootPageService too 2025-07-11 09:04:13 -05:00
Mike Griese
555c488de5 lot of cleanup, it builds and runs 2025-07-10 15:22:36 -05:00
Mike Griese
e214cda85c A different approach to the extension host problem
I think the work to figure out the extension host was much
overcomplicated. I don't think we need all that.
2025-07-10 12:53:38 -05:00
Mike Griese
ae6172dc16 Merge branch 'dev/migrie/40113/viewmodel-factory' into dev/migrie/40113/new-core-project 2025-07-10 10:11:40 -05:00
Mike Griese
b290b9b1a2 Merge branch 'dev/migrie/40113/remove-mainlistpage-from-shellvm' into dev/migrie/40113/viewmodel-factory 2025-07-10 09:37:22 -05:00
Mike Griese
42262ee9d6 Merge remote-tracking branch 'origin/main' into dev/migrie/40113/remove-mainlistpage-from-shellvm 2025-07-10 06:45:34 -05:00
Mike Griese
c3c77f2c75 add support for content pages again 2025-07-09 13:21:17 -05:00
Mike Griese
a8d0fbf44e damn it builds and actually runs 2025-07-09 12:50:26 -05:00
Mike Griese
402e379c6f the ui.vm project builds 2025-07-09 10:27:52 -05:00
Mike Griese
8cd6622d14 the core vm project builds, unbelievable 2025-07-09 10:09:52 -05:00
Mike Griese
ddff05ec54 blind file moves 2025-07-09 10:09:35 -05:00
Mike Griese
ef6412d116 CmdPal: Add a viewmodel factory for pages
_targets #40482_
ref #40113

A smaller refactor, to be sure.

This just moves the instantiation of PageViewModel objects out of the
ShellViewModel, and into its own class.

The idea being that other page types could be added, just by extending
that factory (or implementing your own), and then also handling those
new VMs in your ShellPage.xaml.cs equivalent.
2025-07-09 09:39:33 -05:00
Mike Griese
0654830420 cleanup 2025-07-08 15:22:12 -05:00
Mike Griese
91d085fbca Remove ShellViewModel's dependency on MainListPage
targets #40479

Kinda mental that the viewmodel had this hard dependency.

So instead I added a service for providing the root page for the app.
Theoretically, you could add a different IRootPageService, and give out
a different root page.

This works and builds and runs. Needs cleanup.

ref #49113
2025-07-08 15:07:58 -05:00
Mike Griese
c1d755aea6 This needs to be handled on the UI thread, so move it to the UI 2025-07-08 15:07:11 -05:00
Mike Griese
be5ebf9322 comment 2025-07-08 13:54:19 -05:00
Mike Griese
f2c57ee33e telem too 2025-07-08 13:51:00 -05:00
Mike Griese
1e198d4acf some cleanup 2025-07-08 13:36:13 -05:00
Mike Griese
f809bd139c Refactor ShellPage logic into VM
ref #40113

Moves a lot of the "model" logic out of ShellPage.xaml.cs into
ShellViewModel. It compiles, and runs, hot dang.

Needs some cleanup.
2025-07-08 12:32:45 -05:00
118 changed files with 3757 additions and 129 deletions

View File

@@ -740,6 +740,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{02EA681E-C
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Core.ViewModels", "src\modules\cmdpal\Microsoft.CmdPal.Core.ViewModels\Microsoft.CmdPal.Core.ViewModels.csproj", "{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Core.Control", "src\modules\cmdpal\Microsoft.CmdPal.Core.Control\Microsoft.CmdPal.Core.Control.csproj", "{7E043FD6-F17A-04CE-F8D0-E24CB036BFB5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Core.UI", "src\modules\cmdpal\Microsoft.CmdPal.Core.UI\Microsoft.CmdPal.Core.UI.csproj", "{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
@@ -2738,6 +2742,34 @@ Global
{9D3F3793-EFE3-4525-8782-238015DABA62}.Release|ARM64.Build.0 = Release|ARM64
{9D3F3793-EFE3-4525-8782-238015DABA62}.Release|x64.ActiveCfg = Release|x64
{9D3F3793-EFE3-4525-8782-238015DABA62}.Release|x64.Build.0 = Release|x64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|ARM64.ActiveCfg = Debug|ARM64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|ARM64.Build.0 = Debug|ARM64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|x64.ActiveCfg = Debug|x64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|x64.Build.0 = Debug|x64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|ARM64.ActiveCfg = Release|ARM64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|ARM64.Build.0 = Release|ARM64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|x64.ActiveCfg = Release|x64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|x64.Build.0 = Release|x64
{7E043FD6-F17A-04CE-F8D0-E24CB036BFB5}.Debug|ARM64.ActiveCfg = Debug|ARM64
{7E043FD6-F17A-04CE-F8D0-E24CB036BFB5}.Debug|ARM64.Build.0 = Debug|ARM64
{7E043FD6-F17A-04CE-F8D0-E24CB036BFB5}.Debug|x64.ActiveCfg = Debug|x64
{7E043FD6-F17A-04CE-F8D0-E24CB036BFB5}.Debug|x64.Build.0 = Debug|x64
{7E043FD6-F17A-04CE-F8D0-E24CB036BFB5}.Release|ARM64.ActiveCfg = Release|ARM64
{7E043FD6-F17A-04CE-F8D0-E24CB036BFB5}.Release|ARM64.Build.0 = Release|ARM64
{7E043FD6-F17A-04CE-F8D0-E24CB036BFB5}.Release|x64.ActiveCfg = Release|x64
{7E043FD6-F17A-04CE-F8D0-E24CB036BFB5}.Release|x64.Build.0 = Release|x64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Debug|ARM64.ActiveCfg = Debug|ARM64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Debug|ARM64.Build.0 = Debug|ARM64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Debug|ARM64.Deploy.0 = Debug|ARM64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Debug|x64.ActiveCfg = Debug|x64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Debug|x64.Build.0 = Debug|x64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Debug|x64.Deploy.0 = Debug|x64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Release|ARM64.ActiveCfg = Release|ARM64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Release|ARM64.Build.0 = Release|ARM64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Release|ARM64.Deploy.0 = Release|ARM64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Release|x64.ActiveCfg = Release|x64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Release|x64.Build.0 = Release|x64
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1}.Release|x64.Deploy.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -3025,6 +3057,10 @@ Global
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {3846508C-77EB-4034-A702-F8BB263C4F79}
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{9D3F3793-EFE3-4525-8782-238015DABA62} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {3846508C-77EB-4034-A702-F8BB263C4F79}
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{7E043FD6-F17A-04CE-F8D0-E24CB036BFB5} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{289277DE-09D4-A186-75D6-7FCA4A1BBAF1} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}

View File

@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<UserControl
x:Class="Microsoft.CmdPal.UI.Controls.CommandBar"
x:Class="Microsoft.CmdPal.Core.Control.Controls.CommandBar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
xmlns:cmdpalUI="using:Microsoft.CmdPal.UI"
xmlns:cmdpalUI="using:Microsoft.CmdPal.Core.Control"
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:cpcontrols="using:Microsoft.CmdPal.Core.Control.Controls"
xmlns:coreViewModels="using:Microsoft.CmdPal.Core.ViewModels"
xmlns:cpcontrols="using:Microsoft.CmdPal.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:help="using:Microsoft.CmdPal.UI.Helpers"
xmlns:help="using:Microsoft.CmdPal.Core.Control.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:viewModels="using:Microsoft.CmdPal.UI.ViewModels"
xmlns:viewModels="using:Microsoft.CmdPal.Core.Control.ViewModels"
Background="Transparent"
mc:Ignorable="d">

View File

@@ -3,16 +3,16 @@
// See the LICENSE file in the project root for more information.
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.Control.Views;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.UI.Views;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Input;
using Windows.System;
namespace Microsoft.CmdPal.UI.Controls;
namespace Microsoft.CmdPal.Core.Control.Controls;
public sealed partial class CommandBar : UserControl,
IRecipient<OpenContextMenuMessage>,

View File

@@ -4,11 +4,11 @@
using System.Runtime.InteropServices;
using CommunityToolkit.WinUI;
using ManagedCommon;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.CmdPal.UI.Controls;
namespace Microsoft.CmdPal.Core.Control.Controls;
/// <summary>
/// A helper control which takes an <see cref="IconSource"/> and creates the corresponding <see cref="IconElement"/>.
@@ -17,6 +17,7 @@ public partial class ContentIcon : FontIcon
{
public UIElement Content
{
// [DynamicWindowsRuntimeCast(typeof(UIElement))]
get => (UIElement)GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}
@@ -43,7 +44,7 @@ public partial class ContentIcon : FontIcon
}
catch (COMException ex)
{
Logger.LogError(ex.ToString());
CoreLogger.LogError(ex.ToString());
}
}
}

View File

@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?>
<UserControl
x:Class="Microsoft.CmdPal.UI.Controls.ContextMenu"
x:Class="Microsoft.CmdPal.Core.Control.Controls.ContextMenu"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
xmlns:cmdpalUI="using:Microsoft.CmdPal.UI"
xmlns:cmdpalUI="using:Microsoft.CmdPal.Core.Control"
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:coreViewModels="using:Microsoft.CmdPal.Core.ViewModels"
xmlns:cpcontrols="using:Microsoft.CmdPal.UI.Controls"
xmlns:cpcontrols="using:Microsoft.CmdPal.Core.Control.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:help="using:Microsoft.CmdPal.UI.Helpers"
xmlns:help="using:Microsoft.CmdPal.Core.Control.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:viewModels="using:Microsoft.CmdPal.UI.ViewModels"
xmlns:viewModels="using:Microsoft.CmdPal.Core.Control.ViewModels"
xmlns:coreViewModels="using:Microsoft.CmdPal.Core.ViewModels"
Background="Transparent"
mc:Ignorable="d">

View File

@@ -12,7 +12,7 @@ using Microsoft.UI.Xaml.Input;
using Windows.System;
using Windows.UI.Core;
namespace Microsoft.CmdPal.UI.Controls;
namespace Microsoft.CmdPal.Core.Control.Controls;
public sealed partial class ContextMenu : UserControl,
IRecipient<OpenContextMenuMessage>,

View File

@@ -2,14 +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 Microsoft.CmdPal.Core.Control.Deferred;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.UI.Deferred;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.Foundation;
namespace Microsoft.CmdPal.UI.Controls;
namespace Microsoft.CmdPal.Core.Control.Controls;
/// <summary>
/// A helper control which takes an <see cref="IconSource"/> and creates the corresponding <see cref="IconElement"/>.
@@ -49,6 +49,8 @@ public partial class IconBox : ContentControl
/// </summary>
public event TypedEventHandler<IconBox, SourceRequestedEventArgs>? SourceRequested;
// [DynamicWindowsRuntimeCast(typeof(FontIconSource))]
// [DynamicWindowsRuntimeCast(typeof(IconSource))]
private static void OnSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is IconBox @this)
@@ -79,6 +81,7 @@ public partial class IconBox : ContentControl
}
}
// [DynamicWindowsRuntimeCast(typeof(FontIconSource))]
private static void OnSourceKeyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is IconBox @this)

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<UserControl
x:Class="Microsoft.CmdPal.UI.Controls.SearchBar"
x:Class="Microsoft.CmdPal.Core.Control.Controls.SearchBar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cmdpalUi="using:Microsoft.CmdPal.UI"
xmlns:cmdpalUi="using:Microsoft.CmdPal.Core.Control"
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:cpcontrols="using:Microsoft.CmdPal.UI.Controls"
xmlns:cpcontrols="using:Microsoft.CmdPal.Core.Control.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

View File

@@ -5,9 +5,9 @@
using System.Diagnostics;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.WinUI;
using Microsoft.CmdPal.Core.Control.Views;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.UI.Views;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
@@ -16,7 +16,7 @@ using Microsoft.UI.Xaml.Input;
using CoreVirtualKeyStates = Windows.UI.Core.CoreVirtualKeyStates;
using VirtualKey = Windows.System.VirtualKey;
namespace Microsoft.CmdPal.UI.Controls;
namespace Microsoft.CmdPal.Core.Control.Controls;
public sealed partial class SearchBar : UserControl,
IRecipient<GoHomeMessage>,

View File

@@ -6,7 +6,7 @@ using CommunityToolkit.Common.Deferred;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.CmdPal.UI.Controls;
namespace Microsoft.CmdPal.Core.Control.Controls;
/// <summary>
/// See <see cref="IconBox.SourceRequested"/> event.

View File

@@ -2,7 +2,7 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.CmdPal.UI.Controls">
xmlns:local="using:Microsoft.CmdPal.Core.Control.Controls">
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">

View File

@@ -2,18 +2,17 @@
// 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.Core.Control.Helpers;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.UI.Helpers;
using Microsoft.CommandPalette.Extensions;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
namespace Microsoft.CmdPal.UI.Controls;
namespace Microsoft.CmdPal.Core.Control.Controls;
[TemplatePart(Name = TagIconBox, Type = typeof(IconBox))]
public partial class Tag : Control
public partial class Tag : Microsoft.UI.Xaml.Controls.Control
{
internal const string TagIconBox = "PART_Icon";

View File

@@ -8,7 +8,7 @@ using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
namespace Microsoft.CmdPal.UI;
namespace Microsoft.CmdPal.Core.Control;
internal sealed partial class ContextItemTemplateSelector : DataTemplateSelector
{
@@ -18,6 +18,7 @@ internal sealed partial class ContextItemTemplateSelector : DataTemplateSelector
public DataTemplate? Separator { get; set; }
// [DynamicWindowsRuntimeCast(typeof(ListViewItem))]
protected override DataTemplate? SelectTemplateCore(object item, DependencyObject dependencyObject)
{
DataTemplate? dataTemplate = Default;

View File

@@ -6,7 +6,7 @@ using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.CmdPal.UI;
namespace Microsoft.CmdPal.Core.Control;
public partial class DetailsDataTemplateSelector : DataTemplateSelector
{

View File

@@ -5,9 +5,9 @@
using Microsoft.CommandPalette.Extensions;
using Microsoft.UI.Xaml.Data;
using Windows.System;
using RS_ = Microsoft.CmdPal.UI.Helpers.ResourceLoaderInstance;
using RS_ = Microsoft.CmdPal.Core.Control.Helpers.ResourceLoaderInstance;
namespace Microsoft.CmdPal.UI;
namespace Microsoft.CmdPal.Core.Control;
public partial class KeyChordToStringConverter : IValueConverter
{

View File

@@ -6,10 +6,11 @@ using Microsoft.CommandPalette.Extensions;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Data;
namespace Microsoft.CmdPal.UI;
namespace Microsoft.CmdPal.Core.Control;
public partial class MessageStateToSeverityConverter : IValueConverter
{
// [DynamicWindowsRuntimeCast(typeof(MessageState))]
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is MessageState state)

View File

@@ -3,9 +3,9 @@
// See the LICENSE file in the project root for more information.
using Microsoft.UI.Xaml.Data;
using RS_ = Microsoft.CmdPal.UI.Helpers.ResourceLoaderInstance;
using RS_ = Microsoft.CmdPal.Core.Control.Helpers.ResourceLoaderInstance;
namespace Microsoft.CmdPal.UI;
namespace Microsoft.CmdPal.Core.Control;
public partial class PlaceholderTextConverter : IValueConverter
{

View File

@@ -6,10 +6,14 @@ using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
namespace Microsoft.CmdPal.UI;
namespace Microsoft.CmdPal.Core.Control;
public static class CleanupHelper
{
// [DynamicWindowsRuntimeCast(typeof(ItemsControl))]
// [DynamicWindowsRuntimeCast(typeof(FrameworkElement))]
// [DynamicWindowsRuntimeCast(typeof(ItemsRepeater))]
// [DynamicWindowsRuntimeCast(typeof(TabView))]
public static void Cleanup(FrameworkElement element)
{
var count = VisualTreeHelper.GetChildrenCount(element);

View File

@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="Microsoft.CmdPal.UI.ListPage"
x:Class="Microsoft.CmdPal.Core.Control.ListPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:coreViewModels="using:Microsoft.CmdPal.Core.ViewModels"
xmlns:cpcontrols="using:Microsoft.CmdPal.UI.Controls"
xmlns:cpcontrols="using:Microsoft.CmdPal.Core.Control.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:help="using:Microsoft.CmdPal.UI.Helpers"
xmlns:local="using:Microsoft.CmdPal.UI"
xmlns:help="using:Microsoft.CmdPal.Core.Control.Helpers"
xmlns:local="using:Microsoft.CmdPal.Core.Control"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="using:Microsoft.CmdPal.UI.ViewModels"
xmlns:coreViewModels="using:Microsoft.CmdPal.Core.ViewModels"
xmlns:viewModels="using:Microsoft.CmdPal.Core.Control.ViewModels"
Background="Transparent"
mc:Ignorable="d">

View File

@@ -4,18 +4,15 @@
using System.Diagnostics;
using CommunityToolkit.Mvvm.Messaging;
using ManagedCommon;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.CmdPal.UI;
namespace Microsoft.CmdPal.Core.Control;
public sealed partial class ListPage : Page,
IRecipient<NavigateNextCommand>,
@@ -97,16 +94,18 @@ public sealed partial class ListPage : Page,
{
if (e.ClickedItem is ListItemViewModel item)
{
var settings = App.Current.Services.GetService<SettingsModel>()!;
if (settings.SingleClickActivates)
{
ViewModel?.InvokeItemCommand.Execute(item);
}
else
{
ViewModel?.UpdateSelectedItemCommand.Execute(item);
WeakReferenceMessenger.Default.Send<FocusSearchBoxMessage>();
}
// TODO! settings?
// var settings = App.Current.Services.GetService<SettingsModel>()!;
// if (settings.SingleClickActivates)
// {
// ViewModel?.InvokeItemCommand.Execute(item);
// }
// else
// {
ViewModel?.UpdateSelectedItemCommand.Execute(item);
WeakReferenceMessenger.Default.Send<FocusSearchBoxMessage>();
// }
}
}
@@ -114,11 +113,13 @@ public sealed partial class ListPage : Page,
{
if (ItemsList.SelectedItem is ListItemViewModel vm)
{
var settings = App.Current.Services.GetService<SettingsModel>()!;
if (!settings.SingleClickActivates)
{
ViewModel?.InvokeItemCommand.Execute(vm);
}
// TODO! settings?
// var settings = App.Current.Services.GetService<SettingsModel>()!;
// if (!settings.SingleClickActivates)
// {
ViewModel?.InvokeItemCommand.Execute(vm);
// }
}
}
@@ -245,7 +246,7 @@ public sealed partial class ListPage : Page,
}
else if (e.NewValue == null)
{
Logger.LogDebug("cleared view model");
CoreLogger.LogDebug("cleared view model");
}
}
}
@@ -276,6 +277,7 @@ public sealed partial class ListPage : Page,
}
}
// [DynamicWindowsRuntimeCast(typeof(ScrollViewer))]
private ScrollViewer? FindScrollViewer(DependencyObject parent)
{
if (parent is ScrollViewer)
@@ -296,6 +298,7 @@ public sealed partial class ListPage : Page,
return null;
}
// [DynamicWindowsRuntimeCast(typeof(FrameworkElement))]
private void ItemsList_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
if (e.OriginalSource is FrameworkElement element &&

View File

@@ -2,11 +2,10 @@
// 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.Core.Control.Controls;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.UI.Controls;
using Microsoft.CmdPal.UI.Helpers;
namespace Microsoft.CmdPal.UI.Helpers;
namespace Microsoft.CmdPal.Core.Control.Helpers;
/// <summary>
/// Common async event handler provides the cache lookup function for the <see cref="IconBox.SourceRequested"/> deferred event.

View File

@@ -10,7 +10,7 @@ using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Imaging;
using Windows.Storage.Streams;
namespace Microsoft.CmdPal.UI.Helpers;
namespace Microsoft.CmdPal.Core.Control.Helpers;
public sealed class IconCacheService(DispatcherQueue dispatcherQueue)
{

View File

@@ -7,7 +7,7 @@ using Microsoft.UI;
using Microsoft.UI.Xaml.Media;
using Color = Windows.UI.Color;
namespace Microsoft.CmdPal.UI.Helpers;
namespace Microsoft.CmdPal.Core.Control.Helpers;
public static partial class OptionalColorBrushCacheProvider
{

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using Microsoft.Windows.ApplicationModel.Resources;
namespace Microsoft.CmdPal.UI.Helpers;
namespace Microsoft.CmdPal.Core.Control.Helpers;
internal static class ResourceLoaderInstance
{

View File

@@ -6,7 +6,7 @@ using CommunityToolkit.Common.Deferred;
using Windows.Foundation;
// Pilfered from CommunityToolkit.WinUI.Deferred
namespace Microsoft.CmdPal.UI.Deferred;
namespace Microsoft.CmdPal.Core.Control.Deferred;
/// <summary>
/// Extensions to <see cref="TypedEventHandler{TSender, TResult}"/> for Deferred Events.

View File

@@ -0,0 +1,106 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\CmdPalVersion.props" />
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\Common.Dotnet.AotCompatibility.props" />
<PropertyGroup>
<RootNamespace>Microsoft.CmdPal.Core.Control</RootNamespace>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath>
<!-- For MVVM Toolkit Partial Properties/AOT support -->
<LangVersion>preview</LangVersion>
<!-- Disable SA1313 for Primary Constructor fields conflict https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/instance-constructors#primary-constructors -->
<NoWarn>SA1313;</NoWarn>
</PropertyGroup>
<PropertyGroup>
<CsWinRTAotOptimizerEnabled>true</CsWinRTAotOptimizerEnabled>
</PropertyGroup>
<PropertyGroup>
<!-- This lets us actually reference types from Microsoft.Terminal.UI -->
<CsWinRTIncludes>Microsoft.Terminal.UI;</CsWinRTIncludes>
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" />
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
<PackageReference Include="CommunityToolkit.WinUI.Animations" />
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Markdown" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
<PackageReference Include="Microsoft.WindowsAppSDK" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" />
<!-- <PackageReference Include="WinUIEx" /> -->
<PackageReference Include="Microsoft.Windows.CsWin32">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="System.Net.Http" />
</ItemGroup>
<!--
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
Tools extension to be activated for this project even if the Windows App SDK Nuget
package has not yet been restored.
-->
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />
</ItemGroup>
<ItemGroup>
<RdXmlFile Include="rd.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.CmdPal.Common\Microsoft.CmdPal.Common.csproj" />
<ProjectReference Include="..\Microsoft.CmdPal.Core.ViewModels\Microsoft.CmdPal.Core.ViewModels.csproj" />
<ProjectReference Include="..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
<ProjectReference Include="..\Microsoft.Terminal.UI\Microsoft.Terminal.UI.vcxproj">
<ReferenceOutputAssembly>True</ReferenceOutputAssembly>
<Private>True</Private>
<CopyLocalSatelliteAssemblies>True</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Page Update="LoadingPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="ShellPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Controls\SearchBar.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Styles\Button.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page>
<Page Update="Styles\TextBox.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page>
<Page Update="Styles\Colors.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Styles\Settings.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="Microsoft.CmdPal.Core.Control.Pages.LoadingPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<ProgressRing
Width="36"
Height="36"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsIndeterminate="True" />
</Grid>
</Page>

View File

@@ -0,0 +1,46 @@
// 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.Core.ViewModels;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.CmdPal.Core.Control.Pages;
/// <summary>
/// We use this page to do initialization of our extensions and cache loading to hydrate our ViewModels.
/// </summary>
public sealed partial class LoadingPage : Page
{
private readonly DispatcherQueue _queue = DispatcherQueue.GetForCurrentThread();
public LoadingPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.Parameter is ShellViewModel shellVM
&& shellVM.LoadCommand != null)
{
// This will load the built-in commands, then navigate to the main page.
// Once the mainpage loads, we'll start loading extensions.
shellVM.LoadCommand.Execute(null);
_ = Task.Run(async () =>
{
await shellVM.LoadCommand.ExecutionTask!;
if (shellVM.LoadCommand.ExecutionTask.Status != TaskStatus.RanToCompletion)
{
// TODO: Handle failure case
}
});
}
base.OnNavigatedTo(e);
}
}

View File

@@ -0,0 +1,515 @@
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="Microsoft.CmdPal.Core.Control.Pages.ShellPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
xmlns:cmdpalUI="using:Microsoft.CmdPal.Core.Control"
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:cpcontrols="using:Microsoft.CmdPal.Core.Control.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:help="using:Microsoft.CmdPal.Core.Control.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:viewModels="using:Microsoft.CmdPal.Core.Control.ViewModels"
xmlns:coreViewModels="using:Microsoft.CmdPal.Core.ViewModels"
Background="Transparent"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Styles/Button.xaml" />
<ResourceDictionary Source="../Styles/Colors.xaml" />
<ResourceDictionary Source="../Styles/TextBlock.xaml" />
<ResourceDictionary Source="../Styles/TextBox.xaml" />
<ResourceDictionary Source="../Styles/Settings.xaml" />
<ResourceDictionary Source="../Controls/Tag.xaml" />
<!-- <ResourceDictionary Source="../Controls/KeyVisual/KeyVisual.xaml" /> -->
</ResourceDictionary.MergedDictionaries>
<converters:StringVisibilityConverter
x:Key="StringNotEmptyToVisibilityConverter"
EmptyValue="Collapsed"
NotEmptyValue="Visible" />
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
<cmdpalUI:MessageStateToSeverityConverter x:Key="MessageStateToSeverityConverter" />
<cmdpalUI:DetailsDataTemplateSelector
x:Key="DetailsDataTemplateSelector"
CommandTemplate="{StaticResource DetailsCommandsTemplate}"
LinkTemplate="{StaticResource DetailsLinkTemplate}"
SeparatorTemplate="{StaticResource DetailsSeparatorTemplate}"
TagTemplate="{StaticResource DetailsTagsTemplate}" />
<converters:BoolToVisibilityConverter
x:Key="BoolToInvertedVisibilityConverter"
FalseValue="Visible"
TrueValue="Collapsed" />
<DataTemplate x:Key="TagTemplate" x:DataType="coreViewModels:TagViewModel">
<cpcontrols:Tag
HorizontalAlignment="Left"
AutomationProperties.Name="{x:Bind Text, Mode=OneWay}"
BackgroundColor="{x:Bind Background, Mode=OneWay}"
FontSize="12"
ForegroundColor="{x:Bind Foreground, Mode=OneWay}"
Icon="{x:Bind Icon, Mode=OneWay}"
Text="{x:Bind Text, Mode=OneWay}"
ToolTipService.ToolTip="{x:Bind ToolTip, Mode=OneWay}" />
</DataTemplate>
<DataTemplate x:Key="CommandTemplate" x:DataType="coreViewModels:CommandViewModel">
<StackPanel Orientation="Vertical">
<Button
Name="Command"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Click="Command_Click"
Style="{StaticResource SubtleButtonStyle}">
<StackPanel VerticalAlignment="Center" Orientation="Horizontal">
<cpcontrols:IconBox
Width="16"
Height="16"
Margin="0,3,8,0"
SourceKey="{x:Bind Icon, Mode=OneWay}"
SourceRequested="{x:Bind help:IconCacheProvider.SourceRequested}" />
<TextBlock Text="{x:Bind Name}" />
</StackPanel>
</Button>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="DetailsLinkTemplate" x:DataType="coreViewModels:DetailsLinkViewModel">
<StackPanel Orientation="Vertical">
<TextBlock
IsTextSelectionEnabled="True"
Text="{x:Bind Key, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
<TextBlock
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
IsTextSelectionEnabled="True"
Text="{x:Bind Text, Mode=OneWay}"
TextWrapping="WrapWholeWords"
Visibility="{x:Bind IsText, Mode=OneWay}" />
<HyperlinkButton
Padding="0"
Content="{x:Bind Text, Mode=OneWay}"
FontSize="12"
NavigateUri="{x:Bind Link, Mode=OneWay}"
Visibility="{x:Bind IsLink, Mode=OneWay}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="DetailsCommandsTemplate" x:DataType="coreViewModels:DetailsCommandsViewModel">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock
IsTextSelectionEnabled="True"
Text="{x:Bind Key, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
<ItemsControl
ItemTemplate="{StaticResource CommandTemplate}"
ItemsSource="{x:Bind Commands, Mode=OneWay}"
Visibility="{x:Bind HasCommands, Mode=OneWay}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="DetailsSeparatorTemplate" x:DataType="coreViewModels:DetailsSeparatorViewModel">
<StackPanel Margin="0,8,8,0" Orientation="Vertical">
<Border
Margin="8,0,0,0"
BorderBrush="{ThemeResource TextFillColorSecondaryBrush}"
BorderThickness="0,0,0,2">
<TextBlock
Margin="-8,0,0,8"
FontWeight="SemiBold"
IsTextSelectionEnabled="True"
Text="{x:Bind Key, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
</Border>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="DetailsTagsTemplate" x:DataType="coreViewModels:DetailsTagsViewModel">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock
IsTextSelectionEnabled="True"
Text="{x:Bind Key, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
<ItemsControl
ItemTemplate="{StaticResource TagTemplate}"
ItemsSource="{x:Bind Tags, Mode=OneWay}"
Visibility="{x:Bind HasTags, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel
x:Name="TagsWrapPanel"
MinWidth="0"
Padding="0"
HorizontalSpacing="4"
Orientation="Horizontal"
VerticalSpacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ResourceDictionary>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Background="{ThemeResource LayerOnAcrylicPrimaryBackgroundBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Back button and search box -->
<Grid
Padding="0,12,0,12"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Back button -->
<StackPanel Orientation="Horizontal">
<Image
Width="20"
Margin="20,0,6,0"
HorizontalAlignment="Center"
ui:VisualExtensions.NormalizedCenterPoint="0.5,0.5"
AutomationProperties.AccessibilityView="Raw"
Source="ms-appx:///Assets/icon.svg"
Visibility="{x:Bind ViewModel.CurrentPage.IsNested, Mode=OneWay, Converter={StaticResource BoolToInvertedVisibilityConverter}}">
<animations:Implicit.ShowAnimations>
<animations:OpacityAnimation
EasingMode="EaseIn"
EasingType="Cubic"
From="0"
To="1.0"
Duration="0:0:0.187" />
<animations:ScaleAnimation
EasingMode="EaseIn"
EasingType="Cubic"
From="0.5"
To="1"
Duration="0:0:0.187" />
</animations:Implicit.ShowAnimations>
<animations:Implicit.HideAnimations>
<animations:OpacityAnimation
EasingMode="EaseOut"
EasingType="Cubic"
From="1.0"
To="0"
Duration="0:0:0.187" />
<animations:ScaleAnimation
EasingMode="EaseOut"
EasingType="Cubic"
From="1"
To="0.5"
Duration="0:0:0.187" />
</animations:Implicit.HideAnimations>
</Image>
<Button
x:Name="BackButton"
x:Uid="BackButton"
Margin="4,0,4,0"
Padding="4"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ui:VisualExtensions.NormalizedCenterPoint="0.5,0.5"
Content="{ui:FontIcon Glyph=&#xE76B;,
FontSize=14}"
FontSize="16"
Style="{StaticResource SubtleButtonStyle}"
Tapped="BackButton_Tapped"
Visibility="{x:Bind ViewModel.CurrentPage.IsNested, Mode=OneWay}">
<animations:Implicit.ShowAnimations>
<animations:OpacityAnimation
EasingMode="EaseIn"
EasingType="Cubic"
From="0"
To="1.0"
Duration="0:0:0.333" />
<animations:ScaleAnimation
From="0.5"
To="1"
Duration="0:0:0.333" />
<animations:TranslationAnimation
From="16,0,0"
To="0,0,0"
Duration="0:0:0.333" />
</animations:Implicit.ShowAnimations>
<animations:Implicit.HideAnimations>
<animations:OpacityAnimation
EasingMode="EaseOut"
EasingType="Cubic"
From="1.0"
To="0"
Duration="0:0:0.333" />
<animations:ScaleAnimation
EasingMode="EaseOut"
EasingType="Cubic"
From="1"
To="0.5"
Duration="0:0:0.333" />
<animations:TranslationAnimation
EasingMode="EaseOut"
EasingType="Cubic"
From="0,0,0"
To="16,0,0"
Duration="0:0:0.187" />
</animations:Implicit.HideAnimations>
</Button>
<cpcontrols:IconBox
Grid.Column="1"
Width="20"
Margin="4,0,4,0"
VerticalAlignment="Center"
ui:VisualExtensions.NormalizedCenterPoint="0.5,0.5"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
SourceKey="{x:Bind ViewModel.CurrentPage.Icon, Mode=OneWay}"
SourceRequested="{x:Bind help:IconCacheProvider.SourceRequested}"
Visibility="{x:Bind ViewModel.CurrentPage.IsNested, Mode=OneWay}">
<animations:Implicit.ShowAnimations>
<animations:OpacityAnimation
From="0"
To="1.0"
Duration="0:0:0.333" />
<animations:ScaleAnimation
From="0.8"
To="1"
Duration="0:0:0.333" />
<animations:TranslationAnimation
From="8,0,0"
To="0,0,0"
Duration="0:0:0.187" />
</animations:Implicit.ShowAnimations>
<animations:Implicit.HideAnimations>
<animations:OpacityAnimation
From="1.0"
To="0"
Duration="0:0:0.333" />
<animations:ScaleAnimation
From="1"
To="0.8"
Duration="0:0:0.333" />
<animations:TranslationAnimation
From="0,0,0"
To="8,0,0"
Duration="0:0:0.187" />
</animations:Implicit.HideAnimations>
</cpcontrols:IconBox>
</StackPanel>
<!-- Search box: wrapped in a grid to enable RepositionThemeTransitions -->
<Grid Grid.Column="1" HorizontalAlignment="Stretch">
<cpcontrols:SearchBar
x:Name="SearchBox"
HorizontalAlignment="Stretch"
CurrentPageViewModel="{x:Bind ViewModel.CurrentPage, Mode=OneWay}" />
<Grid.Transitions>
<TransitionCollection>
<RepositionThemeTransition />
</TransitionCollection>
</Grid.Transitions>
</Grid>
</Grid>
<ProgressBar
Grid.ColumnSpan="2"
VerticalAlignment="Bottom"
IsIndeterminate="True"
Visibility="{x:Bind ViewModel.CurrentPage.IsLoading, Mode=OneWay}">
<animations:Implicit.ShowAnimations>
<animations:OpacityAnimation
From="0"
To="1.0"
Duration="0:0:0.333" />
</animations:Implicit.ShowAnimations>
<animations:Implicit.HideAnimations>
<animations:OpacityAnimation
From="1.0"
To="0"
Duration="0:0:0.333" />
</animations:Implicit.HideAnimations>
</ProgressBar>
<Grid
x:Name="ContentGrid"
Grid.Row="1"
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
BorderThickness="0,1,0,1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition x:Name="DetailsColumn" Width="Auto" />
</Grid.ColumnDefinitions>
<Frame
Name="RootFrame"
IsNavigationStackEnabled="True"
Navigated="RootFrame_Navigated" />
<ScrollViewer
x:Name="DetailsContent"
Grid.Column="1"
Margin="4"
HorizontalAlignment="Stretch"
ui:VisualExtensions.NormalizedCenterPoint="0.5,0.5"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="{StaticResource ControlCornerRadius}"
Visibility="Collapsed">
<animations:Implicit.ShowAnimations>
<animations:OpacityAnimation
From="0"
To="1.0"
Duration="0:0:0.187" />
<animations:TranslationAnimation
From="24,0,0"
To="0,0,0"
Duration="0:0:0.187" />
</animations:Implicit.ShowAnimations>
<animations:Implicit.HideAnimations>
<animations:OpacityAnimation
From="1.0"
To="0"
Duration="0:0:0.187" />
<animations:TranslationAnimation
From="0,0,0"
To="24,0,0"
Duration="0:0:0.187" />
</animations:Implicit.HideAnimations>
<Grid Margin="16">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<cpcontrols:IconBox
x:Name="HeroImageBorder"
Width="64"
Margin="0,0,16,16"
HorizontalAlignment="Left"
AutomationProperties.AccessibilityView="Raw"
SourceKey="{x:Bind ViewModel.Details.HeroImage, Mode=OneWay}"
SourceRequested="{x:Bind help:IconCacheProvider.SourceRequested}"
Visibility="{x:Bind HasHeroImage, Mode=OneWay}" />
<TextBlock
Grid.Row="1"
FontSize="18"
FontWeight="SemiBold"
Text="{x:Bind ViewModel.Details.Title, Mode=OneWay}"
TextWrapping="WrapWholeWords"
Visibility="{x:Bind ViewModel.Details.Title, Converter={StaticResource StringNotEmptyToVisibilityConverter}, Mode=OneWay}" />
<toolkit:MarkdownTextBlock
Grid.Row="2"
Margin="0,4,0,24"
Background="Transparent"
Header3FontSize="12"
Header3FontWeight="Normal"
Header3Foreground="{ThemeResource TextFillColorSecondaryBrush}"
IsTextSelectionEnabled="True"
Text="{x:Bind ViewModel.Details.Body, Mode=OneWay}" />
<ItemsRepeater
Grid.Row="3"
ItemTemplate="{StaticResource DetailsDataTemplateSelector}"
ItemsSource="{x:Bind ViewModel.Details.Metadata, Mode=OneWay}">
<ItemsRepeater.Layout>
<StackLayout Spacing="12" />
</ItemsRepeater.Layout>
</ItemsRepeater>
</Grid>
</ScrollViewer>
<!-- /DetailsContent -->
</Grid>
<ScrollView
Grid.Row="2"
Grid.ColumnSpan="2"
MaxHeight="120"
Background="{ThemeResource SystemControlErrorBackgroundColor}"
BorderBrush="{ThemeResource SystemControlErrorTextForegroundBrush}"
BorderThickness="0,1,0,1"
CornerRadius="0"
Visibility="{x:Bind ViewModel.CurrentPage.ErrorMessage, Converter={StaticResource StringNotEmptyToVisibilityConverter}, Mode=OneWay}">
<TextBlock Margin="16,8,16,16" IsTextSelectionEnabled="True">
<Run
FontWeight="SemiBold"
Foreground="{ThemeResource SystemErrorTextColor}"
Text="Error(s) on page:" />
<LineBreak /><Run Text="{x:Bind ViewModel.CurrentPage.ErrorMessage, Mode=OneWay}" />
</TextBlock>
</ScrollView>
</Grid>
<!--
Horrifying: You may ask yourself - why is there a Background on this InfoBar?
Well, as it turns out, the Informational InfoBar has a transparent
background. It just cannot be bothered. So, we need to manually give
it one to actually obscure the text beneath it. And you can't just give
the InfoBar itself a Background, because then the other Severity's
won't get colorized.
See https://github.com/microsoft/microsoft-ui-xaml/issues/5741
-->
<StackPanel
Grid.Row="0"
Margin="16,8,16,8"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
CornerRadius="{ThemeResource ControlCornerRadius}">
<InfoBar
CornerRadius="{ThemeResource ControlCornerRadius}"
IsOpen="{x:Bind ViewModel.CurrentPage.HasStatusMessage, Mode=OneWay}"
Message="{x:Bind ViewModel.CurrentPage.MostRecentStatusMessage.Message, Mode=OneWay}"
Severity="{x:Bind ViewModel.CurrentPage.MostRecentStatusMessage.State, Mode=OneWay, Converter={StaticResource MessageStateToSeverityConverter}}">
<InfoBar.Content>
<ProgressBar
Margin="0,-20,0,0"
IsIndeterminate="{x:Bind ViewModel.CurrentPage.MostRecentStatusMessage.Progress.IsIndeterminate, Mode=OneWay}"
Visibility="{x:Bind ViewModel.CurrentPage.MostRecentStatusMessage.HasProgress, Mode=OneWay}"
Value="{x:Bind ViewModel.CurrentPage.MostRecentStatusMessage.Progress.ProgressPercent, Mode=OneWay}" />
<!-- Margin="0,0,0,6" MaxWidth="200"/> -->
</InfoBar.Content>
</InfoBar>
</StackPanel>
<Grid Grid.Row="1" Background="{ThemeResource LayerOnAcrylicSecondaryBackgroundBrush}">
<cpcontrols:CommandBar CurrentPageViewModel="{x:Bind ViewModel.CurrentPage, Mode=OneWay}" />
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="DetailsCollapsed" />
<VisualState x:Name="DetailsVisible">
<VisualState.StateTriggers>
<StateTrigger IsActive="{x:Bind ViewModel.IsDetailsVisible, Mode=OneWay}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="DetailsContent.Visibility" Value="Visible" />
<Setter Target="DetailsColumn.Width" Value="2*" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

View File

@@ -0,0 +1,498 @@
// 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.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.WinUI;
// using ManagedCommon;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
// using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media.Animation;
using DispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue;
namespace Microsoft.CmdPal.Core.Control.Pages;
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
IRecipient<NavigateBackMessage>,
IRecipient<ShowDetailsMessage>,
IRecipient<HideDetailsMessage>,
IRecipient<ClearSearchMessage>,
IRecipient<LaunchUriMessage>,
IRecipient<GoHomeMessage>,
IRecipient<GoBackMessage>,
IRecipient<ShowConfirmationMessage>,
IRecipient<ShowToastMessage>,
IRecipient<NavigateToPageMessage>,
INotifyPropertyChanged
{
private readonly DispatcherQueue _queue = DispatcherQueue.GetForCurrentThread();
private readonly DispatcherQueueTimer _debounceTimer = DispatcherQueue.GetForCurrentThread().CreateTimer();
private readonly TaskScheduler _mainTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
private readonly SlideNavigationTransitionInfo _slideRightTransition = new() { Effect = SlideNavigationTransitionEffect.FromRight };
private readonly SuppressNavigationTransitionInfo _noAnimation = new();
public ShellViewModel? ViewModel
{
get => (ShellViewModel?)GetValue(ViewModelProperty);
set
{
SetValue(ViewModelProperty, value);
RootFrame.Navigate(typeof(LoadingPage), ViewModel);
}
}
// Using a DependencyProperty as the backing store for ViewModel. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.Register(nameof(ViewModel), typeof(ShellViewModel), typeof(ShellPage), new PropertyMetadata(null, null));
public event PropertyChangedEventHandler? PropertyChanged;
public ShellPage()
{
this.InitializeComponent();
// how we are doing navigation around
WeakReferenceMessenger.Default.Register<NavigateBackMessage>(this);
// WeakReferenceMessenger.Default.Register<OpenSettingsMessage>(this);
// WeakReferenceMessenger.Default.Register<HotkeySummonMessage>(this);
// WeakReferenceMessenger.Default.Register<SettingsWindowClosedMessage>(this);
WeakReferenceMessenger.Default.Register<ShowDetailsMessage>(this);
WeakReferenceMessenger.Default.Register<HideDetailsMessage>(this);
WeakReferenceMessenger.Default.Register<ClearSearchMessage>(this);
WeakReferenceMessenger.Default.Register<LaunchUriMessage>(this);
WeakReferenceMessenger.Default.Register<GoHomeMessage>(this);
WeakReferenceMessenger.Default.Register<GoBackMessage>(this);
WeakReferenceMessenger.Default.Register<ShowConfirmationMessage>(this);
WeakReferenceMessenger.Default.Register<ShowToastMessage>(this);
WeakReferenceMessenger.Default.Register<NavigateToPageMessage>(this);
AddHandler(PointerPressedEvent, new PointerEventHandler(ShellPage_OnPointerPressed), true);
}
// protected override void OnNavigatedTo(NavigationEventArgs e)
// {
// if (e.Parameter is ShellViewModel vm)
// {
// ViewModel = vm;
// }
// }
public void Receive(NavigateBackMessage message)
{
// var settings = App.Current.Services.GetService<SettingsModel>()!;
// if (RootFrame.CanGoBack)
// {
// if (!message.FromBackspace ||
// settings.BackspaceGoesBack)
// {
// GoBack();
// }
// }
// else
// {
// if (!message.FromBackspace)
// {
// // If we can't go back then we must be at the top and thus escape again should quit.
// WeakReferenceMessenger.Default.Send<DismissMessage>();
// PowerToysTelemetry.Log.WriteEvent(new CmdPalDismissedOnEsc());
// }
// }
GoBack();
}
public void Receive(NavigateToPageMessage message)
{
// TODO GH #526 This needs more better locking too
_ = _queue.TryEnqueue(() =>
{
// Also hide our details pane about here, if we had one
HideDetails();
// Navigate to the appropriate host page for that VM
RootFrame.Navigate(
message.Page switch
{
ListViewModel => typeof(ListPage),
// ContentPageViewModel => typeof(ContentPage),
_ => throw new NotSupportedException(),
},
message.Page,
message.WithAnimation ? _slideRightTransition : _noAnimation);
// TODO! Telem
// PowerToysTelemetry.Log.WriteEvent(new OpenPage(RootFrame.BackStackDepth));
// Refocus on the Search for continual typing on the next search request
SearchBox.Focus(Microsoft.UI.Xaml.FocusState.Programmatic);
if (!(ViewModel?.IsNested ?? false))
{
// todo BODGY
RootFrame.BackStack.Clear();
}
});
}
public void Receive(ShowConfirmationMessage message)
{
DispatcherQueue.TryEnqueue(async () =>
{
try
{
await HandleConfirmArgsOnUiThread(message.Args);
}
catch (Exception ex)
{
CoreLogger.LogError(ex.ToString());
}
});
}
public void Receive(ShowToastMessage message)
{
// DispatcherQueue.TryEnqueue(() =>
// {
// _toast.ShowToast(message.Message);
// });
}
// This gets called from the UI thread
private async Task HandleConfirmArgsOnUiThread(IConfirmationArgs? args)
{
if (args == null)
{
return;
}
if (ViewModel == null)
{
return;
}
ConfirmResultViewModel vm = new(args, new(ViewModel.CurrentPage));
var initializeDialogTask = Task.Run(() => { InitializeConfirmationDialog(vm); });
await initializeDialogTask;
var resourceLoader = Microsoft.CmdPal.Core.Control.Helpers.ResourceLoaderInstance.ResourceLoader;
var confirmText = resourceLoader.GetString("ConfirmationDialog_ConfirmButtonText");
var cancelText = resourceLoader.GetString("ConfirmationDialog_CancelButtonText");
var name = string.IsNullOrEmpty(vm.PrimaryCommand.Name) ? confirmText : vm.PrimaryCommand.Name;
ContentDialog dialog = new()
{
Title = vm.Title,
Content = vm.Description,
PrimaryButtonText = name,
CloseButtonText = cancelText,
XamlRoot = this.XamlRoot,
};
if (vm.IsPrimaryCommandCritical)
{
dialog.DefaultButton = ContentDialogButton.Close;
// TODO: Maybe we need to style the primary button to be red?
// dialog.PrimaryButtonStyle = new Style(typeof(Button))
// {
// Setters =
// {
// new Setter(Button.ForegroundProperty, new SolidColorBrush(Colors.Red)),
// new Setter(Button.BackgroundProperty, new SolidColorBrush(Colors.Red)),
// },
// };
}
var result = await dialog.ShowAsync();
if (result == ContentDialogResult.Primary)
{
var performMessage = new PerformCommandMessage(vm);
WeakReferenceMessenger.Default.Send(performMessage);
}
else
{
// cancel
}
}
private void InitializeConfirmationDialog(ConfirmResultViewModel vm)
{
vm.SafeInitializePropertiesSynchronous();
}
// public void Receive(OpenSettingsMessage message)
// {
// _ = DispatcherQueue.TryEnqueue(() =>
// {
// OpenSettings();
// });
// }
// public void OpenSettings()
// {
// if (_settingsWindow == null)
// {
// _settingsWindow = new SettingsWindow();
// }
// _settingsWindow.Activate();
// }
public void Receive(ShowDetailsMessage message)
{
// TERRIBLE HACK TODO GH #245
// There's weird wacky bugs with debounce currently.
if (ViewModel != null && !ViewModel.IsDetailsVisible)
{
ViewModel.Details = message.Details;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasHeroImage)));
ViewModel.IsDetailsVisible = true;
return;
}
// GH #322:
// For inexplicable reasons, if you try to change the details too fast,
// we'll explode. This seemingly only happens if you change the details
// while we're also scrolling a new list view item into view.
_debounceTimer.Debounce(
() =>
{
if (ViewModel != null)
{
ViewModel.Details = message.Details;
}
// Trigger a re-evaluation of whether we have a hero image based on
// the current theme
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasHeroImage)));
},
interval: TimeSpan.FromMilliseconds(50),
immediate: ViewModel?.IsDetailsVisible == false);
if (ViewModel != null)
{
ViewModel.IsDetailsVisible = true;
}
}
public void Receive(HideDetailsMessage message) => HideDetails();
public void Receive(LaunchUriMessage message) => _ = global::Windows.System.Launcher.LaunchUriAsync(message.Uri);
private void HideDetails()
{
if (ViewModel != null)
{
ViewModel.Details = null;
ViewModel.IsDetailsVisible = false;
}
}
public void Receive(ClearSearchMessage message) => SearchBox.ClearSearch();
// public void Receive(HotkeySummonMessage message)
// {
// _ = DispatcherQueue.TryEnqueue(() => SummonOnUiThread(message));
// }
// public void Receive(SettingsWindowClosedMessage message) => _settingsWindow = null;
// private void SummonOnUiThread(HotkeySummonMessage message)
// {
// var settings = App.Current.Services.GetService<SettingsModel>()!;
// var commandId = message.CommandId;
// var isRoot = string.IsNullOrEmpty(commandId);
// if (isRoot)
// {
// // If this is the hotkey for the root level, then always show us
// WeakReferenceMessenger.Default.Send<ShowWindowMessage>(new(message.Hwnd));
// // Depending on the settings, either
// // * Go home, or
// // * Select the search text (if we should remain open on this page)
// if (settings.HotkeyGoesHome)
// {
// GoHome(false);
// }
// else if (settings.HighlightSearchOnActivate)
// {
// SearchBox.SelectSearch();
// }
// }
// else
// {
// try
// {
// // For a hotkey bound to a command, first lookup the
// // command from our list of toplevel commands.
// var tlcManager = App.Current.Services.GetService<TopLevelCommandManager>()!;
// var topLevelCommand = tlcManager.LookupCommand(commandId);
// if (topLevelCommand != null)
// {
// var command = topLevelCommand.CommandViewModel.Model.Unsafe;
// var isPage = command is not IInvokableCommand;
// // If the bound command is an invokable command, then
// // we don't want to open the window at all - we want to
// // just do it.
// if (isPage)
// {
// // If we're here, then the bound command was a page
// // of some kind. Let's pop the stack, show the window, and navigate to it.
// GoHome(false);
// WeakReferenceMessenger.Default.Send<ShowWindowMessage>(new(message.Hwnd));
// }
// var msg = topLevelCommand.GetPerformCommandMessage();
// msg.WithAnimation = false;
// WeakReferenceMessenger.Default.Send<PerformCommandMessage>(msg);
// // we can't necessarily SelectSearch() here, because when the page is loaded,
// // we'll fetch the SearchText from the page itself, and that'll stomp the
// // selection we start now.
// // That's probably okay though.
// }
// }
// catch
// {
// }
// }
// WeakReferenceMessenger.Default.Send<FocusSearchBoxMessage>();
// }
public void Receive(GoBackMessage message)
{
_ = DispatcherQueue.TryEnqueue(() => GoBack(message.WithAnimation, message.FocusSearch));
}
private void GoBack(bool withAnimation = true, bool focusSearch = true)
{
HideDetails();
// Note: That we restore the VM state below in RootFrame_Navigated call back after this occurs.
// In the future, we may want to manage the back stack ourselves vs. relying on Frame
// We could replace Frame with a ContentPresenter, but then have to manage transition animations ourselves.
// However, then we have more fine-grained control on the back stack, managing the VM cache, and not
// having that all be a black box, though then we wouldn't cache the XAML page itself, but sometimes that is a drawback.
// However, we do a good job here, see ForwardStack.Clear below, and BackStack.Clear above about managing that.
if (withAnimation)
{
RootFrame.GoBack();
}
else
{
RootFrame.GoBack(_noAnimation);
}
// Don't store pages we're navigating away from in the Frame cache
// TODO: In the future we probably want a short cache (3-5?) of recent VMs in case the user re-navigates
// back to a recent page they visited (like the Pokedex) so we don't have to reload it from scratch.
// That'd be retrieved as we re-navigate in the PerformCommandMessage logic above
RootFrame.ForwardStack.Clear();
if (!RootFrame.CanGoBack)
{
ViewModel?.GoHome();
}
if (focusSearch)
{
SearchBox.Focus(Microsoft.UI.Xaml.FocusState.Programmatic);
SearchBox.SelectSearch();
}
}
public void Receive(GoHomeMessage message)
{
_ = DispatcherQueue.TryEnqueue(() => GoHome(withAnimation: message.WithAnimation, focusSearch: message.FocusSearch));
}
private void GoHome(bool withAnimation = true, bool focusSearch = true)
{
while (RootFrame.CanGoBack)
{
GoBack(withAnimation, focusSearch);
}
}
private void BackButton_Tapped(object sender, Microsoft.UI.Xaml.Input.TappedRoutedEventArgs e) => WeakReferenceMessenger.Default.Send<NavigateBackMessage>(new());
private void RootFrame_Navigated(object sender, Microsoft.UI.Xaml.Navigation.NavigationEventArgs e)
{
// This listens to the root frame to ensure that we also track the content's page VM as well that we passed as a parameter.
// This is currently used for both forward and backward navigation.
// As when we go back that we restore ourselves to the proper state within our VM
if (e.Parameter is PageViewModel page)
{
// Note, this shortcuts and fights a bit with our LoadPageViewModel above, but we want to better fast display and incrementally load anyway
// We just need to reconcile our loading systems a bit more in the future.
if (ViewModel != null)
{
ViewModel.CurrentPage = page;
}
}
}
/// <summary>
/// Gets a value indicating whether determines if the current Details have a HeroImage, given the theme
/// we're currently in. This needs to be evaluated in the view, because the
/// viewModel doesn't actually know what the current theme is.
/// </summary>
public bool HasHeroImage
{
get
{
var requestedTheme = ActualTheme;
var iconInfoVM = ViewModel?.Details?.HeroImage;
return iconInfoVM?.HasIcon(requestedTheme == Microsoft.UI.Xaml.ElementTheme.Light) ?? false;
}
}
// [DynamicWindowsRuntimeCast(typeof(Button))]
private void Command_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (sender is Button button && button.DataContext is CommandViewModel commandViewModel)
{
WeakReferenceMessenger.Default.Send<PerformCommandMessage>(new(commandViewModel.Model));
}
}
private void ShellPage_OnPointerPressed(object sender, PointerRoutedEventArgs e)
{
try
{
var ptr = e.Pointer;
if (ptr.PointerDeviceType == PointerDeviceType.Mouse)
{
var ptrPt = e.GetCurrentPoint(this);
if (ptrPt.Properties.IsXButton1Pressed)
{
WeakReferenceMessenger.Default.Send(new NavigateBackMessage());
}
}
}
catch (Exception ex)
{
CoreLogger.LogError("Error handling mouse button press event", ex);
}
}
}

View File

@@ -4,7 +4,7 @@
using Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.Views;
namespace Microsoft.CmdPal.Core.Control.Views;
public interface ICurrentPageAware
{

View File

@@ -0,0 +1,7 @@
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name="Microsoft.WinUI">
<Type Name="Microsoft.UI.Xaml.Controls.FontIconSource" Dynamic="Required All" />
</Assembly>
</Application>
</Directives>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8" ?>
<Application
x:Class="Microsoft.CmdPal.Core.UI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.CmdPal.Core.UI">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
<ResourceDictionary Source="Styles/Button.xaml" />
<ResourceDictionary Source="Styles/Colors.xaml" />
<ResourceDictionary Source="Styles/TextBlock.xaml" />
<ResourceDictionary Source="Styles/TextBox.xaml" />
<ResourceDictionary Source="Styles/Settings.xaml" />
<ResourceDictionary Source="Styles/Tag.xaml" />
<!-- <ResourceDictionary Source="Controls/KeyVisual/KeyVisual.xaml" /> -->
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
<!-- <x:Double x:Key="SettingActionControlMinWidth">240</x:Double> -->
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,160 @@
// 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.Core.ViewModels;
using Microsoft.CmdPal.Ext.Shell;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml;
// 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.Core.UI;
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
public partial class App : Application
{
/// <summary>
/// Gets the current <see cref="App"/> instance in use.
/// </summary>
public static new App Current => (App)Application.Current;
public Window? AppWindow { get; private set; }
/// <summary>
/// Gets the <see cref="IServiceProvider"/> instance to resolve application services.
/// </summary>
public IServiceProvider Services { get; }
/// <summary>
/// Initializes a new instance of the <see cref="App"/> class.
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
Services = ConfigureServices();
InitializeComponent();
}
/// <summary>
/// Invoked when the application is launched.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
AppWindow = new MainWindow(Services);
// var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
// ((MainWindow)AppWindow).HandleLaunch(activatedEventArgs);
AppWindow.Activate();
}
/// <summary>
/// Configures the services for the application
/// </summary>
private static ServiceProvider ConfigureServices()
{
// TODO: It's in the Labs feed, but we can use Sergio's AOT-friendly source generator for this: https://github.com/CommunityToolkit/Labs-Windows/discussions/463
ServiceCollection services = new();
// Root services
services.AddSingleton(TaskScheduler.FromCurrentSynchronizationContext());
// Built-in Commands. Order matters - this is the order they'll be presented by default.
services.AddSingleton<ICommandProvider, ShellCommandsProvider>(); // TODO! test
// Models
// TODO!
services.AddSingleton<IRootPageService, CoreRootPageService>();
services.AddSingleton<IAppHostService, DummyAppHostService>();
// services.AddSingleton(new TelemetryForwarder());
// ViewModels
services.AddSingleton<ShellViewModel>();
// TODO!
services.AddSingleton<IPageViewModelFactoryService, CoreViewModelFactory>();
return services.BuildServiceProvider();
}
internal sealed class CoreRootPageService : IRootPageService, IDisposable
{
private readonly ShellCommandsProvider _shellCommandsProvider = new();
public CoreRootPageService()
{
}
public IPage GetRootPage()
{
var commands = _shellCommandsProvider.TopLevelCommands();
var commandItem = commands[0];
return (commandItem.Command as IPage)!;
}
public void GoHome()
{
}
public void OnPerformCommand(object? context, bool topLevel, AppExtensionHost? currentHost)
{
}
public Task PostLoadRootPageAsync()
{
return Task.CompletedTask;
}
public Task PreLoadAsync()
{
return Task.CompletedTask;
}
public void Dispose()
{
throw new NotImplementedException();
}
}
internal sealed partial class DummyAppHost : AppExtensionHost
{
public override string? GetExtensionDisplayName() => "This is test code fool";
}
internal sealed class DummyAppHostService : IAppHostService
{
private readonly DummyAppHost _host = new();
public AppExtensionHost GetDefaultHost() => _host;
public AppExtensionHost GetHostForCommand(object? context, AppExtensionHost? currentHost) => _host;
}
internal sealed class CoreViewModelFactory : IPageViewModelFactoryService
{
private readonly TaskScheduler _scheduler;
public CoreViewModelFactory(TaskScheduler scheduler)
{
_scheduler = scheduler;
}
public PageViewModel? TryCreatePageViewModel(IPage page, bool nested, AppExtensionHost host)
{
return page switch
{
IListPage listPage => new ListViewModel(listPage, _scheduler, host) { IsNested = nested },
IContentPage contentPage => new ContentPageViewModel(contentPage, _scheduler, host),
_ => null,
};
}
}
}

View File

@@ -0,0 +1,11 @@
<Window
x:Class="Microsoft.CmdPal.Core.UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pages="using:Microsoft.CmdPal.Core.Control.Pages"
xmlns:viewModels="using:Microsoft.CmdPal.Core.ViewModels"
mc:Ignorable="d">
<pages:ShellPage x:Name="RootShellPage" ViewModel="{x:Bind ShellViewModel, Mode=OneWay}" />
</Window>

View File

@@ -0,0 +1,668 @@
// 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 CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Common.Messages;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Messages;
// using Microsoft.CmdPal.UI.Events;
// using Microsoft.CmdPal.UI.Helpers;
// using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Composition;
using Microsoft.UI.Composition.SystemBackdrops;
using Microsoft.UI.Input;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.Windows.AppLifecycle;
using Windows.Foundation;
using Windows.Graphics;
using Windows.UI;
using Windows.UI.WindowManagement;
using Windows.Win32.Foundation;
using WinRT;
// using RS_ = Microsoft.CmdPal.UI.Helpers.ResourceLoaderInstance;
namespace Microsoft.CmdPal.Core.UI;
public sealed partial class MainWindow : Window,
IRecipient<DismissMessage>,
IRecipient<ShowWindowMessage>,
IRecipient<HideWindowMessage>,
IRecipient<QuitMessage>
{
// [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Stylistically, window messages are WM_")]
// [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "Stylistically, window messages are WM_")]
// private readonly uint WM_TASKBAR_RESTART;
private readonly HWND _hwnd;
// private readonly WNDPROC? _hotkeyWndProc;
// private readonly WNDPROC? _originalWndProc;
// private readonly List<TopLevelHotkey> _hotkeys = [];
// private readonly KeyboardListener _keyboardListener;
// private bool _ignoreHotKeyWhenFullScreen = true;
private DesktopAcrylicController? _acrylicController;
private SystemBackdropConfiguration? _configurationSource;
public ShellViewModel ShellViewModel { get; }
public MainWindow(IServiceProvider provider)
{
ShellViewModel = provider.GetRequiredService<ShellViewModel>();
InitializeComponent();
_hwnd = new HWND(WinRT.Interop.WindowNative.GetWindowHandle(this).ToInt32());
// unsafe
// {
// CommandPaletteHost.SetHostHwnd((ulong)_hwnd.Value);
// }
// _keyboardListener = new KeyboardListener();
// _keyboardListener.Start();
// _keyboardListener.SetProcessCommand(new CmdPalKeyboardService.ProcessCommand(HandleSummon));
// this.SetIcon();
AppWindow.Title = "Command Palette Core";
AppWindow.Resize(new SizeInt32(740, 320));
PositionCentered();
SetAcrylic();
WeakReferenceMessenger.Default.Register<DismissMessage>(this);
WeakReferenceMessenger.Default.Register<QuitMessage>(this);
WeakReferenceMessenger.Default.Register<ShowWindowMessage>(this);
WeakReferenceMessenger.Default.Register<HideWindowMessage>(this);
// Hide our titlebar.
// We need to both ExtendsContentIntoTitleBar, then set the height to Collapsed
// to hide the old caption buttons. Then, in UpdateRegionsForCustomTitleBar,
// we'll make the top drag-able again. (after our content loads)
ExtendsContentIntoTitleBar = true;
AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Collapsed;
SizeChanged += WindowSizeChanged;
RootShellPage.Loaded += RootShellPage_Loaded;
// WM_TASKBAR_RESTART = PInvoke.RegisterWindowMessage("TaskbarCreated");
// // LOAD BEARING: If you don't stick the pointer to HotKeyPrc into a
// // member (and instead like, use a local), then the pointer we marshal
// // into the WindowLongPtr will be useless after we leave this function,
// // and our **WindProc will explode**.
// _hotkeyWndProc = HotKeyPrc;
// var hotKeyPrcPointer = Marshal.GetFunctionPointerForDelegate(_hotkeyWndProc);
// _originalWndProc = Marshal.GetDelegateForFunctionPointer<WNDPROC>(PInvoke.SetWindowLongPtr(_hwnd, WINDOW_LONG_PTR_INDEX.GWL_WNDPROC, hotKeyPrcPointer));
// Load our settings, and then also wire up a settings changed handler
// HotReloadSettings();
// App.Current.Services.GetService<SettingsModel>()!.SettingsChanged += SettingsChangedHandler;
// Make sure that we update the acrylic theme when the OS theme changes
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", () =>
// {
// Summon(string.Empty);
// });
}
// private void SettingsChangedHandler(SettingsModel sender, object? args) => HotReloadSettings();
private void RootShellPage_Loaded(object sender, RoutedEventArgs e) =>
// Now that our content has loaded, we can update our draggable regions
UpdateRegionsForCustomTitleBar();
private void WindowSizeChanged(object sender, WindowSizeChangedEventArgs args) => UpdateRegionsForCustomTitleBar();
private void PositionCentered()
{
var displayArea = DisplayArea.GetFromWindowId(AppWindow.Id, DisplayAreaFallback.Nearest);
PositionCentered(displayArea);
}
private void PositionCentered(DisplayArea displayArea)
{
if (displayArea is not null)
{
var centeredPosition = AppWindow.Position;
centeredPosition.X = (displayArea.WorkArea.Width - AppWindow.Size.Width) / 2;
centeredPosition.Y = (displayArea.WorkArea.Height - AppWindow.Size.Height) / 2;
centeredPosition.X += displayArea.WorkArea.X;
centeredPosition.Y += displayArea.WorkArea.Y;
AppWindow.Move(centeredPosition);
}
}
// private void HotReloadSettings()
// {
// var settings = App.Current.Services.GetService<SettingsModel>()!;
// SetupHotkey(settings);
// App.Current.Services.GetService<TrayIconService>()!.SetupTrayIcon(settings.ShowSystemTrayIcon);
// _ignoreHotKeyWhenFullScreen = settings.IgnoreShortcutWhenFullscreen;
// this.SetVisibilityInSwitchers(Debugger.IsAttached);
// }
// We want to use DesktopAcrylicKind.Thin and custom colors as this is the default material
// other Shell surfaces are using, this cannot be set in XAML however.
private void SetAcrylic()
{
if (DesktopAcrylicController.IsSupported())
{
// Hooking up the policy object.
_configurationSource = new SystemBackdropConfiguration
{
// Initial configuration state.
IsInputActive = true,
};
UpdateAcrylic();
}
}
private void UpdateAcrylic()
{
_acrylicController = GetAcrylicConfig(Content);
// Enable the system backdrop.
// Note: Be sure to have "using WinRT;" to support the Window.As<...>() call.
_acrylicController.AddSystemBackdropTarget(this.As<ICompositionSupportsSystemBackdrop>());
_acrylicController.SetSystemBackdropConfiguration(_configurationSource);
}
private static DesktopAcrylicController GetAcrylicConfig(UIElement content)
{
var feContent = content as FrameworkElement;
return feContent?.ActualTheme == ElementTheme.Light
? new DesktopAcrylicController()
{
Kind = DesktopAcrylicKind.Thin,
TintColor = Color.FromArgb(255, 243, 243, 243),
LuminosityOpacity = 0.90f,
TintOpacity = 0.0f,
FallbackColor = Color.FromArgb(255, 238, 238, 238),
}
: new DesktopAcrylicController()
{
Kind = DesktopAcrylicKind.Thin,
TintColor = Color.FromArgb(255, 32, 32, 32),
LuminosityOpacity = 0.96f,
TintOpacity = 0.5f,
FallbackColor = Color.FromArgb(255, 28, 28, 28),
};
}
// private void ShowHwnd(IntPtr hwndValue, MonitorBehavior target)
// {
// var hwnd = new HWND(hwndValue != 0 ? hwndValue : _hwnd);
// // Make sure our HWND is cloaked before any possible window manipulations
// Cloak();
// // Remember, IsIconic == "minimized", which is entirely different state
// // from "show/hide"
// // If we're currently minimized, restore us first, before we reveal
// // our window. Otherwise, we'd just be showing a minimized window -
// // which would remain not visible to the user.
// if (PInvoke.IsIconic(hwnd))
// {
// PInvoke.ShowWindow(hwnd, SHOW_WINDOW_CMD.SW_RESTORE);
// }
// var display = GetScreen(hwnd, target);
// PositionCentered(display);
// // Just to be sure, SHOW our hwnd.
// PInvoke.ShowWindow(hwnd, SHOW_WINDOW_CMD.SW_SHOW);
// // Once we're done, uncloak to avoid all animations
// Uncloak();
// PInvoke.SetForegroundWindow(hwnd);
// PInvoke.SetActiveWindow(hwnd);
// // Push our window to the top of the Z-order and make it the topmost, so that it appears above all other windows.
// // We want to remove the topmost status when we hide the window (because we cloak it instead of hiding it).
// PInvoke.SetWindowPos(hwnd, HWND.HWND_TOPMOST, 0, 0, 0, 0, SET_WINDOW_POS_FLAGS.SWP_NOMOVE | SET_WINDOW_POS_FLAGS.SWP_NOSIZE);
// }
// private DisplayArea GetScreen(HWND currentHwnd, MonitorBehavior target)
// {
// // Leaving a note here, in case we ever need it:
// // https://github.com/microsoft/microsoft-ui-xaml/issues/6454
// // If we need to ever FindAll, we'll need to iterate manually
// var displayAreas = Microsoft.UI.Windowing.DisplayArea.FindAll();
// switch (target)
// {
// case MonitorBehavior.InPlace:
// if (PInvoke.GetWindowRect(currentHwnd, out var bounds))
// {
// RectInt32 converted = new(bounds.X, bounds.Y, bounds.Width, bounds.Height);
// return DisplayArea.GetFromRect(converted, DisplayAreaFallback.Nearest);
// }
// break;
// case MonitorBehavior.ToFocusedWindow:
// var foregroundWindowHandle = PInvoke.GetForegroundWindow();
// if (foregroundWindowHandle != IntPtr.Zero)
// {
// if (PInvoke.GetWindowRect(foregroundWindowHandle, out var fgBounds))
// {
// RectInt32 converted = new(fgBounds.X, fgBounds.Y, fgBounds.Width, fgBounds.Height);
// return DisplayArea.GetFromRect(converted, DisplayAreaFallback.Nearest);
// }
// }
// break;
// case MonitorBehavior.ToPrimary:
// return DisplayArea.Primary;
// case MonitorBehavior.ToMouse:
// default:
// if (PInvoke.GetCursorPos(out var cursorPos))
// {
// return DisplayArea.GetFromPoint(new PointInt32(cursorPos.X, cursorPos.Y), DisplayAreaFallback.Nearest);
// }
// break;
// }
// return DisplayArea.Primary;
// }
public void Receive(ShowWindowMessage message)
{
// var settings = App.Current.Services.GetService<SettingsModel>()!;
// ShowHwnd(message.Hwnd, settings.SummonOn);
}
public void Receive(HideWindowMessage message)
{
// This might come in off the UI thread. Make sure to hop back.
DispatcherQueue.TryEnqueue(() =>
{
HideWindow();
});
}
public void Receive(QuitMessage message) =>
// This might come in on a background thread
DispatcherQueue.TryEnqueue(() => Close());
public void Receive(DismissMessage message)
{
// This might come in off the UI thread. Make sure to hop back.
DispatcherQueue.TryEnqueue(() =>
{
HideWindow();
});
}
private void HideWindow()
{
// // Cloak our HWND to avoid all animations.
// Cloak();
// // Then hide our HWND, to make sure that the OS gives the FG / focus back to another app
// // (there's no way for us to guess what the right hwnd might be, only the OS can do it right)
// PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
// // TRICKY: show our HWND again. This will trick XAML into painting our
// // HWND again, so that we avoid the "flicker" caused by a WinUI3 app
// // window being first shown
// // SW_SHOWNA will prevent us for trying to fight the focus back
// PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_SHOWNA);
// // Intentionally leave the window cloaked. So our window is "visible",
// // but also cloaked, so you can't see it.
}
private void Cloak()
{
// unsafe
// {
// BOOL value = true;
// PInvoke.DwmSetWindowAttribute(_hwnd, DWMWINDOWATTRIBUTE.DWMWA_CLOAK, &value, (uint)sizeof(BOOL));
// }
// // Because we're only cloaking the window, bury it at the bottom in case something can
// // see it - e.g. some accessibility helper (note: this also removes the top-most status).
// PInvoke.SetWindowPos(_hwnd, HWND.HWND_BOTTOM, 0, 0, 0, 0, SET_WINDOW_POS_FLAGS.SWP_NOMOVE | SET_WINDOW_POS_FLAGS.SWP_NOSIZE);
}
private void Uncloak()
{
// unsafe
// {
// BOOL value = false;
// PInvoke.DwmSetWindowAttribute(_hwnd, DWMWINDOWATTRIBUTE.DWMWA_CLOAK, &value, (uint)sizeof(BOOL));
// }
}
internal void MainWindow_Closed(object sender, WindowEventArgs args)
{
// var serviceProvider = App.Current.Services;
// var extensionService = serviceProvider.GetService<IExtensionService>()!;
// extensionService.SignalStopExtensionsAsync();
// App.Current.Services.GetService<TrayIconService>()!.Destroy();
// WinUI bug is causing a crash on shutdown when FailFastOnErrors is set to true (#51773592).
// Workaround by turning it off before shutdown.
App.Current.DebugSettings.FailFastOnErrors = false;
DisposeAcrylic();
// _keyboardListener.Stop();
Environment.Exit(0);
}
private void DisposeAcrylic()
{
if (_acrylicController != null)
{
_acrylicController.Dispose();
_acrylicController = null!;
_configurationSource = null!;
}
}
// Updates our window s.t. the top of the window is draggable.
private void UpdateRegionsForCustomTitleBar()
{
// Specify the interactive regions of the title bar.
var scaleAdjustment = RootShellPage.XamlRoot.RasterizationScale;
// Get the rectangle around our XAML content. We're going to mark this
// rectangle as "Passthrough", so that the normal window operations
// (resizing, dragging) don't apply in this space.
var transform = RootShellPage.TransformToVisual(null);
// Reserve 16px of space at the top for dragging.
var topHeight = 16;
var bounds = transform.TransformBounds(new Rect(
0,
topHeight,
RootShellPage.ActualWidth,
RootShellPage.ActualHeight));
var contentRect = GetRect(bounds, scaleAdjustment);
var rectArray = new RectInt32[] { contentRect };
var nonClientInputSrc = InputNonClientPointerSource.GetForWindowId(this.AppWindow.Id);
nonClientInputSrc.SetRegionRects(NonClientRegionKind.Passthrough, rectArray);
// Add a drag-able region on top
var w = RootShellPage.ActualWidth;
_ = RootShellPage.ActualHeight;
var dragSides = new RectInt32[]
{
GetRect(new Rect(0, 0, w, topHeight), scaleAdjustment), // the top, {topHeight=16} tall
};
nonClientInputSrc.SetRegionRects(NonClientRegionKind.Caption, dragSides);
}
private static RectInt32 GetRect(Rect bounds, double scale)
{
return new RectInt32(
_X: (int)Math.Round(bounds.X * scale),
_Y: (int)Math.Round(bounds.Y * scale),
_Width: (int)Math.Round(bounds.Width * scale),
_Height: (int)Math.Round(bounds.Height * scale));
}
internal void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
{
if (args.WindowActivationState == WindowActivationState.Deactivated)
{
// If there's a debugger attached...
if (System.Diagnostics.Debugger.IsAttached)
{
// ... then don't hide the window when it loses focus.
return;
}
// // Are we disabled? If we are, then we don't want to dismiss on focus lost.
// // This can happen if an extension wanted to show a modal dialog on top of our
// // window i.e. in the case of an MSAL auth window.
// if (PInvoke.IsWindowEnabled(_hwnd) == 0)
// {
// return;
// }
// // This will DWM cloak our window:
// HideWindow();
// PowerToysTelemetry.Log.WriteEvent(new CmdPalDismissedOnLostFocus());
}
if (_configurationSource != null)
{
_configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated;
}
}
public void HandleLaunch(AppActivationArguments? activatedEventArgs)
{
if (activatedEventArgs == null)
{
Activate();
return;
}
}
// try
// {
// if (activatedEventArgs.Kind == ExtendedActivationKind.StartupTask)
// {
// return;
// }
// if (activatedEventArgs.Kind == ExtendedActivationKind.Protocol)
// {
// if (activatedEventArgs.Data is IProtocolActivatedEventArgs protocolArgs)
// {
// if (protocolArgs.Uri.ToString() is string uri)
// {
// // was the URI "x-cmdpal://background" ?
// if (uri.StartsWith("x-cmdpal://background", StringComparison.OrdinalIgnoreCase))
// {
// // we're running, we don't want to activate our window. bail
// return;
// }
// else if (uri.StartsWith("x-cmdpal://settings", StringComparison.OrdinalIgnoreCase))
// {
// WeakReferenceMessenger.Default.Send<OpenSettingsMessage>(new());
// return;
// }
// }
// }
// }
// }
// catch (COMException ex)
// {
// // Accessing properties activatedEventArgs.Kind and activatedEventArgs.Data might cause COMException
// // if the args are not valid or not passed correctly.
// Logger.LogError("COM exception when activating the application", ex);
// }
// Summon(string.Empty);
// }
// public void Summon(string commandId) =>
// // The actual showing and hiding of the window will be done by the
// // ShellPage. This is because we don't want to show the window if the
// // user bound a hotkey to just an invokable command, which we can't
// // know till the message is being handled.
// WeakReferenceMessenger.Default.Send<HotkeySummonMessage>(new(commandId, _hwnd));
// private void UnregisterHotkeys()
// {
// _keyboardListener.ClearHotkeys();
// while (_hotkeys.Count > 0)
// {
// PInvoke.UnregisterHotKey(_hwnd, _hotkeys.Count - 1);
// _hotkeys.RemoveAt(_hotkeys.Count - 1);
// }
// }
// private void SetupHotkey(SettingsModel settings)
// {
// UnregisterHotkeys();
// var globalHotkey = settings.Hotkey;
// if (globalHotkey != null)
// {
// if (settings.UseLowLevelGlobalHotkey)
// {
// _keyboardListener.SetHotkeyAction(globalHotkey.Win, globalHotkey.Ctrl, globalHotkey.Shift, globalHotkey.Alt, (byte)globalHotkey.Code, string.Empty);
// _hotkeys.Add(new(globalHotkey, string.Empty));
// }
// else
// {
// var vk = globalHotkey.Code;
// var modifiers =
// (globalHotkey.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
// (globalHotkey.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
// (globalHotkey.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
// (globalHotkey.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
// ;
// var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
// if (success)
// {
// _hotkeys.Add(new(globalHotkey, string.Empty));
// }
// }
// }
// foreach (var commandHotkey in settings.CommandHotkeys)
// {
// var key = commandHotkey.Hotkey;
// if (key != null)
// {
// if (settings.UseLowLevelGlobalHotkey)
// {
// _keyboardListener.SetHotkeyAction(key.Win, key.Ctrl, key.Shift, key.Alt, (byte)key.Code, commandHotkey.CommandId);
// _hotkeys.Add(new(globalHotkey, string.Empty));
// }
// else
// {
// var vk = key.Code;
// var modifiers =
// (key.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
// (key.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
// (key.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
// (key.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
// ;
// var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
// if (success)
// {
// _hotkeys.Add(commandHotkey);
// }
// }
// }
// }
// }
// private void HandleSummon(string commandId)
// {
// var isRootHotkey = string.IsNullOrEmpty(commandId);
// PowerToysTelemetry.Log.WriteEvent(new CmdPalHotkeySummoned(isRootHotkey));
// var isVisible = this.Visible;
// unsafe
// {
// // We need to check if our window is cloaked or not. A cloaked window is still
// // technically visible, because SHOW/HIDE != iconic (minimized) != cloaked
// // (these are all separate states)
// long attr = 0;
// PInvoke.DwmGetWindowAttribute(_hwnd, DWMWINDOWATTRIBUTE.DWMWA_CLOAKED, &attr, sizeof(long));
// if (attr == 1 /* DWM_CLOAKED_APP */)
// {
// isVisible = false;
// }
// }
// // Note to future us: the wParam will have the index of the hotkey we registered.
// // We can use that in the future to differentiate the hotkeys we've pressed
// // so that we can bind hotkeys to individual commands
// if (!isVisible || !isRootHotkey)
// {
// Activate();
// Summon(commandId);
// }
// else if (isRootHotkey)
// {
// // If there's a debugger attached...
// if (System.Diagnostics.Debugger.IsAttached)
// {
// // ... then manually hide our window. When debugged, we won't get the cool cloaking,
// // but that's the price to pay for having the HWND not light-dismiss while we're debugging.
// Cloak();
// this.Hide();
// return;
// }
// HideWindow();
// }
// }
// private LRESULT HotKeyPrc(
// HWND hwnd,
// uint uMsg,
// WPARAM wParam,
// LPARAM lParam)
// {
// switch (uMsg)
// {
// // Prevent the window from maximizing when double-clicking the title bar area
// case PInvoke.WM_NCLBUTTONDBLCLK:
// return (LRESULT)IntPtr.Zero;
// case PInvoke.WM_HOTKEY:
// {
// var hotkeyIndex = (int)wParam.Value;
// if (hotkeyIndex < _hotkeys.Count)
// {
// if (_ignoreHotKeyWhenFullScreen)
// {
// // If we're in full screen mode, ignore the hotkey
// if (WindowHelper.IsWindowFullscreen())
// {
// return (LRESULT)IntPtr.Zero;
// }
// }
// var hotkey = _hotkeys[hotkeyIndex];
// HandleSummon(hotkey.CommandId);
// }
// return (LRESULT)IntPtr.Zero;
// }
// default:
// if (uMsg == WM_TASKBAR_RESTART)
// {
// HotReloadSettings();
// }
// break;
// }
// return PInvoke.CallWindowProc(_originalWndProc, hwnd, uMsg, wParam, lParam);
// }
}

View File

@@ -0,0 +1,114 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\CmdPalVersion.props" />
<Import Project="..\Microsoft.CmdPal.UI\CmdPal.pre.props" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
<RootNamespace>Microsoft.CmdPal.Core.UI</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<Version>$(CmdPalVersion)</Version>
<!-- OutputPath is set in CmdPal.Branding.props -->
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>
<!-- Branding -->
<PropertyGroup>
<ApplicationIcon>$(SolutionDir)\src\modules\cmdpal\Microsoft.CmdPal.UI\Assets\Dev\icon.ico</ApplicationIcon>
<CmdPalAssetSuffix>Dev</CmdPalAssetSuffix>
</PropertyGroup>
<ItemGroup>
<!-- Images -->
<Content Include="$(SolutionDir)\src\modules\cmdpal\Microsoft.CmdPal.UI\Assets\$(CmdPalAssetSuffix)\**\*">
<DeploymentContent>true</DeploymentContent>
<Link>Assets\%(RecursiveDir)%(FileName)%(Extension)</Link>
</Content>
<Manifest Include="$(ApplicationManifest)" />
<AppxManifest Include="Package.appxmanifest" />
</ItemGroup>
<PropertyGroup>
<!-- This lets us actually reference types from Microsoft.Terminal.UI -->
<!-- <CsWinRTIncludes>Microsoft.Terminal.UI;</CsWinRTIncludes> -->
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
</PropertyGroup>
<PropertyGroup>
<!-- This disables the auto-generated main, so we can be single-instanced -->
<DefineConstants>DISABLE_XAML_GENERATED_MAIN</DefineConstants>
</PropertyGroup>
<!-- BODGY: XES Versioning and WinAppSDK get into a fight about the app manifest, which breaks WinAppSDK. -->
<Target Name="RearrangeXefVersioningAndWinAppSDKResourceGeneration" DependsOnTargets="GetNewAppManifestValues;CreateWinRTRegistration" BeforeTargets="XesWriteVersionInfoResourceFile">
<PropertyGroup>
<!-- XES uses this property to store the "final" location of the app manifest, before it erases it.
We have to update it to the value WinAppSDK set it to. -->
<OriginalApplicationManifest>$(ApplicationManifest.Replace("$(MSBuildProjectDirectory)\",""))</OriginalApplicationManifest>
</PropertyGroup>
<Message Importance="High" Text="Updated final manifest path to $(OriginalApplicationManifest)" />
</Target>
<ItemGroup>
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" />
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
<PackageReference Include="CommunityToolkit.WinUI.Animations" />
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Markdown" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
<PackageReference Include="Microsoft.WindowsAppSDK" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" />
<PackageReference Include="WinUIEx" />
<PackageReference Include="Microsoft.Windows.CsWin32">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="System.Net.Http" />
<PackageReference Include="System.Private.Uri" />
<PackageReference Include="System.Text.Json" />
<PackageReference Include="System.Text.RegularExpressions" />
</ItemGroup>
<!--
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
Tools extension to be activated for this project even if the Windows App SDK Nuget
package has not yet been restored.
-->
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />
</ItemGroup>
<ItemGroup>
<RdXmlFile Include="rd.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.CmdPal.Common\Microsoft.CmdPal.Common.csproj" />
<ProjectReference Include="..\Microsoft.CmdPal.Core.ViewModels\Microsoft.CmdPal.Core.ViewModels.csproj" />
<ProjectReference Include="..\Microsoft.CmdPal.Core.Control\Microsoft.CmdPal.Core.Control.csproj" />
<ProjectReference Include="..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
<!-- As a test: -->
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.Shell\Microsoft.CmdPal.Ext.Shell.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,51 @@
GetPhysicallyInstalledSystemMemory
GlobalMemoryStatusEx
GetSystemInfo
GetForegroundWindow
SetForegroundWindow
GetWindowRect
GetCursorPos
SetWindowPos
HWND_TOPMOST
HWND_BOTTOM
IsIconic
RegisterHotKey
UnregisterHotKey
SetWindowLongPtr
CallWindowProc
ShowWindow
SetForegroundWindow
EnableWindow
IsWindowEnabled
SetFocus
SetActiveWindow
MonitorFromWindow
GetMonitorInfo
GetDpiForMonitor
CoAllowSetForegroundWindow
WM_HOTKEY
WM_NCLBUTTONDBLCLK
Shell_NotifyIcon
LoadIcon
WM_USER
WM_WINDOWPOSCHANGING
RegisterWindowMessageW
ExtractIconEx
TRACK_POPUP_MENU_FLAGS
WM_COMMAND
WM_RBUTTONUP
WM_LBUTTONUP
WM_LBUTTONDBLCLK
CreatePopupMenu
TrackPopupMenuEx
InsertMenu
MessageBox
DwmGetWindowAttribute
DwmSetWindowAttribute
DWM_CLOAKED_APP
CoWaitForMultipleObjects
INFINITE
CWMO_FLAGS

View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
xmlns:uap7="http://schemas.microsoft.com/appx/manifest/uap/windows10/7"
xmlns:uap17="http://schemas.microsoft.com/appx/manifest/uap/windows10/17"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:virtualization="http://schemas.microsoft.com/appx/manifest/virtualization/windows10"
IgnorableNamespaces="uap mp rescap uap3 uap17 desktop6 virtualization">
<Identity
Name="Microsoft.CommandPalette.Core"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Version="0.0.1.0" />
<mp:PhoneIdentity PhoneProductId="69b8faa1-5ada-484f-999d-4998c7ff2082" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>ms-resource:AppName</DisplayName>
<PublisherDisplayName>A Lone Developer</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
<desktop6:RegistryWriteVirtualization>disabled</desktop6:RegistryWriteVirtualization>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.19041.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="ms-resource:AppName"
Description="ms-resource:AppDescription"
BackgroundColor="transparent"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" Square71x71Logo="Assets\SmallTile.png" Square310x310Logo="Assets\LargeTile.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
<Extensions>
<!-- <uap3:Extension Category="windows.appExtensionHost">
<uap3:AppExtensionHost>
<uap3:Name>com.microsoft.commandpalette</uap3:Name>
</uap3:AppExtensionHost>
</uap3:Extension>
<uap5:Extension Category="windows.startupTask">
<uap5:StartupTask
TaskId="CmdPalStartup"
Enabled="false"
DisplayName="ms-resource:StartupTaskName" />
</uap5:Extension> -->
<!-- <uap:Extension Category="windows.protocol">
<uap:Protocol Name="x-cmdpal">
<uap:Logo>Assets\StoreLogo.png</uap:Logo>
<uap:DisplayName>Command Palette URI scheme</uap:DisplayName>
</uap:Protocol>
</uap:Extension> -->
</Extensions>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
<rescap:Capability Name="unvirtualizedResources" />
<rescap:Capability Name="appLicensing" />
</Capabilities>
</Package>

View File

@@ -0,0 +1,134 @@
// 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.UI.Events;
// using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Dispatching;
using Microsoft.Windows.AppLifecycle;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Com;
namespace Microsoft.CmdPal.Core.UI;
// cribbed heavily from
//
// https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/AppLifecycle/Instancing/cs2/cs-winui-packaged/CsWinUiDesktopInstancing
internal sealed class Program
{
private static DispatcherQueueSynchronizationContext? uiContext;
private static App? app;
// LOAD BEARING
//
// Main cannot be async. If it is, then the clipboard won't work, and neither will narrator.
// That means you, the person thinking about making this a MTA thread. Don't
// do it. It won't work. That's not the solution.
[STAThread]
private static int Main(string[] args)
{
// if (Helpers.GpoValueChecker.GetConfiguredCmdPalEnabledValue() == Helpers.GpoRuleConfiguredValue.Disabled)
// {
// // There's a GPO rule configured disabling CmdPal. Exit as soon as possible.
// return 0;
// }
// try
// {
// Logger.InitializeLogger("\\CmdPal\\Logs\\");
// }
// catch (COMException e)
// {
// // This is unexpected. For the sake of debugging:
// // pop a message box
// PInvoke.MessageBox(
// (HWND)IntPtr.Zero,
// $"Failed to initialize the logger. COMException: \r{e.Message}",
// "Command Palette",
// MESSAGEBOX_STYLE.MB_OK | MESSAGEBOX_STYLE.MB_ICONERROR);
// return 0;
// }
// catch (Exception e2)
// {
// // This is unexpected. For the sake of debugging:
// // pop a message box
// PInvoke.MessageBox(
// (HWND)IntPtr.Zero,
// $"Failed to initialize the logger. Unknown Exception: \r{e2.Message}",
// "Command Palette",
// MESSAGEBOX_STYLE.MB_OK | MESSAGEBOX_STYLE.MB_ICONERROR);
// return 0;
// }
// Logger.LogDebug($"Starting at {DateTime.UtcNow}");
// PowerToysTelemetry.Log.WriteEvent(new CmdPalProcessStarted());
WinRT.ComWrappersSupport.InitializeComWrappers();
var isRedirect = DecideRedirection();
if (!isRedirect)
{
Microsoft.UI.Xaml.Application.Start((p) =>
{
uiContext = new DispatcherQueueSynchronizationContext(DispatcherQueue.GetForCurrentThread());
SynchronizationContext.SetSynchronizationContext(uiContext);
app = new App();
});
}
return 0;
}
private static bool DecideRedirection()
{
var isRedirect = false;
var args = AppInstance.GetCurrent().GetActivatedEventArgs();
var keyInstance = AppInstance.FindOrRegisterForKey("randomKey");
if (keyInstance.IsCurrent)
{
// PowerToysTelemetry.Log.WriteEvent(new ColdLaunch());
keyInstance.Activated += OnActivated;
}
else
{
isRedirect = true;
// PowerToysTelemetry.Log.WriteEvent(new ReactivateInstance());
RedirectActivationTo(args, keyInstance);
}
return isRedirect;
}
private static void RedirectActivationTo(AppActivationArguments args, AppInstance keyInstance)
{
// Do the redirection on another thread, and use a non-blocking
// wait method to wait for the redirection to complete.
var redirectSemaphore = new Semaphore(0, 1);
Task.Run(() =>
{
keyInstance.RedirectActivationToAsync(args).AsTask().Wait();
redirectSemaphore.Release();
});
_ = PInvoke.CoWaitForMultipleObjects(
(uint)CWMO_FLAGS.CWMO_DEFAULT,
PInvoke.INFINITE,
[new HANDLE(redirectSemaphore.SafeWaitHandle.DangerousGetHandle())],
out _);
}
private static void OnActivated(object? sender, AppActivationArguments args)
{
// If we already have a form, display the message now.
// Otherwise, add it to the collection for displaying later.
if (App.Current is App thisApp)
{
if (thisApp.AppWindow is not null and
MainWindow mainWindow)
{
uiContext?.Post(_ => mainWindow.HandleLaunch(args), null);
}
}
}
}

View File

@@ -0,0 +1,431 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppName" xml:space="preserve">
<value>Command Palette</value>
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppNameDev" xml:space="preserve">
<value>Command Palette Dev</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="AppNameCan" xml:space="preserve">
<value>Command Palette Canary</value>
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppNamePre" xml:space="preserve">
<value>Command Palette Preview</value>
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppStoreName" xml:space="preserve">
<value>Windows Command Palette</value>
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppStoreNameDev" xml:space="preserve">
<value>Windows Command Palette Dev</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="AppStoreNameCan" xml:space="preserve">
<value>Windows Command Palette Canary</value>
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}. "Canary" in this context means an unstable or nightly build of a software product, not the bird.</comment>
</data>
<data name="AppStoreNamePre" xml:space="preserve">
<value>Windows Command Palette Preview</value>
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppShortName" xml:space="preserve">
<value>Command Palette</value>
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppShortNameDev" xml:space="preserve">
<value>Command Palette Dev</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="AppShortNameCan" xml:space="preserve">
<value>Command Palette Canary</value>
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppShortNamePre" xml:space="preserve">
<value>Command Palette Preview</value>
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppDescription" xml:space="preserve">
<value>The Windows Command Palette</value>
</data>
<data name="AppDescriptionDev" xml:space="preserve">
<value>A dev build of the Command Palette</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="AppDescriptionCan" xml:space="preserve">
<value>The Windows Command Palette (Canary build)</value>
<comment>{Locked}</comment>
</data>
<data name="AppDescriptionPre" xml:space="preserve">
<value>The Windows Command Palette (Preview build)</value>
</data>
<data name="StartupTaskName" xml:space="preserve">
<value>Command Palette</value>
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="StartupTaskNameDev" xml:space="preserve">
<value>Command Palette Dev</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="Activation_Shortcut_Cancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="Activation_Shortcut_Description" xml:space="preserve">
<value>Press a combination of keys to change this shortcut</value>
</data>
<data name="Activation_Shortcut_With_Disable_Description" xml:space="preserve">
<value>Press a combination of keys to change this shortcut.
Right-click to remove the key combination, thereby deactivating the shortcut.</value>
</data>
<data name="Activation_Shortcut_Reset" xml:space="preserve">
<value>Reset</value>
</data>
<data name="Activation_Shortcut_Save" xml:space="preserve">
<value>Save</value>
</data>
<data name="Activation_Shortcut_Title" xml:space="preserve">
<value>Activation shortcut</value>
</data>
<data name="InvalidShortcut.Title" xml:space="preserve">
<value>Invalid shortcut</value>
</data>
<data name="InvalidShortcutWarningLabel.Text" xml:space="preserve">
<value>Only shortcuts that start with **Windows key**, **Ctrl**, **Alt** or **Shift** are valid.</value>
<comment>The ** sequences are used for text formatting of the key names. Don't remove them on translation.</comment>
</data>
<data name="WarningShortcutAltGr.Title" xml:space="preserve">
<value>Possible shortcut interference with Alt Gr</value>
<comment>Alt Gr refers to the right alt key on some international keyboards</comment>
</data>
<data name="WarningShortcutAltGr.ToolTipService.ToolTip" xml:space="preserve">
<value>Shortcuts with **Ctrl** and **Alt** may remove functionality from some international keyboards, because **Ctrl** + **Alt** = **Alt Gr** in those keyboards.</value>
<comment>The ** sequences are used for text formatting of the key names. Don't remove them on translation.</comment>
</data>
<data name="CmdPalSettingsHeader.Text" xml:space="preserve">
<value>Command Palette settings</value>
<comment>A section header for app-wide settings. "Command Palette" is the name of the app.</comment>
</data>
<data name="AboutSettingsHeader.Text" xml:space="preserve">
<value>About</value>
<comment>A section header for information about the app</comment>
</data>
<data name="ExtensionAboutHeader.Text" xml:space="preserve">
<value>About</value>
<comment>A section header for information about the app</comment>
</data>
<data name="ExtensionSettingsHeader.Text" xml:space="preserve">
<value>Extension settings</value>
<comment>A section header for extension-specific settings.</comment>
</data>
<data name="ExtensionCommandsHeader.Text" xml:space="preserve">
<value>Commands</value>
<comment>A section header for information about the app</comment>
</data>
<data name="ExtensionFallbackCommandsHeader.Text" xml:space="preserve">
<value>Fallback commands</value>
<comment>A section header for information about the commands presented to the user when the search text doesn't exactly match the name of a command.</comment>
</data>
<data name="ExtensionDisabledHeader.Text" xml:space="preserve">
<value>This extension is disabled</value>
<comment>A header to inform the user that an extension is not currently active</comment>
</data>
<data name="ExtensionDisabledDetails.Text" xml:space="preserve">
<value>Enable this extension to view commands and settings</value>
<comment>Additional details for when an extension is disabled. Displayed under ExtensionDisabledHeader.Text</comment>
</data>
<data name="ExtensionDisabledText" xml:space="preserve">
<value>Disabled</value>
<comment>Displayed when an extension is disabled</comment>
</data>
<data name="ExtensionEnableCard.Header" xml:space="preserve">
<value>Enable this extension</value>
<comment>Displayed on a toggle controlling the extension's enabled / disabled state</comment>
</data>
<data name="ExtensionEnableCard.Description" xml:space="preserve">
<value>Load commands and settings from this extension</value>
<comment>Displayed on a toggle controlling the extension's enabled / disabled state</comment>
</data>
<data name="SettingsWindowTitle" xml:space="preserve">
<value>Command Palette Settings</value>
<comment>The title of the settings window for the app</comment>
</data>
<data name="ToastWindowTitle" xml:space="preserve">
<value>Command Palette Toast</value>
<comment>The title of the toast window for the command palette</comment>
</data>
<data name="DefaultSearchPlaceholderText" xml:space="preserve">
<value>Type here to search...</value>
</data>
<data name="Run_PositionHeader.Header" xml:space="preserve">
<value>Preferred monitor position</value>
<comment>as in Show Command Palette on primary monitor</comment>
</data>
<data name="Run_PositionHeader.Description" xml:space="preserve">
<value>If multiple monitors are in use, Command Palette can be launched on the desired monitor</value>
<comment>as in Show Command Palette on primary monitor</comment>
</data>
<data name="Run_Radio_Position_Cursor.Content" xml:space="preserve">
<value>Monitor with mouse cursor</value>
</data>
<data name="Run_Radio_Position_Focus.Content" xml:space="preserve">
<value>Monitor with focused window</value>
</data>
<data name="Run_Radio_Position_Primary_Monitor.Content" xml:space="preserve">
<value>Primary monitor</value>
</data>
<data name="Run_Radio_Position_In_Place.Content" xml:space="preserve">
<value>Don't move</value>
</data>
<data name="ConfirmationDialog_ConfirmButtonText" xml:space="preserve">
<value>Confirm</value>
</data>
<data name="ConfirmationDialog_CancelButtonText" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="Settings_ExtensionPage_GlobalHotkey_SettingsCard.Header" xml:space="preserve">
<value>Global hotkey</value>
</data>
<data name="Settings_ExtensionPage_GlobalHotkey_SettingsCard.Description" xml:space="preserve">
<value>Directly open Command Palette to this command.</value>
</data>
<data name="Settings_ExtensionPage_Alias_SettingsCard.Header" xml:space="preserve">
<value>Alias</value>
</data>
<data name="Settings_ExtensionPage_Alias_SettingsCard.Description" xml:space="preserve">
<value>Typing this alias will navigate to this command. Direct aliases navigate as soon as you type the alias. Indirect aliases navigate after typing a trailing space.</value>
</data>
<data name="Settings_ExtensionPage_Builtin_SettingsCard.Header" xml:space="preserve">
<value>Built-in</value>
</data>
<data name="Settings_ExtensionPage_Builtin_SettingsCard.Description" xml:space="preserve">
<value>These commands are built-in to the Windows Command Palette.</value>
</data>
<data name="Settings_GeneralPage_ActivationKey_SettingsExpander.Header" xml:space="preserve">
<value>Activation key</value>
</data>
<data name="Settings_GeneralPage_ActivationKey_SettingsExpander.Description" xml:space="preserve">
<value>This key will open the Command Palette.</value>
</data>
<data name="Settings_GeneralPage_LowLevelHook_SettingsCard.Header" xml:space="preserve">
<value>Use low-level keyboard hook</value>
</data>
<data name="Settings_GeneralPage_LowLevelHook_SettingsCard.Description" xml:space="preserve">
<value>Try this if there are issues with the shortcut (Command Palette might not get focus when triggered from an elevated window)</value>
</data>
<data name="Settings_GeneralPage_IgnoreShortcutWhenFullscreen_SettingsCard.Header" xml:space="preserve">
<value>Ignore shortcut in fullscreen mode</value>
</data>
<data name="Settings_GeneralPage_IgnoreShortcutWhenFullscreen_SettingsCard.Description" xml:space="preserve">
<value>Preventing disruption of the program running in fullscreen by unintentional activation of shortcut</value>
</data>
<data name="Settings_GeneralPage_GoHome_SettingsCard.Header" xml:space="preserve">
<value>Go home when activated</value>
</data>
<data name="Settings_GeneralPage_GoHome_SettingsCard.Description" xml:space="preserve">
<value>Automatically opens the home page upon activation</value>
</data>
<data name="Settings_GeneralPage_HighlightSearch_SettingsCard.Header" xml:space="preserve">
<value>Highlight search on activate</value>
</data>
<data name="Settings_GeneralPage_HighlightSearch_SettingsCard.Description" xml:space="preserve">
<value>Selects the previous search text at launch</value>
</data>
<data name="Settings_GeneralPage_ShowAppDetails_SettingsCard.Header" xml:space="preserve">
<value>Show app details</value>
</data>
<data name="Settings_GeneralPage_ShowAppDetails_SettingsCard.Description" xml:space="preserve">
<value>Controls if app details are automatically expanded or not.</value>
</data>
<data name="Settings_GeneralPage_BackspaceGoesBack_SettingsCard.Header" xml:space="preserve">
<value>Backspace goes back</value>
</data>
<data name="Settings_GeneralPage_BackspaceGoesBack_SettingsCard.Description" xml:space="preserve">
<value>If the search field is empty, backspace returns to the previous page</value>
</data>
<data name="Settings_GeneralPage_SingleClickActivation_SettingsCard.Header" xml:space="preserve">
<value>Single-click activation</value>
</data>
<data name="Settings_GeneralPage_SingleClickActivation_SettingsCard.Description" xml:space="preserve">
<value>Choose how to interact with list items: single-click to activate, or single-click to select and double-click to activate</value>
</data>
<data name="Settings_GeneralPage_About_SettingsExpander.Header" xml:space="preserve">
<value>Windows Command Palette</value>
</data>
<data name="Settings_GeneralPage_About_SettingsExpander.Description" xml:space="preserve">
<value>© 2025. All rights reserved.</value>
</data>
<data name="Settings_GeneralPage_About_GithubLink_Hyperlink.Content" xml:space="preserve">
<value>View GitHub repository</value>
</data>
<data name="Settings_GeneralPage_About_SDKDocs_Hyperlink.Content" xml:space="preserve">
<value>Extension SDK docs</value>
</data>
<data name="Settings_GeneralPage_SendFeedback_Hyperlink.Content" xml:space="preserve">
<value>Send feedback</value>
</data>
<data name="Settings_GeneralPage_NavigationViewItem_General.Content" xml:space="preserve">
<value>General</value>
</data>
<data name="Settings_GeneralPage_NavigationViewItem_Extensions.Content" xml:space="preserve">
<value>Extensions</value>
</data>
<data name="SettingsButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Open Command Palette settings</value>
</data>
<data name="ActivationSettingsHeader.Text" xml:space="preserve">
<value>Activation</value>
</data>
<data name="BehaviorSettingsHeader.Text" xml:space="preserve">
<value>Behavior</value>
</data>
<data name="ContextFilterBox.PlaceholderText" xml:space="preserve">
<value>Search commands...</value>
</data>
<data name="Settings_GeneralPage_ShowSystemTrayIcon_SettingsCard.Header" xml:space="preserve">
<value>Show system tray icon</value>
</data>
<data name="Settings_GeneralPage_ShowSystemTrayIcon_SettingsCard.Description" xml:space="preserve">
<value>Choose if Command Palette is visible in the system tray</value>
</data>
<data name="BackButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Back</value>
</data>
<data name="BackButton.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Back</value>
</data>
<data name="MoreCommandsButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>More</value>
</data>
<data name="TrayMenu_Settings" xml:space="preserve">
<value>Settings</value>
</data>
<data name="TrayMenu_Exit" xml:space="preserve">
<value>Exit</value>
</data>
<data name="Settings_ExtensionPage_Alias_ToggleSwitch.OnContent" xml:space="preserve">
<value>Direct</value>
</data>
<data name="Settings_ExtensionPage_Alias_ToggleSwitch.OffContent" xml:space="preserve">
<value>Indirect</value>
</data>
</root>

View File

@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SystemColorWindowColorBrush" />
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SystemColorHighlightTextColorBrush" />
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SystemColorWindowColorBrush" />
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SystemControlBackgroundBaseLowBrush" />
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SystemColorWindowColorBrush" />
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SystemColorHighlightColorBrush" />
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SystemColorHighlightColorBrush" />
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SystemColorGrayTextColor" />
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="SystemColorButtonTextColorBrush" />
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="SystemControlHighlightBaseHighBrush" />
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="SystemControlHighlightBaseHighBrush" />
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<Style x:Key="SubtleButtonStyle" TargetType="Button">
<Setter Property="Background" Value="{ThemeResource SubtleButtonBackground}" />
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
<Setter Property="Foreground" Value="{ThemeResource SubtleButtonForeground}" />
<Setter Property="BorderBrush" Value="{ThemeResource SubtleButtonBorderBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="-3" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter
x:Name="ContentPresenter"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AnimatedIcon.State="Normal"
AutomationProperties.AccessibilityView="Raw"
Background="{TemplateBinding Background}"
BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
CornerRadius="{TemplateBinding CornerRadius}"
Foreground="{TemplateBinding Foreground}">
<ContentPresenter.BackgroundTransition>
<BrushTransition Duration="0:0:0.083" />
</ContentPresenter.BackgroundTransition>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="PointerOver" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Pressed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<!-- DisabledVisual Should be handled by the control, not the animated icon. -->
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Normal" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<ResourceDictionary.ThemeDictionaries>
<!-- For slightly adjust the LayerOnAcrylicFillColorDefault color so that the cursor of the searchbox shows -->
<ResourceDictionary x:Key="Default">
<!-- This is a local copy of LayerOnAcrylicFillColorDefaultBrush -->
<SolidColorBrush
x:Key="LayerOnAcrylicPrimaryBackgroundBrush"
Opacity="0.3"
Color="#222222" />
<SolidColorBrush
x:Key="LayerOnAcrylicSecondaryBackgroundBrush"
Opacity="0.0"
Color="#222222" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<SolidColorBrush
x:Key="LayerOnAcrylicPrimaryBackgroundBrush"
Opacity="0.65"
Color="#FFFFFF" />
<!-- Because we are tweaking the LayerOnAcrylicPrimaryBackgroundBrush, we need to tweak the command bar background too. If not, it's too bright. -->
<SolidColorBrush
x:Key="LayerOnAcrylicSecondaryBackgroundBrush"
Opacity="0.4"
Color="#FFFFFF" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<!-- This is a local copy of LayerOnAcrylicFillColorDefaultBrush -->
<SolidColorBrush x:Key="LayerOnAcrylicPrimaryBackgroundBrush" Color="{ThemeResource LayerOnAcrylicFillColorDefault}" />
<SolidColorBrush x:Key="LayerOnAcrylicSecondaryBackgroundBrush" Color="Transparent" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<x:Double x:Key="SettingsCardSpacing">4</x:Double>
<!-- Style (inc. the correct spacing) of a section header -->
<Style
x:Key="SettingsSectionHeaderTextBlockStyle"
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
TargetType="TextBlock">
<Style.Setters>
<Setter Property="Margin" Value="1,30,0,6" />
</Style.Setters>
</Style>
<StackLayout
x:Name="VerticalStackLayout"
Orientation="Vertical"
Spacing="{StaticResource SettingsCardSpacing}" />
</ResourceDictionary>

View File

@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.CmdPal.Core.Control.Controls">
<!--
TODO! This file is a big dumb
-->
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<StaticResource x:Key="TagBackground" ResourceKey="ControlFillColorSecondaryBrush" />
<StaticResource x:Key="TagBorderBrush" ResourceKey="DividerStrokeColorDefaultBrush" />
<StaticResource x:Key="TagForeground" ResourceKey="TextFillColorTertiaryBrush" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<StaticResource x:Key="TagBackground" ResourceKey="ControlFillColorSecondaryBrush" />
<StaticResource x:Key="TagBorderBrush" ResourceKey="DividerStrokeColorDefaultBrush" />
<StaticResource x:Key="TagForeground" ResourceKey="TextFillColorTertiaryBrush" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<StaticResource x:Key="TagBackground" ResourceKey="SystemColorButtonFaceColorBrush" />
<StaticResource x:Key="TagBorderBrush" ResourceKey="ControlFillColorTransparent" />
<StaticResource x:Key="TagForeground" ResourceKey="SystemColorButtonTextColorBrush" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<Thickness x:Key="TagPadding">4,2,4,2</Thickness>
<Thickness x:Key="TagBorderThickness">1</Thickness>
<Style BasedOn="{StaticResource DefaultTagStyle}" TargetType="local:Tag" />
<Style x:Key="DefaultTagStyle" TargetType="local:Tag">
<Style.Setters>
<Setter Property="Background" Value="{ThemeResource TagBackground}" />
<Setter Property="BorderBrush" Value="{ThemeResource TagBorderBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource TagBorderThickness}" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="AutomationProperties.AutomationControlType" Value="Custom" />
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
<Setter Property="Padding" Value="{ThemeResource TagPadding}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="Foreground" Value="{ThemeResource TagForeground}" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="-3" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:Tag">
<Grid
x:Name="PART_RootGrid"
MinWidth="{TemplateBinding MinWidth}"
MinHeight="{TemplateBinding MinHeight}"
MaxWidth="{TemplateBinding MaxWidth}"
Padding="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
AutomationProperties.Name="{TemplateBinding Text}"
Background="{TemplateBinding Background}"
BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<local:IconBox
x:Name="PART_Icon"
Grid.Column="0"
Height="12"
Margin="0,0,4,0"
SourceKey="{TemplateBinding Icon}" />
<TextBlock
Grid.Column="1"
Margin="0,-1,0,0"
CharacterSpacing="{TemplateBinding CharacterSpacing}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}"
Text="{TemplateBinding Text}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:CommunityToolkit.WinUI.Converters">
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<Style
x:Key="ContextItemTitleTextBlockCriticalStyle"
BasedOn="{StaticResource BaseTextBlockStyle}"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemFillColorCriticalBrush}" />
<Setter Property="FontWeight" Value="Normal" />
</Style>
<Style
x:Key="ContextItemCaptionTextBlockCriticalStyle"
BasedOn="{StaticResource CaptionTextBlockStyle}"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemFillColorCriticalBrush}" />
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,279 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:CommunityToolkit.WinUI.Converters">
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<converters:StringVisibilityConverter
x:Key="ReverseStringVisibilityConverter"
EmptyValue="Visible"
NotEmptyValue="Collapsed" />
<Style x:Key="SearchTextBoxStyle" TargetType="TextBox">
<Setter Property="Foreground" Value="{ThemeResource TextControlForeground}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextControlSelectionHighlightColor}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}" />
<Setter Property="UseSystemFocusVisuals" Value="{ThemeResource IsApplicationFocusVisualKindReveal}" />
<Setter Property="ContextFlyout" Value="{StaticResource TextControlCommandBarContextFlyout}" />
<Setter Property="SelectionFlyout" Value="{StaticResource TextControlCommandBarSelectionFlyout}" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Grid.Resources>
<Style x:Name="DeleteButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid
x:Name="ButtonLayoutGrid"
Margin="{ThemeResource TextBoxInnerButtonMargin}"
Background="{ThemeResource TextControlButtonBackground}"
BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{ThemeResource TextControlButtonBorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<TextBlock
x:Name="GlyphElement"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="{ThemeResource TextBoxIconFontSize}"
FontStyle="Normal"
Foreground="{ThemeResource TextControlButtonForeground}"
Text="&#xE894;" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="ButtonLayoutGrid"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter
x:Name="HeaderContentPresenter"
Margin="{ThemeResource TextBoxTopHeaderMargin}"
VerticalAlignment="Center"
x:DeferLoadStrategy="Lazy"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
FontWeight="Normal"
Foreground="{ThemeResource TextControlHeaderForeground}"
TextWrapping="Wrap"
Visibility="Collapsed" />
<Border
x:Name="BorderElement"
Grid.Column="1"
Grid.ColumnSpan="2"
MinWidth="{TemplateBinding MinWidth}"
MinHeight="{TemplateBinding MinHeight}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Control.IsTemplateFocusTarget="True"
CornerRadius="{TemplateBinding CornerRadius}" />
<ScrollViewer
x:Name="ContentElement"
Grid.Column="1"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
AutomationProperties.AccessibilityView="Raw"
Foreground="{TemplateBinding Foreground}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsTabStop="False"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
ZoomMode="Disabled" />
<TextBlock
x:Name="PlaceholderTextContentPresenter"
Grid.Column="1"
Grid.ColumnSpan="1"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
Foreground="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForeground}}"
IsHitTestVisible="False"
Text="{TemplateBinding PlaceholderText}"
TextAlignment="{TemplateBinding TextAlignment}"
TextWrapping="{TemplateBinding TextWrapping}"
Visibility="{Binding Description, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ReverseStringVisibilityConverter}, Mode=OneWay}" />
<Button
x:Name="DeleteButton"
Grid.Column="2"
Margin="0,0,8,0"
Padding="4"
HorizontalAlignment="Right"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"
FontSize="{TemplateBinding FontSize}"
IsTabStop="False"
Style="{StaticResource DeleteButtonStyle}"
Visibility="Collapsed" />
<TextBlock
x:Name="DescriptionPresenter"
Grid.Column="1"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
x:Load="False"
AutomationProperties.AccessibilityView="Raw"
CharacterSpacing="15"
Foreground="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForeground}}"
Text="{TemplateBinding Description}"
TextWrapping="{TemplateBinding TextWrapping}" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<Storyboard>
<!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlHeaderForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>-->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DescriptionPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundDisabled}}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>-->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundPointerOver}}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DescriptionPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundPointerOver}}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundFocused}}" />
</ObjectAnimationUsingKeyFrames>
<!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderThemeThicknessFocused}" />
</ObjectAnimationUsingKeyFrames>-->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DescriptionPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundFocused}}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates">
<VisualState x:Name="ButtonVisible">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DeleteButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ButtonCollapsed" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="WindowsCommandPalette.app"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- The ID below informs the system that this application is compatible with OS features first introduced in Windows 10.
It is necessary to support features in unpackaged applications, for example the custom titlebar implementation.
For more info see https://docs.microsoft.com/windows/apps/windows-app-sdk/use-windows-app-sdk-run-time#declare-os-compatibility-in-your-application-manifest -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
</assembly>

View File

@@ -4,7 +4,6 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using ManagedCommon;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Foundation;
@@ -60,7 +59,7 @@ public abstract partial class AppExtensionHost : IExtensionHost
return Task.CompletedTask.AsAsyncAction();
}
Logger.LogDebug(message.Message);
CoreLogger.LogDebug(message.Message);
_ = Task.Run(() =>
{

View File

@@ -8,7 +8,6 @@ using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Diagnostics.Utilities;
using Windows.System;
namespace Microsoft.CmdPal.Core.ViewModels;

View File

@@ -0,0 +1,60 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.ViewModels;
public static class CoreLogger
{
public static void InitializeLogger(ILogger implementation)
{
_logger = implementation;
}
private static ILogger? _logger;
public static void LogError(string message, Exception ex, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogError(message, ex, memberName, sourceFilePath, sourceLineNumber);
}
public static void LogError(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogError(message, memberName, sourceFilePath, sourceLineNumber);
}
public static void LogWarning(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogWarning(message, memberName, sourceFilePath, sourceLineNumber);
}
public static void LogInfo(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogInfo(message, memberName, sourceFilePath, sourceLineNumber);
}
public static void LogDebug(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogDebug(message, memberName, sourceFilePath, sourceLineNumber);
}
public static void LogTrace([System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogTrace(memberName, sourceFilePath, sourceLineNumber);
}
}
public interface ILogger
{
void LogError(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
void LogError(string message, Exception ex, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
void LogWarning(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
void LogInfo(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
void LogDebug(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
void LogTrace([System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
}

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using CommunityToolkit.Mvvm.ComponentModel;
using ManagedCommon;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -84,7 +83,7 @@ public abstract partial class ExtensionObjectViewModel : ObservableObject
}
catch (Exception ex)
{
Logger.LogDebug(ex.ToString());
CoreLogger.LogDebug(ex.ToString());
}
}
}

View File

@@ -570,4 +570,4 @@ public partial class ListViewModel : PageViewModel, IDisposable
model.ItemsChanged -= Model_ItemsChanged;
}
}
}
}

View File

@@ -19,6 +19,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWinRT" />
<PackageReference Include="CommunityToolkit.Common" />
<PackageReference Include="CommunityToolkit.Mvvm" />
@@ -26,15 +28,11 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="WyHash" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.CmdPal.Common\Microsoft.CmdPal.Common.csproj" />
<ProjectReference Include="..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
</ItemGroup>
<ItemGroup>
@@ -45,16 +43,4 @@
</Compile>
</ItemGroup>
<!-- Just mark it as AOT compatible. Do not publish with AOT now. We need fully test before we really publish it as AOT enabled-->
<!--<PropertyGroup>
<SelfContained>true</SelfContained>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<PublishTrimmed>true</PublishTrimmed>
<PublishSingleFile>true</PublishSingleFile>
--><!-- <DisableRuntimeMarshalling>true</DisableRuntimeMarshalling> --><!--
<PublishAot>true</PublishAot>
<EnableMsixTooling>true</EnableMsixTooling>
</PropertyGroup>-->
</Project>

View File

@@ -5,7 +5,6 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using ManagedCommon;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
@@ -49,7 +48,7 @@ public partial class ShellViewModel : ObservableObject,
}
catch (Exception ex)
{
Logger.LogError(ex.ToString());
CoreLogger.LogError(ex.ToString());
}
}
}
@@ -139,7 +138,7 @@ public partial class ShellViewModel : ObservableObject,
// TODO: Handle failure case
if (viewModel.InitializeCommand.ExecutionTask.Exception is AggregateException ex)
{
Logger.LogError(ex.ToString());
CoreLogger.LogError(ex.ToString());
}
// TODO GH #239 switch back when using the new MD text block
@@ -196,7 +195,7 @@ public partial class ShellViewModel : ObservableObject,
{
if (command is IPage page)
{
Logger.LogDebug($"Navigating to page");
CoreLogger.LogDebug($"Navigating to page");
var isMainPage = command == _rootPage;
_isNested = !isMainPage;
@@ -205,7 +204,7 @@ public partial class ShellViewModel : ObservableObject,
var pageViewModel = _pageViewModelFactory.TryCreatePageViewModel(page, _isNested, host);
if (pageViewModel == null)
{
Logger.LogError($"Failed to create ViewModel for page {page.GetType().Name}");
CoreLogger.LogError($"Failed to create ViewModel for page {page.GetType().Name}");
throw new NotSupportedException();
}
@@ -219,7 +218,7 @@ public partial class ShellViewModel : ObservableObject,
}
else if (command is IInvokableCommand invokable)
{
Logger.LogDebug($"Invoking command");
CoreLogger.LogDebug($"Invoking command");
WeakReferenceMessenger.Default.Send<BeginInvokeMessage>();
StartInvoke(message, invokable, host);
@@ -285,7 +284,7 @@ public partial class ShellViewModel : ObservableObject,
}
var kind = result.Kind;
Logger.LogDebug($"handling {kind.ToString()}");
CoreLogger.LogDebug($"handling {kind.ToString()}");
WeakReferenceMessenger.Default.Send<CmdPalInvokeResultMessage>(new(kind));
switch (kind)

View File

@@ -44,7 +44,7 @@ public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings,
}
catch (Exception ex)
{
Logger.LogError($"Failed to load settings page", ex: ex);
CoreLogger.LogError($"Failed to load settings page", ex: ex);
}
Initialized = true;

View File

@@ -71,6 +71,11 @@ public partial class App : Application
AppWindow?.Close();
Environment.Exit(0);
});
// Connect the PT logging to the core project's logging.
// This way, log statements from the core project will be captured by the PT logs
var logWrapper = new LogWrapper();
CoreLogger.InitializeLogger(logWrapper);
}
/// <summary>

View File

@@ -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 System.Runtime.InteropServices;
using System.Security;
namespace Microsoft.CmdPal.UI.Helpers;
[SuppressUnmanagedCodeSecurity]
internal static class NativeMethods
{
[DllImport("shell32.dll")]
public static extern int SHQueryUserNotificationState(out UserNotificationState state);
}
internal enum UserNotificationState : int
{
QUNS_NOT_PRESENT = 1,
QUNS_BUSY,
QUNS_RUNNING_D3D_FULL_SCREEN,
QUNS_PRESENTATION_MODE,
QUNS_ACCEPTS_NOTIFICATIONS,
QUNS_QUIET_TIME,
QUNS_APP,
}

View File

@@ -0,0 +1,41 @@
// 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.Core.ViewModels;
namespace Microsoft.CmdPal.UI;
internal sealed class LogWrapper : ILogger
{
public void LogError(string message, Exception ex, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
Logger.LogError(message, ex, memberName, sourceFilePath, sourceLineNumber);
}
public void LogError(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
Logger.LogError(message, memberName, sourceFilePath, sourceLineNumber);
}
public void LogWarning(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
Logger.LogWarning(message, memberName, sourceFilePath, sourceLineNumber);
}
public void LogInfo(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
Logger.LogInfo(message, memberName, sourceFilePath, sourceLineNumber);
}
public void LogDebug(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
Logger.LogDebug(message, memberName, sourceFilePath, sourceLineNumber);
}
public void LogTrace([System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
Logger.LogTrace(memberName, sourceFilePath, sourceLineNumber);
}
}

View File

@@ -117,7 +117,7 @@ internal sealed class PowerToysRootPageService : IRootPageService
}
catch (Exception ex)
{
Logger.LogError(ex.ToString());
ManagedCommon.Logger.LogError(ex.ToString());
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Some files were not shown because too many files have changed in this diff Show More