Merge branch '1.12.4' into linux-improvements

This commit is contained in:
2025-11-11 17:12:51 +01:00
6 changed files with 72 additions and 35 deletions

View File

@@ -113,7 +113,7 @@ public class LightlessConfig : ILightlessConfiguration
public int WarningNotificationDurationSeconds { get; set; } = 15; public int WarningNotificationDurationSeconds { get; set; } = 15;
public int ErrorNotificationDurationSeconds { get; set; } = 20; public int ErrorNotificationDurationSeconds { get; set; } = 20;
public int PairRequestDurationSeconds { get; set; } = 180; 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 int PerformanceNotificationDurationSeconds { get; set; } = 20;
public uint CustomInfoSoundId { get; set; } = 2; // Se2 public uint CustomInfoSoundId { get; set; } = 2; // Se2
public uint CustomWarningSoundId { get; set; } = 16; // Se15 public uint CustomWarningSoundId { get; set; } = 16; // Se15

View File

@@ -342,12 +342,6 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
_ => download.Status _ => 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 private TimeSpan GetDefaultDurationForType(NotificationType type) => type switch
{ {
NotificationType.Info => TimeSpan.FromSeconds(_configService.Current.InfoNotificationDurationSeconds), NotificationType.Info => TimeSpan.FromSeconds(_configService.Current.InfoNotificationDurationSeconds),
@@ -607,11 +601,6 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
}; };
Mediator.Publish(new LightlessNotificationMessage(notification)); Mediator.Publish(new LightlessNotificationMessage(notification));
if (userDownloads.Count == 0 || AreAllDownloadsCompleted(userDownloads))
{
Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress"));
}
} }
private void HandlePerformanceNotification(PerformanceNotificationMessage msg) private void HandlePerformanceNotification(PerformanceNotificationMessage msg)

View File

@@ -58,13 +58,21 @@ public class DownloadUi : WindowMediatorSubscriberBase
IsOpen = true; IsOpen = true;
Mediator.Subscribe<DownloadStartedMessage>(this, (msg) => _currentDownloads[msg.DownloadId] = msg.DownloadStatus); Mediator.Subscribe<DownloadStartedMessage>(this, (msg) =>
{
_currentDownloads[msg.DownloadId] = msg.DownloadStatus;
_notificationDismissed = false;
});
Mediator.Subscribe<DownloadFinishedMessage>(this, (msg) => Mediator.Subscribe<DownloadFinishedMessage>(this, (msg) =>
{ {
_currentDownloads.TryRemove(msg.DownloadId, out _); _currentDownloads.TryRemove(msg.DownloadId, out _);
if (!_currentDownloads.Any())
// Dismiss notification if all downloads are complete
if (!_currentDownloads.Any() && !_notificationDismissed)
{ {
Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress")); Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress"));
_notificationDismissed = true;
_lastDownloadStateHash = 0;
} }
}); });
Mediator.Subscribe<GposeStartMessage>(this, (_) => IsOpen = false); Mediator.Subscribe<GposeStartMessage>(this, (_) => IsOpen = false);
@@ -361,5 +369,4 @@ public class DownloadUi : WindowMediatorSubscriberBase
} }
} }
} }
} }

View File

@@ -45,6 +45,9 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
ImGuiWindowFlags.NoNav | ImGuiWindowFlags.NoNav |
ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoBackground |
ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoCollapse |
ImGuiWindowFlags.NoInputs |
ImGuiWindowFlags.NoTitleBar |
ImGuiWindowFlags.NoScrollbar |
ImGuiWindowFlags.AlwaysAutoResize; ImGuiWindowFlags.AlwaysAutoResize;
PositionCondition = ImGuiCond.Always; PositionCondition = ImGuiCond.Always;
@@ -86,6 +89,13 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
existing.Progress = updated.Progress; existing.Progress = updated.Progress;
existing.ShowProgress = updated.ShowProgress; existing.ShowProgress = updated.ShowProgress;
existing.Title = updated.Title; existing.Title = updated.Title;
// Reset the duration timer on every update for download notifications
if (updated.Type == NotificationType.Download)
{
existing.CreatedAt = DateTime.UtcNow;
}
_logger.LogDebug("Updated existing notification: {Title}", updated.Title); _logger.LogDebug("Updated existing notification: {Title}", updated.Title);
} }
@@ -335,6 +345,13 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
DrawBackground(drawList, windowPos, windowSize, bgColor); DrawBackground(drawList, windowPos, windowSize, bgColor);
DrawAccentBar(drawList, windowPos, windowSize, accentColor); DrawAccentBar(drawList, windowPos, windowSize, accentColor);
DrawDurationProgressBar(notification, alpha, windowPos, windowSize, drawList); 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); DrawNotificationText(notification, alpha);
} }
@@ -416,7 +433,7 @@ public class LightlessNotificationUi : WindowMediatorSubscriberBase
private void DrawDurationProgressBar(LightlessNotification notification, float alpha, Vector2 windowPos, Vector2 windowSize, ImDrawListPtr drawList) 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 progressBarColor = UIColors.Get("LightlessBlue");
var progressHeight = 2f; var progressHeight = 2f;
var progressY = windowPos.Y + windowSize.Y - progressHeight; var progressY = windowPos.Y + windowSize.Y - progressHeight;
@@ -430,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) var progress = Math.Clamp(notification.Progress, 0f, 1f);
{ var progressBarColor = UIColors.Get("LightlessGreen");
return Math.Clamp(notification.Progress, 0f, 1f); 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; var elapsed = DateTime.UtcNow - notification.CreatedAt;
return Math.Min(1.0f, (float)(elapsed.TotalSeconds / notification.Duration.TotalSeconds)); return Math.Min(1.0f, (float)(elapsed.TotalSeconds / notification.Duration.TotalSeconds));
} }

