diff --git a/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/TemplateCmdPalExtension/Pages/TemplateExtensionPage.cs b/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/TemplateCmdPalExtension/Pages/TemplateCmdPalExtensionPage.cs
similarity index 100%
rename from src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/TemplateCmdPalExtension/Pages/TemplateExtensionPage.cs
rename to src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/TemplateCmdPalExtension/Pages/TemplateCmdPalExtensionPage.cs
diff --git a/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/deps/Microsoft.CommandPalette.Extensions/Microsoft.CommandPalette.Extensions.0.0.5.nupkg b/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/deps/Microsoft.CommandPalette.Extensions/Microsoft.CommandPalette.Extensions.0.0.5.nupkg
deleted file mode 100644
index ba9079f60263..000000000000
Binary files a/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/deps/Microsoft.CommandPalette.Extensions/Microsoft.CommandPalette.Extensions.0.0.5.nupkg and /dev/null differ
diff --git a/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/nuget.config b/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/nuget.config
index 2f9ebc93c1ac..e6a17ffdfed7 100644
--- a/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/nuget.config
+++ b/src/modules/cmdpal/ExtensionTemplate/TemplateCmdPalExtension/nuget.config
@@ -3,14 +3,10 @@
-
-
-
-
diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/ExtensionHostInstance.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/ExtensionHostInstance.cs
similarity index 96%
rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/ExtensionHostInstance.cs
rename to src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/ExtensionHostInstance.cs
index ba46cc0bd5e8..c736eea123a8 100644
--- a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/ExtensionHostInstance.cs
+++ b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/ExtensionHostInstance.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation
+// 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.
@@ -7,7 +7,7 @@
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
-namespace Microsoft.CmdPal.Ext.WinGet;
+namespace Microsoft.CmdPal.Common;
public partial class ExtensionHostInstance
{
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Assets/template.zip b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Assets/template.zip
new file mode 100644
index 000000000000..398512fd492b
Binary files /dev/null and b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Assets/template.zip differ
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/BuiltInsCommandProvider.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/BuiltInsCommandProvider.cs
index e94c77c4701a..db55670be464 100644
--- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/BuiltInsCommandProvider.cs
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/BuiltInsCommandProvider.cs
@@ -2,7 +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.UI.ViewModels.Commands;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -18,10 +17,12 @@ public partial class BuiltInsCommandProvider : CommandProvider
private readonly QuitCommand quitCommand = new();
private readonly FallbackReloadItem _fallbackReloadItem = new();
private readonly FallbackLogItem _fallbackLogItem = new();
+ private readonly NewExtensionPage _newExtension = new();
public override ICommandItem[] TopLevelCommands() =>
[
new CommandItem(openSettings) { Subtitle = "Open Command Palette settings" },
+ new CommandItem(_newExtension) { Title = _newExtension.Title, Subtitle = "Creates a project for a new Command Palette extension" },
];
public override IFallbackCommandItem[] FallbackCommands() =>
@@ -37,4 +38,6 @@ public BuiltInsCommandProvider()
DisplayName = "Built-in commands";
Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.scale-200.png");
}
+
+ public override void InitializeWithHost(IExtensionHost host) => BuiltinsExtensionHost.Instance.Initialize(host);
}
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/BuiltinsExtensionHost.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/BuiltinsExtensionHost.cs
new file mode 100644
index 000000000000..f643f0fc848a
--- /dev/null
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/BuiltinsExtensionHost.cs
@@ -0,0 +1,20 @@
+// 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.IO.Compression;
+using System.Text.Json;
+using System.Text.Json.Nodes;
+using Microsoft.CmdPal.Common;
+using Microsoft.CmdPal.UI.ViewModels.Messages;
+using Microsoft.CommandPalette.Extensions;
+using Microsoft.CommandPalette.Extensions.Toolkit;
+using Windows.Foundation;
+
+namespace Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;
+
+public partial class BuiltinsExtensionHost
+{
+ internal static ExtensionHostInstance Instance { get; } = new();
+}
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/CreatedExtensionForm.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/CreatedExtensionForm.cs
new file mode 100644
index 000000000000..d2cd61788e1b
--- /dev/null
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/CreatedExtensionForm.cs
@@ -0,0 +1,148 @@
+// 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.IO.Compression;
+using System.Text.Json;
+using System.Text.Json.Nodes;
+using Microsoft.CmdPal.UI.ViewModels.Messages;
+using Microsoft.CommandPalette.Extensions;
+using Microsoft.CommandPalette.Extensions.Toolkit;
+using Windows.Foundation;
+
+namespace Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;
+
+internal sealed partial class CreatedExtensionForm : NewExtensionFormBase
+{
+ public CreatedExtensionForm(string name, string displayName, string path)
+ {
+ TemplateJson = CardTemplate;
+ DataJson = $$"""
+{
+ "name": {{JsonSerializer.Serialize(name)}},
+ "directory": {{JsonSerializer.Serialize(path)}},
+ "displayName": {{JsonSerializer.Serialize(displayName)}}
+}
+""";
+ _name = name;
+ _displayName = displayName;
+ _path = path;
+ }
+
+ public override ICommandResult SubmitForm(string inputs, string data)
+ {
+ var dataInput = JsonNode.Parse(data)?.AsObject();
+ if (dataInput == null)
+ {
+ return CommandResult.KeepOpen();
+ }
+
+ var verb = dataInput["x"]?.AsValue()?.ToString() ?? string.Empty;
+ return verb switch
+ {
+ "sln" => OpenSolution(),
+ "dir" => OpenDirectory(),
+ "new" => CreateNew(),
+ _ => CommandResult.KeepOpen(),
+ };
+ }
+
+ private ICommandResult OpenSolution()
+ {
+ string[] parts = [_path, _name, $"{_name}.sln"];
+ var pathToSolution = Path.Combine(parts);
+ ShellHelpers.OpenInShell(pathToSolution);
+ return CommandResult.GoHome();
+ }
+
+ private ICommandResult OpenDirectory()
+ {
+ string[] parts = [_path, _name];
+ var pathToDir = Path.Combine(parts);
+ ShellHelpers.OpenInShell(pathToDir);
+ return CommandResult.GoHome();
+ }
+
+ private ICommandResult CreateNew()
+ {
+ RaiseFormSubmit(null);
+ return CommandResult.KeepOpen();
+ }
+
+ private static readonly string CardTemplate = """
+{
+ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
+ "type": "AdaptiveCard",
+ "version": "1.6",
+ "body": [
+ {
+ "type": "TextBlock",
+ "text": "Successfully created your new extension!",
+ "size": "large",
+ "weight": "bolder",
+ "style": "heading",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "text": "Your new extension \"${displayName}\" was created in:",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "text": "${directory}",
+ "fontType": "monospace"
+ },
+ {
+ "type": "TextBlock",
+ "text": "Next steps",
+ "style": "heading",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "text": "Now that your extension project has been created, open the solution up in Visual Studio to start writing your extension code.",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "text": "Navigate to `${name}Page.cs` to start adding items to the list, or to `${name}CommandsProvider.cs` to add new commands.",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "text": "Once you're ready to test deploy the package locally with Visual Studio, then run the \"Reload\" command in the Command Palette to load your new extension.",
+ "wrap": true
+ }
+ ],
+ "actions": [
+ {
+ "type": "Action.Submit",
+ "title": "Open Solution",
+ "data": {
+ "x": "sln"
+ }
+ },
+ {
+ "type": "Action.Submit",
+ "title": "Open directory",
+ "data": {
+ "x": "dir"
+ }
+ },
+ {
+ "type": "Action.Submit",
+ "title": "Create another",
+ "data": {
+ "x": "new"
+ }
+ }
+ ]
+}
+""";
+
+ private readonly string _name;
+ private readonly string _displayName;
+ private readonly string _path;
+}
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs
new file mode 100644
index 000000000000..320921d77817
--- /dev/null
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs
@@ -0,0 +1,216 @@
+// 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.IO.Compression;
+using System.Text.Json.Nodes;
+using Microsoft.CommandPalette.Extensions;
+using Microsoft.CommandPalette.Extensions.Toolkit;
+
+namespace Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;
+
+internal sealed partial class NewExtensionForm : NewExtensionFormBase
+{
+ private static readonly string _creatingText = "Creating new extension...";
+ private readonly StatusMessage _creatingMessage = new()
+ {
+ Message = _creatingText,
+ Progress = new ProgressState() { IsIndeterminate = true },
+ };
+
+ public NewExtensionForm()
+ {
+ TemplateJson = $$"""
+{
+ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
+ "type": "AdaptiveCard",
+ "version": "1.6",
+ "body": [
+ {
+ "type": "TextBlock",
+ "text": "Create your new extension",
+ "size": "large"
+ },
+ {
+ "type": "TextBlock",
+ "text": "Use this page to create a new extension project.",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "text": "Extension name",
+ "weight": "bolder",
+ "size": "default"
+ },
+ {
+ "type": "TextBlock",
+ "text": "This is the name of your new extension project. It should be a valid C# class name. Best practice is to also include the word 'Extension' in the name.",
+ "wrap": true
+ },
+ {
+ "type": "Input.Text",
+ "label": "Extension name",
+ "isRequired": true,
+ "errorMessage": "Extension name is required, without spaces",
+ "id": "ExtensionName",
+ "placeholder": "ExtensionName",
+ "regex": "^[^\\s]+$"
+ },
+ {
+ "type": "TextBlock",
+ "text": "Display name",
+ "weight": "bolder",
+ "size": "default"
+ },
+ {
+ "type": "TextBlock",
+ "text": "The name of your extension as users will see it.",
+ "wrap": true
+ },
+ {
+ "type": "Input.Text",
+ "label": "Display name",
+ "isRequired": true,
+ "errorMessage": "Display name is required",
+ "id": "DisplayName",
+ "placeholder": "My new extension"
+ },
+ {
+ "type": "TextBlock",
+ "text": "Output path",
+ "weight": "bolder",
+ "size": "default"
+ },
+ {
+ "type": "TextBlock",
+ "text": "Where should the new extension be created? This path will be created if it doesn't exist",
+ "wrap": true
+ },
+ {
+ "type": "Input.Text",
+ "label": "Output path",
+ "isRequired": true,
+ "errorMessage": "Output path is required",
+ "id": "OutputPath",
+ "placeholder": "C:\\users\\me\\dev"
+ }
+ ],
+ "actions": [
+ {
+ "type": "Action.Submit",
+ "title": "Create extension",
+ "associatedInputs": "auto"
+ }
+ ]
+}
+""";
+ }
+
+ public override CommandResult SubmitForm(string payload)
+ {
+ var formInput = JsonNode.Parse(payload)?.AsObject();
+ if (formInput == null)
+ {
+ return CommandResult.KeepOpen();
+ }
+
+ var extensionName = formInput["ExtensionName"]?.AsValue()?.ToString() ?? string.Empty;
+ var displayName = formInput["DisplayName"]?.AsValue()?.ToString() ?? string.Empty;
+ var outputPath = formInput["OutputPath"]?.AsValue()?.ToString() ?? string.Empty;
+
+ _creatingMessage.State = MessageState.Info;
+ _creatingMessage.Message = _creatingText;
+ _creatingMessage.Progress = new ProgressState() { IsIndeterminate = true };
+ BuiltinsExtensionHost.Instance.ShowStatus(_creatingMessage);
+
+ try
+ {
+ CreateExtension(extensionName, displayName, outputPath);
+
+ // _creatingMessage.Progress = null;
+ // _creatingMessage.State = MessageState.Success;
+ // _creatingMessage.Message = $"Successfully created extension";
+ BuiltinsExtensionHost.Instance.HideStatus(_creatingMessage);
+
+ // BuiltinsExtensionHost.Instance.HideStatus(_creatingMessage);
+ RaiseFormSubmit(new CreatedExtensionForm(extensionName, displayName, outputPath));
+
+ // _toast.Message.State = MessageState.Success;
+ // _toast.Message.Message = $"Successfully created extension";
+ // _toast.Show();
+ }
+ catch (Exception e)
+ {
+ BuiltinsExtensionHost.Instance.HideStatus(_creatingMessage);
+
+ _creatingMessage.State = MessageState.Error;
+ _creatingMessage.Message = $"Error: {e.Message}";
+
+ // _toast.Show();
+ }
+
+ // _ = Task.Run(() =>
+ // {
+ // Thread.Sleep(2500);
+ // BuiltinsExtensionHost.Instance.HideStatus(_creatingMessage);
+ // });
+ return CommandResult.KeepOpen();
+ }
+
+ private void CreateExtension(string extensionName, string newDisplayName, string outputPath)
+ {
+ var newGuid = Guid.NewGuid().ToString();
+
+ // Unzip `template.zip` to a temp dir:
+ var tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
+
+ // Console.WriteLine($"Extracting to {tempDir}");
+
+ // Does the output path exist?
+ if (!Directory.Exists(outputPath))
+ {
+ Directory.CreateDirectory(outputPath);
+ }
+
+ var assetsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory.ToString(), "Microsoft.CmdPal.UI.ViewModels\\Assets\\template.zip");
+ ZipFile.ExtractToDirectory(assetsPath, tempDir);
+
+ var files = Directory.GetFiles(tempDir, "*", SearchOption.AllDirectories);
+ foreach (var file in files)
+ {
+ var text = File.ReadAllText(file);
+
+ Console.WriteLine($" Processing {file}");
+
+ // Replace all the instances of `FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF` with a new random guid:
+ text = text.Replace("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF", newGuid);
+
+ // Then replace all the `TemplateCmdPalExtension` with `extensionName`
+ text = text.Replace("TemplateCmdPalExtension", extensionName);
+
+ // Then replace all the `TemplateDisplayName` with `newDisplayName`
+ text = text.Replace("TemplateDisplayName", newDisplayName);
+
+ // We're going to write the file to the same relative location in the output path
+ var relativePath = Path.GetRelativePath(tempDir, file);
+
+ var newFileName = Path.Combine(outputPath, relativePath);
+
+ // if the file name had `TemplateCmdPalExtension` in it, replace it with `extensionName`
+ newFileName = newFileName.Replace("TemplateCmdPalExtension", extensionName);
+
+ // Make sure the directory exists
+ Directory.CreateDirectory(Path.GetDirectoryName(newFileName)!);
+
+ File.WriteAllText(newFileName, text);
+
+ Console.WriteLine($" Wrote {newFileName}");
+
+ // Delete the old file
+ File.Delete(file);
+ }
+
+ // Delete the temp dir
+ Directory.Delete(tempDir, true);
+ }
+}
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionFormBase.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionFormBase.cs
new file mode 100644
index 000000000000..e68fef10a41e
--- /dev/null
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionFormBase.cs
@@ -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 System.Diagnostics.CodeAnalysis;
+using System.IO.Compression;
+using System.Text.Json;
+using System.Text.Json.Nodes;
+using Microsoft.CmdPal.UI.ViewModels.Messages;
+using Microsoft.CommandPalette.Extensions;
+using Microsoft.CommandPalette.Extensions.Toolkit;
+using Windows.Foundation;
+
+namespace Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;
+
+internal abstract partial class NewExtensionFormBase : FormContent
+{
+ public event TypedEventHandler? FormSubmitted;
+
+ protected void RaiseFormSubmit(NewExtensionFormBase? next) => FormSubmitted?.Invoke(this, next);
+}
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionPage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionPage.cs
new file mode 100644
index 000000000000..2f0055b5f260
--- /dev/null
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionPage.cs
@@ -0,0 +1,49 @@
+// 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;
+using Microsoft.CommandPalette.Extensions.Toolkit;
+
+namespace Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;
+
+public partial class NewExtensionPage : ContentPage
+{
+ private NewExtensionForm _inputForm = new();
+ private NewExtensionFormBase? _resultForm;
+
+ public override IContent[] GetContent()
+ {
+ return _resultForm != null ? [_resultForm] : [_inputForm];
+ }
+
+ public NewExtensionPage()
+ {
+ Name = "Open";
+ Title = "Create a new extension";
+ Icon = new IconInfo("\uEA86"); // Puzzle
+
+ _inputForm.FormSubmitted += FormSubmitted;
+ }
+
+ private void FormSubmitted(NewExtensionFormBase sender, NewExtensionFormBase? args)
+ {
+ if (_resultForm != null)
+ {
+ _resultForm.FormSubmitted -= FormSubmitted;
+ }
+
+ _resultForm = args;
+ if (_resultForm != null)
+ {
+ _resultForm.FormSubmitted += FormSubmitted;
+ }
+ else
+ {
+ _inputForm = new();
+ _inputForm.FormSubmitted += FormSubmitted;
+ }
+
+ RaiseItemsChanged(1);
+ }
+}
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs
index 1247b3939d5a..a148576bf136 100644
--- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs
@@ -83,19 +83,22 @@ public void HandleSubmit(IAdaptiveActionElement action, JsonObject inputs)
var dataString = (action as AdaptiveSubmitAction)?.DataJson.Stringify() ?? string.Empty;
var inputString = inputs.Stringify();
- try
+ _ = Task.Run(() =>
{
- var model = _formModel.Unsafe!;
- if (model != null)
+ try
{
- var result = model.SubmitForm(inputString, dataString);
- WeakReferenceMessenger.Default.Send(new(new(result)));
+ var model = _formModel.Unsafe!;
+ if (model != null)
+ {
+ var result = model.SubmitForm(inputString, dataString);
+ WeakReferenceMessenger.Default.Send(new(new(result)));
+ }
}
- }
- catch (Exception ex)
- {
- PageContext.ShowException(ex);
- }
+ catch (Exception ex)
+ {
+ PageContext.ShowException(ex);
+ }
+ });
}
}
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj
index ce02d54414c2..c3058f39b496 100644
--- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj
@@ -34,4 +34,8 @@
+
+
+
+
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/App.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/App.xaml.cs
index 02bec2921180..02cb9d64976a 100644
--- a/src/modules/cmdpal/Microsoft.CmdPal.UI/App.xaml.cs
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/App.xaml.cs
@@ -85,7 +85,6 @@ private static ServiceProvider ConfigureServices()
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
- services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
@@ -94,6 +93,7 @@ private static ServiceProvider ConfigureServices()
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
+ services.AddSingleton();
// Models
services.AddSingleton();
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml
index 6dea9252baa4..3d37c550dbaf 100644
--- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml
@@ -20,6 +20,10 @@
x:Key="StringNotEmptyToVisibilityConverter"
EmptyValue="Collapsed"
NotEmptyValue="Visible" />
+
@@ -65,7 +69,8 @@
+ Tapped="PageIcon_Tapped"
+ Visibility="{x:Bind CurrentPageViewModel.IsNested, Mode=OneWay}">
+
+ Text="{x:Bind CurrentPageViewModel.Title, Mode=OneWay}"
+ Visibility="{x:Bind CurrentPageViewModel.IsNested, Mode=OneWay}" />
();
+ e.Handled = true;
+ }
}
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml
index f29e940850ff..48784a997f38 100644
--- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml
@@ -1,4 +1,4 @@
-
+
-
-
+
+
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml.cs
index 89a218bffdc1..5ae1a4da6a3a 100644
--- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml.cs
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContentFormControl.xaml.cs
@@ -24,7 +24,13 @@ public sealed partial class ContentFormControl : UserControl
static ContentFormControl()
{
- _renderer = new AdaptiveCardRenderer();
+ // We can't use `CardOverrideStyles` here yet, because we haven't called InitializeComponent once.
+ // But also, the default value isn't `null` here. It's... some other default empty value.
+ // So clear it out so that we know when the first time we get created is
+ _renderer = new AdaptiveCardRenderer()
+ {
+ OverrideStyles = null,
+ };
}
public ContentFormControl()
@@ -33,6 +39,14 @@ public ContentFormControl()
var lightTheme = ActualTheme == Microsoft.UI.Xaml.ElementTheme.Light;
_renderer.HostConfig = lightTheme ? AdaptiveCardsConfig.Light : AdaptiveCardsConfig.Dark;
+ // 5% bodgy: if we set this multiple times over the lifetime of the app,
+ // then the second call will explode, because "CardOverrideStyles is already the child of another element".
+ // SO only set this once.
+ if (_renderer.OverrideStyles == null)
+ {
+ _renderer.OverrideStyles = CardOverrideStyles;
+ }
+
// TODO in the future, we should handle ActualThemeChanged and replace
// our rendered card with one for that theme. But today is not that day
}
diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml
index 9371636428a4..54de7967b5ba 100644
--- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml
+++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml
@@ -50,7 +50,7 @@
VerticalAlignment="Center"
FontSize="8"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
- Glyph="" />
+ Glyph="" />
+
+
+ PreserveNewest
+
+
MSBuild:Compile
diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj b/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj
index 3e7a7c8d7205..2f5d8d8f13eb 100644
--- a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj
+++ b/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj
@@ -27,7 +27,8 @@
-
+
+