Several UI enhancements

+ Added paused user field to main UI
+ Excluded paused users from online list
+ Excluded visible users from online list
+ Fixed an issue where remotely paused users would always show offline
+ Ensured paused users returns true if EITHER client OR remote paused them.
+ Made paused users show as Grey
+ Changed paired icon from check to snowflake
+ Fixed a bug where clients would have icons for both paired AND visible simultaneously
+ Fixed a bug where clients would show both online AND visible unnecessarily.
+ Made paused users render just above offline users.
+ Changed default ui icon from SS to Snowflake/Flower thingy.
This commit is contained in:
2025-09-05 17:31:45 -04:00
parent 9a0f2c062c
commit 837b487281
6 changed files with 54 additions and 36 deletions

View File

@@ -362,13 +362,14 @@ public class CompactUi : WindowMediatorSubscriberBase
: (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - TransferPartHeight - ImGui.GetCursorPosY(); : (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - TransferPartHeight - ImGui.GetCursorPosY();
var users = GetFilteredUsers().OrderBy(u => u.GetPairSortKey(), StringComparer.Ordinal); var users = GetFilteredUsers().OrderBy(u => u.GetPairSortKey(), StringComparer.Ordinal);
var onlineUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.IsOnline || u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Online" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList(); var onlineUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.IsOnline && !u.IsVisible && (!u.UserPair!.OtherPermissions.IsPaused() && !u.UserPair!.OwnPermissions.IsPaused()))).Select(c => new DrawUserPair("Online" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
var pausedUsers = users.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.UserPair!.OtherPermissions.IsPaused() || u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Paused" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
var visibleUsers = users.Where(u => u.IsVisible).Select(c => new DrawUserPair("Visible" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList(); var visibleUsers = users.Where(u => u.IsVisible).Select(c => new DrawUserPair("Visible" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
var offlineUsers = users.Where(u => !u.UserPair!.OtherPermissions.IsPaired() || (!u.IsOnline && !u.UserPair!.OwnPermissions.IsPaused())).Select(c => new DrawUserPair("Offline" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList(); var offlineUsers = users.Where(u => !u.UserPair!.OtherPermissions.IsPaired() || !u.IsOnline && (!u.UserPair!.OwnPermissions.IsPaused() && !u.UserPair.OtherPermissions.IsPaused())).Select(c => new DrawUserPair("Offline" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager)).ToList();
ImGui.BeginChild("list", new Vector2(WindowContentWidth, ySize), border: false); ImGui.BeginChild("list", new Vector2(WindowContentWidth, ySize), border: false);
_pairGroupsUi.Draw(visibleUsers, onlineUsers, offlineUsers); _pairGroupsUi.Draw(visibleUsers, onlineUsers, pausedUsers, offlineUsers);
ImGui.EndChild(); ImGui.EndChild();
} }

View File

@@ -52,23 +52,24 @@ public class DrawUserPair : DrawPairBase
{ {
connectionIcon = FontAwesomeIcon.PauseCircle; connectionIcon = FontAwesomeIcon.PauseCircle;
connectionText = "Pairing status with " + _pair.UserData.AliasOrUID + " is paused"; connectionText = "Pairing status with " + _pair.UserData.AliasOrUID + " is paused";
connectionColor = ImGuiColors.DalamudYellow; connectionColor = ImGuiColors.DalamudGrey;
} }
else else
{ {
connectionIcon = FontAwesomeIcon.Check; connectionIcon = FontAwesomeIcon.Snowflake;
connectionText = "You are paired with " + _pair.UserData.AliasOrUID; connectionText = "You are paired with " + _pair.UserData.AliasOrUID;
connectionColor = ImGuiColors.ParsedGreen; connectionColor = _pair.IsOnline ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudGrey;
}
if (!_pair.IsVisible)
{
ImGui.SetCursorPosY(textPosY);
ImGui.PushFont(UiBuilder.IconFont);
UiSharedService.ColorText(connectionIcon.ToIconString(), connectionColor);
ImGui.PopFont();
UiSharedService.AttachToolTip(connectionText);
} }
ImGui.SetCursorPosY(textPosY);
ImGui.PushFont(UiBuilder.IconFont);
UiSharedService.ColorText(connectionIcon.ToIconString(), connectionColor);
ImGui.PopFont();
UiSharedService.AttachToolTip(connectionText);
if (_pair is { IsOnline: true, IsVisible: true }) if (_pair is { IsOnline: true, IsVisible: true })
{ {
ImGui.SameLine();
ImGui.SetCursorPosY(textPosY); ImGui.SetCursorPosY(textPosY);
ImGui.PushFont(UiBuilder.IconFont); ImGui.PushFont(UiBuilder.IconFont);
UiSharedService.ColorText(FontAwesomeIcon.Eye.ToIconString(), ImGuiColors.ParsedGreen); UiSharedService.ColorText(FontAwesomeIcon.Eye.ToIconString(), ImGuiColors.ParsedGreen);

View File

@@ -5,6 +5,8 @@ using MareSynchronos.API.Data.Extensions;
using MareSynchronos.MareConfiguration; using MareSynchronos.MareConfiguration;
using MareSynchronos.UI.Handlers; using MareSynchronos.UI.Handlers;
using MareSynchronos.WebAPI; using MareSynchronos.WebAPI;
using Serilog.Core;
using System.Diagnostics;
namespace MareSynchronos.UI.Components; namespace MareSynchronos.UI.Components;
@@ -28,15 +30,15 @@ public class PairGroupsUi
_uiSharedService = uiSharedService; _uiSharedService = uiSharedService;
} }
public void Draw<T>(List<T> visibleUsers, List<T> onlineUsers, List<T> offlineUsers) where T : DrawPairBase public void Draw<T>(List<T> visibleUsers, List<T> onlineUsers, List<T> pausedUsers, List<T> offlineUsers) where T : DrawPairBase
{ {
// Only render those tags that actually have pairs in them, otherwise // Only render those tags that actually have pairs in them, otherwise
// we can end up with a bunch of useless pair groups // we can end up with a bunch of useless pair groups
var tagsWithPairsInThem = _tagHandler.GetAllTagsSorted(); var tagsWithPairsInThem = _tagHandler.GetAllTagsSorted();
var allUsers = onlineUsers.Concat(offlineUsers).ToList(); var allUsers = onlineUsers.Concat(offlineUsers).Concat(pausedUsers).ToList();
if (typeof(T) == typeof(DrawUserPair)) if (typeof(T) == typeof(DrawUserPair))
{ {
DrawUserPairs(tagsWithPairsInThem, allUsers.Cast<DrawUserPair>().ToList(), visibleUsers.Cast<DrawUserPair>(), onlineUsers.Cast<DrawUserPair>(), offlineUsers.Cast<DrawUserPair>()); DrawUserPairs(tagsWithPairsInThem, allUsers.Cast<DrawUserPair>().ToList(), visibleUsers.Cast<DrawUserPair>(), onlineUsers.Cast<DrawUserPair>(), pausedUsers.Cast<DrawUserPair>(), offlineUsers.Cast<DrawUserPair>());
} }
} }
@@ -91,13 +93,19 @@ public class PairGroupsUi
} }
} }
private void DrawCategory(string tag, IEnumerable<DrawPairBase> onlineUsers, IEnumerable<DrawPairBase> allUsers, IEnumerable<DrawPairBase>? visibleUsers = null) private void DrawCategory(string tag, IEnumerable<DrawPairBase> onlineUsers, IEnumerable<DrawPairBase> pausedUsers, IEnumerable<DrawPairBase> allUsers, IEnumerable<DrawPairBase>? visibleUsers = null)
{ {
IEnumerable<DrawPairBase> usersInThisTag; IEnumerable<DrawPairBase> usersInThisTag;
HashSet<string>? otherUidsTaggedWithTag = null; HashSet<string>? otherUidsTaggedWithTag = null;
bool isSpecialTag = false; bool isSpecialTag = false;
int visibleInThisTag = 0; int visibleInThisTag = 0;
if (tag is TagHandler.CustomOfflineTag or TagHandler.CustomOnlineTag or TagHandler.CustomVisibleTag or TagHandler.CustomUnpairedTag)
if (tag is TagHandler.CustomPausedTag)
{
usersInThisTag = pausedUsers;
isSpecialTag = true;
}
else if (tag is TagHandler.CustomOfflineTag or TagHandler.CustomOnlineTag or TagHandler.CustomVisibleTag or TagHandler.CustomUnpairedTag)
{ {
usersInThisTag = onlineUsers; usersInThisTag = onlineUsers;
isSpecialTag = true; isSpecialTag = true;
@@ -113,14 +121,13 @@ public class PairGroupsUi
if (isSpecialTag && !usersInThisTag.Any()) return; if (isSpecialTag && !usersInThisTag.Any()) return;
DrawName(tag, isSpecialTag, visibleInThisTag, usersInThisTag.Count(), otherUidsTaggedWithTag?.Count); DrawName(tag, isSpecialTag, visibleInThisTag, usersInThisTag.Count(), pausedUsers.Count(), otherUidsTaggedWithTag?.Count);
if (!isSpecialTag) if (!isSpecialTag)
{ {
using (ImRaii.PushId($"group-{tag}-buttons")) DrawButtons(tag, allUsers.Cast<DrawUserPair>().Where(p => otherUidsTaggedWithTag!.Contains(p.UID)).ToList()); using (ImRaii.PushId($"group-{tag}-buttons")) DrawButtons(tag, allUsers.Cast<DrawUserPair>().Where(p => otherUidsTaggedWithTag!.Contains(p.UID)).ToList());
} }
else else
{ {
// Avoid uncomfortably close group names
if (!_tagHandler.IsTagOpen(tag)) if (!_tagHandler.IsTagOpen(tag))
{ {
var size = ImGui.CalcTextSize("").Y + ImGui.GetStyle().FramePadding.Y * 2f; var size = ImGui.CalcTextSize("").Y + ImGui.GetStyle().FramePadding.Y * 2f;
@@ -151,18 +158,19 @@ public class PairGroupsUi
UiSharedService.AttachToolTip($"Delete Group {tag} (Will not delete the pairs)" + Environment.NewLine + "Hold CTRL to delete"); UiSharedService.AttachToolTip($"Delete Group {tag} (Will not delete the pairs)" + Environment.NewLine + "Hold CTRL to delete");
} }
private void DrawName(string tag, bool isSpecialTag, int visible, int online, int? total) private void DrawName(string tag, bool isSpecialTag, int visible, int online, int paused, int? total)
{ {
string displayedName = tag switch string displayedName = tag switch
{ {
TagHandler.CustomUnpairedTag => "Unpaired", TagHandler.CustomUnpairedTag => "Unpaired",
TagHandler.CustomOfflineTag => "Offline", TagHandler.CustomOfflineTag => "Offline",
TagHandler.CustomOnlineTag => _mareConfig.Current.ShowOfflineUsersSeparately ? "Online/Paused" : "Contacts", TagHandler.CustomOnlineTag => _mareConfig.Current.ShowOfflineUsersSeparately ? "Online" : "Contacts",
TagHandler.CustomPausedTag => "Paused",
TagHandler.CustomVisibleTag => "Visible", TagHandler.CustomVisibleTag => "Visible",
_ => tag _ => tag
}; };
string resultFolderName = !isSpecialTag ? $"{displayedName} ({visible}/{online}/{total} Pairs)" : $"{displayedName} ({online} Pairs)"; string resultFolderName = !isSpecialTag ? $"{displayedName} ({visible}/{online}/{paused}/{total} Pairs)" : $"{displayedName} ({online} Pairs)";
// FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight // FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight
var icon = _tagHandler.IsTagOpen(tag) ? FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight; var icon = _tagHandler.IsTagOpen(tag) ? FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight;
@@ -184,7 +192,8 @@ public class PairGroupsUi
ImGui.TextUnformatted($"Group {tag}"); ImGui.TextUnformatted($"Group {tag}");
ImGui.Separator(); ImGui.Separator();
ImGui.TextUnformatted($"{visible} Pairs visible"); ImGui.TextUnformatted($"{visible} Pairs visible");
ImGui.TextUnformatted($"{online} Pairs online/paused"); ImGui.TextUnformatted($"{online} Pairs online");
ImGui.TextUnformatted($"{paused} Pairs paused");
ImGui.TextUnformatted($"{total} Pairs total"); ImGui.TextUnformatted($"{total} Pairs total");
ImGui.EndTooltip(); ImGui.EndTooltip();
} }
@@ -197,39 +206,45 @@ public class PairGroupsUi
ImGui.Separator(); ImGui.Separator();
} }
private void DrawUserPairs(List<string> tagsWithPairsInThem, List<DrawUserPair> allUsers, IEnumerable<DrawUserPair> visibleUsers, IEnumerable<DrawUserPair> onlineUsers, IEnumerable<DrawUserPair> offlineUsers) private void DrawUserPairs(List<string> tagsWithPairsInThem, List<DrawUserPair> allUsers, IEnumerable<DrawUserPair> visibleUsers, IEnumerable<DrawUserPair> onlineUsers, IEnumerable<DrawUserPair> pausedUsers, IEnumerable<DrawUserPair> offlineUsers)
{ {
if (_mareConfig.Current.ShowVisibleUsersSeparately) if (_mareConfig.Current.ShowVisibleUsersSeparately)
{ {
using (ImRaii.PushId("$group-VisibleCustomTag")) DrawCategory(TagHandler.CustomVisibleTag, visibleUsers, allUsers); using (ImRaii.PushId("$group-VisibleCustomTag")) DrawCategory(TagHandler.CustomVisibleTag, visibleUsers, Enumerable.Empty<DrawUserPair>(), allUsers);
} }
foreach (var tag in tagsWithPairsInThem) foreach (var tag in tagsWithPairsInThem)
{ {
if (_mareConfig.Current.ShowOfflineUsersSeparately) if (_mareConfig.Current.ShowOfflineUsersSeparately)
{ {
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, onlineUsers, allUsers, visibleUsers); using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, onlineUsers, pausedUsers, allUsers, visibleUsers);
} }
else else
{ {
using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, allUsers, allUsers, visibleUsers); using (ImRaii.PushId($"group-{tag}")) DrawCategory(tag, allUsers, Enumerable.Empty<DrawUserPair>(), allUsers, visibleUsers);
} }
} }
if (_mareConfig.Current.ShowOfflineUsersSeparately) if (_mareConfig.Current.ShowOfflineUsersSeparately)
{ {
using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag, using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag,
onlineUsers.Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), allUsers); onlineUsers.Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
if (pausedUsers.Any()) using (ImRaii.PushId("group-PausedCustomTag")) DrawCategory(TagHandler.CustomPausedTag,
Enumerable.Empty<DrawUserPair>(), pausedUsers, allUsers);
using (ImRaii.PushId($"group-OfflineCustomTag")) DrawCategory(TagHandler.CustomOfflineTag, using (ImRaii.PushId($"group-OfflineCustomTag")) DrawCategory(TagHandler.CustomOfflineTag,
offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired()).ToList(), allUsers); offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired()).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
} }
else else
{ {
using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag, using (ImRaii.PushId($"group-OnlineCustomTag")) DrawCategory(TagHandler.CustomOnlineTag,
onlineUsers.Concat(offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired())).Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), allUsers); onlineUsers.Concat(offlineUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired())).Where(u => !_tagHandler.HasAnyTag(u.UID)).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
} }
using (ImRaii.PushId($"group-UnpairedCustomTag")) DrawCategory(TagHandler.CustomUnpairedTag, using (ImRaii.PushId($"group-UnpairedCustomTag")) DrawCategory(TagHandler.CustomUnpairedTag,
offlineUsers.Where(u => !u.UserPair!.OtherPermissions.IsPaired()).ToList(), allUsers); offlineUsers.Where(u => !u.UserPair!.OtherPermissions.IsPaired()).ToList(), Enumerable.Empty<DrawUserPair>(), allUsers);
} }
private void PauseRemainingPairs(List<DrawUserPair> availablePairs) private void PauseRemainingPairs(List<DrawUserPair> availablePairs)
{ {
foreach (var pairToPause in availablePairs.Where(pair => !pair.UserPair!.OwnPermissions.IsPaused())) foreach (var pairToPause in availablePairs.Where(pair => !pair.UserPair!.OwnPermissions.IsPaused()))

View File

@@ -203,10 +203,10 @@ public sealed class DtrEntry : IDisposable, IHostedService
DtrStyle.Style4 => $"\xE03A {text}", DtrStyle.Style4 => $"\xE03A {text}",
DtrStyle.Style5 => $"\xE033 {text}", DtrStyle.Style5 => $"\xE033 {text}",
DtrStyle.Style6 => $"\xE038 {text}", DtrStyle.Style6 => $"\xE038 {text}",
DtrStyle.Style7 => $"\xE05D {text}", DtrStyle.Style7 => $"\xE044 {text}",
DtrStyle.Style8 => $"\xE03C{text}", DtrStyle.Style8 => $"\xE03C{text}",
DtrStyle.Style9 => $"\xE040 {text} \xE041", DtrStyle.Style9 => $"\xE040 {text} \xE041",
_ => $"\uE044 {text}" _ => $"\uE05D {text}"
}; };
} }