View File

@@ -3845,9 +3845,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
_uiShared.DrawHelpText("Choose which corner of the screen notifications appear in."); _uiShared.DrawHelpText("Choose which corner of the screen notifications appear in.");
int offsetY = _configService.Current.NotificationOffsetY; int offsetY = _configService.Current.NotificationOffsetY;
if (ImGui.SliderInt("Vertical Offset", ref offsetY, 0, 1000)) if (ImGui.SliderInt("Vertical Offset", ref offsetY, -2500, 2500))
{ {
_configService.Current.NotificationOffsetY = Math.Clamp(offsetY, 0, 1000); _configService.Current.NotificationOffsetY = Math.Clamp(offsetY, -2500, 2500);
_configService.Save(); _configService.Save();
} }
if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
@@ -3860,9 +3860,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
_uiShared.DrawHelpText("Distance from the top edge of the screen."); _uiShared.DrawHelpText("Distance from the top edge of the screen.");
int offsetX = _configService.Current.NotificationOffsetX; int offsetX = _configService.Current.NotificationOffsetX;
if (ImGui.SliderInt("Horizontal Offset", ref offsetX, 0, 500)) if (ImGui.SliderInt("Horizontal Offset", ref offsetX, -2500, 2500))
{ {
_configService.Current.NotificationOffsetX = Math.Clamp(offsetX, 0, 500); _configService.Current.NotificationOffsetX = Math.Clamp(offsetX, -2500, 2500);
_configService.Save(); _configService.Save();
} }
if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
@@ -3979,9 +3979,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
ImGui.SetTooltip("Right click to reset to default (20)."); ImGui.SetTooltip("Right click to reset to default (20).");
int pairRequestDuration = _configService.Current.PairRequestDurationSeconds; 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(); _configService.Save();
} }
if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
@@ -3993,23 +3993,23 @@ public class SettingsUi : WindowMediatorSubscriberBase
ImGui.SetTooltip("Right click to reset to default (180)."); ImGui.SetTooltip("Right click to reset to default (180).");
int downloadDuration = _configService.Current.DownloadNotificationDurationSeconds; int downloadDuration = _configService.Current.DownloadNotificationDurationSeconds;
if (ImGui.SliderInt("Download Duration (seconds)", ref downloadDuration, 60, 600)) if (ImGui.SliderInt("Download Duration (seconds)", ref downloadDuration, 15, 120))
{ {
_configService.Current.DownloadNotificationDurationSeconds = Math.Clamp(downloadDuration, 60, 600); _configService.Current.DownloadNotificationDurationSeconds = Math.Clamp(downloadDuration, 15, 120);
_configService.Save(); _configService.Save();
} }
if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
{ {
_configService.Current.DownloadNotificationDurationSeconds = 300; _configService.Current.DownloadNotificationDurationSeconds = 30;
_configService.Save(); _configService.Save();
} }
if (ImGui.IsItemHovered()) 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; 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(); _configService.Save();
} }
if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
@@ -4144,7 +4144,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
{ {
return new[] return new[]
{ {
NotificationLocation.LightlessUi, NotificationLocation.ChatAndLightlessUi, NotificationLocation.Nowhere NotificationLocation.LightlessUi, NotificationLocation.Chat, NotificationLocation.ChatAndLightlessUi, NotificationLocation.Nowhere
}; };
} }

View File

@@ -76,13 +76,15 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
ShowCloseButton = true; ShowCloseButton = true;
Flags = ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | Flags = ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse |
ImGuiWindowFlags.NoTitleBar; ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoMove;
SizeConstraints = new WindowSizeConstraints() SizeConstraints = new WindowSizeConstraints()
{ {
MinimumSize = new Vector2(800, 700), MaximumSize = new Vector2(800, 700), MinimumSize = new Vector2(800, 700), MaximumSize = new Vector2(800, 700),
}; };
PositionCondition = ImGuiCond.Always;
LoadEmbeddedResources(); LoadEmbeddedResources();
logger.LogInformation("UpdateNotesUi constructor completed successfully"); logger.LogInformation("UpdateNotesUi constructor completed successfully");
} }
@@ -93,11 +95,20 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
_hasInitializedCollapsingHeaders = false; _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() protected override void DrawInternal()
{ {
if (_uiShared.IsInGpose) if (_uiShared.IsInGpose)
return; return;
CenterWindow();
DrawHeader(); DrawHeader();
ImGuiHelpers.ScaledDummy(6); ImGuiHelpers.ScaledDummy(6);
DrawTabs(); DrawTabs();