Files
terminal/src/cascadia/TerminalSettingsEditor/AddProfile.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

84 lines
3.6 KiB
C++
Raw Normal View History

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "AddProfile.h"
#include "AddProfile.g.cpp"
#include "AddProfilePageNavigationState.g.cpp"
#include "EnumEntry.h"
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Navigation;
using namespace winrt::Microsoft::Terminal::Settings::Model;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
AddProfile::AddProfile()
{
InitializeComponent();
Automation::AutomationProperties::SetName(AddNewButton(), RS_(L"AddProfile_AddNewTextBlock/Text"));
Automation::AutomationProperties::SetName(DuplicateButton(), RS_(L"AddProfile_DuplicateTextBlock/Text"));
}
void AddProfile::OnNavigatedTo(const NavigationEventArgs& e)
{
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_State = args.ViewModel().as<Editor::AddProfilePageNavigationState>();
Implement search in Settings UI (#19519) ## Summary of the Pull Request Adds search functionality to the settings UI. This is added to an `AutoSuggestBox` in the main `NavigationView`. Invoking a result navigates to the proper location in the settings UI and focuses the setting, when possible. ## References and Relevant Issues Based on https://github.com/microsoft/PowerToys/pull/41285 ## Detailed Description of the Pull Request / Additional comments - tools/GenerateSettingsIndex.ps1: parses all the XAML files in the settings UI for SettingsContainers and builds a search index from them - XAML changes: ensures all SettingContainer objects have an `x:Name` so that we can navigate to them and bring them into view. - TerminalSettingsEditor/Utils.h: implements `BringIntoViewWhenLoaded()` which navigates to the relevant part of the UI. This is called in `OnNavigatedTo()` for each page. - fzf was moved out of TerminalApp so that TerminalSettingsEditor can access it - There's a few main components to searching, all of it is in `MainPage`: - `MainPage::_UpdateSearchIndex()`|`SearchIndex::Reset()`: loads the search index generated by `GenerateSettingsIndex.ps1`; provides additional localization, if needed - `MainPage::SettingsSearchBox_TextChanged`: - detect that text changed in the search box - perform the actual search in `SearchIndex::SearchAsync()`. This is a HEFTY async function that can be cancelled. It needs a lot of context passed in to expand the search index appropriately (i.e. build awareness of "PowerShell" profile and generate results appropriately). This is also where fzf is used to perform weighted matching. - the weighted matching itself is pretty complicated, but all the associated bonus weights are at the top of SearchIndex.cpp. - `SettingsSearchBox_QuerySubmitted`: extract the search index metadata and call the correct `_Navigate()` function ## Validation Steps Performed Search for... - settings that don't change at runtime: - [x] global settings - [x] settings in profile.defaults - [x] "add new profile" page - settings that may change at runtime: - [x] settings in a profile - [x] individual color schemes - [x] actions (main actions page + edit action subpage) - [x] new tab menu folders - [x] extensions - misc. corner cases: - [x] terminal chat (blocked in indexing script; requires minor changes in feature branch) - [x] settings in appearance objects To test fzf matching and weighted results, I specifically tested these scenarios: - "PowerShell" --> prioritize the PowerShell profile page(s) - "font size" --> prioritize profile defaults entry - "font size powershell" --> prioritize PowerShell > font size ## PR Checklist Closes #12949 ## Follow-ups - search by JSON key: need a way to add JSON keys to index entries. `GetSearchableFields()` should make the rest pretty easy. - search by keywords: need to define keywords. `GetSearchableFields()` should make the rest pretty easy.
2026-02-20 15:04:45 -08:00
BringIntoViewWhenLoaded(args.ElementToFocus());
Add telemetry for settings UI traffic (#19156) ## Summary of the Pull Request Adds a telemetry provider to the Terminal.Settings.Editor project as well as new telemetry events to track traffic through the settings UI. Specifically, the following events were added: - `NavigatedToPage`: Event emitted when the user navigates to a page in the settings UI - Has a `PageId` parameter that includes the identifier of the page that was navigated to - (conditionally added when PageId = `page.editColorScheme`) `SchemeName` parameter tracks the name of the color scheme that's being edited - conditionally added when PageId = `page.extensions`: - `ExtensionPackageCount`: The number of extension packages displayed - `ProfilesModifiedCount`: The number of profiles modified by enabled extensions - `ProfilesAddedCount`: The number of profiles added by enabled extensions - `ColorSchemesAddedCount`: The number of color schemes added by enabled extensions - conditionally added when PageId = `page.extensions.extensionView`: - `FragmentSource`: The source of the fragment included in this extension package - `FragmentCount`: The number of fragments included in this extension package - `Enabled`: The enabled status of the extension - (conditionally added when PageID = `page.newTabMenu`) if the page is representing a folder view - conditionally added when PageID = `page.profile.*`: - `IsProfileDefaults`: if the modified profile is the profile.defaults object - `ProfileGuid`: the guid of the profile that was navigated to - `ProfileSource`: the source of the profile that was navigated to - conditionally added when PageID = `page.profile` (aka the base profile page): - `Orphaned`: tracks if the profile was orphaned - `Hidden`: tracks if the profile is hidden - (conditionally added when PageID = `page.profile.appearance`) `HasBackgroundImage`: `if the profile has a background image defined` - (conditionally added when PageID = `page.profile.appearance`) `HasUnfocusedAppearance`: `if the profile has an unfocused appearance defined` - `AddNewProfile`: Event emitted when the user adds a new profile `IsExtensionView` parameter tracks if the page is representing a view of an extension - Has a `Type` parameter that represents the type of the creation method (i.e. empty profile, duplicate) - `ResetApplicationState`: Event emitted when the user resets their application state (via the UI) - `ResetToDefaultSettings`: Event emitted when the user resets their settings to their default value (via the UI) - `OpenJson`: Event emitted when the user clicks the Open JSON button in the settings UI - Has a `SettingsTarget` parameter that represents the target settings file (i.e. settings.json vs defaults.json) - `CreateUnfocusedAppearance`: Event emitted when the user creates an unfocused appearance for a profile - `IsProfileDefaults`: if the modified profile is the profile.defaults object - `ProfileGuid`: the guid of the profile that was navigated to - `ProfileSource`: the source of the profile that was navigated to - `DeleteProfile`: Event emitted when the user deletes a profile - also includes `ProfileGuid`, `ProfileSource`, `Orphaned` from the `NavigatedToPage` section above The page ids can be reused later as a serialized reference to the page. We already use the one for the extensions page for the "new" badge.
2025-08-21 17:06:20 -07:00
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,
"NavigatedToPage",
TraceLoggingDescription("Event emitted when the user navigates to a page in the settings UI"),
TraceLoggingValue("addProfile", "PageId", "The identifier of the page that was navigated to"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
}
void AddProfile::AddNewClick(const IInspectable& /*sender*/,
const Windows::UI::Xaml::RoutedEventArgs& /*eventArgs*/)
{
Add telemetry for settings UI traffic (#19156) ## Summary of the Pull Request Adds a telemetry provider to the Terminal.Settings.Editor project as well as new telemetry events to track traffic through the settings UI. Specifically, the following events were added: - `NavigatedToPage`: Event emitted when the user navigates to a page in the settings UI - Has a `PageId` parameter that includes the identifier of the page that was navigated to - (conditionally added when PageId = `page.editColorScheme`) `SchemeName` parameter tracks the name of the color scheme that's being edited - conditionally added when PageId = `page.extensions`: - `ExtensionPackageCount`: The number of extension packages displayed - `ProfilesModifiedCount`: The number of profiles modified by enabled extensions - `ProfilesAddedCount`: The number of profiles added by enabled extensions - `ColorSchemesAddedCount`: The number of color schemes added by enabled extensions - conditionally added when PageId = `page.extensions.extensionView`: - `FragmentSource`: The source of the fragment included in this extension package - `FragmentCount`: The number of fragments included in this extension package - `Enabled`: The enabled status of the extension - (conditionally added when PageID = `page.newTabMenu`) if the page is representing a folder view - conditionally added when PageID = `page.profile.*`: - `IsProfileDefaults`: if the modified profile is the profile.defaults object - `ProfileGuid`: the guid of the profile that was navigated to - `ProfileSource`: the source of the profile that was navigated to - conditionally added when PageID = `page.profile` (aka the base profile page): - `Orphaned`: tracks if the profile was orphaned - `Hidden`: tracks if the profile is hidden - (conditionally added when PageID = `page.profile.appearance`) `HasBackgroundImage`: `if the profile has a background image defined` - (conditionally added when PageID = `page.profile.appearance`) `HasUnfocusedAppearance`: `if the profile has an unfocused appearance defined` - `AddNewProfile`: Event emitted when the user adds a new profile `IsExtensionView` parameter tracks if the page is representing a view of an extension - Has a `Type` parameter that represents the type of the creation method (i.e. empty profile, duplicate) - `ResetApplicationState`: Event emitted when the user resets their application state (via the UI) - `ResetToDefaultSettings`: Event emitted when the user resets their settings to their default value (via the UI) - `OpenJson`: Event emitted when the user clicks the Open JSON button in the settings UI - Has a `SettingsTarget` parameter that represents the target settings file (i.e. settings.json vs defaults.json) - `CreateUnfocusedAppearance`: Event emitted when the user creates an unfocused appearance for a profile - `IsProfileDefaults`: if the modified profile is the profile.defaults object - `ProfileGuid`: the guid of the profile that was navigated to - `ProfileSource`: the source of the profile that was navigated to - `DeleteProfile`: Event emitted when the user deletes a profile - also includes `ProfileGuid`, `ProfileSource`, `Orphaned` from the `NavigatedToPage` section above The page ids can be reused later as a serialized reference to the page. We already use the one for the extensions page for the "new" badge.
2025-08-21 17:06:20 -07:00
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,
"AddNewProfile",
TraceLoggingDescription("Event emitted when the user adds a new profile"),
TraceLoggingValue("EmptyProfile", "Type", "The type of the creation method (i.e. empty profile, duplicate)"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
_State.RequestAddNew();
}
void AddProfile::DuplicateClick(const IInspectable& /*sender*/,
const Windows::UI::Xaml::RoutedEventArgs& /*eventArgs*/)
{
if (const auto selected = Profiles().SelectedItem())
{
Add telemetry for settings UI traffic (#19156) ## Summary of the Pull Request Adds a telemetry provider to the Terminal.Settings.Editor project as well as new telemetry events to track traffic through the settings UI. Specifically, the following events were added: - `NavigatedToPage`: Event emitted when the user navigates to a page in the settings UI - Has a `PageId` parameter that includes the identifier of the page that was navigated to - (conditionally added when PageId = `page.editColorScheme`) `SchemeName` parameter tracks the name of the color scheme that's being edited - conditionally added when PageId = `page.extensions`: - `ExtensionPackageCount`: The number of extension packages displayed - `ProfilesModifiedCount`: The number of profiles modified by enabled extensions - `ProfilesAddedCount`: The number of profiles added by enabled extensions - `ColorSchemesAddedCount`: The number of color schemes added by enabled extensions - conditionally added when PageId = `page.extensions.extensionView`: - `FragmentSource`: The source of the fragment included in this extension package - `FragmentCount`: The number of fragments included in this extension package - `Enabled`: The enabled status of the extension - (conditionally added when PageID = `page.newTabMenu`) if the page is representing a folder view - conditionally added when PageID = `page.profile.*`: - `IsProfileDefaults`: if the modified profile is the profile.defaults object - `ProfileGuid`: the guid of the profile that was navigated to - `ProfileSource`: the source of the profile that was navigated to - conditionally added when PageID = `page.profile` (aka the base profile page): - `Orphaned`: tracks if the profile was orphaned - `Hidden`: tracks if the profile is hidden - (conditionally added when PageID = `page.profile.appearance`) `HasBackgroundImage`: `if the profile has a background image defined` - (conditionally added when PageID = `page.profile.appearance`) `HasUnfocusedAppearance`: `if the profile has an unfocused appearance defined` - `AddNewProfile`: Event emitted when the user adds a new profile `IsExtensionView` parameter tracks if the page is representing a view of an extension - Has a `Type` parameter that represents the type of the creation method (i.e. empty profile, duplicate) - `ResetApplicationState`: Event emitted when the user resets their application state (via the UI) - `ResetToDefaultSettings`: Event emitted when the user resets their settings to their default value (via the UI) - `OpenJson`: Event emitted when the user clicks the Open JSON button in the settings UI - Has a `SettingsTarget` parameter that represents the target settings file (i.e. settings.json vs defaults.json) - `CreateUnfocusedAppearance`: Event emitted when the user creates an unfocused appearance for a profile - `IsProfileDefaults`: if the modified profile is the profile.defaults object - `ProfileGuid`: the guid of the profile that was navigated to - `ProfileSource`: the source of the profile that was navigated to - `DeleteProfile`: Event emitted when the user deletes a profile - also includes `ProfileGuid`, `ProfileSource`, `Orphaned` from the `NavigatedToPage` section above The page ids can be reused later as a serialized reference to the page. We already use the one for the extensions page for the "new" badge.
2025-08-21 17:06:20 -07:00
const auto selectedProfile = selected.as<Model::Profile>();
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,
"AddNewProfile",
TraceLoggingDescription("Event emitted when the user adds a new profile"),
TraceLoggingValue("Duplicate", "Type", "The type of the creation method (i.e. empty profile, duplicate)"),
TraceLoggingValue(!selectedProfile.Source().empty(), "SourceProfileHasSource", "True, if the source profile has a source (i.e. dynamic profile generator namespace, fragment). Otherwise, False, indicating it's based on a custom profile."),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
_State.RequestDuplicate(selectedProfile.Guid());
}
}
Disable duplicate button without selected profile (#12096) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request - Settings > Add a new profile - Disable "Duplicate" button until a profile is selected ![Duplicate](https://user-images.githubusercontent.com/25966642/148303450-a084cd5f-7f1c-4de3-86bd-602b9336649e.gif) <!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> ## References <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [x] Should take care of #12056, once we can get a build to the a11y team (MAINTAINER EDIT: we unfortunately can't just say "closes #foo" for issues like this one, we need another team to validate the following build.) * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
2022-01-06 19:29:45 +01:00
void AddProfile::ProfilesSelectionChanged(const IInspectable& /*sender*/,
const Windows::UI::Xaml::RoutedEventArgs& /*eventArgs*/)
{
if (!_IsProfileSelected)
{
IsProfileSelected(true);
}
}
}