UI Update

This commit is contained in:
2025-10-19 21:56:19 +02:00
parent 89fa1a999f
commit d891dceb28
12 changed files with 1002 additions and 472 deletions

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<AssemblyName>UmbraSync</AssemblyName> <AssemblyName>UmbraSync</AssemblyName>
<RootNamespace>UmbraSync</RootNamespace> <RootNamespace>UmbraSync</RootNamespace>
<Version>0.1.9.5</Version> <Version>0.1.9.6</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -182,17 +182,22 @@ public sealed class Plugin : IDalamudPlugin
// add scoped services // add scoped services
collection.AddScoped<CacheMonitor>(); collection.AddScoped<CacheMonitor>();
collection.AddScoped<UiFactory>(); collection.AddScoped<UiFactory>();
collection.AddScoped<WindowMediatorSubscriberBase, SettingsUi>(); collection.AddScoped<SettingsUi>();
collection.AddScoped<WindowMediatorSubscriberBase, CompactUi>(); collection.AddScoped<CompactUi>();
collection.AddScoped<EditProfileUi>();
collection.AddScoped<DataAnalysisUi>();
collection.AddScoped<AutoDetectUi>();
collection.AddScoped<WindowMediatorSubscriberBase>(sp => sp.GetRequiredService<SettingsUi>());
collection.AddScoped<WindowMediatorSubscriberBase>(sp => sp.GetRequiredService<CompactUi>());
collection.AddScoped<WindowMediatorSubscriberBase, IntroUi>(); collection.AddScoped<WindowMediatorSubscriberBase, IntroUi>();
collection.AddScoped<WindowMediatorSubscriberBase, DownloadUi>(); collection.AddScoped<WindowMediatorSubscriberBase, DownloadUi>();
collection.AddScoped<WindowMediatorSubscriberBase, AutoDetectUi>(); collection.AddScoped<WindowMediatorSubscriberBase>(sp => sp.GetRequiredService<AutoDetectUi>());
collection.AddScoped<WindowMediatorSubscriberBase, ChangelogUi>(); collection.AddScoped<WindowMediatorSubscriberBase, ChangelogUi>();
collection.AddScoped<WindowMediatorSubscriberBase, PopoutProfileUi>(); collection.AddScoped<WindowMediatorSubscriberBase, PopoutProfileUi>();
collection.AddScoped<WindowMediatorSubscriberBase, DataAnalysisUi>(); collection.AddScoped<WindowMediatorSubscriberBase>(sp => sp.GetRequiredService<DataAnalysisUi>());
collection.AddScoped<WindowMediatorSubscriberBase, EventViewerUI>(); collection.AddScoped<WindowMediatorSubscriberBase, EventViewerUI>();
collection.AddScoped<WindowMediatorSubscriberBase, CharaDataHubUi>(); collection.AddScoped<WindowMediatorSubscriberBase, CharaDataHubUi>();
collection.AddScoped<WindowMediatorSubscriberBase, EditProfileUi>(); collection.AddScoped<WindowMediatorSubscriberBase>(sp => sp.GetRequiredService<EditProfileUi>());
collection.AddScoped<WindowMediatorSubscriberBase, PopupHandler>(); collection.AddScoped<WindowMediatorSubscriberBase, PopupHandler>();
collection.AddScoped<WindowMediatorSubscriberBase, TypingIndicatorOverlay>(); collection.AddScoped<WindowMediatorSubscriberBase, TypingIndicatorOverlay>();
collection.AddScoped<IPopupHandler, ReportPopupHandler>(); collection.AddScoped<IPopupHandler, ReportPopupHandler>();

View File

