mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +01:00
Continuing part deux
This commit is contained in:
@@ -356,6 +356,29 @@
|
|||||||
<Project Path="src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj" Id="f5e1146e-b7b3-4e11-85fd-270a500bd78c" />
|
<Project Path="src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj" Id="f5e1146e-b7b3-4e11-85fd-270a500bd78c" />
|
||||||
<Project Path="src/modules/CropAndLock/CropAndLockModuleInterface/CropAndLockModuleInterface.vcxproj" Id="3157fa75-86cf-4ee2-8f62-c43f776493c6" />
|
<Project Path="src/modules/CropAndLock/CropAndLockModuleInterface/CropAndLockModuleInterface.vcxproj" Id="3157fa75-86cf-4ee2-8f62-c43f776493c6" />
|
||||||
</Folder>
|
</Folder>
|
||||||
|
<Folder Name="/modules/Deux/" />
|
||||||
|
<Folder Name="/modules/Deux/SDK/">
|
||||||
|
<Project Path="src/modules/Deux/SDK/Microsoft.CommandPalette.Extensions.Toolkit/Microsoft.CommandPalette.Extensions.Toolkit.csproj">
|
||||||
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||||
|
<Platform Solution="*|x64" Project="x64" />
|
||||||
|
</Project>
|
||||||
|
<Project Path="src/modules/Deux/SDK/Microsoft.CommandPalette.Extensions/Microsoft.CommandPalette.Extensions.vcxproj" Id="7997dad4-31d6-496b-95db-6c028d699370" />
|
||||||
|
</Folder>
|
||||||
|
<Folder Name="/modules/Deux/UI/">
|
||||||
|
<Project Path="src/modules/Deux/UI/Microsoft.CommandPalette.UI.Models/Microsoft.CommandPalette.UI.Models.csproj">
|
||||||
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||||
|
<Platform Solution="*|x64" Project="x64" />
|
||||||
|
</Project>
|
||||||
|
<Project Path="src/modules/Deux/UI/Microsoft.CommandPalette.UI.ViewModels/Microsoft.CommandPalette.UI.ViewModels.csproj">
|
||||||
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||||
|
<Platform Solution="*|x64" Project="x64" />
|
||||||
|
</Project>
|
||||||
|
<Project Path="src/modules/Deux/UI/Microsoft.CommandPalette.UI/Microsoft.CommandPalette.UI.csproj">
|
||||||
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||||
|
<Platform Solution="*|x64" Project="x64" />
|
||||||
|
<Deploy />
|
||||||
|
</Project>
|
||||||
|
</Folder>
|
||||||
<Folder Name="/modules/EnvironmentVariables/">
|
<Folder Name="/modules/EnvironmentVariables/">
|
||||||
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariables.csproj">
|
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariables.csproj">
|
||||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// 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.CommandPalette.UI.Models.Messages;
|
||||||
|
|
||||||
|
public record DismissMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// 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.CommandPalette.UI.Models.Messages;
|
||||||
|
|
||||||
|
public record GoBackMessage(bool WithAnimation = true, bool FocusSearch = true)
|
||||||
|
{
|
||||||
|
// TODO! sticking these properties here feels like leaking the UI into the models
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// 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.CommandPalette.UI.Models.Messages;
|
||||||
|
|
||||||
|
// TODO! sticking these properties here feels like leaking the UI into the models
|
||||||
|
public record GoHomeMessage(bool WithAnimation = true, bool FocusSearch = true)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// 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.CommandPalette.UI.Models.Messages;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Message to request hiding the window.
|
||||||
|
/// </summary>
|
||||||
|
public partial record HideWindowMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
namespace Microsoft.CmdPal.UI.Models.Messages;
|
namespace Microsoft.CommandPalette.UI.Models.Messages;
|
||||||
|
|
||||||
public record HotkeySummonMessage(string CommandId, IntPtr Hwnd)
|
public record HotkeySummonMessage(string CommandId, IntPtr Hwnd)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
namespace Microsoft.CmdPal.UI.Models.Messages;
|
namespace Microsoft.CommandPalette.UI.Models.Messages;
|
||||||
|
|
||||||
public record OpenSettingsMessage()
|
public record OpenSettingsMessage()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
namespace Microsoft.CmdPal.UI.Models.Messages;
|
namespace Microsoft.CommandPalette.UI.Models.Messages;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Message which closes the application. Used by <see cref="QuitCommand"/> via <see cref="BuiltInsCommandProvider"/>.
|
/// Message which closes the application. Used by <see cref="QuitCommand"/> via <see cref="BuiltInsCommandProvider"/>.
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// 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.CommandPalette.UI.Models.Messages;
|
||||||
|
|
||||||
|
public record ReloadCommandsMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// 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.CommandPalette.UI.Models.Messages;
|
||||||
|
|
||||||
|
public record ShowWindowMessage(IntPtr Hwnd)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -25,6 +25,11 @@
|
|||||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" />
|
<PackageReference Include="Microsoft.Extensions.Logging" />
|
||||||
|
<PackageReference Include="Microsoft.Windows.CsWin32">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
@@ -39,6 +44,7 @@
|
|||||||
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||||
<ProjectReference Include="..\..\SDK\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
|
<ProjectReference Include="..\..\SDK\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Events\" />
|
<Folder Include="Events\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,190 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using ManagedCommon;
|
||||||
|
using Microsoft.CommandPalette.UI.ViewModels.Helpers;
|
||||||
|
using Microsoft.UI;
|
||||||
|
using Windows.System;
|
||||||
|
using Windows.UI;
|
||||||
|
using DispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue;
|
||||||
|
|
||||||
|
namespace Microsoft.CommandPalette.UI.ViewModels;
|
||||||
|
|
||||||
|
public sealed partial class DevRibbonViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private const int MaxLogEntries = 2;
|
||||||
|
private const string Release = "Release";
|
||||||
|
private const string Debug = "Debug";
|
||||||
|
|
||||||
|
private static readonly Color ReleaseAotColor = ColorHelper.FromArgb(255, 124, 58, 237);
|
||||||
|
private static readonly Color ReleaseColor = ColorHelper.FromArgb(255, 51, 65, 85);
|
||||||
|
private static readonly Color DebugAotColor = ColorHelper.FromArgb(255, 99, 102, 241);
|
||||||
|
private static readonly Color DebugColor = ColorHelper.FromArgb(255, 107, 114, 128);
|
||||||
|
|
||||||
|
private readonly DispatcherQueue _dispatcherQueue;
|
||||||
|
|
||||||
|
public DevRibbonViewModel()
|
||||||
|
{
|
||||||
|
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||||
|
Trace.Listeners.Add(new DevRibbonTraceListener(this));
|
||||||
|
|
||||||
|
var configLabel = BuildConfiguration == Release ? "RLS" : "DBG"; /* #no-spell-check-line */
|
||||||
|
var aotLabel = BuildInfo.IsNativeAot ? "⚡AOT" : "NO AOT";
|
||||||
|
Tag = $"{configLabel} | {aotLabel}";
|
||||||
|
|
||||||
|
TagColor = (BuildConfiguration, BuildInfo.IsNativeAot) switch
|
||||||
|
{
|
||||||
|
(Release, true) => ReleaseAotColor,
|
||||||
|
(Release, false) => ReleaseColor,
|
||||||
|
(Debug, true) => DebugAotColor,
|
||||||
|
(Debug, false) => DebugColor,
|
||||||
|
_ => Colors.Fuchsia,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BuildConfiguration => BuildInfo.Configuration;
|
||||||
|
|
||||||
|
public bool IsAotReleaseConfiguration => BuildConfiguration == Release && BuildInfo.IsNativeAot;
|
||||||
|
|
||||||
|
public bool IsAot => BuildInfo.IsNativeAot;
|
||||||
|
|
||||||
|
public bool IsPublishTrimmed => BuildInfo.PublishTrimmed;
|
||||||
|
|
||||||
|
public ObservableCollection<LogEntryViewModel> LatestLogs { get; } = [];
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial int WarningCount { get; private set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial int ErrorCount { get; private set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string Tag { get; private set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial Color TagColor { get; private set; }
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task OpenLogFileAsync()
|
||||||
|
{
|
||||||
|
var logPath = Logger.CurrentLogFile;
|
||||||
|
if (File.Exists(logPath))
|
||||||
|
{
|
||||||
|
await Launcher.LaunchUriAsync(new Uri(logPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task OpenLogFolderAsync()
|
||||||
|
{
|
||||||
|
var logFolderPath = Logger.CurrentVersionLogDirectoryPath;
|
||||||
|
if (Directory.Exists(logFolderPath))
|
||||||
|
{
|
||||||
|
await Launcher.LaunchFolderPathAsync(logFolderPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void ResetErrorCounters()
|
||||||
|
{
|
||||||
|
WarningCount = 0;
|
||||||
|
ErrorCount = 0;
|
||||||
|
LatestLogs.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed partial class DevRibbonTraceListener(DevRibbonViewModel viewModel) : TraceListener
|
||||||
|
{
|
||||||
|
private const string TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff";
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^\[(?<timestamp>.*?)\] \[(?<severity>.*?)\] (?<message>.*)")]
|
||||||
|
private static partial Regex LogRegex();
|
||||||
|
|
||||||
|
private readonly Lock _lock = new();
|
||||||
|
private LogEntryViewModel? _latestLogEntry;
|
||||||
|
|
||||||
|
public override void Write(string? message)
|
||||||
|
{
|
||||||
|
// Not required for this scenario.
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteLine(string? message)
|
||||||
|
{
|
||||||
|
if (message is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
var match = LogRegex().Match(message);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
var severity = match.Groups["severity"].Value;
|
||||||
|
var isWarning = severity.Equals("Warning", StringComparison.OrdinalIgnoreCase);
|
||||||
|
var isError = severity.Equals("Error", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
if (isWarning || isError)
|
||||||
|
{
|
||||||
|
var timestampStr = match.Groups["timestamp"].Value;
|
||||||
|
var timestamp = DateTimeOffset.TryParseExact(
|
||||||
|
timestampStr,
|
||||||
|
TimestampFormat,
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
DateTimeStyles.AssumeLocal,
|
||||||
|
out var parsed)
|
||||||
|
? parsed
|
||||||
|
: DateTimeOffset.Now;
|
||||||
|
|
||||||
|
var logEntry = new LogEntryViewModel(
|
||||||
|
timestamp,
|
||||||
|
severity,
|
||||||
|
match.Groups["message"].Value,
|
||||||
|
string.Empty);
|
||||||
|
|
||||||
|
_latestLogEntry = logEntry;
|
||||||
|
|
||||||
|
viewModel._dispatcherQueue.TryEnqueue(() =>
|
||||||
|
{
|
||||||
|
if (isWarning)
|
||||||
|
{
|
||||||
|
viewModel.WarningCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
viewModel.ErrorCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.LatestLogs.Insert(0, logEntry);
|
||||||
|
|
||||||
|
while (viewModel.LatestLogs.Count > MaxLogEntries)
|
||||||
|
{
|
||||||
|
viewModel.LatestLogs.RemoveAt(viewModel.LatestLogs.Count - 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_latestLogEntry = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IndentLevel > 0 && _latestLogEntry is { } latest)
|
||||||
|
{
|
||||||
|
viewModel._dispatcherQueue.TryEnqueue(() =>
|
||||||
|
{
|
||||||
|
latest.AppendDetails(message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// 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.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Microsoft.CommandPalette.UI.ViewModels.Helpers;
|
||||||
|
|
||||||
|
public static class BuildInfo
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
public const string Configuration = "Debug";
|
||||||
|
#else
|
||||||
|
public const string Configuration = "Release";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Runtime AOT detection
|
||||||
|
public static bool IsNativeAot => !RuntimeFeature.IsDynamicCodeSupported;
|
||||||
|
|
||||||
|
// From assembly metadata (build-time values)
|
||||||
|
public static bool PublishTrimmed => GetBoolMetadata("PublishTrimmed", false);
|
||||||
|
|
||||||
|
// From assembly metadata (build-time values)
|
||||||
|
public static bool PublishAot => GetBoolMetadata("PublishAot", false);
|
||||||
|
|
||||||
|
public static bool IsCiBuild => GetBoolMetadata("CIBuild", false);
|
||||||
|
|
||||||
|
private static string? GetMetadata(string key) =>
|
||||||
|
Assembly.GetExecutingAssembly()
|
||||||
|
.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||||
|
.FirstOrDefault(a => a.Key == key)?.Value;
|
||||||
|
|
||||||
|
private static bool GetBoolMetadata(string key, bool defaultValue) =>
|
||||||
|
bool.TryParse(GetMetadata(key), out var result) ? result : defaultValue;
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
// 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.Globalization;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
namespace Microsoft.CommandPalette.UI.ViewModels;
|
||||||
|
|
||||||
|
public sealed partial class LogEntryViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private const int HeaderMaxLength = 80;
|
||||||
|
private const string WarningGlyph = "\uE7BA";
|
||||||
|
private const string ErrorGlyph = "\uEA39";
|
||||||
|
private const string TimestampFormat = "HH:mm:ss";
|
||||||
|
|
||||||
|
private DateTimeOffset Timestamp { get; }
|
||||||
|
|
||||||
|
private string Severity { get; }
|
||||||
|
|
||||||
|
private string Message { get; }
|
||||||
|
|
||||||
|
private string FormattedTimestamp { get; }
|
||||||
|
|
||||||
|
public string SeverityGlyph { get; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string Header { get; private set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string Description { get; private set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string Details { get; private set; }
|
||||||
|
|
||||||
|
public LogEntryViewModel(DateTimeOffset timestamp, string severity, string message, string details)
|
||||||
|
{
|
||||||
|
Timestamp = timestamp;
|
||||||
|
Severity = severity;
|
||||||
|
Message = message;
|
||||||
|
Details = details;
|
||||||
|
|
||||||
|
SeverityGlyph = severity.ToUpperInvariant() switch
|
||||||
|
{
|
||||||
|
"WARNING" => WarningGlyph,
|
||||||
|
"ERROR" => ErrorGlyph,
|
||||||
|
_ => string.Empty,
|
||||||
|
};
|
||||||
|
|
||||||
|
FormattedTimestamp = timestamp.ToString(TimestampFormat, CultureInfo.CurrentCulture);
|
||||||
|
Description = $"{FormattedTimestamp} • {Message}";
|
||||||
|
Header = Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AppendDetails(string? message)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(message))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Details += Environment.NewLine + message;
|
||||||
|
|
||||||
|
// Make header the second line of details (because that's actually the message itself):
|
||||||
|
var detailsLines = Details.Split([Environment.NewLine], StringSplitOptions.None);
|
||||||
|
if (detailsLines.Length < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Header = detailsLines[1].Trim();
|
||||||
|
if (Header.Length > HeaderMaxLength)
|
||||||
|
{
|
||||||
|
Header = Header[..(HeaderMaxLength - 1)] + "…";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<UserControl
|
||||||
|
x:Class="Microsoft.CommandPalette.UI.Controls.DevRibbon"
|
||||||
|
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:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:viewModels="using:Microsoft.CommandPalette.UI.ViewModels"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<UserControl.Resources>
|
||||||
|
<DataTemplate x:Key="LogEntryTemplate" x:DataType="viewModels:LogEntryViewModel">
|
||||||
|
<controls:SettingsExpander Description="{x:Bind Description}" Header="{x:Bind Header}">
|
||||||
|
<controls:SettingsExpander.HeaderIcon>
|
||||||
|
<FontIcon Glyph="{x:Bind SeverityGlyph}" />
|
||||||
|
</controls:SettingsExpander.HeaderIcon>
|
||||||
|
<controls:SettingsExpander.Items>
|
||||||
|
<controls:SettingsCard HorizontalContentAlignment="Stretch" ContentAlignment="Vertical">
|
||||||
|
<ScrollViewer
|
||||||
|
MaxWidth="1160"
|
||||||
|
HorizontalScrollMode="Auto"
|
||||||
|
VerticalScrollMode="Auto">
|
||||||
|
<TextBlock
|
||||||
|
FontFamily="Consolas"
|
||||||
|
FontSize="11"
|
||||||
|
Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}"
|
||||||
|
IsTextSelectionEnabled="True"
|
||||||
|
Text="{x:Bind Details}"
|
||||||
|
TextWrapping="NoWrap" />
|
||||||
|
</ScrollViewer>
|
||||||
|
</controls:SettingsCard>
|
||||||
|
</controls:SettingsExpander.Items>
|
||||||
|
</controls:SettingsExpander>
|
||||||
|
</DataTemplate>
|
||||||
|
|
||||||
|
<converters:BoolToVisibilityConverter
|
||||||
|
x:Key="InvertedBoolToVisibilityConverter"
|
||||||
|
FalseValue="Visible"
|
||||||
|
TrueValue="Collapsed" />
|
||||||
|
|
||||||
|
</UserControl.Resources>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Border
|
||||||
|
x:Name="RootBorder"
|
||||||
|
Height="26"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Background="{ThemeResource SettingsCardBackground}"
|
||||||
|
BorderBrush="{ThemeResource SurfaceStrokeColorFlyoutBrush}"
|
||||||
|
BorderThickness="1,0,1,1"
|
||||||
|
CornerRadius="0,0,8,8"
|
||||||
|
Opacity="0.3">
|
||||||
|
<Button
|
||||||
|
Padding="0"
|
||||||
|
CornerRadius="0,0,8,8"
|
||||||
|
FontSize="11"
|
||||||
|
PointerEntered="DevRibbonButton_PointerEntered"
|
||||||
|
PointerExited="DevRibbonButton_PointerExited">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<StackPanel
|
||||||
|
Padding="8,4"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Background="DarkOrange"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
Visibility="{x:Bind VisibleIfGreaterThanZero(ViewModel.WarningCount), Mode=OneWay}">
|
||||||
|
<FontIcon
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||||
|
FontSize="12"
|
||||||
|
Glyph="" />
|
||||||
|
<TextBlock VerticalAlignment="Center">
|
||||||
|
<Run Text="{x:Bind ViewModel.WarningCount, Mode=OneWay}" />
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel
|
||||||
|
Padding="8,4"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Background="Maroon"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
Visibility="{x:Bind VisibleIfGreaterThanZero(ViewModel.ErrorCount), Mode=OneWay}">
|
||||||
|
<FontIcon
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||||
|
FontSize="12"
|
||||||
|
Glyph="" />
|
||||||
|
<TextBlock VerticalAlignment="Center">
|
||||||
|
<Run Text="{x:Bind ViewModel.ErrorCount, Mode=OneWay}" />
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
<Border Padding="8,4">
|
||||||
|
<Border.Background>
|
||||||
|
<SolidColorBrush Color="{x:Bind ViewModel.TagColor}" />
|
||||||
|
</Border.Background>
|
||||||
|
<TextBlock Padding="4" VerticalAlignment="Center">
|
||||||
|
<Run Text="{x:Bind ViewModel.Tag}" />
|
||||||
|
</TextBlock>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<Button.Flyout>
|
||||||
|
<Flyout
|
||||||
|
Placement="Bottom"
|
||||||
|
ShouldConstrainToRootBounds="False"
|
||||||
|
SystemBackdrop="{ThemeResource AcrylicBackgroundFillColorDefaultBackdrop}">
|
||||||
|
<Flyout.FlyoutPresenterStyle>
|
||||||
|
<Style BasedOn="{StaticResource DefaultFlyoutPresenterStyle}" TargetType="FlyoutPresenter">
|
||||||
|
<Setter Property="MinWidth" Value="600" />
|
||||||
|
<Setter Property="MaxWidth" Value="1200" />
|
||||||
|
<Setter Property="Padding" Value="0" />
|
||||||
|
</Style>
|
||||||
|
</Flyout.FlyoutPresenterStyle>
|
||||||
|
|
||||||
|
<Grid x:Name="FlyoutContent">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<StackPanel Padding="16" Spacing="8">
|
||||||
|
|
||||||
|
<!-- Logs section -->
|
||||||
|
<TextBlock
|
||||||
|
Margin="1,0,0,6"
|
||||||
|
Style="{ThemeResource SettingsSectionHeaderTextBlockStyle}"
|
||||||
|
Text="Logs" />
|
||||||
|
<ItemsControl ItemTemplate="{StaticResource LogEntryTemplate}" ItemsSource="{x:Bind ViewModel.LatestLogs, Mode=OneWay}" />
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<Button Command="{x:Bind ViewModel.OpenLogFileCommand}" Content="Open Log File" />
|
||||||
|
<Button Command="{x:Bind ViewModel.OpenLogFolderCommand}" Content="Open Log Folder" />
|
||||||
|
<Button Command="{x:Bind ViewModel.ResetErrorCountersCommand}" Content="Clear Counters" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Build info section -->
|
||||||
|
<TextBlock Style="{ThemeResource SettingsSectionHeaderTextBlockStyle}" Text="Build Info" />
|
||||||
|
<Border
|
||||||
|
Padding="16"
|
||||||
|
Background="{ThemeResource SettingsCardBackground}"
|
||||||
|
BorderBrush="{ThemeResource SettingsCardBorderBrush}"
|
||||||
|
BorderThickness="1">
|
||||||
|
<Grid ColumnSpacing="8">
|
||||||
|
<Grid.Resources>
|
||||||
|
<Style
|
||||||
|
x:Key="KeyTextBlockStyle"
|
||||||
|
BasedOn="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
TargetType="TextBlock">
|
||||||
|
<Setter Property="IsTextSelectionEnabled" Value="True" />
|
||||||
|
<Setter Property="Foreground" Value="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||||
|
</Style>
|
||||||
|
<Style
|
||||||
|
x:Key="ValueTextBlockStyle"
|
||||||
|
BasedOn="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
TargetType="TextBlock">
|
||||||
|
<Setter Property="IsTextSelectionEnabled" Value="True" />
|
||||||
|
<Setter Property="TextAlignment" Value="Right" />
|
||||||
|
</Style>
|
||||||
|
</Grid.Resources>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
Style="{StaticResource KeyTextBlockStyle}"
|
||||||
|
Text="Configuration:" />
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ValueTextBlockStyle}"
|
||||||
|
Text="{x:Bind ViewModel.BuildConfiguration, Mode=OneWay}" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="0"
|
||||||
|
Style="{StaticResource KeyTextBlockStyle}"
|
||||||
|
Text="AOT:" />
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ValueTextBlockStyle}"
|
||||||
|
Text="{x:Bind ViewModel.IsAot, Mode=OneWay}" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="2"
|
||||||
|
Grid.Column="0"
|
||||||
|
Style="{StaticResource KeyTextBlockStyle}"
|
||||||
|
Text="Trimmed:" />
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="2"
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ValueTextBlockStyle}"
|
||||||
|
Text="{x:Bind ViewModel.IsPublishTrimmed, Mode=OneWay}" />
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<Border
|
||||||
|
Grid.Row="1"
|
||||||
|
Padding="16"
|
||||||
|
Background="{ThemeResource SettingsCardBackground}"
|
||||||
|
BorderBrush="{ThemeResource SettingsCardBorderBrush}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="{ThemeResource ControlCornerRadius}"
|
||||||
|
Visibility="{x:Bind ViewModel.IsAotReleaseConfiguration, Mode=OneWay, Converter={StaticResource InvertedBoolToVisibilityConverter}}">
|
||||||
|
<TextBlock Text="Warning: Test in Release/AOT configuration to verify everything works." TextWrapping="Wrap" />
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</Flyout>
|
||||||
|
</Button.Flyout>
|
||||||
|
</Button>
|
||||||
|
</Border>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation
|
||||||
|
Storyboard.TargetName="RootBorder"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="1.0"
|
||||||
|
Duration="0:0:0.1" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="SeverityStates">
|
||||||
|
<VisualState x:Name="NoLog" />
|
||||||
|
<VisualState x:Name="WarningLog">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SeverityIcon" Storyboard.TargetProperty="Glyph">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="ErrorLog">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SeverityIcon" Storyboard.TargetProperty="Glyph">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@@ -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 Microsoft.CommandPalette.UI.ViewModels;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Input;
|
||||||
|
|
||||||
|
namespace Microsoft.CommandPalette.UI.Controls;
|
||||||
|
|
||||||
|
internal sealed partial class DevRibbon : UserControl
|
||||||
|
{
|
||||||
|
public DevRibbonViewModel ViewModel { get; }
|
||||||
|
|
||||||
|
public DevRibbon()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
ViewModel = new DevRibbonViewModel();
|
||||||
|
|
||||||
|
if (FlyoutContent != null)
|
||||||
|
{
|
||||||
|
FlyoutContent.DataContext = ViewModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DevRibbonButton_PointerEntered(object sender, PointerRoutedEventArgs e)
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, "PointerOver", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DevRibbonButton_PointerExited(object sender, PointerRoutedEventArgs e)
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, "Normal", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Visibility VisibleIfGreaterThanZero(int value)
|
||||||
|
{
|
||||||
|
return value > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
// 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 Windows.System;
|
||||||
|
using Windows.Win32;
|
||||||
|
using Windows.Win32.Foundation;
|
||||||
|
using Windows.Win32.UI.WindowsAndMessaging;
|
||||||
|
|
||||||
|
namespace Microsoft.CommandPalette.UI.Helpers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A class that listens for local keyboard events using a Windows hook.
|
||||||
|
/// </summary>
|
||||||
|
internal sealed partial class LocalKeyboardListener : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event that is raised when a key is pressed down.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<LocalKeyboardListenerKeyPressedEventArgs>? KeyPressed;
|
||||||
|
|
||||||
|
private bool _disposed;
|
||||||
|
private UnhookWindowsHookExSafeHandle? _handle;
|
||||||
|
private HOOKPROC? _hookProc; // Keep reference to prevent GC collection
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers a global keyboard hook to listen for key down events.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="InvalidOperationException">
|
||||||
|
/// Throws if the hook could not be registered, which may happen if the system is unable to set the hook.
|
||||||
|
/// </exception>
|
||||||
|
public void RegisterKeyboardHook()
|
||||||
|
{
|
||||||
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
if (_handle is not null && !_handle.IsInvalid)
|
||||||
|
{
|
||||||
|
// Hook is already set
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_hookProc = KeyEventHook;
|
||||||
|
if (!SetWindowKeyHook(_hookProc))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Failed to register keyboard hook.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to register a global keyboard hook to listen for key down events.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true"/> if the keyboard hook was successfully registered; otherwise, <see langword="false"/>.
|
||||||
|
/// </returns>
|
||||||
|
public bool Start()
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RegisterKeyboardHook();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError("Failed to register hook", ex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UnregisterKeyboardHook()
|
||||||
|
{
|
||||||
|
if (_handle is not null && !_handle.IsInvalid)
|
||||||
|
{
|
||||||
|
// The SafeHandle should automatically call UnhookWindowsHookEx when disposed
|
||||||
|
_handle.Dispose();
|
||||||
|
_handle = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_hookProc = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SetWindowKeyHook(HOOKPROC hookProc)
|
||||||
|
{
|
||||||
|
if (_handle is not null && !_handle.IsInvalid)
|
||||||
|
{
|
||||||
|
// Hook is already set
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_handle = PInvoke.SetWindowsHookEx(
|
||||||
|
WINDOWS_HOOK_ID.WH_KEYBOARD,
|
||||||
|
hookProc,
|
||||||
|
PInvoke.GetModuleHandle(null),
|
||||||
|
PInvoke.GetCurrentThreadId());
|
||||||
|
|
||||||
|
// Check if the hook was successfully set
|
||||||
|
return _handle is not null && !_handle.IsInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsKeyDownHook(LPARAM lParam)
|
||||||
|
{
|
||||||
|
// The 30th bit tells what the previous key state is with 0 being the "UP" state
|
||||||
|
// For more info see https://learn.microsoft.com/windows/win32/winmsg/keyboardproc#lparam-in
|
||||||
|
return ((lParam.Value >> 30) & 1) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LRESULT KeyEventHook(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (nCode >= 0 && IsKeyDownHook(lParam))
|
||||||
|
{
|
||||||
|
InvokeKeyDown((VirtualKey)wParam.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError("Failed when invoking key down keyboard hook event", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call next hook in chain - pass null as first parameter for current hook
|
||||||
|
return PInvoke.CallNextHookEx(null, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InvokeKeyDown(VirtualKey virtualKey)
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
KeyPressed?.Invoke(this, new LocalKeyboardListenerKeyPressedEventArgs(virtualKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
UnregisterKeyboardHook();
|
||||||
|
}
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// 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 Windows.System;
|
||||||
|
|
||||||
|
namespace Microsoft.CommandPalette.UI.Helpers;
|
||||||
|
|
||||||
|
public class LocalKeyboardListenerKeyPressedEventArgs(VirtualKey key) : EventArgs
|
||||||
|
{
|
||||||
|
public VirtualKey Key { get; } = key;
|
||||||
|
}
|
||||||
@@ -10,7 +10,9 @@
|
|||||||
Height="480"
|
Height="480"
|
||||||
MinWidth="320"
|
MinWidth="320"
|
||||||
MinHeight="240"
|
MinHeight="240"
|
||||||
|
Activated="MainWindow_Activated"
|
||||||
|
Closed="MainWindow_Closed"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<Frame x:Name="RootElement">
|
<Grid x:Name="RootElement">
|
||||||
</Frame>
|
</Grid>
|
||||||
</winuiex:WindowEx>
|
</winuiex:WindowEx>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Page
|
<Page
|
||||||
x:Class="Microsoft.CommandPalette.UI.Pages.ShellPage"
|
x:Class="Microsoft.CommandPalette.UI.Pages.ShellPage"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
|
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
|
||||||
|
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="using:Microsoft.CommandPalette.UI.Pages"
|
xmlns:local="using:Microsoft.CommandPalette.UI.Pages"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
@@ -12,6 +13,14 @@
|
|||||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Page.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<converters:BoolToVisibilityConverter
|
||||||
|
x:Key="BoolToInvertedVisibilityConverter"
|
||||||
|
FalseValue="Visible"
|
||||||
|
TrueValue="Collapsed" />
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Page.Resources>
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
@@ -26,178 +35,6 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<!-- Back button and search box -->
|
|
||||||
<Grid
|
|
||||||
x:Name="TopBarGrid"
|
|
||||||
Padding="0,12,0,12"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
VerticalAlignment="Stretch"
|
|
||||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
|
||||||
BorderThickness="0,0,0,1">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
</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.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}"
|
|
||||||
Visibility="{x:Bind viewModel.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>
|
|
||||||
</StackPanel>
|
|
||||||
<!-- Search box: wrapped in a grid to enable RepositionThemeTransitions -->
|
|
||||||
<Grid Grid.Column="1" HorizontalAlignment="Stretch">
|
|
||||||
|
|
||||||
<Grid.Transitions>
|
|
||||||
<TransitionCollection>
|
|
||||||
<RepositionThemeTransition />
|
|
||||||
</TransitionCollection>
|
|
||||||
</Grid.Transitions>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid x:Name="ContentGrid" Grid.Row="1">
|
|
||||||
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="3*" />
|
|
||||||
<ColumnDefinition x:Name="DetailsColumn" Width="Auto" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<Frame
|
|
||||||
Name="RootFrame"
|
|
||||||
AutomationProperties.AutomationControlType="Pane"
|
|
||||||
AutomationProperties.LandmarkType="Navigation"
|
|
||||||
AutomationProperties.LiveSetting="Assertive"
|
|
||||||
IsNavigationStackEnabled="True" />
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
</Grid>
|
|
||||||
</ScrollViewer>
|
|
||||||
<!-- /DetailsContent -->
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
Reference in New Issue
Block a user