rework main ui

This commit is contained in:
rootdarkarchon
2023-10-21 18:29:20 +02:00
parent 984ee08a2b
commit 33344386c4
11 changed files with 656 additions and 132 deletions

Submodule MareAPI updated: 9199d9c667...d04781fddf

View File

@@ -100,7 +100,7 @@ public sealed class CommandManagerService : IDisposable
} }
else if (string.Equals(splitArgs[0], "analyze", StringComparison.OrdinalIgnoreCase)) else if (string.Equals(splitArgs[0], "analyze", StringComparison.OrdinalIgnoreCase))
{ {
_mediator.Publish(new OpenDataAnalysisUiMessage()); _mediator.Publish(new UiToggleMessage(typeof(DataAnalysisUi)));
} }
} }
} }

View File

@@ -15,7 +15,6 @@ namespace MareSynchronos.Services.Mediator;
public record SwitchToIntroUiMessage : MessageBase; public record SwitchToIntroUiMessage : MessageBase;
public record SwitchToMainUiMessage : MessageBase; public record SwitchToMainUiMessage : MessageBase;
public record OpenSettingsUiMessage : MessageBase; public record OpenSettingsUiMessage : MessageBase;
public record OpenDataAnalysisUiMessage : MessageBase;
public record DalamudLoginMessage : MessageBase; public record DalamudLoginMessage : MessageBase;
public record DalamudLogoutMessage : MessageBase; public record DalamudLogoutMessage : MessageBase;
public record FrameworkUpdateMessage : SameThreadMessage; public record FrameworkUpdateMessage : SameThreadMessage;

View File

