mirror of
https://github.com/space-wizards/space-station-14.git
synced 2026-02-14 19:29:53 +01:00
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 <beck314159@hotmail.com> Co-authored-by: SlamBamActionman <slambamactionman@gmail.com> Co-authored-by: Simon <63975668+Simyon264@users.noreply.github.com>
This commit is contained in:
@@ -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) =>
|
||||
{
|
||||
|
||||
71
Content.Client/FeedbackPopup/ClientFeedbackManager.cs
Normal file
71
Content.Client/FeedbackPopup/ClientFeedbackManager.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using Content.Shared.FeedbackSystem;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.FeedbackPopup;
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed class ClientFeedbackManager : SharedFeedbackManager
|
||||
{
|
||||
/// <summary>
|
||||
/// A read-only set representing the currently displayed feedback popups.
|
||||
/// </summary>
|
||||
public IReadOnlySet<ProtoId<FeedbackPopupPrototype>> DisplayedPopups => _displayedPopups;
|
||||
|
||||
private readonly HashSet<ProtoId<FeedbackPopupPrototype>> _displayedPopups = [];
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
NetManager.RegisterNetMessage<FeedbackPopupMessage>(ReceivedPopupMessage);
|
||||
NetManager.RegisterNetMessage<OpenFeedbackPopupMessage>(_ => Open());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the feedback popup window.
|
||||
/// </summary>
|
||||
public void Open()
|
||||
{
|
||||
InvokeDisplayedPopupsChanged(true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Display(List<ProtoId<FeedbackPopupPrototype>>? prototypes)
|
||||
{
|
||||
if (prototypes == null || !NetManager.IsClient)
|
||||
return;
|
||||
|
||||
var count = _displayedPopups.Count;
|
||||
_displayedPopups.UnionWith(prototypes);
|
||||
InvokeDisplayedPopupsChanged(_displayedPopups.Count > count);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Remove(List<ProtoId<FeedbackPopupPrototype>>? 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);
|
||||
}
|
||||
}
|
||||
24
Content.Client/FeedbackPopup/FeedbackEntry.xaml
Normal file
24
Content.Client/FeedbackPopup/FeedbackEntry.xaml
Normal file
@@ -0,0 +1,24 @@
|
||||
<Control xmlns="https://spacestation14.io"
|
||||
MinHeight="100">
|
||||
<PanelContainer StyleClasses="BackgroundPanel" ModulateSelfOverride="#2b2b31"/>
|
||||
<BoxContainer Orientation="Vertical">
|
||||
|
||||
<!-- Title -->
|
||||
<PanelContainer StyleIdentifier="FeedbackBorderThinBottom">
|
||||
<RichTextLabel Name="TitleLabel" Margin="12 6 6 6" />
|
||||
</PanelContainer>
|
||||
|
||||
<!-- Description -->
|
||||
<RichTextLabel Name="DescriptionLabel" StyleClasses="LabelLight" Margin="12 4 12 8" VerticalExpand="True"/>
|
||||
|
||||
<!-- Footer -->
|
||||
<PanelContainer StyleIdentifier="FeedbackBorderThinTop">
|
||||
<BoxContainer>
|
||||
<Label FontColorOverride="#b1b1b2" StyleClasses="LabelSmall" Name="TypeLabel" Margin="14 6 6 6" />
|
||||
<Button Name="LinkButton" Text="{Loc feedbackpopup-control-button-text}" MinWidth="80"
|
||||
Margin="8 6 14 6" HorizontalExpand="True" HorizontalAlignment="Right" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
54
Content.Client/FeedbackPopup/FeedbackEntry.xaml.cs
Normal file
54
Content.Client/FeedbackPopup/FeedbackEntry.xaml.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using Content.Shared.FeedbackSystem;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.FeedbackPopup;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class FeedbackEntry : Control
|
||||
{
|
||||
private readonly IUriOpener _uri;
|
||||
|
||||
private readonly FeedbackPopupPrototype? _prototype;
|
||||
|
||||
public FeedbackEntry(ProtoId<FeedbackPopupPrototype> popupProto, IPrototypeManager proto, IUriOpener uri)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
_uri = uri;
|
||||
|
||||
_prototype = proto.Index(popupProto);
|
||||
|
||||
// Title
|
||||
TitleLabel.Text = _prototype.Title;
|
||||
DescriptionLabel.Text = _prototype.Description;
|
||||
TypeLabel.Text = _prototype.ResponseType;
|
||||
|
||||
LinkButton.Visible = !string.IsNullOrEmpty(_prototype.ResponseLink);
|
||||
|
||||
// link button
|
||||
if (!string.IsNullOrEmpty(_prototype.ResponseLink))
|
||||
{
|
||||
LinkButton.OnPressed += OnButtonPressed;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnButtonPressed(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(_prototype?.ResponseLink))
|
||||
_uri.OpenUri(_prototype.ResponseLink);
|
||||
}
|
||||
|
||||
protected override void Resized()
|
||||
{
|
||||
base.Resized();
|
||||
// magic
|
||||
TitleLabel.SetWidth = Width - TitleLabel.Margin.SumHorizontal;
|
||||
TitleLabel.InvalidateArrange();
|
||||
DescriptionLabel.SetWidth = Width - DescriptionLabel.Margin.SumHorizontal;
|
||||
DescriptionLabel.InvalidateArrange();
|
||||
}
|
||||
}
|
||||
|
||||
36
Content.Client/FeedbackPopup/FeedbackPopupSheetlet.cs
Normal file
36
Content.Client/FeedbackPopup/FeedbackPopupSheetlet.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Content.Client.Stylesheets;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using static Content.Client.Stylesheets.StylesheetHelpers;
|
||||
|
||||
namespace Content.Client.FeedbackPopup;
|
||||
|
||||
[CommonSheetlet]
|
||||
public sealed class FeedbackPopupSheetlet : Sheetlet<PalettedStylesheet>
|
||||
{
|
||||
public override StyleRule[] GetRules(PalettedStylesheet sheet, object config)
|
||||
{
|
||||
var borderTop = new StyleBoxFlat()
|
||||
{
|
||||
BorderColor = sheet.SecondaryPalette.Base,
|
||||
BorderThickness = new Thickness(0, 1, 0, 0),
|
||||
};
|
||||
|
||||
var borderBottom = new StyleBoxFlat()
|
||||
{
|
||||
BorderColor = sheet.SecondaryPalette.Base,
|
||||
BorderThickness = new Thickness(0, 0, 0, 1),
|
||||
};
|
||||
|
||||
return
|
||||
[
|
||||
E<PanelContainer>()
|
||||
.Identifier("FeedbackBorderThinTop")
|
||||
.Prop(PanelContainer.StylePropertyPanel, borderTop),
|
||||
E<PanelContainer>()
|
||||
.Identifier("FeedbackBorderThinBottom")
|
||||
.Prop(PanelContainer.StylePropertyPanel, borderBottom),
|
||||
];
|
||||
}
|
||||
}
|
||||
75
Content.Client/FeedbackPopup/FeedbackPopupUIController.cs
Normal file
75
Content.Client/FeedbackPopup/FeedbackPopupUIController.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using Content.Shared.FeedbackSystem;
|
||||
using Content.Shared.GameTicking;
|
||||
using Robust.Client.UserInterface.Controllers;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.FeedbackPopup;
|
||||
|
||||
/// <summary>
|
||||
/// This handles getting feedback popup messages from the server and making a popup in the client.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public sealed class FeedbackPopupUIController : UIController
|
||||
{
|
||||
[Dependency] private readonly ClientFeedbackManager _feedbackManager = null!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = null!;
|
||||
[Dependency] private readonly IUriOpener _uri = null!;
|
||||
|
||||
private FeedbackPopupWindow _window = null!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_window = new FeedbackPopupWindow(_proto, _uri);
|
||||
|
||||
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReloaded);
|
||||
SubscribeNetworkEvent<RoundEndMessageEvent>(OnRoundEnd);
|
||||
|
||||
_feedbackManager.DisplayedPopupsChanged += OnPopupsChanged;
|
||||
}
|
||||
|
||||
public void ToggleWindow()
|
||||
{
|
||||
if (_window.IsOpen)
|
||||
{
|
||||
_window.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
_window.OpenCentered();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRoundEnd(RoundEndMessageEvent ev, EntitySessionEventArgs args)
|
||||
{
|
||||
// Add round end prototypes.
|
||||
var roundEndPrototypes = _feedbackManager.GetOriginFeedbackPrototypes(true);
|
||||
if (roundEndPrototypes.Count == 0)
|
||||
return;
|
||||
|
||||
_feedbackManager.Display(roundEndPrototypes);
|
||||
|
||||
// Even if no new prototypes were added, we still want to open the window.
|
||||
if (!_window.IsOpen)
|
||||
_window.OpenCentered();
|
||||
}
|
||||
|
||||
private void OnPopupsChanged(bool newPopups)
|
||||
{
|
||||
UpdateWindow(_feedbackManager.DisplayedPopups);
|
||||
|
||||
if (newPopups && !_window.IsOpen)
|
||||
_window.OpenCentered();
|
||||
}
|
||||
|
||||
private void OnPrototypesReloaded(PrototypesReloadedEventArgs ev)
|
||||
{
|
||||
UpdateWindow(_feedbackManager.DisplayedPopups);
|
||||
}
|
||||
|
||||
private void UpdateWindow(IReadOnlyCollection<ProtoId<FeedbackPopupPrototype>> prototypes)
|
||||
{
|
||||
_window.Update(prototypes);
|
||||
}
|
||||
}
|
||||
24
Content.Client/FeedbackPopup/FeedbackPopupWindow.xaml
Normal file
24
Content.Client/FeedbackPopup/FeedbackPopupWindow.xaml
Normal file
@@ -0,0 +1,24 @@
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
Title="{Loc feedbackpopup-window-name}" MinSize="510 460" RectClipContent="True">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
|
||||
<!-- main box area -->
|
||||
<BoxContainer Margin="12 12 12 5" VerticalExpand="True">
|
||||
<PanelContainer HorizontalExpand="True" StyleClasses="PanelDark">
|
||||
<ScrollContainer HorizontalExpand="True" HScrollEnabled="False">
|
||||
<BoxContainer Name="NotificationContainer" HorizontalExpand="True" Orientation="Vertical" Margin="10" SeparationOverride="10" />
|
||||
</ScrollContainer>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Footer -->
|
||||
<BoxContainer Orientation="Vertical" SetHeight="30" Margin="2 0 0 0">
|
||||
<BoxContainer SetHeight="33" Margin="10 0 10 5">
|
||||
<Label Text="{Loc feedbackpopup-control-ui-footer}" Margin="6 0" StyleClasses="PdaContentFooterText"/>
|
||||
<Label Name="NumNotifications" Margin="6 0" HorizontalExpand="True" HorizontalAlignment="Right"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</controls:FancyWindow>
|
||||
49
Content.Client/FeedbackPopup/FeedbackPopupWindow.xaml.cs
Normal file
49
Content.Client/FeedbackPopup/FeedbackPopupWindow.xaml.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.FeedbackSystem;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.FeedbackPopup;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class FeedbackPopupWindow : FancyWindow
|
||||
{
|
||||
private readonly IPrototypeManager _proto;
|
||||
private readonly IUriOpener _uri;
|
||||
|
||||
public FeedbackPopupWindow(IPrototypeManager proto, IUriOpener uri)
|
||||
{
|
||||
_proto = proto;
|
||||
_uri = uri;
|
||||
RobustXamlLoader.Load(this);
|
||||
DisplayNoEntryLabel();
|
||||
}
|
||||
|
||||
public void Update(IReadOnlyCollection<ProtoId<FeedbackPopupPrototype>> prototypes)
|
||||
{
|
||||
NotificationContainer.RemoveAllChildren();
|
||||
|
||||
if (prototypes.Count == 0)
|
||||
DisplayNoEntryLabel();
|
||||
|
||||
foreach (var proto in prototypes)
|
||||
{
|
||||
NotificationContainer.AddChild(new FeedbackEntry(proto, _proto, _uri));
|
||||
}
|
||||
|
||||
NumNotifications.Text = Loc.GetString("feedbackpopup-control-total-surveys", ("num", prototypes.Count));
|
||||
}
|
||||
|
||||
private void DisplayNoEntryLabel()
|
||||
{
|
||||
NotificationContainer.AddChild(new Label()
|
||||
{
|
||||
Text = Loc.GetString("feedbackpopup-control-no-entries"),
|
||||
HorizontalAlignment = HAlignment.Center,
|
||||
VerticalAlignment = VAlignment.Center,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace Content.Client.Guidebook.RichText;
|
||||
|
||||
/// <summary>
|
||||
/// RichText tag that can display values extracted from entity prototypes.
|
||||
/// In order to be accessed by this tag, the desired field/property must
|
||||
/// To be accessed by this tag, the desired field/property must
|
||||
/// be tagged with <see cref="Shared.Guidebook.GuidebookDataAttribute"/>.
|
||||
/// </summary>
|
||||
public sealed class ProtodataTag : IMarkupTagHandler
|
||||
|
||||
@@ -4,6 +4,7 @@ using Content.Client.Chat.Managers;
|
||||
using Content.Client.Clickable;
|
||||
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;
|
||||
@@ -23,6 +24,7 @@ using Content.Client.Lobby;
|
||||
using Content.Client.Players.RateLimiting;
|
||||
using Content.Shared.Administration.Managers;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.FeedbackSystem;
|
||||
using Content.Shared.IoC;
|
||||
using Content.Shared.Players.PlayTimeTracking;
|
||||
using Content.Shared.Players.RateLimiting;
|
||||
@@ -62,6 +64,8 @@ namespace Content.Client.IoC
|
||||
collection.Register<SharedPlayerRateLimitManager, PlayerRateLimitManager>();
|
||||
collection.Register<TitleWindowManager>();
|
||||
collection.Register<ClientsidePlaytimeTrackingManager>();
|
||||
collection.Register<ClientFeedbackManager>();
|
||||
collection.Register<ISharedFeedbackManager, ClientFeedbackManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<Button Access="Public" Name="GuidebookButton" Text="{Loc 'ui-escape-guidebook'}" />
|
||||
<Button Access="Public" Name="WikiButton" Text="{Loc 'ui-escape-wiki'}" />
|
||||
<changelog:ChangelogButton Access="Public" Name="ChangelogButton" />
|
||||
<Button Access="Public" Name="FeedbackButton" Text="{Loc 'ui-escape-feedback'}"/>
|
||||
<PanelContainer StyleClasses="LowDivider" Margin="0 2.5 0 2.5" />
|
||||
<Button Access="Public" Name="OptionsButton" Text="{Loc 'ui-escape-options'}" />
|
||||
<PanelContainer StyleClasses="LowDivider" Margin="0 2.5 0 2.5" />
|
||||
|
||||
@@ -1345,7 +1345,6 @@ namespace Content.Client.Stylesheets
|
||||
|
||||
Element<Label>().Class(StyleClassLabelSmall)
|
||||
.Prop(Label.StylePropertyFont, notoSans10),
|
||||
// ---
|
||||
|
||||
// Different Background shapes ---
|
||||
Element<PanelContainer>().Class(ClassAngleRect)
|
||||
@@ -1608,6 +1607,29 @@ namespace Content.Client.Stylesheets
|
||||
BackgroundColor = FancyTreeSelectedRowColor,
|
||||
}),
|
||||
|
||||
// Inset background (News manager, notifications)
|
||||
Element<PanelContainer>().Class("InsetBackground")
|
||||
.Prop(PanelContainer.StylePropertyPanel, new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = Color.FromHex("#202023"),
|
||||
}),
|
||||
|
||||
// Default fancy window border styles
|
||||
Element<PanelContainer>().Class("DefaultBorderBottom")
|
||||
.Prop(PanelContainer.StylePropertyPanel, new StyleBoxFlat
|
||||
{
|
||||
BorderColor= Color.FromHex("#3B3E56"),
|
||||
BorderThickness= new Thickness(0, 0, 0, 1),
|
||||
}),
|
||||
|
||||
|
||||
Element<PanelContainer>().Class("DefaultBorderTop")
|
||||
.Prop(PanelContainer.StylePropertyPanel, new StyleBoxFlat
|
||||
{
|
||||
BorderColor= Color.FromHex("#3B3E56"),
|
||||
BorderThickness= new Thickness(0, 1, 0, 0),
|
||||
}),
|
||||
|
||||
// Silicon law edit ui
|
||||
Element<Label>().Class(SiliconLawContainer.StyleClassSiliconLawPositionLabel)
|
||||
.Prop(Label.StylePropertyFontColor, NanoGold),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Client.Gameplay;
|
||||
using Content.Client.FeedbackPopup;
|
||||
using Content.Client.Gameplay;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Client.UserInterface.Systems.Guidebook;
|
||||
using Content.Client.UserInterface.Systems.Info;
|
||||
@@ -25,6 +26,7 @@ public sealed class EscapeUIController : UIController, IOnStateEntered<GameplayS
|
||||
[Dependency] private readonly InfoUIController _info = default!;
|
||||
[Dependency] private readonly OptionsUIController _options = default!;
|
||||
[Dependency] private readonly GuidebookUIController _guidebook = default!;
|
||||
[Dependency] private readonly FeedbackPopupUIController _feedback = null!;
|
||||
|
||||
private Options.UI.EscapeMenu? _escapeWindow;
|
||||
|
||||
@@ -63,6 +65,12 @@ public sealed class EscapeUIController : UIController, IOnStateEntered<GameplayS
|
||||
_escapeWindow.OnClose += DeactivateButton;
|
||||
_escapeWindow.OnOpen += ActivateButton;
|
||||
|
||||
_escapeWindow.FeedbackButton.OnPressed += _ =>
|
||||
{
|
||||
CloseEscapeWindow();
|
||||
_feedback.ToggleWindow();
|
||||
};
|
||||
|
||||
_escapeWindow.ChangelogButton.OnPressed += _ =>
|
||||
{
|
||||
CloseEscapeWindow();
|
||||
|
||||
@@ -8,6 +8,7 @@ using Content.Server.Connection;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.Discord.DiscordLink;
|
||||
using Content.Server.EUI;
|
||||
using Content.Server.FeedbackSystem;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GhostKick;
|
||||
using Content.Server.GuideGenerator;
|
||||
@@ -23,6 +24,7 @@ using Content.Server.ServerInfo;
|
||||
using Content.Server.ServerUpdates;
|
||||
using Content.Server.Voting.Managers;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.FeedbackSystem;
|
||||
using Content.Shared.Kitchen;
|
||||
using Content.Shared.Localizations;
|
||||
using Robust.Server;
|
||||
@@ -76,6 +78,7 @@ namespace Content.Server.Entry
|
||||
[Dependency] private readonly ServerApi _serverApi = default!;
|
||||
[Dependency] private readonly ServerInfoManager _serverInfo = default!;
|
||||
[Dependency] private readonly ServerUpdateManager _updateManager = default!;
|
||||
[Dependency] private readonly ServerFeedbackManager _feedbackManager = null!;
|
||||
|
||||
public override void PreInit()
|
||||
{
|
||||
@@ -165,6 +168,7 @@ namespace Content.Server.Entry
|
||||
_connection.PostInit();
|
||||
_multiServerKick.Initialize();
|
||||
_cvarCtrl.Initialize();
|
||||
_feedbackManager.Initialize();
|
||||
}
|
||||
|
||||
public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs)
|
||||
|
||||
63
Content.Server/FeedbackSystem/FeedbackCommand.cs
Normal file
63
Content.Server/FeedbackSystem/FeedbackCommand.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.FeedbackSystem;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Toolshed;
|
||||
|
||||
namespace Content.Server.FeedbackSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Adds, removes, and displays feedback for specified sessions.
|
||||
/// </summary>
|
||||
[ToolshedCommand]
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public sealed class FeedbackCommand : ToolshedCommand
|
||||
{
|
||||
[Dependency] private readonly ISharedFeedbackManager _feedback = null!;
|
||||
|
||||
[CommandImplementation("show")]
|
||||
public void ExecuteShow([CommandArgument] ICommonSession session)
|
||||
{
|
||||
_feedback.OpenForSession(session);
|
||||
}
|
||||
|
||||
[CommandImplementation("show")]
|
||||
public void ExecuteShow([PipedArgument] IEnumerable<ICommonSession> sessions)
|
||||
{
|
||||
foreach (var session in sessions)
|
||||
{
|
||||
_feedback.OpenForSession(session);
|
||||
}
|
||||
}
|
||||
|
||||
[CommandImplementation("add")]
|
||||
public void ExecuteAdd([CommandArgument] ICommonSession session, ProtoId<FeedbackPopupPrototype> protoId)
|
||||
{
|
||||
_feedback.SendToSession(session, [protoId]);
|
||||
}
|
||||
|
||||
[CommandImplementation("add")]
|
||||
public void ExecuteAdd([PipedArgument] IEnumerable<ICommonSession> sessions, ProtoId<FeedbackPopupPrototype> protoId)
|
||||
{
|
||||
foreach (var session in sessions)
|
||||
{
|
||||
_feedback.SendToSession(session, [protoId]);
|
||||
}
|
||||
}
|
||||
|
||||
[CommandImplementation("remove")]
|
||||
public void ExecuteRemove([CommandArgument] ICommonSession session, ProtoId<FeedbackPopupPrototype> protoId)
|
||||
{
|
||||
_feedback.SendToSession(session, [protoId], true);
|
||||
}
|
||||
|
||||
[CommandImplementation("remove")]
|
||||
public void ExecuteRemove([PipedArgument] IEnumerable<ICommonSession> sessions, ProtoId<FeedbackPopupPrototype> protoId)
|
||||
{
|
||||
foreach (var session in sessions)
|
||||
{
|
||||
_feedback.SendToSession(session, [protoId], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Content.Server/FeedbackSystem/OpenFeedbackPopupCommand.cs
Normal file
24
Content.Server/FeedbackSystem/OpenFeedbackPopupCommand.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.FeedbackSystem;
|
||||
using Robust.Shared.Toolshed;
|
||||
|
||||
namespace Content.Server.FeedbackSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Opens the feedback popup window for the executing session
|
||||
/// </summary>
|
||||
[AnyCommand]
|
||||
[ToolshedCommand]
|
||||
public sealed class OpenFeedbackPopupCommand : ToolshedCommand
|
||||
{
|
||||
[Dependency] private readonly ISharedFeedbackManager _feedback = null!;
|
||||
|
||||
[CommandImplementation]
|
||||
public void Execute(IInvocationContext context)
|
||||
{
|
||||
if (context.Session == null)
|
||||
return;
|
||||
|
||||
_feedback.OpenForSession(context.Session);
|
||||
}
|
||||
}
|
||||
78
Content.Server/FeedbackSystem/ServerFeedbackManager.cs
Normal file
78
Content.Server/FeedbackSystem/ServerFeedbackManager.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using Content.Shared.FeedbackSystem;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.FeedbackSystem;
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed class ServerFeedbackManager : SharedFeedbackManager
|
||||
{
|
||||
[Dependency] private readonly ISharedPlayerManager _player = null!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
NetManager.RegisterNetMessage<FeedbackPopupMessage>();
|
||||
NetManager.RegisterNetMessage<OpenFeedbackPopupMessage>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Send(EntityUid uid, List<ProtoId<FeedbackPopupPrototype>> popupPrototypes)
|
||||
{
|
||||
if (!_player.TryGetSessionByEntity(uid, out var session))
|
||||
return false;
|
||||
|
||||
SendToSession(session, popupPrototypes);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SendToSession(ICommonSession session, List<ProtoId<FeedbackPopupPrototype>> popupPrototypes, bool remove = false)
|
||||
{
|
||||
if (!NetManager.IsServer)
|
||||
return;
|
||||
|
||||
var msg = new FeedbackPopupMessage
|
||||
{
|
||||
FeedbackPrototypes = popupPrototypes,
|
||||
Remove = remove,
|
||||
};
|
||||
|
||||
NetManager.ServerSendMessage(msg, session.Channel);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SendToAllSessions(List<ProtoId<FeedbackPopupPrototype>> popupPrototypes, bool remove = false)
|
||||
{
|
||||
if (!NetManager.IsServer)
|
||||
return;
|
||||
|
||||
var msg = new FeedbackPopupMessage
|
||||
{
|
||||
FeedbackPrototypes = popupPrototypes,
|
||||
Remove = remove,
|
||||
};
|
||||
|
||||
NetManager.ServerSendToAll(msg);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OpenForSession(ICommonSession session)
|
||||
{
|
||||
if (!NetManager.IsServer)
|
||||
return;
|
||||
|
||||
var msg = new OpenFeedbackPopupMessage();
|
||||
NetManager.ServerSendMessage(msg, session.Channel);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OpenForAllSessions()
|
||||
{
|
||||
if (!NetManager.IsServer)
|
||||
return;
|
||||
|
||||
var msg = new OpenFeedbackPopupMessage();
|
||||
NetManager.ServerSendToAll(msg);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ using Content.Server.Discord;
|
||||
using Content.Server.Discord.DiscordLink;
|
||||
using Content.Server.Discord.WebhookMessages;
|
||||
using Content.Server.EUI;
|
||||
using Content.Server.FeedbackSystem;
|
||||
using Content.Server.GhostKick;
|
||||
using Content.Server.Info;
|
||||
using Content.Server.Mapping;
|
||||
@@ -26,6 +27,7 @@ using Content.Server.Worldgen.Tools;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Administration.Managers;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.FeedbackSystem;
|
||||
using Content.Shared.IoC;
|
||||
using Content.Shared.Kitchen;
|
||||
using Content.Shared.Players.PlayTimeTracking;
|
||||
@@ -80,5 +82,7 @@ internal static class ServerContentIoC
|
||||
deps.Register<CVarControlManager>();
|
||||
deps.Register<DiscordLink>();
|
||||
deps.Register<DiscordChatLink>();
|
||||
deps.Register<ServerFeedbackManager>();
|
||||
deps.Register<ISharedFeedbackManager, ServerFeedbackManager>();
|
||||
}
|
||||
}
|
||||
|
||||
17
Content.Shared/CCVar/CCVars.Feedback.cs
Normal file
17
Content.Shared/CCVar/CCVars.Feedback.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Shared.CCVar;
|
||||
|
||||
public sealed partial class CCVars
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to set what popups are shown. Can accept multiple origins, just use spaces! See
|
||||
/// <see cref="Content.Shared.FeedbackSystem.FeedbackPopupPrototype">FeedbackPopupPrototype</see>'s <see cref="Content.Shared.FeedbackSystem.FeedbackPopupPrototype.PopupOrigin">PopupOrigin</see> field.
|
||||
/// Only prototypes who's PopupOrigin matches one of the FeedbackValidOrigins will be shown to players.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// wizden deltav
|
||||
/// </example>
|
||||
public static readonly CVarDef<string> FeedbackValidOrigins =
|
||||
CVarDef.Create("feedback.valid_origins", "", CVar.SERVER | CVar.REPLICATED);
|
||||
}
|
||||
61
Content.Shared/FeedbackSystem/FeedbackPopupMessage.cs
Normal file
61
Content.Shared/FeedbackSystem/FeedbackPopupMessage.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.FeedbackSystem;
|
||||
|
||||
/// <summary>
|
||||
/// When clients receive this message a popup will appear with the contents from the given prototypes.
|
||||
/// </summary>
|
||||
public sealed class FeedbackPopupMessage : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
|
||||
/// <summary>
|
||||
/// When true, the popup prototypes specified in this message will be removed from the client's list of feedback popups.
|
||||
/// If no prototypes are specified, all popups will be removed.
|
||||
/// </summary>
|
||||
/// <remarks>If this is false and the list of prototypes is empty, the message will be ignored</remarks>
|
||||
public bool Remove { get; set; }
|
||||
public List<ProtoId<FeedbackPopupPrototype>>? FeedbackPrototypes;
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
Remove = buffer.ReadBoolean();
|
||||
buffer.ReadPadBits();
|
||||
|
||||
var count = buffer.ReadVariableInt32();
|
||||
FeedbackPrototypes = [];
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
FeedbackPrototypes.Add(new ProtoId<FeedbackPopupPrototype>(buffer.ReadString()));
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer)
|
||||
{
|
||||
buffer.Write(Remove);
|
||||
buffer.WritePadBits();
|
||||
buffer.WriteVariableInt32(FeedbackPrototypes?.Count ?? 0);
|
||||
|
||||
if (FeedbackPrototypes == null)
|
||||
return;
|
||||
|
||||
foreach (var proto in FeedbackPrototypes)
|
||||
{
|
||||
buffer.Write(proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sent from the server to open the feedback popup.
|
||||
/// </summary>
|
||||
public sealed class OpenFeedbackPopupMessage : NetMessage
|
||||
{
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer) { }
|
||||
|
||||
public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer) { }
|
||||
}
|
||||
56
Content.Shared/FeedbackSystem/FeedbackPopupPrototype.cs
Normal file
56
Content.Shared/FeedbackSystem/FeedbackPopupPrototype.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.FeedbackSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Prototype that describes the contents of a feedback popup.
|
||||
/// </summary>
|
||||
[Prototype]
|
||||
public sealed partial class FeedbackPopupPrototype : IPrototype
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[IdDataField]
|
||||
public string ID { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// What server the popup is from, you must edit the ccvar to include this for the popup to appear!
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public string PopupOrigin = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Title of the popup. This supports rich text so you can use colors and stuff.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public string Title = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// List of "paragraphs" that are placed in the middle of the popup. Put any relevant information about what to give
|
||||
/// feedback on here! [bold]Rich text is allowed[/bold]
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public string Description = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The kind of response the player should expect to give; good examples are "Survey", "Discord Channel", "Feedback Thread" etc.
|
||||
/// Will be listed near the "Open Link" button; rich text is not allowed.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string? ResponseType;
|
||||
|
||||
/// <summary>
|
||||
/// A link leading to where you want players to give feedback. Discord channel, form etc...
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string? ResponseLink;
|
||||
|
||||
/// <summary>
|
||||
/// Should this feedback be shown when the round ends.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this is false popups have to be shown to players by running the <pre>feedback:add</pre> command.<br />
|
||||
/// This allows admins to show popups to only specific people.
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
public bool ShowRoundEnd = true;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.GameTicking;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Shared.FeedbackSystem;
|
||||
|
||||
public abstract partial class SharedFeedbackManager : IEntityEventSubscriber
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _configManager = null!;
|
||||
|
||||
private void InitSubscriptions()
|
||||
{
|
||||
_configManager.OnValueChanged(CCVars.FeedbackValidOrigins, OnFeedbackOriginsUpdated, true);
|
||||
}
|
||||
|
||||
private void OnFeedbackOriginsUpdated(string newOrigins)
|
||||
{
|
||||
_validOrigins = newOrigins.Split(' ').ToList();
|
||||
}
|
||||
}
|
||||
150
Content.Shared/FeedbackSystem/SharedFeedbackManager.cs
Normal file
150
Content.Shared/FeedbackSystem/SharedFeedbackManager.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using System.Linq;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.FeedbackSystem;
|
||||
|
||||
/// <summary>
|
||||
/// SharedFeedbackManager handles feedback popup management and distribution across sessions.
|
||||
/// It manages the state of displayed popups and provides mechanisms for opening, displaying, removing,
|
||||
/// and sending popups to specified sessions or all sessions.
|
||||
/// </summary>
|
||||
public interface ISharedFeedbackManager
|
||||
{
|
||||
/// <summary>
|
||||
/// An event that is triggered whenever the set of displayed feedback popups changes.<br/>
|
||||
/// The boolean parameter is true if new popups have been added
|
||||
/// </summary>
|
||||
event Action<bool>? DisplayedPopupsChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified popup prototypes to the displayed popups on the client..
|
||||
/// </summary>
|
||||
/// <param name="prototypes">A list of popup prototype IDs to be added to the displayed prototypes</param>
|
||||
/// <remarks>
|
||||
/// This does nothing on the server.
|
||||
/// <br/>
|
||||
/// Use this if you want to add a popup from a shared or client-side entity system.
|
||||
/// </remarks>
|
||||
void Display(List<ProtoId<FeedbackPopupPrototype>>? prototypes) {}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified popup prototypes from the displayed popups on the client.
|
||||
/// </summary>
|
||||
/// <param name="prototypes">A list of popup prototype IDs to be removed from the displayed prototypes.
|
||||
/// If null, all displayed popups will be cleared.</param>
|
||||
/// <remarks>This does nothing on the server.</remarks>
|
||||
void Remove(List<ProtoId<FeedbackPopupPrototype>>? prototypes) {}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a list of feedback popup prototypes to a specific entity, identified by its EntityUid.
|
||||
/// </summary>
|
||||
/// <param name="uid">The unique identifier of the entity to send the feedback popups to.</param>
|
||||
/// <param name="popupPrototypes">The list of feedback popup prototypes to send to the entity.</param>
|
||||
/// <returns>Returns true if the feedback popups were successfully sent, otherwise false.</returns>
|
||||
/// <remarks>This does nothing on the client.</remarks>
|
||||
bool Send(EntityUid uid, List<ProtoId<FeedbackPopupPrototype>> popupPrototypes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a list of feedback popup prototypes to the specified session.
|
||||
/// </summary>
|
||||
/// <param name="session">The session to which the feedback popups will be sent.</param>
|
||||
/// <param name="popupPrototypes">A list of feedback popup prototype IDs to send to the session.</param>
|
||||
/// <param name="remove">When true, removes the specified prototypes instead of adding them</param>
|
||||
/// <remarks>This does nothing on the client.</remarks>
|
||||
void SendToSession(ICommonSession session, List<ProtoId<FeedbackPopupPrototype>> popupPrototypes, bool remove = false) {}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the specified feedback popup prototypes to all connected client sessions.
|
||||
/// </summary>
|
||||
/// <param name="popupPrototypes">A list of popup prototype IDs to be sent to all connected sessions.</param>
|
||||
/// <param name="remove">When true, removes the specified prototypes instead of adding them</param>
|
||||
/// <remarks>This does nothing on the client.</remarks>
|
||||
void SendToAllSessions(List<ProtoId<FeedbackPopupPrototype>> popupPrototypes, bool remove = false) {}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the feedback popup for a specific session.
|
||||
/// </summary>
|
||||
/// <param name="session">The session for which the feedback popup should be opened.</param>
|
||||
/// <remarks>This does nothing on the client.</remarks>
|
||||
void OpenForSession(ICommonSession session) {}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the feedback popup for all connected sessions.
|
||||
/// </summary>
|
||||
/// <remarks>This does nothing on the client.</remarks>
|
||||
void OpenForAllSessions() {}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ISharedFeedbackManager" />
|
||||
public abstract partial class SharedFeedbackManager : ISharedFeedbackManager
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _proto = null!;
|
||||
[Dependency] protected readonly INetManager NetManager = null!;
|
||||
|
||||
public virtual IReadOnlySet<ProtoId<FeedbackPopupPrototype>>? DisplayedPopups => null;
|
||||
|
||||
// <inheritdoc />
|
||||
public event Action<bool>? DisplayedPopupsChanged;
|
||||
|
||||
/// <summary>
|
||||
/// List of valid origns of the feedback popup that is filled from the CCVar. See
|
||||
/// <see cref="Content.Shared.CCVar.CCVars.FeedbackValidOrigins">FeedbackValidOrigins</see>
|
||||
/// </summary>
|
||||
private List<string> _validOrigins = [];
|
||||
|
||||
[MustCallBase]
|
||||
public virtual void Initialize()
|
||||
{
|
||||
InitSubscriptions();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Display(List<ProtoId<FeedbackPopupPrototype>>? prototypes) {}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Remove(List<ProtoId<FeedbackPopupPrototype>>? prototypes) {}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool Send(EntityUid uid, List<ProtoId<FeedbackPopupPrototype>> popupPrototypes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void SendToSession(ICommonSession session, List<ProtoId<FeedbackPopupPrototype>> popupPrototypes, bool remove = false) {}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void SendToAllSessions(List<ProtoId<FeedbackPopupPrototype>> popupPrototypes, bool remove = false) {}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void OpenForSession(ICommonSession session) {}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void OpenForAllSessions() {}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of feedback prototypes that match the current valid origins.
|
||||
/// </summary>
|
||||
/// <param name="roundEndOnly">If true, only retrieve pop-ups with ShowRoundEnd set to true.</param>
|
||||
/// <returns>Returns a list of protoIds; possibly empty.</returns>
|
||||
public List<ProtoId<FeedbackPopupPrototype>> GetOriginFeedbackPrototypes(bool roundEndOnly)
|
||||
{
|
||||
var feedbackProtypes = _proto.EnumeratePrototypes<FeedbackPopupPrototype>()
|
||||
.Where(x => (!roundEndOnly || x.ShowRoundEnd) && _validOrigins.Contains(x.PopupOrigin))
|
||||
.Select(x => new ProtoId<FeedbackPopupPrototype>(x.ID))
|
||||
.OrderBy(x => x.Id)
|
||||
.ToList();
|
||||
|
||||
return feedbackProtypes;
|
||||
}
|
||||
|
||||
protected void InvokeDisplayedPopupsChanged(bool show)
|
||||
{
|
||||
DisplayedPopupsChanged?.Invoke(show);
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,4 @@ ui-escape-guidebook = Guidebook
|
||||
ui-escape-wiki = Wiki
|
||||
ui-escape-disconnect = Disconnect
|
||||
ui-escape-quit = Quit
|
||||
|
||||
ui-escape-feedback = Feedback
|
||||
|
||||
28
Resources/Locale/en-US/feedbackpopup/feedbackpopup.ftl
Normal file
28
Resources/Locale/en-US/feedbackpopup/feedbackpopup.ftl
Normal file
@@ -0,0 +1,28 @@
|
||||
feedbackpopup-window-name = Request for feedback
|
||||
|
||||
feedbackpopup-control-button-text = Open Link
|
||||
|
||||
feedbackpopup-control-total-surveys = {$num ->
|
||||
[one] {$num} entry
|
||||
*[other] {$num} entries
|
||||
}
|
||||
feedbackpopup-control-no-entries= No entries
|
||||
feedbackpopup-control-ui-footer = Let us know what you think!
|
||||
|
||||
# Command strings
|
||||
command-description-openfeedbackpopup = Opens the feedback popup window.
|
||||
command-description-feedback-show = Opens the feedback popup window for the given sessions.
|
||||
command-description-feedback-add = Adds a feedback popup prototype to the given clients and opens the popup window if the client didn't already have the prototype listed.
|
||||
command-description-feedback-remove = Removes a feedback popup prototype from the given clients.
|
||||
|
||||
feedbackpopup-give-command-name = givefeedbackpopup
|
||||
feedbackpopup-show-command-name = showfeedbackpopup
|
||||
cmd-givefeedbackpopup-desc = Gives the targeted player a feedback popup.
|
||||
cmd-givefeedbackpopup-help = Usage: givefeedbackpopup <playerUid> <prototypeId>
|
||||
cmd-showfeedbackpopup-desc = Open the feedback popup window.
|
||||
cmd-showfeedbackpopup-help = Usage: showfeedbackpopup
|
||||
feedbackpopup-command-error-invalid-proto = Invalid feedback popup prototype.
|
||||
feedbackpopup-command-error-popup-send-fail = Failed to send popup! There probably isn't a mind attached to the given entity.
|
||||
feedbackpopup-command-success = Sent popup!
|
||||
feedbackpopup-command-hint-playerUid = <playerUid>
|
||||
feedbackpopup-command-hint-protoId = <prototypeId>
|
||||
19
Resources/Prototypes/FeedbackPopup/feedbackpopups.yml
Normal file
19
Resources/Prototypes/FeedbackPopup/feedbackpopups.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
- type: feedbackPopup
|
||||
id: FeedbackPopup
|
||||
popupOrigin: wizden_master
|
||||
title: "[bold]Feedback on the new feedback popup system[/bold]"
|
||||
description: |-
|
||||
This window you are seeing is a new system to get feedback on features. It will give popups at the end of the round (mostly on our testing server Vulture)!
|
||||
Please share your thoughts through the forums below! Log in with your Space Station 14 account!
|
||||
responseType: "Feedback Thread A"
|
||||
responseLink: "https://forum.spacestation14.com/t/feedback-popup-feedback/22858"
|
||||
|
||||
- type: feedbackPopup
|
||||
id: GeneralFeedback
|
||||
popupOrigin: wizden_master
|
||||
title: "[bold]General feedback for the game[/bold]"
|
||||
description: >-
|
||||
If you have any feedback on the game, feel free to create a thread in the feedback forum category.
|
||||
responseType: "General Feedback"
|
||||
responseLink: "https://forum.spacestation14.com/c/development/feedback/51"
|
||||
showRoundEnd: false
|
||||
Reference in New Issue
Block a user