updated layout and adjusted scanning

This commit is contained in:
2025-09-25 06:06:19 +09:00
parent 7569b15993
commit e8f8512cdd
4 changed files with 148 additions and 111 deletions

View File

@@ -28,11 +28,14 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
private readonly CancellationTokenSource _cleanupCts = new(); private readonly CancellationTokenSource _cleanupCts = new();
private Task? _cleanupTask; private Task? _cleanupTask;
private int _checkEveryFrames = 20;
private int _frameCounter = 0; private int _frameCounter = 0;
private int _lookupsThisFrame = 0; private int _lookupsThisFrame = 0;
private const int MaxLookupsPerFrame = 15; private const int MaxLookupsPerFrame = 30;
private const int MaxQueueSize = 100; private const int MaxQueueSize = 100;
private volatile bool _batchRunning = false;
public IReadOnlyDictionary<string, BroadcastEntry> BroadcastCache => _broadcastCache; public IReadOnlyDictionary<string, BroadcastEntry> BroadcastCache => _broadcastCache;
public readonly record struct BroadcastEntry(bool IsBroadcasting, DateTime ExpiryTime, string? GID); public readonly record struct BroadcastEntry(bool IsBroadcasting, DateTime ExpiryTime, string? GID);
@@ -85,7 +88,7 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
_lookupQueue.Enqueue(cid); _lookupQueue.Enqueue(cid);
} }
if (_frameCounter % 2 == 0 && _lookupQueue.Count > 0) if (_frameCounter % _checkEveryFrames == 0 && _lookupQueue.Count > 0)
{ {
var cidsToLookup = new List<string>(); var cidsToLookup = new List<string>();
while (_lookupQueue.Count > 0 && _lookupsThisFrame < MaxLookupsPerFrame) while (_lookupQueue.Count > 0 && _lookupsThisFrame < MaxLookupsPerFrame)
@@ -96,8 +99,11 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
_lookupsThisFrame++; _lookupsThisFrame++;
} }
if (cidsToLookup.Count > 0) if (cidsToLookup.Count > 0 && !_batchRunning)
_ = BatchUpdateBroadcastCacheAsync(cidsToLookup); {
_batchRunning = true;
_ = BatchUpdateBroadcastCacheAsync(cidsToLookup).ContinueWith(_ => _batchRunning = false);
}
} }
} }

View File

