[PR #18559] Add Extensions page to Settings UI #31561

Closed
opened 2026-01-31 09:48:01 +00:00 by claunia · 0 comments
Owner

Original Pull Request: https://github.com/microsoft/terminal/pull/18559

State: closed
Merged: Yes


Summary of the Pull Request

Adds an Extensions page to the Settings UI. This lets you enable/disable extensions and see how they affect your settings (i.e. adding/modifying profiles and adding color schemes). This page is specifically designed for fragment extensions and dynamic profile generators, but can be expanded on in the future as we develop a more advanced extensions model.

App extensions extract the name and icon from the extension package and display it in the UI. Dynamic profile generators extract the name and icon from the generator and display it in the UI. We prefer to use the display name for breadcrumbs when possible.

A "NEW" badge was added to the Extensions page's NavigationViewItem to highlight that it's new. It goes away once the user visits it.

Detailed Description of the Pull Request / Additional comments

  • Settings Model changes:
    • FragmentSettings represents a parsed json fragment extension.
    • FragmentProfileEntry and FragmentColorSchemeEntry are used to track profiles and color schemes added/modified
    • ExtensionPackage bundles the FragmentSettings together. This is how we represent multiple JSON files in one extension.
    • IDynamicProfileGenerator exposes a DisplayName and Icon
    • ExtensionPackages created from app extensions extract the DisplayName and Icon from the extension
    • ApplicationState is used to track which badges have been dismissed and prevent them from appearing again
    • a std::unordered_set is used to keep track of the dismissed badges, but we only expose a get and append function via the IDL to interact with it
  • Editor changes - view models:
    • ExtensionsViewModel operates as the main view model for the page.
    • FragmentProfileViewModel and FragmentColorSchemeViewModel are used to reference specific components of fragments. They also provide support for navigating to the linked profile or color scheme via the settings UI!
    • ExtensionPackageViewModel is a VM for a group of extensions exposed by a single source. This is mainly needed because a single source can have multiple JSON fragments in it. This is used for the navigators on the main page. Can be extended to provide additional information (i.e. package logo, package name, etc.)
    • CurrentExtensionPackage is used to track which extension package is currently in view, if applicable (similar to how the new tab menu page works)
  • Editor changes - views:
    • Extensions.xaml uses a lot of data templates. These are reused in ItemsControls to display extension components.
    • ExtensionPackageTemplateSelector is used to display ExtensionPackages with metadata vs simple ones that just have a source (i.e. Git)
    • Added a NewInfoBadge style that is just an InfoBadge with "New" in it instead of a number or an icon. Based on https://github.com/microsoft/PowerToys/pull/36939
    • The visibility is bound to a get call to the ApplicationState conducted via the ExtensionsPageViewModel. The VM is also responsible for updating the state.
  • Lazy loading extension objects
    • Since most instances of Terminal won't actually open the settings UI, it doesn't make sense to create all the extension objects upon startup. Instead, we defer creating those objects until the user actually navigates to the Extensions page. This is most of the work that happened in CascadiaSettingsSerialization.cpp. The SettingsLoader can be used specifically to load and create the extension objects.

Validation Steps

Keyboard navigation feels right
Screen reader reads all info on screen properly
Accessibility Insights FastPass found no issues
"Discard changes" retains subpage, but removes any changes
Extensions page nav item displays a badge if page hasn't been visited
The badge is dismissed when the user visits the page

Follow-ups

  • Streamline a process for adding extensions from the new page
  • Long-term, we can reuse the InfoBadge system and make the following minor changes:
    • SettingContainer: display the badge and add logic to read/write ApplicationState appropriately (similarly to above)
    • XPageViewModel:
      • count all the badges that will be displayed and expose/bind that to InfoBadge.Value
      • If a whole page is new, we can just style the badge using the NewInfoBadge style
**Original Pull Request:** https://github.com/microsoft/terminal/pull/18559 **State:** closed **Merged:** Yes --- ## Summary of the Pull Request Adds an Extensions page to the Settings UI. This lets you enable/disable extensions and see how they affect your settings (i.e. adding/modifying profiles and adding color schemes). This page is specifically designed for fragment extensions and dynamic profile generators, but can be expanded on in the future as we develop a more advanced extensions model. App extensions extract the name and icon from the extension package and display it in the UI. Dynamic profile generators extract the name and icon from the generator and display it in the UI. We prefer to use the display name for breadcrumbs when possible. A "NEW" badge was added to the Extensions page's `NavigationViewItem` to highlight that it's new. It goes away once the user visits it. ## Detailed Description of the Pull Request / Additional comments - Settings Model changes: - `FragmentSettings` represents a parsed json fragment extension. - `FragmentProfileEntry` and `FragmentColorSchemeEntry` are used to track profiles and color schemes added/modified - `ExtensionPackage` bundles the `FragmentSettings` together. This is how we represent multiple JSON files in one extension. - `IDynamicProfileGenerator` exposes a `DisplayName` and `Icon` - `ExtensionPackage`s created from app extensions extract the `DisplayName` and `Icon` from the extension - `ApplicationState` is used to track which badges have been dismissed and prevent them from appearing again - a `std::unordered_set` is used to keep track of the dismissed badges, but we only expose a get and append function via the IDL to interact with it - Editor changes - view models: - `ExtensionsViewModel` operates as the main view model for the page. - `FragmentProfileViewModel` and `FragmentColorSchemeViewModel` are used to reference specific components of fragments. They also provide support for navigating to the linked profile or color scheme via the settings UI! - `ExtensionPackageViewModel` is a VM for a group of extensions exposed by a single source. This is mainly needed because a single source can have multiple JSON fragments in it. This is used for the navigators on the main page. Can be extended to provide additional information (i.e. package logo, package name, etc.) - `CurrentExtensionPackage` is used to track which extension package is currently in view, if applicable (similar to how the new tab menu page works) - Editor changes - views: - `Extensions.xaml` uses _a lot_ of data templates. These are reused in `ItemsControl`s to display extension components. - `ExtensionPackageTemplateSelector` is used to display `ExtensionPackage`s with metadata vs simple ones that just have a source (i.e. Git) - Added a `NewInfoBadge` style that is just an InfoBadge with "New" in it instead of a number or an icon. Based on https://github.com/microsoft/PowerToys/pull/36939 - The visibility is bound to a `get` call to the `ApplicationState` conducted via the `ExtensionsPageViewModel`. The VM is also responsible for updating the state. - Lazy loading extension objects - Since most instances of Terminal won't actually open the settings UI, it doesn't make sense to create all the extension objects upon startup. Instead, we defer creating those objects until the user actually navigates to the Extensions page. This is most of the work that happened in `CascadiaSettingsSerialization.cpp`. The `SettingsLoader` can be used specifically to load and create the extension objects. ## Validation Steps ✅ Keyboard navigation feels right ✅ Screen reader reads all info on screen properly ✅ Accessibility Insights FastPass found no issues ✅ "Discard changes" retains subpage, but removes any changes ✅ Extensions page nav item displays a badge if page hasn't been visited ✅ The badge is dismissed when the user visits the page ## Follow-ups - Streamline a process for adding extensions from the new page - Long-term, we can reuse the InfoBadge system and make the following minor changes: - `SettingContainer`: display the badge and add logic to read/write `ApplicationState` appropriately (similarly to above) - `XPageViewModel`: - count all the badges that will be displayed and expose/bind that to `InfoBadge.Value` - If a whole page is new, we can just style the badge using the `NewInfoBadge` style
claunia added the pull-request label 2026-01-31 09:48:01 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#31561