From 8692e877cf377a8488cfb86ae011f4e9a5323c6d Mon Sep 17 00:00:00 2001 From: choco Date: Mon, 10 Nov 2025 10:59:42 +0100 Subject: [PATCH 1/6] download notification stuck fix, more x and y offset positions --- LightlessSync/Services/NotificationService.cs | 11 --------- LightlessSync/UI/DownloadUi.cs | 10 ++++---- LightlessSync/UI/LightlessNotificationUI.cs | 6 +++++ LightlessSync/UI/SettingsUi.cs | 24 +++++++++---------- 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/LightlessSync/Services/NotificationService.cs b/LightlessSync/Services/NotificationService.cs index 72f4a16..8709710 100644 --- a/LightlessSync/Services/NotificationService.cs +++ b/LightlessSync/Services/NotificationService.cs @@ -342,12 +342,6 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ _ => download.Status }; - private bool AreAllDownloadsCompleted(List<(string PlayerName, float Progress, string Status)> userDownloads) => - userDownloads.Any() && userDownloads.All(x => x.Progress >= 1.0f); - - public void DismissPairDownloadNotification() => - Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress")); - private TimeSpan GetDefaultDurationForType(NotificationType type) => type switch { NotificationType.Info => TimeSpan.FromSeconds(_configService.Current.InfoNotificationDurationSeconds), @@ -607,11 +601,6 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ }; Mediator.Publish(new LightlessNotificationMessage(notification)); - - if (userDownloads.Count == 0 || AreAllDownloadsCompleted(userDownloads)) - { - Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress")); - } } private void HandlePerformanceNotification(PerformanceNotificationMessage msg) diff --git a/LightlessSync/UI/DownloadUi.cs b/LightlessSync/UI/DownloadUi.cs index a592e43..2761b59 100644 --- a/LightlessSync/UI/DownloadUi.cs +++ b/LightlessSync/UI/DownloadUi.cs @@ -58,14 +58,14 @@ public class DownloadUi : WindowMediatorSubscriberBase IsOpen = true; - Mediator.Subscribe(this, (msg) => _currentDownloads[msg.DownloadId] = msg.DownloadStatus); + Mediator.Subscribe(this, (msg) => + { + _currentDownloads[msg.DownloadId] = msg.DownloadStatus; + _notificationDismissed = false; + }); Mediator.Subscribe(this, (msg) => { _currentDownloads.TryRemove(msg.DownloadId, out _); - if (!_currentDownloads.Any()) - { - Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress")); - } }); Mediator.Subscribe(this, (_) => IsOpen = false); Mediator.Subscribe(this, (_) => IsOpen = true); diff --git a/LightlessSync/UI/LightlessNotificationUI.cs b/LightlessSync/UI/LightlessNotificationUI.cs index 3d2d748..2d412f2 100644 --- a/LightlessSync/UI/LightlessNotificationUI.cs +++ b/LightlessSync/UI/LightlessNotificationUI.cs @@ -86,6 +86,12 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase existing.Progress = updated.Progress; existing.ShowProgress = updated.ShowProgress; existing.Title = updated.Title; + + if (updated.Type == NotificationType.Download && updated.Progress < 1.0f) + { + existing.CreatedAt = DateTime.UtcNow; + } + _logger.LogDebug("Updated existing notification: {Title}", updated.Title); } diff --git a/LightlessSync/UI/SettingsUi.cs b/LightlessSync/UI/SettingsUi.cs index febc142..4054853 100644 --- a/LightlessSync/UI/SettingsUi.cs +++ b/LightlessSync/UI/SettingsUi.cs @@ -3851,9 +3851,9 @@ public class SettingsUi : WindowMediatorSubscriberBase _uiShared.DrawHelpText("Choose which corner of the screen notifications appear in."); int offsetY = _configService.Current.NotificationOffsetY; - if (ImGui.SliderInt("Vertical Offset", ref offsetY, 0, 1000)) + if (ImGui.SliderInt("Vertical Offset", ref offsetY, 0, 5000)) { - _configService.Current.NotificationOffsetY = Math.Clamp(offsetY, 0, 1000); + _configService.Current.NotificationOffsetY = Math.Clamp(offsetY, 0, 5000); _configService.Save(); } if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) @@ -3866,9 +3866,9 @@ public class SettingsUi : WindowMediatorSubscriberBase _uiShared.DrawHelpText("Distance from the top edge of the screen."); int offsetX = _configService.Current.NotificationOffsetX; - if (ImGui.SliderInt("Horizontal Offset", ref offsetX, 0, 500)) + if (ImGui.SliderInt("Horizontal Offset", ref offsetX, 0, 2500)) { - _configService.Current.NotificationOffsetX = Math.Clamp(offsetX, 0, 500); + _configService.Current.NotificationOffsetX = Math.Clamp(offsetX, 0, 2500); _configService.Save(); } if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) @@ -3985,9 +3985,9 @@ public class SettingsUi : WindowMediatorSubscriberBase ImGui.SetTooltip("Right click to reset to default (20)."); int pairRequestDuration = _configService.Current.PairRequestDurationSeconds; - if (ImGui.SliderInt("Pair Request Duration (seconds)", ref pairRequestDuration, 30, 600)) + if (ImGui.SliderInt("Pair Request Duration (seconds)", ref pairRequestDuration, 30, 1800)) { - _configService.Current.PairRequestDurationSeconds = Math.Clamp(pairRequestDuration, 30, 600); + _configService.Current.PairRequestDurationSeconds = Math.Clamp(pairRequestDuration, 30, 1800); _configService.Save(); } if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) @@ -3999,23 +3999,23 @@ public class SettingsUi : WindowMediatorSubscriberBase ImGui.SetTooltip("Right click to reset to default (180)."); int downloadDuration = _configService.Current.DownloadNotificationDurationSeconds; - if (ImGui.SliderInt("Download Duration (seconds)", ref downloadDuration, 60, 600)) + if (ImGui.SliderInt("Download Duration (seconds)", ref downloadDuration, 60, 120)) { - _configService.Current.DownloadNotificationDurationSeconds = Math.Clamp(downloadDuration, 60, 600); + _configService.Current.DownloadNotificationDurationSeconds = Math.Clamp(downloadDuration, 60, 120); _configService.Save(); } if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) { - _configService.Current.DownloadNotificationDurationSeconds = 300; + _configService.Current.DownloadNotificationDurationSeconds = 30; _configService.Save(); } if (ImGui.IsItemHovered()) - ImGui.SetTooltip("Right click to reset to default (300)."); + ImGui.SetTooltip("Right click to reset to default (30)."); int performanceDuration = _configService.Current.PerformanceNotificationDurationSeconds; - if (ImGui.SliderInt("Performance Duration (seconds)", ref performanceDuration, 5, 60)) + if (ImGui.SliderInt("Performance Duration (seconds)", ref performanceDuration, 5, 120)) { - _configService.Current.PerformanceNotificationDurationSeconds = Math.Clamp(performanceDuration, 5, 60); + _configService.Current.PerformanceNotificationDurationSeconds = Math.Clamp(performanceDuration, 5, 120); _configService.Save(); } if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) From c02a8ed2eee044c845083779532f4df5b9ddd4a3 Mon Sep 17 00:00:00 2001 From: choco Date: Mon, 10 Nov 2025 20:57:43 +0100 Subject: [PATCH 2/6] notification clickthrougable, update notes centered in the middle of the screen unmovable --- LightlessSync/UI/LightlessNotificationUI.cs | 3 +++ LightlessSync/UI/UpdateNotesUi.cs | 13 ++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/LightlessSync/UI/LightlessNotificationUI.cs b/LightlessSync/UI/LightlessNotificationUI.cs index 2d412f2..65a6c69 100644 --- a/LightlessSync/UI/LightlessNotificationUI.cs +++ b/LightlessSync/UI/LightlessNotificationUI.cs @@ -45,6 +45,9 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase ImGuiWindowFlags.NoNav | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoCollapse | + ImGuiWindowFlags.NoInputs | + ImGuiWindowFlags.NoTitleBar | + ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.AlwaysAutoResize; PositionCondition = ImGuiCond.Always; diff --git a/LightlessSync/UI/UpdateNotesUi.cs b/LightlessSync/UI/UpdateNotesUi.cs index bc60ab5..02e0b4d 100644 --- a/LightlessSync/UI/UpdateNotesUi.cs +++ b/LightlessSync/UI/UpdateNotesUi.cs @@ -76,13 +76,15 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase ShowCloseButton = true; Flags = ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | - ImGuiWindowFlags.NoTitleBar; + ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoMove; SizeConstraints = new WindowSizeConstraints() { MinimumSize = new Vector2(800, 700), MaximumSize = new Vector2(800, 700), }; + PositionCondition = ImGuiCond.Always; + LoadEmbeddedResources(); logger.LogInformation("UpdateNotesUi constructor completed successfully"); } @@ -93,11 +95,20 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase _hasInitializedCollapsingHeaders = false; } + private void CenterWindow() + { + var viewport = ImGui.GetMainViewport(); + var center = viewport.GetCenter(); + var windowSize = new Vector2(800f * ImGuiHelpers.GlobalScale, 700f * ImGuiHelpers.GlobalScale); + Position = center - windowSize / 2f; + } + protected override void DrawInternal() { if (_uiShared.IsInGpose) return; + CenterWindow(); DrawHeader(); ImGuiHelpers.ScaledDummy(6); DrawTabs(); From f89ce900c776a4e49c71492c1ca6f3b08bb2a8e6 Mon Sep 17 00:00:00 2001 From: choco Date: Mon, 10 Nov 2025 21:05:39 +0100 Subject: [PATCH 3/6] more offset changes accepting minus for notifications till -2500 --- LightlessSync/UI/SettingsUi.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LightlessSync/UI/SettingsUi.cs b/LightlessSync/UI/SettingsUi.cs index 4054853..f1da3c0 100644 --- a/LightlessSync/UI/SettingsUi.cs +++ b/LightlessSync/UI/SettingsUi.cs @@ -3851,9 +3851,9 @@ public class SettingsUi : WindowMediatorSubscriberBase _uiShared.DrawHelpText("Choose which corner of the screen notifications appear in."); int offsetY = _configService.Current.NotificationOffsetY; - if (ImGui.SliderInt("Vertical Offset", ref offsetY, 0, 5000)) + if (ImGui.SliderInt("Vertical Offset", ref offsetY, -2500, 2500)) { - _configService.Current.NotificationOffsetY = Math.Clamp(offsetY, 0, 5000); + _configService.Current.NotificationOffsetY = Math.Clamp(offsetY, -2500, 2500); _configService.Save(); } if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) @@ -3866,9 +3866,9 @@ public class SettingsUi : WindowMediatorSubscriberBase _uiShared.DrawHelpText("Distance from the top edge of the screen."); int offsetX = _configService.Current.NotificationOffsetX; - if (ImGui.SliderInt("Horizontal Offset", ref offsetX, 0, 2500)) + if (ImGui.SliderInt("Horizontal Offset", ref offsetX, -2500, 2500)) { - _configService.Current.NotificationOffsetX = Math.Clamp(offsetX, 0, 2500); + _configService.Current.NotificationOffsetX = Math.Clamp(offsetX, -2500, 2500); _configService.Save(); } if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) From 25b03aea15ef7235509343e7af753ee617acae24 Mon Sep 17 00:00:00 2001 From: choco Date: Mon, 10 Nov 2025 21:22:28 +0100 Subject: [PATCH 4/6] download dismiss message if downloads are complete --- LightlessSync/UI/DownloadUi.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/LightlessSync/UI/DownloadUi.cs b/LightlessSync/UI/DownloadUi.cs index 2761b59..275b338 100644 --- a/LightlessSync/UI/DownloadUi.cs +++ b/LightlessSync/UI/DownloadUi.cs @@ -66,6 +66,14 @@ public class DownloadUi : WindowMediatorSubscriberBase Mediator.Subscribe(this, (msg) => { _currentDownloads.TryRemove(msg.DownloadId, out _); + + // Dismiss notification if all downloads are complete + if (!_currentDownloads.Any() && !_notificationDismissed) + { + Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress")); + _notificationDismissed = true; + _lastDownloadStateHash = 0; + } }); Mediator.Subscribe(this, (_) => IsOpen = false); Mediator.Subscribe(this, (_) => IsOpen = true); From 41a303dc9136d97aa1c23291536cb01a2daa633e Mon Sep 17 00:00:00 2001 From: choco Date: Mon, 10 Nov 2025 21:29:55 +0100 Subject: [PATCH 5/6] auto dismiss notifs if no updates --- LightlessSync/UI/DownloadUi.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/LightlessSync/UI/DownloadUi.cs b/LightlessSync/UI/DownloadUi.cs index 275b338..4f64c38 100644 --- a/LightlessSync/UI/DownloadUi.cs +++ b/LightlessSync/UI/DownloadUi.cs @@ -24,6 +24,8 @@ public class DownloadUi : WindowMediatorSubscriberBase private readonly ConcurrentDictionary _uploadingPlayers = new(); private bool _notificationDismissed = true; private int _lastDownloadStateHash = 0; + private DateTime _lastNotificationUpdate = DateTime.MinValue; + private const int NotificationAutoCloseSeconds = 15; public DownloadUi(ILogger logger, DalamudUtilService dalamudUtilService, LightlessConfigService configService, PairProcessingLimiter pairProcessingLimiter, FileUploadManager fileTransferManager, LightlessMediator mediator, UiSharedService uiShared, @@ -147,6 +149,20 @@ public class DownloadUi : WindowMediatorSubscriberBase _notificationDismissed = true; _lastDownloadStateHash = 0; } + + // Auto-dismiss notification if no updates for 15 seconds + if (!_notificationDismissed && _lastNotificationUpdate != DateTime.MinValue) + { + var timeSinceLastUpdate = (DateTime.UtcNow - _lastNotificationUpdate).TotalSeconds; + if (timeSinceLastUpdate > NotificationAutoCloseSeconds) + { + _logger.LogDebug("Auto-dismissing download notification after {Seconds}s of inactivity", timeSinceLastUpdate); + Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress")); + _notificationDismissed = true; + _lastDownloadStateHash = 0; + _lastNotificationUpdate = DateTime.MinValue; + } + } } else { @@ -363,11 +379,11 @@ public class DownloadUi : WindowMediatorSubscriberBase if (currentHash != _lastDownloadStateHash) { _lastDownloadStateHash = currentHash; + _lastNotificationUpdate = DateTime.UtcNow; if (downloadStatus.Count > 0 || queueWaiting > 0) { Mediator.Publish(new PairDownloadStatusMessage(downloadStatus, queueWaiting)); } } } - } \ No newline at end of file From 95e7f2daa7607676e38bc8d55524358553e4db0c Mon Sep 17 00:00:00 2001 From: choco Date: Mon, 10 Nov 2025 21:59:20 +0100 Subject: [PATCH 6/6] download notification progress and download bar, chat only option for notifications (idk why you would bother even enabling the lightless nofis then) --- .../Configurations/LightlessConfig.cs | 2 +- LightlessSync/UI/DownloadUi.cs | 17 --------- LightlessSync/UI/LightlessNotificationUI.cs | 35 +++++++++++++++---- LightlessSync/UI/SettingsUi.cs | 6 ++-- 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/LightlessSync/LightlessConfiguration/Configurations/LightlessConfig.cs b/LightlessSync/LightlessConfiguration/Configurations/LightlessConfig.cs index f849c87..929cbbc 100644 --- a/LightlessSync/LightlessConfiguration/Configurations/LightlessConfig.cs +++ b/LightlessSync/LightlessConfiguration/Configurations/LightlessConfig.cs @@ -113,7 +113,7 @@ public class LightlessConfig : ILightlessConfiguration public int WarningNotificationDurationSeconds { get; set; } = 15; public int ErrorNotificationDurationSeconds { get; set; } = 20; public int PairRequestDurationSeconds { get; set; } = 180; - public int DownloadNotificationDurationSeconds { get; set; } = 300; + public int DownloadNotificationDurationSeconds { get; set; } = 30; public int PerformanceNotificationDurationSeconds { get; set; } = 20; public uint CustomInfoSoundId { get; set; } = 2; // Se2 public uint CustomWarningSoundId { get; set; } = 16; // Se15 diff --git a/LightlessSync/UI/DownloadUi.cs b/LightlessSync/UI/DownloadUi.cs index 4f64c38..aa3132a 100644 --- a/LightlessSync/UI/DownloadUi.cs +++ b/LightlessSync/UI/DownloadUi.cs @@ -24,8 +24,6 @@ public class DownloadUi : WindowMediatorSubscriberBase private readonly ConcurrentDictionary _uploadingPlayers = new(); private bool _notificationDismissed = true; private int _lastDownloadStateHash = 0; - private DateTime _lastNotificationUpdate = DateTime.MinValue; - private const int NotificationAutoCloseSeconds = 15; public DownloadUi(ILogger logger, DalamudUtilService dalamudUtilService, LightlessConfigService configService, PairProcessingLimiter pairProcessingLimiter, FileUploadManager fileTransferManager, LightlessMediator mediator, UiSharedService uiShared, @@ -149,20 +147,6 @@ public class DownloadUi : WindowMediatorSubscriberBase _notificationDismissed = true; _lastDownloadStateHash = 0; } - - // Auto-dismiss notification if no updates for 15 seconds - if (!_notificationDismissed && _lastNotificationUpdate != DateTime.MinValue) - { - var timeSinceLastUpdate = (DateTime.UtcNow - _lastNotificationUpdate).TotalSeconds; - if (timeSinceLastUpdate > NotificationAutoCloseSeconds) - { - _logger.LogDebug("Auto-dismissing download notification after {Seconds}s of inactivity", timeSinceLastUpdate); - Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress")); - _notificationDismissed = true; - _lastDownloadStateHash = 0; - _lastNotificationUpdate = DateTime.MinValue; - } - } } else { @@ -379,7 +363,6 @@ public class DownloadUi : WindowMediatorSubscriberBase if (currentHash != _lastDownloadStateHash) { _lastDownloadStateHash = currentHash; - _lastNotificationUpdate = DateTime.UtcNow; if (downloadStatus.Count > 0 || queueWaiting > 0) { Mediator.Publish(new PairDownloadStatusMessage(downloadStatus, queueWaiting)); diff --git a/LightlessSync/UI/LightlessNotificationUI.cs b/LightlessSync/UI/LightlessNotificationUI.cs index 65a6c69..8cb6922 100644 --- a/LightlessSync/UI/LightlessNotificationUI.cs +++ b/LightlessSync/UI/LightlessNotificationUI.cs @@ -90,7 +90,8 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase existing.ShowProgress = updated.ShowProgress; existing.Title = updated.Title; - if (updated.Type == NotificationType.Download && updated.Progress < 1.0f) + // Reset the duration timer on every update for download notifications + if (updated.Type == NotificationType.Download) { existing.CreatedAt = DateTime.UtcNow; } @@ -344,6 +345,13 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase DrawBackground(drawList, windowPos, windowSize, bgColor); DrawAccentBar(drawList, windowPos, windowSize, accentColor); DrawDurationProgressBar(notification, alpha, windowPos, windowSize, drawList); + + // Draw download progress bar above duration bar for download notifications + if (notification.Type == NotificationType.Download && notification.ShowProgress) + { + DrawDownloadProgressBar(notification, alpha, windowPos, windowSize, drawList); + } + DrawNotificationText(notification, alpha); } @@ -425,7 +433,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase private void DrawDurationProgressBar(LightlessNotification notification, float alpha, Vector2 windowPos, Vector2 windowSize, ImDrawListPtr drawList) { - var progress = CalculateProgress(notification); + var progress = CalculateDurationProgress(notification); var progressBarColor = UIColors.Get("LightlessBlue"); var progressHeight = 2f; var progressY = windowPos.Y + windowSize.Y - progressHeight; @@ -439,13 +447,26 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase } } - private float CalculateProgress(LightlessNotification notification) + private void DrawDownloadProgressBar(LightlessNotification notification, float alpha, Vector2 windowPos, Vector2 windowSize, ImDrawListPtr drawList) { - if (notification.Type == NotificationType.Download && notification.ShowProgress) - { - return Math.Clamp(notification.Progress, 0f, 1f); - } + var progress = Math.Clamp(notification.Progress, 0f, 1f); + var progressBarColor = UIColors.Get("LightlessGreen"); + var progressHeight = 3f; + // Position above the duration bar (2px duration bar + 1px spacing) + var progressY = windowPos.Y + windowSize.Y - progressHeight - 3f; + var progressWidth = windowSize.X * progress; + DrawProgressBackground(drawList, windowPos, windowSize, progressY, progressHeight, progressBarColor, alpha); + + if (progress > 0) + { + DrawProgressForeground(drawList, windowPos, progressY, progressHeight, progressWidth, progressBarColor, alpha); + } + } + + private float CalculateDurationProgress(LightlessNotification notification) + { + // Calculate duration timer progress var elapsed = DateTime.UtcNow - notification.CreatedAt; return Math.Min(1.0f, (float)(elapsed.TotalSeconds / notification.Duration.TotalSeconds)); } diff --git a/LightlessSync/UI/SettingsUi.cs b/LightlessSync/UI/SettingsUi.cs index c841fd7..1b8aa12 100644 --- a/LightlessSync/UI/SettingsUi.cs +++ b/LightlessSync/UI/SettingsUi.cs @@ -3993,9 +3993,9 @@ public class SettingsUi : WindowMediatorSubscriberBase ImGui.SetTooltip("Right click to reset to default (180)."); int downloadDuration = _configService.Current.DownloadNotificationDurationSeconds; - if (ImGui.SliderInt("Download Duration (seconds)", ref downloadDuration, 60, 120)) + if (ImGui.SliderInt("Download Duration (seconds)", ref downloadDuration, 15, 120)) { - _configService.Current.DownloadNotificationDurationSeconds = Math.Clamp(downloadDuration, 60, 120); + _configService.Current.DownloadNotificationDurationSeconds = Math.Clamp(downloadDuration, 15, 120); _configService.Save(); } if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) @@ -4144,7 +4144,7 @@ public class SettingsUi : WindowMediatorSubscriberBase { return new[] { - NotificationLocation.LightlessUi, NotificationLocation.ChatAndLightlessUi, NotificationLocation.Nowhere + NotificationLocation.LightlessUi, NotificationLocation.Chat, NotificationLocation.ChatAndLightlessUi, NotificationLocation.Nowhere }; }