Merge branch '1.12.3' into banner-api-changes

This commit is contained in:
2025-10-21 22:41:29 +02:00
20 changed files with 467 additions and 258 deletions

View File

@@ -56,7 +56,6 @@ public class CompactUi : WindowMediatorSubscriberBase
private readonly BroadcastService _broadcastService;
private List<IDrawFolder> _drawFolders;
private Dictionary<ObjectKind, Dictionary<string, CharacterAnalyzer.FileDataEntry>>? _cachedAnalysis;
private Pair? _lastAddedUser;
private string _lastAddedUserComment = string.Empty;
private Vector2 _lastPosition = Vector2.One;
@@ -382,15 +381,26 @@ public class CompactUi : WindowMediatorSubscriberBase
_uiSharedService.IconText(FontAwesomeIcon.Upload);
ImGui.SameLine(35 * ImGuiHelpers.GlobalScale);
if (currentUploads.Any())
if (currentUploads.Count > 0)
{
var totalUploads = currentUploads.Count;
int totalUploads = currentUploads.Count;
int doneUploads = 0;
long totalUploaded = 0;
long totalToUpload = 0;
var doneUploads = currentUploads.Count(c => c.IsTransferred);
var activeUploads = currentUploads.Count(c => !c.IsTransferred);
foreach (var upload in currentUploads)
{
if (upload.IsTransferred)
{
doneUploads++;
}
totalUploaded += upload.Transferred;
totalToUpload += upload.Total;
}
int activeUploads = totalUploads - doneUploads;
var uploadSlotLimit = Math.Clamp(_configService.Current.ParallelUploads, 1, 8);
var totalUploaded = currentUploads.Sum(c => c.Transferred);
var totalToUpload = currentUploads.Sum(c => c.Total);
ImGui.TextUnformatted($"{doneUploads}/{totalUploads} (slots {activeUploads}/{uploadSlotLimit})");
var uploadText = $"({UiSharedService.ByteToString(totalUploaded)}/{UiSharedService.ByteToString(totalToUpload)})";
@@ -405,17 +415,17 @@ public class CompactUi : WindowMediatorSubscriberBase
ImGui.TextUnformatted("No uploads in progress");
}
var currentDownloads = BuildCurrentDownloadSnapshot();
var downloadSummary = GetDownloadSummary();
ImGui.AlignTextToFramePadding();
_uiSharedService.IconText(FontAwesomeIcon.Download);
ImGui.SameLine(35 * ImGuiHelpers.GlobalScale);
if (currentDownloads.Any())
if (downloadSummary.HasDownloads)
{
var totalDownloads = currentDownloads.Sum(c => c.TotalFiles);
var doneDownloads = currentDownloads.Sum(c => c.TransferredFiles);
var totalDownloaded = currentDownloads.Sum(c => c.TransferredBytes);
var totalToDownload = currentDownloads.Sum(c => c.TotalBytes);
var totalDownloads = downloadSummary.TotalFiles;
var doneDownloads = downloadSummary.TransferredFiles;
var totalDownloaded = downloadSummary.TransferredBytes;
var totalToDownload = downloadSummary.TotalBytes;
ImGui.TextUnformatted($"{doneDownloads}/{totalDownloads}");
var downloadText =
@@ -433,27 +443,35 @@ public class CompactUi : WindowMediatorSubscriberBase
}
private List<FileDownloadStatus> BuildCurrentDownloadSnapshot()
private DownloadSummary GetDownloadSummary()
{
List<FileDownloadStatus> snapshot = new();
long totalBytes = 0;
long transferredBytes = 0;
int totalFiles = 0;
int transferredFiles = 0;
foreach (var kvp in _currentDownloads.ToArray())
{
var value = kvp.Value;
if (value == null || value.Count == 0)
if (kvp.Value is not { Count: > 0 } statuses)
{
continue;
try
{
snapshot.AddRange(value.Values.ToArray());
}
catch (System.ArgumentException)
foreach (var status in statuses.Values)
{
// skibidi
totalBytes += status.TotalBytes;
transferredBytes += status.TransferredBytes;
totalFiles += status.TotalFiles;
transferredFiles += status.TransferredFiles;
}
}
return snapshot;
return new DownloadSummary(totalFiles, transferredFiles, transferredBytes, totalBytes);
}
private readonly record struct DownloadSummary(int TotalFiles, int TransferredFiles, long TransferredBytes, long TotalBytes)
{
public bool HasDownloads => TotalFiles > 0 || TotalBytes > 0;
}
private void DrawUIDHeader()
@@ -480,7 +498,7 @@ public class CompactUi : WindowMediatorSubscriberBase
}
//Getting information of character and triangles threshold to show overlimit status in UID bar.
_cachedAnalysis = _characterAnalyzer.LastAnalysis.DeepClone();
var analysisSummary = _characterAnalyzer.LatestSummary;
Vector2 uidTextSize, iconSize;
using (_uiSharedService.UidFont.Push())
@@ -509,6 +527,7 @@ public class CompactUi : WindowMediatorSubscriberBase
if (ImGui.IsItemHovered())
{
ImGui.BeginTooltip();
ImGui.PushTextWrapPos(ImGui.GetFontSize() * 32f);
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("PairBlue"));
ImGui.Text("Lightfinder");
@@ -556,6 +575,7 @@ public class CompactUi : WindowMediatorSubscriberBase
ImGui.PopStyleColor();
}
ImGui.PopTextWrapPos();
ImGui.EndTooltip();
}
@@ -574,7 +594,7 @@ public class CompactUi : WindowMediatorSubscriberBase
var seString = SeStringUtils.BuildFormattedPlayerName(uidText, vanityTextColor, vanityGlowColor);
var cursorPos = ImGui.GetCursorScreenPos();
var fontPtr = ImGui.GetFont();
SeStringUtils.RenderSeStringWithHitbox(seString, cursorPos, fontPtr);
SeStringUtils.RenderSeStringWithHitbox(seString, cursorPos, fontPtr, "uid-header");
}
else
{
@@ -591,56 +611,40 @@ public class CompactUi : WindowMediatorSubscriberBase
UiSharedService.AttachToolTip("Click to copy");
if (_cachedAnalysis != null && _apiController.ServerState is ServerState.Connected)
if (_apiController.ServerState is ServerState.Connected && analysisSummary.HasData)
{
var firstEntry = _cachedAnalysis.FirstOrDefault();
var valueDict = firstEntry.Value;
if (valueDict != null && valueDict.Count > 0)
var objectSummary = analysisSummary.Objects.Values.FirstOrDefault(summary => summary.HasEntries);
if (objectSummary.HasEntries)
{
var groupedfiles = valueDict
.Select(v => v.Value)
.Where(v => v != null)
.GroupBy(f => f.FileType, StringComparer.Ordinal)
.OrderBy(k => k.Key, StringComparer.Ordinal)
.ToList();
var actualVramUsage = objectSummary.TexOriginalBytes;
var actualTriCount = objectSummary.TotalTriangles;
var actualTriCount = valueDict
.Select(v => v.Value)
.Where(v => v != null)
.Sum(f => f.Triangles);
var isOverVRAMUsage = _playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB * 1024 * 1024 < actualVramUsage;
var isOverTriHold = actualTriCount > (_playerPerformanceConfig.Current.TrisWarningThresholdThousands * 1000);
if (groupedfiles != null)
if ((isOverTriHold || isOverVRAMUsage) && _playerPerformanceConfig.Current.WarnOnExceedingThresholds)
{
//Checking of VRAM threshhold
var texGroup = groupedfiles.SingleOrDefault(v => string.Equals(v.Key, "tex", StringComparison.Ordinal));
var actualVramUsage = texGroup != null ? texGroup.Sum(f => f.OriginalSize) : 0L;
var isOverVRAMUsage = _playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB * 1024 * 1024 < actualVramUsage;
var isOverTriHold = actualTriCount > (_playerPerformanceConfig.Current.TrisWarningThresholdThousands * 1000);
ImGui.SameLine();
ImGui.SetCursorPosY(cursorY + 15f);
_uiSharedService.IconText(FontAwesomeIcon.ExclamationTriangle, UIColors.Get("LightlessYellow"));
if ((isOverTriHold || isOverVRAMUsage) && _playerPerformanceConfig.Current.WarnOnExceedingThresholds)
string warningMessage = "";
if (isOverTriHold)
{
ImGui.SameLine();
ImGui.SetCursorPosY(cursorY + 15f);
_uiSharedService.IconText(FontAwesomeIcon.ExclamationTriangle, UIColors.Get("LightlessYellow"));
warningMessage += $"You exceed your own triangles threshold by " +
$"{actualTriCount - _playerPerformanceConfig.Current.TrisWarningThresholdThousands * 1000} triangles.";
warningMessage += Environment.NewLine;
string warningMessage = "";
if (isOverTriHold)
{
warningMessage += $"You exceed your own triangles threshold by " +
$"{actualTriCount - _playerPerformanceConfig.Current.TrisWarningThresholdThousands * 1000} triangles.";
warningMessage += Environment.NewLine;
}
if (isOverVRAMUsage)
{
warningMessage += $"You exceed your own VRAM threshold by " +
$"{UiSharedService.ByteToString(actualVramUsage - (_playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB * 1024 * 1024))}.";
}
UiSharedService.AttachToolTip(warningMessage);
if (ImGui.IsItemClicked())
{
_lightlessMediator.Publish(new UiToggleMessage(typeof(DataAnalysisUi)));
}
}
if (isOverVRAMUsage)
{
warningMessage += $"You exceed your own VRAM threshold by " +
$"{UiSharedService.ByteToString(actualVramUsage - (_playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB * 1024 * 1024))}.";
}
UiSharedService.AttachToolTip(warningMessage);
if (ImGui.IsItemClicked())
{
_lightlessMediator.Publish(new UiToggleMessage(typeof(DataAnalysisUi)));
}
}
}
@@ -663,7 +667,7 @@ public class CompactUi : WindowMediatorSubscriberBase
var seString = SeStringUtils.BuildFormattedPlayerName(_apiController.UID, vanityTextColor, vanityGlowColor);
var cursorPos = ImGui.GetCursorScreenPos();
var fontPtr = ImGui.GetFont();
SeStringUtils.RenderSeStringWithHitbox(seString, cursorPos, fontPtr);
SeStringUtils.RenderSeStringWithHitbox(seString, cursorPos, fontPtr, "uid-footer");
}
else
{
@@ -921,4 +925,4 @@ public class CompactUi : WindowMediatorSubscriberBase
_wasOpen = IsOpen;
IsOpen = false;
}
}
}

