From 8bad3fd91c6ce2d516eb40177d2462e6bdc34bdb Mon Sep 17 00:00:00 2001 From: Stanley Dimant Date: Sun, 2 Oct 2022 15:17:49 +0200 Subject: [PATCH] move groups into separate class, allow setting comments for groups, add new api methods --- MareAPI | 2 +- MareSynchronos/Configuration.cs | 18 + MareSynchronos/UI/CompactUI.cs | 439 ++-------------- MareSynchronos/UI/GroupPanel.cs | 495 ++++++++++++++++++ MareSynchronos/UI/UIShared.cs | 41 ++ .../WebAPI/ApiController.Functions.Groups.cs | 12 + 6 files changed, 597 insertions(+), 410 deletions(-) create mode 100644 MareSynchronos/UI/GroupPanel.cs diff --git a/MareAPI b/MareAPI index cfd0ba4..bab758f 160000 --- a/MareAPI +++ b/MareAPI @@ -1 +1 @@ -Subproject commit cfd0ba4c234b89667b11b5eefa83c9fc55baca10 +Subproject commit bab758f1736e266a392a7a93a47357b03b7b3e01 diff --git a/MareSynchronos/Configuration.cs b/MareSynchronos/Configuration.cs index 8416d80..5ab1507 100644 --- a/MareSynchronos/Configuration.cs +++ b/MareSynchronos/Configuration.cs @@ -26,6 +26,23 @@ public static class ConfigurationExtensions : new Dictionary(); } + public static Dictionary GetCurrentServerGidComments(this Configuration configuration) + { + return configuration.GidServerComments.ContainsKey(configuration.ApiUri) + ? configuration.GidServerComments[configuration.ApiUri] + : new Dictionary(); + } + + public static void SetCurrentServerGidComment(this Configuration configuration, string gid, string comment) + { + if (!configuration.GidServerComments.ContainsKey(configuration.ApiUri)) + { + configuration.GidServerComments[configuration.ApiUri] = new Dictionary(); + } + + configuration.GidServerComments[configuration.ApiUri][gid] = comment; + } + public static void SetCurrentServerUidComment(this Configuration configuration, string uid, string comment) { if (!configuration.UidServerComments.ContainsKey(configuration.ApiUri)) @@ -66,6 +83,7 @@ public class Configuration : IPluginConfiguration public bool FullPause { get; set; } = false; public Dictionary> UidServerComments { get; set; } = new(); + public Dictionary> GidServerComments { get; set; } = new(); public Dictionary UidComments { get; set; } = new(); public int Version { get; set; } = 5; diff --git a/MareSynchronos/UI/CompactUI.cs b/MareSynchronos/UI/CompactUI.cs index 0880def..897fd88 100644 --- a/MareSynchronos/UI/CompactUI.cs +++ b/MareSynchronos/UI/CompactUI.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.Linq; using System.Numerics; using System.Reflection; -using System.Threading.Tasks; using Dalamud.Interface; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; @@ -22,33 +20,25 @@ public class CompactUi : Window, IDisposable { private readonly ApiController _apiController; private readonly Configuration _configuration; - private readonly Dictionary _showUidForEntry = new(); + public readonly Dictionary ShowUidForEntry = new(); private readonly UiShared _uiShared; private readonly WindowSystem _windowSystem; private string _characterOrCommentFilter = string.Empty; - private string _editCharComment = string.Empty; - private string _editNickEntry = string.Empty; + public string EditUserComment = string.Empty; + public string EditNickEntry = string.Empty; + private string _pairToAdd = string.Empty; - private string _syncShellPassword = string.Empty; - private string _syncShellToJoin = string.Empty; + private readonly Stopwatch _timeout = new(); private bool _buttonState; - private float _transferPartHeight = 0; + public float TransferPartHeight = 0; + public float _windowContentWidth = 0; - private float _windowContentWidth = 0; - private bool _showModalEnterPassword; - private bool _showModalCreateGroup; - private bool _showModalChangePassword; - private string _newSyncShellPassword = string.Empty; - private bool _isPasswordValid; - private bool _errorGroupJoin; - private bool _errorGroupCreate = false; - private GroupCreatedDto? _lastCreatedGroup = null; - private Dictionary ExpandedGroupState = new Dictionary(); private bool showSyncShells = false; + private GroupPanel groupPanel; public CompactUi(WindowSystem windowSystem, UiShared uiShared, Configuration configuration, ApiController apiController) : base("###MareSynchronosMainUI") @@ -78,6 +68,8 @@ public class CompactUi : Window, IDisposable _configuration = configuration; _apiController = apiController; + groupPanel = new(this, uiShared, configuration, apiController); + SizeConstraints = new WindowSizeConstraints() { MinimumSize = new Vector2(300, 400), @@ -147,19 +139,19 @@ public class CompactUi : Window, IDisposable } else { - UiShared.DrawWithID("syncshells", DrawSyncshells); + UiShared.DrawWithID("syncshells", groupPanel.DrawSyncshells); } ImGui.Separator(); UiShared.DrawWithID("transfers", DrawTransfers); - _transferPartHeight = ImGui.GetCursorPosY() - _transferPartHeight; + TransferPartHeight = ImGui.GetCursorPosY() - TransferPartHeight; } } public override void OnClose() { - _editNickEntry = string.Empty; - _editCharComment = string.Empty; + EditNickEntry = string.Empty; + EditUserComment = string.Empty; base.OnClose(); } private void DrawAddPair() @@ -306,7 +298,7 @@ public class CompactUi : Window, IDisposable } var textIsUid = true; - _showUidForEntry.TryGetValue(entry.OtherUID, out var showUidInsteadOfName); + ShowUidForEntry.TryGetValue(entry.OtherUID, out var showUidInsteadOfName); if (!showUidInsteadOfName && _configuration.GetCurrentServerUidComments().TryGetValue(entry.OtherUID, out var playerText)) { if (string.IsNullOrEmpty(playerText)) @@ -324,7 +316,7 @@ public class CompactUi : Window, IDisposable } ImGui.SameLine(); - if (_editNickEntry != entry.OtherUID) + if (EditNickEntry != entry.OtherUID) { ImGui.SetCursorPosY(textPos); if (textIsUid) ImGui.PushFont(UiBuilder.MonoFont); @@ -335,22 +327,22 @@ public class CompactUi : Window, IDisposable if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) { var prevState = textIsUid; - if (_showUidForEntry.ContainsKey(entry.OtherUID)) + if (ShowUidForEntry.ContainsKey(entry.OtherUID)) { - prevState = _showUidForEntry[entry.OtherUID]; + prevState = ShowUidForEntry[entry.OtherUID]; } - _showUidForEntry[entry.OtherUID] = !prevState; + ShowUidForEntry[entry.OtherUID] = !prevState; } if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) { - _configuration.SetCurrentServerUidComment(_editNickEntry, _editCharComment); + _configuration.SetCurrentServerUidComment(EditNickEntry, EditUserComment); _configuration.Save(); - _editCharComment = _configuration.GetCurrentServerUidComments().ContainsKey(entry.OtherUID) + EditUserComment = _configuration.GetCurrentServerUidComments().ContainsKey(entry.OtherUID) ? _configuration.GetCurrentServerUidComments()[entry.OtherUID] : string.Empty; - _editNickEntry = entry.OtherUID; + EditNickEntry = entry.OtherUID; } } else @@ -358,16 +350,16 @@ public class CompactUi : Window, IDisposable ImGui.SetCursorPosY(originalY); ImGui.SetNextItemWidth(UiShared.GetWindowContentRegionWidth() - ImGui.GetCursorPosX() - buttonSizes - ImGui.GetStyle().ItemSpacing.X * 2); - if (ImGui.InputTextWithHint("", "Nick/Notes", ref _editCharComment, 255, ImGuiInputTextFlags.EnterReturnsTrue)) + if (ImGui.InputTextWithHint("", "Nick/Notes", ref EditUserComment, 255, ImGuiInputTextFlags.EnterReturnsTrue)) { - _configuration.SetCurrentServerUidComment(entry.OtherUID, _editCharComment); + _configuration.SetCurrentServerUidComment(entry.OtherUID, EditUserComment); _configuration.Save(); - _editNickEntry = string.Empty; + EditNickEntry = string.Empty; } if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) { - _editNickEntry = string.Empty; + EditNickEntry = string.Empty; } UiShared.AttachToolTip("Hit ENTER to save\nRight click to cancel"); } @@ -397,26 +389,19 @@ public class CompactUi : Window, IDisposable } } - private void DrawSyncshells() - { - UiShared.DrawWithID("addsyncshell", DrawAddSyncshell); - UiShared.DrawWithID("syncshelllist", DrawSyncshellList); - _transferPartHeight = ImGui.GetCursorPosY(); - } - private void DrawPairList() { UiShared.DrawWithID("addpair", DrawAddPair); UiShared.DrawWithID("pairs", DrawPairs); - _transferPartHeight = ImGui.GetCursorPosY(); + TransferPartHeight = ImGui.GetCursorPosY(); UiShared.DrawWithID("filter", DrawFilter); } private void DrawPairs() { - var ySize = _transferPartHeight == 0 + var ySize = TransferPartHeight == 0 ? 1 - : (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - _transferPartHeight - ImGui.GetCursorPosY(); + : (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - TransferPartHeight - ImGui.GetCursorPosY(); var users = GetFilteredUsers(); users = users.OrderBy(u => _configuration.GetCurrentServerUidComments().ContainsKey(u.OtherUID) ? _configuration.GetCurrentServerUidComments()[u.OtherUID] : !string.IsNullOrEmpty(u.VanityUID) ? u.VanityUID : u.OtherUID); @@ -430,371 +415,7 @@ public class CompactUi : Window, IDisposable ImGui.EndChild(); } - private void DrawAddSyncshell() - { - var buttonSize = UiShared.GetIconButtonSize(FontAwesomeIcon.Plus); - ImGui.SetNextItemWidth(UiShared.GetWindowContentRegionWidth() - ImGui.GetWindowContentRegionMin().X - buttonSize.X); - ImGui.InputTextWithHint("##syncshellid", "Syncshell GID/Alias", ref _syncShellToJoin, 20); - ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + UiShared.GetWindowContentRegionWidth() - buttonSize.X); - if (ImGuiComponents.IconButton(FontAwesomeIcon.Plus)) - { - if (_apiController.Groups.All(w => w.GID != _syncShellToJoin) && !string.IsNullOrEmpty(_syncShellToJoin)) - { - _errorGroupJoin = false; - _showModalEnterPassword = true; - ImGui.OpenPopup("Enter Syncshell Password"); - } - else - { - _lastCreatedGroup = null; - _errorGroupCreate = false; - _showModalCreateGroup = true; - ImGui.OpenPopup("Create Syncshell"); - } - } - UiShared.AttachToolTip(_syncShellToJoin.IsNullOrEmpty() ? "Create Syncshell" : "Join Syncshell" + _syncShellToJoin); - - if (ImGui.BeginPopupModal("Enter Syncshell Password", ref _showModalEnterPassword, ImGuiWindowFlags.AlwaysAutoResize)) - { - UiShared.TextWrapped("Before joining any Syncshells please be aware that you will be automatically paired with everyone in the Syncshell."); - ImGui.Separator(); - UiShared.TextWrapped("Enter the password for Syncshell " + _syncShellToJoin + ":"); - ImGui.InputTextWithHint("##password", _syncShellToJoin + " Password", ref _syncShellPassword, 255, ImGuiInputTextFlags.Password); - if (_errorGroupJoin) - { - UiShared.ColorTextWrapped("An error occured during joining of this Syncshell: you either have joined the maximum amount of Syncshells (6), it does not exist, the password you entered is wrong, you already joined the Syncshell, the Syncshell is full (100 users) or the Syncshell has closed invites.", - new Vector4(1, 0, 0, 1)); - } - if (ImGui.Button("Join " + _syncShellToJoin)) - { - var shell = _syncShellToJoin; - var pw = _syncShellPassword; - _errorGroupJoin = !_apiController.SendGroupJoin(shell, pw).Result; - if (!_errorGroupJoin) - { - _syncShellToJoin = string.Empty; - _showModalEnterPassword = false; - } - _syncShellPassword = string.Empty; - } - ImGui.EndPopup(); - } - - if (ImGui.BeginPopupModal("Create Syncshell", ref _showModalCreateGroup)) - { - ImGui.SetWindowSize(new(400, 200)); - UiShared.TextWrapped("Press the button below to create a new Syncshell."); - ImGui.SetNextItemWidth(200); - if (ImGui.Button("Create Syncshell")) - { - try - { - _lastCreatedGroup = _apiController.CreateGroup().Result; - } - catch - { - _errorGroupCreate = true; - } - } - - if (_lastCreatedGroup != null) - { - ImGui.Separator(); - _errorGroupCreate = false; - ImGui.TextUnformatted("Syncshell ID: " + _lastCreatedGroup.GID); - ImGui.TextUnformatted("Syncshell Password: " + _lastCreatedGroup.Password); - ImGui.SameLine(); - if (ImGuiComponents.IconButton(FontAwesomeIcon.Copy)) - { - ImGui.SetClipboardText(_lastCreatedGroup.Password); - } - UiShared.TextWrapped("You can change the Syncshell password later at any time."); - } - - if (_errorGroupCreate) - { - UiShared.ColorTextWrapped("You are already owner of the maximum amount of Syncshells (3) or joined the maximum amount of Syncshells (6). Relinquish ownership of your own Syncshells to someone else or leave existing Syncshells.", - new Vector4(1, 0, 0, 1)); - } - - ImGui.EndPopup(); - } - - - ImGuiHelpers.ScaledDummy(2); - } - - private void DrawSyncshellList() - { - var ySize = _transferPartHeight == 0 - ? 1 - : (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - _transferPartHeight - ImGui.GetCursorPosY(); - ImGui.BeginChild("list", new Vector2(_windowContentWidth, ySize), false); - foreach (var entry in _apiController.Groups.OrderBy(g => g.Alias ?? g.GID).ToList()) - { - UiShared.DrawWithID(entry.GID, () => DrawSyncshell(entry)); - } - ImGui.EndChild(); - } - - private void DrawSyncshell(GroupDto group) - { - var name = group.Alias ?? group.GID; - var pairsInGroup = _apiController.GroupPairedClients.Where(p => p.GroupGID == group.GID).ToList(); - if (!ExpandedGroupState.TryGetValue(group.GID, out bool isExpanded)) - { - isExpanded = false; - ExpandedGroupState.Add(group.GID, isExpanded); - } - var icon = isExpanded ? FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight; - var collapseButton = UiShared.GetIconButtonSize(icon); - ImGui.PushStyleColor(ImGuiCol.Button, new Vector4(0, 0, 0, 0)); - ImGui.PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(0, 0, 0, 0)); - if (ImGuiComponents.IconButton(icon)) - { - ExpandedGroupState[group.GID] = !ExpandedGroupState[group.GID]; - } - ImGui.PopStyleColor(2); - ImGui.SameLine(); - var pauseIcon = (group.IsPaused ?? false) ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause; - if (ImGuiComponents.IconButton(pauseIcon)) - { - _ = _apiController.SendPauseGroup(group.GID, !group.IsPaused ?? false); - } - UiShared.AttachToolTip(((group.IsPaused ?? false) ? "Resume" : "Pause") + " pairing with all users in this Syncshell"); - ImGui.SameLine(); - ImGui.TextUnformatted(group.Alias ?? group.GID); - UiShared.AttachToolTip("Users: " + (pairsInGroup.Count + 1) + ", Owner: " + group.OwnedBy); - - ImGui.Indent(collapseButton.X + ImGui.GetStyle().ItemSpacing.X); - if (ExpandedGroupState[group.GID]) - { - UiShared.DrawWithID(group.GID + "settings", () => DrawSyncShellButtons(group, name)); - pairsInGroup = pairsInGroup.OrderBy(p => p.UserUID == group.OwnedBy ? 0 : 1).ThenBy(p => p.UserAlias ?? p.UserUID).ToList(); - foreach (var pair in pairsInGroup) - { - ImGui.Indent(ImGui.GetStyle().ItemSpacing.X / 2); - UiShared.DrawWithID(group.GID + pair.UserUID, () => DrawSyncshellPairedClient(pair, group.OwnedBy == _apiController.UID, group?.IsPaused ?? false)); - ImGui.Unindent(ImGui.GetStyle().ItemSpacing.X / 2); - } - } - ImGui.Unindent(collapseButton.X + ImGui.GetStyle().ItemSpacing.X); - } - - private void DrawSyncShellButtons(GroupDto entry, string name) - { - bool invitesEnabled = entry.InvitesEnabled ?? true; - var lockedIcon = invitesEnabled ? FontAwesomeIcon.LockOpen : FontAwesomeIcon.Lock; - - if (ImGuiComponents.IconButton(FontAwesomeIcon.ArrowCircleLeft)) - { - if (UiShared.CtrlPressed()) - { - _ = _apiController.SendLeaveGroup(entry.GID); - } - } - UiShared.AttachToolTip("Hold CTRL and click to leave this Syncshell"); - - ImGui.SameLine(); - if (ImGuiComponents.IconButton(FontAwesomeIcon.Copy)) - { - ImGui.SetClipboardText(entry.Alias ?? entry.GID); - } - UiShared.AttachToolTip("Copy Syncshell ID to Clipboard"); - if (entry.OwnedBy == _apiController.UID) - { - ImGui.SameLine(); - if (ImGuiComponents.IconButton(lockedIcon)) - { - _ = _apiController.SendGroupChangeInviteState(entry.GID, !entry.InvitesEnabled ?? true); - } - UiShared.AttachToolTip("Change Syncshell joining permissions" + Environment.NewLine + "Syncshell is currently " + (invitesEnabled ? "open" : "closed") + " for people to join"); - ImGui.SameLine(); - if (ImGuiComponents.IconButton(FontAwesomeIcon.Passport)) - { - ImGui.OpenPopup("Change Syncshell Password"); - _isPasswordValid = true; - _showModalChangePassword = true; - } - UiShared.AttachToolTip("Change Syncshell Password"); - - if (ImGui.BeginPopupModal("Change Syncshell Password", ref _showModalChangePassword, ImGuiWindowFlags.AlwaysAutoResize)) - { - UiShared.TextWrapped("Enter the new Syncshell password for Syncshell " + name + " here."); - UiShared.TextWrapped("This action is irreversible"); - ImGui.InputTextWithHint("##changepw", "New password for " + name, ref _newSyncShellPassword, 255); - if (ImGui.Button("Change password")) - { - var pw = _newSyncShellPassword; - _isPasswordValid = _apiController.ChangeGroupPassword(entry.GID, pw).Result; - _newSyncShellPassword = string.Empty; - if (_isPasswordValid) _showModalChangePassword = false; - } - - if (!_isPasswordValid) - { - UiShared.ColorTextWrapped("The selected password is too short. It must be at least 10 characters.", new Vector4(1, 0, 0, 1)); - } - - ImGui.EndPopup(); - } - - ImGui.SameLine(); - if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash)) - { - if (UiShared.CtrlPressed()) - { - _ = _apiController.SendDeleteGroup(entry.GID); - } - } - UiShared.AttachToolTip("Hold CTRL and click to delete this Syncshell. WARNING: this action is irreversible." - + Environment.NewLine + "Leaving an owned Syncshell will transfer the ownership to a random person in the Syncshell."); - } - else - { - ImGui.SameLine(); - ImGui.SameLine(); - ImGui.PushFont(UiBuilder.IconFont); - ImGui.Text(lockedIcon.ToIconString()); - ImGui.PopFont(); - UiShared.AttachToolTip(invitesEnabled ? "Syncshell is open for new joiners" : "Syncshell is closed for new joiners"); - } - } - - private void DrawSyncshellPairedClient(GroupPairDto entry, bool isOwner, bool isPausedByYou) - { - var plusButtonSize = UiShared.GetIconButtonSize(FontAwesomeIcon.Plus); - var trashButtonSize = UiShared.GetIconButtonSize(FontAwesomeIcon.Trash); - var crownButtonSize = UiShared.GetIconButtonSize(FontAwesomeIcon.Crown); - var entryUID = string.IsNullOrEmpty(entry.UserAlias) ? entry.UserUID : entry.UserAlias; - var textSize = ImGui.CalcTextSize(entryUID); - var originalY = ImGui.GetCursorPosY(); - var buttonSizes = plusButtonSize.Y; - - var textPos = originalY + plusButtonSize.Y / 2 - textSize.Y / 2; - ImGui.SetCursorPosY(textPos); - if (isPausedByYou || (entry.IsPaused ?? false)) - { - ImGui.PushFont(UiBuilder.IconFont); - UiShared.ColorText(FontAwesomeIcon.PauseCircle.ToIconString(), ImGuiColors.DalamudYellow); - ImGui.PopFont(); - - UiShared.AttachToolTip("Pairing status with " + entryUID + " is paused"); - } - else - { - ImGui.PushFont(UiBuilder.IconFont); - UiShared.ColorText(FontAwesomeIcon.Check.ToIconString(), ImGuiColors.ParsedGreen); - ImGui.PopFont(); - - UiShared.AttachToolTip("You are paired with " + entryUID); - } - - var textIsUid = true; - _showUidForEntry.TryGetValue(entry.UserUID, out var showUidInsteadOfName); - if (!showUidInsteadOfName && _configuration.GetCurrentServerUidComments().TryGetValue(entry.UserUID, out var playerText)) - { - if (string.IsNullOrEmpty(playerText)) - { - playerText = entryUID; - } - else - { - textIsUid = false; - } - } - else - { - playerText = entryUID; - } - - ImGui.SameLine(); - if (_editNickEntry != entry.UserUID) - { - ImGui.SetCursorPosY(textPos); - if (textIsUid) ImGui.PushFont(UiBuilder.MonoFont); - ImGui.TextUnformatted(playerText); - if (textIsUid) ImGui.PopFont(); - UiShared.AttachToolTip("Left click to switch between UID display and nick" + Environment.NewLine + - "Right click to change nick for " + entryUID); - if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) - { - var prevState = textIsUid; - if (_showUidForEntry.ContainsKey(entry.UserUID)) - { - prevState = _showUidForEntry[entry.UserUID]; - } - - _showUidForEntry[entry.UserUID] = !prevState; - } - - if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) - { - _configuration.SetCurrentServerUidComment(_editNickEntry, _editCharComment); - _configuration.Save(); - _editCharComment = _configuration.GetCurrentServerUidComments().ContainsKey(entry.UserUID) - ? _configuration.GetCurrentServerUidComments()[entry.UserUID] - : string.Empty; - _editNickEntry = entry.UserUID; - } - } - else - { - ImGui.SetCursorPosY(originalY); - - ImGui.SetNextItemWidth(UiShared.GetWindowContentRegionWidth() - ImGui.GetCursorPosX() - buttonSizes - ImGui.GetStyle().ItemSpacing.X * 2); - if (ImGui.InputTextWithHint("", "Nick/Notes", ref _editCharComment, 255, ImGuiInputTextFlags.EnterReturnsTrue)) - { - _configuration.SetCurrentServerUidComment(entry.UserUID, _editCharComment); - _configuration.Save(); - _editNickEntry = string.Empty; - } - - if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) - { - _editNickEntry = string.Empty; - } - UiShared.AttachToolTip("Hit ENTER to save\nRight click to cancel"); - } - - bool addButtonShown = !_apiController.PairedClients.Any(p => p.OtherUID == entry.UserUID); - if (isOwner) - { - ImGui.SetCursorPosY(originalY); - var subtractedWidth = addButtonShown ? (ImGui.GetStyle().ItemSpacing.X + plusButtonSize.X) : 0; - ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + UiShared.GetWindowContentRegionWidth() - subtractedWidth - trashButtonSize.X - ImGui.GetStyle().ItemSpacing.X - crownButtonSize.X); - - if (ImGuiComponents.IconButton(FontAwesomeIcon.Crown)) - { - if (UiShared.CtrlPressed() && UiShared.ShiftPressed()) - { - _ = _apiController.ChangeOwnerOfGroup(entry.GroupGID, entry.UserUID); - } - } - UiShared.AttachToolTip("Hold CTRL and SHIFT and click to transfer ownership of this Syncshell to " + (entry.UserAlias ?? entry.UserUID) + Environment.NewLine + "WARNING: This action is irreversible."); - ImGui.SameLine(); - if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash)) - { - if (UiShared.CtrlPressed()) - { - _ = _apiController.SendRemoveUserFromGroup(entry.GroupGID, entry.UserUID); - } - } - UiShared.AttachToolTip("Hold CTRL and click to remove user " + (entry.UserAlias ?? entry.UserUID) + " from Syncshell"); - } - - if (addButtonShown) - { - ImGui.SetCursorPosY(originalY); - ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + UiShared.GetWindowContentRegionWidth() - plusButtonSize.X); - - if (ImGuiComponents.IconButton(FontAwesomeIcon.Plus)) - { - _ = _apiController.SendPairedClientAddition(entry.UserUID); - } - UiShared.AttachToolTip("Pair with " + entryUID + " individually"); - } - } + private IEnumerable GetFilteredUsers() { diff --git a/MareSynchronos/UI/GroupPanel.cs b/MareSynchronos/UI/GroupPanel.cs new file mode 100644 index 0000000..e6981e4 --- /dev/null +++ b/MareSynchronos/UI/GroupPanel.cs @@ -0,0 +1,495 @@ +using Dalamud.Interface.Colors; +using Dalamud.Interface.Components; +using Dalamud.Interface; +using Dalamud.Utility; +using ImGuiNET; +using MareSynchronos.API; +using MareSynchronos.WebAPI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +namespace MareSynchronos.UI +{ + internal class GroupPanel + { + private readonly CompactUi _mainUi; + private UiShared _uiShared; + private Configuration _configuration; + private ApiController _apiController; + + private readonly Dictionary _showGidForEntry = new(); + private string _editGroupEntry = string.Empty; + private string _editGroupComment = string.Empty; + private string _syncShellPassword = string.Empty; + private string _syncShellToJoin = string.Empty; + + private bool _showModalEnterPassword; + private bool _showModalCreateGroup; + private bool _showModalChangePassword; + private string _newSyncShellPassword = string.Empty; + private bool _isPasswordValid; + private bool _errorGroupJoin; + private bool _errorGroupCreate = false; + private GroupCreatedDto? _lastCreatedGroup = null; + private Dictionary ExpandedGroupState = new Dictionary(); + + public GroupPanel(CompactUi mainUi, UiShared uiShared, Configuration configuration, ApiController apiController) + { + _mainUi = mainUi; + _uiShared = uiShared; + _configuration = configuration; + _apiController = apiController; + } + + public void DrawSyncshells() + { + UiShared.DrawWithID("addsyncshell", DrawAddSyncshell); + UiShared.DrawWithID("syncshelllist", DrawSyncshellList); + _mainUi.TransferPartHeight = ImGui.GetCursorPosY(); + } + + private void DrawAddSyncshell() + { + var buttonSize = UiShared.GetIconButtonSize(FontAwesomeIcon.Plus); + ImGui.SetNextItemWidth(UiShared.GetWindowContentRegionWidth() - ImGui.GetWindowContentRegionMin().X - buttonSize.X); + ImGui.InputTextWithHint("##syncshellid", "Syncshell GID/Alias", ref _syncShellToJoin, 20); + ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + UiShared.GetWindowContentRegionWidth() - buttonSize.X); + if (ImGuiComponents.IconButton(FontAwesomeIcon.Plus)) + { + if (_apiController.Groups.All(w => w.GID != _syncShellToJoin) && !string.IsNullOrEmpty(_syncShellToJoin)) + { + _errorGroupJoin = false; + _showModalEnterPassword = true; + ImGui.OpenPopup("Enter Syncshell Password"); + } + else + { + _lastCreatedGroup = null; + _errorGroupCreate = false; + _showModalCreateGroup = true; + ImGui.OpenPopup("Create Syncshell"); + } + } + UiShared.AttachToolTip(_syncShellToJoin.IsNullOrEmpty() ? "Create Syncshell" : "Join Syncshell" + _syncShellToJoin); + + if (ImGui.BeginPopupModal("Enter Syncshell Password", ref _showModalEnterPassword, ImGuiWindowFlags.AlwaysAutoResize)) + { + UiShared.TextWrapped("Before joining any Syncshells please be aware that you will be automatically paired with everyone in the Syncshell."); + ImGui.Separator(); + UiShared.TextWrapped("Enter the password for Syncshell " + _syncShellToJoin + ":"); + ImGui.InputTextWithHint("##password", _syncShellToJoin + " Password", ref _syncShellPassword, 255, ImGuiInputTextFlags.Password); + if (_errorGroupJoin) + { + UiShared.ColorTextWrapped("An error occured during joining of this Syncshell: you either have joined the maximum amount of Syncshells (6), it does not exist, the password you entered is wrong, you already joined the Syncshell, the Syncshell is full (100 users) or the Syncshell has closed invites.", + new Vector4(1, 0, 0, 1)); + } + if (ImGui.Button("Join " + _syncShellToJoin)) + { + var shell = _syncShellToJoin; + var pw = _syncShellPassword; + _errorGroupJoin = !_apiController.SendGroupJoin(shell, pw).Result; + if (!_errorGroupJoin) + { + _syncShellToJoin = string.Empty; + _showModalEnterPassword = false; + } + _syncShellPassword = string.Empty; + } + ImGui.EndPopup(); + } + + if (ImGui.BeginPopupModal("Create Syncshell", ref _showModalCreateGroup)) + { + ImGui.SetWindowSize(new(400, 200)); + UiShared.TextWrapped("Press the button below to create a new Syncshell."); + ImGui.SetNextItemWidth(200); + if (ImGui.Button("Create Syncshell")) + { + try + { + _lastCreatedGroup = _apiController.CreateGroup().Result; + } + catch + { + _errorGroupCreate = true; + } + } + + if (_lastCreatedGroup != null) + { + ImGui.Separator(); + _errorGroupCreate = false; + ImGui.TextUnformatted("Syncshell ID: " + _lastCreatedGroup.GID); + ImGui.TextUnformatted("Syncshell Password: " + _lastCreatedGroup.Password); + ImGui.SameLine(); + if (ImGuiComponents.IconButton(FontAwesomeIcon.Copy)) + { + ImGui.SetClipboardText(_lastCreatedGroup.Password); + } + UiShared.TextWrapped("You can change the Syncshell password later at any time."); + } + + if (_errorGroupCreate) + { + UiShared.ColorTextWrapped("You are already owner of the maximum amount of Syncshells (3) or joined the maximum amount of Syncshells (6). Relinquish ownership of your own Syncshells to someone else or leave existing Syncshells.", + new Vector4(1, 0, 0, 1)); + } + + ImGui.EndPopup(); + } + + + ImGuiHelpers.ScaledDummy(2); + } + + private void DrawSyncshellList() + { + var ySize = _mainUi.TransferPartHeight == 0 + ? 1 + : (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - _mainUi.TransferPartHeight - ImGui.GetCursorPosY(); + ImGui.BeginChild("list", new Vector2(_mainUi._windowContentWidth, ySize), false); + foreach (var entry in _apiController.Groups.OrderBy(g => g.Alias ?? g.GID).ToList()) + { + UiShared.DrawWithID(entry.GID, () => DrawSyncshell(entry)); + } + ImGui.EndChild(); + } + + private void DrawSyncshell(GroupDto group) + { + var name = group.Alias ?? group.GID; + var pairsInGroup = _apiController.GroupPairedClients.Where(p => p.GroupGID == group.GID).ToList(); + if (!ExpandedGroupState.TryGetValue(group.GID, out bool isExpanded)) + { + isExpanded = false; + ExpandedGroupState.Add(group.GID, isExpanded); + } + var icon = isExpanded ? FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight; + var collapseButton = UiShared.GetIconButtonSize(icon); + ImGui.PushStyleColor(ImGuiCol.Button, new Vector4(0, 0, 0, 0)); + ImGui.PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(0, 0, 0, 0)); + if (ImGuiComponents.IconButton(icon)) + { + ExpandedGroupState[group.GID] = !ExpandedGroupState[group.GID]; + } + ImGui.PopStyleColor(2); + ImGui.SameLine(); + var pauseIcon = (group.IsPaused ?? false) ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause; + if (ImGuiComponents.IconButton(pauseIcon)) + { + _ = _apiController.SendPauseGroup(group.GID, !group.IsPaused ?? false); + } + UiShared.AttachToolTip(((group.IsPaused ?? false) ? "Resume" : "Pause") + " pairing with all users in this Syncshell"); + ImGui.SameLine(); + + var groupName = group.Alias ?? group.GID; + var textIsGid = true; + _showGidForEntry.TryGetValue(group.GID, out var showGidInsteadOfName); + if (!showGidInsteadOfName && _configuration.GetCurrentServerGidComments().TryGetValue(group.GID, out var groupComment)) + { + if (!string.IsNullOrEmpty(groupComment)) + { + groupName = groupComment; + textIsGid = false; + } + } + + if (_editGroupEntry != group.GID) + { + if (textIsGid) ImGui.PushFont(UiBuilder.MonoFont); + ImGui.TextUnformatted(groupName); + if (textIsGid) ImGui.PopFont(); + UiShared.AttachToolTip("Left click to switch between GID display and comment" + Environment.NewLine + + "Right click to change comment for " + groupName + Environment.NewLine + Environment.NewLine + + "Users: " + (pairsInGroup.Count + 1) + ", Owner: " + group.OwnedBy); + if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) + { + var prevState = textIsGid; + if (_showGidForEntry.ContainsKey(group.GID)) + { + prevState = _showGidForEntry[group.GID]; + } + + _showGidForEntry[group.GID] = !prevState; + } + + if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) + { + _configuration.SetCurrentServerGidComment(_editGroupEntry, _editGroupComment); + _configuration.Save(); + _editGroupComment = _configuration.GetCurrentServerGidComments().ContainsKey(group.GID) + ? _configuration.GetCurrentServerGidComments()[group.GID] + : string.Empty; + _editGroupEntry = group.GID; + } + } + else + { + ImGui.SetNextItemWidth(UiShared.GetWindowContentRegionWidth() - ImGui.GetCursorPosX()); + if (ImGui.InputTextWithHint("", "Comment/Notes", ref _editGroupComment, 255, ImGuiInputTextFlags.EnterReturnsTrue)) + { + _configuration.SetCurrentServerGidComment(group.GID, _editGroupComment); + _configuration.Save(); + _editGroupEntry = string.Empty; + } + + if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) + { + _editGroupEntry = string.Empty; + } + UiShared.AttachToolTip("Hit ENTER to save\nRight click to cancel"); + } + + ImGui.Indent(collapseButton.X + ImGui.GetStyle().ItemSpacing.X); + if (ExpandedGroupState[group.GID]) + { + UiShared.DrawWithID(group.GID + "settings", () => DrawSyncShellButtons(group, name)); + pairsInGroup = pairsInGroup.OrderBy(p => p.UserUID == group.OwnedBy ? 0 : 1).ThenBy(p => p.IsPinned ?? false).ThenBy(p => p.UserAlias ?? p.UserUID).ToList(); + foreach (var pair in pairsInGroup) + { + ImGui.Indent(ImGui.GetStyle().ItemSpacing.X / 2); + UiShared.DrawWithID(group.GID + pair.UserUID, () => DrawSyncshellPairedClient(pair, group.OwnedBy == _apiController.UID, group?.IsPaused ?? false)); + ImGui.Unindent(ImGui.GetStyle().ItemSpacing.X / 2); + } + } + ImGui.Unindent(collapseButton.X + ImGui.GetStyle().ItemSpacing.X); + } + + private void DrawSyncShellButtons(GroupDto entry, string name) + { + bool invitesEnabled = entry.InvitesEnabled ?? true; + var lockedIcon = invitesEnabled ? FontAwesomeIcon.LockOpen : FontAwesomeIcon.Lock; + + if (ImGuiComponents.IconButton(FontAwesomeIcon.ArrowCircleLeft)) + { + if (UiShared.CtrlPressed()) + { + _ = _apiController.SendLeaveGroup(entry.GID); + } + } + UiShared.AttachToolTip("Hold CTRL and click to leave this Syncshell" + (entry.OwnedBy != _apiController.UID ? string.Empty : Environment.NewLine + + "WARNING: This action is irreverisble" + Environment.NewLine + "Leaving an owned Syncshell will transfer the ownership to a random person in the Syncshell.")); + + ImGui.SameLine(); + if (ImGuiComponents.IconButton(FontAwesomeIcon.Copy)) + { + ImGui.SetClipboardText(entry.Alias ?? entry.GID); + } + UiShared.AttachToolTip("Copy Syncshell ID to Clipboard"); + if (entry.OwnedBy == _apiController.UID) + { + ImGui.SameLine(); + if (ImGuiComponents.IconButton(lockedIcon)) + { + _ = _apiController.SendGroupChangeInviteState(entry.GID, !entry.InvitesEnabled ?? true); + } + UiShared.AttachToolTip("Change Syncshell joining permissions" + Environment.NewLine + "Syncshell is currently " + (invitesEnabled ? "open" : "closed") + " for people to join"); + ImGui.SameLine(); + if (ImGuiComponents.IconButton(FontAwesomeIcon.Passport)) + { + ImGui.OpenPopup("Change Syncshell Password"); + _isPasswordValid = true; + _showModalChangePassword = true; + } + UiShared.AttachToolTip("Change Syncshell Password"); + + if (ImGui.BeginPopupModal("Change Syncshell Password", ref _showModalChangePassword, ImGuiWindowFlags.AlwaysAutoResize)) + { + UiShared.TextWrapped("Enter the new Syncshell password for Syncshell " + name + " here."); + UiShared.TextWrapped("This action is irreversible"); + ImGui.InputTextWithHint("##changepw", "New password for " + name, ref _newSyncShellPassword, 255); + if (ImGui.Button("Change password")) + { + var pw = _newSyncShellPassword; + _isPasswordValid = _apiController.ChangeGroupPassword(entry.GID, pw).Result; + _newSyncShellPassword = string.Empty; + if (_isPasswordValid) _showModalChangePassword = false; + } + + if (!_isPasswordValid) + { + UiShared.ColorTextWrapped("The selected password is too short. It must be at least 10 characters.", new Vector4(1, 0, 0, 1)); + } + + ImGui.EndPopup(); + } + + ImGui.SameLine(); + if (ImGuiComponents.IconButton(FontAwesomeIcon.Broom)) + { + if (UiShared.CtrlPressed()) + { + _ = _apiController.SendClearGroup(entry.GID); + } + } + UiShared.AttachToolTip("Hold CTRL and click to clear this Syncshell." + Environment.NewLine + "WARNING: this action is irreversible." + Environment.NewLine + + "Clearing the Syncshell will remove all not pinned users from it."); + + ImGui.SameLine(); + if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash)) + { + if (UiShared.CtrlPressed() && UiShared.ShiftPressed()) + { + _ = _apiController.SendDeleteGroup(entry.GID); + } + } + UiShared.AttachToolTip("Hold CTRL and Shift and click to delete this Syncshell." + Environment.NewLine + "WARNING: this action is irreversible."); + } + else + { + ImGui.SameLine(); + ImGui.SameLine(); + ImGui.PushFont(UiBuilder.IconFont); + ImGui.Text(lockedIcon.ToIconString()); + ImGui.PopFont(); + UiShared.AttachToolTip(invitesEnabled ? "Syncshell is open for new joiners" : "Syncshell is closed for new joiners"); + } + } + + private void DrawSyncshellPairedClient(GroupPairDto entry, bool isOwner, bool isPausedByYou) + { + var plusButtonSize = UiShared.GetIconButtonSize(FontAwesomeIcon.Plus); + var trashButtonSize = UiShared.GetIconButtonSize(FontAwesomeIcon.Trash); + var crownButtonSize = UiShared.GetIconButtonSize(FontAwesomeIcon.Crown); + var entryUID = string.IsNullOrEmpty(entry.UserAlias) ? entry.UserUID : entry.UserAlias; + var textSize = ImGui.CalcTextSize(entryUID); + var originalY = ImGui.GetCursorPosY(); + var buttonSizes = plusButtonSize.Y; + + var textPos = originalY + plusButtonSize.Y / 2 - textSize.Y / 2; + ImGui.SetCursorPosY(textPos); + if (isPausedByYou || (entry.IsPaused ?? false)) + { + ImGui.PushFont(UiBuilder.IconFont); + UiShared.ColorText(FontAwesomeIcon.PauseCircle.ToIconString(), ImGuiColors.DalamudYellow); + ImGui.PopFont(); + + UiShared.AttachToolTip("Pairing status with " + entryUID + " is paused"); + } + else + { + ImGui.PushFont(UiBuilder.IconFont); + UiShared.ColorText(FontAwesomeIcon.Check.ToIconString(), ImGuiColors.ParsedGreen); + ImGui.PopFont(); + + UiShared.AttachToolTip("You are paired with " + entryUID); + } + + if (entry.IsPinned ?? false) + { + ImGui.SameLine(); + ImGui.SetCursorPosY(textPos); + ImGui.PushFont(UiBuilder.IconFont); + ImGui.TextUnformatted(FontAwesomeIcon.Thumbtack.ToIconString()); + ImGui.PopFont(); + } + + var textIsUid = true; + _mainUi.ShowUidForEntry.TryGetValue(entry.UserUID, out var showUidInsteadOfName); + if (!showUidInsteadOfName && _configuration.GetCurrentServerUidComments().TryGetValue(entry.UserUID, out var playerText)) + { + if (string.IsNullOrEmpty(playerText)) + { + playerText = entryUID; + } + else + { + textIsUid = false; + } + } + else + { + playerText = entryUID; + } + + ImGui.SameLine(); + if (_mainUi.EditNickEntry != entry.UserUID) + { + ImGui.SetCursorPosY(textPos); + if (textIsUid) ImGui.PushFont(UiBuilder.MonoFont); + ImGui.TextUnformatted(playerText); + if (textIsUid) ImGui.PopFont(); + UiShared.AttachToolTip("Left click to switch between UID display and nick" + Environment.NewLine + + "Right click to change nick for " + entryUID); + if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) + { + var prevState = textIsUid; + if (_mainUi.ShowUidForEntry.ContainsKey(entry.UserUID)) + { + prevState = _mainUi.ShowUidForEntry[entry.UserUID]; + } + + _mainUi.ShowUidForEntry[entry.UserUID] = !prevState; + } + + if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) + { + _configuration.SetCurrentServerUidComment(_mainUi.EditNickEntry, _mainUi.EditUserComment); + _configuration.Save(); + _mainUi.EditUserComment = _configuration.GetCurrentServerUidComments().ContainsKey(entry.UserUID) + ? _configuration.GetCurrentServerUidComments()[entry.UserUID] + : string.Empty; + _mainUi.EditNickEntry = entry.UserUID; + } + } + else + { + ImGui.SetCursorPosY(originalY); + + ImGui.SetNextItemWidth(UiShared.GetWindowContentRegionWidth() - ImGui.GetCursorPosX() - buttonSizes - ImGui.GetStyle().ItemSpacing.X * 2); + if (ImGui.InputTextWithHint("", "Nick/Notes", ref _mainUi.EditUserComment, 255, ImGuiInputTextFlags.EnterReturnsTrue)) + { + _configuration.SetCurrentServerUidComment(entry.UserUID, _mainUi.EditUserComment); + _configuration.Save(); + _mainUi.EditNickEntry = string.Empty; + } + + if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) + { + _mainUi.EditNickEntry = string.Empty; + } + UiShared.AttachToolTip("Hit ENTER to save\nRight click to cancel"); + } + + bool addButtonShown = !_apiController.PairedClients.Any(p => p.OtherUID == entry.UserUID); + if (isOwner) + { + ImGui.SetCursorPosY(originalY); + var subtractedWidth = addButtonShown ? (ImGui.GetStyle().ItemSpacing.X + plusButtonSize.X) : 0; + ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + UiShared.GetWindowContentRegionWidth() - subtractedWidth - trashButtonSize.X - ImGui.GetStyle().ItemSpacing.X - crownButtonSize.X); + + if (ImGuiComponents.IconButton(FontAwesomeIcon.Crown)) + { + if (UiShared.CtrlPressed() && UiShared.ShiftPressed()) + { + _ = _apiController.ChangeOwnerOfGroup(entry.GroupGID, entry.UserUID); + } + } + UiShared.AttachToolTip("Hold CTRL and SHIFT and click to transfer ownership of this Syncshell to " + (entry.UserAlias ?? entry.UserUID) + Environment.NewLine + "WARNING: This action is irreversible."); + ImGui.SameLine(); + if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash)) + { + if (UiShared.CtrlPressed()) + { + _ = _apiController.SendRemoveUserFromGroup(entry.GroupGID, entry.UserUID); + } + } + UiShared.AttachToolTip("Hold CTRL and click to remove user " + (entry.UserAlias ?? entry.UserUID) + " from Syncshell"); + } + + if (addButtonShown) + { + ImGui.SetCursorPosY(originalY); + ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + UiShared.GetWindowContentRegionWidth() - plusButtonSize.X); + + if (ImGuiComponents.IconButton(FontAwesomeIcon.Plus)) + { + _ = _apiController.SendPairedClientAddition(entry.UserUID); + } + UiShared.AttachToolTip("Pair with " + entryUID + " individually"); + } + } + } +} diff --git a/MareSynchronos/UI/UIShared.cs b/MareSynchronos/UI/UIShared.cs index 8447028..800324e 100644 --- a/MareSynchronos/UI/UIShared.cs +++ b/MareSynchronos/UI/UIShared.cs @@ -548,6 +548,47 @@ public class UiShared : IDisposable DrawHelpText("This allows you to stop the periodic scans of your Penumbra and Mare cache directories. Use this to move the Mare cache and Penumbra mod folders around. If you enable this permanently, run a Force rescan after adding mods to Penumbra."); } + private static Vector2 GetIconSize(FontAwesomeIcon icon) + { + ImGui.PushFont(UiBuilder.IconFont); + var iconSize = ImGui.CalcTextSize(icon.ToIconString()); + ImGui.PopFont(); + return iconSize; + } + + public static bool IconTextButton(FontAwesomeIcon icon, string text) + { + var buttonClicked = false; + + var iconSize = GetIconSize(icon); + var textSize = ImGui.CalcTextSize(text); + var padding = ImGui.GetStyle().FramePadding; + var spacing = ImGui.GetStyle().ItemSpacing; + + var buttonSizeX = iconSize.X + textSize.X + padding.X * 2 + spacing.X; + var buttonSizeY = (iconSize.Y > textSize.Y ? iconSize.Y : textSize.Y) + padding.Y * 2; + var buttonSize = new Vector2(buttonSizeX, buttonSizeY); + + if (ImGui.BeginChild(icon.ToIconString() + text, buttonSize)) + { + if (ImGui.Button("", buttonSize)) + { + buttonClicked = true; + } + + ImGui.SameLine(); + ImGui.SetCursorPosX(padding.X); + ImGui.PushFont(UiBuilder.IconFont); + ImGui.Text(icon.ToIconString()); + ImGui.PopFont(); + ImGui.SameLine(); + ImGui.Text(text); + ImGui.EndChild(); + } + + return buttonClicked; + } + public void Dispose() { _pluginInterface.UiBuilder.BuildFonts -= BuildFont; diff --git a/MareSynchronos/WebAPI/ApiController.Functions.Groups.cs b/MareSynchronos/WebAPI/ApiController.Functions.Groups.cs index c54c2ac..40b3f07 100644 --- a/MareSynchronos/WebAPI/ApiController.Functions.Groups.cs +++ b/MareSynchronos/WebAPI/ApiController.Functions.Groups.cs @@ -49,6 +49,18 @@ public partial class ApiController await _mareHub!.SendAsync(Api.SendGroupDelete, gid); } + public async Task SendChangeUserPinned(string gid, string uid, bool isPinned) + { + if (!IsConnected || SecretKey == "-") return; + await _mareHub!.SendAsync(Api.SendGroupChangePinned, gid, uid, isPinned); + } + + public async Task SendClearGroup(string gid) + { + if (!IsConnected || SecretKey == "-") return; + await _mareHub!.SendAsync(Api.SendGroupClear, gid); + } + public async Task SendLeaveGroup(string gid) { if (!IsConnected || SecretKey == "-") return;