mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-10 00:48:23 -06:00
Add SSH folder to NTM for dynamic SSH profiles (#19239)
Automatically generates an "SSH" folder in the new tab menu that contains all profiles generated by the SSH profile generator. This folder is created if the SSH generator created some profiles and the folder hasn't been created before. Detecting if the folder was generated is done via the new `bool ApplicationState::SSHFolderGenerated`. The logic is similar to `SettingsLoader::DisableDeletedProfiles()`. Found a bug on new tab menu's folder inlining feature where we were counting the number of raw entries to determine whether to inline or not. Since the folder only contained the match profiles entry, this bug made it so that the profile entries would always be inlined. The fix was very simple: count the number of _resolved_ entries instead of the raw entries. This can be pulled into its own PR and serviced, if desired. ## References and Relevant Issues #18814 #14042 ## Validation Steps Performed ✅ Existing users get an SSH folder if profiles were generated ## PR Checklist Closes #19043
This commit is contained in:
parent
abaa9488d9
commit
1b2aad6504
@ -1069,7 +1069,7 @@ namespace winrt::TerminalApp::implementation
|
||||
auto folderEntryItems = _CreateNewTabFlyoutItems(folderEntries);
|
||||
|
||||
// If the folder should auto-inline and there is only one item, do so.
|
||||
if (folderEntry.Inlining() == FolderEntryInlining::Auto && folderEntries.Size() == 1)
|
||||
if (folderEntry.Inlining() == FolderEntryInlining::Auto && folderEntryItems.size() == 1)
|
||||
{
|
||||
for (auto const& folderEntryItem : folderEntryItems)
|
||||
{
|
||||
|
||||
@ -41,7 +41,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
X(FileSource::Shared, Windows::Foundation::Collections::IVector<hstring>, RecentCommands, "recentCommands") \
|
||||
X(FileSource::Shared, Windows::Foundation::Collections::IVector<winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage>, DismissedMessages, "dismissedMessages") \
|
||||
X(FileSource::Local, Windows::Foundation::Collections::IVector<hstring>, AllowedCommandlines, "allowedCommandlines") \
|
||||
X(FileSource::Local, std::unordered_set<hstring>, DismissedBadges, "dismissedBadges")
|
||||
X(FileSource::Local, std::unordered_set<hstring>, DismissedBadges, "dismissedBadges") \
|
||||
X(FileSource::Shared, bool, SSHFolderGenerated, "sshFolderGenerated", false)
|
||||
|
||||
struct WindowLayout : WindowLayoutT<WindowLayout>
|
||||
{
|
||||
|
||||
@ -93,6 +93,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
void MergeFragmentIntoUserSettings(const winrt::hstring& source, const winrt::hstring& basePath, const std::string_view& content);
|
||||
void FinalizeLayering();
|
||||
bool DisableDeletedProfiles();
|
||||
bool AddDynamicProfileFolders();
|
||||
bool RemapColorSchemeForProfile(const winrt::com_ptr<winrt::Microsoft::Terminal::Settings::Model::implementation::Profile>& profile);
|
||||
bool FixupUserSettings();
|
||||
|
||||
@ -100,6 +101,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
ParsedSettings userSettings;
|
||||
std::unordered_map<hstring, winrt::com_ptr<implementation::ExtensionPackage>> extensionPackageMap;
|
||||
bool duplicateProfile = false;
|
||||
bool sshProfilesGenerated = false;
|
||||
|
||||
private:
|
||||
struct JsonSettings
|
||||
|
||||
@ -213,8 +213,11 @@ void SettingsLoader::GenerateProfiles()
|
||||
auto generateProfiles = [&](const IDynamicProfileGenerator& generator) {
|
||||
if (!_ignoredNamespaces.contains(generator.GetNamespace()))
|
||||
{
|
||||
const auto oldProfileCount = inboxSettings.profiles.size();
|
||||
_executeGenerator(generator, inboxSettings.profiles);
|
||||
return oldProfileCount != inboxSettings.profiles.size();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Generate profiles for each generator and add them to the inbox settings.
|
||||
@ -224,7 +227,7 @@ void SettingsLoader::GenerateProfiles()
|
||||
generateProfiles(AzureCloudShellGenerator{});
|
||||
generateProfiles(VisualStudioGenerator{});
|
||||
#if TIL_FEATURE_DYNAMICSSHPROFILES_ENABLED
|
||||
generateProfiles(SshHostGenerator{});
|
||||
sshProfilesGenerated = generateProfiles(SshHostGenerator{});
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -536,6 +539,33 @@ bool SettingsLoader::DisableDeletedProfiles()
|
||||
return newGeneratedProfiles;
|
||||
}
|
||||
|
||||
// Returns true if something got changed and
|
||||
// the settings need to be saved to disk.
|
||||
bool SettingsLoader::AddDynamicProfileFolders()
|
||||
{
|
||||
// Keep track of generated folders to avoid regenerating them
|
||||
const auto state = get_self<ApplicationState>(ApplicationState::SharedInstance());
|
||||
|
||||
// If the SSH generator is enabled, try to create an "SSH" folder with all the generated profiles
|
||||
if (sshProfilesGenerated && !state->SSHFolderGenerated())
|
||||
{
|
||||
SshHostGenerator sshGenerator;
|
||||
auto matchProfilesEntry = make_self<implementation::MatchProfilesEntry>();
|
||||
matchProfilesEntry->Source(hstring{ sshGenerator.GetNamespace() });
|
||||
|
||||
auto folderEntry = make_self<implementation::FolderEntry>();
|
||||
folderEntry->Name(L"SSH");
|
||||
folderEntry->Icon(MediaResource::FromString(hstring{ sshGenerator.GetIcon() }));
|
||||
folderEntry->Inlining(FolderEntryInlining::Auto);
|
||||
folderEntry->RawEntries(winrt::single_threaded_vector<Model::NewTabMenuEntry>({ *matchProfilesEntry }));
|
||||
|
||||
userSettings.globals->NewTabMenu().Append(folderEntry.as<Model::NewTabMenuEntry>());
|
||||
state->SSHFolderGenerated(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool winrt::Microsoft::Terminal::Settings::Model::implementation::SettingsLoader::RemapColorSchemeForProfile(const winrt::com_ptr<winrt::Microsoft::Terminal::Settings::Model::implementation::Profile>& profile)
|
||||
{
|
||||
bool modified{ false };
|
||||
@ -1229,6 +1259,7 @@ try
|
||||
// DisableDeletedProfiles returns true whenever we encountered any new generated/dynamic profiles.
|
||||
// Similarly FixupUserSettings returns true, when it encountered settings that were patched up.
|
||||
mustWriteToDisk |= loader.DisableDeletedProfiles();
|
||||
mustWriteToDisk |= loader.AddDynamicProfileFolders();
|
||||
mustWriteToDisk |= loader.FixupUserSettings();
|
||||
|
||||
// If this throws, the app will catch it and use the default settings.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user