rework lightfinder for new api

This commit is contained in:
azyges
2025-10-09 07:33:49 +09:00
parent 86107acf12
commit f01229a97f
11 changed files with 531 additions and 164 deletions

View File

@@ -1,10 +1,11 @@
using Dalamud.Game.Gui.Dtr;
using Dalamud.Game.Gui.Dtr;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Plugin.Services;
using LightlessSync.LightlessConfiguration;
using LightlessSync.LightlessConfiguration.Configurations;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.Services;
using LightlessSync.Services.Mediator;
using LightlessSync.Services.ServerConfiguration;
using LightlessSync.WebAPI;
@@ -12,6 +13,7 @@ using LightlessSync.WebAPI.SignalR.Utils;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Runtime.InteropServices;
using System.Text;
namespace LightlessSync.UI;
@@ -22,35 +24,52 @@ public sealed class DtrEntry : IDisposable, IHostedService
private readonly CancellationTokenSource _cancellationTokenSource = new();
private readonly ConfigurationServiceBase<LightlessConfig> _configService;
private readonly IDtrBar _dtrBar;
private readonly Lazy<IDtrBarEntry> _entry;
private readonly Lazy<IDtrBarEntry> _statusEntry;
private readonly Lazy<IDtrBarEntry> _lightfinderEntry;
private readonly ILogger<DtrEntry> _logger;
private readonly BroadcastService _broadcastService;
private readonly LightlessMediator _lightlessMediator;
private readonly PairManager _pairManager;
private Task? _runTask;
private string? _text;
private string? _tooltip;
private Colors _colors;
private string? _statusText;
private string? _statusTooltip;
private Colors _statusColors;
private string? _lightfinderText;
private string? _lightfinderTooltip;
private Colors _lightfinderColors;
public DtrEntry(ILogger<DtrEntry> logger, IDtrBar dtrBar, ConfigurationServiceBase<LightlessConfig> configService, LightlessMediator lightlessMediator, PairManager pairManager, ApiController apiController, ServerConfigurationManager serverManager)
public DtrEntry(
ILogger<DtrEntry> logger,
IDtrBar dtrBar,
ConfigurationServiceBase<LightlessConfig> configService,
LightlessMediator lightlessMediator,
PairManager pairManager,
ApiController apiController,
ServerConfigurationManager serverManager,
BroadcastService broadcastService)
{
_logger = logger;
_dtrBar = dtrBar;
_entry = new(CreateEntry);
_statusEntry = new(CreateStatusEntry);
_lightfinderEntry = new(CreateLightfinderEntry);
_configService = configService;
_lightlessMediator = lightlessMediator;
_pairManager = pairManager;
_apiController = apiController;
_serverManager = serverManager;
_broadcastService = broadcastService;
}
public void Dispose()
{
if (_entry.IsValueCreated)
if (_statusEntry.IsValueCreated)
{
_logger.LogDebug("Disposing DtrEntry");
Clear();
_entry.Value.Remove();
_statusEntry.Value.Remove();
}
if (_lightfinderEntry.IsValueCreated)
_lightfinderEntry.Value.Remove();
}
public Task StartAsync(CancellationToken cancellationToken)
@@ -70,7 +89,7 @@ public sealed class DtrEntry : IDisposable, IHostedService
}
catch (OperationCanceledException)
{
// ignore cancelled
}
finally
{
@@ -80,33 +99,66 @@ public sealed class DtrEntry : IDisposable, IHostedService
private void Clear()
{
if (!_entry.IsValueCreated) return;
_logger.LogInformation("Clearing entry");
_text = null;
_tooltip = null;
_colors = default;
_entry.Value.Shown = false;
HideStatusEntry();
HideLightfinderEntry();
}
private IDtrBarEntry CreateEntry()
private void HideStatusEntry()
{
_logger.LogTrace("Creating new DtrBar entry");
if (_statusEntry.IsValueCreated && _statusEntry.Value.Shown)
{
_logger.LogInformation("Hiding status entry");
_statusEntry.Value.Shown = false;
}
_statusText = null;
_statusTooltip = null;
_statusColors = default;
}
private void HideLightfinderEntry()
{
if (_lightfinderEntry.IsValueCreated && _lightfinderEntry.Value.Shown)
{
_logger.LogInformation("Hiding Lightfinder entry");
_lightfinderEntry.Value.Shown = false;
}
_lightfinderText = null;
_lightfinderTooltip = null;
_lightfinderColors = default;
}
private IDtrBarEntry CreateStatusEntry()
{
_logger.LogTrace("Creating status DtrBar entry");
var entry = _dtrBar.Get("Lightless Sync");
entry.OnClick = interactionEvent => OnClickEvent(interactionEvent);
entry.OnClick = interactionEvent => OnStatusEntryClick(interactionEvent);
return entry;
}
private void OnClickEvent(DtrInteractionEvent interactionEvent)
private IDtrBarEntry CreateLightfinderEntry()
{
if (interactionEvent.ClickType.Equals(MouseClickType.Left) && !interactionEvent.ModifierKeys.Equals(ClickModifierKeys.Shift))
_logger.LogTrace("Creating Lightfinder DtrBar entry");
var entry = _dtrBar.Get("Lightfinder");
entry.OnClick = interactionEvent => OnLightfinderEntryClick(interactionEvent);
return entry;
}
private void OnStatusEntryClick(DtrInteractionEvent interactionEvent)
{
if (interactionEvent.ClickType.Equals(MouseClickType.Left))
{
_lightlessMediator.Publish(new UiToggleMessage(typeof(CompactUi)));
}
else if (interactionEvent.ClickType.Equals(MouseClickType.Left) && interactionEvent.ModifierKeys.Equals(ClickModifierKeys.Shift))
{
_lightlessMediator.Publish(new UiToggleMessage(typeof(SettingsUi)));
if (interactionEvent.ModifierKeys.HasFlag(ClickModifierKeys.Shift))
{
_lightlessMediator.Publish(new UiToggleMessage(typeof(SettingsUi)));
}
else
{
_lightlessMediator.Publish(new UiToggleMessage(typeof(CompactUi)));
}
return;
}
if (interactionEvent.ClickType.Equals(MouseClickType.Right))
@@ -131,6 +183,17 @@ public sealed class DtrEntry : IDisposable, IHostedService
}
}
private void OnLightfinderEntryClick(DtrInteractionEvent interactionEvent)
{
if (!_configService.Current.ShowLightfinderInDtr)
return;
if (interactionEvent.ClickType.Equals(MouseClickType.Left))
{
_broadcastService.ToggleBroadcast();
}
}
private async Task RunAsync()
{
while (!_cancellationTokenSource.IsCancellationRequested)
@@ -143,73 +206,171 @@ public sealed class DtrEntry : IDisposable, IHostedService
private void Update()
{
if (!_configService.Current.EnableDtrEntry || !_configService.Current.HasValidSetup())
{
if (_entry.IsValueCreated && _entry.Value.Shown)
{
_logger.LogInformation("Disabling entry");
var config = _configService.Current;
Clear();
}
if (!config.HasValidSetup())
{
HideStatusEntry();
HideLightfinderEntry();
return;
}
if (!_entry.Value.Shown)
{
_logger.LogInformation("Showing entry");
_entry.Value.Shown = true;
}
if (config.EnableDtrEntry)
UpdateStatusEntry(config);
else
HideStatusEntry();
if (config.ShowLightfinderInDtr)
UpdateLightfinderEntry(config);
else
HideLightfinderEntry();
}
private void UpdateStatusEntry(LightlessConfig config)
{
string text;
string tooltip;
Colors colors;
if (_apiController.IsConnected)
{
var pairCount = _pairManager.GetVisibleUserCount();
text = $"\uE044 {pairCount}";
if (pairCount > 0)
{
IEnumerable<string> visiblePairs;
if (_configService.Current.ShowUidInDtrTooltip)
{
visiblePairs = _pairManager.GetOnlineUserPairs()
.Where(x => x.IsVisible)
.Select(x => string.Format("{0} ({1})", _configService.Current.PreferNoteInDtrTooltip ? x.GetNote() ?? x.PlayerName : x.PlayerName, x.UserData.AliasOrUID));
}
else
{
visiblePairs = _pairManager.GetOnlineUserPairs()
.Where(x => x.IsVisible)
.Select(x => string.Format("{0}", _configService.Current.PreferNoteInDtrTooltip ? x.GetNote() ?? x.PlayerName : x.PlayerName));
}
var preferNote = config.PreferNoteInDtrTooltip;
var showUid = config.ShowUidInDtrTooltip;
var visiblePairsQuery = _pairManager.GetOnlineUserPairs()
.Where(x => x.IsVisible);
IEnumerable<string> visiblePairs = showUid
? visiblePairsQuery.Select(x => string.Format("{0} ({1})", preferNote ? x.GetNote() ?? x.PlayerName : x.PlayerName, x.UserData.AliasOrUID))
: visiblePairsQuery.Select(x => string.Format("{0}", preferNote ? x.GetNote() ?? x.PlayerName : x.PlayerName));
tooltip = $"Lightless Sync: Connected{Environment.NewLine}----------{Environment.NewLine}{string.Join(Environment.NewLine, visiblePairs)}";
colors = _configService.Current.DtrColorsPairsInRange;
colors = config.DtrColorsPairsInRange;
}
else
{
tooltip = "Lightless Sync: Connected";
colors = _configService.Current.DtrColorsDefault;
colors = config.DtrColorsDefault;
}
}
else
{
text = "\uE044 \uE04C";
tooltip = "Lightless Sync: Not Connected";
colors = _configService.Current.DtrColorsNotConnected;
colors = config.DtrColorsNotConnected;
}
if (!_configService.Current.UseColorsInDtr)
if (!config.UseColorsInDtr)
colors = default;
if (!string.Equals(text, _text, StringComparison.Ordinal) || !string.Equals(tooltip, _tooltip, StringComparison.Ordinal) || colors != _colors)
var statusEntry = _statusEntry.Value;
if (!statusEntry.Shown)
{
_text = text;
_tooltip = tooltip;
_colors = colors;
_entry.Value.Text = BuildColoredSeString(text, colors);
_entry.Value.Tooltip = tooltip;
_logger.LogInformation("Showing status entry");
statusEntry.Shown = true;
}
bool statusNeedsUpdate =
!string.Equals(text, _statusText, StringComparison.Ordinal) ||
!string.Equals(tooltip, _statusTooltip, StringComparison.Ordinal) ||
colors != _statusColors;
if (statusNeedsUpdate)
{
statusEntry.Text = BuildColoredSeString(text, colors);
statusEntry.Tooltip = tooltip;
_statusText = text;
_statusTooltip = tooltip;
_statusColors = colors;
}
}
private void UpdateLightfinderEntry(LightlessConfig config)
{
var lightfinderEntry = _lightfinderEntry.Value;
if (!lightfinderEntry.Shown)
{
_logger.LogInformation("Showing Lightfinder entry");
lightfinderEntry.Shown = true;
}
var indicator = BuildLightfinderIndicator();
var lightfinderText = indicator.Text ?? string.Empty;
var lightfinderColors = config.UseLightfinderColorsInDtr ? indicator.Colors : default;
var lightfinderTooltip = BuildLightfinderTooltip(indicator.Tooltip);
bool lightfinderNeedsUpdate =
!string.Equals(lightfinderText, _lightfinderText, StringComparison.Ordinal) ||
!string.Equals(lightfinderTooltip, _lightfinderTooltip, StringComparison.Ordinal) ||
lightfinderColors != _lightfinderColors;
if (lightfinderNeedsUpdate)
{
lightfinderEntry.Text = BuildColoredSeString(lightfinderText, lightfinderColors);
lightfinderEntry.Tooltip = lightfinderTooltip;
_lightfinderText = lightfinderText;
_lightfinderTooltip = lightfinderTooltip;
_lightfinderColors = lightfinderColors;
}
}
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.");
}
if (_broadcastService.IsBroadcasting)
{
return ($"{icon} ON", config.DtrColorsLightfinderEnabled, "Lightfinder - Enabled");
}
var tooltip = new StringBuilder("Lightfinder - Disabled");
var colors = 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;
}
return ($"{icon} OFF", colors, tooltip.ToString());
}
private static string BuildLightfinderTooltip(string baseTooltip)
{
var builder = new StringBuilder();
if (!string.IsNullOrWhiteSpace(baseTooltip))
builder.Append(baseTooltip.TrimEnd());
else
builder.Append("Lightfinder status unavailable.");
return builder.ToString().TrimEnd();
}
private static void AppendColoredSegment(SeStringBuilder builder, string? text, Colors colors)
{
if (string.IsNullOrEmpty(text))
return;
if (colors.Foreground != default)
builder.Add(BuildColorStartPayload(_colorTypeForeground, colors.Foreground));
if (colors.Glow != default)
builder.Add(BuildColorStartPayload(_colorTypeGlow, colors.Glow));
builder.AddText(text);
if (colors.Glow != default)
builder.Add(BuildColorEndPayload(_colorTypeGlow));
if (colors.Foreground != default)
builder.Add(BuildColorEndPayload(_colorTypeForeground));
}
#region Colored SeString
@@ -219,15 +380,7 @@ public sealed class DtrEntry : IDisposable, IHostedService
private static SeString BuildColoredSeString(string text, Colors colors)
{
var ssb = new SeStringBuilder();
if (colors.Foreground != default)
ssb.Add(BuildColorStartPayload(_colorTypeForeground, colors.Foreground));
if (colors.Glow != default)
ssb.Add(BuildColorStartPayload(_colorTypeGlow, colors.Glow));
ssb.AddText(text);
if (colors.Glow != default)
ssb.Add(BuildColorEndPayload(_colorTypeGlow));
if (colors.Foreground != default)
ssb.Add(BuildColorEndPayload(_colorTypeForeground));
AppendColoredSegment(ssb, text, colors);
return ssb.Build();
}