@@ -38,20 +38,20 @@ public class CompactUi : WindowMediatorSubscriberBase
private readonly PairManager _pairManager; private readonly PairManager _pairManager;
private readonly SelectTagForPairUi _selectGroupForPairUi; private readonly SelectTagForPairUi _selectGroupForPairUi;
private readonly SelectPairForTagUi _selectPairsForGroupUi; private readonly SelectPairForTagUi _selectPairsForGroupUi;
private readonly TopTabMenu _tabMenu;
private readonly ServerConfigurationManager _serverManager; private readonly ServerConfigurationManager _serverManager;
private readonly TagHandler _tagHandler; private readonly TagHandler _tagHandler;
private readonly UiSharedService _uiShared; private readonly UiSharedService _uiShared;
private string _characterOrCommentFilter = string.Empty;
private List<IDrawFolder> _drawFolders; private List<IDrawFolder> _drawFolders;
private Pair? _lastAddedUser; private Pair? _lastAddedUser;
private string _lastAddedUserComment = string.Empty; private string _lastAddedUserComment = string.Empty;
private Vector2 _lastPosition = Vector2.One; private Vector2 _lastPosition = Vector2.One;
private Vector2 _lastSize = Vector2.One; private Vector2 _lastSize = Vector2.One;
private string _pairToAdd = string.Empty;
private int _secretKeyIdx = -1; private int _secretKeyIdx = -1;
private bool _showModalForUserAddition; private bool _showModalForUserAddition;
private bool _wasOpen; private bool _wasOpen;
public CompactUi(ILogger<CompactUi> logger, UiSharedService uiShared, MareConfigService configService, ApiController apiController, PairManager pairManager, public CompactUi(ILogger<CompactUi> logger, UiSharedService uiShared, MareConfigService configService, ApiController apiController, PairManager pairManager,
ServerConfigurationManager serverManager, MareMediator mediator, FileUploadManager fileTransferManager, ServerConfigurationManager serverManager, MareMediator mediator, FileUploadManager fileTransferManager,
TagHandler tagHandler, DrawEntityFactory drawEntityFactory, SelectTagForPairUi selectTagForPairUi, SelectPairForTagUi selectPairForTagUi) TagHandler tagHandler, DrawEntityFactory drawEntityFactory, SelectTagForPairUi selectTagForPairUi, SelectPairForTagUi selectPairForTagUi)
@@ -67,6 +67,7 @@ public class CompactUi : WindowMediatorSubscriberBase
_drawEntityFactory = drawEntityFactory; _drawEntityFactory = drawEntityFactory;
_selectGroupForPairUi = selectTagForPairUi; _selectGroupForPairUi = selectTagForPairUi;
_selectPairsForGroupUi = selectPairForTagUi; _selectPairsForGroupUi = selectPairForTagUi;
_tabMenu = new TopTabMenu(Mediator, _apiController, _pairManager);
_drawFolders = GetDrawFolders().ToList(); _drawFolders = GetDrawFolders().ToList();
@@ -121,11 +122,12 @@ public class CompactUi : WindowMediatorSubscriberBase
if (_apiController.ServerState is ServerState.Connected) if (_apiController.ServerState is ServerState.Connected)
{ {
UiSharedService.DrawWithID("global-topmenu", () => _tabMenu.Draw());
UiSharedService.DrawWithID("pairlist", DrawPairList); UiSharedService.DrawWithID("pairlist", DrawPairList);
ImGui.Separator(); ImGui.Separator();
UiSharedService.DrawWithID("transfers", DrawTransfers); UiSharedService.DrawWithID("transfers", DrawTransfers);
TransferPartHeight = ImGui.GetCursorPosY() - TransferPartHeight; TransferPartHeight = ImGui.GetCursorPosY() - TransferPartHeight - ImGui.GetTextLineHeight();
UiSharedService.DrawWithID("group-user-popup", () => _selectPairsForGroupUi.Draw(_pairManager.DirectPairs)); UiSharedService.DrawWithID("group-user-popup", () => _selectPairsForGroupUi.Draw(_pairManager.DirectPairs));
UiSharedService.DrawWithID("grouping-popup", () => _selectGroupForPairUi.Draw()); UiSharedService.DrawWithID("grouping-popup", () => _selectGroupForPairUi.Draw());
} }
@@ -171,6 +173,28 @@ public class CompactUi : WindowMediatorSubscriberBase
} }
} }
private void DrawPairList()
{
UiSharedService.DrawWithID("pairs", DrawPairs);
TransferPartHeight = ImGui.GetCursorPosY();
}
private void DrawPairs()
{
var ySize = TransferPartHeight == 0
? 1
: (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - TransferPartHeight - ImGui.GetCursorPosY();
ImGui.BeginChild("list", new Vector2(WindowContentWidth, ySize), border: false);
foreach (var item in _drawFolders)
{
item.Draw();
}
ImGui.EndChild();
}
private void DrawAddCharacter() private void DrawAddCharacter()
{ {
ImGui.Dummy(new(10)); ImGui.Dummy(new(10));
@@ -200,93 +224,6 @@ public class CompactUi : WindowMediatorSubscriberBase
} }
} }
private void DrawAddPair()
{
var buttonSize = UiSharedService.GetIconButtonSize(FontAwesomeIcon.UserPlus);
var usersButtonSize = UiSharedService.GetIconButtonSize(FontAwesomeIcon.Users);
ImGui.SetNextItemWidth(UiSharedService.GetWindowContentRegionWidth() - ImGui.GetWindowContentRegionMin().X - buttonSize.X - ImGui.GetStyle().ItemSpacing.X - usersButtonSize.X);
ImGui.InputTextWithHint("##otheruid", "Other players UID/Alias", ref _pairToAdd, 20);
ImGui.SameLine();
var alreadyExisting = _pairManager.DirectPairs.Exists(p => string.Equals(p.UserData.UID, _pairToAdd, StringComparison.Ordinal) || string.Equals(p.UserData.Alias, _pairToAdd, StringComparison.Ordinal));
using (ImRaii.Disabled(alreadyExisting || string.IsNullOrEmpty(_pairToAdd)))
{
if (ImGuiComponents.IconButton(FontAwesomeIcon.UserPlus))
{
_ = _apiController.UserAddPair(new(new(_pairToAdd)));
_pairToAdd = string.Empty;
}
UiSharedService.AttachToolTip("Pair with " + (_pairToAdd.IsNullOrEmpty() ? "other user" : _pairToAdd));
}
ImGui.SameLine();
if (ImGuiComponents.IconButton(FontAwesomeIcon.Users))
{
ImGui.OpenPopup("Syncshell Menu");
}
UiSharedService.AttachToolTip("Syncshell Menu");
if (ImGui.BeginPopup("Syncshell Menu"))
{
using (ImRaii.Disabled(_pairManager.GroupPairs.Select(k => k.Key).Distinct()
.Count(g => string.Equals(g.OwnerUID, _apiController.UID, StringComparison.Ordinal)) >= _apiController.ServerInfo.MaxGroupsCreatedByUser))
{
if (UiSharedService.IconTextButton(FontAwesomeIcon.Plus, "Create new Syncshell", _syncshellMenuSize, true))
{
Mediator.Publish(new UiToggleMessage(typeof(CreateSyncshellUI)));
ImGui.CloseCurrentPopup();
}
}
using (ImRaii.Disabled(_pairManager.GroupPairs.Select(k => k.Key).Distinct().Count() >= _apiController.ServerInfo.MaxGroupsJoinedByUser))
{
if (UiSharedService.IconTextButton(FontAwesomeIcon.Users, "Join existing Syncshell", _syncshellMenuSize, true))
{
Mediator.Publish(new UiToggleMessage(typeof(JoinSyncshellUI)));
ImGui.CloseCurrentPopup();
}
}
_syncshellMenuSize = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
ImGui.EndPopup();
}
ImGuiHelpers.ScaledDummy(2);
}
private float _syncshellMenuSize = 0;
private void DrawFilter()
{
ImGui.SetNextItemWidth(WindowContentWidth);
if (ImGui.InputTextWithHint("##filter", "Filter for UID/notes", ref _characterOrCommentFilter, 255))
{
Mediator.Publish(new RefreshUiMessage());
}
}
private void DrawPairList()
{
UiSharedService.DrawWithID("addpair", DrawAddPair);
UiSharedService.DrawWithID("pairs", DrawPairs);
TransferPartHeight = ImGui.GetCursorPosY();
UiSharedService.DrawWithID("filter", DrawFilter);
}
private void DrawPairs()
{
var ySize = TransferPartHeight == 0
? 1
: (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - TransferPartHeight - ImGui.GetCursorPosY();
ImGui.BeginChild("list", new Vector2(WindowContentWidth, ySize), border: false);
foreach (var item in _drawFolders)
{
item.Draw();
}
ImGui.EndChild();
}
private void DrawServerStatus() private void DrawServerStatus()
{ {
var buttonSize = UiSharedService.GetIconButtonSize(FontAwesomeIcon.Link); var buttonSize = UiSharedService.GetIconButtonSize(FontAwesomeIcon.Link);
@@ -331,16 +268,6 @@ public class CompactUi : WindowMediatorSubscriberBase
var color = UiSharedService.GetBoolColor(!_serverManager.CurrentServer!.FullPause); var color = UiSharedService.GetBoolColor(!_serverManager.CurrentServer!.FullPause);
var connectedIcon = !_serverManager.CurrentServer.FullPause ? FontAwesomeIcon.Link : FontAwesomeIcon.Unlink; var connectedIcon = !_serverManager.CurrentServer.FullPause ? FontAwesomeIcon.Link : FontAwesomeIcon.Unlink;
if (_apiController.ServerState is ServerState.Connected)
{
ImGui.SetCursorPosX(0 + ImGui.GetStyle().ItemSpacing.X);
if (ImGuiComponents.IconButton(FontAwesomeIcon.UserCircle))
{
Mediator.Publish(new UiToggleMessage(typeof(EditProfileUi)));
}
UiSharedService.AttachToolTip("Edit your Mare Profile");
}
ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - buttonSize.X); ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - buttonSize.X);
if (printShard) if (printShard)
{ {
@@ -412,13 +339,6 @@ public class CompactUi : WindowMediatorSubscriberBase
{ {
ImGui.TextUnformatted("No downloads in progress"); ImGui.TextUnformatted("No downloads in progress");
} }
if (UiSharedService.IconTextButton(FontAwesomeIcon.PersonCircleQuestion, "Mare Character Data Analysis", WindowContentWidth))
{
Mediator.Publish(new OpenDataAnalysisUiMessage());
}
ImGui.SameLine();
} }
private void DrawUIDHeader() private void DrawUIDHeader()
@@ -495,7 +415,7 @@ public class CompactUi : WindowMediatorSubscriberBase
} }
List<IDrawFolder> groupFolders = new(); List<IDrawFolder> groupFolders = new();
foreach (var group in _pairManager.GroupPairs.Select(g => g.Key).OrderBy(g => g.GroupAliasOrGID, StringComparer.Ordinal)) foreach (var group in _pairManager.GroupPairs.Select(g => g.Key).OrderBy(g => g.GroupAliasOrGID, StringComparer.OrdinalIgnoreCase))
{ {
var groupUsers2 = users.Where(v => v.Value.Exists(g => string.Equals(g.GID, group.GID, StringComparison.Ordinal)) var groupUsers2 = users.Where(v => v.Value.Exists(g => string.Equals(g.GID, group.GID, StringComparison.Ordinal))
&& (v.Key.IsOnline || (!v.Key.IsOnline && !_configService.Current.ShowOfflineUsersSeparately) && (v.Key.IsOnline || (!v.Key.IsOnline && !_configService.Current.ShowOfflineUsersSeparately)
@@ -514,7 +434,7 @@ public class CompactUi : WindowMediatorSubscriberBase
.ThenBy( .ThenBy(
u => _configService.Current.ShowCharacterNameInsteadOfNotesForVisible && !string.IsNullOrEmpty(u.Key.PlayerName) u => _configService.Current.ShowCharacterNameInsteadOfNotesForVisible && !string.IsNullOrEmpty(u.Key.PlayerName)
? (_configService.Current.PreferNotesOverNamesForVisible ? u.Key.GetNote() : u.Key.PlayerName) ? (_configService.Current.PreferNotesOverNamesForVisible ? u.Key.GetNote() : u.Key.PlayerName)
: (u.Key.GetNote() ?? u.Key.UserData.AliasOrUID), StringComparer.Ordinal) : (u.Key.GetNote() ?? u.Key.UserData.AliasOrUID), StringComparer.OrdinalIgnoreCase)
.ToDictionary(k => k.Key, k => k.Value); .ToDictionary(k => k.Key, k => k.Value);
groupFolders.Add(_drawEntityFactory.CreateDrawGroupFolder(group, groupUsers2, groupFolders.Add(_drawEntityFactory.CreateDrawGroupFolder(group, groupUsers2,
@@ -590,14 +510,14 @@ public class CompactUi : WindowMediatorSubscriberBase
private Dictionary<Pair, List<GroupFullInfoDto>> GetFilteredGroupUsers() private Dictionary<Pair, List<GroupFullInfoDto>> GetFilteredGroupUsers()
{ {
if (string.IsNullOrEmpty(_characterOrCommentFilter)) return _pairManager.PairsWithGroups; if (string.IsNullOrEmpty(_tabMenu.Filter)) return _pairManager.PairsWithGroups;
return _pairManager.PairsWithGroups.Where(p => return _pairManager.PairsWithGroups.Where(p =>
{ {
if (_characterOrCommentFilter.IsNullOrEmpty()) return true; if (_tabMenu.Filter.IsNullOrEmpty()) return true;
return p.Key.UserData.AliasOrUID.Contains(_characterOrCommentFilter, StringComparison.OrdinalIgnoreCase) || return p.Key.UserData.AliasOrUID.Contains(_tabMenu.Filter, StringComparison.OrdinalIgnoreCase) ||
(p.Key.GetNote()?.Contains(_characterOrCommentFilter, StringComparison.OrdinalIgnoreCase) ?? false) || (p.Key.GetNote()?.Contains(_tabMenu.Filter, StringComparison.OrdinalIgnoreCase) ?? false) ||
(p.Key.PlayerName?.Contains(_characterOrCommentFilter, StringComparison.OrdinalIgnoreCase) ?? false); (p.Key.PlayerName?.Contains(_tabMenu.Filter, StringComparison.OrdinalIgnoreCase) ?? false);
}).ToDictionary(k => k.Key, k => k.Value); }).ToDictionary(k => k.Key, k => k.Value);
} }

View File

@@ -164,21 +164,25 @@ public class DrawFolderTag : DrawFolderBase
private void PauseRemainingPairs(IEnumerable<DrawUserPair> availablePairs) private void PauseRemainingPairs(IEnumerable<DrawUserPair> availablePairs)
{ {
foreach (var pairToPause in availablePairs.Where(pair => !pair.UserPair!.OwnPermissions.IsPaused())) _ = _apiController.SetBulkPermissions(new(availablePairs
.ToDictionary(g => g.UID, g =>
{ {
var perm = pairToPause.UserPair!.OwnPermissions; var perm = g.UserPair.OwnPermissions;
perm.SetPaused(paused: true); perm.SetPaused(paused: true);
_ = _apiController.UserSetPairPermissions(new(new(pairToPause.UID), perm)); return perm;
} }, StringComparer.Ordinal), new(StringComparer.Ordinal)))
.ConfigureAwait(false);
} }
private void ResumeAllPairs(IEnumerable<DrawUserPair> availablePairs) private void ResumeAllPairs(IEnumerable<DrawUserPair> availablePairs)
{ {
foreach (var pairToPause in availablePairs) _ = _apiController.SetBulkPermissions(new(availablePairs
{ .ToDictionary(g => g.UID, g =>
var perm = pairToPause.UserPair!.OwnPermissions; {
perm.SetPaused(paused: false); var perm = g.UserPair.OwnPermissions;
_ = _apiController.UserSetPairPermissions(new(new(pairToPause.UID), perm)); perm.SetPaused(paused: false);
} return perm;
}, StringComparer.Ordinal), new(StringComparer.Ordinal)))
.ConfigureAwait(false);
} }
} }

View File

@@ -39,7 +39,6 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
{ {
_hasUpdate = true; _hasUpdate = true;
}); });
Mediator.Subscribe<OpenDataAnalysisUiMessage>(this, (_) => Toggle());
SizeConstraints = new() SizeConstraints = new()
{ {
MinimumSize = new() MinimumSize = new()

View File

@@ -70,7 +70,7 @@ internal class JoinSyncshellUI : WindowMediatorSubscriberBase
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted("Syncshell Password"); ImGui.TextUnformatted("Syncshell Password");
ImGui.SameLine(200); ImGui.SameLine(200);
ImGui.InputTextWithHint("##syncshellpw", "Password", ref _syncshellPassword, 20, ImGuiInputTextFlags.Password); ImGui.InputTextWithHint("##syncshellpw", "Password", ref _syncshellPassword, 50, ImGuiInputTextFlags.Password);
using (ImRaii.Disabled(string.IsNullOrEmpty(_desiredSyncshellToJoin) || string.IsNullOrEmpty(_syncshellPassword))) using (ImRaii.Disabled(string.IsNullOrEmpty(_desiredSyncshellToJoin) || string.IsNullOrEmpty(_syncshellPassword)))
{ {
if (UiSharedService.IconTextButton(Dalamud.Interface.FontAwesomeIcon.Plus, "Join Syncshell")) if (UiSharedService.IconTextButton(Dalamud.Interface.FontAwesomeIcon.Plus, "Join Syncshell"))

View File

@@ -0,0 +1,557 @@
using Dalamud.Interface;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Utility;
using ImGuiNET;
using MareSynchronos.API.Data.Enum;
using MareSynchronos.API.Data.Extensions;
using MareSynchronos.PlayerData.Pairs;
using MareSynchronos.Services.Mediator;
using MareSynchronos.WebAPI;
using System.Numerics;
namespace MareSynchronos.UI;
public class TopTabMenu
{
private readonly ApiController _apiController;
private readonly MareMediator _mareMediator;
private readonly PairManager _pairManager;
private int _globalControlCountdown = 0;
private string _pairToAdd = string.Empty;
private SelectedTab _selectedTab = SelectedTab.None;
public TopTabMenu(MareMediator mareMediator, ApiController apiController, PairManager pairManager)
{
_mareMediator = mareMediator;
_apiController = apiController;
_pairManager = pairManager;
}
private enum SelectedTab
{
None,
Individual,
Syncshell,
Filter,
UserConfig
}
public string Filter { get; private set; } = string.Empty;
public void Draw()
{
var availableWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
var spacing = ImGui.GetStyle().ItemSpacing;
var buttonX = (availableWidth - (spacing.X * 3)) / 4f;
var buttonY = UiSharedService.GetIconButtonSize(FontAwesomeIcon.Pause).Y;
var buttonSize = new Vector2(buttonX, buttonY);
var drawList = ImGui.GetWindowDrawList();
var underlineColor = ImGui.GetColorU32(ImGuiCol.Separator);
var btncolor = ImRaii.PushColor(ImGuiCol.Button, ImGui.ColorConvertFloat4ToU32(new(0, 0, 0, 0)));
ImGuiHelpers.ScaledDummy(spacing.Y / 2f);
using (ImRaii.PushFont(UiBuilder.IconFont))
{
var x = ImGui.GetCursorScreenPos();
if (ImGui.Button(FontAwesomeIcon.User.ToIconString(), buttonSize))
{
_selectedTab = _selectedTab == SelectedTab.Individual ? SelectedTab.None : SelectedTab.Individual;
}
ImGui.SameLine();
var xAfter = ImGui.GetCursorScreenPos();
if (_selectedTab == SelectedTab.Individual)
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
underlineColor, 2);
}
UiSharedService.AttachToolTip("Individual Pair Menu");
using (ImRaii.PushFont(UiBuilder.IconFont))
{
var x = ImGui.GetCursorScreenPos();
if (ImGui.Button(FontAwesomeIcon.Users.ToIconString(), buttonSize))
{
_selectedTab = _selectedTab == SelectedTab.Syncshell ? SelectedTab.None : SelectedTab.Syncshell;
}
ImGui.SameLine();
var xAfter = ImGui.GetCursorScreenPos();
if (_selectedTab == SelectedTab.Syncshell)
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
underlineColor, 2);
}
UiSharedService.AttachToolTip("Syncshell Menu");
ImGui.SameLine();
using (ImRaii.PushFont(UiBuilder.IconFont))
{
var x = ImGui.GetCursorScreenPos();
if (ImGui.Button(FontAwesomeIcon.Filter.ToIconString(), buttonSize))
{
_selectedTab = _selectedTab == SelectedTab.Filter ? SelectedTab.None : SelectedTab.Filter;
}
ImGui.SameLine();
var xAfter = ImGui.GetCursorScreenPos();
if (_selectedTab == SelectedTab.Filter)
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
underlineColor, 2);
}
UiSharedService.AttachToolTip("Filter");
ImGui.SameLine();
using (ImRaii.PushFont(UiBuilder.IconFont))
{
var x = ImGui.GetCursorScreenPos();
if (ImGui.Button(FontAwesomeIcon.UserCog.ToIconString(), buttonSize))
{
_selectedTab = _selectedTab == SelectedTab.UserConfig ? SelectedTab.None : SelectedTab.UserConfig;
}
ImGui.SameLine();
var xAfter = ImGui.GetCursorScreenPos();
if (_selectedTab == SelectedTab.UserConfig)
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y },
xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
underlineColor, 2);
}
UiSharedService.AttachToolTip("Your User Menu");
ImGui.NewLine();
btncolor.Dispose();
ImGuiHelpers.ScaledDummy(spacing);
if (_selectedTab == SelectedTab.Individual)
{
DrawAddPair(availableWidth, spacing.X);
DrawGlobalIndividualButtons(availableWidth, spacing.X);
}
else if (_selectedTab == SelectedTab.Syncshell)
{
DrawSyncshellMenu(availableWidth, spacing.X);
DrawGlobalSyncshellButtons(availableWidth, spacing.X);
}
else if (_selectedTab == SelectedTab.Filter)
{
DrawFilter(availableWidth);
}
else if (_selectedTab == SelectedTab.UserConfig)
{
DrawUserConfig(availableWidth, spacing.X);
}
if (_selectedTab != SelectedTab.None) ImGuiHelpers.ScaledDummy(3f);
ImGui.Separator();
ImGuiHelpers.ScaledDummy(1f);
}
private void DrawAddPair(float availableXWidth, float spacingX)
{
var buttonSize = UiSharedService.GetIconTextButtonSize(FontAwesomeIcon.UserPlus, "Add");
ImGui.SetNextItemWidth(availableXWidth - buttonSize.X - spacingX);
ImGui.InputTextWithHint("##otheruid", "Other players UID/Alias", ref _pairToAdd, 20);
ImGui.SameLine();
var alreadyExisting = _pairManager.DirectPairs.Exists(p => string.Equals(p.UserData.UID, _pairToAdd, StringComparison.Ordinal) || string.Equals(p.UserData.Alias, _pairToAdd, StringComparison.Ordinal));
using (ImRaii.Disabled(alreadyExisting || string.IsNullOrEmpty(_pairToAdd)))
{
if (UiSharedService.IconTextButton(FontAwesomeIcon.UserPlus, "Add"))
{
_ = _apiController.UserAddPair(new(new(_pairToAdd)));
_pairToAdd = string.Empty;
}
}
UiSharedService.AttachToolTip("Pair with " + (_pairToAdd.IsNullOrEmpty() ? "other user" : _pairToAdd));
}
private void DrawFilter(float availableWidth)
{
ImGui.SetNextItemWidth(availableWidth);
string filter = Filter;
if (ImGui.InputTextWithHint("##filter", "Filter for UID/notes", ref filter, 255))
{
Filter = filter;
_mareMediator.Publish(new RefreshUiMessage());
}
}
private void DrawGlobalIndividualButtons(float availableXWidth, float spacingX)
{
var buttonX = (availableXWidth - (spacingX * 3)) / 4f;
var buttonY = UiSharedService.GetIconButtonSize(FontAwesomeIcon.Pause).Y;
var buttonSize = new Vector2(buttonX, buttonY);
using (ImRaii.PushFont(UiBuilder.IconFont))
{
using var disabled = ImRaii.Disabled(_globalControlCountdown > 0);
if (ImGui.Button(FontAwesomeIcon.Pause.ToIconString(), buttonSize))
{
ImGui.OpenPopup("Individual Pause");
}
}
UiSharedService.AttachToolTip("Globally resume or pause all individual pairs." + UiSharedService.TooltipSeparator
+ (_globalControlCountdown > 0 ? UiSharedService.TooltipSeparator + "Available again in " + _globalControlCountdown + " seconds." : string.Empty));
ImGui.SameLine();
using (ImRaii.PushFont(UiBuilder.IconFont))
{
using var disabled = ImRaii.Disabled(_globalControlCountdown > 0);
if (ImGui.Button(FontAwesomeIcon.VolumeUp.ToIconString(), buttonSize))
{
ImGui.OpenPopup("Individual Sounds");
}
}
UiSharedService.AttachToolTip("Globally enable or disable sound sync with all individual pairs."
+ (_globalControlCountdown > 0 ? UiSharedService.TooltipSeparator + "Available again in " + _globalControlCountdown + " seconds." : string.Empty));
ImGui.SameLine();
using (ImRaii.PushFont(UiBuilder.IconFont))
{
using var disabled = ImRaii.Disabled(_globalControlCountdown > 0);
if (ImGui.Button(FontAwesomeIcon.Running.ToIconString(), buttonSize))
{
ImGui.OpenPopup("Individual Animations");
}
}
UiSharedService.AttachToolTip("Globally enable or disable animation sync with all individual pairs." + UiSharedService.TooltipSeparator
+ (_globalControlCountdown > 0 ? UiSharedService.TooltipSeparator + "Available again in " + _globalControlCountdown + " seconds." : string.Empty));
ImGui.SameLine();
using (ImRaii.PushFont(UiBuilder.IconFont))
{
using var disabled = ImRaii.Disabled(_globalControlCountdown > 0);
if (ImGui.Button(FontAwesomeIcon.Sun.ToIconString(), buttonSize))
{
ImGui.OpenPopup("Individual VFX");
}
}
UiSharedService.AttachToolTip("Globally enable or disable VFX sync with all individual pairs." + UiSharedService.TooltipSeparator
+ (_globalControlCountdown > 0 ? UiSharedService.TooltipSeparator + "Available again in " + _globalControlCountdown + " seconds." : string.Empty));
PopupIndividualSetting("Individual Pause", "Unpause all individuals", "Pause all individuals",
FontAwesomeIcon.Play, FontAwesomeIcon.Pause,
(perm) =>
{
perm.SetPaused(false);
return perm;
},
(perm) =>
{
perm.SetPaused(true);
return perm;
});
PopupIndividualSetting("Individual Sounds", "Enable sounds for all individuals", "Disable sounds for all individuals",
FontAwesomeIcon.VolumeUp, FontAwesomeIcon.VolumeMute,
(perm) =>
{
perm.SetDisableSounds(false);
return perm;
},
(perm) =>
{
perm.SetDisableSounds(true);
return perm;
});
PopupIndividualSetting("Individual Animations", "Enable sounds for all individuals", "Disable sounds for all individuals",
FontAwesomeIcon.Running, FontAwesomeIcon.Stop,
(perm) =>
{
perm.SetDisableAnimations(false);
return perm;
},
(perm) =>
{
perm.SetDisableAnimations(true);
return perm;
});
PopupIndividualSetting("Individual VFX", "Enable VFX for all individuals", "Disable VFX for all individuals",
FontAwesomeIcon.Sun, FontAwesomeIcon.Circle,
(perm) =>
{
perm.SetDisableVFX(false);
return perm;
},
(perm) =>
{
perm.SetDisableVFX(true);
return perm;
});
}
private void DrawGlobalSyncshellButtons(float availableXWidth, float spacingX)
{
var buttonX = (availableXWidth - (spacingX * 4)) / 5f;
var buttonY = UiSharedService.GetIconButtonSize(FontAwesomeIcon.Pause).Y;
var buttonSize = new Vector2(buttonX, buttonY);
using (ImRaii.PushFont(UiBuilder.IconFont))
{
using var disabled = ImRaii.Disabled(_globalControlCountdown > 0);
if (ImGui.Button(FontAwesomeIcon.Pause.ToIconString(), buttonSize))
{
ImGui.OpenPopup("Syncshell Pause");
}
}
UiSharedService.AttachToolTip("Globally resume or pause all syncshells." + UiSharedService.TooltipSeparator
+ "Note: This will not affect users with preferred permissions in syncshells."
+ (_globalControlCountdown > 0 ? UiSharedService.TooltipSeparator + "Available again in " + _globalControlCountdown + " seconds." : string.Empty));
ImGui.SameLine();
using (ImRaii.PushFont(UiBuilder.IconFont))
{
using var disabled = ImRaii.Disabled(_globalControlCountdown > 0);
if (ImGui.Button(FontAwesomeIcon.VolumeUp.ToIconString(), buttonSize))
{
ImGui.OpenPopup("Syncshell Sounds");
}
}
UiSharedService.AttachToolTip("Globally enable or disable sound sync with all syncshells." + UiSharedService.TooltipSeparator
+ "Note: This will not affect users with preferred permissions in syncshells."
+ (_globalControlCountdown > 0 ? UiSharedService.TooltipSeparator + "Available again in " + _globalControlCountdown + " seconds." : string.Empty));
ImGui.SameLine();
using (ImRaii.PushFont(UiBuilder.IconFont))
{
using var disabled = ImRaii.Disabled(_globalControlCountdown > 0);
if (ImGui.Button(FontAwesomeIcon.Running.ToIconString(), buttonSize))
{
ImGui.OpenPopup("Syncshell Animations");
}
}
UiSharedService.AttachToolTip("Globally enable or disable animation sync with all syncshells." + UiSharedService.TooltipSeparator
+ "Note: This will not affect users with preferred permissions in syncshells."
+ (_globalControlCountdown > 0 ? UiSharedService.TooltipSeparator + "Available again in " + _globalControlCountdown + " seconds." : string.Empty));
ImGui.SameLine();
using (ImRaii.PushFont(UiBuilder.IconFont))
{
using var disabled = ImRaii.Disabled(_globalControlCountdown > 0);
if (ImGui.Button(FontAwesomeIcon.Sun.ToIconString(), buttonSize))
{
ImGui.OpenPopup("Syncshell VFX");
}
}
UiSharedService.AttachToolTip("Globally enable or disable VFX sync with all syncshells." + UiSharedService.TooltipSeparator
+ "Note: This will not affect users with preferred permissions in syncshells."
+ (_globalControlCountdown > 0 ? UiSharedService.TooltipSeparator + "Available again in " + _globalControlCountdown + " seconds." : string.Empty));
PopupSyncshellSetting("Syncshell Pause", "Unpause all syncshells", "Pause all syncshells",
FontAwesomeIcon.Play, FontAwesomeIcon.Pause,
(perm) =>
{
perm.SetPaused(false);
return perm;
},
(perm) =>
{
perm.SetPaused(true);
return perm;
});
PopupSyncshellSetting("Syncshell Sounds", "Enable sounds for all syncshells", "Disable sounds for all syncshells",
FontAwesomeIcon.VolumeUp, FontAwesomeIcon.VolumeMute,
(perm) =>
{
perm.SetDisableSounds(false);
return perm;
},
(perm) =>
{
perm.SetDisableSounds(true);
return perm;
});
PopupSyncshellSetting("Syncshell Animations", "Enable sounds for all syncshells", "Disable sounds for all syncshells",
FontAwesomeIcon.Running, FontAwesomeIcon.Stop,
(perm) =>
{
perm.SetDisableAnimations(false);
return perm;
},
(perm) =>
{
perm.SetDisableAnimations(true);
return perm;
});
PopupSyncshellSetting("Syncshell VFX", "Enable VFX for all syncshells", "Disable VFX for all syncshells",
FontAwesomeIcon.Sun, FontAwesomeIcon.Circle,
(perm) =>
{
perm.SetDisableVFX(false);
return perm;
},
(perm) =>
{
perm.SetDisableVFX(true);
return perm;
});
ImGui.SameLine();
using (ImRaii.PushFont(UiBuilder.IconFont))
{
using var disabled = ImRaii.Disabled(_globalControlCountdown > 0);
if (ImGui.Button(FontAwesomeIcon.Check.ToIconString(), buttonSize))
{
_ = GlobalControlCountdown(10);
var bulkSyncshells = _pairManager.GroupPairs.Keys.OrderBy(g => g.GroupAliasOrGID, StringComparer.OrdinalIgnoreCase)
.ToDictionary(g => g.Group.GID, g =>
{
var perm = g.GroupUserPermissions;
perm.SetDisableSounds(g.GroupPermissions.IsPreferDisableSounds());
perm.SetDisableAnimations(g.GroupPermissions.IsPreferDisableAnimations());
perm.SetDisableVFX(g.GroupPermissions.IsPreferDisableVFX());
return perm;
}, StringComparer.Ordinal);
_ = _apiController.SetBulkPermissions(new(new(StringComparer.Ordinal), bulkSyncshells)).ConfigureAwait(false);
}
}
UiSharedService.AttachToolTip("Globally align syncshell permissions to suggested syncshell permissions." + UiSharedService.TooltipSeparator
+ "Note: This will not affect users with preferred permissions in syncshells." + Environment.NewLine
+ "Note: If multiple users share one syncshell the permissions to that user will be set to " + Environment.NewLine
+ "the ones of the last applied syncshell in alphabetical order."
+ (_globalControlCountdown > 0 ? UiSharedService.TooltipSeparator + "Available again in " + _globalControlCountdown + " seconds." : string.Empty));
}
private void DrawSyncshellMenu(float availableWidth, float spacingX)
{
var buttonX = (availableWidth - (spacingX)) / 2f;
using (ImRaii.Disabled(_pairManager.GroupPairs.Select(k => k.Key).Distinct()
.Count(g => string.Equals(g.OwnerUID, _apiController.UID, StringComparison.Ordinal)) >= _apiController.ServerInfo.MaxGroupsCreatedByUser))
{
if (UiSharedService.IconTextButton(FontAwesomeIcon.Plus, "Create new Syncshell", buttonX))
{
_mareMediator.Publish(new UiToggleMessage(typeof(CreateSyncshellUI)));
}
ImGui.SameLine();
}
using (ImRaii.Disabled(_pairManager.GroupPairs.Select(k => k.Key).Distinct().Count() >= _apiController.ServerInfo.MaxGroupsJoinedByUser))
{
if (UiSharedService.IconTextButton(FontAwesomeIcon.Users, "Join existing Syncshell", buttonX))
{
_mareMediator.Publish(new UiToggleMessage(typeof(JoinSyncshellUI)));
}
}
}
private void DrawUserConfig(float availableWidth, float spacingX)
{
var buttonX = (availableWidth - spacingX) / 2f;
if (UiSharedService.IconTextButton(FontAwesomeIcon.UserCircle, "Edit Mare Profile", buttonX))
{
_mareMediator.Publish(new UiToggleMessage(typeof(EditProfileUi)));
}
UiSharedService.AttachToolTip("Edit your Mare Profile");
ImGui.SameLine();
if (UiSharedService.IconTextButton(FontAwesomeIcon.PersonCircleQuestion, "Chara Data Analysis", buttonX))
{
_mareMediator.Publish(new UiToggleMessage(typeof(DataAnalysisUi)));
}
UiSharedService.AttachToolTip("View and analyze your generated character data");
}
private async Task GlobalControlCountdown(int countdown)
{
#if DEBUG
return;
#endif
_globalControlCountdown = countdown;
while (_globalControlCountdown > 0)
{
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
_globalControlCountdown--;
}
}
private void PopupIndividualSetting(string popupTitle, string enableText, string disableText,
FontAwesomeIcon enableIcon, FontAwesomeIcon disableIcon,
Func<UserPermissions, UserPermissions> actEnable, Func<UserPermissions, UserPermissions> actDisable)
{
if (ImGui.BeginPopup(popupTitle))
{
if (UiSharedService.IconTextButton(enableIcon, enableText, 0, true))
{
_ = GlobalControlCountdown(10);
var bulkIndividualPairs = _pairManager.PairsWithGroups.Keys
.Where(g => g.IndividualPairStatus == API.Data.Enum.IndividualPairStatus.Bidirectional)
.ToDictionary(g => g.UserPair.User.UID, g =>
{
return actEnable(g.UserPair.OwnPermissions);
}, StringComparer.Ordinal);
_ = _apiController.SetBulkPermissions(new(bulkIndividualPairs, new(StringComparer.Ordinal))).ConfigureAwait(false);
ImGui.CloseCurrentPopup();
}
if (UiSharedService.IconTextButton(disableIcon, disableText, 0, true))
{
_ = GlobalControlCountdown(10);
var bulkIndividualPairs = _pairManager.PairsWithGroups.Keys
.Where(g => g.IndividualPairStatus == API.Data.Enum.IndividualPairStatus.Bidirectional)
.ToDictionary(g => g.UserPair.User.UID, g =>
{
return actDisable(g.UserPair.OwnPermissions);
}, StringComparer.Ordinal);
_ = _apiController.SetBulkPermissions(new(bulkIndividualPairs, new(StringComparer.Ordinal))).ConfigureAwait(false);
ImGui.CloseCurrentPopup();
}
ImGui.EndPopup();
}
}
private void PopupSyncshellSetting(string popupTitle, string enableText, string disableText,
FontAwesomeIcon enableIcon, FontAwesomeIcon disableIcon,
Func<GroupUserPreferredPermissions, GroupUserPreferredPermissions> actEnable,
Func<GroupUserPreferredPermissions, GroupUserPreferredPermissions> actDisable)
{
if (ImGui.BeginPopup(popupTitle))
{
if (UiSharedService.IconTextButton(enableIcon, enableText, 0, true))
{
_ = GlobalControlCountdown(10);
var bulkSyncshells = _pairManager.GroupPairs.Keys
.ToDictionary(g => g.Group.GID, g =>
{
return actEnable(g.GroupUserPermissions);
}, StringComparer.Ordinal);
_ = _apiController.SetBulkPermissions(new(new(StringComparer.Ordinal), bulkSyncshells)).ConfigureAwait(false);
ImGui.CloseCurrentPopup();
}
if (UiSharedService.IconTextButton(disableIcon, disableText, 0, true))
{
_ = GlobalControlCountdown(10);
var bulkSyncshells = _pairManager.GroupPairs.Keys
.ToDictionary(g => g.Group.GID, g =>
{
return actDisable(g.GroupUserPermissions);
}, StringComparer.Ordinal);
_ = _apiController.SetBulkPermissions(new(new(StringComparer.Ordinal), bulkSyncshells)).ConfigureAwait(false);
ImGui.CloseCurrentPopup();
}
ImGui.EndPopup();
}
}
}

View File

@@ -133,7 +133,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
public static void AttachToolTip(string text) public static void AttachToolTip(string text)
{ {
if (ImGui.IsItemHovered()) if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
{ {
ImGui.BeginTooltip(); ImGui.BeginTooltip();
if (text.Contains(TooltipSeparator, StringComparison.Ordinal)) if (text.Contains(TooltipSeparator, StringComparison.Ordinal))
@@ -349,6 +349,31 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
return ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X; return ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
} }
public static Vector2 GetIconTextButtonSize(FontAwesomeIcon icon, string text, float? width = null, bool isInPopup = false)
{
var iconSize = GetIconSize(icon);
var textSize = ImGui.CalcTextSize(text);
var padding = ImGui.GetStyle().FramePadding;
var spacing = ImGui.GetStyle().ItemSpacing;
var buttonSizeY = textSize.Y + padding.Y * 2;
var iconExtraSpacing = isInPopup ? padding.X * 2 : 0;
var iconXoffset = iconSize.X <= iconSize.Y ? (iconSize.Y - iconSize.X) / 2f : 0;
var iconScaling = iconSize.X > iconSize.Y ? 1 / (iconSize.X / iconSize.Y) : 1;
if (width == null || width <= 0)
{
var buttonSizeX = (iconScaling == 1 ? iconSize.Y : (iconSize.X * iconScaling))
+ textSize.X + padding.X * 2 + spacing.X + (iconXoffset * 2);
return new Vector2(buttonSizeX + iconExtraSpacing, buttonSizeY);
}
else
{
return new Vector2(width.Value, buttonSizeY);
}
}
public static bool IconTextButton(FontAwesomeIcon icon, string text, float? width = null, bool isInPopup = false) public static bool IconTextButton(FontAwesomeIcon icon, string text, float? width = null, bool isInPopup = false)
{ {
var wasClicked = false; var wasClicked = false;

View File

@@ -69,6 +69,20 @@ public partial class ApiController
} }
} }
public async Task SetBulkPermissions(BulkPermissionsDto dto)
{
CheckConnection();
try
{
await _mareHub!.InvokeAsync(nameof(SetBulkPermissions), dto).ConfigureAwait(false);
}
catch (Exception ex)
{
Logger.LogWarning(ex, "Failed to set permissions");
}
}
public async Task UserRemovePair(UserDto userDto) public async Task UserRemovePair(UserDto userDto)
{ {
if (!IsConnected) return; if (!IsConnected) return;
@@ -83,7 +97,10 @@ public partial class ApiController
public async Task UserSetPairPermissions(UserPermissionsDto userPermissions) public async Task UserSetPairPermissions(UserPermissionsDto userPermissions)
{ {
await _mareHub!.SendAsync(nameof(UserSetPairPermissions), userPermissions).ConfigureAwait(false); await SetBulkPermissions(new(new(StringComparer.Ordinal)
{
{ userPermissions.User.UID, userPermissions.Permissions }
}, new(StringComparer.Ordinal))).ConfigureAwait(false);
} }
public async Task UserSetProfile(UserProfileDto userDescription) public async Task UserSetProfile(UserProfileDto userDescription)

View File

@@ -21,7 +21,10 @@ public partial class ApiController
public async Task GroupChangeIndividualPermissionState(GroupPairUserPermissionDto dto) public async Task GroupChangeIndividualPermissionState(GroupPairUserPermissionDto dto)
{ {
CheckConnection(); CheckConnection();
await _mareHub!.SendAsync(nameof(GroupChangeIndividualPermissionState), dto).ConfigureAwait(false); await SetBulkPermissions(new(new(StringComparer.Ordinal),
new(StringComparer.Ordinal) {
{ dto.Group.GID, dto.GroupPairPermissions }
})).ConfigureAwait(false);
} }
public async Task GroupChangeOwnership(GroupPairDto groupPair) public async Task GroupChangeOwnership(GroupPairDto groupPair)