ChatBox.xaml.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. using Content.Client.UserInterface.Systems.Chat.Controls;
  2. using Content.Shared.Chat;
  3. using Content.Shared.Input;
  4. using Robust.Client.Audio;
  5. using Robust.Client.AutoGenerated;
  6. using Robust.Client.GameObjects;
  7. using Robust.Client.UserInterface;
  8. using Robust.Client.UserInterface.Controls;
  9. using Robust.Client.UserInterface.XAML;
  10. using Robust.Shared.Audio;
  11. using Robust.Shared.Input;
  12. using Robust.Shared.Player;
  13. using Robust.Shared.Utility;
  14. using static Robust.Client.UserInterface.Controls.LineEdit;
  15. namespace Content.Client.UserInterface.Systems.Chat.Widgets;
  16. [GenerateTypedNameReferences]
  17. [Virtual]
  18. public partial class ChatBox : UIWidget
  19. {
  20. private readonly ChatUIController _controller;
  21. private readonly IEntityManager _entManager;
  22. public bool Main { get; set; }
  23. public ChatSelectChannel SelectedChannel => ChatInput.ChannelSelector.SelectedChannel;
  24. public ChatBox()
  25. {
  26. RobustXamlLoader.Load(this);
  27. _entManager = IoCManager.Resolve<IEntityManager>();
  28. ChatInput.Input.OnTextEntered += OnTextEntered;
  29. ChatInput.Input.OnKeyBindDown += OnInputKeyBindDown;
  30. ChatInput.Input.OnTextChanged += OnTextChanged;
  31. ChatInput.ChannelSelector.OnChannelSelect += OnChannelSelect;
  32. ChatInput.FilterButton.Popup.OnChannelFilter += OnChannelFilter;
  33. _controller = UserInterfaceManager.GetUIController<ChatUIController>();
  34. _controller.MessageAdded += OnMessageAdded;
  35. _controller.RegisterChat(this);
  36. }
  37. private void OnTextEntered(LineEditEventArgs args)
  38. {
  39. _controller.SendMessage(this, SelectedChannel);
  40. }
  41. private void OnMessageAdded(ChatMessage msg)
  42. {
  43. Logger.DebugS("chat", $"{msg.Channel}: {msg.Message}");
  44. if (!ChatInput.FilterButton.Popup.IsActive(msg.Channel))
  45. {
  46. return;
  47. }
  48. if (msg is { Read: false, AudioPath: { } })
  49. _entManager.System<AudioSystem>().PlayGlobal(msg.AudioPath, Filter.Local(), false, AudioParams.Default.WithVolume(msg.AudioVolume));
  50. msg.Read = true;
  51. var color = msg.MessageColorOverride ?? msg.Channel.TextColor();
  52. AddLine(msg.WrappedMessage, color);
  53. }
  54. private void OnChannelSelect(ChatSelectChannel channel)
  55. {
  56. _controller.UpdateSelectedChannel(this);
  57. }
  58. public void Repopulate()
  59. {
  60. Contents.Clear();
  61. foreach (var message in _controller.History)
  62. {
  63. OnMessageAdded(message.Item2);
  64. }
  65. }
  66. private void OnChannelFilter(ChatChannel channel, bool active)
  67. {
  68. Contents.Clear();
  69. foreach (var message in _controller.History)
  70. {
  71. OnMessageAdded(message.Item2);
  72. }
  73. if (active)
  74. {
  75. _controller.ClearUnfilteredUnreads(channel);
  76. }
  77. }
  78. public void AddLine(string message, Color color)
  79. {
  80. var formatted = new FormattedMessage(3);
  81. formatted.PushColor(color);
  82. formatted.AddMarkupOrThrow(message);
  83. formatted.Pop();
  84. Contents.AddMessage(formatted);
  85. }
  86. public void Focus(ChatSelectChannel? channel = null)
  87. {
  88. var input = ChatInput.Input;
  89. var selectStart = Index.End;
  90. if (channel != null)
  91. ChatInput.ChannelSelector.Select(channel.Value);
  92. input.IgnoreNext = true;
  93. input.GrabKeyboardFocus();
  94. input.CursorPosition = input.Text.Length;
  95. input.SelectionStart = selectStart.GetOffset(input.Text.Length);
  96. }
  97. public void CycleChatChannel(bool forward)
  98. {
  99. var idx = Array.IndexOf(ChannelSelectorPopup.ChannelSelectorOrder, SelectedChannel);
  100. do
  101. {
  102. // go over every channel until we find one we can actually select.
  103. idx += forward ? 1 : -1;
  104. idx = MathHelper.Mod(idx, ChannelSelectorPopup.ChannelSelectorOrder.Length);
  105. } while ((_controller.SelectableChannels & ChannelSelectorPopup.ChannelSelectorOrder[idx]) == 0);
  106. SafelySelectChannel(ChannelSelectorPopup.ChannelSelectorOrder[idx]);
  107. }
  108. public void SafelySelectChannel(ChatSelectChannel toSelect)
  109. {
  110. toSelect = _controller.MapLocalIfGhost(toSelect);
  111. if ((_controller.SelectableChannels & toSelect) == 0)
  112. return;
  113. ChatInput.ChannelSelector.Select(toSelect);
  114. }
  115. private void OnInputKeyBindDown(GUIBoundKeyEventArgs args)
  116. {
  117. if (args.Function == EngineKeyFunctions.TextReleaseFocus)
  118. {
  119. ChatInput.Input.ReleaseKeyboardFocus();
  120. ChatInput.Input.Clear();
  121. args.Handle();
  122. return;
  123. }
  124. if (args.Function == ContentKeyFunctions.CycleChatChannelForward)
  125. {
  126. CycleChatChannel(true);
  127. args.Handle();
  128. return;
  129. }
  130. if (args.Function == ContentKeyFunctions.CycleChatChannelBackward)
  131. {
  132. CycleChatChannel(false);
  133. args.Handle();
  134. }
  135. }
  136. private void OnTextChanged(LineEditEventArgs args)
  137. {
  138. // Update channel select button to correct channel if we have a prefix.
  139. _controller.UpdateSelectedChannel(this);
  140. // Warn typing indicator about change
  141. _controller.NotifyChatTextChange();
  142. }
  143. protected override void Dispose(bool disposing)
  144. {
  145. base.Dispose(disposing);
  146. if (!disposing) return;
  147. _controller.UnregisterChat(this);
  148. ChatInput.Input.OnTextEntered -= OnTextEntered;
  149. ChatInput.Input.OnKeyBindDown -= OnInputKeyBindDown;
  150. ChatInput.Input.OnTextChanged -= OnTextChanged;
  151. ChatInput.ChannelSelector.OnChannelSelect -= OnChannelSelect;
  152. }
  153. }