mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-30 00:46:20 +01:00
Compare commits
5 Commits
feature/ru
...
dev/mjolle
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42bf5ad885 | ||
|
|
0b10a15a8a | ||
|
|
c755b8585a | ||
|
|
bfc1bcae6d | ||
|
|
c0f6a3f9f4 |
@@ -1,62 +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;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.Common;
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -9,4 +9,8 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.Common.Services;
|
||||
@@ -26,12 +24,4 @@ public interface IExtensionService
|
||||
void EnableExtension(string extensionUniqueId);
|
||||
|
||||
void DisableExtension(string extensionUniqueId);
|
||||
|
||||
///// <summary>
|
||||
///// Gets a boolean indicating whether the extension was disabled due to the corresponding Windows optional feature
|
||||
///// being absent from the machine or in an unknown state.
|
||||
///// </summary>
|
||||
///// <param name="extension">The out of proc extension object</param>
|
||||
///// <returns>True only if the extension was disabled. False otherwise.</returns>
|
||||
// public Task<bool> DisableExtensionIfWindowsFeatureNotAvailable(IExtensionWrapper extension);
|
||||
}
|
||||
|
||||
@@ -23,12 +23,3 @@ public interface IRunHistoryService
|
||||
/// <param name="item">The run history item to add.</param>
|
||||
void AddRunHistoryItem(string item);
|
||||
}
|
||||
|
||||
public interface ITelemetryService
|
||||
{
|
||||
void LogRunQuery(string query, int resultCount, ulong durationMs);
|
||||
|
||||
void LogRunCommand(string command, bool asAdmin, bool success);
|
||||
|
||||
void LogOpenUri(string uri, bool isWeb, bool success);
|
||||
}
|
||||
|
||||
@@ -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.CmdPal.Core.Common.Services.Telemetry;
|
||||
|
||||
public interface ITelemetryService
|
||||
{
|
||||
void WriteEvent(TelemetryEventBase telemetryEvent);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// 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.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
|
||||
public abstract class TelemetryEventBase : EventBase, IEvent
|
||||
{
|
||||
// Overridden in derived classes
|
||||
public abstract PartA_PrivTags PartA_PrivTags { get; }
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.CmdPal.Core.Common;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
@@ -14,6 +14,7 @@ namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
public abstract partial class AppExtensionHost : IExtensionHost
|
||||
{
|
||||
private static readonly GlobalLogPageContext _globalLogPageContext = new();
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private static ulong _hostingHwnd;
|
||||
|
||||
@@ -27,6 +28,11 @@ public abstract partial class AppExtensionHost : IExtensionHost
|
||||
|
||||
public static void SetHostHwnd(ulong hostHwnd) => _hostingHwnd = hostHwnd;
|
||||
|
||||
public AppExtensionHost(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void DebugLog(string message)
|
||||
{
|
||||
#if DEBUG
|
||||
@@ -60,7 +66,7 @@ public abstract partial class AppExtensionHost : IExtensionHost
|
||||
return Task.CompletedTask.AsAsyncAction();
|
||||
}
|
||||
|
||||
CoreLogger.LogDebug(message.Message);
|
||||
Log_DebugMessage(message.Message);
|
||||
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
@@ -96,7 +102,7 @@ public abstract partial class AppExtensionHost : IExtensionHost
|
||||
|
||||
public void ProcessLogMessage(ILogMessage message)
|
||||
{
|
||||
var vm = new LogMessageViewModel(message, _globalLogPageContext);
|
||||
var vm = new LogMessageViewModel(message, _globalLogPageContext, _logger);
|
||||
vm.SafeInitializePropertiesSynchronous();
|
||||
|
||||
Task.Factory.StartNew(
|
||||
@@ -127,7 +133,7 @@ public abstract partial class AppExtensionHost : IExtensionHost
|
||||
return;
|
||||
}
|
||||
|
||||
var vm = new StatusMessageViewModel(message, new(_globalLogPageContext));
|
||||
var vm = new StatusMessageViewModel(message, new(_globalLogPageContext), _logger);
|
||||
vm.SafeInitializePropertiesSynchronous();
|
||||
|
||||
Task.Factory.StartNew(
|
||||
@@ -158,6 +164,11 @@ public abstract partial class AppExtensionHost : IExtensionHost
|
||||
}
|
||||
|
||||
public abstract string? GetExtensionDisplayName();
|
||||
|
||||
public abstract AppExtensionHost GetHostForCommand(object? context, AppExtensionHost? currentHost);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "{Message}")]
|
||||
partial void Log_DebugMessage(string message);
|
||||
}
|
||||
|
||||
public interface IAppHostService
|
||||
|
||||
@@ -6,6 +6,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Windows.System;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
@@ -13,6 +14,8 @@ namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
public partial class CommandBarViewModel : ObservableObject,
|
||||
IRecipient<UpdateCommandBarMessage>
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public ICommandBarContext? SelectedItem
|
||||
{
|
||||
get => field;
|
||||
@@ -48,8 +51,9 @@ public partial class CommandBarViewModel : ObservableObject,
|
||||
[ObservableProperty]
|
||||
public partial PageViewModel? CurrentPage { get; set; }
|
||||
|
||||
public CommandBarViewModel()
|
||||
public CommandBarViewModel(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
WeakReferenceMessenger.Default.Register<UpdateCommandBarMessage>(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
|
||||
public partial class CommandContextItemViewModel(ICommandContextItem contextItem, WeakReference<IPageContext> context) : CommandItemViewModel(new(contextItem), context), IContextItemViewModel
|
||||
public partial class CommandContextItemViewModel(ICommandContextItem contextItem, WeakReference<IPageContext> context, ILogger logger) : CommandItemViewModel(new(contextItem), context, logger), IContextItemViewModel
|
||||
{
|
||||
private readonly KeyChord nullKeyChord = new(0, 0, 0);
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.CmdPal.Core.Common;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
@@ -86,11 +86,11 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
|
||||
_errorIcon.InitializeProperties();
|
||||
}
|
||||
|
||||
public CommandItemViewModel(ExtensionObject<ICommandItem> item, WeakReference<IPageContext> errorContext)
|
||||
: base(errorContext)
|
||||
public CommandItemViewModel(ExtensionObject<ICommandItem> item, WeakReference<IPageContext> errorContext, ILogger logger)
|
||||
: base(errorContext, logger)
|
||||
{
|
||||
_commandItemModel = item;
|
||||
Command = new(null, errorContext);
|
||||
Command = new(null, errorContext, Logger);
|
||||
}
|
||||
|
||||
public void FastInitializeProperties()
|
||||
@@ -106,7 +106,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
|
||||
return;
|
||||
}
|
||||
|
||||
Command = new(model.Command, PageContext);
|
||||
Command = new(model.Command, PageContext, Logger);
|
||||
Command.FastInitializeProperties();
|
||||
|
||||
_itemTitle = model.Title;
|
||||
@@ -184,7 +184,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
|
||||
MoreCommands = more
|
||||
.Select<IContextItem, IContextItemViewModel>(item =>
|
||||
{
|
||||
return item is ICommandContextItem contextItem ? new CommandContextItemViewModel(contextItem, PageContext) : new SeparatorViewModel();
|
||||
return item is ICommandContextItem contextItem ? new CommandContextItemViewModel(contextItem, PageContext, Logger) : new SeparatorViewModel();
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
@@ -201,7 +201,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
|
||||
|
||||
if (!string.IsNullOrEmpty(model.Command?.Name))
|
||||
{
|
||||
_defaultCommandContextItemViewModel = new CommandContextItemViewModel(new CommandContextItem(model.Command!), PageContext)
|
||||
_defaultCommandContextItemViewModel = new CommandContextItemViewModel(new CommandContextItem(model.Command!), PageContext, Logger)
|
||||
{
|
||||
_itemTitle = Name,
|
||||
Subtitle = Subtitle,
|
||||
@@ -231,8 +231,8 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CoreLogger.LogError("error fast initializing CommandItemViewModel", ex);
|
||||
Command = new(null, PageContext);
|
||||
Log_ErrorFastInitializingCommandItemViewModel(Logger, ex);
|
||||
Command = new(null, PageContext, Logger);
|
||||
_itemTitle = "Error";
|
||||
Subtitle = "Item failed to load";
|
||||
MoreCommands = [];
|
||||
@@ -253,7 +253,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
|
||||
catch (Exception ex)
|
||||
{
|
||||
Initialized |= InitializedState.Error;
|
||||
CoreLogger.LogError("error slow initializing CommandItemViewModel", ex);
|
||||
Log_ErrorSlowInitializingCommandItemViewModel(Logger, ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -268,8 +268,8 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CoreLogger.LogError("error initializing CommandItemViewModel", ex);
|
||||
Command = new(null, PageContext);
|
||||
Log_ErrorSlowInitializingCommandItemViewModel(Logger, ex);
|
||||
Command = new(null, PageContext, Logger);
|
||||
_itemTitle = "Error";
|
||||
Subtitle = "Item failed to load";
|
||||
MoreCommands = [];
|
||||
@@ -304,7 +304,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
|
||||
{
|
||||
case nameof(Command):
|
||||
Command.PropertyChanged -= Command_PropertyChanged;
|
||||
Command = new(model.Command, PageContext);
|
||||
Command = new(model.Command, PageContext, Logger);
|
||||
Command.InitializeProperties();
|
||||
Command.PropertyChanged += Command_PropertyChanged;
|
||||
|
||||
@@ -351,7 +351,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
|
||||
var newContextMenu = more
|
||||
.Select<IContextItem, IContextItemViewModel>(item =>
|
||||
{
|
||||
return item is ICommandContextItem contextItem ? new CommandContextItemViewModel(contextItem, PageContext) : new SeparatorViewModel();
|
||||
return item is ICommandContextItem contextItem ? new CommandContextItemViewModel(contextItem, PageContext, Logger) : new SeparatorViewModel();
|
||||
})
|
||||
.ToList();
|
||||
lock (MoreCommands)
|
||||
@@ -464,6 +464,15 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
|
||||
base.SafeCleanup();
|
||||
Initialized |= InitializedState.CleanedUp;
|
||||
}
|
||||
|
||||
[LoggerMessage(level: LogLevel.Error, message: "error fast initializing CommandItemViewModel")]
|
||||
static partial void Log_ErrorFastInitializingCommandItemViewModel(ILogger logger, Exception ex);
|
||||
|
||||
[LoggerMessage(level: LogLevel.Error, message: "error slow initializing CommandItemViewModel")]
|
||||
static partial void Log_ErrorSlowInitializingCommandItemViewModel(ILogger logger, Exception ex);
|
||||
|
||||
[LoggerMessage(level: LogLevel.Error, message: "error initializing CommandItemViewModel")]
|
||||
static partial void Log_ErrorInitializingCommandItemViewModel(ILogger logger, Exception ex);
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
@@ -38,8 +39,8 @@ public partial class CommandViewModel : ExtensionObjectViewModel
|
||||
|
||||
public IReadOnlyDictionary<string, ExtensionObject<object>>? Properties => _properties?.AsReadOnly();
|
||||
|
||||
public CommandViewModel(ICommand? command, WeakReference<IPageContext> pageContext)
|
||||
: base(pageContext)
|
||||
public CommandViewModel(ICommand? command, WeakReference<IPageContext> pageContext, ILogger logger)
|
||||
: base(pageContext, logger)
|
||||
{
|
||||
Model = new(command);
|
||||
Icon = new(null);
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public partial class ConfirmResultViewModel(IConfirmationArgs _args, WeakReference<IPageContext> context) :
|
||||
ExtensionObjectViewModel(context)
|
||||
public partial class ConfirmResultViewModel(IConfirmationArgs? args, WeakReference<IPageContext> context, ILogger logger)
|
||||
: ExtensionObjectViewModel(context, logger)
|
||||
{
|
||||
public ExtensionObject<IConfirmationArgs> Model { get; } = new(_args);
|
||||
public ExtensionObject<IConfirmationArgs> Model { get; private set; } = new(args);
|
||||
|
||||
// Remember - "observable" properties from the model (via PropChanged)
|
||||
// cannot be marked [ObservableProperty]
|
||||
@@ -20,7 +21,7 @@ public partial class ConfirmResultViewModel(IConfirmationArgs _args, WeakReferen
|
||||
|
||||
public bool IsPrimaryCommandCritical { get; private set; }
|
||||
|
||||
public CommandViewModel PrimaryCommand { get; private set; } = new(null, context);
|
||||
public CommandViewModel PrimaryCommand { get; private set; } = new(null, context, logger);
|
||||
|
||||
public override void InitializeProperties()
|
||||
{
|
||||
@@ -33,7 +34,7 @@ public partial class ConfirmResultViewModel(IConfirmationArgs _args, WeakReferen
|
||||
Title = model.Title;
|
||||
Description = model.Description;
|
||||
IsPrimaryCommandCritical = model.IsPrimaryCommandCritical;
|
||||
PrimaryCommand = new(model.PrimaryCommand, PageContext);
|
||||
PrimaryCommand = new(model.PrimaryCommand, PageContext, Logger);
|
||||
PrimaryCommand.InitializeProperties();
|
||||
|
||||
UpdateProperty(nameof(Title));
|
||||
|
||||
@@ -11,12 +11,14 @@ using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
|
||||
{
|
||||
private readonly ExtensionObject<IContentPage> _model;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<ContentViewModel> Content { get; set; } = [];
|
||||
@@ -47,10 +49,11 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
|
||||
|
||||
// Remember - "observable" properties from the model (via PropChanged)
|
||||
// cannot be marked [ObservableProperty]
|
||||
public ContentPageViewModel(IContentPage model, TaskScheduler scheduler, AppExtensionHost host)
|
||||
: base(model, scheduler, host)
|
||||
public ContentPageViewModel(IContentPage model, AppExtensionHost host, ILogger logger)
|
||||
: base(model, host, logger)
|
||||
{
|
||||
_model = new(model);
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
// TODO: Does this need to hop to a _different_ thread, so that we don't block the extension while we're fetching?
|
||||
@@ -115,7 +118,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
|
||||
{
|
||||
if (item is ICommandContextItem contextItem)
|
||||
{
|
||||
return new CommandContextItemViewModel(contextItem, PageContext);
|
||||
return new CommandContextItemViewModel(contextItem, PageContext, _logger);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -135,7 +138,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
|
||||
var extensionDetails = model.Details;
|
||||
if (extensionDetails is not null)
|
||||
{
|
||||
Details = new(extensionDetails, PageContext);
|
||||
Details = new(extensionDetails, PageContext, _logger);
|
||||
Details.InitializeProperties();
|
||||
}
|
||||
|
||||
@@ -174,7 +177,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
|
||||
{
|
||||
if (item is ICommandContextItem contextItem)
|
||||
{
|
||||
return new CommandContextItemViewModel(contextItem, PageContext) as IContextItemViewModel;
|
||||
return new CommandContextItemViewModel(contextItem, PageContext, _logger) as IContextItemViewModel;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -216,7 +219,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
|
||||
break;
|
||||
case nameof(Details):
|
||||
var extensionDetails = model.Details;
|
||||
Details = extensionDetails is not null ? new(extensionDetails, PageContext) : null;
|
||||
Details = extensionDetails is not null ? new(extensionDetails, PageContext, _logger) : null;
|
||||
UpdateDetails();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
// 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.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public abstract partial class ContentViewModel(WeakReference<IPageContext> context) :
|
||||
ExtensionObjectViewModel(context)
|
||||
public abstract partial class ContentViewModel(WeakReference<IPageContext> context, ILogger logger) :
|
||||
ExtensionObjectViewModel(context, logger)
|
||||
{
|
||||
public bool OnlyControlOnPage { get; internal set; }
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.CmdPal.Core.Common;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
@@ -138,11 +137,7 @@ public partial class ContextMenuViewModel : ObservableObject,
|
||||
if (item is CommandContextItemViewModel cmd && cmd.HasRequestedShortcut)
|
||||
{
|
||||
var key = cmd.RequestedShortcut ?? new KeyChord(0, 0, 0);
|
||||
var added = result.TryAdd(key, cmd);
|
||||
if (!added)
|
||||
{
|
||||
CoreLogger.LogWarning($"Ignoring duplicate keyboard shortcut {KeyChordHelpers.FormatForDebug(key)} on command '{cmd.Title ?? cmd.Name ?? "(unknown)"}'");
|
||||
}
|
||||
_ = result.TryAdd(key, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,19 +4,26 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public partial class DetailsCommandsViewModel(
|
||||
IDetailsElement _detailsElement,
|
||||
WeakReference<IPageContext> context) : DetailsElementViewModel(_detailsElement, context)
|
||||
public partial class DetailsCommandsViewModel : DetailsElementViewModel
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public List<CommandViewModel> Commands { get; private set; } = [];
|
||||
|
||||
public bool HasCommands => Commands.Count > 0;
|
||||
|
||||
private readonly ExtensionObject<IDetailsCommands> _dataModel =
|
||||
new(_detailsElement.Data as IDetailsCommands);
|
||||
private readonly ExtensionObject<IDetailsCommands> _dataModel;
|
||||
|
||||
public DetailsCommandsViewModel(IDetailsElement _detailsElement, WeakReference<IPageContext> context, ILogger logger)
|
||||
: base(_detailsElement, context, logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_dataModel = new(_detailsElement.Data as IDetailsCommands);
|
||||
}
|
||||
|
||||
public override void InitializeProperties()
|
||||
{
|
||||
@@ -31,7 +38,7 @@ public partial class DetailsCommandsViewModel(
|
||||
.Commands?
|
||||
.Select(c =>
|
||||
{
|
||||
var vm = new CommandViewModel(c, PageContext);
|
||||
var vm = new CommandViewModel(c, PageContext, _logger);
|
||||
vm.InitializeProperties();
|
||||
return vm;
|
||||
})
|
||||
|
||||
@@ -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.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public abstract partial class DetailsDataViewModel(IPageContext context) : ExtensionObjectViewModel(context)
|
||||
public abstract partial class DetailsDataViewModel(IPageContext context, ILogger logger) : ExtensionObjectViewModel(context, logger)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public abstract partial class DetailsElementViewModel(IDetailsElement _detailsElement, WeakReference<IPageContext> context) : ExtensionObjectViewModel(context)
|
||||
public abstract partial class DetailsElementViewModel(IDetailsElement _detailsElement, WeakReference<IPageContext> context, ILogger logger) : ExtensionObjectViewModel(context, logger)
|
||||
{
|
||||
private readonly ExtensionObject<IDetailsElement> _model = new(_detailsElement);
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public partial class DetailsLinkViewModel(
|
||||
IDetailsElement _detailsElement,
|
||||
WeakReference<IPageContext> context) : DetailsElementViewModel(_detailsElement, context)
|
||||
public partial class DetailsLinkViewModel(IDetailsElement _detailsElement, WeakReference<IPageContext> context, ILogger logger)
|
||||
: DetailsElementViewModel(_detailsElement, context, logger)
|
||||
{
|
||||
private static readonly string[] _initProperties = [
|
||||
nameof(Text),
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public partial class DetailsSeparatorViewModel(
|
||||
IDetailsElement _detailsElement,
|
||||
WeakReference<IPageContext> context) : DetailsElementViewModel(_detailsElement, context)
|
||||
WeakReference<IPageContext> context, ILogger logger) : DetailsElementViewModel(_detailsElement, context, logger)
|
||||
{
|
||||
private readonly ExtensionObject<IDetailsSeparator> _dataModel =
|
||||
new(_detailsElement.Data as IDetailsSeparator);
|
||||
|
||||
@@ -4,19 +4,25 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public partial class DetailsTagsViewModel(
|
||||
IDetailsElement _detailsElement,
|
||||
WeakReference<IPageContext> context) : DetailsElementViewModel(_detailsElement, context)
|
||||
public partial class DetailsTagsViewModel : DetailsElementViewModel
|
||||
{
|
||||
public List<TagViewModel> Tags { get; private set; } = [];
|
||||
|
||||
public bool HasTags => Tags.Count > 0;
|
||||
|
||||
private readonly ExtensionObject<IDetailsTags> _dataModel =
|
||||
new(_detailsElement.Data as IDetailsTags);
|
||||
private readonly ExtensionObject<IDetailsTags> _dataModel;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public DetailsTagsViewModel(IDetailsElement _detailsElement, WeakReference<IPageContext> context, ILogger logger)
|
||||
: base(_detailsElement, context, logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_dataModel = new(_detailsElement.Data as IDetailsTags);
|
||||
}
|
||||
|
||||
public override void InitializeProperties()
|
||||
{
|
||||
@@ -31,7 +37,7 @@ public partial class DetailsTagsViewModel(
|
||||
.Tags?
|
||||
.Select(t =>
|
||||
{
|
||||
var vm = new TagViewModel(t, PageContext);
|
||||
var vm = new TagViewModel(t, PageContext, _logger);
|
||||
vm.InitializeProperties();
|
||||
return vm;
|
||||
})
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public partial class DetailsViewModel(IDetails _details, WeakReference<IPageContext> context) : ExtensionObjectViewModel(context)
|
||||
public partial class DetailsViewModel(IDetails _details, WeakReference<IPageContext> context, ILogger logger) : ExtensionObjectViewModel(context, logger)
|
||||
{
|
||||
private readonly ExtensionObject<IDetails> _detailsModel = new(_details);
|
||||
|
||||
@@ -47,10 +48,10 @@ public partial class DetailsViewModel(IDetails _details, WeakReference<IPageCont
|
||||
{
|
||||
DetailsElementViewModel? vm = element.Data switch
|
||||
{
|
||||
IDetailsSeparator => new DetailsSeparatorViewModel(element, this.PageContext),
|
||||
IDetailsLink => new DetailsLinkViewModel(element, this.PageContext),
|
||||
IDetailsCommands => new DetailsCommandsViewModel(element, this.PageContext),
|
||||
IDetailsTags => new DetailsTagsViewModel(element, this.PageContext),
|
||||
IDetailsSeparator => new DetailsSeparatorViewModel(element, this.PageContext, Logger),
|
||||
IDetailsLink => new DetailsLinkViewModel(element, this.PageContext, Logger),
|
||||
IDetailsCommands => new DetailsCommandsViewModel(element, this.PageContext, Logger),
|
||||
IDetailsTags => new DetailsTagsViewModel(element, this.PageContext, Logger),
|
||||
_ => null,
|
||||
};
|
||||
if (vm is not null)
|
||||
|
||||
@@ -3,23 +3,29 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Microsoft.CmdPal.Core.Common;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public abstract partial class ExtensionObjectViewModel : ObservableObject
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public ILogger Logger => _logger;
|
||||
|
||||
public WeakReference<IPageContext> PageContext { get; set; }
|
||||
|
||||
internal ExtensionObjectViewModel(IPageContext? context)
|
||||
internal ExtensionObjectViewModel(IPageContext? context, ILogger logger)
|
||||
{
|
||||
var realContext = context ?? (this is IPageContext c ? c : throw new ArgumentException("You need to pass in an IErrorContext"));
|
||||
_logger = logger;
|
||||
PageContext = new(realContext);
|
||||
}
|
||||
|
||||
internal ExtensionObjectViewModel(WeakReference<IPageContext> context)
|
||||
internal ExtensionObjectViewModel(WeakReference<IPageContext> context, ILogger logger)
|
||||
{
|
||||
PageContext = context;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async virtual Task InitializePropertiesAsync()
|
||||
@@ -114,7 +120,10 @@ public abstract partial class ExtensionObjectViewModel : ObservableObject
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CoreLogger.LogDebug(ex.ToString());
|
||||
Log_CleanupException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug)]
|
||||
partial void Log_CleanupException(Exception exception);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
@@ -23,8 +24,8 @@ public partial class FilterItemViewModel : ExtensionObjectViewModel, IFilterItem
|
||||
|
||||
public bool IsInErrorState => Initialized.HasFlag(InitializedState.Error);
|
||||
|
||||
public FilterItemViewModel(IFilter filter, WeakReference<IPageContext> context)
|
||||
: base(context)
|
||||
public FilterItemViewModel(IFilter filter, WeakReference<IPageContext> context, ILogger logger)
|
||||
: base(context, logger)
|
||||
{
|
||||
_model = new(filter);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
@@ -21,8 +20,8 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
|
||||
|
||||
public bool ShouldShowFilters => Filters.Length > 0;
|
||||
|
||||
public FiltersViewModel(ExtensionObject<IFilters> filters, WeakReference<IPageContext> context)
|
||||
: base(context)
|
||||
public FiltersViewModel(ExtensionObject<IFilters> filters, WeakReference<IPageContext> context, ILogger logger)
|
||||
: base(context, logger)
|
||||
{
|
||||
_filtersModel = filters;
|
||||
}
|
||||
@@ -71,7 +70,7 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
|
||||
{
|
||||
if (filter is IFilter filterItem)
|
||||
{
|
||||
var filterItemViewModel = new FilterItemViewModel(filterItem, PageContext);
|
||||
var filterItemViewModel = new FilterItemViewModel(filterItem, PageContext, Logger);
|
||||
filterItemViewModel.InitializeProperties();
|
||||
|
||||
if (firstFilterItem is null)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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.Messages;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
// Represents everything the command bar needs to know about to show command
|
||||
// buttons at the bottom.
|
||||
//
|
||||
// This is implemented by both ListItemViewModel and ContentPageViewModel,
|
||||
// the two things with sub-commands.
|
||||
public interface ICommandBarContext : IContextMenuContext
|
||||
{
|
||||
public string SecondaryCommandName { get; }
|
||||
|
||||
public CommandItemViewModel? PrimaryCommand { get; }
|
||||
|
||||
public CommandItemViewModel? SecondaryCommand { get; }
|
||||
}
|
||||
@@ -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.CmdPal.Core.ViewModels;
|
||||
|
||||
public interface IPageContext
|
||||
{
|
||||
void ShowException(Exception ex, string? extensionHint = null);
|
||||
|
||||
TaskScheduler Scheduler { get; }
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public interface IPageViewModelFactoryService
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the page view model for the given page type.
|
||||
/// </summary>
|
||||
/// <param name="page">The page for which to create the view model.</param>
|
||||
/// <param name="nested">Indicates whether the page is not the top-level page.</param>
|
||||
/// <param name="host">The command palette host that will host the page (for status messages)</param>
|
||||
/// <returns>A new instance of the page view model.</returns>
|
||||
PageViewModel? TryCreatePageViewModel(IPage page, bool nested, AppExtensionHost host);
|
||||
}
|
||||
@@ -7,13 +7,14 @@ using Microsoft.CmdPal.Core.ViewModels.Commands;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public partial class ListItemViewModel(IListItem model, WeakReference<IPageContext> context)
|
||||
: CommandItemViewModel(new(model), context)
|
||||
// Fix for CS9107: Do not capture 'logger' in the primary constructor; use a regular constructor instead.
|
||||
public partial class ListItemViewModel : CommandItemViewModel
|
||||
{
|
||||
public new ExtensionObject<IListItem> Model { get; } = new(model);
|
||||
public new ExtensionObject<IListItem> Model { get; }
|
||||
|
||||
public List<TagViewModel>? Tags { get; set; }
|
||||
|
||||
@@ -32,6 +33,15 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
|
||||
|
||||
public string AccessibleName { get; private set; } = string.Empty;
|
||||
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public ListItemViewModel(IListItem model, WeakReference<IPageContext> context, ILogger logger)
|
||||
: base(new(model), context, logger)
|
||||
{
|
||||
Model = new(model);
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override void InitializeProperties()
|
||||
{
|
||||
if (IsInitialized)
|
||||
@@ -69,7 +79,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
|
||||
var extensionDetails = model.Details;
|
||||
if (extensionDetails is not null)
|
||||
{
|
||||
Details = new(extensionDetails, PageContext);
|
||||
Details = new(extensionDetails, PageContext, Logger);
|
||||
Details.InitializeProperties();
|
||||
UpdateProperty(nameof(Details));
|
||||
UpdateProperty(nameof(HasDetails));
|
||||
@@ -104,7 +114,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
|
||||
break;
|
||||
case nameof(Details):
|
||||
var extensionDetails = model.Details;
|
||||
Details = extensionDetails is not null ? new(extensionDetails, PageContext) : null;
|
||||
Details = extensionDetails is not null ? new(extensionDetails, PageContext, Logger) : null;
|
||||
Details?.InitializeProperties();
|
||||
UpdateProperty(nameof(Details));
|
||||
UpdateProperty(nameof(HasDetails));
|
||||
@@ -146,7 +156,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
|
||||
// Create the view model for the show details command
|
||||
var showDetailsCommand = new ShowDetailsCommand(Details);
|
||||
var showDetailsContextItem = new CommandContextItem(showDetailsCommand);
|
||||
var showDetailsContextItemViewModel = new CommandContextItemViewModel(showDetailsContextItem, PageContext);
|
||||
var showDetailsContextItemViewModel = new CommandContextItemViewModel(showDetailsContextItem, PageContext, _logger);
|
||||
showDetailsContextItemViewModel.SlowInitializeProperties();
|
||||
MoreCommands.Add(showDetailsContextItemViewModel);
|
||||
}
|
||||
@@ -180,7 +190,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
|
||||
// Create the view model for the show details command
|
||||
var showDetailsCommand = new ShowDetailsCommand(Details);
|
||||
var showDetailsContextItem = new CommandContextItem(showDetailsCommand);
|
||||
var showDetailsContextItemViewModel = new CommandContextItemViewModel(showDetailsContextItem, PageContext);
|
||||
var showDetailsContextItemViewModel = new CommandContextItemViewModel(showDetailsContextItem, PageContext, _logger);
|
||||
showDetailsContextItemViewModel.SlowInitializeProperties();
|
||||
MoreCommands.Add(showDetailsContextItemViewModel);
|
||||
|
||||
@@ -193,7 +203,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
|
||||
{
|
||||
var newTags = newTagsFromModel?.Select(t =>
|
||||
{
|
||||
var vm = new TagViewModel(t, PageContext);
|
||||
var vm = new TagViewModel(t, PageContext, Logger);
|
||||
vm.InitializeProperties();
|
||||
return vm;
|
||||
})
|
||||
|
||||
@@ -11,6 +11,7 @@ using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
@@ -19,6 +20,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
||||
{
|
||||
// private readonly HashSet<ListItemViewModel> _itemCache = [];
|
||||
private readonly TaskFactory filterTaskFactory = new(new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler);
|
||||
private readonly ILogger _logger;
|
||||
|
||||
// TODO: Do we want a base "ItemsPageViewModel" for anything that's going to have items?
|
||||
|
||||
@@ -90,11 +92,12 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public ListViewModel(IListPage model, TaskScheduler scheduler, AppExtensionHost host)
|
||||
: base(model, scheduler, host)
|
||||
public ListViewModel(IListPage model, TaskScheduler scheduler, AppExtensionHost host, ILogger logger)
|
||||
: base(model, host, logger)
|
||||
{
|
||||
_model = new(model);
|
||||
EmptyContent = new(new(null), PageContext);
|
||||
EmptyContent = new(new(null), PageContext, logger);
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
private void FiltersPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
@@ -232,7 +235,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
||||
return;
|
||||
}
|
||||
|
||||
ListItemViewModel viewModel = new(item, new(this));
|
||||
ListItemViewModel viewModel = new(item, new(this), _logger);
|
||||
|
||||
// If an item fails to load, silently ignore it.
|
||||
if (viewModel.SafeFastInit())
|
||||
@@ -594,11 +597,11 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
||||
UpdateProperty(nameof(SearchText));
|
||||
UpdateProperty(nameof(InitialSearchText));
|
||||
|
||||
EmptyContent = new(new(model.EmptyContent), PageContext);
|
||||
EmptyContent = new(new(model.EmptyContent), PageContext, _logger);
|
||||
EmptyContent.SlowInitializeProperties();
|
||||
|
||||
Filters?.PropertyChanged -= FiltersPropertyChanged;
|
||||
Filters = new(new(model.Filters), PageContext);
|
||||
Filters = new(new(model.Filters), PageContext, _logger);
|
||||
Filters?.PropertyChanged += FiltersPropertyChanged;
|
||||
|
||||
Filters?.InitializeProperties();
|
||||
@@ -696,12 +699,12 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
||||
SearchText = model.SearchText;
|
||||
break;
|
||||
case nameof(EmptyContent):
|
||||
EmptyContent = new(new(model.EmptyContent), PageContext);
|
||||
EmptyContent = new(new(model.EmptyContent), PageContext, _logger);
|
||||
EmptyContent.SlowInitializeProperties();
|
||||
break;
|
||||
case nameof(Filters):
|
||||
Filters?.PropertyChanged -= FiltersPropertyChanged;
|
||||
Filters = new(new(model.Filters), PageContext);
|
||||
Filters = new(new(model.Filters), PageContext, _logger);
|
||||
Filters?.PropertyChanged += FiltersPropertyChanged;
|
||||
Filters?.InitializeProperties();
|
||||
break;
|
||||
@@ -751,7 +754,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
||||
base.UnsafeCleanup();
|
||||
|
||||
EmptyContent?.SafeCleanup();
|
||||
EmptyContent = new(new(null), PageContext); // necessary?
|
||||
EmptyContent = new(new(null), PageContext, _logger); // necessary?
|
||||
|
||||
_cancellationTokenSource?.Cancel();
|
||||
filterCancellationTokenSource?.Cancel();
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public partial class LoadingPageViewModel : PageViewModel
|
||||
{
|
||||
public LoadingPageViewModel(IPage? model, TaskScheduler scheduler, AppExtensionHost host)
|
||||
: base(model, scheduler, host)
|
||||
public LoadingPageViewModel(IPage? model, AppExtensionHost host, ILogger logger)
|
||||
: base(model, host, logger)
|
||||
{
|
||||
ModelIsLoading = true;
|
||||
IsInitialized = false;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
@@ -13,8 +14,8 @@ public partial class LogMessageViewModel : ExtensionObjectViewModel
|
||||
|
||||
public string Message { get; private set; } = string.Empty;
|
||||
|
||||
public LogMessageViewModel(ILogMessage message, IPageContext context)
|
||||
: base(context)
|
||||
public LogMessageViewModel(ILogMessage message, IPageContext context, ILogger logger)
|
||||
: base(context, logger)
|
||||
{
|
||||
_model = new(message);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
/// <summary>
|
||||
/// Used to perform a list item's secondary command when the user presses ctrl+enter in the search box
|
||||
/// </summary>
|
||||
public record ActivateSecondaryCommandMessage
|
||||
{
|
||||
}
|
||||
public record ActivateSecondaryCommandMessage;
|
||||
|
||||
@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
/// <summary>
|
||||
/// Used to perform a list item's command when the user presses enter in the search box
|
||||
/// </summary>
|
||||
public record ActivateSelectedListItemMessage
|
||||
{
|
||||
}
|
||||
public record ActivateSelectedListItemMessage;
|
||||
|
||||
@@ -4,6 +4,4 @@
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record ClearSearchMessage()
|
||||
{
|
||||
}
|
||||
public record ClearSearchMessage();
|
||||
|
||||
@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
/// <summary>
|
||||
/// Used to announce that a context menu should close
|
||||
/// </summary>
|
||||
public record CloseContextMenuMessage
|
||||
{
|
||||
}
|
||||
public record CloseContextMenuMessage;
|
||||
|
||||
@@ -4,6 +4,4 @@
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record DismissMessage()
|
||||
{
|
||||
}
|
||||
public record DismissMessage();
|
||||
|
||||
@@ -4,6 +4,4 @@
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record FocusSearchBoxMessage()
|
||||
{
|
||||
}
|
||||
public record FocusSearchBoxMessage();
|
||||
|
||||
@@ -4,7 +4,5 @@
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record GoBackMessage(bool WithAnimation = true, bool FocusSearch = true)
|
||||
{
|
||||
// TODO! sticking these properties here feels like leaking the UI into the models
|
||||
}
|
||||
// TODO! sticking these properties here feels like leaking the UI into the models
|
||||
public record GoBackMessage(bool WithAnimation = true, bool FocusSearch = true);
|
||||
|
||||
@@ -5,6 +5,4 @@
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
// TODO! sticking these properties here feels like leaking the UI into the models
|
||||
public record GoHomeMessage(bool WithAnimation = true, bool FocusSearch = true)
|
||||
{
|
||||
}
|
||||
public record GoHomeMessage(bool WithAnimation = true, bool FocusSearch = true);
|
||||
|
||||
@@ -7,6 +7,4 @@ using Microsoft.CommandPalette.Extensions;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record HandleCommandResultMessage(ExtensionObject<ICommandResult> Result)
|
||||
{
|
||||
}
|
||||
public record HandleCommandResultMessage(ExtensionObject<ICommandResult> Result);
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
// 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.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record HideDetailsMessage()
|
||||
{
|
||||
}
|
||||
public record HideDetailsMessage();
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// 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 Microsoft.CommandPalette.Extensions;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public interface IContextMenuContext : INotifyPropertyChanged
|
||||
{
|
||||
public IEnumerable<IContextItemViewModel> MoreCommands { get; }
|
||||
|
||||
public bool HasMoreCommands { get; }
|
||||
|
||||
public List<IContextItemViewModel> AllCommands { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Generates a mapping of key -> command item for this particular item's
|
||||
/// MoreCommands. (This won't include the primary Command, but it will
|
||||
/// include the secondary one). This map can be used to quickly check if a
|
||||
/// shortcut key was pressed
|
||||
/// </summary>
|
||||
/// <returns>a dictionary of KeyChord -> Context commands, for all commands
|
||||
/// that have a shortcut key set.</returns>
|
||||
public Dictionary<KeyChord, CommandContextItemViewModel> Keybindings()
|
||||
{
|
||||
var result = new Dictionary<KeyChord, CommandContextItemViewModel>();
|
||||
|
||||
var menu = MoreCommands;
|
||||
if (menu is null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var item in menu)
|
||||
{
|
||||
if (item is CommandContextItemViewModel cmd && cmd.HasRequestedShortcut)
|
||||
{
|
||||
var key = cmd.RequestedShortcut ?? new KeyChord(0, 0, 0);
|
||||
var added = result.TryAdd(key, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,6 @@
|
||||
// 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.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record LaunchUriMessage(Uri Uri)
|
||||
{
|
||||
}
|
||||
public record LaunchUriMessage(Uri Uri);
|
||||
|
||||
@@ -4,6 +4,4 @@
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record NavigateBackMessage(bool FromBackspace = false)
|
||||
{
|
||||
}
|
||||
public record NavigateBackMessage(bool FromBackspace = false);
|
||||
|
||||
@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Commands;
|
||||
/// <summary>
|
||||
/// Used to navigate to the next command in the page when pressing the Down key in the SearchBox.
|
||||
/// </summary>
|
||||
public record NavigateNextCommand
|
||||
{
|
||||
}
|
||||
public record NavigateNextCommand;
|
||||
|
||||
@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
/// <summary>
|
||||
/// Used to navigate down one page in the page when pressing the PageDown key in the SearchBox.
|
||||
/// </summary>
|
||||
public record NavigatePageDownCommand
|
||||
{
|
||||
}
|
||||
public record NavigatePageDownCommand;
|
||||
|
||||
@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
/// <summary>
|
||||
/// Used to navigate up one page in the page when pressing the PageUp key in the SearchBox.
|
||||
/// </summary>
|
||||
public record NavigatePageUpCommand
|
||||
{
|
||||
}
|
||||
public record NavigatePageUpCommand;
|
||||
|
||||
@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
/// <summary>
|
||||
/// Used to navigate to the previous command in the page when pressing the Down key in the SearchBox.
|
||||
/// </summary>
|
||||
public record NavigatePreviousCommand
|
||||
{
|
||||
}
|
||||
public record NavigatePreviousCommand;
|
||||
|
||||
@@ -4,6 +4,4 @@
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record ShowConfirmationMessage(Microsoft.CommandPalette.Extensions.IConfirmationArgs? Args)
|
||||
{
|
||||
}
|
||||
public record ShowConfirmationMessage(Microsoft.CommandPalette.Extensions.IConfirmationArgs? Args);
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
// 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.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record ShowDetailsMessage(DetailsViewModel Details)
|
||||
{
|
||||
}
|
||||
public record ShowDetailsMessage(DetailsViewModel Details);
|
||||
|
||||
@@ -4,6 +4,4 @@
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record ShowToastMessage(string Message)
|
||||
{
|
||||
}
|
||||
public record ShowToastMessage(string Message);
|
||||
|
||||
@@ -4,6 +4,4 @@
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record ShowWindowMessage(IntPtr Hwnd)
|
||||
{
|
||||
}
|
||||
public record ShowWindowMessage(IntPtr Hwnd);
|
||||
|
||||
@@ -2,73 +2,9 @@
|
||||
// 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 Microsoft.CmdPal.Core.Common;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// Used to update the command bar at the bottom to reflect the commands for a list item
|
||||
/// </summary>
|
||||
public record UpdateCommandBarMessage(ICommandBarContext? ViewModel)
|
||||
{
|
||||
}
|
||||
|
||||
public interface IContextMenuContext : INotifyPropertyChanged
|
||||
{
|
||||
public IEnumerable<IContextItemViewModel> MoreCommands { get; }
|
||||
|
||||
public bool HasMoreCommands { get; }
|
||||
|
||||
public List<IContextItemViewModel> AllCommands { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Generates a mapping of key -> command item for this particular item's
|
||||
/// MoreCommands. (This won't include the primary Command, but it will
|
||||
/// include the secondary one). This map can be used to quickly check if a
|
||||
/// shortcut key was pressed
|
||||
/// </summary>
|
||||
/// <returns>a dictionary of KeyChord -> Context commands, for all commands
|
||||
/// that have a shortcut key set.</returns>
|
||||
public Dictionary<KeyChord, CommandContextItemViewModel> Keybindings()
|
||||
{
|
||||
var result = new Dictionary<KeyChord, CommandContextItemViewModel>();
|
||||
|
||||
var menu = MoreCommands;
|
||||
if (menu is null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var item in menu)
|
||||
{
|
||||
if (item is CommandContextItemViewModel cmd && cmd.HasRequestedShortcut)
|
||||
{
|
||||
var key = cmd.RequestedShortcut ?? new KeyChord(0, 0, 0);
|
||||
var added = result.TryAdd(key, cmd);
|
||||
if (!added)
|
||||
{
|
||||
CoreLogger.LogWarning($"Ignoring duplicate keyboard shortcut {KeyChordHelpers.FormatForDebug(key)} on command '{cmd.Title ?? cmd.Name ?? "(unknown)"}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Represents everything the command bar needs to know about to show command
|
||||
// buttons at the bottom.
|
||||
//
|
||||
// This is implemented by both ListItemViewModel and ContentPageViewModel,
|
||||
// the two things with sub-commands.
|
||||
public interface ICommandBarContext : IContextMenuContext
|
||||
{
|
||||
public string SecondaryCommandName { get; }
|
||||
|
||||
public CommandItemViewModel? PrimaryCommand { get; }
|
||||
|
||||
public CommandItemViewModel? SecondaryCommand { get; }
|
||||
}
|
||||
public record UpdateCommandBarMessage(ICommandBarContext? ViewModel);
|
||||
|
||||
@@ -4,6 +4,4 @@
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
public record UpdateSuggestionMessage(string TextToSuggest)
|
||||
{
|
||||
}
|
||||
public record UpdateSuggestionMessage(string TextToSuggest);
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
// 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.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
internal sealed partial class NullPageViewModel(TaskScheduler scheduler, AppExtensionHost extensionHost)
|
||||
: PageViewModel(null, scheduler, extensionHost);
|
||||
internal sealed partial class NullPageViewModel(AppExtensionHost extensionHost, ILogger logger)
|
||||
: PageViewModel(null, extensionHost, logger);
|
||||
|
||||
@@ -8,15 +8,16 @@ using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.CmdPal.Core.Common.Helpers;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public partial class PageViewModel : ExtensionObjectViewModel, IPageContext
|
||||
{
|
||||
public TaskScheduler Scheduler { get; private set; }
|
||||
|
||||
private readonly ExtensionObject<IPage> _pageModel;
|
||||
|
||||
public TaskScheduler Scheduler { get; private set; } = TaskScheduler.FromCurrentSynchronizationContext();
|
||||
|
||||
public bool IsLoading => ModelIsLoading || (!IsInitialized);
|
||||
|
||||
[ObservableProperty]
|
||||
@@ -76,11 +77,10 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext
|
||||
|
||||
public IconInfoViewModel Icon { get; protected set; }
|
||||
|
||||
public PageViewModel(IPage? model, TaskScheduler scheduler, AppExtensionHost extensionHost)
|
||||
: base((IPageContext?)null)
|
||||
public PageViewModel(IPage? model, AppExtensionHost extensionHost, ILogger logger)
|
||||
: base((IPageContext?)null, logger)
|
||||
{
|
||||
_pageModel = new(model);
|
||||
Scheduler = scheduler;
|
||||
PageContext = new(this);
|
||||
ExtensionHost = extensionHost;
|
||||
Icon = new(null);
|
||||
@@ -258,22 +258,3 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IPageContext
|
||||
{
|
||||
void ShowException(Exception ex, string? extensionHint = null);
|
||||
|
||||
TaskScheduler Scheduler { get; }
|
||||
}
|
||||
|
||||
public interface IPageViewModelFactoryService
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the page view model for the given page type.
|
||||
/// </summary>
|
||||
/// <param name="page">The page for which to create the view model.</param>
|
||||
/// <param name="nested">Indicates whether the page is not the top-level page.</param>
|
||||
/// <param name="host">The command palette host that will host the page (for status messages)</param>
|
||||
/// <returns>A new instance of the page view model.</returns>
|
||||
PageViewModel? TryCreatePageViewModel(IPage page, bool nested, AppExtensionHost host);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
@@ -15,8 +16,8 @@ public partial class ProgressViewModel : ExtensionObjectViewModel
|
||||
|
||||
public uint ProgressPercent { get; private set; }
|
||||
|
||||
public ProgressViewModel(IProgressState progress, WeakReference<IPageContext> context)
|
||||
: base(context)
|
||||
public ProgressViewModel(IProgressState progress, WeakReference<IPageContext> context, ILogger logger)
|
||||
: base(context, logger)
|
||||
{
|
||||
Model = new(progress);
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@ using System.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.CmdPal.Core.Common;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
@@ -18,9 +18,10 @@ public partial class ShellViewModel : ObservableObject,
|
||||
IRecipient<HandleCommandResultMessage>
|
||||
{
|
||||
private readonly IRootPageService _rootPageService;
|
||||
private readonly IAppHostService _appHostService;
|
||||
private readonly TaskScheduler _scheduler;
|
||||
private readonly AppExtensionHost _appHost;
|
||||
private readonly TaskScheduler _scheduler = TaskScheduler.FromCurrentSynchronizationContext();
|
||||
private readonly IPageViewModelFactoryService _pageViewModelFactory;
|
||||
private readonly ILogger _logger;
|
||||
private readonly Lock _invokeLock = new();
|
||||
private Task? _handleInvokeTask;
|
||||
|
||||
@@ -60,7 +61,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CoreLogger.LogError(ex.ToString());
|
||||
Log_Exception(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,18 +85,18 @@ public partial class ShellViewModel : ObservableObject,
|
||||
public PageViewModel NullPage { get; private set; }
|
||||
|
||||
public ShellViewModel(
|
||||
TaskScheduler scheduler,
|
||||
IRootPageService rootPageService,
|
||||
IPageViewModelFactoryService pageViewModelFactory,
|
||||
IAppHostService appHostService)
|
||||
AppExtensionHost appHost,
|
||||
ILogger<ShellViewModel> logger)
|
||||
{
|
||||
_pageViewModelFactory = pageViewModelFactory;
|
||||
_scheduler = scheduler;
|
||||
_rootPageService = rootPageService;
|
||||
_appHostService = appHostService;
|
||||
_appHost = appHost;
|
||||
_logger = logger;
|
||||
|
||||
NullPage = new NullPageViewModel(_scheduler, appHostService.GetDefaultHost());
|
||||
_currentPage = new LoadingPageViewModel(null, _scheduler, appHostService.GetDefaultHost());
|
||||
NullPage = new NullPageViewModel(_appHost, _logger);
|
||||
_currentPage = new LoadingPageViewModel(null, _appHost, _logger);
|
||||
|
||||
// Register to receive messages
|
||||
WeakReferenceMessenger.Default.Register<PerformCommandMessage>(this);
|
||||
@@ -162,7 +163,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
{
|
||||
if (viewModel.InitializeCommand.ExecutionTask.Exception is AggregateException ex)
|
||||
{
|
||||
CoreLogger.LogError(ex.ToString());
|
||||
Log_Exception(ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -180,7 +181,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CoreLogger.LogError(ex.ToString());
|
||||
Log_Exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +211,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CoreLogger.LogError(ex.ToString());
|
||||
Log_Exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +241,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CoreLogger.LogError(ex.ToString());
|
||||
Log_Exception(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -256,7 +257,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
return;
|
||||
}
|
||||
|
||||
var host = _appHostService.GetHostForCommand(message.Context, CurrentPage.ExtensionHost);
|
||||
var host = _appHost.GetHostForCommand(message.Context, CurrentPage.ExtensionHost);
|
||||
|
||||
_rootPageService.OnPerformCommand(message.Context, !CurrentPage.IsNested, host);
|
||||
|
||||
@@ -264,7 +265,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
{
|
||||
if (command is IPage page)
|
||||
{
|
||||
CoreLogger.LogDebug($"Navigating to page");
|
||||
Log_NavigateToPage();
|
||||
|
||||
var isMainPage = command == _rootPage;
|
||||
_isNested = !isMainPage;
|
||||
@@ -273,7 +274,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
var pageViewModel = _pageViewModelFactory.TryCreatePageViewModel(page, _isNested, host);
|
||||
if (pageViewModel is null)
|
||||
{
|
||||
CoreLogger.LogError($"Failed to create ViewModel for page {page.GetType().Name}");
|
||||
Log_FailedToCreateViewModel(page.GetType().Name);
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
@@ -303,7 +304,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
}
|
||||
else if (command is IInvokableCommand invokable)
|
||||
{
|
||||
CoreLogger.LogDebug($"Invoking command");
|
||||
Log_InvokingCommand();
|
||||
|
||||
WeakReferenceMessenger.Default.Send<BeginInvokeMessage>();
|
||||
StartInvoke(message, invokable, host);
|
||||
@@ -369,7 +370,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
}
|
||||
|
||||
var kind = result.Kind;
|
||||
CoreLogger.LogDebug($"handling {kind.ToString()}");
|
||||
Log_HandlingCommandResult(kind.ToString());
|
||||
|
||||
WeakReferenceMessenger.Default.Send<CmdPalInvokeResultMessage>(new(kind));
|
||||
switch (kind)
|
||||
@@ -460,4 +461,19 @@ public partial class ShellViewModel : ObservableObject,
|
||||
{
|
||||
_navigationCts?.Cancel();
|
||||
}
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error)]
|
||||
partial void Log_Exception(Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Navigating to page")]
|
||||
partial void Log_NavigateToPage();
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to create ViewModel for page {PageTypeName}")]
|
||||
partial void Log_FailedToCreateViewModel(string pageTypeName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Invoking command")]
|
||||
partial void Log_InvokingCommand();
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Handling {CommandResultKind}")]
|
||||
partial void Log_HandlingCommandResult(string commandResultKind);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
@@ -19,8 +20,8 @@ public partial class StatusMessageViewModel : ExtensionObjectViewModel
|
||||
|
||||
public bool HasProgress => Progress is not null;
|
||||
|
||||
public StatusMessageViewModel(IStatusMessage message, WeakReference<IPageContext> context)
|
||||
: base(context)
|
||||
public StatusMessageViewModel(IStatusMessage message, WeakReference<IPageContext> context, ILogger logger)
|
||||
: base(context, logger)
|
||||
{
|
||||
Model = new(message);
|
||||
}
|
||||
@@ -38,7 +39,7 @@ public partial class StatusMessageViewModel : ExtensionObjectViewModel
|
||||
var modelProgress = model.Progress;
|
||||
if (modelProgress is not null)
|
||||
{
|
||||
Progress = new(modelProgress, this.PageContext);
|
||||
Progress = new(modelProgress, this.PageContext, Logger);
|
||||
Progress.InitializeProperties();
|
||||
UpdateProperty(nameof(HasProgress));
|
||||
}
|
||||
@@ -78,7 +79,7 @@ public partial class StatusMessageViewModel : ExtensionObjectViewModel
|
||||
var modelProgress = model.Progress;
|
||||
if (modelProgress is not null)
|
||||
{
|
||||
Progress = new(modelProgress, this.PageContext);
|
||||
Progress = new(modelProgress, this.PageContext, Logger);
|
||||
Progress.InitializeProperties();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||
|
||||
public partial class TagViewModel(ITag _tag, WeakReference<IPageContext> context) : ExtensionObjectViewModel(context)
|
||||
public partial class TagViewModel(ITag _tag, WeakReference<IPageContext> context, ILogger logger) : ExtensionObjectViewModel(context, logger)
|
||||
{
|
||||
private readonly ExtensionObject<ITag> _tagModel = new(_tag);
|
||||
|
||||
|
||||
@@ -4,23 +4,20 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public partial class CommandPaletteContentPageViewModel : ContentPageViewModel
|
||||
public partial class CommandPaletteContentPageViewModel(IContentPage model, AppExtensionHost host, ILogger logger)
|
||||
: ContentPageViewModel(model, host, logger)
|
||||
{
|
||||
public CommandPaletteContentPageViewModel(IContentPage model, TaskScheduler scheduler, AppExtensionHost host)
|
||||
: base(model, scheduler, host)
|
||||
{
|
||||
}
|
||||
|
||||
public override ContentViewModel? ViewModelFromContent(IContent content, WeakReference<IPageContext> context)
|
||||
{
|
||||
ContentViewModel? viewModel = content switch
|
||||
{
|
||||
IFormContent form => new ContentFormViewModel(form, context),
|
||||
IMarkdownContent markdown => new ContentMarkdownViewModel(markdown, context),
|
||||
ITreeContent tree => new ContentTreeViewModel(tree, context),
|
||||
IFormContent form => new ContentFormViewModel(form, context, Logger),
|
||||
IMarkdownContent markdown => new ContentMarkdownViewModel(markdown, context, Logger),
|
||||
ITreeContent tree => new ContentTreeViewModel(tree, context, Logger),
|
||||
_ => null,
|
||||
};
|
||||
return viewModel;
|
||||
|
||||
@@ -5,29 +5,29 @@
|
||||
using Microsoft.CmdPal.Core.Common.Services;
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public sealed partial class CommandPaletteHost : AppExtensionHost, IExtensionHost
|
||||
{
|
||||
// Static singleton, so that we can access this from anywhere
|
||||
// Post MVVM - this should probably be like, a dependency injection thing.
|
||||
public static CommandPaletteHost Instance { get; } = new();
|
||||
|
||||
public IExtensionWrapper? Extension { get; }
|
||||
|
||||
private readonly ICommandProvider? _builtInProvider;
|
||||
|
||||
private CommandPaletteHost()
|
||||
public CommandPaletteHost(ILogger logger)
|
||||
: base(logger)
|
||||
{
|
||||
}
|
||||
|
||||
public CommandPaletteHost(IExtensionWrapper source)
|
||||
public CommandPaletteHost(IExtensionWrapper source, ILogger logger)
|
||||
: base(logger)
|
||||
{
|
||||
Extension = source;
|
||||
}
|
||||
|
||||
public CommandPaletteHost(ICommandProvider builtInProvider)
|
||||
public CommandPaletteHost(ICommandProvider builtInProvider, ILogger logger)
|
||||
: base(logger)
|
||||
{
|
||||
_builtInProvider = builtInProvider;
|
||||
}
|
||||
@@ -36,4 +36,15 @@ public sealed partial class CommandPaletteHost : AppExtensionHost, IExtensionHos
|
||||
{
|
||||
return Extension?.ExtensionDisplayName;
|
||||
}
|
||||
|
||||
public override AppExtensionHost GetHostForCommand(object? context, AppExtensionHost? currentHost)
|
||||
{
|
||||
AppExtensionHost? topLevelHost = null;
|
||||
if (context is TopLevelViewModel topLevelViewModel)
|
||||
{
|
||||
topLevelHost = topLevelViewModel.ExtensionHost;
|
||||
}
|
||||
|
||||
return topLevelHost ?? currentHost ?? this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,25 +4,27 @@
|
||||
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public class CommandPalettePageViewModelFactory
|
||||
: IPageViewModelFactoryService
|
||||
{
|
||||
private readonly TaskScheduler _scheduler;
|
||||
private readonly TaskScheduler _scheduler = TaskScheduler.FromCurrentSynchronizationContext();
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public CommandPalettePageViewModelFactory(TaskScheduler scheduler)
|
||||
public CommandPalettePageViewModelFactory(ILogger logger)
|
||||
{
|
||||
_scheduler = scheduler;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public PageViewModel? TryCreatePageViewModel(IPage page, bool nested, AppExtensionHost host)
|
||||
{
|
||||
return page switch
|
||||
{
|
||||
IListPage listPage => new ListViewModel(listPage, _scheduler, host) { IsNested = nested },
|
||||
IContentPage contentPage => new CommandPaletteContentPageViewModel(contentPage, _scheduler, host),
|
||||
IListPage listPage => new ListViewModel(listPage, _scheduler, host, _logger) { IsNested = nested },
|
||||
IContentPage contentPage => new CommandPaletteContentPageViewModel(contentPage, host, _logger),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,22 +2,23 @@
|
||||
// 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.Common.Services;
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public sealed class CommandProviderWrapper
|
||||
public sealed partial class CommandProviderWrapper
|
||||
{
|
||||
public bool IsExtension => Extension is not null;
|
||||
|
||||
private readonly bool isValid;
|
||||
private readonly ILogger _logger;
|
||||
private readonly AliasManager _aliasManager;
|
||||
private readonly HotkeyManager _hotKeyManager;
|
||||
|
||||
private readonly ExtensionObject<ICommandProvider> _commandProvider;
|
||||
|
||||
@@ -51,15 +52,18 @@ public sealed class CommandProviderWrapper
|
||||
}
|
||||
}
|
||||
|
||||
public CommandProviderWrapper(ICommandProvider provider, TaskScheduler mainThread)
|
||||
public CommandProviderWrapper(ICommandProvider provider, TaskScheduler mainThread, AliasManager aliasManager, HotkeyManager hotkeyManager, ILogger logger)
|
||||
{
|
||||
// This ctor is only used for in-proc builtin commands. So the Unsafe!
|
||||
// calls are pretty dang safe actually.
|
||||
_commandProvider = new(provider);
|
||||
_taskScheduler = mainThread;
|
||||
_logger = logger;
|
||||
_aliasManager = aliasManager;
|
||||
_hotKeyManager = hotkeyManager;
|
||||
|
||||
// Hook the extension back into us
|
||||
ExtensionHost = new CommandPaletteHost(provider);
|
||||
ExtensionHost = new CommandPaletteHost(provider, logger);
|
||||
_commandProvider.Unsafe!.InitializeWithHost(ExtensionHost);
|
||||
|
||||
_commandProvider.Unsafe!.ItemsChanged += CommandProvider_ItemsChanged;
|
||||
@@ -72,16 +76,20 @@ public sealed class CommandProviderWrapper
|
||||
|
||||
// Note: explicitly not InitializeProperties()ing the settings here. If
|
||||
// we do that, then we'd regress GH #38321
|
||||
Settings = new(provider.Settings, this, _taskScheduler);
|
||||
Settings = new(provider.Settings, this, _taskScheduler, _logger);
|
||||
|
||||
Logger.LogDebug($"Initialized command provider {ProviderId}");
|
||||
Log_CommandProviderInitialized(ProviderId);
|
||||
}
|
||||
|
||||
public CommandProviderWrapper(IExtensionWrapper extension, TaskScheduler mainThread)
|
||||
public CommandProviderWrapper(IExtensionWrapper extension, TaskScheduler mainThread, AliasManager aliasManager, HotkeyManager hotkeyManager, ILogger logger)
|
||||
{
|
||||
_taskScheduler = mainThread;
|
||||
_logger = logger;
|
||||
_aliasManager = aliasManager;
|
||||
_hotKeyManager = hotkeyManager;
|
||||
Extension = extension;
|
||||
ExtensionHost = new CommandPaletteHost(extension);
|
||||
|
||||
ExtensionHost = new CommandPaletteHost(extension, logger);
|
||||
if (!Extension.IsRunning())
|
||||
{
|
||||
throw new ArgumentException("You forgot to start the extension. This is a CmdPal error - we need to make sure to call StartExtensionAsync");
|
||||
@@ -106,13 +114,11 @@ public sealed class CommandProviderWrapper
|
||||
|
||||
isValid = true;
|
||||
|
||||
Logger.LogDebug($"Initialized extension command provider {Extension.PackageFamilyName}:{Extension.ExtensionUniqueId}");
|
||||
Log_ExtensionInitialized(Extension.PackageFamilyName, Extension.ExtensionUniqueId);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError("Failed to initialize CommandProvider for extension.");
|
||||
Logger.LogError($"Extension was {Extension!.PackageFamilyName}");
|
||||
Logger.LogError(e.ToString());
|
||||
Log_FailedToInitializeCommandProviderForExtension(Extension!.PackageFamilyName, e);
|
||||
}
|
||||
|
||||
isValid = true;
|
||||
@@ -123,7 +129,7 @@ public sealed class CommandProviderWrapper
|
||||
return settings.GetProviderSettings(this);
|
||||
}
|
||||
|
||||
public async Task LoadTopLevelCommands(IServiceProvider serviceProvider, WeakReference<IPageContext> pageContext)
|
||||
public async Task LoadTopLevelCommands(SettingsModel settingsModel, WeakReference<IPageContext> pageContext)
|
||||
{
|
||||
if (!isValid)
|
||||
{
|
||||
@@ -131,9 +137,7 @@ public sealed class CommandProviderWrapper
|
||||
return;
|
||||
}
|
||||
|
||||
var settings = serviceProvider.GetService<SettingsModel>()!;
|
||||
|
||||
IsActive = GetProviderSettings(settings).IsEnabled;
|
||||
IsActive = GetProviderSettings(settingsModel).IsEnabled;
|
||||
if (!IsActive)
|
||||
{
|
||||
return;
|
||||
@@ -165,30 +169,27 @@ public sealed class CommandProviderWrapper
|
||||
|
||||
// Note: explicitly not InitializeProperties()ing the settings here. If
|
||||
// we do that, then we'd regress GH #38321
|
||||
Settings = new(model.Settings, this, _taskScheduler);
|
||||
Settings = new(model.Settings, this, _taskScheduler, _logger);
|
||||
|
||||
// We do need to explicitly initialize commands though
|
||||
InitializeCommands(commands, fallbacks, serviceProvider, pageContext);
|
||||
InitializeCommands(commands, fallbacks, settingsModel, pageContext);
|
||||
|
||||
Logger.LogDebug($"Loaded commands from {DisplayName} ({ProviderId})");
|
||||
Log_LoadedCommandsFromExtension(DisplayName, ProviderId);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError("Failed to load commands from extension");
|
||||
Logger.LogError($"Extension was {Extension!.PackageFamilyName}");
|
||||
Logger.LogError(e.ToString());
|
||||
Log_FailedToLoadCommandsFromProvider(Extension!.PackageFamilyName, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeCommands(ICommandItem[] commands, IFallbackCommandItem[] fallbacks, IServiceProvider serviceProvider, WeakReference<IPageContext> pageContext)
|
||||
private void InitializeCommands(ICommandItem[] commands, IFallbackCommandItem[] fallbacks, SettingsModel settingsModel, WeakReference<IPageContext> pageContext)
|
||||
{
|
||||
var settings = serviceProvider.GetService<SettingsModel>()!;
|
||||
var providerSettings = GetProviderSettings(settings);
|
||||
var providerSettings = GetProviderSettings(settingsModel);
|
||||
|
||||
Func<ICommandItem?, bool, TopLevelViewModel> makeAndAdd = (ICommandItem? i, bool fallback) =>
|
||||
{
|
||||
CommandItemViewModel commandItemViewModel = new(new(i), pageContext);
|
||||
TopLevelViewModel topLevelViewModel = new(commandItemViewModel, fallback, ExtensionHost, ProviderId, settings, providerSettings, serviceProvider);
|
||||
CommandItemViewModel commandItemViewModel = new(new(i), pageContext, _logger);
|
||||
TopLevelViewModel topLevelViewModel = new(commandItemViewModel, fallback, ExtensionHost, ProviderId, settingsModel, providerSettings, _aliasManager, _hotKeyManager);
|
||||
topLevelViewModel.InitializeProperties();
|
||||
|
||||
return topLevelViewModel;
|
||||
@@ -211,12 +212,13 @@ public sealed class CommandProviderWrapper
|
||||
private void UnsafePreCacheApiAdditions(ICommandProvider2 provider)
|
||||
{
|
||||
var apiExtensions = provider.GetApiExtensionStubs();
|
||||
Logger.LogDebug($"Provider supports {apiExtensions.Length} extensions");
|
||||
Log_ProviderCount(apiExtensions.Length);
|
||||
|
||||
foreach (var a in apiExtensions)
|
||||
{
|
||||
if (a is IExtendedAttributesProvider command2)
|
||||
{
|
||||
Logger.LogDebug($"{ProviderId}: Found an IExtendedAttributesProvider");
|
||||
Log_IExtendedAttributesProviderFound(ProviderId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,4 +236,25 @@ public sealed class CommandProviderWrapper
|
||||
// In handling this, a call will be made to `LoadTopLevelCommands` to
|
||||
// retrieve the new items.
|
||||
this.CommandsChanged?.Invoke(this, args);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Initialized CommandProvider '{ProviderId}'")]
|
||||
partial void Log_CommandProviderInitialized(string providerId);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "{ProviderId}: Found an IExtendedAttributesProvider")]
|
||||
partial void Log_IExtendedAttributesProviderFound(string providerId);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Provider exposed {Count} API extensions")]
|
||||
partial void Log_ProviderCount(int count);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Initialized CommandProvider from extension '{PackageFamilyName}' ({ExtensionId})")]
|
||||
partial void Log_ExtensionInitialized(string packageFamilyName, string extensionId);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Loaded commands from {DisplayName} ({ProviderId})")]
|
||||
partial void Log_LoadedCommandsFromExtension(string displayName, string providerId);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to load commands from extension '{PackageFamilyName}'")]
|
||||
partial void Log_FailedToLoadCommandsFromProvider(string packageFamilyName, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to initialize CommandProvider for extension '{PackageFamilyName}'")]
|
||||
partial void Log_FailedToInitializeCommandProviderForExtension(string packageFamilyName, Exception exception);
|
||||
}
|
||||
|
||||
@@ -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.Common;
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings, CommandProviderWrapper provider, TaskScheduler mainThread)
|
||||
public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings, CommandProviderWrapper provider, TaskScheduler mainThread, ILogger logger)
|
||||
{
|
||||
private readonly ExtensionObject<ICommandSettings> _model = new(_unsafeSettings);
|
||||
|
||||
@@ -31,7 +31,7 @@ public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings,
|
||||
|
||||
if (model.SettingsPage is not null)
|
||||
{
|
||||
SettingsPage = new CommandPaletteContentPageViewModel(model.SettingsPage, mainThread, provider.ExtensionHost);
|
||||
SettingsPage = new CommandPaletteContentPageViewModel(model.SettingsPage, provider.ExtensionHost, logger);
|
||||
SettingsPage.InitializeProperties();
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings,
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CoreLogger.LogError($"Failed to load settings page", ex: ex);
|
||||
Log_FailedToLoadSettingsPage(ex);
|
||||
}
|
||||
|
||||
Initialized = true;
|
||||
@@ -58,4 +58,7 @@ public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings,
|
||||
TaskCreationOptions.None,
|
||||
mainThread);
|
||||
}
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to load settings page")]
|
||||
partial void Log_FailedToLoadSettingsPage(Exception ex);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ public partial class MainListPage : DynamicListPage,
|
||||
"com.microsoft.cmdpal.builtin.datetime",
|
||||
];
|
||||
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly TopLevelCommandManager _tlcManager;
|
||||
private List<Scored<IListItem>>? _filteredItems;
|
||||
private List<Scored<IListItem>>? _filteredApps;
|
||||
@@ -53,14 +52,13 @@ public partial class MainListPage : DynamicListPage,
|
||||
|
||||
private CancellationTokenSource? _cancellationTokenSource;
|
||||
|
||||
public MainListPage(IServiceProvider serviceProvider)
|
||||
public MainListPage(TopLevelCommandManager topLevelCommandManager, SettingsModel settingsModel)
|
||||
{
|
||||
Title = Resources.builtin_home_name;
|
||||
Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.scale-200.png");
|
||||
PlaceholderText = Properties.Resources.builtin_main_list_page_searchbar_placeholder;
|
||||
_serviceProvider = serviceProvider;
|
||||
|
||||
_tlcManager = _serviceProvider.GetService<TopLevelCommandManager>()!;
|
||||
_tlcManager = topLevelCommandManager;
|
||||
_tlcManager.PropertyChanged += TlcManager_PropertyChanged;
|
||||
_tlcManager.TopLevelCommands.CollectionChanged += Commands_CollectionChanged;
|
||||
|
||||
@@ -78,7 +76,7 @@ public partial class MainListPage : DynamicListPage,
|
||||
WeakReferenceMessenger.Default.Register<ClearSearchMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<UpdateFallbackItemsMessage>(this);
|
||||
|
||||
var settings = _serviceProvider.GetService<SettingsModel>()!;
|
||||
var settings = settingsModel;
|
||||
settings.SettingsChanged += SettingsChangedHandler;
|
||||
HotReloadSettings(settings);
|
||||
_includeApps = _tlcManager.IsProviderActive(AllAppsCommandProvider.WellKnownId);
|
||||
|
||||
@@ -7,19 +7,26 @@ using System.Text.Json;
|
||||
using AdaptiveCards.ObjectModel.WinUI3;
|
||||
using AdaptiveCards.Templating;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Windows.Data.Json;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPageContext> context) :
|
||||
ContentViewModel(context)
|
||||
public partial class ContentFormViewModel : ContentViewModel
|
||||
{
|
||||
private readonly ExtensionObject<IFormContent> _formModel = new(_form);
|
||||
private readonly ExtensionObject<IFormContent> _formModel;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public ContentFormViewModel(IFormContent _form, WeakReference<IPageContext> context, ILogger logger)
|
||||
: base(context, logger)
|
||||
{
|
||||
_formModel = new(_form);
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
// Remember - "observable" properties from the model (via PropChanged)
|
||||
// cannot be marked [ObservableProperty]
|
||||
@@ -38,7 +45,8 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
|
||||
string templateJson,
|
||||
string dataJson,
|
||||
out AdaptiveCardParseResult? card,
|
||||
out Exception? error)
|
||||
out Exception? error,
|
||||
ILogger logger)
|
||||
{
|
||||
card = null;
|
||||
error = null;
|
||||
@@ -52,7 +60,7 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Error building card from template", ex);
|
||||
Log_ErrorBuildindCard(logger, ex);
|
||||
error = ex;
|
||||
return false;
|
||||
}
|
||||
@@ -70,7 +78,7 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
|
||||
StateJson = model.StateJson;
|
||||
DataJson = model.DataJson;
|
||||
|
||||
if (TryBuildCard(TemplateJson, DataJson, out var builtCard, out var renderingError))
|
||||
if (TryBuildCard(TemplateJson, DataJson, out var builtCard, out var renderingError, _logger))
|
||||
{
|
||||
Card = builtCard;
|
||||
UpdateProperty(nameof(Card));
|
||||
@@ -87,7 +95,7 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
|
||||
}
|
||||
""";
|
||||
|
||||
if (TryBuildCard(ErrorCardJson, errorPayload, out var errorCard, out var _))
|
||||
if (TryBuildCard(ErrorCardJson, errorPayload, out var errorCard, out var _, _logger))
|
||||
{
|
||||
Card = errorCard;
|
||||
UpdateProperty(nameof(Card));
|
||||
@@ -173,4 +181,7 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
|
||||
]
|
||||
}
|
||||
""";
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Error building adaptive card for form.")]
|
||||
static partial void Log_ErrorBuildindCard(ILogger logger, Exception ex);
|
||||
}
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public partial class ContentMarkdownViewModel(IMarkdownContent _markdown, WeakReference<IPageContext> context) :
|
||||
ContentViewModel(context)
|
||||
public partial class ContentMarkdownViewModel(IMarkdownContent _markdown, WeakReference<IPageContext> context, ILogger logger) :
|
||||
ContentViewModel(context, logger)
|
||||
{
|
||||
public ExtensionObject<IMarkdownContent> Model { get; } = new(_markdown);
|
||||
|
||||
|
||||
@@ -7,11 +7,12 @@ using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPageContext> context) :
|
||||
ContentViewModel(context)
|
||||
public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPageContext> context, ILogger logger) :
|
||||
ContentViewModel(context, logger)
|
||||
{
|
||||
public ExtensionObject<ITreeContent> Model { get; } = new(_tree);
|
||||
|
||||
@@ -55,9 +56,9 @@ public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPag
|
||||
{
|
||||
ContentViewModel? viewModel = content switch
|
||||
{
|
||||
IFormContent form => new ContentFormViewModel(form, context),
|
||||
IMarkdownContent markdown => new ContentMarkdownViewModel(markdown, context),
|
||||
ITreeContent tree => new ContentTreeViewModel(tree, context),
|
||||
IFormContent form => new ContentFormViewModel(form, context, Logger),
|
||||
IMarkdownContent markdown => new ContentMarkdownViewModel(markdown, context, Logger),
|
||||
ITreeContent tree => new ContentTreeViewModel(tree, context, Logger),
|
||||
_ => null,
|
||||
};
|
||||
return viewModel;
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// 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.Common.Services;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.ApplicationModel.AppExtensions;
|
||||
using Windows.Foundation;
|
||||
@@ -22,6 +22,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
|
||||
private static readonly Lock _lock = new();
|
||||
private readonly SemaphoreSlim _getInstalledExtensionsLock = new(1, 1);
|
||||
private readonly SemaphoreSlim _getInstalledWidgetsLock = new(1, 1);
|
||||
private readonly ILogger _logger;
|
||||
|
||||
// private readonly ILocalSettingsService _localSettingsService;
|
||||
private bool _disposedValue;
|
||||
@@ -32,8 +33,9 @@ public partial class ExtensionService : IExtensionService, IDisposable
|
||||
private static readonly List<IExtensionWrapper> _installedExtensions = [];
|
||||
private static readonly List<IExtensionWrapper> _enabledExtensions = [];
|
||||
|
||||
public ExtensionService()
|
||||
public ExtensionService(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_catalog.PackageInstalling += Catalog_PackageInstalling;
|
||||
_catalog.PackageUninstalling += Catalog_PackageUninstalling;
|
||||
_catalog.PackageUpdating += Catalog_PackageUpdating;
|
||||
@@ -92,14 +94,14 @@ public partial class ExtensionService : IExtensionService, IDisposable
|
||||
var extension = isCmdPalExtensionResult.Extension;
|
||||
if (isExtension && extension is not null)
|
||||
{
|
||||
CommandPaletteHost.Instance.DebugLog($"Installed new extension app {extension.DisplayName}");
|
||||
Log_ExtensionInstalled(extension.DisplayName);
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await _getInstalledExtensionsLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
var wrappers = await CreateWrappersForExtension(extension);
|
||||
var wrappers = await CreateWrappersForExtension(extension, _logger);
|
||||
|
||||
UpdateExtensionsListsFromWrappers(wrappers);
|
||||
|
||||
@@ -120,7 +122,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
|
||||
{
|
||||
if (extension.PackageFullName == package.Id.FullName)
|
||||
{
|
||||
CommandPaletteHost.Instance.DebugLog($"Uninstalled extension app {extension.PackageDisplayName}");
|
||||
Log_ExtensionUninstalled(extension.PackageDisplayName);
|
||||
|
||||
removedExtensions.Add(extension);
|
||||
}
|
||||
@@ -199,7 +201,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
|
||||
var extensions = await GetInstalledAppExtensionsAsync();
|
||||
foreach (var extension in extensions)
|
||||
{
|
||||
var wrappers = await CreateWrappersForExtension(extension);
|
||||
var wrappers = await CreateWrappersForExtension(extension, _logger);
|
||||
UpdateExtensionsListsFromWrappers(wrappers);
|
||||
}
|
||||
}
|
||||
@@ -233,7 +235,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<List<ExtensionWrapper>> CreateWrappersForExtension(AppExtension extension)
|
||||
private static async Task<List<ExtensionWrapper>> CreateWrappersForExtension(AppExtension extension, ILogger logger)
|
||||
{
|
||||
var (cmdPalProvider, classIds) = await GetCmdPalExtensionPropertiesAsync(extension);
|
||||
|
||||
@@ -245,14 +247,14 @@ public partial class ExtensionService : IExtensionService, IDisposable
|
||||
List<ExtensionWrapper> wrappers = [];
|
||||
foreach (var classId in classIds)
|
||||
{
|
||||
var extensionWrapper = CreateExtensionWrapper(extension, cmdPalProvider, classId);
|
||||
var extensionWrapper = CreateExtensionWrapper(extension, cmdPalProvider, classId, logger);
|
||||
wrappers.Add(extensionWrapper);
|
||||
}
|
||||
|
||||
return wrappers;
|
||||
}
|
||||
|
||||
private static ExtensionWrapper CreateExtensionWrapper(AppExtension extension, IPropertySet cmdPalProvider, string classId)
|
||||
private static ExtensionWrapper CreateExtensionWrapper(AppExtension extension, IPropertySet cmdPalProvider, string classId, ILogger logger)
|
||||
{
|
||||
var extensionWrapper = new ExtensionWrapper(extension, classId);
|
||||
|
||||
@@ -269,7 +271,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
|
||||
else
|
||||
{
|
||||
// log warning that extension declared unsupported extension interface
|
||||
CommandPaletteHost.Instance.DebugLog($"Extension {extension.DisplayName} declared an unsupported interface: {supportedInterface.Key}");
|
||||
Log_InvalidExtensionInterface(logger, extension.DisplayName, supportedInterface.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -288,7 +290,8 @@ public partial class ExtensionService : IExtensionService, IDisposable
|
||||
var installedExtensions = await GetInstalledExtensionsAsync();
|
||||
foreach (var installedExtension in installedExtensions)
|
||||
{
|
||||
Logger.LogDebug($"Signaling dispose to {installedExtension.ExtensionUniqueId}");
|
||||
Log_SignalingDispose(installedExtension.ExtensionUniqueId);
|
||||
|
||||
try
|
||||
{
|
||||
if (installedExtension.IsRunning())
|
||||
@@ -298,7 +301,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to send dispose signal to extension {installedExtension.ExtensionUniqueId}", ex);
|
||||
Log_ErrorSignalingDispose(installedExtension.ExtensionUniqueId, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,6 +403,21 @@ public partial class ExtensionService : IExtensionService, IDisposable
|
||||
_enabledExtensions.Remove(extension.First());
|
||||
}
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Information, Message = "Installed new extension app {ExtensionName}")]
|
||||
partial void Log_ExtensionInstalled(string extensionName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Information, Message = "Uninstalled extension app {ExtensionName}")]
|
||||
partial void Log_ExtensionUninstalled(string extensionName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Signaling dispose to {ExtensionUniqueId}")]
|
||||
partial void Log_SignalingDispose(string extensionUniqueId);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to send dispose signal to extension {ExtensionUniqueId}")]
|
||||
partial void Log_ErrorSignalingDispose(string extensionUniqueId, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Warning, Message = "Extension {ExtensionName} declared unsupported extension interface: {InterfaceName}")]
|
||||
static partial void Log_InvalidExtensionInterface(ILogger logger, string extensionName, string interfaceName);
|
||||
|
||||
/*
|
||||
///// <inheritdoc cref="IExtensionService.DisableExtensionIfWindowsFeatureNotAvailable(IExtensionWrapper)"/>
|
||||
//public async Task<bool> DisableExtensionIfWindowsFeatureNotAvailable(IExtensionWrapper extension)
|
||||
|
||||
@@ -8,14 +8,13 @@ using System.Diagnostics;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Core.Common.Helpers;
|
||||
using Microsoft.CmdPal.Core.Common.Services;
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CmdPal.UI.ViewModels.Messages;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
@@ -24,8 +23,14 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
IPageContext,
|
||||
IDisposable
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly TaskScheduler _taskScheduler;
|
||||
private readonly TaskScheduler _taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
|
||||
private readonly ILogger _logger;
|
||||
private readonly AppExtensionHost _commandPaletteHost;
|
||||
private readonly IExtensionService _extensionService;
|
||||
private readonly IEnumerable<ICommandProvider> _builtInProviders;
|
||||
private readonly SettingsModel _settingsModel;
|
||||
private readonly AliasManager _aliasManager;
|
||||
private readonly HotkeyManager _hotkeyManager;
|
||||
|
||||
private readonly List<CommandProviderWrapper> _builtInCommands = [];
|
||||
private readonly List<CommandProviderWrapper> _extensionCommandProviders = [];
|
||||
@@ -34,10 +39,22 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
|
||||
TaskScheduler IPageContext.Scheduler => _taskScheduler;
|
||||
|
||||
public TopLevelCommandManager(IServiceProvider serviceProvider)
|
||||
public TopLevelCommandManager(
|
||||
AppExtensionHost commandPaletteHost,
|
||||
IExtensionService extensionService,
|
||||
IEnumerable<ICommandProvider> builtInProviders,
|
||||
SettingsModel settingsModel,
|
||||
AliasManager aliasManager,
|
||||
HotkeyManager hotkeyManager,
|
||||
ILogger logger)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_taskScheduler = _serviceProvider.GetService<TaskScheduler>()!;
|
||||
_logger = logger;
|
||||
_commandPaletteHost = commandPaletteHost;
|
||||
_extensionService = extensionService;
|
||||
_builtInProviders = builtInProviders;
|
||||
_settingsModel = settingsModel;
|
||||
_aliasManager = aliasManager;
|
||||
_hotkeyManager = hotkeyManager;
|
||||
WeakReferenceMessenger.Default.Register<ReloadCommandsMessage>(this);
|
||||
_reloadCommandsGate = new(ReloadAllCommandsAsyncCore);
|
||||
}
|
||||
@@ -70,10 +87,9 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
|
||||
// Load built-In commands first. These are all in-proc, and
|
||||
// owned by our ServiceProvider.
|
||||
var builtInCommands = _serviceProvider.GetServices<ICommandProvider>();
|
||||
foreach (var provider in builtInCommands)
|
||||
foreach (var provider in _builtInProviders)
|
||||
{
|
||||
CommandProviderWrapper wrapper = new(provider, _taskScheduler);
|
||||
CommandProviderWrapper wrapper = new(provider, _taskScheduler, _aliasManager, _hotkeyManager, _logger);
|
||||
lock (_commandProvidersLock)
|
||||
{
|
||||
_builtInCommands.Add(wrapper);
|
||||
@@ -91,7 +107,7 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
|
||||
s.Stop();
|
||||
|
||||
Logger.LogDebug($"Loading built-ins took {s.ElapsedMilliseconds}ms");
|
||||
Log_BuiltInsLoaded(s.ElapsedMilliseconds);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -101,7 +117,7 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
{
|
||||
WeakReference<IPageContext> weakSelf = new(this);
|
||||
|
||||
await commandProvider.LoadTopLevelCommands(_serviceProvider, weakSelf);
|
||||
await commandProvider.LoadTopLevelCommands(_settingsModel, weakSelf);
|
||||
|
||||
var commands = await Task.Factory.StartNew(
|
||||
() =>
|
||||
@@ -149,7 +165,7 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
private async Task UpdateCommandsForProvider(CommandProviderWrapper sender, IItemsChangedEventArgs args)
|
||||
{
|
||||
WeakReference<IPageContext> weakSelf = new(this);
|
||||
await sender.LoadTopLevelCommands(_serviceProvider, weakSelf);
|
||||
await sender.LoadTopLevelCommands(_settingsModel, weakSelf);
|
||||
|
||||
List<TopLevelViewModel> newItems = [.. sender.TopLevelItems];
|
||||
foreach (var i in sender.FallbackItems)
|
||||
@@ -216,8 +232,7 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
private async Task ReloadAllCommandsAsyncCore(CancellationToken cancellationToken)
|
||||
{
|
||||
IsLoading = true;
|
||||
var extensionService = _serviceProvider.GetService<IExtensionService>()!;
|
||||
await extensionService.SignalStopExtensionsAsync();
|
||||
await _extensionService.SignalStopExtensionsAsync();
|
||||
|
||||
lock (TopLevelCommands)
|
||||
{
|
||||
@@ -238,12 +253,10 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
[RelayCommand]
|
||||
public async Task<bool> LoadExtensionsAsync()
|
||||
{
|
||||
var extensionService = _serviceProvider.GetService<IExtensionService>()!;
|
||||
_extensionService.OnExtensionAdded -= ExtensionService_OnExtensionAdded;
|
||||
_extensionService.OnExtensionRemoved -= ExtensionService_OnExtensionRemoved;
|
||||
|
||||
extensionService.OnExtensionAdded -= ExtensionService_OnExtensionAdded;
|
||||
extensionService.OnExtensionRemoved -= ExtensionService_OnExtensionRemoved;
|
||||
|
||||
var extensions = (await extensionService.GetInstalledExtensionsAsync()).ToImmutableList();
|
||||
var extensions = (await _extensionService.GetInstalledExtensionsAsync()).ToImmutableList();
|
||||
lock (_commandProvidersLock)
|
||||
{
|
||||
_extensionCommandProviders.Clear();
|
||||
@@ -254,8 +267,8 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
await StartExtensionsAndGetCommands(extensions);
|
||||
}
|
||||
|
||||
extensionService.OnExtensionAdded += ExtensionService_OnExtensionAdded;
|
||||
extensionService.OnExtensionRemoved += ExtensionService_OnExtensionRemoved;
|
||||
_extensionService.OnExtensionAdded += ExtensionService_OnExtensionAdded;
|
||||
_extensionService.OnExtensionRemoved += ExtensionService_OnExtensionRemoved;
|
||||
|
||||
IsLoading = false;
|
||||
|
||||
@@ -310,20 +323,20 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
}
|
||||
|
||||
timer.Stop();
|
||||
Logger.LogDebug($"Loading extensions took {timer.ElapsedMilliseconds} ms");
|
||||
Log_ExtensionsLoaded(timer.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
private async Task<CommandProviderWrapper?> StartExtensionWithTimeoutAsync(IExtensionWrapper extension)
|
||||
{
|
||||
Logger.LogDebug($"Starting {extension.PackageFullName}");
|
||||
Log_StartingExtension(extension.PackageFullName);
|
||||
try
|
||||
{
|
||||
await extension.StartExtensionAsync().WaitAsync(TimeSpan.FromSeconds(10));
|
||||
return new CommandProviderWrapper(extension, _taskScheduler);
|
||||
return new CommandProviderWrapper(extension, _taskScheduler, _aliasManager, _hotkeyManager, _logger);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to start extension {extension.PackageFullName}: {ex}");
|
||||
Log_FailedToStartExtension(extension.PackageFullName, ex);
|
||||
return null; // Return null for failed extensions
|
||||
}
|
||||
}
|
||||
@@ -336,11 +349,11 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
Logger.LogError($"Loading commands from {wrapper!.ExtensionHost?.Extension?.PackageFullName} timed out");
|
||||
Log_LoadingCommandsTimedOut(wrapper!.ExtensionHost?.Extension?.PackageFullName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to load commands for extension {wrapper!.ExtensionHost?.Extension?.PackageFullName}: {ex}");
|
||||
Log_FailedToLoadCommandsForExtension(wrapper!.ExtensionHost?.Extension?.PackageFullName, ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -414,7 +427,7 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
void IPageContext.ShowException(Exception ex, string? extensionHint)
|
||||
{
|
||||
var message = DiagnosticsHelper.BuildExceptionMessage(ex, extensionHint ?? "TopLevelCommandManager");
|
||||
CommandPaletteHost.Instance.Log(message);
|
||||
_commandPaletteHost.Log(message);
|
||||
}
|
||||
|
||||
internal bool IsProviderActive(string id)
|
||||
@@ -431,4 +444,22 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
_reloadCommandsGate.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Loading built-ins took {ElapsedMilliseconds}ms")]
|
||||
partial void Log_BuiltInsLoaded(long elapsedMilliseconds);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Loading extensions took {ElapsedMilliseconds}ms")]
|
||||
partial void Log_ExtensionsLoaded(long elapsedMilliseconds);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to load commands for extension {ExtensionName}")]
|
||||
partial void Log_FailedToLoadCommandsForExtension(string? extensionName, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Warning, Message = "Loading commands for extension {ExtensionName} timed out")]
|
||||
partial void Log_LoadingCommandsTimedOut(string? extensionName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to start extension {ExtensionName}")]
|
||||
partial void Log_FailedToStartExtension(string extensionName, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Starting extension {ExtensionName}")]
|
||||
partial void Log_StartingExtension(string extensionName);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ using Microsoft.CmdPal.UI.ViewModels.Messages;
|
||||
using Microsoft.CmdPal.UI.ViewModels.Settings;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Windows.Foundation;
|
||||
using WyHash;
|
||||
|
||||
@@ -22,7 +21,8 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
|
||||
{
|
||||
private readonly SettingsModel _settings;
|
||||
private readonly ProviderSettings _providerSettings;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly HotkeyManager _hotKeyManager;
|
||||
private readonly AliasManager _aliasManager;
|
||||
private readonly CommandItemViewModel _commandItemViewModel;
|
||||
|
||||
private readonly string _commandProviderId;
|
||||
@@ -99,7 +99,7 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
|
||||
get => _hotkey;
|
||||
set
|
||||
{
|
||||
_serviceProvider.GetService<HotkeyManager>()!.UpdateHotkey(Id, value);
|
||||
_hotKeyManager.UpdateHotkey(Id, value);
|
||||
UpdateHotkey();
|
||||
UpdateTags();
|
||||
Save();
|
||||
@@ -177,9 +177,11 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
|
||||
string commandProviderId,
|
||||
SettingsModel settings,
|
||||
ProviderSettings providerSettings,
|
||||
IServiceProvider serviceProvider)
|
||||
AliasManager aliasManager,
|
||||
HotkeyManager hotkeyManager)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_hotKeyManager = hotkeyManager;
|
||||
_aliasManager = aliasManager;
|
||||
_settings = settings;
|
||||
_providerSettings = providerSettings;
|
||||
_commandProviderId = commandProviderId;
|
||||
@@ -268,16 +270,15 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
|
||||
? null
|
||||
: new CommandAlias(Alias.Alias, Alias.CommandId, Alias.IsDirect);
|
||||
|
||||
_serviceProvider.GetService<AliasManager>()!.UpdateAlias(Id, commandAlias);
|
||||
_aliasManager.UpdateAlias(Id, commandAlias);
|
||||
UpdateTags();
|
||||
}
|
||||
|
||||
private void FetchAliasFromAliasManager()
|
||||
{
|
||||
var am = _serviceProvider.GetService<AliasManager>();
|
||||
if (am is not null)
|
||||
if (_aliasManager is not null)
|
||||
{
|
||||
var commandAlias = am.AliasFromId(Id);
|
||||
var commandAlias = _aliasManager.AliasFromId(Id);
|
||||
if (commandAlias is not null)
|
||||
{
|
||||
// Decouple from the alias manager alias object
|
||||
|
||||
@@ -2,33 +2,6 @@
|
||||
// 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.Common;
|
||||
using Microsoft.CmdPal.Core.Common.Helpers;
|
||||
using Microsoft.CmdPal.Core.Common.Services;
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CmdPal.Ext.Apps;
|
||||
using Microsoft.CmdPal.Ext.Bookmarks;
|
||||
using Microsoft.CmdPal.Ext.Calc;
|
||||
using Microsoft.CmdPal.Ext.ClipboardHistory;
|
||||
using Microsoft.CmdPal.Ext.Indexer;
|
||||
using Microsoft.CmdPal.Ext.Registry;
|
||||
using Microsoft.CmdPal.Ext.Shell;
|
||||
using Microsoft.CmdPal.Ext.System;
|
||||
using Microsoft.CmdPal.Ext.TimeDate;
|
||||
using Microsoft.CmdPal.Ext.WebSearch;
|
||||
using Microsoft.CmdPal.Ext.WindowsServices;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings;
|
||||
using Microsoft.CmdPal.Ext.WindowsTerminal;
|
||||
using Microsoft.CmdPal.Ext.WindowWalker;
|
||||
using Microsoft.CmdPal.Ext.WinGet;
|
||||
using Microsoft.CmdPal.UI.Helpers;
|
||||
using Microsoft.CmdPal.UI.ViewModels;
|
||||
using Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;
|
||||
using Microsoft.CmdPal.UI.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
@@ -40,8 +13,6 @@ namespace Microsoft.CmdPal.UI;
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
private readonly GlobalErrorHandler _globalErrorHandler = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current <see cref="App"/> instance in use.
|
||||
/// </summary>
|
||||
@@ -49,43 +20,16 @@ public partial class App : Application
|
||||
|
||||
public Window? AppWindow { get; private set; }
|
||||
|
||||
public ETWTrace EtwTrace { get; private set; } = new ETWTrace();
|
||||
|
||||
/// <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()
|
||||
public App(MainWindow mainWindow)
|
||||
{
|
||||
#if !CMDPAL_DISABLE_GLOBAL_ERROR_HANDLER
|
||||
_globalErrorHandler.Register(this);
|
||||
#endif
|
||||
|
||||
Services = ConfigureServices();
|
||||
AppWindow = mainWindow;
|
||||
|
||||
this.InitializeComponent();
|
||||
|
||||
// Ensure types used in XAML are preserved for AOT compilation
|
||||
TypePreservation.PreserveTypes();
|
||||
|
||||
NativeEventWaiter.WaitForEventLoop(
|
||||
"Local\\PowerToysCmdPal-ExitEvent-eb73f6be-3f22-4b36-aee3-62924ba40bfd", () =>
|
||||
{
|
||||
EtwTrace?.Dispose();
|
||||
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>
|
||||
@@ -94,84 +38,7 @@ public partial class App : Application
|
||||
/// <param name="args">Details about the launch request and process.</param>
|
||||
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
|
||||
{
|
||||
AppWindow = new MainWindow();
|
||||
|
||||
var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
|
||||
((MainWindow)AppWindow).HandleLaunchNonUI(activatedEventArgs);
|
||||
}
|
||||
|
||||
/// <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.
|
||||
var allApps = new AllAppsCommandProvider();
|
||||
var files = new IndexerCommandsProvider();
|
||||
files.SuppressFallbackWhen(ShellCommandsProvider.SuppressFileFallbackIf);
|
||||
services.AddSingleton<ICommandProvider>(allApps);
|
||||
|
||||
services.AddSingleton<ICommandProvider, ShellCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, CalculatorCommandProvider>();
|
||||
services.AddSingleton<ICommandProvider>(files);
|
||||
services.AddSingleton<ICommandProvider, BookmarksCommandProvider>(_ => BookmarksCommandProvider.CreateWithDefaultStore());
|
||||
|
||||
services.AddSingleton<ICommandProvider, WindowWalkerCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, WebSearchCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, ClipboardHistoryCommandsProvider>();
|
||||
|
||||
// GH #38440: Users might not have WinGet installed! Or they might have
|
||||
// a ridiculously old version. Or might be running as admin.
|
||||
// We shouldn't explode in the App ctor if we fail to instantiate an
|
||||
// instance of PackageManager, which will happen in the static ctor
|
||||
// for WinGetStatics
|
||||
try
|
||||
{
|
||||
var winget = new WinGetExtensionCommandsProvider();
|
||||
var callback = allApps.LookupApp;
|
||||
winget.SetAllLookup(callback);
|
||||
services.AddSingleton<ICommandProvider>(winget);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Couldn't load winget");
|
||||
Logger.LogError(ex.ToString());
|
||||
}
|
||||
|
||||
services.AddSingleton<ICommandProvider, WindowsTerminalCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, WindowsSettingsCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, RegistryCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, WindowsServicesCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, BuiltInsCommandProvider>();
|
||||
services.AddSingleton<ICommandProvider, TimeDateCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, SystemCommandExtensionProvider>();
|
||||
|
||||
// Models
|
||||
services.AddSingleton<TopLevelCommandManager>();
|
||||
services.AddSingleton<AliasManager>();
|
||||
services.AddSingleton<HotkeyManager>();
|
||||
var sm = SettingsModel.LoadSettings();
|
||||
services.AddSingleton(sm);
|
||||
var state = AppStateModel.LoadState();
|
||||
services.AddSingleton(state);
|
||||
services.AddSingleton<IExtensionService, ExtensionService>();
|
||||
services.AddSingleton<TrayIconService>();
|
||||
services.AddSingleton<IRunHistoryService, RunHistoryService>();
|
||||
|
||||
services.AddSingleton<IRootPageService, PowerToysRootPageService>();
|
||||
services.AddSingleton<IAppHostService, PowerToysAppHostService>();
|
||||
services.AddSingleton<ITelemetryService, TelemetryForwarder>();
|
||||
|
||||
// ViewModels
|
||||
services.AddSingleton<ShellViewModel>();
|
||||
services.AddSingleton<IPageViewModelFactoryService, CommandPalettePageViewModelFactory>();
|
||||
|
||||
return services.BuildServiceProvider();
|
||||
((MainWindow)AppWindow!).HandleLaunchNonUI(activatedEventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public sealed partial class CommandBar : UserControl,
|
||||
IRecipient<TryCommandKeybindingMessage>,
|
||||
ICurrentPageAware
|
||||
{
|
||||
public CommandBarViewModel ViewModel { get; } = new();
|
||||
public CommandBarViewModel ViewModel { get; set; }
|
||||
|
||||
public PageViewModel? CurrentPageViewModel
|
||||
{
|
||||
@@ -32,9 +32,10 @@ public sealed partial class CommandBar : UserControl,
|
||||
public static readonly DependencyProperty CurrentPageViewModelProperty =
|
||||
DependencyProperty.Register(nameof(CurrentPageViewModel), typeof(PageViewModel), typeof(CommandBar), new PropertyMetadata(null));
|
||||
|
||||
public CommandBar()
|
||||
public CommandBar(CommandBarViewModel commandBarViewModel)
|
||||
{
|
||||
this.InitializeComponent();
|
||||
ViewModel = commandBarViewModel;
|
||||
|
||||
// RegisterAll isn't AOT compatible
|
||||
WeakReferenceMessenger.Default.Register<OpenContextMenuMessage>(this);
|
||||
|
||||
@@ -21,6 +21,7 @@ public sealed partial class ContextMenu : UserControl,
|
||||
IRecipient<UpdateCommandBarMessage>,
|
||||
IRecipient<TryCommandKeybindingMessage>
|
||||
{
|
||||
// Fix for CS8618: Mark ViewModel property as required to ensure it is initialized by the constructor.
|
||||
public ContextMenuViewModel ViewModel { get; } = new();
|
||||
|
||||
public ContextMenu()
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class BeginInvoke : EventBase, IEvent
|
||||
public class BeginInvokeEvent : TelemetryEventBase
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public BeginInvoke()
|
||||
public BeginInvokeEvent()
|
||||
{
|
||||
EventName = "CmdPal_BeginInvoke";
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class CmdPalDismissedOnLostFocus : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class CmdPalProcessStarted : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
@@ -4,18 +4,18 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class ColdLaunch : EventBase, IEvent
|
||||
public class ColdLaunchEvent : TelemetryEventBase
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public ColdLaunch()
|
||||
public ColdLaunchEvent()
|
||||
{
|
||||
EventName = "CmdPal_ColdLaunch";
|
||||
}
|
||||
@@ -4,15 +4,19 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class CmdPalDismissedOnEsc : EventBase, IEvent
|
||||
public class DismissedOnEscEvent : TelemetryEventBase
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public DismissedOnEscEvent()
|
||||
{
|
||||
EventName = "CmdPal_DismissedOnEsc";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class DismissedOnLostFocusEvent : TelemetryEventBase
|
||||
{
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public DismissedOnLostFocusEvent()
|
||||
{
|
||||
EventName = "CmdPal_DismissedOnLostFocus";
|
||||
}
|
||||
}
|
||||
@@ -4,22 +4,22 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class CmdPalHotkeySummoned : EventBase, IEvent
|
||||
public class HotkeySummonedEvent : TelemetryEventBase
|
||||
{
|
||||
public bool Global { get; set; }
|
||||
|
||||
public CmdPalHotkeySummoned(bool global)
|
||||
public HotkeySummonedEvent(bool global)
|
||||
{
|
||||
Global = global;
|
||||
EventName = "CmdPal_HotkeySummoned";
|
||||
}
|
||||
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
@@ -4,22 +4,23 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class CmdPalInvokeResult : EventBase, IEvent
|
||||
public class InvokeResultEvent : TelemetryEventBase
|
||||
{
|
||||
public string ResultKind { get; set; }
|
||||
|
||||
public CmdPalInvokeResult(CommandResultKind resultKind)
|
||||
public InvokeResultEvent(CommandResultKind resultKind)
|
||||
{
|
||||
EventName = "CmdPal_InvokeResult";
|
||||
ResultKind = resultKind.ToString();
|
||||
}
|
||||
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
@@ -4,20 +4,20 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class OpenPage : EventBase, IEvent
|
||||
public class OpenPageEvent : TelemetryEventBase
|
||||
{
|
||||
public int PageDepth { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
|
||||
public OpenPage(int pageDepth, string id)
|
||||
public OpenPageEvent(int pageDepth, string id)
|
||||
{
|
||||
PageDepth = pageDepth;
|
||||
Id = id;
|
||||
@@ -25,5 +25,5 @@ public class OpenPage : EventBase, IEvent
|
||||
EventName = "CmdPal_OpenPage";
|
||||
}
|
||||
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class OpenUriEvent : TelemetryEventBase
|
||||
{
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public string Uri { get; set; }
|
||||
|
||||
public bool IsWeb { get; set; }
|
||||
|
||||
public bool Success { get; set; }
|
||||
|
||||
public OpenUriEvent(string uri, bool isWeb, bool success)
|
||||
{
|
||||
EventName = "CmdPal_OpenUri";
|
||||
Uri = uri;
|
||||
IsWeb = isWeb;
|
||||
Success = success;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class ProcessStartedEvent : TelemetryEventBase
|
||||
{
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public ProcessStartedEvent()
|
||||
{
|
||||
EventName = "CmdPal_ProcessStarted";
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,18 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class ReactivateInstance : EventBase, IEvent
|
||||
public class ReactivateInstanceEvent : TelemetryEventBase
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public ReactivateInstance()
|
||||
public ReactivateInstanceEvent()
|
||||
{
|
||||
EventName = "CmdPal_ReactivateInstance";
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class RunCommandEvent : TelemetryEventBase
|
||||
{
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public string Command { get; set; }
|
||||
|
||||
public bool AsAdmin { get; set; }
|
||||
|
||||
public bool Success { get; set; }
|
||||
|
||||
public RunCommandEvent(string command, bool asAdmin, bool success)
|
||||
{
|
||||
EventName = "CmdPal_RunCommand";
|
||||
Command = command;
|
||||
AsAdmin = asAdmin;
|
||||
Success = success;
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
// Just put all the run events in one file for simplicity.
|
||||
#pragma warning disable SA1402 // File may only contain a single type
|
||||
#pragma warning disable SA1649 // File name should match first type name
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class CmdPalRunQuery : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public string Query { get; set; }
|
||||
|
||||
public int ResultCount { get; set; }
|
||||
|
||||
public ulong DurationMs { get; set; }
|
||||
|
||||
public CmdPalRunQuery(string query, int resultCount, ulong durationMs)
|
||||
{
|
||||
EventName = "CmdPal_RunQuery";
|
||||
Query = query;
|
||||
ResultCount = resultCount;
|
||||
DurationMs = durationMs;
|
||||
}
|
||||
}
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class CmdPalRunCommand : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public string Command { get; set; }
|
||||
|
||||
public bool AsAdmin { get; set; }
|
||||
|
||||
public bool Success { get; set; }
|
||||
|
||||
public CmdPalRunCommand(string command, bool asAdmin, bool success)
|
||||
{
|
||||
EventName = "CmdPal_RunCommand";
|
||||
Command = command;
|
||||
AsAdmin = asAdmin;
|
||||
Success = success;
|
||||
}
|
||||
}
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class CmdPalOpenUri : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public string Uri { get; set; }
|
||||
|
||||
public bool IsWeb { get; set; }
|
||||
|
||||
public bool Success { get; set; }
|
||||
|
||||
public CmdPalOpenUri(string uri, bool isWeb, bool success)
|
||||
{
|
||||
EventName = "CmdPal_OpenUri";
|
||||
Uri = uri;
|
||||
IsWeb = isWeb;
|
||||
Success = success;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore SA1649 // File name should match first type name
|
||||
#pragma warning restore SA1402 // File may only contain a single type
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Events;
|
||||
|
||||
[EventData]
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class RunQueryEvent : TelemetryEventBase
|
||||
{
|
||||
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
|
||||
public string Query { get; set; }
|
||||
|
||||
public int ResultCount { get; set; }
|
||||
|
||||
public ulong DurationMs { get; set; }
|
||||
|
||||
public RunQueryEvent(string query, int resultCount, ulong durationMs)
|
||||
{
|
||||
EventName = "CmdPal_RunQuery";
|
||||
Query = query;
|
||||
ResultCount = resultCount;
|
||||
DurationMs = durationMs;
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@
|
||||
xmlns:coreViewModels="using:Microsoft.CmdPal.Core.ViewModels"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:Microsoft.CmdPal.UI"
|
||||
xmlns:markdownImageProviders="using:Microsoft.CmdPal.UI.Helpers.MarkdownImageProviders"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:viewModels="using:Microsoft.CmdPal.UI.ViewModels"
|
||||
@@ -25,7 +24,7 @@
|
||||
x:Key="DefaultMarkdownThemeConfig"
|
||||
H3FontSize="12"
|
||||
H3FontWeight="Normal" />
|
||||
<markdownImageProviders:ImageProvider x:Key="ImageProvider" />
|
||||
<Frame x:Name="ImageProviderFrame"/>
|
||||
<tkcontrols:MarkdownConfig
|
||||
x:Key="DefaultMarkdownConfig"
|
||||
ImageProvider="{StaticResource ImageProvider}"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.CmdPal.UI.Helpers.MarkdownImageProviders;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
@@ -19,8 +19,6 @@ public sealed partial class ContentPage : Page,
|
||||
IRecipient<ActivateSelectedListItemMessage>,
|
||||
IRecipient<ActivateSecondaryCommandMessage>
|
||||
{
|
||||
private readonly DispatcherQueue _queue = DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
public ContentPageViewModel? ViewModel
|
||||
{
|
||||
get => (ContentPageViewModel?)GetValue(ViewModelProperty);
|
||||
@@ -31,10 +29,15 @@ public sealed partial class ContentPage : Page,
|
||||
public static readonly DependencyProperty ViewModelProperty =
|
||||
DependencyProperty.Register(nameof(ViewModel), typeof(ContentPageViewModel), typeof(ContentPage), new PropertyMetadata(null));
|
||||
|
||||
public ContentPage()
|
||||
private readonly ImageProvider _imageProvider;
|
||||
|
||||
public ContentPage(ImageProvider imageProvider)
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.Unloaded += OnUnloaded;
|
||||
_imageProvider = imageProvider;
|
||||
|
||||
ImageProviderFrame.Content = _imageProvider;
|
||||
}
|
||||
|
||||
private void OnUnloaded(object sender, RoutedEventArgs e)
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
|
||||
using System.Diagnostics;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Commands;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.CmdPal.UI.Helpers;
|
||||
using Microsoft.CmdPal.UI.Messages;
|
||||
using Microsoft.CmdPal.UI.ViewModels;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
@@ -31,8 +30,11 @@ public sealed partial class ListPage : Page,
|
||||
IRecipient<ActivateSelectedListItemMessage>,
|
||||
IRecipient<ActivateSecondaryCommandMessage>
|
||||
{
|
||||
private readonly SettingsModel settings;
|
||||
private InputSource _lastInputSource;
|
||||
|
||||
public ILogger Logger { get; private set; }
|
||||
|
||||
internal ListViewModel? ViewModel
|
||||
{
|
||||
get => (ListViewModel?)GetValue(ViewModelProperty);
|
||||
@@ -51,9 +53,11 @@ public sealed partial class ListPage : Page,
|
||||
}
|
||||
}
|
||||
|
||||
public ListPage()
|
||||
public ListPage(SettingsModel settingsModel, ILogger logger)
|
||||
{
|
||||
this.InitializeComponent();
|
||||
settings = settingsModel;
|
||||
Logger = logger;
|
||||
this.NavigationCacheMode = NavigationCacheMode.Disabled;
|
||||
this.ItemView.Loaded += Items_Loaded;
|
||||
this.ItemView.PreviewKeyDown += Items_PreviewKeyDown;
|
||||
@@ -133,7 +137,6 @@ public sealed partial class ListPage : Page,
|
||||
return;
|
||||
}
|
||||
|
||||
var settings = App.Current.Services.GetService<SettingsModel>()!;
|
||||
if (settings.SingleClickActivates)
|
||||
{
|
||||
ViewModel?.InvokeItemCommand.Execute(item);
|
||||
@@ -150,7 +153,6 @@ public sealed partial class ListPage : Page,
|
||||
{
|
||||
if (ItemView.SelectedItem is ListItemViewModel vm)
|
||||
{
|
||||
var settings = App.Current.Services.GetService<SettingsModel>()!;
|
||||
if (!settings.SingleClickActivates)
|
||||
{
|
||||
ViewModel?.InvokeItemCommand.Execute(vm);
|
||||
@@ -456,7 +458,7 @@ public sealed partial class ListPage : Page,
|
||||
}
|
||||
else if (e.NewValue is null)
|
||||
{
|
||||
Logger.LogDebug("cleared view model");
|
||||
Log_ClearedViewModel(@this.Logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -576,4 +578,7 @@ public sealed partial class ListPage : Page,
|
||||
Keyboard,
|
||||
Pointer,
|
||||
}
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Cleared view model")]
|
||||
static partial void Log_ClearedViewModel(ILogger logger);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Core.Common.Helpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
@@ -17,6 +17,13 @@ namespace Microsoft.CmdPal.UI.Helpers;
|
||||
/// </summary>
|
||||
internal sealed partial class GlobalErrorHandler
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public GlobalErrorHandler(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
// GlobalErrorHandler is designed to be self-contained; it can be registered and invoked before a service provider is available.
|
||||
internal void Register(App app)
|
||||
{
|
||||
@@ -54,9 +61,9 @@ internal sealed partial class GlobalErrorHandler
|
||||
HandleException(e.Exception, Context.UnobservedTaskException);
|
||||
}
|
||||
|
||||
private static void HandleException(Exception ex, Context context)
|
||||
private void HandleException(Exception ex, Context context)
|
||||
{
|
||||
Logger.LogError($"Unhandled exception detected ({context})", ex);
|
||||
Log_UnhandledException(ex, context);
|
||||
|
||||
if (context == Context.MainThreadException)
|
||||
{
|
||||
@@ -93,7 +100,7 @@ internal sealed partial class GlobalErrorHandler
|
||||
}
|
||||
}
|
||||
|
||||
private static string? StoreReport(string report, bool storeOnDesktop)
|
||||
private string? StoreReport(string report, bool storeOnDesktop)
|
||||
{
|
||||
// Generate a unique name for the report file; include timestamp and a random zero-padded number to avoid collisions
|
||||
// in case of crash storm.
|
||||
@@ -101,15 +108,16 @@ internal sealed partial class GlobalErrorHandler
|
||||
|
||||
// Always store a copy in log directory, this way it is available for Bug Report Tool
|
||||
string? reportPath = null;
|
||||
if (Logger.CurrentVersionLogDirectoryPath != null)
|
||||
{
|
||||
reportPath = Save(report, name, static () => Logger.CurrentVersionLogDirectoryPath);
|
||||
}
|
||||
|
||||
// if (!string.IsNullOrEmpty(logWrapper.CurrentVersionLogDirectoryPath))
|
||||
// {
|
||||
// reportPath = Save(report, name, logWrapper.CurrentVersionLogDirectoryPath);
|
||||
// s}
|
||||
|
||||
// Optionally store a copy on the desktop for user (in)convenience
|
||||
if (storeOnDesktop)
|
||||
{
|
||||
var path = Save(report, name, static () => Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory));
|
||||
var path = Save(report, name, Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory));
|
||||
|
||||
// show the desktop copy if both succeeded
|
||||
if (path != null)
|
||||
@@ -120,11 +128,10 @@ internal sealed partial class GlobalErrorHandler
|
||||
|
||||
return reportPath;
|
||||
|
||||
static string? Save(string reportContent, string reportFileName, Func<string> directory)
|
||||
string? Save(string reportContent, string reportFileName, string logDirectory)
|
||||
{
|
||||
try
|
||||
{
|
||||
var logDirectory = directory();
|
||||
Directory.CreateDirectory(logDirectory);
|
||||
var reportFilePath = Path.Combine(logDirectory, reportFileName);
|
||||
File.WriteAllText(reportFilePath, reportContent);
|
||||
@@ -132,7 +139,7 @@ internal sealed partial class GlobalErrorHandler
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed to store exception report", ex);
|
||||
Log_FailureToStoreExceptionReport(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -146,4 +153,10 @@ internal sealed partial class GlobalErrorHandler
|
||||
UnobservedTaskException,
|
||||
AppDomainUnhandledException,
|
||||
}
|
||||
|
||||
[LoggerMessage(level: LogLevel.Error, Message = "Failed to store exception report")]
|
||||
partial void Log_FailureToStoreExceptionReport(Exception ex);
|
||||
|
||||
[LoggerMessage(level: LogLevel.Error, message: "Unhandled exception detected ({Context})")]
|
||||
partial void Log_UnhandledException(Exception ex, Context context);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
// 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.Extensions.Logging;
|
||||
using Windows.System;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
@@ -16,6 +15,13 @@ namespace Microsoft.CmdPal.UI.Helpers;
|
||||
/// </summary>
|
||||
internal sealed partial class LocalKeyboardListener : IDisposable
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public LocalKeyboardListener(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event that is raised when a key is pressed down.
|
||||
/// </summary>
|
||||
@@ -68,7 +74,7 @@ internal sealed partial class LocalKeyboardListener : IDisposable
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed to register hook", ex);
|
||||
Log_FailureToRegisterHook(ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -121,7 +127,7 @@ internal sealed partial class LocalKeyboardListener : IDisposable
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed when invoking key down keyboard hook event", ex);
|
||||
Log_FailureToInvokeKeyDownHook(ex);
|
||||
}
|
||||
|
||||
// Call next hook in chain - pass null as first parameter for current hook
|
||||
@@ -154,4 +160,10 @@ internal sealed partial class LocalKeyboardListener : IDisposable
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to register hook")]
|
||||
partial void Log_FailureToRegisterHook(Exception ex);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Failed when invoking key down keyboard hook event")]
|
||||
partial void Log_FailureToInvokeKeyDownHook(Exception ex);
|
||||
}
|
||||
|
||||
@@ -3,14 +3,20 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using CommunityToolkit.WinUI.Controls;
|
||||
using ManagedCommon;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Helpers.MarkdownImageProviders;
|
||||
|
||||
internal sealed partial class ImageProvider : IImageProvider
|
||||
public sealed partial class ImageProvider : IImageProvider
|
||||
{
|
||||
private readonly CompositeImageSourceProvider _compositeProvider = new();
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public ImageProvider(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<Image> GetImage(string url)
|
||||
{
|
||||
@@ -31,7 +37,7 @@ internal sealed partial class ImageProvider : IImageProvider
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to provide an image from URI '{url}'", ex);
|
||||
Log_FailedToProvideImageFromUrl(url, ex);
|
||||
return null!;
|
||||
}
|
||||
}
|
||||
@@ -40,4 +46,7 @@ internal sealed partial class ImageProvider : IImageProvider
|
||||
{
|
||||
return _compositeProvider.ShouldUseThisProvider(url);
|
||||
}
|
||||
|
||||
[LoggerMessage(level: LogLevel.Error, message: "Failed to provide an image from URI '{url}'")]
|
||||
partial void Log_FailedToProvideImageFromUrl(string url, Exception ex);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.CmdPal.Core.Common.Services;
|
||||
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.CmdPal.UI.Events;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
@@ -30,28 +30,30 @@ internal sealed class TelemetryForwarder :
|
||||
WeakReferenceMessenger.Default.Register<CmdPalInvokeResultMessage>(this);
|
||||
}
|
||||
|
||||
public void WriteEvent(TelemetryEventBase telemetryEvent) => PowerToysTelemetry.Log.WriteEvent(telemetryEvent);
|
||||
|
||||
public void Receive(CmdPalInvokeResultMessage message)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new CmdPalInvokeResult(message.Kind));
|
||||
PowerToysTelemetry.Log.WriteEvent(new InvokeResultEvent(message.Kind));
|
||||
}
|
||||
|
||||
public void Receive(BeginInvokeMessage message)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new BeginInvoke());
|
||||
PowerToysTelemetry.Log.WriteEvent(new BeginInvokeEvent());
|
||||
}
|
||||
|
||||
public void LogRunQuery(string query, int resultCount, ulong durationMs)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new CmdPalRunQuery(query, resultCount, durationMs));
|
||||
PowerToysTelemetry.Log.WriteEvent(new RunQueryEvent(query, resultCount, durationMs));
|
||||
}
|
||||
|
||||
public void LogRunCommand(string command, bool asAdmin, bool success)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new CmdPalRunCommand(command, asAdmin, success));
|
||||
PowerToysTelemetry.Log.WriteEvent(new RunCommandEvent(command, asAdmin, success));
|
||||
}
|
||||
|
||||
public void LogOpenUri(string uri, bool isWeb, bool success)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new CmdPalOpenUri(uri, isWeb, success));
|
||||
PowerToysTelemetry.Log.WriteEvent(new OpenUriEvent(uri, isWeb, success));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Microsoft.CmdPal.UI.Helpers;
|
||||
|
||||
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Stylistically, window messages are WM_*")]
|
||||
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "Stylistically, window messages are WM_*")]
|
||||
internal sealed partial class TrayIconService
|
||||
public sealed partial class TrayIconService
|
||||
{
|
||||
private const uint MY_NOTIFY_ID = 1000;
|
||||
private const uint WM_TRAY_ICON = PInvoke.WM_USER + 1;
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Automation.Peers;
|
||||
|
||||
@@ -14,10 +9,6 @@ namespace Microsoft.CmdPal.UI.Helpers;
|
||||
|
||||
public static partial class UIHelper
|
||||
{
|
||||
static UIHelper()
|
||||
{
|
||||
}
|
||||
|
||||
public static void AnnounceActionForAccessibility(UIElement ue, string announcement, string activityID)
|
||||
{
|
||||
if (FrameworkElementAutomationPeer.FromElement(ue) is AutomationPeer peer)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user