Hide profiles by default if they aren't new (#10910)
Let's say a user doesn't know that they need to write `"hidden": true` in order to prevent a profile from showing up (and a settings UI doesn't exist). Naturally they would open settings.json and try to remove the profile object. This section of code recognizes if a profile was seen before and marks it as `"hidden": true` by default and thus ensures the behavior the user expects: Profiles won't show up again after they've been removed from settings.json. ## References #8324 - Application State ## PR Checklist * [x] Closes #8270 * [x] I work here * [x] Tests added/passed ## Validation Steps Performed * settings.json/state.json are created if they don't exist ✔️ * Removing any profile from settings.json doesn't cause it to appear again ✔️ * Hitting save in SUI creates profiles with `"hidden": true` ✔️ * Removing a default profile and hitting save in SUI works ❌ An empty object is added instead.
This commit is contained in:
parent
0220f71883
commit
5d36e5d2df
|
@ -185,8 +185,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
|
|
||||||
inline bool _IsClosing() const noexcept
|
inline bool _IsClosing() const noexcept
|
||||||
{
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
// _closing isn't atomic and may only be accessed from the main thread.
|
// _closing isn't atomic and may only be accessed from the main thread.
|
||||||
assert(Dispatcher().HasThreadAccess());
|
if (const auto dispatcher = Dispatcher())
|
||||||
|
{
|
||||||
|
assert(dispatcher.HasThreadAccess());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return _closing;
|
return _closing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,15 +155,14 @@ winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings CascadiaSettings::
|
||||||
const auto hardcodedDefaultGuid = resultPtr->GlobalSettings().DefaultProfile();
|
const auto hardcodedDefaultGuid = resultPtr->GlobalSettings().DefaultProfile();
|
||||||
|
|
||||||
std::optional<std::string> fileData = _ReadUserSettings();
|
std::optional<std::string> fileData = _ReadUserSettings();
|
||||||
const bool foundFile = fileData.has_value();
|
|
||||||
|
|
||||||
// Make sure the file isn't totally empty. If it is, we'll treat the file
|
// Make sure the file isn't totally empty. If it is, we'll treat the file
|
||||||
// like it doesn't exist at all.
|
// like it doesn't exist at all.
|
||||||
const bool fileHasData = foundFile && !fileData.value().empty();
|
const bool fileHasData = fileData && !fileData->empty();
|
||||||
bool needToWriteFile = false;
|
bool needToWriteFile = false;
|
||||||
if (fileHasData)
|
if (fileHasData)
|
||||||
{
|
{
|
||||||
resultPtr->_ParseJsonString(fileData.value(), false);
|
resultPtr->_ParseJsonString(*fileData, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load profiles from dynamic profile generators. _userSettings should be
|
// Load profiles from dynamic profile generators. _userSettings should be
|
||||||
|
@ -204,6 +203,35 @@ winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings CascadiaSettings::
|
||||||
_CatchRethrowSerializationExceptionWithLocationInfo(resultPtr->_userSettingsString);
|
_CatchRethrowSerializationExceptionWithLocationInfo(resultPtr->_userSettingsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Let's say a user doesn't know that they need to write `"hidden": true` in
|
||||||
|
// order to prevent a profile from showing up (and a settings UI doesn't exist).
|
||||||
|
// Naturally they would open settings.json and try to remove the profile object.
|
||||||
|
// This section of code recognizes if a profile was seen before and marks it as
|
||||||
|
// `"hidden": true` by default and thus ensures the behavior the user expects:
|
||||||
|
// Profiles won't show up again after they've been removed from settings.json.
|
||||||
|
{
|
||||||
|
const auto state = winrt::get_self<implementation::ApplicationState>(ApplicationState::SharedInstance());
|
||||||
|
auto generatedProfiles = state->GeneratedProfiles();
|
||||||
|
bool generatedProfilesChanged = false;
|
||||||
|
|
||||||
|
for (auto profile : resultPtr->_allProfiles)
|
||||||
|
{
|
||||||
|
if (generatedProfiles.emplace(profile.Guid()).second)
|
||||||
|
{
|
||||||
|
generatedProfilesChanged = true;
|
||||||
|
}
|
||||||
|
else if (profile.Origin() != OriginTag::User)
|
||||||
|
{
|
||||||
|
profile.Hidden(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generatedProfilesChanged)
|
||||||
|
{
|
||||||
|
state->GeneratedProfiles(generatedProfiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// After layering the user settings, check if there are any new profiles
|
// After layering the user settings, check if there are any new profiles
|
||||||
// that need to be inserted into their user settings file.
|
// that need to be inserted into their user settings file.
|
||||||
needToWriteFile = resultPtr->_AppendDynamicProfilesToUserSettings() || needToWriteFile;
|
needToWriteFile = resultPtr->_AppendDynamicProfilesToUserSettings() || needToWriteFile;
|
||||||
|
@ -352,7 +380,6 @@ void CascadiaSettings::_LoadDynamicProfiles()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const GUID nullGuid{ 0 };
|
|
||||||
for (auto& generator : _profileGenerators)
|
for (auto& generator : _profileGenerators)
|
||||||
{
|
{
|
||||||
const std::wstring generatorNamespace{ generator->GetNamespace() };
|
const std::wstring generatorNamespace{ generator->GetNamespace() };
|
||||||
|
@ -711,7 +738,7 @@ bool CascadiaSettings::_AppendDynamicProfilesToUserSettings()
|
||||||
wbuilder.settings_["indentation"] = " ";
|
wbuilder.settings_["indentation"] = " ";
|
||||||
wbuilder.settings_["enableYAMLCompatibility"] = true; // suppress spaces around colons
|
wbuilder.settings_["enableYAMLCompatibility"] = true; // suppress spaces around colons
|
||||||
|
|
||||||
auto isInJsonObj = [](const auto& profile, const auto& json) {
|
static const auto isInJsonObj = [](const auto& profile, const auto& json) {
|
||||||
for (auto profileJson : _GetProfilesJsonObject(json))
|
for (auto profileJson : _GetProfilesJsonObject(json))
|
||||||
{
|
{
|
||||||
if (profileJson.isObject())
|
if (profileJson.isObject())
|
||||||
|
@ -745,8 +772,16 @@ bool CascadiaSettings::_AppendDynamicProfilesToUserSettings()
|
||||||
|
|
||||||
for (const auto& profile : _allProfiles)
|
for (const auto& profile : _allProfiles)
|
||||||
{
|
{
|
||||||
// Skip profiles that are in the user settings or the default settings.
|
// Skip profiles that are:
|
||||||
if (isInJsonObj(profile, _userSettings) || isInJsonObj(profile, _defaultSettings))
|
// * hidden
|
||||||
|
// Because when a user manually removes profiles from settings.json,
|
||||||
|
// we mark them as hidden in LoadAll(). Adding those profiles right
|
||||||
|
// back into settings.json would feel confusing, while the
|
||||||
|
// profile that was just erased is added right back.
|
||||||
|
// * in the user settings or the default settings
|
||||||
|
// Because we don't want to add profiles which are already
|
||||||
|
// in the settings.json (explicitly or implicitly).
|
||||||
|
if (profile.Hidden() || isInJsonObj(profile, _userSettings) || isInJsonObj(profile, _defaultSettings))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue