Merge remote-tracking branch 'origin/2.0.0-crashing-bugfixes' into 2.0.0-crashing-bugfixes
# Conflicts: # LightlessSync/Services/DalamudUtilService.cs # LightlessSync/UI/DtrEntry.cs
This commit is contained in:
@@ -968,20 +968,25 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
|
||||
Dictionary<ObjectKind, Dictionary<string, CharacterAnalyzer.FileDataEntry>> source)
|
||||
{
|
||||
var clone = new Dictionary<ObjectKind, Dictionary<string, CharacterAnalyzer.FileDataEntry>>(source.Count);
|
||||
|
||||
foreach (var (objectKind, entries) in source)
|
||||
{
|
||||
var entryClone = new Dictionary<string, CharacterAnalyzer.FileDataEntry>(entries.Count, entries.Comparer);
|
||||
|
||||
foreach (var (hash, entry) in entries)
|
||||
{
|
||||
entryClone[hash] = new CharacterAnalyzer.FileDataEntry(
|
||||
hash,
|
||||
entry.FileType,
|
||||
entry.GamePaths.ToList(),
|
||||
entry.FilePaths.ToList(),
|
||||
entry.OriginalSize,
|
||||
entry.CompressedSize,
|
||||
entry.Triangles);
|
||||
hash: hash,
|
||||
fileType: entry.FileType,
|
||||
gamePaths: entry.GamePaths?.ToList() ?? [],
|
||||
filePaths: entry.FilePaths?.ToList() ?? [],
|
||||
originalSize: entry.OriginalSize,
|
||||
compressedSize: entry.CompressedSize,
|
||||
triangles: entry.Triangles,
|
||||
cacheEntries: entry.CacheEntries
|
||||
);
|
||||
}
|
||||
|
||||
clone[objectKind] = entryClone;
|
||||
}
|
||||
|
||||
|
||||
@@ -364,21 +364,28 @@ public sealed class DtrEntry : IDisposable, IHostedService
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
var cid = _dalamudUtilService.GetCID();
|
||||
var hashedCid = cid.ToString().GetHash256();
|
||||
_localHashedCid = hashedCid;
|
||||
_localHashedCidFetchedAt = now;
|
||||
return hashedCid;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (now >= _localHashedCidNextErrorLog)
|
||||
try
|
||||
{
|
||||
_logger.LogDebug(ex, "Failed to refresh local hashed CID for Lightfinder DTR entry.");
|
||||
_localHashedCidNextErrorLog = now + _localHashedCidErrorCooldown;
|
||||
var cid = _dalamudUtilService.GetCID();
|
||||
var hashedCid = cid.ToString().GetHash256();
|
||||
lock (_localHashedCidLock)
|
||||
{
|
||||
_localHashedCid = hashedCid;
|
||||
_localHashedCidFetchedAt = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
lock (_localHashedCidLock)
|
||||
{
|
||||
if (now >= _localHashedCidNextErrorLog)
|
||||
{
|
||||
_logger.LogDebug(ex, "Failed to refresh local hashed CID for Lightfinder DTR entry.");
|
||||
_localHashedCidNextErrorLog = now + _localHashedCidErrorCooldown;
|
||||
}
|
||||
|
||||
_localHashedCid = null;
|
||||
_localHashedCidFetchedAt = now;
|
||||
|
||||
@@ -37,6 +37,7 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
private readonly LightFinderService _broadcastService;
|
||||
private readonly LightlessConfigService _configService;
|
||||
private readonly LightlessProfileManager _lightlessProfileManager;
|
||||
private readonly LightFinderPlateHandler _lightFinderPlateHandler;
|
||||
private readonly PairUiService _pairUiService;
|
||||
private readonly UiSharedService _uiSharedService;
|
||||
|
||||
@@ -100,7 +101,8 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
DalamudUtilService dalamudUtilService,
|
||||
LightlessProfileManager lightlessProfileManager,
|
||||
ActorObjectService actorObjectService
|
||||
) : base(logger, mediator, "Lightfinder###LightlessLightfinderUI", performanceCollectorService)
|
||||
,
|
||||
LightFinderPlateHandler lightFinderPlateHandler) : base(logger, mediator, "Lightfinder###LightlessLightfinderUI", performanceCollectorService)
|
||||
{
|
||||
_broadcastService = broadcastService;
|
||||
_uiSharedService = uiShared;
|
||||
@@ -126,6 +128,7 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
Mediator.Subscribe<BroadcastStatusChangedMessage>(this, async _ => await RefreshNearbySyncshellsAsync().ConfigureAwait(false));
|
||||
Mediator.Subscribe<UserLeftSyncshell>(this, async _ => await RefreshNearbySyncshellsAsync(_.gid).ConfigureAwait(false));
|
||||
Mediator.Subscribe<UserJoinedSyncshell>(this, async _ => await RefreshNearbySyncshellsAsync(_.gid).ConfigureAwait(false));
|
||||
_lightFinderPlateHandler = lightFinderPlateHandler;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -175,9 +178,9 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
new("Debug", LightfinderTabDebug.Debug)
|
||||
};
|
||||
UiSharedService.Tab("LightfinderTabs", debugTabOptions, ref _selectedTabDebug);
|
||||
|
||||
|
||||
ImGuiHelpers.ScaledDummy(4f);
|
||||
|
||||
|
||||
switch (_selectedTabDebug)
|
||||
{
|
||||
case LightfinderTabDebug.NearbySyncshells:
|
||||
@@ -301,14 +304,14 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
var nearbySyncshellCount = _nearbySyncshells.Count;
|
||||
var nearbySyncshellColor = nearbySyncshellCount > 0 ? UIColors.Get("LightlessPurple") : infoColor;
|
||||
DrawStatusCell(FontAwesomeIcon.Compass, nearbySyncshellColor, nearbySyncshellCount.ToString(), "Syncshells", infoColor, scale);
|
||||
|
||||
|
||||
// Nearby players cell (exclude self)
|
||||
string? myHashedCidForCount = null;
|
||||
try { myHashedCidForCount = _dalamudUtilService.GetCID().ToString().GetHash256(); } catch { }
|
||||
var nearbyPlayerCount = _broadcastScannerService.CountActiveBroadcasts(myHashedCidForCount);
|
||||
var nearbyPlayerColor = nearbyPlayerCount > 0 ? UIColors.Get("LightlessBlue") : infoColor;
|
||||
DrawStatusCell(FontAwesomeIcon.Users, nearbyPlayerColor, nearbyPlayerCount.ToString(), "Players", infoColor, scale);
|
||||
|
||||
|
||||
// Broadcasting syncshell cell
|
||||
var isBroadcastingSyncshell = _configService.Current.SyncshellFinderEnabled && isBroadcasting;
|
||||
var broadcastSyncshellColor = isBroadcastingSyncshell ? UIColors.Get("LightlessGreen") : infoColor;
|
||||
@@ -318,7 +321,7 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
|
||||
// Enable/Disable button cell - right aligned
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
|
||||
float cellWidth = ImGui.GetContentRegionAvail().X;
|
||||
float offsetX = cellWidth - buttonWidth;
|
||||
if (offsetX > 0)
|
||||
@@ -378,11 +381,11 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
private void UpdateItemAnimations(IEnumerable<string> visibleItemIds)
|
||||
{
|
||||
var deltaTime = ImGui.GetIO().DeltaTime;
|
||||
|
||||
|
||||
_previousVisibleItems.Clear();
|
||||
foreach (var id in _currentVisibleItems)
|
||||
_previousVisibleItems.Add(id);
|
||||
|
||||
|
||||
_currentVisibleItems.Clear();
|
||||
foreach (var id in visibleItemIds)
|
||||
_currentVisibleItems.Add(id);
|
||||
@@ -392,7 +395,7 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
{
|
||||
if (!_itemAlpha.ContainsKey(id))
|
||||
_itemAlpha[id] = 0f;
|
||||
|
||||
|
||||
_itemAlpha[id] = Math.Min(1f, _itemAlpha[id] + deltaTime * AnimationSpeed);
|
||||
}
|
||||
|
||||
@@ -407,7 +410,7 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
toRemove.Add(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (var id in toRemove)
|
||||
_itemAlpha.Remove(id);
|
||||
}
|
||||
@@ -665,14 +668,14 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
||||
private void DrawJoinButton(GroupJoinDto shell, bool fullWidth)
|
||||
private void DrawJoinButton(GroupJoinDto shell, bool fullWidth)
|
||||
{
|
||||
const string visibleLabel = "Join";
|
||||
var label = $"{visibleLabel}##{shell.Group.GID}";
|
||||
|
||||
var isAlreadyMember = _currentSyncshells.Exists(g => string.Equals(g.GID, shell.Group.GID, StringComparison.Ordinal));
|
||||
var isRecentlyJoined = _recentlyJoined.Contains(shell.Group.GID);
|
||||
var isOwnBroadcast = _configService.Current.SyncshellFinderEnabled
|
||||
var isOwnBroadcast = _configService.Current.SyncshellFinderEnabled
|
||||
&& _broadcastService.IsBroadcasting
|
||||
&& string.Equals(_configService.Current.SelectedFinderSyncshell, shell.Group.GID, StringComparison.Ordinal);
|
||||
|
||||
@@ -755,7 +758,7 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
if (_joinDto == null || _joinInfo == null) return;
|
||||
|
||||
var scale = ImGuiHelpers.GlobalScale;
|
||||
|
||||
|
||||
// if not already open
|
||||
if (!ImGui.IsPopupOpen("JoinSyncshellModal"))
|
||||
ImGui.OpenPopup("JoinSyncshellModal");
|
||||
@@ -771,12 +774,12 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
ImGui.SetNextWindowSize(new Vector2(modalWidth, modalHeight));
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowRounding, 6f * ImGuiHelpers.GlobalScale);
|
||||
ImGui.PushStyleColor(ImGuiCol.Border, Vector4.Zero);
|
||||
|
||||
|
||||
using ImRaii.Color modalBorder = ImRaii.PushColor(ImGuiCol.Border, UIColors.Get("LightlessPurple").WithAlpha(0.5f));
|
||||
using ImRaii.Style rounding = ImRaii.PushStyle(ImGuiStyleVar.WindowRounding, 8f * scale);
|
||||
using ImRaii.Style borderSize = ImRaii.PushStyle(ImGuiStyleVar.WindowBorderSize, 2f * scale);
|
||||
using ImRaii.Style padding = ImRaii.PushStyle(ImGuiStyleVar.WindowPadding, new Vector2(16f * scale, 16f * scale));
|
||||
|
||||
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoScrollbar;
|
||||
if (ImGui.BeginPopupModal("JoinSyncshellModal", ref _joinModalOpen, flags))
|
||||
{
|
||||
@@ -795,22 +798,22 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
ImGui.TextColored(ImGuiColors.DalamudWhite, "Permissions");
|
||||
ImGuiHelpers.ScaledDummy(6f);
|
||||
|
||||
DrawPermissionToggleRow("Sounds", FontAwesomeIcon.VolumeUp,
|
||||
_joinInfo.GroupPermissions.IsPreferDisableSounds(),
|
||||
_ownPermissions.DisableGroupSounds,
|
||||
v => _ownPermissions.DisableGroupSounds = v,
|
||||
DrawPermissionToggleRow("Sounds", FontAwesomeIcon.VolumeUp,
|
||||
_joinInfo.GroupPermissions.IsPreferDisableSounds(),
|
||||
_ownPermissions.DisableGroupSounds,
|
||||
v => _ownPermissions.DisableGroupSounds = v,
|
||||
contentWidth);
|
||||
|
||||
DrawPermissionToggleRow("Animations", FontAwesomeIcon.Running,
|
||||
_joinInfo.GroupPermissions.IsPreferDisableAnimations(),
|
||||
_ownPermissions.DisableGroupAnimations,
|
||||
v => _ownPermissions.DisableGroupAnimations = v,
|
||||
DrawPermissionToggleRow("Animations", FontAwesomeIcon.Running,
|
||||
_joinInfo.GroupPermissions.IsPreferDisableAnimations(),
|
||||
_ownPermissions.DisableGroupAnimations,
|
||||
v => _ownPermissions.DisableGroupAnimations = v,
|
||||
contentWidth);
|
||||
|
||||
DrawPermissionToggleRow("VFX", FontAwesomeIcon.Magic,
|
||||
_joinInfo.GroupPermissions.IsPreferDisableVFX(),
|
||||
_ownPermissions.DisableGroupVFX,
|
||||
v => _ownPermissions.DisableGroupVFX = v,
|
||||
DrawPermissionToggleRow("VFX", FontAwesomeIcon.Magic,
|
||||
_joinInfo.GroupPermissions.IsPreferDisableVFX(),
|
||||
_ownPermissions.DisableGroupVFX,
|
||||
v => _ownPermissions.DisableGroupVFX = v,
|
||||
contentWidth);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(12f);
|
||||
@@ -876,13 +879,13 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
var scale = ImGuiHelpers.GlobalScale;
|
||||
float rowHeight = 28f * scale;
|
||||
bool isDifferent = current != suggested;
|
||||
|
||||
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 4f * scale))
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.ChildRounding, 4f * scale))
|
||||
using (ImRaii.PushColor(ImGuiCol.ChildBg, new Vector4(0.18f, 0.15f, 0.22f, 0.6f)))
|
||||
{
|
||||
ImGui.BeginChild($"PermRow_{label}", new Vector2(contentWidth, rowHeight), false, ImGuiWindowFlags.NoScrollbar);
|
||||
|
||||
|
||||
float innerPadding = 8f * scale;
|
||||
ImGui.SetCursorPos(new Vector2(innerPadding, (rowHeight - ImGui.GetTextLineHeight()) * 0.5f));
|
||||
|
||||
@@ -890,7 +893,7 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
var enabledColor = UIColors.Get("LightlessGreen");
|
||||
var disabledColor = UIColors.Get("DimRed");
|
||||
var currentColor = !current ? enabledColor : disabledColor;
|
||||
|
||||
|
||||
_uiSharedService.IconText(icon, currentColor);
|
||||
ImGui.SameLine(0f, 6f * scale);
|
||||
ImGui.TextUnformatted(label);
|
||||
@@ -918,7 +921,7 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
float applyX = contentWidth - 26f * scale;
|
||||
ImGui.SetCursorPosX(applyX);
|
||||
ImGui.SetCursorPosY((rowHeight - ImGui.GetFrameHeight()) * 0.5f);
|
||||
|
||||
|
||||
using (ImRaii.PushColor(ImGuiCol.Button, UIColors.Get("LightlessGreen").WithAlpha(0.6f)))
|
||||
using (ImRaii.PushColor(ImGuiCol.ButtonHovered, UIColors.Get("LightlessGreen")))
|
||||
using (ImRaii.PushColor(ImGuiCol.ButtonActive, UIColors.Get("LightlessGreenDefault")))
|
||||
@@ -1034,12 +1037,12 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
}
|
||||
|
||||
private readonly record struct NearbyPlayerData(
|
||||
string HashedCid,
|
||||
string Name,
|
||||
string? World,
|
||||
nint Address,
|
||||
Pair? Pair,
|
||||
bool IsDirectlyPaired,
|
||||
string HashedCid,
|
||||
string Name,
|
||||
string? World,
|
||||
nint Address,
|
||||
Pair? Pair,
|
||||
bool IsDirectlyPaired,
|
||||
List<string> SharedSyncshells);
|
||||
|
||||
private void DrawNearbyPlayerRow(NearbyPlayerData data)
|
||||
@@ -1093,8 +1096,8 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
ImGui.SetCursorPosX(startX);
|
||||
_uiSharedService.IconText(FontAwesomeIcon.Users, UIColors.Get("LightlessPurple"));
|
||||
ImGui.SameLine(0f, 4f * ImGuiHelpers.GlobalScale);
|
||||
var shellText = data.SharedSyncshells.Count == 1
|
||||
? data.SharedSyncshells[0]
|
||||
var shellText = data.SharedSyncshells.Count == 1
|
||||
? data.SharedSyncshells[0]
|
||||
: $"{data.SharedSyncshells.Count} shared shells";
|
||||
ImGui.TextColored(UIColors.Get("LightlessPurple"), shellText);
|
||||
if (data.SharedSyncshells.Count > 1 && ImGui.IsItemHovered())
|
||||
@@ -1379,58 +1382,92 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
|
||||
#endregion
|
||||
|
||||
#if DEBUG
|
||||
#region Debug Tab
|
||||
|
||||
private void DrawDebugTab()
|
||||
{
|
||||
ImGui.Text("Broadcast Cache");
|
||||
|
||||
if (ImGui.BeginTable("##BroadcastCacheTable", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.Borders | ImGuiTableFlags.ScrollY, new Vector2(-1, 200f)))
|
||||
{
|
||||
ImGui.TableSetupColumn("CID", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Broadcasting", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Expires In", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Syncshell GID", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableHeadersRow();
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
foreach (var (cid, entry) in _broadcastScannerService.BroadcastCache)
|
||||
#if DEBUG
|
||||
if (ImGui.CollapsingHeader("LightFinder Plates", ImGuiTreeNodeFlags.DefaultOpen))
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
var h = _lightFinderPlateHandler;
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted(cid.Truncate(12));
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip(cid);
|
||||
var enabled = h.DebugEnabled;
|
||||
if (ImGui.Checkbox("Enable LightFinder debug", ref enabled))
|
||||
h.DebugEnabled = enabled;
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
var colorBroadcast = entry.IsBroadcasting ? UIColors.Get("LightlessGreen") : UIColors.Get("DimRed");
|
||||
ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, ImGui.GetColorU32(colorBroadcast));
|
||||
ImGui.TextUnformatted(entry.IsBroadcasting.ToString());
|
||||
if (h.DebugEnabled)
|
||||
{
|
||||
ImGui.Indent();
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
var remaining = entry.ExpiryTime - now;
|
||||
var colorTtl = remaining <= TimeSpan.Zero ? UIColors.Get("DimRed")
|
||||
: remaining < TimeSpan.FromSeconds(10) ? UIColors.Get("LightlessYellow")
|
||||
: (Vector4?)null;
|
||||
var disableOcc = h.DebugDisableOcclusion;
|
||||
if (ImGui.Checkbox("Disable occlusion (force draw)", ref disableOcc))
|
||||
h.DebugDisableOcclusion = disableOcc;
|
||||
|
||||
if (colorTtl != null)
|
||||
ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, ImGui.GetColorU32(colorTtl.Value));
|
||||
var drawUiRects = h.DebugDrawUiRects;
|
||||
if (ImGui.Checkbox("Draw UI rects", ref drawUiRects))
|
||||
h.DebugDrawUiRects = drawUiRects;
|
||||
|
||||
ImGui.TextUnformatted(remaining > TimeSpan.Zero ? remaining.ToString("hh\\:mm\\:ss") : "Expired");
|
||||
var drawLabelRects = h.DebugDrawLabelRects;
|
||||
if (ImGui.Checkbox("Draw label rects", ref drawLabelRects))
|
||||
h.DebugDrawLabelRects = drawLabelRects;
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted(entry.GID ?? "-");
|
||||
ImGui.Separator();
|
||||
ImGui.TextUnformatted($"Labels last frame: {h.DebugLabelCountLastFrame}");
|
||||
ImGui.TextUnformatted($"UI rects last frame: {h.DebugUiRectCountLastFrame}");
|
||||
ImGui.TextUnformatted($"Occluded last frame: {h.DebugOccludedCountLastFrame}");
|
||||
ImGui.TextUnformatted($"Last NamePlate frame: {h.DebugLastNameplateFrame}");
|
||||
|
||||
ImGui.Unindent();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndTable();
|
||||
}
|
||||
}
|
||||
ImGui.Separator();
|
||||
|
||||
#endregion
|
||||
ImGui.Text("Broadcast Cache");
|
||||
|
||||
if (ImGui.BeginTable("##BroadcastCacheTable", 4,
|
||||
ImGuiTableFlags.RowBg | ImGuiTableFlags.Borders | ImGuiTableFlags.ScrollY,
|
||||
new Vector2(-1, 225f)))
|
||||
{
|
||||
ImGui.TableSetupColumn("CID", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("IsBroadcasting", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Expires In", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Syncshell GID", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableHeadersRow();
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
foreach (var (cid, entry) in _broadcastScannerService.BroadcastCache)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted(cid.Truncate(12));
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip(cid);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
var colorBroadcast = entry.IsBroadcasting ? UIColors.Get("LightlessGreen") : UIColors.Get("DimRed");
|
||||
ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, ImGui.GetColorU32(colorBroadcast));
|
||||
ImGui.TextUnformatted(entry.IsBroadcasting.ToString());
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
var remaining = entry.ExpiryTime - now;
|
||||
var colorTtl = remaining <= TimeSpan.Zero ? UIColors.Get("DimRed")
|
||||
: remaining < TimeSpan.FromSeconds(10) ? UIColors.Get("LightlessYellow")
|
||||
: (Vector4?)null;
|
||||
|
||||
if (colorTtl != null)
|
||||
ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, ImGui.GetColorU32(colorTtl.Value));
|
||||
|
||||
ImGui.TextUnformatted(remaining > TimeSpan.Zero ? remaining.ToString("hh\\:mm\\:ss") : "Expired");
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted(entry.GID ?? "-");
|
||||
}
|
||||
|
||||
ImGui.EndTable();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#region Data Refresh
|
||||
|
||||
@@ -1699,4 +1736,4 @@ public class LightFinderUI : WindowMediatorSubscriberBase
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
private bool _pairDiagnosticsEnabled;
|
||||
private string? _selectedPairDebugUid = null;
|
||||
private string _lightfinderIconInput = string.Empty;
|
||||
private bool _showLightfinderRendererWarning = false;
|
||||
private LightfinderLabelRenderer _pendingLightfinderRenderer = LightfinderLabelRenderer.Pictomancy;
|
||||
private bool _lightfinderIconInputInitialized = false;
|
||||
private int _lightfinderIconPresetIndex = -1;
|
||||
private static readonly LightlessConfig DefaultConfig = new();
|
||||
@@ -2387,7 +2389,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
var labelRenderer = _configService.Current.LightfinderLabelRenderer;
|
||||
var labelRendererLabel = labelRenderer switch
|
||||
{
|
||||
LightfinderLabelRenderer.SignatureHook => "Native nameplate (sig hook)",
|
||||
LightfinderLabelRenderer.SignatureHook => "Native Nameplate Rendering",
|
||||
_ => "ImGui Overlay",
|
||||
};
|
||||
|
||||
@@ -2397,18 +2399,25 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
var optionLabel = option switch
|
||||
{
|
||||
LightfinderLabelRenderer.SignatureHook => "Native Nameplate (sig hook)",
|
||||
LightfinderLabelRenderer.SignatureHook => "Native Nameplate Rendering",
|
||||
_ => "ImGui Overlay",
|
||||
};
|
||||
|
||||
var selected = option == labelRenderer;
|
||||
if (ImGui.Selectable(optionLabel, selected))
|
||||
{
|
||||
_configService.Current.LightfinderLabelRenderer = option;
|
||||
_configService.Save();
|
||||
_nameplateService.RequestRedraw();
|
||||
if (option == LightfinderLabelRenderer.SignatureHook)
|
||||
{
|
||||
_pendingLightfinderRenderer = option;
|
||||
_showLightfinderRendererWarning = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_configService.Current.LightfinderLabelRenderer = option;
|
||||
_configService.Save();
|
||||
_nameplateService.RequestRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
if (selected)
|
||||
ImGui.SetItemDefaultFocus();
|
||||
}
|
||||
@@ -2416,6 +2425,34 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
if (_showLightfinderRendererWarning)
|
||||
{
|
||||
ImGui.SetNextWindowSize(new Vector2(450f, 0f), ImGuiCond.Appearing);
|
||||
ImGui.OpenPopup("Nameplate Warning");
|
||||
}
|
||||
|
||||
if (ImGui.BeginPopupModal("Nameplate Warning", ref _showLightfinderRendererWarning, ImGuiWindowFlags.AlwaysAutoResize))
|
||||
{
|
||||
ImGui.TextColored(UIColors.Get("DimRed"), "USE AT YOUR RISK!");
|
||||
ImGui.Spacing();
|
||||
ImGui.TextWrapped("Writing on to the native Nameplates is known to be unstable and MAY cause crashes. DO NOT REPORT THOSE CRASHES TO DALAMUD. We will also not be supporting Nameplate crashes. You have been warned.");
|
||||
ImGui.Spacing();
|
||||
ImGui.TextWrapped("By accepting this warning, you understand that you are using this feature at risk of crashing.");
|
||||
ImGui.Spacing();
|
||||
|
||||
var buttonWidth = ImGui.GetContentRegionAvail().X;
|
||||
if (ImGui.Button("I Understand", new Vector2(buttonWidth, 0)))
|
||||
{
|
||||
_configService.Current.LightfinderLabelRenderer = _pendingLightfinderRenderer;
|
||||
_configService.Save();
|
||||
_nameplateService.RequestRedraw();
|
||||
_showLightfinderRendererWarning = false;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
_uiShared.DrawHelpText("Choose how Lightfinder labels render: the default ImGui overlay or native nameplate nodes via signature hook.");
|
||||
|
||||
UiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
|
||||
@@ -2602,7 +2639,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
var selected = i == _lightfinderIconPresetIndex;
|
||||
if (ImGui.Selectable(preview, selected))
|
||||
{
|
||||
_lightfinderIconInput = LightFinderPlateHandler.ToIconEditorString(optionGlyph);
|
||||
_lightfinderIconInput = LightFinderPlateHandler.NormalizeIconGlyph(optionGlyph);
|
||||
_lightfinderIconPresetIndex = i;
|
||||
}
|
||||
}
|
||||
@@ -4083,7 +4120,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
private void RefreshLightfinderIconState()
|
||||
{
|
||||
var normalized = LightFinderPlateHandler.NormalizeIconGlyph(_configService.Current.LightfinderLabelIconGlyph);
|
||||
_lightfinderIconInput = LightFinderPlateHandler.ToIconEditorString(normalized);
|
||||
_lightfinderIconInput = LightFinderPlateHandler.NormalizeIconGlyph(normalized);
|
||||
_lightfinderIconInputInitialized = true;
|
||||
|
||||
_lightfinderIconPresetIndex = -1;
|
||||
@@ -4101,7 +4138,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
_configService.Current.LightfinderLabelIconGlyph = normalizedGlyph;
|
||||
_configService.Save();
|
||||
_lightfinderIconInput = LightFinderPlateHandler.ToIconEditorString(normalizedGlyph);
|
||||
_lightfinderIconInput = LightFinderPlateHandler.NormalizeIconGlyph(normalizedGlyph);
|
||||
_lightfinderIconPresetIndex = presetIndex;
|
||||
_lightfinderIconInputInitialized = true;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using LightlessSync.Services.ServerConfiguration;
|
||||
using LightlessSync.UI.Services;
|
||||
using LightlessSync.UI.Tags;
|
||||
using LightlessSync.Utils;
|
||||
using LightlessSync.WebAPI;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Numerics;
|
||||
|
||||
@@ -22,6 +23,7 @@ public class StandaloneProfileUi : WindowMediatorSubscriberBase
|
||||
private readonly PairUiService _pairUiService;
|
||||
private readonly ServerConfigurationManager _serverManager;
|
||||
private readonly ProfileTagService _profileTagService;
|
||||
private readonly ApiController _apiController;
|
||||
private readonly UiSharedService _uiSharedService;
|
||||
private readonly UserData? _userData;
|
||||
private readonly GroupData? _groupData;
|
||||
@@ -60,7 +62,8 @@ public class StandaloneProfileUi : WindowMediatorSubscriberBase
|
||||
GroupData? groupData,
|
||||
bool isLightfinderContext,
|
||||
string? lightfinderCid,
|
||||
PerformanceCollectorService performanceCollector)
|
||||
PerformanceCollectorService performanceCollector,
|
||||
ApiController apiController)
|
||||
: base(logger, mediator, BuildWindowTitle(
|
||||
userData,
|
||||
groupData,
|
||||
@@ -94,6 +97,7 @@ public class StandaloneProfileUi : WindowMediatorSubscriberBase
|
||||
.Apply();
|
||||
|
||||
IsOpen = true;
|
||||
_apiController = apiController;
|
||||
}
|
||||
|
||||
public Pair? Pair { get; }
|
||||
@@ -248,19 +252,33 @@ public class StandaloneProfileUi : WindowMediatorSubscriberBase
|
||||
ResetBannerTexture();
|
||||
_lastBannerPicture = bannerBytes;
|
||||
}
|
||||
|
||||
string? noteText = null;
|
||||
string statusLabel = _isLightfinderContext ? "Exploring" : "Offline";
|
||||
|
||||
var isSelfProfile = !_isLightfinderContext
|
||||
&& _userData is not null
|
||||
&& !string.IsNullOrEmpty(_apiController.UID)
|
||||
&& string.Equals(_userData.UID, _apiController.UID, StringComparison.Ordinal);
|
||||
|
||||
string statusLabel = _isLightfinderContext
|
||||
? "Exploring"
|
||||
: isSelfProfile ? "Online" : "Offline";
|
||||
|
||||
string? visiblePlayerName = null;
|
||||
bool directPair = false;
|
||||
bool youPaused = false;
|
||||
bool theyPaused = false;
|
||||
List<string> syncshellLines = [];
|
||||
|
||||
if (!_isLightfinderContext)
|
||||
{
|
||||
noteText = _serverManager.GetNoteForUid(_userData!.UID);
|
||||
}
|
||||
|
||||
if (!_isLightfinderContext && Pair != null)
|
||||
{
|
||||
var snapshot = _pairUiService.GetSnapshot();
|
||||
noteText = _serverManager.GetNoteForUid(Pair.UserData.UID);
|
||||
|
||||
statusLabel = Pair.IsVisible ? "Visible" : (Pair.IsOnline ? "Online" : "Offline");
|
||||
visiblePlayerName = Pair.IsVisible ? Pair.PlayerName : null;
|
||||
|
||||
@@ -282,11 +300,15 @@ public class StandaloneProfileUi : WindowMediatorSubscriberBase
|
||||
var groupLabel = snapshot.GroupsByGid.TryGetValue(gid, out var groupInfo)
|
||||
? groupInfo.GroupAliasOrGID
|
||||
: gid;
|
||||
|
||||
var groupNote = _serverManager.GetNoteForGid(gid);
|
||||
syncshellLines.Add(string.IsNullOrEmpty(groupNote) ? groupLabel : $"{groupNote} ({groupLabel})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isSelfProfile)
|
||||
statusLabel = "Online";
|
||||
}
|
||||
|
||||
var presenceTokens = new List<PresenceToken>
|
||||
|
||||
@@ -993,18 +993,33 @@ public sealed class ZoneChatUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
_refocusChatInput = true;
|
||||
_refocusChatInputKey = channel.Key;
|
||||
var sanitized = SanitizeOutgoingDraft(draft);
|
||||
|
||||
var draftAtSend = draft;
|
||||
var sanitized = SanitizeOutgoingDraft(draftAtSend);
|
||||
|
||||
if (sanitized is not null)
|
||||
{
|
||||
TrackPendingDraftClear(channel.Key, sanitized);
|
||||
if (TrySendDraft(channel, sanitized))
|
||||
draft = string.Empty;
|
||||
_draftMessages[channel.Key] = draft;
|
||||
_scrollToBottom = true;
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
_scrollToBottom = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RemovePendingDraftClear(channel.Key, sanitized);
|
||||
}
|
||||
try
|
||||
{
|
||||
var succeeded = await _zoneChatService.SendMessageAsync(channel.Descriptor, sanitized).ConfigureAwait(false);
|
||||
if (!succeeded)
|
||||
{
|
||||
RemovePendingDraftClear(channel.Key, sanitized);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to send chat message");
|
||||
RemovePendingDraftClear(channel.Key, sanitized);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user