@@ -90,6 +90,11 @@ public class AutoDetectUi : WindowMediatorSubscriberBase
} }
} }
public void DrawInline()
{
DrawInternal();
}
private static void DrawStyledTab(string label, Vector4 accent, Vector4 inactive, Vector4 hover, Action draw, bool disabled = false) private static void DrawStyledTab(string label, Vector4 accent, Vector4 inactive, Vector4 hover, Action draw, bool disabled = false)
{ {
var tabColor = disabled ? ImGuiColors.DalamudGrey3 : inactive; var tabColor = disabled ? ImGuiColors.DalamudGrey3 : inactive;

File diff suppressed because it is too large Load Diff

View File

@@ -45,6 +45,43 @@ public class DrawGroupPair : DrawPairBase
_serverConfigurationManager = serverConfigurationManager; _serverConfigurationManager = serverConfigurationManager;
} }
protected override float GetRightSideExtraWidth()
{
float width = 0f;
float spacing = ImGui.GetStyle().ItemSpacing.X;
var soundsDisabled = _fullInfoDto.GroupUserPermissions.IsDisableSounds();
var animDisabled = _fullInfoDto.GroupUserPermissions.IsDisableAnimations();
var vfxDisabled = _fullInfoDto.GroupUserPermissions.IsDisableVFX();
var individualSoundsDisabled = (_pair.UserPair?.OwnPermissions.IsDisableSounds() ?? false) || (_pair.UserPair?.OtherPermissions.IsDisableSounds() ?? false);
var individualAnimDisabled = (_pair.UserPair?.OwnPermissions.IsDisableAnimations() ?? false) || (_pair.UserPair?.OtherPermissions.IsDisableAnimations() ?? false);
var individualVFXDisabled = (_pair.UserPair?.OwnPermissions.IsDisableVFX() ?? false) || (_pair.UserPair?.OtherPermissions.IsDisableVFX() ?? false);
bool showInfo = individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled || animDisabled || soundsDisabled || vfxDisabled;
bool showShared = _charaDataManager.SharedWithYouData.TryGetValue(_pair.UserData, out var sharedData);
bool showPlus = _pair.UserPair == null && _pair.IsOnline;
if (showShared)
{
width += _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Running).X + spacing;
}
if (showInfo)
{
var icon = (individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled)
? FontAwesomeIcon.ExclamationTriangle
: FontAwesomeIcon.InfoCircle;
width += UiSharedService.GetIconSize(icon).X + spacing;
}
if (showPlus)
{
width += _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Plus).X + spacing;
}
return width;
}
protected override void DrawLeftSide(float textPosY, float originalY) protected override void DrawLeftSide(float textPosY, float originalY)
{ {
var entryUID = _pair.UserData.AliasOrUID; var entryUID = _pair.UserData.AliasOrUID;

View File

@@ -1,5 +1,8 @@
using Dalamud.Bindings.ImGui; using System;
using System.Numerics;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Utility;
using MareSynchronos.PlayerData.Pairs; using MareSynchronos.PlayerData.Pairs;
using MareSynchronos.UI.Handlers; using MareSynchronos.UI.Handlers;
using MareSynchronos.WebAPI; using MareSynchronos.WebAPI;
@@ -28,36 +31,75 @@ public abstract class DrawPairBase
public void DrawPairedClient() public void DrawPairedClient()
{ {
var originalY = ImGui.GetCursorPosY(); var style = ImGui.GetStyle();
var pauseIconSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Play); var padding = style.FramePadding;
var textSize = ImGui.CalcTextSize(_pair.UserData.AliasOrUID); var spacing = style.ItemSpacing;
var rowStartCursor = ImGui.GetCursorPos();
var rowStartScreen = ImGui.GetCursorScreenPos();
var startPos = ImGui.GetCursorStartPos(); var pauseButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Pause);
var playButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Play);
var menuButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars);
var framePadding = ImGui.GetStyle().FramePadding; float pauseClusterWidth = Math.Max(pauseButtonSize.X, playButtonSize.X);
var lineHeight = textSize.Y + framePadding.Y * 2; float pauseClusterHeight = Math.Max(pauseButtonSize.Y, playButtonSize.Y);
float reservedSpacing = style.ItemSpacing.X * 2.4f;
float rightButtonWidth =
menuButtonSize.X +
pauseClusterWidth +
reservedSpacing +
GetRightSideExtraWidth();
var off = startPos.Y; float availableWidth = Math.Max(ImGui.GetContentRegionAvail().X - rightButtonWidth, 1f);
var height = UiSharedService.GetWindowContentRegionHeight(); float textHeight = ImGui.GetFontSize();
var presenceIconSize = UiSharedService.GetIconSize(FontAwesomeIcon.Moon);
float iconHeight = presenceIconSize.Y;
float contentHeight = Math.Max(textHeight, Math.Max(iconHeight, pauseClusterHeight));
float rowHeight = contentHeight + padding.Y * 2f;
float totalHeight = rowHeight + spacing.Y;
if ((originalY + off) < -lineHeight || (originalY + off) > height) var origin = ImGui.GetCursorStartPos();
var top = origin.Y + rowStartCursor.Y;
var bottom = top + totalHeight;
var visibleHeight = UiSharedService.GetWindowContentRegionHeight();
if (bottom < 0 || top > visibleHeight)
{ {
ImGui.Dummy(new System.Numerics.Vector2(0f, lineHeight)); ImGui.SetCursorPos(new Vector2(rowStartCursor.X, rowStartCursor.Y + totalHeight));
return; return;
} }
var textPosY = originalY + pauseIconSize.Y / 2 - textSize.Y / 2; var drawList = ImGui.GetWindowDrawList();
DrawLeftSide(textPosY, originalY); var backgroundColor = new Vector4(0.10f, 0.10f, 0.14f, 0.95f);
var borderColor = new Vector4(0f, 0f, 0f, 0.9f);
float rounding = Math.Max(style.FrameRounding, 7f * ImGuiHelpers.GlobalScale);
var panelMin = rowStartScreen + new Vector2(0f, spacing.Y * 0.15f);
var panelMax = panelMin + new Vector2(availableWidth, rowHeight - spacing.Y * 0.3f);
drawList.AddRectFilled(panelMin, panelMax, ImGui.ColorConvertFloat4ToU32(backgroundColor), rounding);
drawList.AddRect(panelMin, panelMax, ImGui.ColorConvertFloat4ToU32(borderColor), rounding);
float iconTop = rowStartCursor.Y + (rowHeight - iconHeight) / 2f;
float textTop = rowStartCursor.Y + (rowHeight - textHeight) / 2f - padding.Y * 0.6f;
float buttonTop = rowStartCursor.Y + (rowHeight - pauseClusterHeight) / 2f;
ImGui.SetCursorPos(new Vector2(rowStartCursor.X + padding.X, iconTop));
DrawLeftSide(iconTop, iconTop);
ImGui.SameLine(); ImGui.SameLine();
ImGui.SetCursorPosY(textTop);
var posX = ImGui.GetCursorPosX(); var posX = ImGui.GetCursorPosX();
var rightSide = DrawRightSide(textPosY, originalY); var rightSide = DrawRightSide(buttonTop, buttonTop);
DrawName(originalY, posX, rightSide); DrawName(textTop + padding.Y * 0.15f, posX, rightSide);
ImGui.SetCursorPos(new Vector2(rowStartCursor.X, rowStartCursor.Y + totalHeight));
ImGui.SetCursorPosX(rowStartCursor.X);
} }
protected abstract void DrawLeftSide(float textPosY, float originalY); protected abstract void DrawLeftSide(float textPosY, float originalY);
protected abstract float DrawRightSide(float textPosY, float originalY); protected abstract float DrawRightSide(float textPosY, float originalY);
protected virtual float GetRightSideExtraWidth() => 0f;
private void DrawName(float originalY, float leftSide, float rightSide) private void DrawName(float originalY, float leftSide, float rightSide)
{ {
_displayHandler.DrawPairText(_id, _pair, leftSide, originalY, () => rightSide - leftSide); _displayHandler.DrawPairText(_id, _pair, leftSide, originalY, () => rightSide - leftSide);

View File

@@ -41,6 +41,28 @@ public class DrawUserPair : DrawPairBase
public bool IsVisible => _pair.IsVisible; public bool IsVisible => _pair.IsVisible;
public UserPairDto UserPair => _pair.UserPair!; public UserPairDto UserPair => _pair.UserPair!;
protected override float GetRightSideExtraWidth()
{
float width = 0f;
var spacingX = ImGui.GetStyle().ItemSpacing.X;
var individualSoundsDisabled = (_pair.UserPair?.OwnPermissions.IsDisableSounds() ?? false) || (_pair.UserPair?.OtherPermissions.IsDisableSounds() ?? false);
var individualAnimDisabled = (_pair.UserPair?.OwnPermissions.IsDisableAnimations() ?? false) || (_pair.UserPair?.OtherPermissions.IsDisableAnimations() ?? false);
var individualVFXDisabled = (_pair.UserPair?.OwnPermissions.IsDisableVFX() ?? false) || (_pair.UserPair?.OtherPermissions.IsDisableVFX() ?? false);
if (individualSoundsDisabled || individualAnimDisabled || individualVFXDisabled)
{
width += _uiSharedService.GetIconButtonSize(FontAwesomeIcon.ExclamationTriangle).X + spacingX * 0.5f;
}
if (_charaDataManager.SharedWithYouData.TryGetValue(_pair.UserData, out var sharedData))
{
width += _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Running).X + spacingX * 0.5f;
}
return width;
}
protected override void DrawLeftSide(float textPosY, float originalY) protected override void DrawLeftSide(float textPosY, float originalY)
{ {
var online = _pair.IsOnline; var online = _pair.IsOnline;
@@ -110,7 +132,8 @@ public class DrawUserPair : DrawPairBase
var barButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars); var barButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars);
var entryUID = _pair.UserData.AliasOrUID; var entryUID = _pair.UserData.AliasOrUID;
var spacingX = ImGui.GetStyle().ItemSpacing.X; var spacingX = ImGui.GetStyle().ItemSpacing.X;
var windowEndX = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth(); var edgePadding = ImGui.GetStyle().WindowPadding.X + 4f * ImGuiHelpers.GlobalScale;
var windowEndX = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - edgePadding;
var rightSidePos = windowEndX - barButtonSize.X; var rightSidePos = windowEndX - barButtonSize.X;
// Flyout Menu // Flyout Menu

View File

@@ -313,19 +313,20 @@ internal sealed class GroupPanel
int shellNumber = _serverConfigurationManager.GetShellNumberForGid(groupDto.GID); int shellNumber = _serverConfigurationManager.GetShellNumberForGid(groupDto.GID);
var name = groupDto.Group.Alias ?? groupDto.GID; var name = groupDto.Group.Alias ?? groupDto.GID;
if (!_expandedGroupState.TryGetValue(groupDto.GID, out bool isExpanded)) if (!_expandedGroupState.ContainsKey(groupDto.GID))
{ {
isExpanded = false; _expandedGroupState[groupDto.GID] = false;
_expandedGroupState.Add(groupDto.GID, isExpanded);
} }
var icon = isExpanded ? FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight; UiSharedService.DrawCard($"syncshell-card-{groupDto.GID}", () =>
_uiShared.IconText(icon);
if (ImGui.IsItemClicked(ImGuiMouseButton.Left))
{ {
_expandedGroupState[groupDto.GID] = !_expandedGroupState[groupDto.GID]; bool expandedState = _expandedGroupState[groupDto.GID];
UiSharedService.DrawArrowToggle(ref expandedState, $"##syncshell-toggle-{groupDto.GID}");
if (expandedState != _expandedGroupState[groupDto.GID])
{
_expandedGroupState[groupDto.GID] = expandedState;
} }
ImGui.SameLine(); ImGui.SameLine(0f, 6f * ImGuiHelpers.GlobalScale);
var textIsGid = true; var textIsGid = true;
string groupName = groupDto.GroupAliasOrGID; string groupName = groupDto.GroupAliasOrGID;
@@ -547,7 +548,7 @@ internal sealed class GroupPanel
bool hideOfflineUsers = pairsInGroup.Count > 1000; bool hideOfflineUsers = pairsInGroup.Count > 1000;
ImGui.Indent(20); ImGui.Indent(20);
if (_expandedGroupState[groupDto.GID]) if (expandedState)
{ {
var sortedPairs = pairsInGroup var sortedPairs = pairsInGroup
.OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal)) .OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal))
@@ -614,6 +615,9 @@ internal sealed class GroupPanel
ImGui.Separator(); ImGui.Separator();
} }
ImGui.Unindent(20); ImGui.Unindent(20);
}, background: new Vector4(0.15f, 0.15f, 0.20f, 0.94f), border: new Vector4(0f, 0f, 0f, 0.78f), stretchWidth: true);
ImGuiHelpers.ScaledDummy(4f);
} }
private void DrawSyncShellButtons(GroupFullInfoDto groupDto, List<Pair> groupPairs) private void DrawSyncShellButtons(GroupFullInfoDto groupDto, List<Pair> groupPairs)
@@ -828,9 +832,22 @@ internal sealed class GroupPanel
private void DrawSyncshellList() private void DrawSyncshellList()
{ {
var ySize = _mainUi.TransferPartHeight == 0 float availableHeight = ImGui.GetContentRegionAvail().Y;
? 1 float ySize;
: (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - _mainUi.TransferPartHeight - ImGui.GetCursorPosY(); if (_mainUi.TransferPartHeight <= 0)
{
float reserve = ImGui.GetFrameHeightWithSpacing() * 2f;
ySize = availableHeight - reserve;
if (ySize <= 0)
{
ySize = System.Math.Max(availableHeight, 1f);
}
}
else
{
ySize = (ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y) - _mainUi.TransferPartHeight - ImGui.GetCursorPosY();
}
ImGui.BeginChild("list", new Vector2(_mainUi.WindowContentWidth, ySize), border: false); ImGui.BeginChild("list", new Vector2(_mainUi.WindowContentWidth, ySize), border: false);
foreach (var entry in _pairManager.GroupPairs.OrderBy(g => g.Key.Group.AliasOrGID, StringComparer.OrdinalIgnoreCase).ToList()) foreach (var entry in _pairManager.GroupPairs.OrderBy(g => g.Key.Group.AliasOrGID, StringComparer.OrdinalIgnoreCase).ToList())
{ {

View File

@@ -1,10 +1,14 @@
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using MareSynchronos.API.Data.Extensions; 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 System;
using System.Collections.Generic;
using System.Linq;
namespace MareSynchronos.UI.Components; namespace MareSynchronos.UI.Components;
@@ -28,7 +32,7 @@ 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> offlineUsers, Action? drawVisibleExtras = null) 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
@@ -36,7 +40,7 @@ public class PairGroupsUi
var allUsers = onlineUsers.Concat(offlineUsers).ToList(); var allUsers = onlineUsers.Concat(offlineUsers).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>(), offlineUsers.Cast<DrawUserPair>(), drawVisibleExtras);
} }
} }
@@ -44,14 +48,15 @@ public class PairGroupsUi
{ {
var allArePaused = availablePairsInThisTag.All(pair => pair.UserPair!.OwnPermissions.IsPaused()); var allArePaused = availablePairsInThisTag.All(pair => pair.UserPair!.OwnPermissions.IsPaused());
var pauseButton = allArePaused ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause; var pauseButton = allArePaused ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
var flyoutMenuX = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars).X; var flyoutMenuSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Bars);
var pauseButtonX = _uiSharedService.GetIconButtonSize(pauseButton).X; var pauseButtonSize = _uiSharedService.GetIconButtonSize(pauseButton);
var windowX = ImGui.GetWindowContentRegionMin().X;
var windowWidth = UiSharedService.GetWindowContentRegionWidth();
var spacingX = ImGui.GetStyle().ItemSpacing.X; var spacingX = ImGui.GetStyle().ItemSpacing.X;
var currentX = ImGui.GetCursorPosX();
var availableWidth = ImGui.GetContentRegionAvail().X;
var buttonsWidth = pauseButtonSize.X + flyoutMenuSize.X + spacingX;
var pauseStart = Math.Max(currentX, currentX + availableWidth - buttonsWidth);
var buttonPauseOffset = windowX + windowWidth - flyoutMenuX - spacingX - pauseButtonX; ImGui.SameLine(pauseStart);
ImGui.SameLine(buttonPauseOffset);
if (_uiSharedService.IconButton(pauseButton)) if (_uiSharedService.IconButton(pauseButton))
{ {
if (allArePaused) if (allArePaused)
@@ -72,8 +77,8 @@ public class PairGroupsUi
UiSharedService.AttachToolTip($"Pause pairing with all pairs in {tag}"); UiSharedService.AttachToolTip($"Pause pairing with all pairs in {tag}");
} }
var buttonDeleteOffset = windowX + windowWidth - flyoutMenuX; var menuStart = Math.Max(pauseStart + pauseButtonSize.X + spacingX, currentX);
ImGui.SameLine(buttonDeleteOffset); ImGui.SameLine(menuStart);
if (_uiSharedService.IconButton(FontAwesomeIcon.Bars)) if (_uiSharedService.IconButton(FontAwesomeIcon.Bars))
{ {
ImGui.OpenPopup("Group Flyout Menu"); ImGui.OpenPopup("Group Flyout Menu");
@@ -86,7 +91,7 @@ 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> allUsers, IEnumerable<DrawPairBase>? visibleUsers = null, Action? drawExtraContent = null)
{ {
IEnumerable<DrawPairBase> usersInThisTag; IEnumerable<DrawPairBase> usersInThisTag;
HashSet<string>? otherUidsTaggedWithTag = null; HashSet<string>? otherUidsTaggedWithTag = null;
@@ -108,26 +113,25 @@ public class PairGroupsUi
if (isSpecialTag && !usersInThisTag.Any()) return; if (isSpecialTag && !usersInThisTag.Any()) return;
DrawName(tag, isSpecialTag, visibleInThisTag, usersInThisTag.Count(), otherUidsTaggedWithTag?.Count); UiSharedService.DrawCard($"pair-group-{tag}", () =>
if (!isSpecialTag)
{ {
using (ImRaii.PushId($"group-{tag}-buttons")) DrawButtons(tag, allUsers.Cast<DrawUserPair>().Where(p => otherUidsTaggedWithTag!.Contains(p.UID)).ToList()); DrawName(tag, isSpecialTag, visibleInThisTag, usersInThisTag.Count(), otherUidsTaggedWithTag?.Count);
} if (!isSpecialTag)
else
{
if (!_tagHandler.IsTagOpen(tag))
{ {
var size = ImGui.CalcTextSize("").Y + ImGui.GetStyle().FramePadding.Y * 2f; using (ImRaii.PushId($"group-{tag}-buttons")) DrawButtons(tag, allUsers.Cast<DrawUserPair>().Where(p => otherUidsTaggedWithTag!.Contains(p.UID)).ToList());
ImGui.SameLine();
ImGui.Dummy(new(size, size));
} }
}
if (!_tagHandler.IsTagOpen(tag)) return; if (!_tagHandler.IsTagOpen(tag)) return;
ImGui.Indent(20); ImGuiHelpers.ScaledDummy(4f);
DrawPairs(tag, usersInThisTag); var indent = 18f * ImGuiHelpers.GlobalScale;
ImGui.Unindent(20); ImGui.Indent(indent);
DrawPairs(tag, usersInThisTag);
drawExtraContent?.Invoke();
ImGui.Unindent(indent);
}, stretchWidth: true);
ImGuiHelpers.ScaledDummy(4f);
} }
private void DrawGroupMenu(string tag) private void DrawGroupMenu(string tag)
@@ -157,17 +161,21 @@ public class PairGroupsUi
}; };
string resultFolderName = !isSpecialTag ? $"{displayedName} ({visible}/{online}/{total} Pairs)" : $"{displayedName} ({online} Pairs)"; string resultFolderName = !isSpecialTag ? $"{displayedName} ({visible}/{online}/{total} Pairs)" : $"{displayedName} ({online} Pairs)";
var icon = _tagHandler.IsTagOpen(tag) ? FontAwesomeIcon.CaretSquareDown : FontAwesomeIcon.CaretSquareRight; bool isOpen = _tagHandler.IsTagOpen(tag);
_uiSharedService.IconText(icon); bool previousState = isOpen;
if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) UiSharedService.DrawArrowToggle(ref isOpen, $"##group-toggle-{tag}");
if (isOpen != previousState)
{ {
ToggleTagOpen(tag); _tagHandler.SetTagOpen(tag, isOpen);
} }
ImGui.SameLine(); ImGui.SameLine(0f, 6f * ImGuiHelpers.GlobalScale);
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(resultFolderName); ImGui.TextUnformatted(resultFolderName);
if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) if (ImGui.IsItemClicked(ImGuiMouseButton.Left))
{ {
ToggleTagOpen(tag); bool newState = !_tagHandler.IsTagOpen(tag);
_tagHandler.SetTagOpen(tag, newState);
isOpen = newState;
} }
if (!isSpecialTag && ImGui.IsItemHovered()) if (!isSpecialTag && ImGui.IsItemHovered())
@@ -186,14 +194,13 @@ public class PairGroupsUi
{ {
// These are all the OtherUIDs that are tagged with this tag // These are all the OtherUIDs that are tagged with this tag
_uidDisplayHandler.RenderPairList(availablePairsInThisCategory); _uidDisplayHandler.RenderPairList(availablePairsInThisCategory);
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> offlineUsers, Action? drawVisibleExtras)
{ {
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, allUsers, drawExtraContent: drawVisibleExtras);
} }
foreach (var tag in tagsWithPairsInThem) foreach (var tag in tagsWithPairsInThem)
{ {

View File

@@ -64,6 +64,16 @@ public class EditProfileUi : WindowMediatorSubscriberBase
} }
protected override void DrawInternal() protected override void DrawInternal()
{
DrawProfileContent();
}
public void DrawInline()
{
DrawProfileContent();
}
private void DrawProfileContent()
{ {
_uiSharedService.BigText("Current Profile (as saved on server)"); _uiSharedService.BigText("Current Profile (as saved on server)");
ImGuiHelpers.ScaledDummy(new Vector2(0f, ImGui.GetStyle().ItemSpacing.Y / 2)); ImGuiHelpers.ScaledDummy(new Vector2(0f, ImGui.GetStyle().ItemSpacing.Y / 2));

View File

@@ -131,6 +131,11 @@ public class SettingsUi : WindowMediatorSubscriberBase
DrawSettingsContent(); DrawSettingsContent();
} }
public void DrawInline()
{
DrawSettingsContent();
}
public override void OnClose() public override void OnClose()
{ {
_uiShared.EditTrackerPosition = false; _uiShared.EditTrackerPosition = false;
@@ -1002,7 +1007,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
_lastTab = "General"; _lastTab = "General";
_uiShared.BigText("Notes"); _uiShared.BigText("Notes");
if (_uiShared.IconTextButton(FontAwesomeIcon.StickyNote, "Export all your user notes to clipboard")) if (_uiShared.IconTextButton(FontAwesomeIcon.StickyNote, "Export all your user notes to clipboard"))
{ {
ImGui.SetClipboardText(UiSharedService.GetNotes(_pairManager.DirectPairs.UnionBy(_pairManager.GroupPairs.SelectMany(p => p.Value), p => p.UserData, UserDataComparer.Instance).ToList())); ImGui.SetClipboardText(UiSharedService.GetNotes(_pairManager.DirectPairs.UnionBy(_pairManager.GroupPairs.SelectMany(p => p.Value), p => p.UserData, UserDataComparer.Instance).ToList()));

View File

@@ -20,6 +20,7 @@ using MareSynchronos.Services.Mediator;
using MareSynchronos.Services.ServerConfiguration; using MareSynchronos.Services.ServerConfiguration;
using MareSynchronos.WebAPI; using MareSynchronos.WebAPI;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System;
using System.Numerics; using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@@ -216,7 +217,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
public static bool CtrlPressed() => (GetKeyState(0xA2) & 0x8000) != 0 || (GetKeyState(0xA3) & 0x8000) != 0; public static bool CtrlPressed() => (GetKeyState(0xA2) & 0x8000) != 0 || (GetKeyState(0xA3) & 0x8000) != 0;
public static void DrawGrouped(Action imguiDrawAction, float rounding = 5f, float? expectedWidth = null) public static void DrawGrouped(Action imguiDrawAction, float rounding = 5f, float? expectedWidth = null, bool drawBorder = true)
{ {
var cursorPos = ImGui.GetCursorPos(); var cursorPos = ImGui.GetCursorPos();
using (ImRaii.Group()) using (ImRaii.Group())
@@ -230,10 +231,122 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
imguiDrawAction.Invoke(); imguiDrawAction.Invoke();
} }
ImGui.GetWindowDrawList().AddRect( if (drawBorder)
ImGui.GetItemRectMin() - ImGui.GetStyle().ItemInnerSpacing, {
ImGui.GetItemRectMax() + ImGui.GetStyle().ItemInnerSpacing, ImGui.GetWindowDrawList().AddRect(
Color(ImGuiColors.DalamudGrey2), rounding); ImGui.GetItemRectMin() - ImGui.GetStyle().ItemInnerSpacing,
ImGui.GetItemRectMax() + ImGui.GetStyle().ItemInnerSpacing,
Color(ImGuiColors.DalamudGrey2), rounding);
}
}
public static void DrawCard(string id, Action draw, Vector2? padding = null, Vector4? background = null,
Vector4? border = null, float? rounding = null, bool stretchWidth = false)
{
var style = ImGui.GetStyle();
var padBase = style.FramePadding;
var pad = padding ?? new Vector2(
padBase.X + 4f * ImGuiHelpers.GlobalScale,
padBase.Y + 3f * ImGuiHelpers.GlobalScale);
var cardBg = background ?? new Vector4(0.08f, 0.08f, 0.10f, 0.94f);
var cardBorder = border ?? new Vector4(0f, 0f, 0f, 0.85f);
float cardRounding = rounding ?? Math.Max(style.FrameRounding, 8f * ImGuiHelpers.GlobalScale);
float borderThickness = Math.Max(1f, Math.Max(style.FrameBorderSize, 1f) * ImGuiHelpers.GlobalScale);
float borderInset = borderThickness;
var originalCursor = ImGui.GetCursorPos();
if (stretchWidth)
{
ImGui.SetCursorPosX(ImGui.GetWindowContentRegionMin().X);
}
var startCursor = ImGui.GetCursorPos();
var drawList = ImGui.GetWindowDrawList();
drawList.ChannelsSplit(2);
drawList.ChannelsSetCurrent(1);
ImGui.PushID(id);
ImGui.SetCursorPos(new Vector2(startCursor.X + pad.X, startCursor.Y + pad.Y));
ImGui.BeginGroup();
draw();
ImGui.EndGroup();
ImGui.PopID();
var contentMin = ImGui.GetItemRectMin();
var contentMax = ImGui.GetItemRectMax();
var cardMin = contentMin - pad;
var cardMax = contentMax + pad;
var outerMin = cardMin;
var outerMax = cardMax;
if (stretchWidth)
{
var windowPos = ImGui.GetWindowPos();
var regionMin = ImGui.GetWindowContentRegionMin();
var regionMax = ImGui.GetWindowContentRegionMax();
var scrollX = ImGui.GetScrollX();
cardMin.X = windowPos.X + regionMin.X + scrollX;
cardMax.X = windowPos.X + regionMax.X + scrollX;
outerMin.X = cardMin.X;
outerMax.X = cardMax.X;
startCursor.X = ImGui.GetWindowContentRegionMin().X;
}
var drawMin = new Vector2(cardMin.X + borderInset, cardMin.Y + borderInset);
var drawMax = new Vector2(cardMax.X - borderInset, cardMax.Y - borderInset);
var clipMin = drawList.GetClipRectMin();
var clipMax = drawList.GetClipRectMax();
var clipInset = new Vector2(borderThickness * 0.5f + 0.5f, borderThickness * 0.5f + 0.5f);
drawMin = Vector2.Max(drawMin, clipMin + clipInset);
drawMax = Vector2.Min(drawMax, clipMax - clipInset);
if (drawMax.X <= drawMin.X)
{
drawMax.X = drawMin.X + borderThickness;
}
if (drawMax.Y <= drawMin.Y)
{
drawMax.Y = drawMin.Y + borderThickness;
}
drawList.ChannelsSetCurrent(0);
drawList.AddRectFilled(drawMin, drawMax, ImGui.ColorConvertFloat4ToU32(cardBg), cardRounding);
if (cardBorder.W > 0f && borderThickness > 0f)
{
drawList.AddRect(drawMin, drawMax, ImGui.ColorConvertFloat4ToU32(cardBorder), cardRounding, ImDrawFlags.None, borderThickness);
}
drawList.ChannelsMerge();
ImGui.SetCursorPos(startCursor);
var dummyWidth = outerMax.X - outerMin.X;
var dummyHeight = outerMax.Y - outerMin.Y;
ImGui.Dummy(new Vector2(dummyWidth, dummyHeight));
ImGui.SetCursorPos(new Vector2(startCursor.X, startCursor.Y + dummyHeight));
if (!stretchWidth)
{
ImGui.SetCursorPosX(originalCursor.X);
}
else
{
ImGui.SetCursorPosX(startCursor.X);
}
}
public static bool DrawArrowToggle(ref bool state, string id)
{
var framePadding = ImGui.GetStyle().FramePadding;
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(framePadding.X, framePadding.Y * 0.85f));
ImGui.PushStyleColor(ImGuiCol.Button, Vector4.Zero);
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(1f, 1f, 1f, 0.08f));
ImGui.PushStyleColor(ImGuiCol.ButtonActive, new Vector4(1f, 1f, 1f, 0.16f));
bool clicked = ImGui.ArrowButton(id, state ? ImGuiDir.Down : ImGuiDir.Right);
ImGui.PopStyleColor(3);
ImGui.PopStyleVar();
if (clicked)
{
state = !state;
}
return state;
} }
public static void DrawGroupedCenteredColorText(string text, Vector4 color, float? maxWidth = null) public static void DrawGroupedCenteredColorText(string text, Vector4 color, float? maxWidth = null)