View File

@@ -2,6 +2,7 @@
using Dalamud.Interface;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using LightlessSync.API.Data.Enum;
using LightlessSync.API.Data.Extensions;
using LightlessSync.API.Dto.Group;
using LightlessSync.API.Dto.User;
@@ -13,6 +14,9 @@ using LightlessSync.Services.ServerConfiguration;
using LightlessSync.UI.Handlers;
using LightlessSync.Utils;
using LightlessSync.WebAPI;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Text;
namespace LightlessSync.UI.Components;
@@ -32,6 +36,8 @@ public class DrawUserPair
private readonly CharaDataManager _charaDataManager;
private float _menuWidth = -1;
private bool _wasHovered = false;
private TooltipSnapshot _tooltipSnapshot = TooltipSnapshot.Empty;
private string _cachedTooltip = string.Empty;
public DrawUserPair(string id, Pair entry, List<GroupFullInfoDto> syncedGroups,
GroupFullInfoDto? currentGroup,
@@ -190,15 +196,12 @@ public class DrawUserPair
private void DrawLeftSide()
{
string userPairText = string.Empty;
ImGui.AlignTextToFramePadding();
if (_pair.IsPaused)
{
using var _ = ImRaii.PushColor(ImGuiCol.Text, UIColors.Get("LightlessYellow"));
_uiSharedService.IconText(FontAwesomeIcon.PauseCircle);
userPairText = _pair.UserData.AliasOrUID + " is paused";
}
else if (!_pair.IsOnline)
{
@@ -207,12 +210,10 @@ public class DrawUserPair
? FontAwesomeIcon.ArrowsLeftRight
: (_pair.IndividualPairStatus == API.Data.Enum.IndividualPairStatus.Bidirectional
? FontAwesomeIcon.User : FontAwesomeIcon.Users));
userPairText = _pair.UserData.AliasOrUID + " is offline";
}
else if (_pair.IsVisible)
{
_uiSharedService.IconText(FontAwesomeIcon.Eye, UIColors.Get("LightlessBlue"));
userPairText = _pair.UserData.AliasOrUID + " is visible: " + _pair.PlayerName + Environment.NewLine + "Click to target this player";
if (ImGui.IsItemClicked())
{
_mediator.Publish(new TargetPairMessage(_pair));
@@ -223,46 +224,9 @@ public class DrawUserPair
using var _ = ImRaii.PushColor(ImGuiCol.Text, UIColors.Get("PairBlue"));
_uiSharedService.IconText(_pair.IndividualPairStatus == API.Data.Enum.IndividualPairStatus.Bidirectional
? FontAwesomeIcon.User : FontAwesomeIcon.Users);
userPairText = _pair.UserData.AliasOrUID + " is online";
}
if (_pair.IndividualPairStatus == API.Data.Enum.IndividualPairStatus.OneSided)
{
userPairText += UiSharedService.TooltipSeparator + "User has not added you back";
}
else if (_pair.IndividualPairStatus == API.Data.Enum.IndividualPairStatus.Bidirectional)
{
userPairText += UiSharedService.TooltipSeparator + "You are directly Paired";
}
if (_pair.LastAppliedDataBytes >= 0)
{
userPairText += UiSharedService.TooltipSeparator;
userPairText += ((!_pair.IsPaired) ? "(Last) " : string.Empty) + "Mods Info" + Environment.NewLine;
userPairText += "Files Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataBytes, true);
if (_pair.LastAppliedApproximateVRAMBytes >= 0)
{
userPairText += Environment.NewLine + "Approx. VRAM Usage: " + UiSharedService.ByteToString(_pair.LastAppliedApproximateVRAMBytes, true);
}
if (_pair.LastAppliedDataTris >= 0)
{
userPairText += Environment.NewLine + "Approx. Triangle Count (excl. Vanilla): "
+ (_pair.LastAppliedDataTris > 1000 ? (_pair.LastAppliedDataTris / 1000d).ToString("0.0'k'") : _pair.LastAppliedDataTris);
}
}
if (_syncedGroups.Any())
{
userPairText += UiSharedService.TooltipSeparator + string.Join(Environment.NewLine,
_syncedGroups.Select(g =>
{
var groupNote = _serverConfigurationManager.GetNoteForGid(g.GID);
var groupString = string.IsNullOrEmpty(groupNote) ? g.GroupAliasOrGID : $"{groupNote} ({g.GroupAliasOrGID})";
return "Paired through " + groupString;
}));
}
UiSharedService.AttachToolTip(userPairText);
UiSharedService.AttachToolTip(GetUserTooltip());
if (_performanceConfigService.Current.ShowPerformanceIndicator
&& !_performanceConfigService.Current.UIDsToIgnore
@@ -327,6 +291,143 @@ public class DrawUserPair
_displayHandler.DrawPairText(_id, _pair, leftSide, () => rightSide - leftSide);
}
private string GetUserTooltip()
{
List<string>? groupDisplays = null;
if (_syncedGroups.Count > 0)
{
groupDisplays = new List<string>(_syncedGroups.Count);
foreach (var group in _syncedGroups)
{
var groupNote = _serverConfigurationManager.GetNoteForGid(group.GID);
groupDisplays.Add(string.IsNullOrEmpty(groupNote) ? group.GroupAliasOrGID : $"{groupNote} ({group.GroupAliasOrGID})");
}
}
var snapshot = new TooltipSnapshot(
_pair.IsPaused,
_pair.IsOnline,
_pair.IsVisible,
_pair.IndividualPairStatus,
_pair.UserData.AliasOrUID,
_pair.PlayerName ?? string.Empty,
_pair.LastAppliedDataBytes,
_pair.LastAppliedApproximateVRAMBytes,
_pair.LastAppliedDataTris,
_pair.IsPaired,
groupDisplays is null ? ImmutableArray<string>.Empty : ImmutableArray.CreateRange(groupDisplays));
if (!_tooltipSnapshot.Equals(snapshot))
{
_cachedTooltip = BuildTooltip(snapshot);
_tooltipSnapshot = snapshot;
}
return _cachedTooltip;
}
private static string BuildTooltip(in TooltipSnapshot snapshot)
{
var builder = new StringBuilder(256);
if (snapshot.IsPaused)
{
builder.Append(snapshot.AliasOrUid);
builder.Append(" is paused");
}
else if (!snapshot.IsOnline)
{
builder.Append(snapshot.AliasOrUid);
builder.Append(" is offline");
}
else if (snapshot.IsVisible)
{
builder.Append(snapshot.AliasOrUid);
builder.Append(" is visible: ");
builder.Append(snapshot.PlayerName);
builder.Append(Environment.NewLine);
builder.Append("Click to target this player");
}
else
{
builder.Append(snapshot.AliasOrUid);
builder.Append(" is online");
}
if (snapshot.PairStatus == IndividualPairStatus.OneSided)
{
builder.Append(UiSharedService.TooltipSeparator);
builder.Append("User has not added you back");
}
else if (snapshot.PairStatus == IndividualPairStatus.Bidirectional)
{
builder.Append(UiSharedService.TooltipSeparator);
builder.Append("You are directly Paired");
}
if (snapshot.LastAppliedDataBytes >= 0)
{
builder.Append(UiSharedService.TooltipSeparator);
if (!snapshot.IsPaired)
{
builder.Append("(Last) ");
}
builder.Append("Mods Info");
builder.Append(Environment.NewLine);
builder.Append("Files Size: ");
builder.Append(UiSharedService.ByteToString(snapshot.LastAppliedDataBytes, true));
if (snapshot.LastAppliedApproximateVRAMBytes >= 0)
{
builder.Append(Environment.NewLine);
builder.Append("Approx. VRAM Usage: ");
builder.Append(UiSharedService.ByteToString(snapshot.LastAppliedApproximateVRAMBytes, true));
}
if (snapshot.LastAppliedDataTris >= 0)
{
builder.Append(Environment.NewLine);
builder.Append("Approx. Triangle Count (excl. Vanilla): ");
builder.Append(snapshot.LastAppliedDataTris > 1000
? (snapshot.LastAppliedDataTris / 1000d).ToString("0.0'k'")
: snapshot.LastAppliedDataTris);
}
}
if (!snapshot.GroupDisplays.IsEmpty)
{
builder.Append(UiSharedService.TooltipSeparator);
for (int i = 0; i < snapshot.GroupDisplays.Length; i++)
{
if (i > 0)
{
builder.Append(Environment.NewLine);
}
builder.Append("Paired through ");
builder.Append(snapshot.GroupDisplays[i]);
}
}
return builder.ToString();
}
private readonly record struct TooltipSnapshot(
bool IsPaused,
bool IsOnline,
bool IsVisible,
IndividualPairStatus PairStatus,
string AliasOrUid,
string PlayerName,
long LastAppliedDataBytes,
long LastAppliedApproximateVRAMBytes,
long LastAppliedDataTris,
bool IsPaired,
ImmutableArray<string> GroupDisplays)
{
public static TooltipSnapshot Empty { get; } =
new(false, false, false, IndividualPairStatus.None, string.Empty, string.Empty, -1, -1, -1, false, ImmutableArray<string>.Empty);
}
private void DrawPairedClientMenu()
{
DrawIndividualMenu();

View File

@@ -22,13 +22,12 @@ public class DownloadUi : WindowMediatorSubscriberBase
private readonly UiSharedService _uiShared;
private readonly PairProcessingLimiter _pairProcessingLimiter;
private readonly ConcurrentDictionary<GameObjectHandler, bool> _uploadingPlayers = new();
private readonly NotificationService _notificationService;
private bool _notificationDismissed = true;
private int _lastDownloadStateHash = 0;
public DownloadUi(ILogger<DownloadUi> logger, DalamudUtilService dalamudUtilService, LightlessConfigService configService,
PairProcessingLimiter pairProcessingLimiter, FileUploadManager fileTransferManager, LightlessMediator mediator, UiSharedService uiShared,
PerformanceCollectorService performanceCollectorService, NotificationService notificationService)
PerformanceCollectorService performanceCollectorService)
: base(logger, mediator, "Lightless Sync Downloads", performanceCollectorService)
{
_dalamudUtilService = dalamudUtilService;
@@ -36,7 +35,6 @@ public class DownloadUi : WindowMediatorSubscriberBase
_pairProcessingLimiter = pairProcessingLimiter;
_fileTransferManager = fileTransferManager;
_uiShared = uiShared;
_notificationService = notificationService;
SizeConstraints = new WindowSizeConstraints()
{
@@ -359,7 +357,7 @@ public class DownloadUi : WindowMediatorSubscriberBase
_lastDownloadStateHash = currentHash;
if (downloadStatus.Count > 0 || queueWaiting > 0)
{
_notificationService.ShowPairDownloadNotification(downloadStatus, queueWaiting);
Mediator.Publish(new PairDownloadStatusMessage(downloadStatus, queueWaiting));
}
}
}

View File

@@ -281,7 +281,7 @@ public class EditProfileUi : WindowMediatorSubscriberBase
{
_uiSharedService.MediumText("Supporter Vanity Settings", UIColors.Get("LightlessPurple"));
ImGui.Dummy(new Vector2(4));
_uiSharedService.DrawNoteLine("# ", UIColors.Get("LightlessPurple"), "Must be a supporter through Patreon/Ko-fi to access these settings.");
_uiSharedService.DrawNoteLine("# ", UIColors.Get("LightlessPurple"), "Must be a supporter through Patreon/Ko-fi to access these settings. If you have the vanity role, you must interact with the Discord bot first.");
var hasVanity = _apiController.HasVanity;

View File

@@ -157,7 +157,7 @@ public class IdDisplayHandler
Vector2 textSize;
using (ImRaii.PushFont(font, textIsUid))
{
SeStringUtils.RenderSeStringWithHitbox(seString, rowStart, font);
SeStringUtils.RenderSeStringWithHitbox(seString, rowStart, font, pair.UserData.UID);
itemMin = ImGui.GetItemRectMin();
itemMax = ImGui.GetItemRectMax();
//textSize = itemMax - itemMin;

View File

@@ -15,17 +15,17 @@ using Dalamud.Bindings.ImGui;
namespace LightlessSync.UI;
public class LightlessNotificationUI : WindowMediatorSubscriberBase
public class LightlessNotificationUi : WindowMediatorSubscriberBase
{
private const float NotificationMinHeight = 60f;
private const float NotificationMaxHeight = 250f;
private const float WindowPaddingOffset = 6f;
private const float SlideAnimationDistance = 100f;
private const float OutAnimationSpeedMultiplier = 0.7f;
private const float ContentPaddingX = 10f;
private const float ContentPaddingY = 6f;
private const float TitleMessageSpacing = 4f;
private const float ActionButtonSpacing = 8f;
private const float _notificationMinHeight = 60f;
private const float _notificationMaxHeight = 250f;
private const float _windowPaddingOffset = 6f;
private const float _slideAnimationDistance = 100f;
private const float _outAnimationSpeedMultiplier = 0.7f;
private const float _contentPaddingX = 10f;
private const float _contentPaddingY = 6f;
private const float _titleMessageSpacing = 4f;
private const float _actionButtonSpacing = 8f;
private readonly List<LightlessNotification> _notifications = new();
private readonly object _notificationLock = new();
@@ -33,7 +33,7 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
private readonly Dictionary<string, float> _notificationYOffsets = new();
private readonly Dictionary<string, float> _notificationTargetYOffsets = new();
public LightlessNotificationUI(ILogger<LightlessNotificationUI> logger, LightlessMediator mediator, PerformanceCollectorService performanceCollector, LightlessConfigService configService)
public LightlessNotificationUi(ILogger<LightlessNotificationUi> logger, LightlessMediator mediator, PerformanceCollectorService performanceCollector, LightlessConfigService configService)
: base(logger, mediator, "Lightless Notifications##LightlessNotifications", performanceCollector)
{
_configService = configService;
@@ -155,8 +155,8 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
var width = _configService.Current.NotificationWidth;
float posX = corner == NotificationCorner.Left
? viewport.WorkPos.X + offsetX - WindowPaddingOffset
: viewport.WorkPos.X + viewport.WorkSize.X - width - offsetX - WindowPaddingOffset;
? viewport.WorkPos.X + offsetX - _windowPaddingOffset
: viewport.WorkPos.X + viewport.WorkSize.X - width - offsetX - _windowPaddingOffset;
return new Vector2(posX, viewport.WorkPos.Y);
}
@@ -274,7 +274,7 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
else if (notification.IsAnimatingOut && notification.AnimationProgress > 0f)
{
notification.AnimationProgress = Math.Max(0f,
notification.AnimationProgress - deltaTime * _configService.Current.NotificationAnimationSpeed * OutAnimationSpeedMultiplier);
notification.AnimationProgress - deltaTime * _configService.Current.NotificationAnimationSpeed * _outAnimationSpeedMultiplier);
}
else if (!notification.IsAnimatingOut && !notification.IsDismissed)
{
@@ -289,7 +289,7 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
private Vector2 CalculateSlideOffset(float alpha)
{
var distance = (1f - alpha) * SlideAnimationDistance;
var distance = (1f - alpha) * _slideAnimationDistance;
var corner = _configService.Current.NotificationCorner;
return corner == NotificationCorner.Left ? new Vector2(-distance, 0) : new Vector2(distance, 0);
}
@@ -466,7 +466,7 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
private void DrawNotificationText(LightlessNotification notification, float alpha)
{
var contentPos = new Vector2(ContentPaddingX, ContentPaddingY);
var contentPos = new Vector2(_contentPaddingX, _contentPaddingY);
var windowSize = ImGui.GetWindowSize();
var contentWidth = CalculateContentWidth(windowSize.X);
@@ -483,7 +483,7 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
}
private float CalculateContentWidth(float windowWidth) =>
windowWidth - (ContentPaddingX * 2);
windowWidth - (_contentPaddingX * 2);
private bool HasActions(LightlessNotification notification) =>
notification.Actions.Count > 0;
@@ -491,9 +491,9 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
private void PositionActionsAtBottom(float windowHeight)
{
var actionHeight = ImGui.GetFrameHeight();
var bottomY = windowHeight - ContentPaddingY - actionHeight;
var bottomY = windowHeight - _contentPaddingY - actionHeight;
ImGui.SetCursorPosY(bottomY);
ImGui.SetCursorPosX(ContentPaddingX);
ImGui.SetCursorPosX(_contentPaddingX);
}
private float DrawTitle(LightlessNotification notification, float contentWidth, float alpha)
@@ -530,7 +530,7 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
{
if (string.IsNullOrEmpty(notification.Message)) return;
var messagePos = contentPos + new Vector2(0f, titleHeight + TitleMessageSpacing);
var messagePos = contentPos + new Vector2(0f, titleHeight + _titleMessageSpacing);
var messageColor = new Vector4(0.9f, 0.9f, 0.9f, alpha);
ImGui.SetCursorPos(messagePos);
@@ -563,13 +563,13 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
private float CalculateActionButtonWidth(int actionCount, float availableWidth)
{
var totalSpacing = (actionCount - 1) * ActionButtonSpacing;
var totalSpacing = (actionCount - 1) * _actionButtonSpacing;
return (availableWidth - totalSpacing) / actionCount;
}
private void PositionActionButton(int index, float startX, float buttonWidth)
{
var xPosition = startX + index * (buttonWidth + ActionButtonSpacing);
var xPosition = startX + index * (buttonWidth + _actionButtonSpacing);
ImGui.SetCursorPosX(xPosition);
}
@@ -687,7 +687,7 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
height += 12f;
}
return Math.Clamp(height, NotificationMinHeight, NotificationMaxHeight);
return Math.Clamp(height, _notificationMinHeight, _notificationMaxHeight);
}
private float CalculateTitleHeight(LightlessNotification notification, float contentWidth)

View File

@@ -63,7 +63,6 @@ public class SettingsUi : WindowMediatorSubscriberBase
private readonly IProgress<(int, int, FileCacheEntity)> _validationProgress;
private readonly NameplateService _nameplateService;
private readonly NameplateHandler _nameplateHandler;
private readonly NotificationService _lightlessNotificationService;
private (int, int, FileCacheEntity) _currentProgress;
private bool _deleteAccountPopupModalShown = false;
private bool _deleteFilesPopupModalShown = false;
@@ -107,8 +106,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
IpcManager ipcManager, CacheMonitor cacheMonitor,
DalamudUtilService dalamudUtilService, HttpClient httpClient,
NameplateService nameplateService,
NameplateHandler nameplateHandler,
NotificationService lightlessNotificationService) : base(logger, mediator, "Lightless Sync Settings",
NameplateHandler nameplateHandler) : base(logger, mediator, "Lightless Sync Settings",
performanceCollector)
{
_configService = configService;
@@ -130,7 +128,6 @@ public class SettingsUi : WindowMediatorSubscriberBase
_uiShared = uiShared;
_nameplateService = nameplateService;
_nameplateHandler = nameplateHandler;
_lightlessNotificationService = lightlessNotificationService;
AllowClickthrough = false;
AllowPinning = true;
_validationProgress = new Progress<(int, int, FileCacheEntity)>(v => _currentProgress = v);
@@ -3616,20 +3613,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
{
if (ImGui.Button($"{FontAwesomeIcon.Play.ToIconString()}##test_pair", new Vector2(availableWidth, 0)))
{
_lightlessNotificationService.ShowPairRequestNotification(
"Test User",
"test-uid-123",
() =>
{
Mediator.Publish(new NotificationMessage("Accepted", "You accepted the test pair request.",
NotificationType.Info));
},
() =>
{
Mediator.Publish(new NotificationMessage("Declined", "You declined the test pair request.",
NotificationType.Info));
}
);
Mediator.Publish(new PairRequestReceivedMessage("test-uid-123", "Test User wants to pair with you."));
}
}
UiSharedService.AttachToolTip("Test pair request notification");
@@ -3652,15 +3636,14 @@ public class SettingsUi : WindowMediatorSubscriberBase
{
if (ImGui.Button($"{FontAwesomeIcon.Play.ToIconString()}##test_download", new Vector2(availableWidth, 0)))
{
_lightlessNotificationService.ShowPairDownloadNotification(
new List<(string playerName, float progress, string status)>
{
Mediator.Publish(new PairDownloadStatusMessage(
[
("Player One", 0.35f, "downloading"),
("Player Two", 0.75f, "downloading"),
("Player Three", 1.0f, "downloading")
},
queueWaiting: 2
);
],
2
));
}
}
UiSharedService.AttachToolTip("Test download progress notification");

View File

@@ -52,12 +52,12 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
private float _particleSpawnTimer;
private readonly Random _random = new();
private const float HeaderHeight = 150f;
private const float ParticleSpawnInterval = 0.2f;
private const int MaxParticles = 50;
private const int MaxTrailLength = 50;
private const float EdgeFadeDistance = 30f;
private const float ExtendedParticleHeight = 40f;
private const float _headerHeight = 150f;
private const float _particleSpawnInterval = 0.2f;
private const int _maxParticles = 50;
private const int _maxTrailLength = 50;
private const float _edgeFadeDistance = 30f;
private const float _extendedParticleHeight = 40f;
public UpdateNotesUi(ILogger<UpdateNotesUi> logger,
LightlessMediator mediator,
@@ -111,16 +111,16 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
var headerWidth = (800f * ImGuiHelpers.GlobalScale) - (windowPadding.X * 2);
var headerStart = windowPos + new Vector2(windowPadding.X, windowPadding.Y);
var headerEnd = headerStart + new Vector2(headerWidth, HeaderHeight);
var headerEnd = headerStart + new Vector2(headerWidth, _headerHeight);
var extendedParticleSize = new Vector2(headerWidth, HeaderHeight + ExtendedParticleHeight);
var extendedParticleSize = new Vector2(headerWidth, _headerHeight + _extendedParticleHeight);
DrawGradientBackground(headerStart, headerEnd);
DrawHeaderText(headerStart);
DrawHeaderButtons(headerStart, headerWidth);
DrawBottomGradient(headerStart, headerEnd, headerWidth);
ImGui.SetCursorPosY(windowPadding.Y + HeaderHeight + 5);
ImGui.SetCursorPosY(windowPadding.Y + _headerHeight + 5);
ImGui.SetCursorPosX(20);
using (ImRaii.PushFont(UiBuilder.IconFont))
{
@@ -260,7 +260,7 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
var deltaTime = ImGui.GetIO().DeltaTime;
_particleSpawnTimer += deltaTime;
if (_particleSpawnTimer > ParticleSpawnInterval && _particles.Count < MaxParticles)
if (_particleSpawnTimer > _particleSpawnInterval && _particles.Count < _maxParticles)
{
SpawnParticle(bannerSize);
_particleSpawnTimer = 0f;
@@ -282,7 +282,7 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
if (particle.Type == ParticleType.ShootingStar && particle.Trail != null)
{
particle.Trail.Insert(0, particle.Position);
if (particle.Trail.Count > MaxTrailLength)
if (particle.Trail.Count > _maxTrailLength)
particle.Trail.RemoveAt(particle.Trail.Count - 1);
}
@@ -316,12 +316,12 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
var lifeFade = Math.Min(fadeIn, fadeOut);
var edgeFadeX = Math.Min(
Math.Min(1f, (particle.Position.X + EdgeFadeDistance) / EdgeFadeDistance),
Math.Min(1f, (bannerSize.X - particle.Position.X + EdgeFadeDistance) / EdgeFadeDistance)
Math.Min(1f, (particle.Position.X + _edgeFadeDistance) / _edgeFadeDistance),
Math.Min(1f, (bannerSize.X - particle.Position.X + _edgeFadeDistance) / _edgeFadeDistance)
);
var edgeFadeY = Math.Min(
Math.Min(1f, (particle.Position.Y + EdgeFadeDistance) / EdgeFadeDistance),
Math.Min(1f, (bannerSize.Y - particle.Position.Y + EdgeFadeDistance) / EdgeFadeDistance)
Math.Min(1f, (particle.Position.Y + _edgeFadeDistance) / _edgeFadeDistance),
Math.Min(1f, (bannerSize.Y - particle.Position.Y + _edgeFadeDistance) / _edgeFadeDistance)
);
var edgeFade = Math.Min(edgeFadeX, edgeFadeY);