diff --git a/LightlessSync/UI/DownloadUi.cs b/LightlessSync/UI/DownloadUi.cs index 301f177..93cc623 100644 --- a/LightlessSync/UI/DownloadUi.cs +++ b/LightlessSync/UI/DownloadUi.cs @@ -24,6 +24,7 @@ public class DownloadUi : WindowMediatorSubscriberBase private readonly ConcurrentDictionary _uploadingPlayers = new(); private readonly NotificationService _notificationService; private bool _notificationDismissed = true; + private int _lastDownloadStateHash = 0; public DownloadUi(ILogger logger, DalamudUtilService dalamudUtilService, LightlessConfigService configService, PairProcessingLimiter pairProcessingLimiter, FileUploadManager fileTransferManager, LightlessMediator mediator, UiSharedService uiShared, @@ -128,16 +129,17 @@ public class DownloadUi : WindowMediatorSubscriberBase if (useNotifications) { - // Use notification system + // Use notification system - only update when data actually changes if (_currentDownloads.Any()) { - UpdateDownloadNotification(limiterSnapshot); + UpdateDownloadNotificationIfChanged(limiterSnapshot); _notificationDismissed = false; } else if (!_notificationDismissed) { _notificationService.DismissPairDownloadNotification(); _notificationDismissed = true; + _lastDownloadStateHash = 0; } } else @@ -298,20 +300,34 @@ public class DownloadUi : WindowMediatorSubscriberBase }; } - private void UpdateDownloadNotification(PairProcessingLimiterSnapshot limiterSnapshot) + private void UpdateDownloadNotificationIfChanged(PairProcessingLimiterSnapshot limiterSnapshot) { - var downloadStatus = new List<(string playerName, float progress, string status)>(); + var downloadStatus = new List<(string playerName, float progress, string status)>(_currentDownloads.Count); + var hashCode = new HashCode(); - foreach (var item in _currentDownloads.ToList()) + foreach (var item in _currentDownloads) { - var dlSlot = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.WaitingForSlot); - var dlQueue = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.WaitingForQueue); - var dlProg = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.Downloading); - var dlDecomp = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.Decompressing); - var totalFiles = item.Value.Sum(c => c.Value.TotalFiles); - var transferredFiles = item.Value.Sum(c => c.Value.TransferredFiles); - var totalBytes = item.Value.Sum(c => c.Value.TotalBytes); - var transferredBytes = item.Value.Sum(c => c.Value.TransferredBytes); + var dlSlot = 0; + var dlQueue = 0; + var dlProg = 0; + var dlDecomp = 0; + long totalBytes = 0; + long transferredBytes = 0; + + // Single pass through the dictionary to count everything - avoid multiple LINQ iterations + foreach (var entry in item.Value) + { + var fileStatus = entry.Value; + switch (fileStatus.DownloadStatus) + { + case DownloadStatus.WaitingForSlot: dlSlot++; break; + case DownloadStatus.WaitingForQueue: dlQueue++; break; + case DownloadStatus.Downloading: dlProg++; break; + case DownloadStatus.Decompressing: dlDecomp++; break; + } + totalBytes += fileStatus.TotalBytes; + transferredBytes += fileStatus.TransferredBytes; + } var progress = totalBytes > 0 ? (float)transferredBytes / totalBytes : 0f; @@ -323,13 +339,27 @@ public class DownloadUi : WindowMediatorSubscriberBase else status = "completed"; downloadStatus.Add((item.Key.Name, progress, status)); + + // Build hash from meaningful state + hashCode.Add(item.Key.Name); + hashCode.Add(transferredBytes); + hashCode.Add(totalBytes); + hashCode.Add(status); } - // Pass queue waiting count separately, show notification if there are downloads or queue items var queueWaiting = limiterSnapshot.IsEnabled ? limiterSnapshot.Waiting : 0; - if (downloadStatus.Any() || queueWaiting > 0) + hashCode.Add(queueWaiting); + + var currentHash = hashCode.ToHashCode(); + + // Only update notification if state has actually changed + if (currentHash != _lastDownloadStateHash) { - _notificationService.ShowPairDownloadNotification(downloadStatus, queueWaiting); + _lastDownloadStateHash = currentHash; + if (downloadStatus.Count > 0 || queueWaiting > 0) + { + _notificationService.ShowPairDownloadNotification(downloadStatus, queueWaiting); + } } } diff --git a/LightlessSync/UI/LightlessNotificationUI.cs b/LightlessSync/UI/LightlessNotificationUI.cs index 36fa508..7ced889 100644 --- a/LightlessSync/UI/LightlessNotificationUI.cs +++ b/LightlessSync/UI/LightlessNotificationUI.cs @@ -134,11 +134,7 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase var viewport = ImGui.GetMainViewport(); - // Set window to full viewport height - var width = _configService.Current.NotificationWidth; - Size = new Vector2(width, viewport.WorkSize.Y); - SizeCondition = ImGuiCond.Always; - + // Window auto-resizes based on content (AlwaysAutoResize flag) Position = CalculateWindowPosition(viewport); PositionCondition = ImGuiCond.Always;