diff --git a/MareAPI b/MareAPI index aaa48b8..ac4cef6 160000 --- a/MareAPI +++ b/MareAPI @@ -1 +1 @@ -Subproject commit aaa48b820461c46076cd639d82d57894999652c1 +Subproject commit ac4cef6baea03393c41c27f27533d3910f4ef157 diff --git a/MareSynchronos/UI/GroupPanel.cs b/MareSynchronos/UI/GroupPanel.cs index 6c2b8a4..3b3eea1 100644 --- a/MareSynchronos/UI/GroupPanel.cs +++ b/MareSynchronos/UI/GroupPanel.cs @@ -32,6 +32,7 @@ namespace MareSynchronos.UI private bool _showModalChangePassword; private bool _showModalBanUser; private bool _showModalBanList = false; + private bool _showModalBulkOneTimeInvites = false; private string _newSyncShellPassword = string.Empty; private string _banReason = string.Empty; private bool _isPasswordValid; @@ -40,9 +41,12 @@ namespace MareSynchronos.UI private GroupCreatedDto? _lastCreatedGroup = null; private readonly Dictionary ExpandedGroupState = new(StringComparer.Ordinal); private List _bannedUsers = new(); + private List _bulkOneTimeInvites = new(); private bool _modalBanListOpened; + private bool _modalBulkOneTimeInvitesOpened; private bool _banUserPopupOpen; private bool _modalChangePwOpened; + private int _bulkInviteCount = 10; public GroupPanel(CompactUi mainUi, UiShared uiShared, Configuration configuration, ApiController apiController) { @@ -368,6 +372,41 @@ namespace MareSynchronos.UI ImGui.EndPopup(); } + if (_showModalBulkOneTimeInvites && !_modalBulkOneTimeInvitesOpened) + { + _modalBulkOneTimeInvitesOpened = true; + ImGui.OpenPopup("Create Bulk One-Time Invites"); + } + + if (!_showModalBulkOneTimeInvites) _modalBulkOneTimeInvitesOpened = false; + + if (ImGui.BeginPopupModal("Create Bulk One-Time Invites", ref _showModalBulkOneTimeInvites, UiShared.PopupWindowFlags)) + { + UiShared.TextWrapped("This allows you to create up to 100 one-time invites at once for the Syncshell " + name + "." + Environment.NewLine + + "The invites are valid for 24h after creation and will automatically expire."); + ImGui.Separator(); + if (_bulkOneTimeInvites.Count == 0) + { + ImGui.SetNextItemWidth(-1); + ImGui.SliderInt("Amount##bulkinvites", ref _bulkInviteCount, 1, 100); + if (UiShared.IconTextButton(FontAwesomeIcon.MailBulk, "Create invites")) + { + _bulkOneTimeInvites = _apiController.GroupCreateTempInvite(group.GID, _bulkInviteCount).Result; + } + } + else + { + UiShared.TextWrapped("A total of " + _bulkOneTimeInvites.Count + " invites have been created."); + if (UiShared.IconTextButton(FontAwesomeIcon.Copy, "Copy invites to clipboard")) + { + ImGui.SetClipboardText(string.Join(Environment.NewLine, _bulkOneTimeInvites)); + } + } + + UiShared.SetScaledWindowSize(290); + ImGui.EndPopup(); + } + ImGui.Indent(collapseButton.X); if (ExpandedGroupState[group.GID]) { @@ -474,6 +513,21 @@ namespace MareSynchronos.UI 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."); + if (UiShared.IconTextButton(FontAwesomeIcon.Envelope, "Single one-time invite")) + { + ImGui.CloseCurrentPopup(); + ImGui.SetClipboardText(_apiController.GroupCreateTempInvite(entry.GID, 1).Result.FirstOrDefault() ?? string.Empty); + } + UiShared.AttachToolTip("Creates a single-use password for joining the syncshell which is valid for 24h and copies it to the clipboard."); + + if (UiShared.IconTextButton(FontAwesomeIcon.MailBulk, "Bulk one-time invites")) + { + ImGui.CloseCurrentPopup(); + _showModalBulkOneTimeInvites = true; + _bulkOneTimeInvites.Clear(); + } + UiShared.AttachToolTip("Opens a dialog to create up to 100 single-use passwords for joining the syncshell."); + if (UiShared.IconTextButton(FontAwesomeIcon.Ban, "Manage Banlist")) { ImGui.CloseCurrentPopup(); diff --git a/MareSynchronos/UI/IntroUI.cs b/MareSynchronos/UI/IntroUI.cs index 3135309..d872586 100644 --- a/MareSynchronos/UI/IntroUI.cs +++ b/MareSynchronos/UI/IntroUI.cs @@ -213,7 +213,7 @@ internal class IntroUi : Window, IDisposable "Additionally, a local cache folder must be set where Mare Synchronos will download its local file cache to. " + "Once the Cache Folder is set and the scan complete, this page will automatically forward to registration at a service."); UiShared.TextWrapped("Note: The initial scan, depending on the amount of mods you have, might take a while. Please wait until it is completed."); - UiShared.ColorTextWrapped("Warning: once past this step you should not delete the FileCache.db of Mare Synchronos in the Plugin Configurations folder of Dalamud. " + + UiShared.ColorTextWrapped("Warning: once past this step you should not delete the FileCache.csv of Mare Synchronos in the Plugin Configurations folder of Dalamud. " + "Otherwise on the next launch a full re-scan of the file cache database will be initiated.", ImGuiColors.DalamudYellow); _uiShared.DrawCacheDirectorySetting(); } @@ -238,7 +238,7 @@ internal class IntroUi : Window, IDisposable ImGui.Separator(); UiShared.TextWrapped("To be able to use Mare Synchronos you will have to register an account."); UiShared.TextWrapped("For the official Mare Synchronos Servers the account creation will be handled on the official Mare Synchronos Discord. Due to security risks for the server, there is no way to handle this senisibly otherwise."); - UiShared.TextWrapped("If you want to register at the main server \"" + WebAPI.ApiController.MainServer + "\" join the Discord and follow the instructions as described in #registration."); + UiShared.TextWrapped("If you want to register at the main server \"" + WebAPI.ApiController.MainServer + "\" join the Discord and follow the instructions as described in #mare-commands."); if (ImGui.Button("Join the Mare Synchronos Discord")) { diff --git a/MareSynchronos/UI/UIShared.cs b/MareSynchronos/UI/UIShared.cs index 2b41852..1080a36 100644 --- a/MareSynchronos/UI/UIShared.cs +++ b/MareSynchronos/UI/UIShared.cs @@ -400,10 +400,9 @@ public class UiShared : IDisposable if (_enterSecretKey) { - ColorTextWrapped("This will overwrite your currently used secret key for the selected service. Make sure to have a backup for the current secret key if you want to switch back to this account.", ImGuiColors.DalamudYellow); - if (!_pluginConfiguration.ClientSecret.ContainsKey(_pluginConfiguration.ApiUri)) + if (_pluginConfiguration.ClientSecret.ContainsKey(_pluginConfiguration.ApiUri)) { - ColorTextWrapped("IF YOU HAVE NEVER MADE AN ACCOUNT BEFORE DO NOT ENTER ANYTHING HERE", ImGuiColors.DalamudYellow); + ColorTextWrapped("A secret key was previously set for this service. Entering a new secret key will overwrite the one set prior.", ImGuiColors.DalamudYellow); } var text = "Enter Secret Key"; diff --git a/MareSynchronos/WebAPI/ApiController.Functions.Groups.cs b/MareSynchronos/WebAPI/ApiController.Functions.Groups.cs index 716dde1..5cb8184 100644 --- a/MareSynchronos/WebAPI/ApiController.Functions.Groups.cs +++ b/MareSynchronos/WebAPI/ApiController.Functions.Groups.cs @@ -107,4 +107,10 @@ public partial class ApiController if (!IsConnected || string.Equals(SecretKey, "-", System.StringComparison.Ordinal)) return; await _mareHub!.SendAsync(nameof(GroupSetModerator), gid, uid, isModerator).ConfigureAwait(false); } + + public async Task> GroupCreateTempInvite(string gid, int amount) + { + if (!IsConnected || string.Equals(SecretKey, "-", System.StringComparison.Ordinal)) return new(); + return await _mareHub!.InvokeAsync>(nameof(GroupCreateTempInvite), gid, amount).ConfigureAwait(false); + } } \ No newline at end of file