make syncshell admin ui to standalone window
This commit is contained in:
@@ -3,6 +3,7 @@ using Dalamud.Interface.ImGuiFileDialog;
|
|||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
using MareSynchronos.API.Dto.Group;
|
||||||
using MareSynchronos.FileCache;
|
using MareSynchronos.FileCache;
|
||||||
using MareSynchronos.Interop;
|
using MareSynchronos.Interop;
|
||||||
using MareSynchronos.MareConfiguration;
|
using MareSynchronos.MareConfiguration;
|
||||||
@@ -103,6 +104,14 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
s.GetRequiredService<ServerConfigurationManager>(),
|
s.GetRequiredService<ServerConfigurationManager>(),
|
||||||
s.GetRequiredService<MareProfileManager>(),
|
s.GetRequiredService<MareProfileManager>(),
|
||||||
s.GetRequiredService<PairManager>(), pair)));
|
s.GetRequiredService<PairManager>(), pair)));
|
||||||
|
collection.AddSingleton(s =>
|
||||||
|
new Func<GroupFullInfoDto, SyncshellAdminUI>((dto) =>
|
||||||
|
new SyncshellAdminUI(s.GetRequiredService<ILogger<SyncshellAdminUI>>(),
|
||||||
|
s.GetRequiredService<MareMediator>(),
|
||||||
|
dto,
|
||||||
|
s.GetRequiredService<ApiController>(),
|
||||||
|
s.GetRequiredService<UiSharedService>(),
|
||||||
|
s.GetRequiredService<PairManager>())));
|
||||||
|
|
||||||
// add scoped services
|
// add scoped services
|
||||||
collection.AddScoped<PeriodicFileScanner>();
|
collection.AddScoped<PeriodicFileScanner>();
|
||||||
@@ -122,17 +131,18 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
collection.AddScoped<WindowMediatorSubscriberBase, PopupHandler>();
|
collection.AddScoped<WindowMediatorSubscriberBase, PopupHandler>();
|
||||||
collection.AddScoped<IPopupHandler, ReportPopupHandler>();
|
collection.AddScoped<IPopupHandler, ReportPopupHandler>();
|
||||||
collection.AddScoped<IPopupHandler, BanUserPopupHandler>();
|
collection.AddScoped<IPopupHandler, BanUserPopupHandler>();
|
||||||
collection.AddScoped<IPopupHandler, SyncshellAdminPopupHandler>();
|
|
||||||
collection.AddScoped<CacheCreationService>();
|
collection.AddScoped<CacheCreationService>();
|
||||||
collection.AddScoped<TransientResourceManager>();
|
collection.AddScoped<TransientResourceManager>();
|
||||||
collection.AddScoped<PlayerDataFactory>();
|
collection.AddScoped<PlayerDataFactory>();
|
||||||
collection.AddScoped<OnlinePlayerManager>();
|
collection.AddScoped<OnlinePlayerManager>();
|
||||||
collection.AddScoped((s) => new UiService(s.GetRequiredService<ILogger<UiService>>(), pluginInterface, s.GetRequiredService<MareConfigService>(),
|
collection.AddScoped((s) => new UiService(s.GetRequiredService<ILogger<UiService>>(), pluginInterface, s.GetRequiredService<MareConfigService>(),
|
||||||
s.GetRequiredService<WindowSystem>(), s.GetServices<WindowMediatorSubscriberBase>(), s.GetRequiredService<Func<Pair, StandaloneProfileUi>>(),
|
s.GetRequiredService<WindowSystem>(), s.GetServices<WindowMediatorSubscriberBase>(),
|
||||||
|
s.GetRequiredService<Func<Pair, StandaloneProfileUi>>(),
|
||||||
|
s.GetRequiredService<Func<GroupFullInfoDto, SyncshellAdminUI>>(),
|
||||||
s.GetRequiredService<FileDialogManager>(), s.GetRequiredService<MareMediator>()));
|
s.GetRequiredService<FileDialogManager>(), s.GetRequiredService<MareMediator>()));
|
||||||
collection.AddScoped((s) => new CommandManagerService(commandManager, s.GetRequiredService<PerformanceCollectorService>(),
|
collection.AddScoped((s) => new CommandManagerService(commandManager, s.GetRequiredService<PerformanceCollectorService>(),
|
||||||
s.GetRequiredService<ServerConfigurationManager>(), s.GetRequiredService<PeriodicFileScanner>(), s.GetRequiredService<ApiController>(),
|
s.GetRequiredService<ServerConfigurationManager>(), s.GetRequiredService<PeriodicFileScanner>(), s.GetRequiredService<ApiController>(),
|
||||||
s.GetRequiredService<MareMediator>()));
|
s.GetRequiredService<MareMediator>(), s.GetRequiredService<MareConfigService>()));
|
||||||
collection.AddScoped((s) => new NotificationService(s.GetRequiredService<ILogger<NotificationService>>(),
|
collection.AddScoped((s) => new NotificationService(s.GetRequiredService<ILogger<NotificationService>>(),
|
||||||
s.GetRequiredService<MareMediator>(), pluginInterface.UiBuilder, chatGui, s.GetRequiredService<MareConfigService>()));
|
s.GetRequiredService<MareMediator>(), pluginInterface.UiBuilder, chatGui, s.GetRequiredService<MareConfigService>()));
|
||||||
collection.AddScoped((s) => new UiSharedService(s.GetRequiredService<ILogger<UiSharedService>>(), s.GetRequiredService<IpcManager>(), s.GetRequiredService<ApiController>(),
|
collection.AddScoped((s) => new UiSharedService(s.GetRequiredService<ILogger<UiSharedService>>(), s.GetRequiredService<IpcManager>(), s.GetRequiredService<ApiController>(),
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public record PairHandlerVisibleMessage(PairHandler Player) : MessageBase;
|
|||||||
public record RefreshUiMessage : MessageBase;
|
public record RefreshUiMessage : MessageBase;
|
||||||
public record OpenReportPopupMessage(Pair PairToReport) : MessageBase;
|
public record OpenReportPopupMessage(Pair PairToReport) : MessageBase;
|
||||||
public record OpenBanUserPopupMessage(Pair PairToBan, GroupFullInfoDto GroupFullInfoDto) : MessageBase;
|
public record OpenBanUserPopupMessage(Pair PairToBan, GroupFullInfoDto GroupFullInfoDto) : MessageBase;
|
||||||
public record OpenSyncshellAdminPanelPopupMessage(GroupFullInfoDto GroupInfo) : MessageBase;
|
public record OpenSyncshellAdminPanel(GroupFullInfoDto GroupInfo) : MessageBase;
|
||||||
|
|
||||||
#pragma warning restore S2094
|
#pragma warning restore S2094
|
||||||
#pragma warning restore MA0048 // File name must match type name
|
#pragma warning restore MA0048 // File name must match type name
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
using Dalamud.Interface.ImGuiFileDialog;
|
using Dalamud.Interface.ImGuiFileDialog;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
|
using MareSynchronos.API.Dto.Group;
|
||||||
using MareSynchronos.MareConfiguration;
|
using MareSynchronos.MareConfiguration;
|
||||||
using MareSynchronos.PlayerData.Pairs;
|
using MareSynchronos.PlayerData.Pairs;
|
||||||
using MareSynchronos.Services.Mediator;
|
using MareSynchronos.Services.Mediator;
|
||||||
using MareSynchronos.UI;
|
using MareSynchronos.UI;
|
||||||
|
using MareSynchronos.UI.Components.Popup;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MareSynchronos.Services;
|
namespace MareSynchronos.Services;
|
||||||
@@ -17,10 +19,13 @@ public sealed class UiService : DisposableMediatorSubscriberBase
|
|||||||
private readonly ILogger<UiService> _logger;
|
private readonly ILogger<UiService> _logger;
|
||||||
private readonly MareConfigService _mareConfigService;
|
private readonly MareConfigService _mareConfigService;
|
||||||
private readonly WindowSystem _windowSystem;
|
private readonly WindowSystem _windowSystem;
|
||||||
|
private readonly Func<GroupFullInfoDto, SyncshellAdminUI> _syncshellAdminUiFactory;
|
||||||
|
|
||||||
public UiService(ILogger<UiService> logger, DalamudPluginInterface dalamudPluginInterface,
|
public UiService(ILogger<UiService> logger, DalamudPluginInterface dalamudPluginInterface,
|
||||||
MareConfigService mareConfigService, WindowSystem windowSystem,
|
MareConfigService mareConfigService, WindowSystem windowSystem,
|
||||||
IEnumerable<WindowMediatorSubscriberBase> windows, Func<Pair, StandaloneProfileUi> standaloneProfileUiFactory,
|
IEnumerable<WindowMediatorSubscriberBase> windows,
|
||||||
|
Func<Pair, StandaloneProfileUi> standaloneProfileUiFactory,
|
||||||
|
Func<GroupFullInfoDto, SyncshellAdminUI> syncshellAdminUiFactory,
|
||||||
FileDialogManager fileDialogManager, MareMediator mareMediator) : base(logger, mareMediator)
|
FileDialogManager fileDialogManager, MareMediator mareMediator) : base(logger, mareMediator)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@@ -28,6 +33,7 @@ public sealed class UiService : DisposableMediatorSubscriberBase
|
|||||||
_dalamudPluginInterface = dalamudPluginInterface;
|
_dalamudPluginInterface = dalamudPluginInterface;
|
||||||
_mareConfigService = mareConfigService;
|
_mareConfigService = mareConfigService;
|
||||||
_windowSystem = windowSystem;
|
_windowSystem = windowSystem;
|
||||||
|
_syncshellAdminUiFactory = syncshellAdminUiFactory;
|
||||||
_fileDialogManager = fileDialogManager;
|
_fileDialogManager = fileDialogManager;
|
||||||
|
|
||||||
_dalamudPluginInterface.UiBuilder.DisableGposeUiHide = true;
|
_dalamudPluginInterface.UiBuilder.DisableGposeUiHide = true;
|
||||||
@@ -51,6 +57,17 @@ public sealed class UiService : DisposableMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Mediator.Subscribe<OpenSyncshellAdminPanel>(this, (msg) =>
|
||||||
|
{
|
||||||
|
if (!_createdWindows.Exists(p => p is SyncshellAdminUI ui
|
||||||
|
&& string.Equals(ui.GroupFullInfo.GID, msg.GroupInfo.GID, StringComparison.Ordinal)))
|
||||||
|
{
|
||||||
|
var window = _syncshellAdminUiFactory(msg.GroupInfo);
|
||||||
|
_createdWindows.Add(window);
|
||||||
|
_windowSystem.AddWindow(window);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Mediator.Subscribe<RemoveWindowMessage>(this, (msg) =>
|
Mediator.Subscribe<RemoveWindowMessage>(this, (msg) =>
|
||||||
{
|
{
|
||||||
_windowSystem.RemoveWindow(msg.Window);
|
_windowSystem.RemoveWindow(msg.Window);
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ public class DrawFolderGroup : DrawFolderBase
|
|||||||
if (UiSharedService.IconTextButton(FontAwesomeIcon.Cog, "Open Admin Panel", menuWidth, true))
|
if (UiSharedService.IconTextButton(FontAwesomeIcon.Cog, "Open Admin Panel", menuWidth, true))
|
||||||
{
|
{
|
||||||
ImGui.CloseCurrentPopup();
|
ImGui.CloseCurrentPopup();
|
||||||
_mareMediator.Publish(new OpenSyncshellAdminPanelPopupMessage(_groupFullInfoDto));
|
_mareMediator.Publish(new OpenSyncshellAdminPanel(_groupFullInfoDto));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using MareSynchronos.Services.Mediator;
|
using MareSynchronos.Services.Mediator;
|
||||||
@@ -43,15 +44,6 @@ public class PopupHandler : WindowMediatorSubscriberBase
|
|||||||
((BanUserPopupHandler)_currentHandler).Open(msg);
|
((BanUserPopupHandler)_currentHandler).Open(msg);
|
||||||
IsOpen = true;
|
IsOpen = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
Mediator.Subscribe<OpenSyncshellAdminPanelPopupMessage>(this, (msg) =>
|
|
||||||
{
|
|
||||||
IsOpen = true;
|
|
||||||
_openPopup = true;
|
|
||||||
_currentHandler = _handlers.OfType<SyncshellAdminPopupHandler>().Single();
|
|
||||||
((SyncshellAdminPopupHandler)_currentHandler).Open(msg.GroupInfo);
|
|
||||||
IsOpen = true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
@@ -65,7 +57,7 @@ public class PopupHandler : WindowMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
var viewportSize = ImGui.GetWindowViewport().Size;
|
var viewportSize = ImGui.GetWindowViewport().Size;
|
||||||
ImGui.SetNextWindowSize(_currentHandler!.PopupSize);
|
ImGui.SetNextWindowSize(_currentHandler!.PopupSize * ImGuiHelpers.GlobalScale);
|
||||||
ImGui.SetNextWindowPos(viewportSize / 2, ImGuiCond.Always, new Vector2(0.5f));
|
ImGui.SetNextWindowPos(viewportSize / 2, ImGuiCond.Always, new Vector2(0.5f));
|
||||||
using var popup = ImRaii.Popup(WindowName, ImGuiWindowFlags.Modal);
|
using var popup = ImRaii.Popup(WindowName, ImGuiWindowFlags.Modal);
|
||||||
if (!popup) return;
|
if (!popup) return;
|
||||||
|
|||||||
@@ -1,234 +0,0 @@
|
|||||||
using Dalamud.Interface;
|
|
||||||
using Dalamud.Interface.Colors;
|
|
||||||
using Dalamud.Interface.Utility.Raii;
|
|
||||||
using ImGuiNET;
|
|
||||||
using MareSynchronos.API.Data.Extensions;
|
|
||||||
using MareSynchronos.API.Dto.Group;
|
|
||||||
using MareSynchronos.PlayerData.Pairs;
|
|
||||||
using MareSynchronos.WebAPI;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace MareSynchronos.UI.Components.Popup;
|
|
||||||
|
|
||||||
internal class SyncshellAdminPopupHandler : IPopupHandler
|
|
||||||
{
|
|
||||||
private readonly ApiController _apiController;
|
|
||||||
private readonly List<string> _oneTimeInvites = [];
|
|
||||||
private readonly PairManager _pairManager;
|
|
||||||
private readonly UiSharedService _uiSharedService;
|
|
||||||
private List<BannedGroupUserDto> _bannedUsers = [];
|
|
||||||
private GroupFullInfoDto _groupFullInfo = null!;
|
|
||||||
private bool _isModerator = false;
|
|
||||||
private bool _isOwner = false;
|
|
||||||
private int _multiInvites = 30;
|
|
||||||
private string _newPassword = string.Empty;
|
|
||||||
private bool _pwChangeSuccess = true;
|
|
||||||
|
|
||||||
public SyncshellAdminPopupHandler(ApiController apiController, UiSharedService uiSharedService, PairManager pairManager)
|
|
||||||
{
|
|
||||||
_apiController = apiController;
|
|
||||||
_uiSharedService = uiSharedService;
|
|
||||||
_pairManager = pairManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2 PopupSize => new(700, 500);
|
|
||||||
|
|
||||||
public void DrawContent()
|
|
||||||
{
|
|
||||||
if (!_isModerator && !_isOwner) return;
|
|
||||||
|
|
||||||
_groupFullInfo = _pairManager.Groups[_groupFullInfo.Group];
|
|
||||||
|
|
||||||
using (ImRaii.PushFont(_uiSharedService.UidFont))
|
|
||||||
ImGui.TextUnformatted(_groupFullInfo.GroupAliasOrGID + " Administrative Panel");
|
|
||||||
|
|
||||||
ImGui.Separator();
|
|
||||||
var perm = _groupFullInfo.GroupPermissions;
|
|
||||||
|
|
||||||
var inviteNode = ImRaii.TreeNode("Invites");
|
|
||||||
if (inviteNode)
|
|
||||||
{
|
|
||||||
bool isInvitesDisabled = perm.IsDisableInvites();
|
|
||||||
|
|
||||||
if (UiSharedService.IconTextButton(isInvitesDisabled ? FontAwesomeIcon.Unlock : FontAwesomeIcon.Lock,
|
|
||||||
isInvitesDisabled ? "Unlock Syncshell" : "Lock Syncshell"))
|
|
||||||
{
|
|
||||||
perm.SetDisableInvites(!isInvitesDisabled);
|
|
||||||
_ = _apiController.GroupChangeGroupPermissionState(new(_groupFullInfo.Group, perm));
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.Dummy(new(2f));
|
|
||||||
|
|
||||||
UiSharedService.TextWrapped("One-time invites work as single-use passwords. Use those if you do not want to distribute your Syncshell password.");
|
|
||||||
if (UiSharedService.IconTextButton(FontAwesomeIcon.Envelope, "Single one-time invite"))
|
|
||||||
{
|
|
||||||
ImGui.SetClipboardText(_apiController.GroupCreateTempInvite(new(_groupFullInfo.Group), 1).Result.FirstOrDefault() ?? string.Empty);
|
|
||||||
}
|
|
||||||
UiSharedService.AttachToolTip("Creates a single-use password for joining the syncshell which is valid for 24h and copies it to the clipboard.");
|
|
||||||
ImGui.InputInt("##amountofinvites", ref _multiInvites);
|
|
||||||
ImGui.SameLine();
|
|
||||||
using (ImRaii.Disabled(_multiInvites <= 1 || _multiInvites > 100))
|
|
||||||
{
|
|
||||||
if (UiSharedService.IconTextButton(FontAwesomeIcon.Envelope, "Generate " + _multiInvites + " one-time invites"))
|
|
||||||
{
|
|
||||||
_oneTimeInvites.AddRange(_apiController.GroupCreateTempInvite(new(_groupFullInfo.Group), _multiInvites).Result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_oneTimeInvites.Any())
|
|
||||||
{
|
|
||||||
var invites = string.Join(Environment.NewLine, _oneTimeInvites);
|
|
||||||
ImGui.InputTextMultiline("Generated Multi Invites", ref invites, 5000, new(0, 0), ImGuiInputTextFlags.ReadOnly);
|
|
||||||
if (UiSharedService.IconTextButton(FontAwesomeIcon.Copy, "Copy Invites to clipboard"))
|
|
||||||
{
|
|
||||||
ImGui.SetClipboardText(invites);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inviteNode.Dispose();
|
|
||||||
|
|
||||||
var mgmtNode = ImRaii.TreeNode("User Management");
|
|
||||||
if (mgmtNode)
|
|
||||||
{
|
|
||||||
if (UiSharedService.IconTextButton(FontAwesomeIcon.Broom, "Clear Syncshell"))
|
|
||||||
{
|
|
||||||
_ = _apiController.GroupClear(new(_groupFullInfo.Group));
|
|
||||||
}
|
|
||||||
UiSharedService.AttachToolTip("This will remove all non-pinned, non-moderator users from the Syncshell");
|
|
||||||
|
|
||||||
ImGui.Dummy(new(2f));
|
|
||||||
|
|
||||||
if (UiSharedService.IconTextButton(FontAwesomeIcon.Retweet, "Refresh Banlist from Server"))
|
|
||||||
{
|
|
||||||
_bannedUsers = _apiController.GroupGetBannedUsers(new GroupDto(_groupFullInfo.Group)).Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui.BeginTable("bannedusertable" + _groupFullInfo.GID, 6, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingStretchProp | ImGuiTableFlags.ScrollY))
|
|
||||||
{
|
|
||||||
ImGui.TableSetupColumn("UID", ImGuiTableColumnFlags.None, 1);
|
|
||||||
ImGui.TableSetupColumn("Alias", ImGuiTableColumnFlags.None, 1);
|
|
||||||
ImGui.TableSetupColumn("By", ImGuiTableColumnFlags.None, 1);
|
|
||||||
ImGui.TableSetupColumn("Date", ImGuiTableColumnFlags.None, 2);
|
|
||||||
ImGui.TableSetupColumn("Reason", ImGuiTableColumnFlags.None, 3);
|
|
||||||
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 1);
|
|
||||||
|
|
||||||
ImGui.TableHeadersRow();
|
|
||||||
|
|
||||||
foreach (var bannedUser in _bannedUsers.ToList())
|
|
||||||
{
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
ImGui.TextUnformatted(bannedUser.UID);
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
ImGui.TextUnformatted(bannedUser.UserAlias ?? string.Empty);
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
ImGui.TextUnformatted(bannedUser.BannedBy);
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
ImGui.TextUnformatted(bannedUser.BannedOn.ToLocalTime().ToString(CultureInfo.CurrentCulture));
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
UiSharedService.TextWrapped(bannedUser.Reason);
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
if (UiSharedService.IconTextButton(FontAwesomeIcon.Check, "Unban#" + bannedUser.UID))
|
|
||||||
{
|
|
||||||
_ = _apiController.GroupUnbanUser(bannedUser);
|
|
||||||
_bannedUsers.RemoveAll(b => string.Equals(b.UID, bannedUser.UID, StringComparison.Ordinal));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.EndTable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mgmtNode.Dispose();
|
|
||||||
|
|
||||||
var permNode = ImRaii.TreeNode("Permissions");
|
|
||||||
if (permNode)
|
|
||||||
{
|
|
||||||
bool isDisableAnimations = perm.IsPreferDisableAnimations();
|
|
||||||
bool isDisableSounds = perm.IsPreferDisableSounds();
|
|
||||||
bool isDisableVfx = perm.IsPreferDisableVFX();
|
|
||||||
|
|
||||||
ImGui.AlignTextToFramePadding();
|
|
||||||
ImGui.Text("Suggest Sound Sync");
|
|
||||||
UiSharedService.BooleanToColoredIcon(!isDisableSounds);
|
|
||||||
ImGui.SameLine(230);
|
|
||||||
if (UiSharedService.IconTextButton(isDisableSounds ? FontAwesomeIcon.VolumeUp : FontAwesomeIcon.VolumeMute,
|
|
||||||
isDisableSounds ? "Suggest to enable sound sync" : "Suggest to disable sound sync"))
|
|
||||||
{
|
|
||||||
perm.SetPreferDisableSounds(!perm.IsPreferDisableSounds());
|
|
||||||
_ = _apiController.GroupChangeGroupPermissionState(new(_groupFullInfo.Group, perm));
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.AlignTextToFramePadding();
|
|
||||||
ImGui.Text("Suggest Animation Sync");
|
|
||||||
UiSharedService.BooleanToColoredIcon(!isDisableAnimations);
|
|
||||||
ImGui.SameLine(230);
|
|
||||||
if (UiSharedService.IconTextButton(isDisableAnimations ? FontAwesomeIcon.Running : FontAwesomeIcon.Stop,
|
|
||||||
isDisableAnimations ? "Suggest to enable animation sync" : "Suggest to disable animation sync"))
|
|
||||||
{
|
|
||||||
perm.SetPreferDisableAnimations(!perm.IsPreferDisableAnimations());
|
|
||||||
_ = _apiController.GroupChangeGroupPermissionState(new(_groupFullInfo.Group, perm));
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.AlignTextToFramePadding();
|
|
||||||
ImGui.Text("Suggest VFX Sync");
|
|
||||||
UiSharedService.BooleanToColoredIcon(!isDisableVfx);
|
|
||||||
ImGui.SameLine(230);
|
|
||||||
if (UiSharedService.IconTextButton(isDisableVfx ? FontAwesomeIcon.Sun : FontAwesomeIcon.Circle,
|
|
||||||
isDisableVfx ? "Suggest to enable vfx sync" : "Suggest to disable vfx sync"))
|
|
||||||
{
|
|
||||||
perm.SetPreferDisableVFX(!perm.IsPreferDisableVFX());
|
|
||||||
_ = _apiController.GroupChangeGroupPermissionState(new(_groupFullInfo.Group, perm));
|
|
||||||
}
|
|
||||||
|
|
||||||
UiSharedService.TextWrapped("Note: those suggested permissions will be shown to users on joining the Syncshell.");
|
|
||||||
}
|
|
||||||
permNode.Dispose();
|
|
||||||
|
|
||||||
if (_isOwner)
|
|
||||||
{
|
|
||||||
var ownerNode = ImRaii.TreeNode("Owner Settings");
|
|
||||||
if (ownerNode)
|
|
||||||
{
|
|
||||||
ImGui.AlignTextToFramePadding();
|
|
||||||
ImGui.TextUnformatted("New Password");
|
|
||||||
ImGui.SameLine();
|
|
||||||
ImGui.InputTextWithHint("##changepw", "Min 10 characters", ref _newPassword, 50);
|
|
||||||
ImGui.SameLine();
|
|
||||||
using (ImRaii.Disabled(_newPassword.Length < 10))
|
|
||||||
{
|
|
||||||
if (UiSharedService.IconTextButton(FontAwesomeIcon.Passport, "Change Password"))
|
|
||||||
{
|
|
||||||
_pwChangeSuccess = _apiController.GroupChangePassword(new GroupPasswordDto(_groupFullInfo.Group, _newPassword)).Result;
|
|
||||||
_newPassword = string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UiSharedService.AttachToolTip("Password requires to be at least 10 characters long. This action is irreversible.");
|
|
||||||
|
|
||||||
if (!_pwChangeSuccess)
|
|
||||||
{
|
|
||||||
UiSharedService.ColorTextWrapped("Failed to change the password. Password requires to be at least 10 characters long.", ImGuiColors.DalamudYellow);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete Syncshell") && UiSharedService.CtrlPressed() && UiSharedService.ShiftPressed())
|
|
||||||
{
|
|
||||||
ImGui.CloseCurrentPopup();
|
|
||||||
_ = _apiController.GroupDelete(new(_groupFullInfo.Group));
|
|
||||||
}
|
|
||||||
UiSharedService.AttachToolTip("Hold CTRL and Shift and click to delete this Syncshell." + Environment.NewLine + "WARNING: this action is irreversible.");
|
|
||||||
}
|
|
||||||
ownerNode.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Open(GroupFullInfoDto groupFullInfo)
|
|
||||||
{
|
|
||||||
_groupFullInfo = groupFullInfo;
|
|
||||||
_isOwner = string.Equals(_groupFullInfo.OwnerUID, _apiController.UID, StringComparison.Ordinal);
|
|
||||||
_isModerator = _groupFullInfo.GroupUserInfo.IsModerator();
|
|
||||||
_newPassword = string.Empty;
|
|
||||||
_bannedUsers.Clear();
|
|
||||||
_oneTimeInvites.Clear();
|
|
||||||
_multiInvites = 30;
|
|
||||||
_pwChangeSuccess = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
252
MareSynchronos/UI/SyncshellAdminUI.cs
Normal file
252
MareSynchronos/UI/SyncshellAdminUI.cs
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
using Dalamud.Interface;
|
||||||
|
using Dalamud.Interface.Colors;
|
||||||
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
using ImGuiNET;
|
||||||
|
using MareSynchronos.API.Data.Extensions;
|
||||||
|
using MareSynchronos.API.Dto.Group;
|
||||||
|
using MareSynchronos.PlayerData.Pairs;
|
||||||
|
using MareSynchronos.Services.Mediator;
|
||||||
|
using MareSynchronos.WebAPI;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace MareSynchronos.UI.Components.Popup;
|
||||||
|
|
||||||
|
public class SyncshellAdminUI : WindowMediatorSubscriberBase
|
||||||
|
{
|
||||||
|
private readonly ApiController _apiController;
|
||||||
|
private readonly bool _isModerator = false;
|
||||||
|
private readonly bool _isOwner = false;
|
||||||
|
private readonly List<string> _oneTimeInvites = [];
|
||||||
|
private readonly PairManager _pairManager;
|
||||||
|
private readonly UiSharedService _uiSharedService;
|
||||||
|
private List<BannedGroupUserDto> _bannedUsers = [];
|
||||||
|
private int _multiInvites;
|
||||||
|
private string _newPassword;
|
||||||
|
private bool _pwChangeSuccess;
|
||||||
|
public SyncshellAdminUI(ILogger<SyncshellAdminUI> logger, MareMediator mediator, GroupFullInfoDto groupFullInfo, ApiController apiController, UiSharedService uiSharedService, PairManager pairManager)
|
||||||
|
: base(logger, mediator, "Syncshell Admin Panel (" + groupFullInfo.GID + ")")
|
||||||
|
{
|
||||||
|
GroupFullInfo = groupFullInfo;
|
||||||
|
_apiController = apiController;
|
||||||
|
_uiSharedService = uiSharedService;
|
||||||
|
_pairManager = pairManager;
|
||||||
|
_isOwner = string.Equals(GroupFullInfo.OwnerUID, _apiController.UID, StringComparison.Ordinal);
|
||||||
|
_isModerator = GroupFullInfo.GroupUserInfo.IsModerator();
|
||||||
|
_newPassword = string.Empty;
|
||||||
|
_multiInvites = 30;
|
||||||
|
_pwChangeSuccess = true;
|
||||||
|
IsOpen = true;
|
||||||
|
SizeConstraints = new WindowSizeConstraints()
|
||||||
|
{
|
||||||
|
MinimumSize = new(700, 500),
|
||||||
|
MaximumSize = new(700, 2000),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupFullInfoDto GroupFullInfo { get; private set; }
|
||||||
|
|
||||||
|
public override void Draw()
|
||||||
|
{
|
||||||
|
if (!_isModerator && !_isOwner) return;
|
||||||
|
|
||||||
|
GroupFullInfo = _pairManager.Groups[GroupFullInfo.Group];
|
||||||
|
|
||||||
|
using var id = ImRaii.PushId("syncshell_admin_" + GroupFullInfo.GID);
|
||||||
|
|
||||||
|
using (ImRaii.PushFont(_uiSharedService.UidFont))
|
||||||
|
ImGui.TextUnformatted(GroupFullInfo.GroupAliasOrGID + " Administrative Panel");
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
var perm = GroupFullInfo.GroupPermissions;
|
||||||
|
|
||||||
|
using var tabbar = ImRaii.TabBar("syncshell_tab_" + GroupFullInfo.GID);
|
||||||
|
|
||||||
|
if (tabbar)
|
||||||
|
{
|
||||||
|
var inviteTab = ImRaii.TabItem("Invites");
|
||||||
|
if (inviteTab)
|
||||||
|
{
|
||||||
|
bool isInvitesDisabled = perm.IsDisableInvites();
|
||||||
|
|
||||||
|
if (UiSharedService.IconTextButton(isInvitesDisabled ? FontAwesomeIcon.Unlock : FontAwesomeIcon.Lock,
|
||||||
|
isInvitesDisabled ? "Unlock Syncshell" : "Lock Syncshell"))
|
||||||
|
{
|
||||||
|
perm.SetDisableInvites(!isInvitesDisabled);
|
||||||
|
_ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Dummy(new(2f));
|
||||||
|
|
||||||
|
UiSharedService.TextWrapped("One-time invites work as single-use passwords. Use those if you do not want to distribute your Syncshell password.");
|
||||||
|
if (UiSharedService.IconTextButton(FontAwesomeIcon.Envelope, "Single one-time invite"))
|
||||||
|
{
|
||||||
|
ImGui.SetClipboardText(_apiController.GroupCreateTempInvite(new(GroupFullInfo.Group), 1).Result.FirstOrDefault() ?? string.Empty);
|
||||||
|
}
|
||||||
|
UiSharedService.AttachToolTip("Creates a single-use password for joining the syncshell which is valid for 24h and copies it to the clipboard.");
|
||||||
|
ImGui.InputInt("##amountofinvites", ref _multiInvites);
|
||||||
|
ImGui.SameLine();
|
||||||
|
using (ImRaii.Disabled(_multiInvites <= 1 || _multiInvites > 100))
|
||||||
|
{
|
||||||
|
if (UiSharedService.IconTextButton(FontAwesomeIcon.Envelope, "Generate " + _multiInvites + " one-time invites"))
|
||||||
|
{
|
||||||
|
_oneTimeInvites.AddRange(_apiController.GroupCreateTempInvite(new(GroupFullInfo.Group), _multiInvites).Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_oneTimeInvites.Any())
|
||||||
|
{
|
||||||
|
var invites = string.Join(Environment.NewLine, _oneTimeInvites);
|
||||||
|
ImGui.InputTextMultiline("Generated Multi Invites", ref invites, 5000, new(0, 0), ImGuiInputTextFlags.ReadOnly);
|
||||||
|
if (UiSharedService.IconTextButton(FontAwesomeIcon.Copy, "Copy Invites to clipboard"))
|
||||||
|
{
|
||||||
|
ImGui.SetClipboardText(invites);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inviteTab.Dispose();
|
||||||
|
|
||||||
|
var mgmtTab = ImRaii.TabItem("User Management");
|
||||||
|
if (mgmtTab)
|
||||||
|
{
|
||||||
|
if (UiSharedService.IconTextButton(FontAwesomeIcon.Broom, "Clear Syncshell"))
|
||||||
|
{
|
||||||
|
_ = _apiController.GroupClear(new(GroupFullInfo.Group));
|
||||||
|
}
|
||||||
|
UiSharedService.AttachToolTip("This will remove all non-pinned, non-moderator users from the Syncshell");
|
||||||
|
|
||||||
|
ImGui.Dummy(new(2f));
|
||||||
|
|
||||||
|
if (UiSharedService.IconTextButton(FontAwesomeIcon.Retweet, "Refresh Banlist from Server"))
|
||||||
|
{
|
||||||
|
_bannedUsers = _apiController.GroupGetBannedUsers(new GroupDto(GroupFullInfo.Group)).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.BeginTable("bannedusertable" + GroupFullInfo.GID, 6, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingStretchProp | ImGuiTableFlags.ScrollY))
|
||||||
|
{
|
||||||
|
ImGui.TableSetupColumn("UID", ImGuiTableColumnFlags.None, 1);
|
||||||
|
ImGui.TableSetupColumn("Alias", ImGuiTableColumnFlags.None, 1);
|
||||||
|
ImGui.TableSetupColumn("By", ImGuiTableColumnFlags.None, 1);
|
||||||
|
ImGui.TableSetupColumn("Date", ImGuiTableColumnFlags.None, 2);
|
||||||
|
ImGui.TableSetupColumn("Reason", ImGuiTableColumnFlags.None, 3);
|
||||||
|
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 1);
|
||||||
|
|
||||||
|
ImGui.TableHeadersRow();
|
||||||
|
|
||||||
|
foreach (var bannedUser in _bannedUsers.ToList())
|
||||||
|
{
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
ImGui.TextUnformatted(bannedUser.UID);
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
ImGui.TextUnformatted(bannedUser.UserAlias ?? string.Empty);
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
ImGui.TextUnformatted(bannedUser.BannedBy);
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
ImGui.TextUnformatted(bannedUser.BannedOn.ToLocalTime().ToString(CultureInfo.CurrentCulture));
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
UiSharedService.TextWrapped(bannedUser.Reason);
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
if (UiSharedService.IconTextButton(FontAwesomeIcon.Check, "Unban#" + bannedUser.UID))
|
||||||
|
{
|
||||||
|
_ = _apiController.GroupUnbanUser(bannedUser);
|
||||||
|
_bannedUsers.RemoveAll(b => string.Equals(b.UID, bannedUser.UID, StringComparison.Ordinal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mgmtTab.Dispose();
|
||||||
|
|
||||||
|
var permissionTab = ImRaii.TabItem("Permissions");
|
||||||
|
if (permissionTab)
|
||||||
|
{
|
||||||
|
bool isDisableAnimations = perm.IsPreferDisableAnimations();
|
||||||
|
bool isDisableSounds = perm.IsPreferDisableSounds();
|
||||||
|
bool isDisableVfx = perm.IsPreferDisableVFX();
|
||||||
|
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.Text("Suggest Sound Sync");
|
||||||
|
UiSharedService.BooleanToColoredIcon(!isDisableSounds);
|
||||||
|
ImGui.SameLine(230);
|
||||||
|
if (UiSharedService.IconTextButton(isDisableSounds ? FontAwesomeIcon.VolumeUp : FontAwesomeIcon.VolumeMute,
|
||||||
|
isDisableSounds ? "Suggest to enable sound sync" : "Suggest to disable sound sync"))
|
||||||
|
{
|
||||||
|
perm.SetPreferDisableSounds(!perm.IsPreferDisableSounds());
|
||||||
|
_ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.Text("Suggest Animation Sync");
|
||||||
|
UiSharedService.BooleanToColoredIcon(!isDisableAnimations);
|
||||||
|
ImGui.SameLine(230);
|
||||||
|
if (UiSharedService.IconTextButton(isDisableAnimations ? FontAwesomeIcon.Running : FontAwesomeIcon.Stop,
|
||||||
|
isDisableAnimations ? "Suggest to enable animation sync" : "Suggest to disable animation sync"))
|
||||||
|
{
|
||||||
|
perm.SetPreferDisableAnimations(!perm.IsPreferDisableAnimations());
|
||||||
|
_ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.Text("Suggest VFX Sync");
|
||||||
|
UiSharedService.BooleanToColoredIcon(!isDisableVfx);
|
||||||
|
ImGui.SameLine(230);
|
||||||
|
if (UiSharedService.IconTextButton(isDisableVfx ? FontAwesomeIcon.Sun : FontAwesomeIcon.Circle,
|
||||||
|
isDisableVfx ? "Suggest to enable vfx sync" : "Suggest to disable vfx sync"))
|
||||||
|
{
|
||||||
|
perm.SetPreferDisableVFX(!perm.IsPreferDisableVFX());
|
||||||
|
_ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm));
|
||||||
|
}
|
||||||
|
|
||||||
|
UiSharedService.TextWrapped("Note: those suggested permissions will be shown to users on joining the Syncshell.");
|
||||||
|
}
|
||||||
|
permissionTab.Dispose();
|
||||||
|
|
||||||
|
if (_isOwner)
|
||||||
|
{
|
||||||
|
var ownerTab = ImRaii.TabItem("Owner Settings");
|
||||||
|
if (ownerTab)
|
||||||
|
{
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("New Password");
|
||||||
|
var availableWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
|
||||||
|
var buttonSize = UiSharedService.GetIconTextButtonSize(FontAwesomeIcon.Passport, "Change Password").X;
|
||||||
|
var textSize = ImGui.CalcTextSize("New Password").X;
|
||||||
|
var spacing = ImGui.GetStyle().ItemSpacing.X;
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetNextItemWidth(availableWidth - buttonSize - textSize - spacing * 2);
|
||||||
|
ImGui.InputTextWithHint("##changepw", "Min 10 characters", ref _newPassword, 50);
|
||||||
|
ImGui.SameLine();
|
||||||
|
using (ImRaii.Disabled(_newPassword.Length < 10))
|
||||||
|
{
|
||||||
|
if (UiSharedService.IconTextButton(FontAwesomeIcon.Passport, "Change Password"))
|
||||||
|
{
|
||||||
|
_pwChangeSuccess = _apiController.GroupChangePassword(new GroupPasswordDto(GroupFullInfo.Group, _newPassword)).Result;
|
||||||
|
_newPassword = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UiSharedService.AttachToolTip("Password requires to be at least 10 characters long. This action is irreversible.");
|
||||||
|
|
||||||
|
if (!_pwChangeSuccess)
|
||||||
|
{
|
||||||
|
UiSharedService.ColorTextWrapped("Failed to change the password. Password requires to be at least 10 characters long.", ImGuiColors.DalamudYellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete Syncshell") && UiSharedService.CtrlPressed() && UiSharedService.ShiftPressed())
|
||||||
|
{
|
||||||
|
IsOpen = false;
|
||||||
|
_ = _apiController.GroupDelete(new(GroupFullInfo.Group));
|
||||||
|
}
|
||||||
|
UiSharedService.AttachToolTip("Hold CTRL and Shift and click to delete this Syncshell." + Environment.NewLine + "WARNING: this action is irreversible.");
|
||||||
|
}
|
||||||
|
ownerTab.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnClose()
|
||||||
|
{
|
||||||
|
Mediator.Publish(new RemoveWindowMessage(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user