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> {