add info options for server bar, direct settings button in lightfinder window and fix color swaps
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Utility;
|
||||
@@ -252,12 +253,27 @@ namespace LightlessSync.UI
|
||||
_broadcastService.ToggleBroadcast();
|
||||
}
|
||||
|
||||
var toggleButtonHeight = ImGui.GetItemRectSize().Y;
|
||||
|
||||
if (isOnCooldown || !_broadcastService.IsLightFinderAvailable)
|
||||
ImGui.EndDisabled();
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
ImGui.SameLine();
|
||||
if (_uiSharedService.IconButton(FontAwesomeIcon.Cog, toggleButtonHeight))
|
||||
{
|
||||
Mediator.Publish(new OpenLightfinderSettingsMessage());
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.BeginTooltip();
|
||||
ImGui.TextUnformatted("Open Lightfinder settings.");
|
||||
ImGui.EndTooltip();
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ using LightlessSync.Services.Mediator;
|
||||
using LightlessSync.Services.ServerConfiguration;
|
||||
using LightlessSync.WebAPI;
|
||||
using LightlessSync.WebAPI.SignalR.Utils;
|
||||
using LightlessSync.Utils;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -19,6 +20,9 @@ namespace LightlessSync.UI;
|
||||
|
||||
public sealed class DtrEntry : IDisposable, IHostedService
|
||||
{
|
||||
private static readonly TimeSpan _localHashedCidCacheDuration = TimeSpan.FromMinutes(2);
|
||||
private static readonly TimeSpan _localHashedCidErrorCooldown = TimeSpan.FromMinutes(1);
|
||||
|
||||
private readonly ApiController _apiController;
|
||||
private readonly ServerConfigurationManager _serverManager;
|
||||
private readonly CancellationTokenSource _cancellationTokenSource = new();
|
||||
@@ -28,8 +32,11 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
private readonly Lazy<IDtrBarEntry> _lightfinderEntry;
|
||||
private readonly ILogger<DtrEntry> _logger;
|
||||
private readonly BroadcastService _broadcastService;
|
||||
private readonly BroadcastScannerService _broadcastScannerService;
|
||||
private readonly LightlessMediator _lightlessMediator;
|
||||
private readonly PairManager _pairManager;
|
||||
private readonly PairRequestService _pairRequestService;
|
||||
private readonly DalamudUtilService _dalamudUtilService;
|
||||
private Task? _runTask;
|
||||
private string? _statusText;
|
||||
private string? _statusTooltip;
|
||||
@@ -37,6 +44,10 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
private string? _lightfinderText;
|
||||
private string? _lightfinderTooltip;
|
||||
private Colors _lightfinderColors;
|
||||
private string? _localHashedCid;
|
||||
private DateTime _localHashedCidFetchedAt = DateTime.MinValue;
|
||||
private DateTime _localHashedCidNextErrorLog = DateTime.MinValue;
|
||||
private DateTime _pairRequestNextErrorLog = DateTime.MinValue;
|
||||
|
||||
public DtrEntry(
|
||||
ILogger<DtrEntry> logger,
|
||||
@@ -44,9 +55,12 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
ConfigurationServiceBase<LightlessConfig> configService,
|
||||
LightlessMediator lightlessMediator,
|
||||
PairManager pairManager,
|
||||
PairRequestService pairRequestService,
|
||||
ApiController apiController,
|
||||
ServerConfigurationManager serverManager,
|
||||
BroadcastService broadcastService)
|
||||
BroadcastService broadcastService,
|
||||
BroadcastScannerService broadcastScannerService,
|
||||
DalamudUtilService dalamudUtilService)
|
||||
{
|
||||
_logger = logger;
|
||||
_dtrBar = dtrBar;
|
||||
@@ -55,9 +69,12 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
_configService = configService;
|
||||
_lightlessMediator = lightlessMediator;
|
||||
_pairManager = pairManager;
|
||||
_pairRequestService = pairRequestService;
|
||||
_apiController = apiController;
|
||||
_serverManager = serverManager;
|
||||
_broadcastService = broadcastService;
|
||||
_broadcastScannerService = broadcastScannerService;
|
||||
_dalamudUtilService = dalamudUtilService;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -318,27 +335,99 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
}
|
||||
}
|
||||
|
||||
private string? GetLocalHashedCid()
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
if (_localHashedCid is not null && now - _localHashedCidFetchedAt < _localHashedCidCacheDuration)
|
||||
return _localHashedCid;
|
||||
|
||||
try
|
||||
{
|
||||
var cid = _dalamudUtilService.GetCIDAsync().GetAwaiter().GetResult();
|
||||
var hashedCid = cid.ToString().GetHash256();
|
||||
_localHashedCid = hashedCid;
|
||||
_localHashedCidFetchedAt = now;
|
||||
return hashedCid;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (now >= _localHashedCidNextErrorLog)
|
||||
{
|
||||
_logger.LogDebug(ex, "Failed to refresh local hashed CID for Lightfinder DTR entry.");
|
||||
_localHashedCidNextErrorLog = now + _localHashedCidErrorCooldown;
|
||||
}
|
||||
|
||||
_localHashedCid = null;
|
||||
_localHashedCidFetchedAt = now;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private int GetNearbyBroadcastCount()
|
||||
{
|
||||
var localHashedCid = GetLocalHashedCid();
|
||||
return _broadcastScannerService.CountActiveBroadcasts(
|
||||
string.IsNullOrEmpty(localHashedCid) ? null : localHashedCid);
|
||||
}
|
||||
|
||||
private int GetPendingPairRequestCount()
|
||||
{
|
||||
try
|
||||
{
|
||||
return _pairRequestService.GetActiveRequests().Count;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
if (now >= _pairRequestNextErrorLog)
|
||||
{
|
||||
_logger.LogDebug(ex, "Failed to retrieve pair request count for Lightfinder DTR entry.");
|
||||
_pairRequestNextErrorLog = now + _localHashedCidErrorCooldown;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private (string Text, Colors Colors, string Tooltip) BuildLightfinderIndicator()
|
||||
{
|
||||
var config = _configService.Current;
|
||||
const string icon = "\uE048";
|
||||
if (!_broadcastService.IsLightFinderAvailable)
|
||||
{
|
||||
return ($"{icon} --", config.DtrColorsLightfinderUnavailable, "Lightfinder - Unavailable on this server.");
|
||||
return ($"{icon} --", SwapColorChannels(config.DtrColorsLightfinderUnavailable), "Lightfinder - Unavailable on this server.");
|
||||
}
|
||||
|
||||
if (_broadcastService.IsBroadcasting)
|
||||
{
|
||||
return ($"{icon} ON", config.DtrColorsLightfinderEnabled, "Lightfinder - Enabled");
|
||||
var tooltipBuilder = new StringBuilder("Lightfinder - Enabled");
|
||||
|
||||
switch (config.LightfinderDtrDisplayMode)
|
||||
{
|
||||
case LightfinderDtrDisplayMode.PendingPairRequests:
|
||||
{
|
||||
var requestCount = GetPendingPairRequestCount();
|
||||
tooltipBuilder.AppendLine();
|
||||
tooltipBuilder.Append("Pending pair requests: ").Append(requestCount);
|
||||
return ($"{icon} Requests {requestCount}", SwapColorChannels(config.DtrColorsLightfinderEnabled), tooltipBuilder.ToString());
|
||||
}
|
||||
default:
|
||||
{
|
||||
var broadcastCount = GetNearbyBroadcastCount();
|
||||
tooltipBuilder.AppendLine();
|
||||
tooltipBuilder.Append("Nearby Lightfinder users: ").Append(broadcastCount);
|
||||
return ($"{icon} {broadcastCount}", SwapColorChannels(config.DtrColorsLightfinderEnabled), tooltipBuilder.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var tooltip = new StringBuilder("Lightfinder - Disabled");
|
||||
var colors = config.DtrColorsLightfinderDisabled;
|
||||
var colors = SwapColorChannels(config.DtrColorsLightfinderDisabled);
|
||||
if (_broadcastService.RemainingCooldown is { } cooldown && cooldown > TimeSpan.Zero)
|
||||
{
|
||||
tooltip.AppendLine();
|
||||
tooltip.Append("Cooldown: ").Append(Math.Ceiling(cooldown.TotalSeconds)).Append("s");
|
||||
colors = config.DtrColorsLightfinderCooldown;
|
||||
colors = SwapColorChannels(config.DtrColorsLightfinderCooldown);
|
||||
}
|
||||
|
||||
return ($"{icon} OFF", colors, tooltip.ToString());
|
||||
@@ -377,6 +466,17 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
private const byte _colorTypeForeground = 0x13;
|
||||
private const byte _colorTypeGlow = 0x14;
|
||||
|
||||
private static Colors SwapColorChannels(Colors colors)
|
||||
=> new(SwapColorComponent(colors.Foreground), SwapColorComponent(colors.Glow));
|
||||
|
||||
private static uint SwapColorComponent(uint color)
|
||||
{
|
||||
if (color == 0)
|
||||
return 0;
|
||||
|
||||
return ((color & 0xFFu) << 16) | (color & 0xFF00u) | ((color >> 16) & 0xFFu);
|
||||
}
|
||||
|
||||
private static SeString BuildColoredSeString(string text, Colors colors)
|
||||
{
|
||||
var ssb = new SeStringBuilder();
|
||||
@@ -385,7 +485,16 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
}
|
||||
|
||||
private static RawPayload BuildColorStartPayload(byte colorType, uint color)
|
||||
=> new(unchecked([0x02, colorType, 0x05, 0xF6, byte.Max((byte)color, 0x01), byte.Max((byte)(color >> 8), 0x01), byte.Max((byte)(color >> 16), 0x01), 0x03]));
|
||||
=> new(unchecked([
|
||||
0x02,
|
||||
colorType,
|
||||
0x05,
|
||||
0xF6,
|
||||
byte.Max((byte)color, (byte)0x01),
|
||||
byte.Max((byte)(color >> 8), (byte)0x01),
|
||||
byte.Max((byte)(color >> 16), (byte)0x01),
|
||||
0x03
|
||||
]));
|
||||
|
||||
private static RawPayload BuildColorEndPayload(byte colorType)
|
||||
=> new([0x02, colorType, 0x02, 0xEC, 0x03]);
|
||||
|
||||
@@ -73,6 +73,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
private string _lightfinderIconInput = string.Empty;
|
||||
private bool _lightfinderIconInputInitialized = false;
|
||||
private int _lightfinderIconPresetIndex = -1;
|
||||
private bool _selectGeneralTabOnNextDraw = false;
|
||||
private bool _openLightfinderSectionOnNextDraw = false;
|
||||
private static readonly (string Label, SeIconChar Icon)[] LightfinderIconPresets = new[]
|
||||
{
|
||||
("Link Marker", SeIconChar.LinkMarker),
|
||||
@@ -136,6 +138,12 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
};
|
||||
|
||||
Mediator.Subscribe<OpenSettingsUiMessage>(this, (_) => Toggle());
|
||||
Mediator.Subscribe<OpenLightfinderSettingsMessage>(this, (_) =>
|
||||
{
|
||||
IsOpen = true;
|
||||
_selectGeneralTabOnNextDraw = true;
|
||||
_openLightfinderSectionOnNextDraw = true;
|
||||
});
|
||||
Mediator.Subscribe<SwitchToIntroUiMessage>(this, (_) => IsOpen = false);
|
||||
Mediator.Subscribe<CutsceneStartMessage>(this, (_) => UiSharedService_GposeStart());
|
||||
Mediator.Subscribe<CutsceneEndMessage>(this, (_) => UiSharedService_GposeEnd());
|
||||
@@ -222,6 +230,17 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private static DtrEntry.Colors SwapColorChannels(DtrEntry.Colors colors)
|
||||
=> new(SwapColorChannels(colors.Foreground), SwapColorChannels(colors.Glow));
|
||||
|
||||
private static uint SwapColorChannels(uint color)
|
||||
{
|
||||
if (color == 0)
|
||||
return 0;
|
||||
|
||||
return ((color & 0xFFu) << 16) | (color & 0xFF00u) | ((color >> 16) & 0xFFu);
|
||||
}
|
||||
|
||||
private void DrawBlockedTransfers()
|
||||
{
|
||||
_lastTab = "BlockedTransfers";
|
||||
@@ -1081,18 +1100,31 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
var forceOpenLightfinder = _openLightfinderSectionOnNextDraw;
|
||||
if (_openLightfinderSectionOnNextDraw)
|
||||
{
|
||||
ImGui.SetNextItemOpen(true, ImGuiCond.Always);
|
||||
}
|
||||
|
||||
if (_uiShared.MediumTreeNode("Lightfinder", UIColors.Get("LightlessPurple")))
|
||||
{
|
||||
if (forceOpenLightfinder)
|
||||
{
|
||||
ImGui.SetScrollHereY();
|
||||
}
|
||||
|
||||
_openLightfinderSectionOnNextDraw = false;
|
||||
|
||||
bool autoEnable = _configService.Current.LightfinderAutoEnableOnConnect;
|
||||
var autoAlign = _configService.Current.LightfinderAutoAlign;
|
||||
var offsetX = (int)_configService.Current.LightfinderLabelOffsetX;
|
||||
var offsetY = (int)_configService.Current.LightfinderLabelOffsetY;
|
||||
var labelScale = _configService.Current.LightfinderLabelScale;
|
||||
bool showLightfinderInDtr = _configService.Current.ShowLightfinderInDtr;
|
||||
var dtrLightfinderEnabled = _configService.Current.DtrColorsLightfinderEnabled;
|
||||
var dtrLightfinderDisabled = _configService.Current.DtrColorsLightfinderDisabled;
|
||||
var dtrLightfinderCooldown = _configService.Current.DtrColorsLightfinderCooldown;
|
||||
var dtrLightfinderUnavailable = _configService.Current.DtrColorsLightfinderUnavailable;
|
||||
var dtrLightfinderEnabled = SwapColorChannels(_configService.Current.DtrColorsLightfinderEnabled);
|
||||
var dtrLightfinderDisabled = SwapColorChannels(_configService.Current.DtrColorsLightfinderDisabled);
|
||||
var dtrLightfinderCooldown = SwapColorChannels(_configService.Current.DtrColorsLightfinderCooldown);
|
||||
var dtrLightfinderUnavailable = SwapColorChannels(_configService.Current.DtrColorsLightfinderUnavailable);
|
||||
|
||||
ImGui.TextUnformatted("Connection");
|
||||
if (ImGui.Checkbox("Auto-enable Lightfinder on server connection", ref autoEnable))
|
||||
@@ -1112,6 +1144,40 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
_uiShared.DrawHelpText("Adds a Lightfinder status to the Server info bar. Left click toggles Lightfinder when visible.");
|
||||
|
||||
var lightfinderDisplayMode = _configService.Current.LightfinderDtrDisplayMode;
|
||||
var lightfinderDisplayLabel = lightfinderDisplayMode switch
|
||||
{
|
||||
LightfinderDtrDisplayMode.PendingPairRequests => "Pending pair requests",
|
||||
_ => "Nearby Lightfinder users",
|
||||
};
|
||||
|
||||
ImGui.BeginDisabled(!showLightfinderInDtr);
|
||||
if (ImGui.BeginCombo("Info display", lightfinderDisplayLabel))
|
||||
{
|
||||
foreach (var option in Enum.GetValues<LightfinderDtrDisplayMode>())
|
||||
{
|
||||
var optionLabel = option switch
|
||||
{
|
||||
LightfinderDtrDisplayMode.PendingPairRequests => "Pending pair requests",
|
||||
_ => "Nearby Lightfinder users",
|
||||
};
|
||||
|
||||
var selected = option == lightfinderDisplayMode;
|
||||
if (ImGui.Selectable(optionLabel, selected))
|
||||
{
|
||||
_configService.Current.LightfinderDtrDisplayMode = option;
|
||||
_configService.Save();
|
||||
}
|
||||
|
||||
if (selected)
|
||||
ImGui.SetItemDefaultFocus();
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
ImGui.EndDisabled();
|
||||
_uiShared.DrawHelpText("Choose what the Lightfinder info bar displays while Lightfinder is active.");
|
||||
|
||||
bool useLightfinderColors = _configService.Current.UseLightfinderColorsInDtr;
|
||||
if (ImGui.Checkbox("Color-code the Lightfinder info bar according to status", ref useLightfinderColors))
|
||||
{
|
||||
@@ -1120,24 +1186,24 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
|
||||
ImGui.BeginDisabled(!showLightfinderInDtr || !useLightfinderColors);
|
||||
if (InputDtrColors("Enables", ref dtrLightfinderEnabled))
|
||||
if (InputDtrColors("Enabled", ref dtrLightfinderEnabled))
|
||||
{
|
||||
_configService.Current.DtrColorsLightfinderEnabled = dtrLightfinderEnabled;
|
||||
_configService.Current.DtrColorsLightfinderEnabled = SwapColorChannels(dtrLightfinderEnabled);
|
||||
_configService.Save();
|
||||
}
|
||||
if (InputDtrColors("Disabled", ref dtrLightfinderDisabled))
|
||||
{
|
||||
_configService.Current.DtrColorsLightfinderDisabled = dtrLightfinderDisabled;
|
||||
_configService.Current.DtrColorsLightfinderDisabled = SwapColorChannels(dtrLightfinderDisabled);
|
||||
_configService.Save();
|
||||
}
|
||||
if (InputDtrColors("Cooldown", ref dtrLightfinderCooldown))
|
||||
{
|
||||
_configService.Current.DtrColorsLightfinderCooldown = dtrLightfinderCooldown;
|
||||
_configService.Current.DtrColorsLightfinderCooldown = SwapColorChannels(dtrLightfinderCooldown);
|
||||
_configService.Save();
|
||||
}
|
||||
if (InputDtrColors("Unavailable", ref dtrLightfinderUnavailable))
|
||||
{
|
||||
_configService.Current.DtrColorsLightfinderUnavailable = dtrLightfinderUnavailable;
|
||||
_configService.Current.DtrColorsLightfinderUnavailable = SwapColorChannels(dtrLightfinderUnavailable);
|
||||
_configService.Save();
|
||||
}
|
||||
ImGui.EndDisabled();
|
||||
@@ -2696,8 +2762,15 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.Separator();
|
||||
if (ImGui.BeginTabBar("mainTabBar"))
|
||||
{
|
||||
if (ImGui.BeginTabItem("General"))
|
||||
var generalTabFlags = ImGuiTabItemFlags.None;
|
||||
if (_selectGeneralTabOnNextDraw)
|
||||
{
|
||||
generalTabFlags |= ImGuiTabItemFlags.SetSelected;
|
||||
}
|
||||
|
||||
if (ImGui.BeginTabItem("General", generalTabFlags))
|
||||
{
|
||||
_selectGeneralTabOnNextDraw = false;
|
||||
DrawGeneral();
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user