@@ -139,89 +139,6 @@ public class CompactUi : WindowMediatorSubscriberBase
ImGui.EndTooltip(); ImGui.EndTooltip();
} }
}, },
new TitleBarButton()
{
Icon = FontAwesomeIcon.TowerCell,
Click = (_) =>
{
Mediator.Publish(new UiToggleMessage(typeof(BroadcastUI)));
},
IconOffset = new(2, 1),
ShowTooltip = () =>
{
ImGui.BeginTooltip();
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("PairBlue"));
ImGui.Text("Lightfinder");
ImGui.PopStyleColor();
ImGui.Text("This lets other Lightless users know you use Lightless.");
ImGui.Text("By enabling this, the server will allow other people to see that you are using Lightless.");
ImGui.Text("When disabled, pairing is still possible but both parties need to mutually send each other requests, receiving party will not be notified about the request unless the pairing is complete.");
ImGui.Text("At no point ever, even when Lightfinder is active that any Lightless data is getting sent to other people (including ID's), the server keeps this to itself.");
ImGui.Text("You can request to pair by right-clicking any (not yourself) character and using 'Send Pair Request'.");
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed"));
ImGui.Text("Use it only when you want to be visible.");
ImGui.PopStyleColor();
ImGuiHelpers.ScaledDummy(0.2f);
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
if (_configService.Current.BroadcastEnabled)
{
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("LightlessGreen"));
ImGui.Text("The Lightfinder calls, and somewhere, a soul may answer."); // cringe..
ImGui.PopStyleColor();
var ttl = _broadcastService.RemainingTtl;
if (ttl is { } remaining && remaining > TimeSpan.Zero)
{
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("LightlessYellow"));
ImGui.Text($"Still shining, for {remaining:hh\\:mm\\:ss}");
ImGui.PopStyleColor();
}
else
{
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed"));
ImGui.Text("The Lightfinder's light wanes, but not in vain."); // cringe..
ImGui.PopStyleColor();
}
}
else
{
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed"));
ImGui.Text("The Lightfinder rests, waiting to shine again."); // cringe..
ImGui.PopStyleColor();
}
var cooldown = _broadcastService.RemainingCooldown;
if (cooldown is { } cd)
{
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed"));
ImGui.Text($"The Lightfinder gathers its strength... ({Math.Ceiling(cd.TotalSeconds)}s)");
ImGui.PopStyleColor();
}
ImGui.EndTooltip();
}
},
new TitleBarButton()
{
Icon = FontAwesomeIcon.NetworkWired,
Click = (msg) =>
{
Mediator.Publish(new UiToggleMessage(typeof(SyncshellFinderUI)));
},
IconOffset = new(2,1),
ShowTooltip = () =>
{
ImGui.BeginTooltip();
ImGui.Text("Nearby Syncshells");
ImGui.EndTooltip();
}
}
}; };
_drawFolders = [.. GetDrawFolders()]; _drawFolders = [.. GetDrawFolders()];
@@ -518,18 +435,102 @@ public class CompactUi : WindowMediatorSubscriberBase
//Getting information of character and triangles threshold to show overlimit status in UID bar. //Getting information of character and triangles threshold to show overlimit status in UID bar.
_cachedAnalysis = _characterAnalyzer.LastAnalysis.DeepClone(); _cachedAnalysis = _characterAnalyzer.LastAnalysis.DeepClone();
Vector2 uidTextSize, iconSize;
using (_uiSharedService.UidFont.Push()) using (_uiSharedService.UidFont.Push())
uidTextSize = ImGui.CalcTextSize(uidText);
using (_uiSharedService.IconFont.Push())
iconSize = ImGui.CalcTextSize(FontAwesomeIcon.PersonCirclePlus.ToIconString());
float contentWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
float uidStartX = (contentWidth - uidTextSize.X) / 2f;
float cursorY = ImGui.GetCursorPosY();
if (_configService.Current.BroadcastEnabled)
{ {
var uidTextSize = ImGui.CalcTextSize(uidText); float iconYOffset = (uidTextSize.Y - iconSize.Y) * 0.5f;
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X) / 2 - (uidTextSize.X / 2)); var buttonSize = new Vector2(iconSize.X, uidTextSize.Y);
ImGui.TextColored(GetUidColor(), uidText);
ImGui.SetCursorPos(new Vector2(ImGui.GetStyle().ItemSpacing.X + 5f, cursorY));
ImGui.InvisibleButton("BroadcastIcon", buttonSize);
var iconPos = ImGui.GetItemRectMin() + new Vector2(0f, iconYOffset);
using (_uiSharedService.IconFont.Push())
ImGui.GetWindowDrawList().AddText(iconPos, ImGui.GetColorU32(UIColors.Get("LightlessGreen")), FontAwesomeIcon.PersonCirclePlus.ToIconString());
if (ImGui.IsItemHovered())
{
ImGui.BeginTooltip();
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("PairBlue"));
ImGui.Text("Lightfinder");
ImGui.PopStyleColor();
ImGui.Text("This lets other Lightless users know you use Lightless.");
ImGui.Text("By enabling this, the server will allow other people to see that you are using Lightless.");
ImGui.Text("When disabled, pairing is still possible but both parties need to mutually send each other requests, receiving party will not be notified about the request unless the pairing is complete.");
ImGui.Text("At no point ever, even when Lightfinder is active that any Lightless data is getting sent to other people (including ID's), the server keeps this to itself.");
ImGui.Text("You can request to pair by right-clicking any (not yourself) character and using 'Send Pair Request'.");
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed"));
ImGui.Text("Use it only when you want to be visible.");
ImGui.PopStyleColor();
ImGuiHelpers.ScaledDummy(0.2f);
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
if (_configService.Current.BroadcastEnabled)
{
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("LightlessGreen"));
ImGui.Text("The Lightfinder calls, and somewhere, a soul may answer."); // cringe..
ImGui.PopStyleColor();
var ttl = _broadcastService.RemainingTtl;
if (ttl is { } remaining && remaining > TimeSpan.Zero)
{
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("LightlessYellow"));
ImGui.Text($"Still shining, for {remaining:hh\\:mm\\:ss}");
ImGui.PopStyleColor();
}
else
{
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed"));
ImGui.Text("The Lightfinder's light wanes, but not in vain."); // cringe..
ImGui.PopStyleColor();
}
}
else
{
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed"));
ImGui.Text("The Lightfinder rests, waiting to shine again."); // cringe..
ImGui.PopStyleColor();
}
var cooldown = _broadcastService.RemainingCooldown;
if (cooldown is { } cd)
{
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed"));
ImGui.Text($"The Lightfinder gathers its strength... ({Math.Ceiling(cd.TotalSeconds)}s)");
ImGui.PopStyleColor();
}
ImGui.EndTooltip();
}
if (ImGui.IsItemClicked())
_lightlessMediator.Publish(new UiToggleMessage(typeof(BroadcastUI)));
} }
UiSharedService.AttachToolTip("Click to copy"); ImGui.SetCursorPosY(cursorY);
if (ImGui.IsItemClicked()) ImGui.SetCursorPosX(uidStartX);
using (_uiSharedService.UidFont.Push())
{ {
ImGui.SetClipboardText(uidText); ImGui.TextColored(GetUidColor(), uidText);
if (ImGui.IsItemClicked())
ImGui.SetClipboardText(uidText);
} }
UiSharedService.AttachToolTip("Click to copy");
if (_cachedAnalysis != null && _apiController.ServerState is ServerState.Connected) if (_cachedAnalysis != null && _apiController.ServerState is ServerState.Connected)
{ {

View File

@@ -39,7 +39,7 @@ public class TopTabMenu
None, None,
Individual, Individual,
Syncshell, Syncshell,
Filter, Lightfinder,
UserConfig UserConfig
} }
@@ -60,11 +60,6 @@ public class TopTabMenu
{ {
get => _selectedTab; set get => _selectedTab; set
{ {
if (_selectedTab == SelectedTab.Filter && value != SelectedTab.Filter)
{
Filter = string.Empty;
}
_selectedTab = value; _selectedTab = value;
} }
} }
@@ -76,7 +71,7 @@ public class TopTabMenu
var buttonY = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Pause).Y; var buttonY = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Pause).Y;
var buttonSize = new Vector2(buttonX, buttonY); var buttonSize = new Vector2(buttonX, buttonY);
var drawList = ImGui.GetWindowDrawList(); var drawList = ImGui.GetWindowDrawList();
var underlineColor = ImGui.GetColorU32(ImGuiCol.Separator); var underlineColor = ImGui.GetColorU32(UIColors.Get("LightlessPurpleActive")); // ImGui.GetColorU32(ImGuiCol.Separator);
var btncolor = ImRaii.PushColor(ImGuiCol.Button, ImGui.ColorConvertFloat4ToU32(new(0, 0, 0, 0))); var btncolor = ImRaii.PushColor(ImGuiCol.Button, ImGui.ColorConvertFloat4ToU32(new(0, 0, 0, 0)));
ImGuiHelpers.ScaledDummy(spacing.Y / 2f); ImGuiHelpers.ScaledDummy(spacing.Y / 2f);
@@ -117,19 +112,19 @@ public class TopTabMenu
using (ImRaii.PushFont(UiBuilder.IconFont)) using (ImRaii.PushFont(UiBuilder.IconFont))
{ {
var x = ImGui.GetCursorScreenPos(); var x = ImGui.GetCursorScreenPos();
if (ImGui.Button(FontAwesomeIcon.Filter.ToIconString(), buttonSize)) if (ImGui.Button(FontAwesomeIcon.Compass.ToIconString(), buttonSize))
{ {
TabSelection = TabSelection == SelectedTab.Filter ? SelectedTab.None : SelectedTab.Filter; TabSelection = TabSelection == SelectedTab.Lightfinder ? SelectedTab.None : SelectedTab.Lightfinder;
} }
ImGui.SameLine(); ImGui.SameLine();
var xAfter = ImGui.GetCursorScreenPos(); var xAfter = ImGui.GetCursorScreenPos();
if (TabSelection == SelectedTab.Filter) if (TabSelection == SelectedTab.Lightfinder)
drawList.AddLine(x with { Y = x.Y + buttonSize.Y + spacing.Y }, 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 }, xAfter with { Y = xAfter.Y + buttonSize.Y + spacing.Y, X = xAfter.X - spacing.X },
underlineColor, 2); underlineColor, 2);
} }
UiSharedService.AttachToolTip("Filter"); UiSharedService.AttachToolTip("Lightfinder");
ImGui.SameLine(); ImGui.SameLine();
using (ImRaii.PushFont(UiBuilder.IconFont)) using (ImRaii.PushFont(UiBuilder.IconFont))
@@ -164,9 +159,9 @@ public class TopTabMenu
DrawSyncshellMenu(availableWidth, spacing.X); DrawSyncshellMenu(availableWidth, spacing.X);
DrawGlobalSyncshellButtons(availableWidth, spacing.X); DrawGlobalSyncshellButtons(availableWidth, spacing.X);
} }
else if (TabSelection == SelectedTab.Filter) else if (TabSelection == SelectedTab.Lightfinder)
{ {
DrawFilter(availableWidth, spacing.X); DrawLightfinderMenu(availableWidth, spacing.X);
} }
else if (TabSelection == SelectedTab.UserConfig) else if (TabSelection == SelectedTab.UserConfig)
{ {
@@ -175,6 +170,8 @@ public class TopTabMenu
if (TabSelection != SelectedTab.None) ImGuiHelpers.ScaledDummy(3f); if (TabSelection != SelectedTab.None) ImGuiHelpers.ScaledDummy(3f);
ImGui.Separator(); ImGui.Separator();
DrawFilter(availableWidth, spacing.X);
} }
private void DrawAddPair(float availableXWidth, float spacingX) private void DrawAddPair(float availableXWidth, float spacingX)
@@ -483,6 +480,23 @@ public class TopTabMenu
} }
} }
private void DrawLightfinderMenu(float availableWidth, float spacingX)
{
var buttonX = (availableWidth - (spacingX)) / 2f;
if (_uiSharedService.IconTextButton(FontAwesomeIcon.PersonCirclePlus, "Lightfinder", buttonX, center: true))
{
_lightlessMediator.Publish(new UiToggleMessage(typeof(BroadcastUI)));
}
ImGui.SameLine();
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Globe, "Syncshell Finder", buttonX, center: true))
{
_lightlessMediator.Publish(new UiToggleMessage(typeof(SyncshellFinderUI)));
}
}
private void DrawUserConfig(float availableWidth, float spacingX) private void DrawUserConfig(float availableWidth, float spacingX)
{ {
var buttonX = (availableWidth - spacingX) / 2f; var buttonX = (availableWidth - spacingX) / 2f;

View File

@@ -1144,11 +1144,11 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
IconText(icon, color == null ? ImGui.GetColorU32(ImGuiCol.Text) : ImGui.GetColorU32(color.Value)); IconText(icon, color == null ? ImGui.GetColorU32(ImGuiCol.Text) : ImGui.GetColorU32(color.Value));
} }
public bool IconTextButton(FontAwesomeIcon icon, string text, float? width = null, bool isInPopup = false) public bool IconTextButton(FontAwesomeIcon icon, string text, float? width = null, bool isInPopup = false, bool? center = null)
{ {
return IconTextButtonInternal(icon, text, return IconTextButtonInternal(icon, text,
isInPopup ? ColorHelpers.RgbaUintToVector4(ImGui.GetColorU32(ImGuiCol.PopupBg)) : null, isInPopup ? ColorHelpers.RgbaUintToVector4(ImGui.GetColorU32(ImGuiCol.PopupBg)) : null,
width <= 0 ? null : width); width <= 0 ? null : width, center);
} }
public IDalamudTextureWrap LoadImage(byte[] imageData) public IDalamudTextureWrap LoadImage(byte[] imageData)
@@ -1212,7 +1212,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
ImGui.TextUnformatted(text); ImGui.TextUnformatted(text);
} }
private bool IconTextButtonInternal(FontAwesomeIcon icon, string text, Vector4? defaultColor = null, float? width = null) private bool IconTextButtonInternal(FontAwesomeIcon icon, string text, Vector4? defaultColor = null, float? width = null, bool? center = null)
{ {
int num = 0; int num = 0;
if (defaultColor.HasValue) if (defaultColor.HasValue)
@@ -1222,19 +1222,35 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
} }
ImGui.PushID(text); ImGui.PushID(text);
Vector2 vector; Vector2 vector;
using (IconFont.Push()) using (IconFont.Push())
vector = ImGui.CalcTextSize(icon.ToIconString()); vector = ImGui.CalcTextSize(icon.ToIconString());
Vector2 vector2 = ImGui.CalcTextSize(text); Vector2 vector2 = ImGui.CalcTextSize(text);
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float num2 = 3f * ImGuiHelpers.GlobalScale; float num2 = 3f * ImGuiHelpers.GlobalScale;
float x = width ?? vector.X + vector2.X + ImGui.GetStyle().FramePadding.X * 2f + num2;
float totalTextWidth = vector.X + num2 + vector2.X;
float x = width ?? totalTextWidth + ImGui.GetStyle().FramePadding.X * 2f;
float frameHeight = ImGui.GetFrameHeight(); float frameHeight = ImGui.GetFrameHeight();
bool result = ImGui.Button(string.Empty, new Vector2(x, frameHeight)); bool result = ImGui.Button(string.Empty, new Vector2(x, frameHeight));
Vector2 pos = new Vector2(cursorScreenPos.X + ImGui.GetStyle().FramePadding.X, cursorScreenPos.Y + ImGui.GetStyle().FramePadding.Y);
bool shouldCenter = center == true;
Vector2 pos = shouldCenter
? new Vector2(
cursorScreenPos.X + (x - totalTextWidth) / 2f,
cursorScreenPos.Y + (frameHeight - vector.Y) / 2f)
: new Vector2(
cursorScreenPos.X + ImGui.GetStyle().FramePadding.X,
cursorScreenPos.Y + ImGui.GetStyle().FramePadding.Y);
using (IconFont.Push()) using (IconFont.Push())
windowDrawList.AddText(pos, ImGui.GetColorU32(ImGuiCol.Text), icon.ToIconString()); windowDrawList.AddText(pos, ImGui.GetColorU32(ImGuiCol.Text), icon.ToIconString());
Vector2 pos2 = new Vector2(pos.X + vector.X + num2, cursorScreenPos.Y + ImGui.GetStyle().FramePadding.Y); Vector2 pos2 = new Vector2(pos.X + vector.X + num2, cursorScreenPos.Y + ImGui.GetStyle().FramePadding.Y);
windowDrawList.AddText(pos2, ImGui.GetColorU32(ImGuiCol.Text), text); windowDrawList.AddText(pos2, ImGui.GetColorU32(ImGuiCol.Text), text);
ImGui.PopID(); ImGui.PopID();