diff --git a/Content.Client/Consent/ClientConsentManager.cs b/Content.Client/Consent/ClientConsentManager.cs new file mode 100644 index 00000000000..259b2dfe28e --- /dev/null +++ b/Content.Client/Consent/ClientConsentManager.cs @@ -0,0 +1,45 @@ +using Content.Shared.Consent; +using Robust.Shared.Network; + +namespace Content.Client.Consent; + +public sealed class ClientConsentManager : IClientConsentManager +{ + [Dependency] private readonly IClientNetManager _netManager = default!; + + // TODO: sync all players consent settings with ServerConsentManager, for client prediction + private PlayerConsentSettings? _consent; + + public bool HasLoaded => _consent is not null; + + public event Action? OnServerDataLoaded; + + public void Initialize() + { + _netManager.RegisterNetMessage(HandleUpdateConsent); + } + + public void UpdateConsent(PlayerConsentSettings consentSettings) + { + var msg = new MsgUpdateConsent + { + Consent = consentSettings + }; + _netManager.ClientSendMessage(msg); + } + + public PlayerConsentSettings GetConsent() + { + if (_consent is null) + throw new InvalidOperationException("Consent settings not loaded yet?"); + + return _consent; + } + + private void HandleUpdateConsent(MsgUpdateConsent message) + { + _consent = message.Consent; + + OnServerDataLoaded?.Invoke(); + } +} diff --git a/Content.Client/Consent/ConsentSystem.cs b/Content.Client/Consent/ConsentSystem.cs new file mode 100644 index 00000000000..8c3fb9c46c7 --- /dev/null +++ b/Content.Client/Consent/ConsentSystem.cs @@ -0,0 +1,7 @@ +using Content.Shared.Consent; + +namespace Content.Client.Consent; + +public sealed class ConsentSystem : SharedConsentSystem +{ +} diff --git a/Content.Client/Consent/IClientConsentManager.cs b/Content.Client/Consent/IClientConsentManager.cs new file mode 100644 index 00000000000..1f0e22d52ef --- /dev/null +++ b/Content.Client/Consent/IClientConsentManager.cs @@ -0,0 +1,13 @@ +using Content.Shared.Consent; + +namespace Content.Client.Consent; + +public interface IClientConsentManager +{ + event Action OnServerDataLoaded; + bool HasLoaded { get; } + + void Initialize(); + void UpdateConsent(PlayerConsentSettings consentSettings); + PlayerConsentSettings GetConsent(); +} diff --git a/Content.Client/Consent/UI/ConsentUiController.cs b/Content.Client/Consent/UI/ConsentUiController.cs new file mode 100644 index 00000000000..c0b91da8620 --- /dev/null +++ b/Content.Client/Consent/UI/ConsentUiController.cs @@ -0,0 +1,102 @@ +using Content.Client.Consent.UI.Windows; +using Content.Client.Gameplay; +using Content.Client.UserInterface.Controls; +using Content.Client.UserInterface.Systems.MenuBar.Widgets; +using Content.Shared.Input; +using Robust.Client.Input; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controllers; +using Robust.Client.UserInterface.Controllers.Implementations; +using Robust.Shared.Input.Binding; +using Robust.Shared.Map; +using Robust.Shared.Player; +using Robust.Shared.Utility; +using JetBrains.Annotations; +using static Robust.Client.UserInterface.Controls.BaseButton; + +namespace Content.Client.Consent.UI; + +[UsedImplicitly] +public sealed class ConsentUiController : UIController, IOnStateChanged +{ + [Dependency] private readonly IInputManager _input = default!; + + private ConsentWindow? _window; + + private MenuButton? ConsentButton => UIManager.GetActiveUIWidgetOrNull()?.ConsentButton; + + public void OnStateEntered(GameplayState state) + { + EnsureWindow(); + + _input.SetInputCommand(ContentKeyFunctions.OpenConsentWindow, + InputCmdHandler.FromDelegate(_ => ToggleWindow())); + } + + public void OnStateExited(GameplayState state) + { + if (_window != null) + { + _window.Dispose(); + _window = null; + } + } + + public void UnloadButton() + { + if (ConsentButton == null) + { + return; + } + + ConsentButton.OnPressed -= ConsentButtonPressed; + } + + public void LoadButton() + { + if (ConsentButton == null) + { + return; + } + + ConsentButton.OnPressed += ConsentButtonPressed; + } + + private void ConsentButtonPressed(ButtonEventArgs args) + { + ToggleWindow(); + } + + private void EnsureWindow() + { + if (_window is { Disposed: false }) + return; + + _window = UIManager.CreateWindow(); + _window.OnOpen += () => { + if (ConsentButton is not null) + ConsentButton.Pressed = true; + }; + _window.OnClose += () => { + if (ConsentButton is not null) + ConsentButton.Pressed = false; + _window.UpdateUi(); // Discard unsaved changes + }; + } + + private void ToggleWindow() + { + if (_window is null) + return; + + UIManager.ClickSound(); + if (_window.IsOpen != true) + { + _window.OpenCentered(); + } + else + { + _window.Close(); + } + } +} diff --git a/Content.Client/Consent/UI/Windows/ConsentWindow.xaml b/Content.Client/Consent/UI/Windows/ConsentWindow.xaml new file mode 100644 index 00000000000..09d31a88cdf --- /dev/null +++ b/Content.Client/Consent/UI/Windows/ConsentWindow.xaml @@ -0,0 +1,63 @@ + + +