View File

@@ -9,6 +9,7 @@ public class TagHandler
public const string CustomOnlineTag = "Mare_Online"; public const string CustomOnlineTag = "Mare_Online";
public const string CustomUnpairedTag = "Mare_Unpaired"; public const string CustomUnpairedTag = "Mare_Unpaired";
public const string CustomVisibleTag = "Mare_Visible"; public const string CustomVisibleTag = "Mare_Visible";
public const string CustomPausedTag = "Mare_Paused";
private readonly ServerConfigurationManager _serverConfigurationManager; private readonly ServerConfigurationManager _serverConfigurationManager;
public TagHandler(ServerConfigurationManager serverConfigurationManager) public TagHandler(ServerConfigurationManager serverConfigurationManager)

View File

@@ -1083,12 +1083,12 @@ public class SettingsUi : WindowMediatorSubscriberBase
_configService.Save(); _configService.Save();
} }
_uiShared.DrawHelpText("This will put users using the most VRAM in a syncshell at the top of the list."); _uiShared.DrawHelpText("This will put users using the most VRAM in a syncshell at the top of the list.");
if (ImGui.Checkbox("Show separate Offline group", ref showOfflineSeparate)) if (ImGui.Checkbox("Group users by connection status", ref showOfflineSeparate))
{ {
_configService.Current.ShowOfflineUsersSeparately = showOfflineSeparate; _configService.Current.ShowOfflineUsersSeparately = showOfflineSeparate;
_configService.Save(); _configService.Save();
} }
_uiShared.DrawHelpText("This will show all currently offline users in a special 'Offline' group in the main UI."); _uiShared.DrawHelpText("This will categorize users by their connection status in the main UI.");
if (ImGui.Checkbox("Show player names", ref showCharacterNames)) if (ImGui.Checkbox("Show player names", ref showCharacterNames))
{ {