Compare commits
33 Commits
update-tel
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5442f88f1 | ||
|
|
2522cdcc47 | ||
|
|
f3a58d3058 | ||
|
|
af9b955993 | ||
|
|
8c16c63a68 | ||
|
|
31f362ab66 | ||
|
|
bd9cc00c79 | ||
|
|
630e7e0ac8 | ||
|
|
1a2406671d | ||
|
|
b59f2875f4 | ||
|
|
129c10a0a2 | ||
|
|
8d342b4b32 | ||
|
|
89ac05a8cd | ||
|
|
a10a79ecc8 | ||
|
|
d7eb61d57e | ||
|
|
555c488de5 | ||
|
|
e214cda85c | ||
|
|
ae6172dc16 | ||
|
|
b290b9b1a2 | ||
|
|
42262ee9d6 | ||
|
|
c3c77f2c75 | ||
|
|
a8d0fbf44e | ||
|
|
402e379c6f | ||
|
|
8cd6622d14 | ||
|
|
ddff05ec54 | ||
|
|
ef6412d116 | ||
|
|
0654830420 | ||
|
|
91d085fbca | ||
|
|
c1d755aea6 | ||
|
|
be5ebf9322 | ||
|
|
f2c57ee33e | ||
|
|
1e198d4acf | ||
|
|
f809bd139c |
@@ -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}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>,
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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">
|
||||
|
||||
@@ -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>,
|
||||
@@ -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)
|
||||
@@ -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">
|
||||
@@ -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>,
|
||||
@@ -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.
|
||||
@@ -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">
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
{
|
||||
@@ -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
|
||||
{
|
||||
@@ -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)
|
||||
@@ -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
|
||||
{
|
||||
@@ -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);
|
||||
@@ -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">
|
||||
|
||||
@@ -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 &&
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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
|
||||
{
|
||||
@@ -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
|
||||
{
|
||||
@@ -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.
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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=,
|
||||
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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Views;
|
||||
namespace Microsoft.CmdPal.Core.Control.Views;
|
||||
|
||||
public interface ICurrentPageAware
|
||||
{
|
||||
7
src/modules/cmdpal/Microsoft.CmdPal.Core.Control/rd.xml
Normal 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>
|
||||
26
src/modules/cmdpal/Microsoft.CmdPal.Core.UI/App.xaml
Normal 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>
|
||||
160
src/modules/cmdpal/Microsoft.CmdPal.Core.UI/App.xaml.cs
Normal 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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/modules/cmdpal/Microsoft.CmdPal.Core.UI/MainWindow.xaml
Normal 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>
|
||||
668
src/modules/cmdpal/Microsoft.CmdPal.Core.UI/MainWindow.xaml.cs
Normal 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);
|
||||
// }
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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>
|
||||
134
src/modules/cmdpal/Microsoft.CmdPal.Core.UI/Program.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
158
src/modules/cmdpal/Microsoft.CmdPal.Core.UI/Styles/Button.xaml
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
94
src/modules/cmdpal/Microsoft.CmdPal.Core.UI/Styles/Tag.xaml
Normal 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>
|
||||
@@ -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>
|
||||
279
src/modules/cmdpal/Microsoft.CmdPal.Core.UI/Styles/TextBox.xaml
Normal 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="" />
|
||||
<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>
|
||||
20
src/modules/cmdpal/Microsoft.CmdPal.Core.UI/app.manifest
Normal 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>
|
||||
@@ -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(() =>
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,4 +570,4 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
||||
model.ItemsChanged -= Model_ItemsChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
41
src/modules/cmdpal/Microsoft.CmdPal.UI/LogWrapper.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ internal sealed class PowerToysRootPageService : IRootPageService
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex.ToString());
|
||||
ManagedCommon.Logger.LogError(ex.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 165 KiB |
|
Before Width: | Height: | Size: 432 B |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 181 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 648 B |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 648 B |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |