diff --git a/src/cascadia/TerminalApp/AdminWarningPlaceholder.xaml b/src/cascadia/TerminalApp/AdminWarningPlaceholder.xaml
index e8bf5063a..e417d124b 100644
--- a/src/cascadia/TerminalApp/AdminWarningPlaceholder.xaml
+++ b/src/cascadia/TerminalApp/AdminWarningPlaceholder.xaml
@@ -28,7 +28,7 @@
TextWrapping="WrapWholeWords" />
(sender) };
-
- for (const auto& tab : _tabs)
- {
- if (const auto& tabImpl{ _GetTerminalTabImpl(tab) })
- {
- tabImpl->GetRootPane()->WalkTree([warningControl](std::shared_ptr pane) -> bool {
- if (pane->GetUserControl() == *warningControl)
- {
- pane->ReplaceControl(warningControl->Control());
- return true;
- }
- return false;
- });
- }
- }
-
- auto allowedCommandlines{ ElevatedState::SharedInstance().AllowedCommandlines() };
- if (!allowedCommandlines)
- {
- allowedCommandlines = winrt::single_threaded_vector();
- }
- allowedCommandlines.Append(warningControl->Commandline());
- ElevatedState::SharedInstance().AllowedCommandlines(allowedCommandlines);
- }
-
- void TerminalPage::_adminWarningCancelClicked(const TerminalApp::AdminWarningPlaceholder& sender,
- const winrt::Windows::UI::Xaml::RoutedEventArgs& /*args*/)
- {
- auto warningControl{ winrt::get_self(sender) };
-
- for (const auto& tab : _tabs)
- {
- if (const auto& tabImpl{ _GetTerminalTabImpl(tab) })
- {
- tabImpl->GetRootPane()->WalkTree([warningControl](std::shared_ptr pane) -> bool {
- if (pane->GetUserControl() == *warningControl)
- {
- pane->Close();
- return true;
- }
- return false;
- });
- }
- }
- }
-
// Method Description:
// - Get the icon of the currently focused terminal control, and set its
// tab's icon to that icon.
diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index c905fb308..021d9a319 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -1330,6 +1330,93 @@ namespace winrt::TerminalApp::implementation
return true; // TODO! Change this to false. This is defaulted to true for testing.
}
+ void TerminalPage::_adminWarningPrimaryClicked(const TerminalApp::AdminWarningPlaceholder& sender,
+ const winrt::Windows::UI::Xaml::RoutedEventArgs& /*args*/)
+ {
+ auto warningControl{ winrt::get_self(sender) };
+ const auto& cmdline{ warningControl->Commandline() };
+ // Look through the tabs and panes to look for us. Whichever pane had us
+ // as content - replace their content with the TermControl we were
+ // holding on to.
+ for (const auto& tab : _tabs)
+ {
+ if (const auto& tabImpl{ _GetTerminalTabImpl(tab) })
+ {
+ tabImpl->GetRootPane()->WalkTree([warningControl, cmdline](std::shared_ptr pane) -> bool {
+ if (pane->GetUserControl() == *warningControl)
+ {
+ // Hooray, we found us!
+ pane->ReplaceControl(warningControl->Control());
+ // Don't return true here. We want to make sure to chekc
+ // all the panes for the same commandline we just
+ // approved.
+ }
+ else if (const auto& otherWarning{ winrt::get_self(pane->GetUserControl().try_as()) })
+ {
+ // This pane wasn't us, but it did have a warning in it.
+ // Was it a warning for the same commandline that we
+ // just approved?
+ if (otherWarning->Commandline() == cmdline)
+ {
+ // Go ahead and allow them as well.
+ pane->ReplaceControl(otherWarning->Control());
+ }
+ }
+ return false;
+ });
+ }
+ }
+
+ // Update the list of approved commandlines.
+ auto allowedCommandlines{ ElevatedState::SharedInstance().AllowedCommandlines() };
+ if (!allowedCommandlines)
+ {
+ allowedCommandlines = winrt::single_threaded_vector();
+ }
+
+ // But of course, we don't need to add this commandline if it's already
+ // in the list of approved commandlines.
+ bool foundCopy = false;
+ for (const auto& approved : allowedCommandlines)
+ {
+ if (approved == cmdline)
+ {
+ foundCopy = true;
+ break;
+ }
+ }
+ if (!foundCopy)
+ {
+ allowedCommandlines.Append(cmdline);
+ }
+ ElevatedState::SharedInstance().AllowedCommandlines(allowedCommandlines);
+ }
+
+ void TerminalPage::_adminWarningCancelClicked(const TerminalApp::AdminWarningPlaceholder& sender,
+ const winrt::Windows::UI::Xaml::RoutedEventArgs& /*args*/)
+ {
+ auto warningControl{ winrt::get_self(sender) };
+
+ for (const auto& tab : _tabs)
+ {
+ if (const auto& tabImpl{ _GetTerminalTabImpl(tab) })
+ {
+ tabImpl->GetRootPane()->WalkTree([warningControl](std::shared_ptr pane) -> bool {
+ if (pane->GetUserControl() == *warningControl)
+ {
+ pane->Close();
+ return true;
+ }
+ // We're not going to auto-close all the other panes with
+ // the same commandline warning, akin to what we're doing in
+ // the approve handler. If they want to reject one pane, but
+ // accept the next one, that's okay.
+ return false;
+ });
+ }
+ }
+ }
+
// Method Description:
// - Split the focused pane either horizontally or vertically, and place the
// given TermControl into the newly created pane.
diff --git a/src/cascadia/TerminalSettingsModel/ApplicationState.cpp b/src/cascadia/TerminalSettingsModel/ApplicationState.cpp
index 0eab17d2f..c5061f9a2 100644
--- a/src/cascadia/TerminalSettingsModel/ApplicationState.cpp
+++ b/src/cascadia/TerminalSettingsModel/ApplicationState.cpp
@@ -11,52 +11,6 @@
constexpr std::wstring_view stateFileName{ L"state.json" };
-namespace Microsoft::Terminal::Settings::Model::JsonUtils
-{
- // This trait exists in order to serialize the std::unordered_set for GeneratedProfiles.
- template
- struct ConversionTrait>
- {
- std::unordered_set FromJson(const Json::Value& json) const
- {
- ConversionTrait trait;
- std::unordered_set val;
- val.reserve(json.size());
-
- for (const auto& element : json)
- {
- val.emplace(trait.FromJson(element));
- }
-
- return val;
- }
-
- bool CanConvert(const Json::Value& json) const
- {
- ConversionTrait trait;
- return json.isArray() && std::all_of(json.begin(), json.end(), [trait](const auto& json) -> bool { return trait.CanConvert(json); });
- }
-
- Json::Value ToJson(const std::unordered_set& val)
- {
- ConversionTrait trait;
- Json::Value json{ Json::arrayValue };
-
- for (const auto& key : val)
- {
- json.append(trait.ToJson(key));
- }
-
- return json;
- }
-
- std::string TypeDescription() const
- {
- return fmt::format("{}[]", ConversionTrait{}.TypeDescription());
- }
- };
-}
-
using namespace ::Microsoft::Terminal::Settings::Model;
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
diff --git a/src/cascadia/TerminalSettingsModel/ApplicationState.h b/src/cascadia/TerminalSettingsModel/ApplicationState.h
index 67b91121e..299f2acf0 100644
--- a/src/cascadia/TerminalSettingsModel/ApplicationState.h
+++ b/src/cascadia/TerminalSettingsModel/ApplicationState.h
@@ -34,12 +34,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
virtual void FromJson(const Json::Value& root) const noexcept override;
virtual Json::Value ToJson() const noexcept override;
- // // Methods
- // void Reload() const noexcept;
-
- // // General getters/setters
- // winrt::hstring FilePath() const noexcept;
-
// State getters/setters
#define MTSM_APPLICATION_STATE_GEN(type, name, key, ...) \
type name() const noexcept; \
@@ -55,12 +49,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
#undef MTSM_APPLICATION_STATE_GEN
};
til::shared_mutex _state;
-
- // void _write() const noexcept;
- // void _read() const noexcept;
-
- // std::filesystem::path _path;
- // til::throttled_func_trailing<> _throttler;
};
}
diff --git a/src/cascadia/TerminalSettingsModel/JsonUtils.h b/src/cascadia/TerminalSettingsModel/JsonUtils.h
index c5370cdbf..6799ceee7 100644
--- a/src/cascadia/TerminalSettingsModel/JsonUtils.h
+++ b/src/cascadia/TerminalSettingsModel/JsonUtils.h
@@ -218,6 +218,48 @@ namespace Microsoft::Terminal::Settings::Model::JsonUtils
}
};
+ template
+ struct ConversionTrait>
+ {
+ std::unordered_set FromJson(const Json::Value& json) const
+ {
+ ConversionTrait trait;
+ std::unordered_set val;
+ val.reserve(json.size());
+
+ for (const auto& element : json)
+ {
+ val.emplace(trait.FromJson(element));
+ }
+
+ return val;
+ }
+
+ bool CanConvert(const Json::Value& json) const
+ {
+ ConversionTrait trait;
+ return json.isArray() && std::all_of(json.begin(), json.end(), [trait](const auto& json) -> bool { return trait.CanConvert(json); });
+ }
+
+ Json::Value ToJson(const std::unordered_set& val)
+ {
+ ConversionTrait trait;
+ Json::Value json{ Json::arrayValue };
+
+ for (const auto& key : val)
+ {
+ json.append(trait.ToJson(key));
+ }
+
+ return json;
+ }
+
+ std::string TypeDescription() const
+ {
+ return fmt::format("{}[]", ConversionTrait{}.TypeDescription());
+ }
+ };
+
template
struct ConversionTrait>
{