From 0ba01cc346796d43854db5c998c5dd44129c5945 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Wed, 13 Nov 2024 09:40:59 -0800 Subject: [PATCH] Add Extensions page to Settings UI --- .../TerminalSettingsEditor/Extensions.cpp | 125 ++++++++++++++++++ .../TerminalSettingsEditor/Extensions.h | 54 ++++++++ .../TerminalSettingsEditor/Extensions.idl | 26 ++++ .../TerminalSettingsEditor/Extensions.xaml | 75 +++++++++++ .../TerminalSettingsEditor/MainPage.cpp | 8 ++ .../TerminalSettingsEditor/MainPage.xaml | 8 ++ ...Microsoft.Terminal.Settings.Editor.vcxproj | 15 +++ .../Resources/en-US/Resources.resw | 16 +++ .../CascadiaSettings.cpp | 48 +++++++ .../TerminalSettingsModel/CascadiaSettings.h | 34 ++++- .../CascadiaSettings.idl | 9 ++ .../CascadiaSettingsSerialization.cpp | 23 +++- 12 files changed, 437 insertions(+), 4 deletions(-) create mode 100644 src/cascadia/TerminalSettingsEditor/Extensions.cpp create mode 100644 src/cascadia/TerminalSettingsEditor/Extensions.h create mode 100644 src/cascadia/TerminalSettingsEditor/Extensions.idl create mode 100644 src/cascadia/TerminalSettingsEditor/Extensions.xaml diff --git a/src/cascadia/TerminalSettingsEditor/Extensions.cpp b/src/cascadia/TerminalSettingsEditor/Extensions.cpp new file mode 100644 index 00000000000..ea3f28f26fd --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Extensions.cpp @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "Extensions.h" +#include "Extensions.g.cpp" +#include "ExtensionsViewModel.g.cpp" + +#include +#include "..\WinRTUtils\inc\Utils.h" + +using namespace winrt::Windows::UI::Xaml; +using namespace winrt::Windows::UI::Xaml::Controls; +using namespace winrt::Windows::UI::Xaml::Navigation; + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + Extensions::Extensions() + { + InitializeComponent(); + } + + void Extensions::OnNavigatedTo(const NavigationEventArgs& e) + { + _ViewModel = e.Parameter().as(); + } + + void Extensions::ExtensionLoaded(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& /*args*/) + { + const auto& toggleSwitch = sender.as(); + const auto& extensionSource = toggleSwitch.Tag().as(); + toggleSwitch.IsOn(_ViewModel.GetExtensionState(extensionSource)); + } + + void Extensions::ExtensionToggled(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& /*args*/) + { + const auto& toggleSwitch = sender.as(); + const auto& extensionSource = toggleSwitch.Tag().as(); + _ViewModel.SetExtensionState(extensionSource, toggleSwitch.IsOn()); + } + + ExtensionsViewModel::ExtensionsViewModel(const Model::CascadiaSettings& settings) : + _settings{ settings } + { + std::vector fragmentExtensions; + fragmentExtensions.reserve(settings.FragmentExtensions().Size()); + + std::vector profilesModified; + std::vector profilesAdded; + std::vector colorSchemesAdded; + for (const auto&& fragExt : settings.FragmentExtensions()) + { + fragmentExtensions.push_back(fragExt); + + for (const auto&& profile : fragExt.ModifiedProfilesView()) + { + profilesModified.push_back(profile); + } + + for (const auto&& profile : fragExt.NewProfilesView()) + { + profilesAdded.push_back(profile); + } + + for (const auto&& scheme : fragExt.ColorSchemesView()) + { + colorSchemesAdded.push_back(scheme); + } + } + + _fragmentExtensions = single_threaded_observable_vector(std::move(fragmentExtensions)); + _profilesModified = single_threaded_observable_vector(std::move(profilesModified)); + _profilesAdded = single_threaded_observable_vector(std::move(profilesAdded)); + _colorSchemesAdded = single_threaded_observable_vector(std::move(colorSchemesAdded)); + } + + // Returns true if the extension is enabled, false otherwise + bool ExtensionsViewModel::GetExtensionState(hstring extensionSource) const + { + if (const auto& disabledExtensions = _DisabledProfileSources()) + { + uint32_t ignored; + return !disabledExtensions.IndexOf(extensionSource, ignored); + } + // "disabledProfileSources" not defined --> all extensions are enabled + return true; + } + + // Enable/Disable an extension + void ExtensionsViewModel::SetExtensionState(hstring extensionSource, bool enableExt) + { + // get the current status of the extension + uint32_t idx; + bool currentlyEnabled = true; + const auto& disabledExtensions = _DisabledProfileSources(); + if (disabledExtensions) + { + currentlyEnabled = !disabledExtensions.IndexOf(extensionSource, idx); + } + + // current status mismatches the desired status, + // update the list of disabled extensions + if (currentlyEnabled != enableExt) + { + // If we're disabling an extension and we don't have "disabledProfileSources" defined, + // create it in the model directly + if (!disabledExtensions && !enableExt) + { + std::vector disabledProfileSources{ extensionSource }; + _settings.GlobalSettings().DisabledProfileSources(single_threaded_vector(std::move(disabledProfileSources))); + return; + } + + // Update the list of disabled extensions + if (enableExt) + { + disabledExtensions.RemoveAt(idx); + } + else + { + disabledExtensions.Append(extensionSource); + } + } + } +} diff --git a/src/cascadia/TerminalSettingsEditor/Extensions.h b/src/cascadia/TerminalSettingsEditor/Extensions.h new file mode 100644 index 00000000000..3fbb792b8f1 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Extensions.h @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "Extensions.g.h" +#include "ExtensionsViewModel.g.h" +#include "ViewModelHelpers.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct Extensions : public HasScrollViewer, ExtensionsT + { + public: + Extensions(); + + void OnNavigatedTo(const Windows::UI::Xaml::Navigation::NavigationEventArgs& e); + void ExtensionLoaded(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args); + void ExtensionToggled(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args); + + WINRT_PROPERTY(Editor::ExtensionsViewModel, ViewModel, nullptr); + }; + + struct ExtensionsViewModel : ExtensionsViewModelT, ViewModelHelper + { + public: + ExtensionsViewModel(const Model::CascadiaSettings& settings); + + // Views + Windows::Foundation::Collections::IVectorView FragmentExtensions() const noexcept { return _fragmentExtensions.GetView(); } + Windows::Foundation::Collections::IVectorView ProfilesModified() const noexcept { return _profilesModified.GetView(); } + Windows::Foundation::Collections::IVectorView ProfilesAdded() const noexcept { return _profilesAdded.GetView(); } + Windows::Foundation::Collections::IVectorView ColorSchemesAdded() const noexcept { return _colorSchemesAdded.GetView(); } + + bool GetExtensionState(hstring extensionSource) const; + void SetExtensionState(hstring extensionSource, bool enableExt); + + private: + Model::CascadiaSettings _settings; + Windows::Foundation::Collections::IVector _fragmentExtensions; + Windows::Foundation::Collections::IVector _profilesModified; + Windows::Foundation::Collections::IVector _profilesAdded; + Windows::Foundation::Collections::IVector _colorSchemesAdded; + + Windows::Foundation::Collections::IVector _DisabledProfileSources() const noexcept { return _settings.GlobalSettings().DisabledProfileSources(); } + }; +}; + +namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation +{ + BASIC_FACTORY(Extensions); + BASIC_FACTORY(ExtensionsViewModel); +} diff --git a/src/cascadia/TerminalSettingsEditor/Extensions.idl b/src/cascadia/TerminalSettingsEditor/Extensions.idl new file mode 100644 index 00000000000..4bbaf268549 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Extensions.idl @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Settings.Editor +{ + [default_interface] runtimeclass Extensions : Windows.UI.Xaml.Controls.Page + { + Extensions(); + ExtensionsViewModel ViewModel { get; }; + } + + [default_interface] runtimeclass ExtensionsViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged + { + ExtensionsViewModel(Microsoft.Terminal.Settings.Model.CascadiaSettings settings); + + // Views + Windows.Foundation.Collections.IVectorView FragmentExtensions { get; }; + Windows.Foundation.Collections.IVectorView ProfilesModified { get; }; + Windows.Foundation.Collections.IVectorView ProfilesAdded { get; }; + Windows.Foundation.Collections.IVectorView ColorSchemesAdded { get; }; + + // Methods + Boolean GetExtensionState(String extensionSource); + void SetExtensionState(String extensionSource, Boolean enableExt); + } +} diff --git a/src/cascadia/TerminalSettingsEditor/Extensions.xaml b/src/cascadia/TerminalSettingsEditor/Extensions.xaml new file mode 100644 index 00000000000..0aaef4067e2 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/Extensions.xaml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Coming soon! + + + + + + + + + Coming soon! + + + + + + + + + Coming soon! + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/MainPage.cpp b/src/cascadia/TerminalSettingsEditor/MainPage.cpp index 5daf396b72e..79efaa9021b 100644 --- a/src/cascadia/TerminalSettingsEditor/MainPage.cpp +++ b/src/cascadia/TerminalSettingsEditor/MainPage.cpp @@ -9,6 +9,7 @@ #include "Compatibility.h" #include "Rendering.h" #include "RenderingViewModel.h" +#include "Extensions.h" #include "Actions.h" #include "ProfileViewModel.h" #include "GlobalAppearance.h" @@ -44,6 +45,7 @@ static const std::wstring_view renderingTag{ L"Rendering_Nav" }; static const std::wstring_view compatibilityTag{ L"Compatibility_Nav" }; static const std::wstring_view actionsTag{ L"Actions_Nav" }; static const std::wstring_view newTabMenuTag{ L"NewTabMenu_Nav" }; +static const std::wstring_view extensionsTag{ L"Extensions_Nav" }; static const std::wstring_view globalProfileTag{ L"GlobalProfile_Nav" }; static const std::wstring_view addProfileTag{ L"AddProfile" }; static const std::wstring_view colorSchemesTag{ L"ColorSchemes_Nav" }; @@ -445,6 +447,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation _breadcrumbs.Append(crumb); } } + else if (clickedItemTag == extensionsTag) + { + contentFrame().Navigate(xaml_typename(), winrt::make(_settingsClone)); + const auto crumb = winrt::make(box_value(clickedItemTag), RS_(L"Nav_Extensions/Content"), BreadcrumbSubPage::None); + _breadcrumbs.Append(crumb); + } else if (clickedItemTag == globalProfileTag) { auto profileVM{ _viewModelForProfile(_settingsClone.ProfileDefaults(), _settingsClone, Dispatcher()) }; diff --git a/src/cascadia/TerminalSettingsEditor/MainPage.xaml b/src/cascadia/TerminalSettingsEditor/MainPage.xaml index 3a0773062aa..470aa0497f2 100644 --- a/src/cascadia/TerminalSettingsEditor/MainPage.xaml +++ b/src/cascadia/TerminalSettingsEditor/MainPage.xaml @@ -154,6 +154,14 @@ + + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj index 918fa89e063..da55bbd7571 100644 --- a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj +++ b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj @@ -125,6 +125,10 @@ NewTabMenuViewModel.idl Code + + Extensions.xaml + Code + Profiles_Base.xaml Code @@ -199,6 +203,9 @@ Designer + + Designer + Designer @@ -309,6 +316,10 @@ NewTabMenuViewModel.idl Code + + Extensions.xaml + Code + Profiles_Base.xaml Code @@ -408,6 +419,10 @@ + + Extensions.xaml + Code + Profiles_Base.xaml Code diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index d7a0c3efe36..99b005f2343 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -680,6 +680,10 @@ Actions Header for the "actions" menu item. This navigates to a page that lets you see and modify commands, key bindings, and actions that can be done in the app. + + Extensions + Header for the "extensions" menu item. This navigates to a page that lets you see and modify extensions for the app. + Background opacity Name for a control to determine the level of opacity for the background of the control. The user can choose to make the background of the app more or less opaque. @@ -2316,4 +2320,16 @@ Indicates the software that originally created this profile. + + Active Extensions + + + Modified Profiles + + + Added Profiles + + + Added Color Schemes + diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp index eeb3d7cc2e3..31415d287ab 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp @@ -113,6 +113,17 @@ Model::CascadiaSettings CascadiaSettings::Copy() const settings->_globals = _globals->Copy(); settings->_allProfiles = winrt::single_threaded_observable_vector(std::move(allProfiles)); settings->_activeProfiles = winrt::single_threaded_observable_vector(std::move(activeProfiles)); + + // copy fragment extensions + { + std::vector fragmentExtensions; + fragmentExtensions.reserve(_fragmentExtensions.Size()); + for (const auto& fragment : _fragmentExtensions) + { + fragmentExtensions.emplace_back(get_self(fragment)->Copy()); + } + settings->_fragmentExtensions = winrt::single_threaded_vector(std::move(fragmentExtensions)); + } } // load errors @@ -131,6 +142,38 @@ Model::CascadiaSettings CascadiaSettings::Copy() const return *settings; } +Model::FragmentSettings FragmentSettings::Copy() const +{ + auto fragment{ winrt::make_self(_source) }; + fragment->_source = _source; + + std::vector modifiedProfiles; + modifiedProfiles.reserve(_modifiedProfiles.Size()); + for (const auto& profile : _modifiedProfiles) + { + modifiedProfiles.emplace_back(*get_self(profile)->CopySettings()); + } + fragment->_modifiedProfiles = winrt::single_threaded_observable_vector(std::move(modifiedProfiles)); + + std::vector newProfiles; + newProfiles.reserve(_newProfiles.Size()); + for (const auto& profile : _newProfiles) + { + newProfiles.emplace_back(*get_self(profile)->CopySettings()); + } + fragment->_newProfiles = winrt::single_threaded_observable_vector(std::move(newProfiles)); + + std::vector colorSchemes; + colorSchemes.reserve(_colorSchemes.Size()); + for (const auto& scheme : _colorSchemes) + { + colorSchemes.emplace_back(*get_self(scheme)->Copy()); + } + fragment->_colorSchemes = winrt::single_threaded_observable_vector(std::move(colorSchemes)); + + return *fragment; +} + // Method Description: // - Finds a profile that matches the given GUID. If there is no profile in this // settings object that matches, returns nullptr. @@ -173,6 +216,11 @@ IObservableVector CascadiaSettings::ActiveProfiles() const noexc return _activeProfiles; } +IVectorView CascadiaSettings::FragmentExtensions() const noexcept +{ + return _fragmentExtensions.GetView(); +} + // Method Description: // - Returns the globally configured keybindings // Arguments: diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h index e91c43885e9..4b5f9612832 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h @@ -18,6 +18,7 @@ Author(s): #pragma once #include "CascadiaSettings.g.h" +#include "FragmentSettings.g.h" #include "GlobalAppSettings.h" #include "Profile.h" @@ -70,6 +71,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation ParsedSettings inboxSettings; ParsedSettings userSettings; + std::vector fragmentExtensions; bool duplicateProfile = false; private: @@ -93,7 +95,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation static winrt::com_ptr _parseProfile(const OriginTag origin, const winrt::hstring& source, const Json::Value& profileJson); void _appendProfile(winrt::com_ptr&& profile, const winrt::guid& guid, ParsedSettings& settings); void _addUserProfileParent(const winrt::com_ptr& profile); - void _addOrMergeUserColorScheme(const winrt::com_ptr& colorScheme); + bool _addOrMergeUserColorScheme(const winrt::com_ptr& colorScheme); void _executeGenerator(const IDynamicProfileGenerator& generator); std::unordered_set _ignoredNamespaces; @@ -127,6 +129,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation winrt::Windows::Foundation::Collections::IObservableVector AllProfiles() const noexcept; winrt::Windows::Foundation::Collections::IObservableVector ActiveProfiles() const noexcept; Model::ActionMap ActionMap() const noexcept; + winrt::Windows::Foundation::Collections::IVectorView FragmentExtensions() const noexcept; void WriteSettingsToDisk(); Json::Value ToJson() const; Model::Profile ProfileDefaults() const; @@ -184,6 +187,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation winrt::com_ptr _baseLayerProfile = winrt::make_self(); winrt::Windows::Foundation::Collections::IObservableVector _allProfiles = winrt::single_threaded_observable_vector(); winrt::Windows::Foundation::Collections::IObservableVector _activeProfiles = winrt::single_threaded_observable_vector(); + winrt::Windows::Foundation::Collections::IVector _fragmentExtensions = winrt::single_threaded_vector(); std::set _themesChangeLog{}; // load errors @@ -199,6 +203,34 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation mutable std::once_flag _commandLinesCacheOnce; mutable std::vector> _commandLinesCache; }; + + struct FragmentSettings : FragmentSettingsT + { + public: + FragmentSettings(hstring source) : + _source{ source }, + _modifiedProfiles{ winrt::single_threaded_vector() }, + _newProfiles{ winrt::single_threaded_vector() }, + _colorSchemes{ winrt::single_threaded_vector() } {} + + Model::FragmentSettings Copy() const; + + hstring Source() const noexcept { return _source; } + Windows::Foundation::Collections::IVector ModifiedProfiles() const noexcept { return _modifiedProfiles; } + Windows::Foundation::Collections::IVector NewProfiles() const noexcept { return _newProfiles; } + Windows::Foundation::Collections::IVector ColorSchemes() const noexcept { return _colorSchemes; } + + // views + Windows::Foundation::Collections::IVectorView ModifiedProfilesView() const noexcept { return _modifiedProfiles.GetView(); } + Windows::Foundation::Collections::IVectorView NewProfilesView() const noexcept { return _newProfiles.GetView(); } + Windows::Foundation::Collections::IVectorView ColorSchemesView() const noexcept { return _colorSchemes.GetView(); } + + private: + hstring _source; + Windows::Foundation::Collections::IVector _modifiedProfiles; + Windows::Foundation::Collections::IVector _newProfiles; + Windows::Foundation::Collections::IVector _colorSchemes; + }; } namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl index 2fa41941d6e..80eef99cff7 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl @@ -38,6 +38,7 @@ namespace Microsoft.Terminal.Settings.Model Profile DuplicateProfile(Profile sourceProfile); ActionMap ActionMap { get; }; + Windows.Foundation.Collections.IVectorView FragmentExtensions { get; }; IVectorView Warnings { get; }; Windows.Foundation.IReference GetLoadingError { get; }; @@ -56,4 +57,12 @@ namespace Microsoft.Terminal.Settings.Model void ExpandCommands(); } + + [default_interface] runtimeclass FragmentSettings + { + String Source { get; }; + Windows.Foundation.Collections.IVectorView ModifiedProfilesView { get; }; + Windows.Foundation.Collections.IVectorView NewProfilesView { get; }; + Windows.Foundation.Collections.IVectorView ColorSchemesView { get; }; + } } diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp index ea9bda76166..49aaa6803f9 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp @@ -779,6 +779,9 @@ void SettingsLoader::_parseFragment(const winrt::hstring& source, const std::str } } + // Build a FragmentSettings from the ParsedSettings + // and register it to the SettingsLoader after we're done + auto fragmentSettings = winrt::make_self(source); for (const auto& fragmentProfile : settings.profiles) { if (const auto updates = fragmentProfile->Updates(); updates != winrt::guid{}) @@ -787,25 +790,34 @@ void SettingsLoader::_parseFragment(const winrt::hstring& source, const std::str { it->second->AddMostImportantParent(fragmentProfile); } + fragmentSettings->ModifiedProfiles().Append(*fragmentProfile); } else { _addUserProfileParent(fragmentProfile); + fragmentSettings->NewProfiles().Append(*fragmentProfile); } } // STAGED COLORS are processed here: we merge them into the partially-loaded // settings directly so that we can resolve conflicts between user-generated // color schemes and fragment-originated ones. - for (const auto& fragmentColorScheme : settings.colorSchemes) + for (const auto& [_, fragmentColorScheme] : settings.colorSchemes) { - _addOrMergeUserColorScheme(fragmentColorScheme.second); + if (_addOrMergeUserColorScheme(fragmentColorScheme)) + { + // only register schemes that were successfully added + fragmentSettings->ColorSchemes().Append(*fragmentColorScheme); + + // TODO CARLOS: not sure what we want to do about the ones that weren't added + } } // Add the parsed fragment globals as a parent of the user's settings. // Later, in FinalizeInheritance, this will result in the action map from // the fragments being applied before the user's own settings. userSettings.globals->AddLeastImportantParent(settings.globals); + fragmentExtensions.emplace_back(std::move(*fragmentSettings)); } SettingsLoader::JsonSettings SettingsLoader::_parseJson(const std::string_view& content) @@ -905,7 +917,8 @@ void SettingsLoader::_addUserProfileParent(const winrt::com_ptr& newScheme) +// returns true if the scheme was successfully added, otherwise false +bool SettingsLoader::_addOrMergeUserColorScheme(const winrt::com_ptr& newScheme) { // On entry, all the user color schemes have been loaded. Therefore, any insertions of inbox or fragment schemes // will fail; we can leverage this to detect when they are equivalent and delete the user's duplicate copies. @@ -931,9 +944,12 @@ void SettingsLoader::_addOrMergeUserColorScheme(const winrt::com_ptrName(), newName); // And re-add it to the end. userSettings.colorSchemes.emplace(newName, std::move(existingScheme)); + return true; } } + return false; } + return true; } // As the name implies it executes a generator. @@ -1257,6 +1273,7 @@ CascadiaSettings::CascadiaSettings(SettingsLoader&& loader) : _activeProfiles = winrt::single_threaded_observable_vector(std::move(activeProfiles)); _warnings = winrt::single_threaded_vector(std::move(warnings)); _themesChangeLog = std::move(loader.userSettings.themesChangeLog); + _fragmentExtensions = winrt::single_threaded_vector(std::move(loader.fragmentExtensions)); _resolveDefaultProfile(); _resolveNewTabMenuProfiles();