AdminNotesControl.xaml.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. using System.Linq;
  2. using System.Numerics;
  3. using Content.Shared.Administration.Notes;
  4. using Content.Shared.CCVar;
  5. using Content.Shared.Database;
  6. using Robust.Client.AutoGenerated;
  7. using Robust.Client.GameObjects;
  8. using Robust.Client.UserInterface;
  9. using Robust.Client.UserInterface.Controls;
  10. using Robust.Client.UserInterface.XAML;
  11. using Robust.Shared.Configuration;
  12. namespace Content.Client.Administration.UI.Notes;
  13. [GenerateTypedNameReferences]
  14. public sealed partial class AdminNotesControl : Control
  15. {
  16. [Dependency] private readonly IEntitySystemManager _entitySystem = default!;
  17. [Dependency] private readonly IConfigurationManager _cfg = default!;
  18. public event Action<int, NoteType, string, NoteSeverity?, bool, DateTime?>? NoteChanged;
  19. public event Action<NoteType, string, NoteSeverity?, bool, DateTime?>? NewNoteEntered;
  20. public event Action<int, NoteType>? NoteDeleted;
  21. private AdminNotesLinePopup? _popup;
  22. private readonly SpriteSystem _sprites;
  23. private readonly double _noteFreshDays;
  24. private readonly double _noteStaleDays;
  25. public AdminNotesControl()
  26. {
  27. RobustXamlLoader.Load(this);
  28. IoCManager.InjectDependencies(this);
  29. _sprites = _entitySystem.GetEntitySystem<SpriteSystem>();
  30. // There should be a warning somewhere if fresh > stale
  31. // I thought about putting it here but then it would spam you every time you open notes
  32. _noteFreshDays = _cfg.GetCVar(CCVars.NoteFreshDays);
  33. _noteStaleDays = _cfg.GetCVar(CCVars.NoteStaleDays);
  34. NewNoteButton.OnPressed += OnNewNoteButtonPressed;
  35. ShowMoreButton.OnPressed += OnShowMoreButtonPressed;
  36. }
  37. private Dictionary<(int noteId, NoteType noteType), AdminNotesLine> Inputs { get; } = new();
  38. private bool CanCreate { get; set; }
  39. private bool CanDelete { get; set; }
  40. private bool CanEdit { get; set; }
  41. private string PlayerName { get; set; } = "<Error>";
  42. public void SetPlayerName(string playerName)
  43. {
  44. PlayerName = playerName;
  45. }
  46. private void OnNewNoteButtonPressed(BaseButton.ButtonEventArgs obj)
  47. {
  48. var noteEdit = new NoteEdit(null, PlayerName, CanCreate, CanEdit);
  49. noteEdit.SubmitPressed += OnNoteSubmitted;
  50. noteEdit.OpenCentered();
  51. }
  52. private void OnNoteSubmitted(int id, NoteType type, string message, NoteSeverity? severity, bool secret, DateTime? expiryTime)
  53. {
  54. if (id == 0)
  55. {
  56. NewNoteEntered?.Invoke(type, message, severity, secret, expiryTime);
  57. return;
  58. }
  59. NoteChanged?.Invoke(id, type, message, severity, secret, expiryTime);
  60. }
  61. private bool NoteClicked(AdminNotesLine line)
  62. {
  63. _popup = new AdminNotesLinePopup(line.Note, PlayerName, CanDelete, CanEdit);
  64. _popup.OnEditPressed += (noteId, noteType) =>
  65. {
  66. if (!Inputs.TryGetValue((noteId, noteType), out var input))
  67. {
  68. return;
  69. }
  70. var noteEdit = new NoteEdit(input.Note, PlayerName, CanCreate, CanEdit);
  71. noteEdit.SubmitPressed += OnNoteSubmitted;
  72. noteEdit.OpenCentered();
  73. };
  74. _popup.OnDeletePressed += (noteId, noteType) => NoteDeleted?.Invoke(noteId, noteType);
  75. _popup.OnPopupHide += OnPopupHide;
  76. var box = UIBox2.FromDimensions(UserInterfaceManager.MousePositionScaled.Position, Vector2.One);
  77. _popup.Open(box);
  78. return true;
  79. }
  80. private void OnPopupHide()
  81. {
  82. if (_popup == null ||
  83. !Inputs.TryGetValue((_popup.NoteId, _popup.NoteType), out var input))
  84. {
  85. return;
  86. }
  87. UpdateNoteLineAlpha(input);
  88. }
  89. private void NoteMouseEntered(GUIMouseHoverEventArgs args)
  90. {
  91. if (args.SourceControl is not AdminNotesLine line)
  92. return;
  93. line.Modulate = line.Modulate.WithAlpha(1f);
  94. }
  95. private void NoteMouseExited(GUIMouseHoverEventArgs args)
  96. {
  97. if (args.SourceControl is not AdminNotesLine line)
  98. return;
  99. if (_popup?.NoteId == line.Note.Id && _popup.Visible)
  100. return;
  101. UpdateNoteLineAlpha(line);
  102. }
  103. private void UpdateNoteLineAlpha(AdminNotesLine input)
  104. {
  105. var timeDiff = DateTime.UtcNow - input.Note.CreatedAt;
  106. float alpha;
  107. if (_noteFreshDays == 0 || timeDiff.TotalDays <= _noteFreshDays)
  108. {
  109. alpha = 1f;
  110. }
  111. else if (_noteStaleDays == 0 || timeDiff.TotalDays > _noteStaleDays)
  112. {
  113. alpha = 0f;
  114. }
  115. else
  116. {
  117. alpha = (float) (1 - Math.Clamp((timeDiff.TotalDays - _noteFreshDays) / (_noteStaleDays - _noteFreshDays), 0, 1));
  118. }
  119. input.Modulate = input.Modulate.WithAlpha(alpha);
  120. }
  121. public void SetNotes(Dictionary<(int, NoteType), SharedAdminNote> notes)
  122. {
  123. foreach (var (key, input) in Inputs)
  124. {
  125. if (!notes.ContainsKey(key))
  126. {
  127. // Yes this is slower than just updating, but new notes get added at the bottom. The user won't notice.
  128. Notes.RemoveAllChildren();
  129. Inputs.Clear();
  130. break;
  131. }
  132. Notes.RemoveChild(input);
  133. Inputs.Remove(key);
  134. }
  135. var showMoreButtonVisible = false;
  136. foreach (var note in notes.Values.OrderByDescending(note => note.CreatedAt))
  137. {
  138. if (Inputs.TryGetValue((note.Id, note.NoteType), out var input))
  139. {
  140. input.UpdateNote(note);
  141. continue;
  142. }
  143. input = new AdminNotesLine(_sprites, note);
  144. input.OnClicked += NoteClicked;
  145. input.OnMouseEntered += NoteMouseEntered;
  146. input.OnMouseExited += NoteMouseExited;
  147. UpdateNoteLineAlpha(input);
  148. if (input.Modulate.A == 0)
  149. {
  150. input.Visible = false;
  151. showMoreButtonVisible = true;
  152. }
  153. Notes.AddChild(input);
  154. Inputs[(note.Id, note.NoteType)] = input;
  155. ShowMoreButton.Visible = showMoreButtonVisible;
  156. }
  157. }
  158. private void OnShowMoreButtonPressed(BaseButton.ButtonEventArgs obj)
  159. {
  160. foreach (var input in Inputs.Values)
  161. {
  162. input.Modulate = input.Modulate.WithAlpha(1f);
  163. input.Visible = true;
  164. }
  165. ShowMoreButton.Visible = false;
  166. }
  167. public void SetPermissions(bool create, bool delete, bool edit)
  168. {
  169. CanCreate = create;
  170. CanDelete = delete;
  171. CanEdit = edit;
  172. NewNoteButton.Visible = create;
  173. NewNoteButton.Disabled = !create;
  174. }
  175. protected override void Dispose(bool disposing)
  176. {
  177. base.Dispose(disposing);
  178. if (!disposing)
  179. {
  180. return;
  181. }
  182. Inputs.Clear();
  183. NewNoteButton.OnPressed -= OnNewNoteButtonPressed;
  184. if (_popup != null)
  185. {
  186. UserInterfaceManager.PopupRoot.RemoveChild(_popup);
  187. }
  188. NoteDeleted = null;
  189. }
  190. }