From bcd36127301735eeda37cff3f2d3c0d9ebba74e0 Mon Sep 17 00:00:00 2001 From: Julian Giebel Date: Thu, 22 Jan 2026 23:19:54 +0100 Subject: [PATCH] Add feedback popups (#41352) * Commit * add the form post * dv * fixes * Change wording * Address review * wording change * Added some stuff * New format * bruh * thanks perry! * yes * More fixes! * typo * Add a command to show the list, improve the UI slightly, split up command names * Fix UI controller * Add better comment * Get rid of weird recursive thing * Cleanup * Work on moving feedback popups out of simulation * Move round end screen subscription to feedback ui controller * Finish moving feedback popups out of simulation * Fix _ as parameter * Clean up FeedbackPopupUIController * Clean up commands * Fix prototype yaml * Fix openfeedbackpopup command description * Update Resources/Locale/en-US/feedbackpopup/feedbackpopup.ftl Co-authored-by: Simon <63975668+Simyon264@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Simon <63975668+Simyon264@users.noreply.github.com> * Address reviews * Address reviews * Fix FeedbackPopupPrototype.cs using empty string instead of string.empty * Address some more of the reviews, style nano is still trolling sadly * Fix feedback popup styling * Fix PopupPrototype ID field not having a setter * Address reviews * Add label when no feedback entries are present Change link button to not show when no link is set --------- Co-authored-by: beck-thompson Co-authored-by: SlamBamActionman Co-authored-by: Simon <63975668+Simyon264@users.noreply.github.com> --- Content.Client/Entry/EntryPoint.cs | 4 + .../FeedbackPopup/ClientFeedbackManager.cs | 71 +++++++++ .../FeedbackPopup/FeedbackEntry.xaml | 24 +++ .../FeedbackPopup/FeedbackEntry.xaml.cs | 54 +++++++ .../FeedbackPopup/FeedbackPopupSheetlet.cs | 36 +++++ .../FeedbackPopupUIController.cs | 75 +++++++++ .../FeedbackPopup/FeedbackPopupWindow.xaml | 24 +++ .../FeedbackPopup/FeedbackPopupWindow.xaml.cs | 49 ++++++ .../Guidebook/Richtext/ProtodataTag.cs | 2 +- Content.Client/IoC/ClientContentIoC.cs | 4 + Content.Client/Options/UI/EscapeMenu.xaml | 1 + Content.Client/Stylesheets/StyleNano.cs | 24 ++- .../Systems/EscapeMenu/EscapeUIController.cs | 10 +- Content.Server/Entry/EntryPoint.cs | 4 + .../FeedbackSystem/FeedbackCommand.cs | 63 ++++++++ .../OpenFeedbackPopupCommand.cs | 24 +++ .../FeedbackSystem/ServerFeedbackManager.cs | 78 +++++++++ Content.Server/IoC/ServerContentIoC.cs | 4 + Content.Shared/CCVar/CCVars.Feedback.cs | 17 ++ .../FeedbackSystem/FeedbackPopupMessage.cs | 61 +++++++ .../FeedbackSystem/FeedbackPopupPrototype.cs | 56 +++++++ .../SharedFeedbackManager.Events.cs | 21 +++ .../FeedbackSystem/SharedFeedbackManager.cs | 150 ++++++++++++++++++ .../en-US/escape-menu/ui/escape-menu.ftl | 2 +- .../en-US/feedbackpopup/feedbackpopup.ftl | 28 ++++ .../FeedbackPopup/feedbackpopups.yml | 19 +++ 26 files changed, 901 insertions(+), 4 deletions(-) create mode 100644 Content.Client/FeedbackPopup/ClientFeedbackManager.cs create mode 100644 Content.Client/FeedbackPopup/FeedbackEntry.xaml create mode 100644 Content.Client/FeedbackPopup/FeedbackEntry.xaml.cs create mode 100644 Content.Client/FeedbackPopup/FeedbackPopupSheetlet.cs create mode 100644 Content.Client/FeedbackPopup/FeedbackPopupUIController.cs create mode 100644 Content.Client/FeedbackPopup/FeedbackPopupWindow.xaml create mode 100644 Content.Client/FeedbackPopup/FeedbackPopupWindow.xaml.cs create mode 100644 Content.Server/FeedbackSystem/FeedbackCommand.cs create mode 100644 Content.Server/FeedbackSystem/OpenFeedbackPopupCommand.cs create mode 100644 Content.Server/FeedbackSystem/ServerFeedbackManager.cs create mode 100644 Content.Shared/CCVar/CCVars.Feedback.cs create mode 100644 Content.Shared/FeedbackSystem/FeedbackPopupMessage.cs create mode 100644 Content.Shared/FeedbackSystem/FeedbackPopupPrototype.cs create mode 100644 Content.Shared/FeedbackSystem/SharedFeedbackManager.Events.cs create mode 100644 Content.Shared/FeedbackSystem/SharedFeedbackManager.cs create mode 100644 Resources/Locale/en-US/feedbackpopup/feedbackpopup.ftl create mode 100644 Resources/Prototypes/FeedbackPopup/feedbackpopups.yml diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs index 2266b30c51..e0358d54e7 100644 --- a/Content.Client/Entry/EntryPoint.cs +++ b/Content.Client/Entry/EntryPoint.cs @@ -3,6 +3,7 @@ using Content.Client.Changelog; using Content.Client.Chat.Managers; using Content.Client.DebugMon; using Content.Client.Eui; +using Content.Client.FeedbackPopup; using Content.Client.Fullscreen; using Content.Client.GameTicking.Managers; using Content.Client.GhostKick; @@ -24,6 +25,7 @@ using Content.Client.UserInterface; using Content.Client.Viewport; using Content.Client.Voting; using Content.Shared.Ame.Components; +using Content.Shared.FeedbackSystem; using Content.Shared.Gravity; using Content.Shared.Localizations; using Robust.Client; @@ -76,6 +78,7 @@ namespace Content.Client.Entry [Dependency] private readonly TitleWindowManager _titleWindowManager = default!; [Dependency] private readonly IEntitySystemManager _entitySystemManager = default!; [Dependency] private readonly ClientsidePlaytimeTrackingManager _clientsidePlaytimeManager = default!; + [Dependency] private readonly ClientFeedbackManager _feedbackManager = null!; public override void PreInit() { @@ -170,6 +173,7 @@ namespace Content.Client.Entry _userInterfaceManager.SetActiveTheme(_configManager.GetCVar(CVars.InterfaceTheme)); _documentParsingManager.Initialize(); _titleWindowManager.Initialize(); + _feedbackManager.Initialize(); _baseClient.RunLevelChanged += (_, args) => { diff --git a/Content.Client/FeedbackPopup/ClientFeedbackManager.cs b/Content.Client/FeedbackPopup/ClientFeedbackManager.cs new file mode 100644 index 0000000000..a4cdf6a617 --- /dev/null +++ b/Content.Client/FeedbackPopup/ClientFeedbackManager.cs @@ -0,0 +1,71 @@ +using Content.Shared.FeedbackSystem; +using Robust.Shared.Network; +using Robust.Shared.Prototypes; + +namespace Content.Client.FeedbackPopup; + +/// +public sealed class ClientFeedbackManager : SharedFeedbackManager +{ + /// + /// A read-only set representing the currently displayed feedback popups. + /// + public IReadOnlySet> DisplayedPopups => _displayedPopups; + + private readonly HashSet> _displayedPopups = []; + + public override void Initialize() + { + base.Initialize(); + NetManager.RegisterNetMessage(ReceivedPopupMessage); + NetManager.RegisterNetMessage(_ => Open()); + } + + /// + /// Opens the feedback popup window. + /// + public void Open() + { + InvokeDisplayedPopupsChanged(true); + } + + /// + public override void Display(List>? prototypes) + { + if (prototypes == null || !NetManager.IsClient) + return; + + var count = _displayedPopups.Count; + _displayedPopups.UnionWith(prototypes); + InvokeDisplayedPopupsChanged(_displayedPopups.Count > count); + } + + /// + public override void Remove(List>? prototypes) + { + if (!NetManager.IsClient) + return; + + if (prototypes == null) + { + _displayedPopups.Clear(); + } + else + { + _displayedPopups.ExceptWith(prototypes); + } + + InvokeDisplayedPopupsChanged(false); + } + + private void ReceivedPopupMessage(FeedbackPopupMessage message) + { + if (message.Remove) + { + Remove(message.FeedbackPrototypes); + return; + } + + Display(message.FeedbackPrototypes); + } +} diff --git a/Content.Client/FeedbackPopup/FeedbackEntry.xaml b/Content.Client/FeedbackPopup/FeedbackEntry.xaml new file mode 100644 index 0000000000..9b7e6ceb17 --- /dev/null +++ b/Content.Client/FeedbackPopup/FeedbackEntry.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + +