notification-changes #59
@@ -95,6 +95,7 @@ public class LightlessConfig : ILightlessConfiguration
|
||||
public bool ShowNotificationTimestamp { get; set; } = false;
|
||||
|
||||
// Position & Layout
|
||||
public NotificationCorner NotificationCorner { get; set; } = NotificationCorner.Right;
|
||||
public int NotificationOffsetY { get; set; } = 50;
|
||||
public int NotificationOffsetX { get; set; } = 0;
|
||||
public float NotificationWidth { get; set; } = 350f;
|
||||
@@ -102,6 +103,7 @@ public class LightlessConfig : ILightlessConfiguration
|
||||
|
||||
// Animation & Effects
|
||||
public float NotificationAnimationSpeed { get; set; } = 10f;
|
||||
public float NotificationSlideSpeed { get; set; } = 10f;
|
||||
public float NotificationAccentBarWidth { get; set; } = 3f;
|
||||
|
||||
// Duration per Type
|
||||
|
||||
@@ -18,4 +18,10 @@ public enum NotificationType
|
||||
Error,
|
||||
PairRequest,
|
||||
Download
|
||||
}
|
||||
|
||||
public enum NotificationCorner
|
||||
{
|
||||
Right,
|
||||
Left
|
||||
}
|
||||
@@ -48,7 +48,6 @@ public record PetNamesMessage(string PetNicknamesData) : MessageBase;
|
||||
public record HonorificReadyMessage : MessageBase;
|
||||
public record TransientResourceChangedMessage(IntPtr Address) : MessageBase;
|
||||
public record HaltScanMessage(string Source) : MessageBase;
|
||||
public record ResumeScanMessage(string Source) : MessageBase;
|
||||
public record NotificationMessage
|
||||
(string Title, string Message, NotificationType Type, TimeSpan? TimeShownOnScreen = null) : MessageBase;
|
||||
public record CreateCacheForObjectMessage(GameObjectHandler ObjectToCreateFor) : SameThreadMessage;
|
||||
@@ -56,12 +55,14 @@ public record ClearCacheForObjectMessage(GameObjectHandler ObjectToCreateFor) :
|
||||
public record CharacterDataCreatedMessage(CharacterData CharacterData) : SameThreadMessage;
|
||||
public record LightlessNotificationMessage(LightlessSync.UI.Models.LightlessNotification Notification) : MessageBase;
|
||||
public record LightlessNotificationDismissMessage(string NotificationId) : MessageBase;
|
||||
public record ClearAllNotificationsMessage : MessageBase;
|
||||
public record CharacterDataAnalyzedMessage : MessageBase;
|
||||
public record PenumbraStartRedrawMessage(IntPtr Address) : MessageBase;
|
||||
public record PenumbraEndRedrawMessage(IntPtr Address) : MessageBase;
|
||||
public record HubReconnectingMessage(Exception? Exception) : SameThreadMessage;
|
||||
public record HubReconnectedMessage(string? Arg) : SameThreadMessage;
|
||||
public record HubClosedMessage(Exception? Exception) : SameThreadMessage;
|
||||
public record ResumeScanMessage(string Source) : MessageBase;
|
||||
public record DownloadReadyMessage(Guid RequestId) : MessageBase;
|
||||
public record DownloadStartedMessage(GameObjectHandler DownloadId, Dictionary<string, FileDownloadStatus> DownloadStatus) : MessageBase;
|
||||
public record DownloadFinishedMessage(GameObjectHandler DownloadId) : MessageBase;
|
||||
|
||||
@@ -26,6 +26,8 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
||||
private readonly List<LightlessNotification> _notifications = new();
|
||||
private readonly object _notificationLock = new();
|
||||
private readonly LightlessConfigService _configService;
|
||||
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)
|
||||
: base(logger, mediator, "Lightless Notifications##LightlessNotifications", performanceCollector)
|
||||
@@ -49,12 +51,11 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
||||
|
||||
Mediator.Subscribe<LightlessNotificationMessage>(this, HandleNotificationMessage);
|
||||
Mediator.Subscribe<LightlessNotificationDismissMessage>(this, HandleNotificationDismissMessage);
|
||||
Mediator.Subscribe<ClearAllNotificationsMessage>(this, HandleClearAllNotifications);
|
||||
}
|
||||
private void HandleNotificationMessage(LightlessNotificationMessage message) =>
|
||||
AddNotification(message.Notification);
|
||||
|
||||
private void HandleNotificationDismissMessage(LightlessNotificationDismissMessage message) =>
|
||||
RemoveNotification(message.NotificationId);
|
||||
private void HandleNotificationMessage(LightlessNotificationMessage message) => AddNotification(message.Notification);
|
||||
private void HandleNotificationDismissMessage(LightlessNotificationDismissMessage message) => RemoveNotification(message.NotificationId);
|
||||
private void HandleClearAllNotifications(ClearAllNotificationsMessage message) => ClearAllNotifications();
|
||||
|
||||
public void AddNotification(LightlessNotification notification)
|
||||
{
|
||||
@@ -96,20 +97,34 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearAllNotifications()
|
||||
{
|
||||
lock (_notificationLock)
|
||||
{
|
||||
foreach (var notification in _notifications)
|
||||
{
|
||||
StartOutAnimation(notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StartOutAnimation(LightlessNotification notification)
|
||||
{
|
||||
notification.IsAnimatingOut = true;
|
||||
notification.IsAnimatingIn = false;
|
||||
}
|
||||
|
||||
private bool ShouldRemoveNotification(LightlessNotification notification) =>
|
||||
notification.IsAnimatingOut && notification.AnimationProgress <= 0.01f;
|
||||
|
||||
protected override void DrawInternal()
|
||||
{
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);
|
||||
|
||||
|
||||
lock (_notificationLock)
|
||||
{
|
||||
UpdateNotifications();
|
||||
|
||||
|
||||
if (_notifications.Count == 0)
|
||||
{
|
||||
ImGui.PopStyleVar();
|
||||
@@ -118,33 +133,49 @@ 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;
|
||||
|
||||
Position = CalculateWindowPosition(viewport);
|
||||
PositionCondition = ImGuiCond.Always;
|
||||
|
||||
DrawAllNotifications();
|
||||
}
|
||||
|
||||
|
||||
ImGui.PopStyleVar();
|
||||
}
|
||||
|
||||
private Vector2 CalculateWindowPosition(ImGuiViewportPtr viewport)
|
||||
{
|
||||
var x = viewport.WorkPos.X + viewport.WorkSize.X -
|
||||
_configService.Current.NotificationWidth -
|
||||
_configService.Current.NotificationOffsetX -
|
||||
WindowPaddingOffset;
|
||||
var y = viewport.WorkPos.Y + _configService.Current.NotificationOffsetY;
|
||||
return new Vector2(x, y);
|
||||
var corner = _configService.Current.NotificationCorner;
|
||||
var offsetX = _configService.Current.NotificationOffsetX;
|
||||
var width = _configService.Current.NotificationWidth;
|
||||
|
||||
float posX = corner == NotificationCorner.Left
|
||||
? viewport.WorkPos.X + offsetX - WindowPaddingOffset
|
||||
: viewport.WorkPos.X + viewport.WorkSize.X - width - offsetX - WindowPaddingOffset;
|
||||
|
||||
return new Vector2(posX, viewport.WorkPos.Y);
|
||||
}
|
||||
|
||||
private void DrawAllNotifications()
|
||||
{
|
||||
var offsetY = _configService.Current.NotificationOffsetY;
|
||||
var startY = ImGui.GetCursorPosY() + offsetY;
|
||||
|
||||
for (int i = 0; i < _notifications.Count; i++)
|
||||
{
|
||||
DrawNotification(_notifications[i], i);
|
||||
var notification = _notifications[i];
|
||||
|
||||
if (i < _notifications.Count - 1)
|
||||
if (_notificationYOffsets.TryGetValue(notification.Id, out var yOffset))
|
||||
{
|
||||
ImGui.Dummy(new Vector2(0, _configService.Current.NotificationSpacing));
|
||||
ImGui.SetCursorPosY(startY + yOffset);
|
||||
}
|
||||
|
||||
DrawNotification(notification, i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,18 +205,65 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
||||
|
||||
private void UpdateAnimationsAndRemoveExpired(float deltaTime)
|
||||
{
|
||||
UpdateTargetYPositions();
|
||||
|
||||
for (int i = _notifications.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var notification = _notifications[i];
|
||||
UpdateNotificationAnimation(notification, deltaTime);
|
||||
UpdateNotificationYOffset(notification, deltaTime);
|
||||
|
||||
if (ShouldRemoveNotification(notification))
|
||||
{
|
||||
_notifications.RemoveAt(i);
|
||||
_notificationYOffsets.Remove(notification.Id);
|
||||
_notificationTargetYOffsets.Remove(notification.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTargetYPositions()
|
||||
{
|
||||
float currentY = 0f;
|
||||
|
||||
for (int i = 0; i < _notifications.Count; i++)
|
||||
{
|
||||
var notification = _notifications[i];
|
||||
|
||||
if (!_notificationTargetYOffsets.ContainsKey(notification.Id))
|
||||
{
|
||||
_notificationTargetYOffsets[notification.Id] = currentY;
|
||||
_notificationYOffsets[notification.Id] = currentY;
|
||||
}
|
||||
else
|
||||
{
|
||||
_notificationTargetYOffsets[notification.Id] = currentY;
|
||||
}
|
||||
|
||||
currentY += CalculateNotificationHeight(notification) + _configService.Current.NotificationSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateNotificationYOffset(LightlessNotification notification, float deltaTime)
|
||||
{
|
||||
if (!_notificationYOffsets.ContainsKey(notification.Id) || !_notificationTargetYOffsets.ContainsKey(notification.Id))
|
||||
return;
|
||||
|
||||
var current = _notificationYOffsets[notification.Id];
|
||||
var target = _notificationTargetYOffsets[notification.Id];
|
||||
var diff = target - current;
|
||||
|
||||
if (Math.Abs(diff) < 0.5f)
|
||||
{
|
||||
_notificationYOffsets[notification.Id] = target;
|
||||
}
|
||||
else
|
||||
{
|
||||
var speed = _configService.Current.NotificationSlideSpeed;
|
||||
_notificationYOffsets[notification.Id] = current + (diff * deltaTime * speed);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateNotificationAnimation(LightlessNotification notification, float deltaTime)
|
||||
{
|
||||
if (notification.IsAnimatingIn && notification.AnimationProgress < 1f)
|
||||
@@ -209,20 +287,24 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldRemoveNotification(LightlessNotification notification) =>
|
||||
notification.IsAnimatingOut && notification.AnimationProgress <= 0.01f;
|
||||
private Vector2 CalculateSlideOffset(float alpha)
|
||||
{
|
||||
var distance = (1f - alpha) * SlideAnimationDistance;
|
||||
var corner = _configService.Current.NotificationCorner;
|
||||
return corner == NotificationCorner.Left ? new Vector2(-distance, 0) : new Vector2(distance, 0);
|
||||
}
|
||||
|
||||
private void DrawNotification(LightlessNotification notification, int index)
|
||||
{
|
||||
var alpha = notification.AnimationProgress;
|
||||
if (alpha <= 0f) return;
|
||||
|
||||
var slideOffset = (1f - alpha) * SlideAnimationDistance;
|
||||
var slideOffset = CalculateSlideOffset(alpha);
|
||||
var originalCursorPos = ImGui.GetCursorPos();
|
||||
ImGui.SetCursorPosX(originalCursorPos.X + slideOffset);
|
||||
ImGui.SetCursorPos(originalCursorPos + slideOffset);
|
||||
|
||||
var notificationHeight = CalculateNotificationHeight(notification);
|
||||
var notificationWidth = _configService.Current.NotificationWidth - slideOffset;
|
||||
var notificationWidth = _configService.Current.NotificationWidth - Math.Abs(slideOffset.X);
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);
|
||||
|
||||
@@ -308,15 +390,28 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
||||
private void DrawAccentBar(ImDrawListPtr drawList, Vector2 windowPos, Vector2 windowSize, Vector4 accentColor)
|
||||
{
|
||||
var accentWidth = _configService.Current.NotificationAccentBarWidth;
|
||||
if (accentWidth > 0f)
|
||||
if (accentWidth <= 0f) return;
|
||||
|
||||
var corner = _configService.Current.NotificationCorner;
|
||||
Vector2 accentStart, accentEnd;
|
||||
|
||||
if (corner == NotificationCorner.Left)
|
||||
{
|
||||
drawList.AddRectFilled(
|
||||
windowPos,
|
||||
windowPos + new Vector2(accentWidth, windowSize.Y),
|
||||
ImGui.ColorConvertFloat4ToU32(accentColor),
|
||||
3f
|
||||
);
|
||||
accentStart = windowPos + new Vector2(windowSize.X - accentWidth, 0);
|
||||
accentEnd = windowPos + windowSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
accentStart = windowPos;
|
||||
accentEnd = windowPos + new Vector2(accentWidth, windowSize.Y);
|
||||
}
|
||||
|
||||
drawList.AddRectFilled(
|
||||
accentStart,
|
||||
accentEnd,
|
||||
ImGui.ColorConvertFloat4ToU32(accentColor),
|
||||
3f
|
||||
);
|
||||
}
|
||||
|
||||
private void DrawDurationProgressBar(LightlessNotification notification, float alpha, Vector2 windowPos, Vector2 windowSize, ImDrawListPtr drawList)
|
||||
|
||||
@@ -3493,69 +3493,162 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
if (useLightlessNotifications)
|
||||
{
|
||||
// Lightless notification locations
|
||||
ImGui.Indent();
|
||||
|
||||
var lightlessLocations = GetLightlessNotificationLocations();
|
||||
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Info Notifications:");
|
||||
ImGui.SameLine();
|
||||
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||
_uiShared.DrawCombo("###enhanced_info", lightlessLocations, GetNotificationLocationLabel, (location) =>
|
||||
{
|
||||
_configService.Current.LightlessInfoNotification = location;
|
||||
_configService.Save();
|
||||
}, _configService.Current.LightlessInfoNotification);
|
||||
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Warning Notifications:");
|
||||
ImGui.SameLine();
|
||||
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||
_uiShared.DrawCombo("###enhanced_warning", lightlessLocations, GetNotificationLocationLabel,
|
||||
(location) =>
|
||||
{
|
||||
_configService.Current.LightlessWarningNotification = location;
|
||||
_configService.Save();
|
||||
}, _configService.Current.LightlessWarningNotification);
|
||||
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Error Notifications:");
|
||||
ImGui.SameLine();
|
||||
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||
_uiShared.DrawCombo("###enhanced_error", lightlessLocations, GetNotificationLocationLabel, (location) =>
|
||||
{
|
||||
_configService.Current.LightlessErrorNotification = location;
|
||||
_configService.Save();
|
||||
}, _configService.Current.LightlessErrorNotification);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(3);
|
||||
_uiShared.DrawHelpText("Special notification types:");
|
||||
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Pair Request Notifications:");
|
||||
ImGui.SameLine();
|
||||
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||
_uiShared.DrawCombo("###enhanced_pairrequest", lightlessLocations, GetNotificationLocationLabel,
|
||||
(location) =>
|
||||
{
|
||||
_configService.Current.LightlessPairRequestNotification = location;
|
||||
_configService.Save();
|
||||
}, _configService.Current.LightlessPairRequestNotification);
|
||||
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Download Progress Notifications:");
|
||||
ImGui.SameLine();
|
||||
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||
var downloadLocations = GetDownloadNotificationLocations();
|
||||
_uiShared.DrawCombo("###enhanced_download", downloadLocations, GetNotificationLocationLabel,
|
||||
(location) =>
|
||||
|
||||
if (ImGui.BeginTable("##NotificationLocationTable", 3, ImGuiTableFlags.Borders | ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit))
|
||||
{
|
||||
ImGui.TableSetupColumn("Notification Type", ImGuiTableColumnFlags.WidthFixed, 200f * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Location", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Test", ImGuiTableColumnFlags.WidthFixed, 40f * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableHeadersRow();
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Info Notifications");
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
_uiShared.DrawCombo("###enhanced_info", lightlessLocations, GetNotificationLocationLabel, (location) =>
|
||||
{
|
||||
_configService.Current.LightlessDownloadNotification = location;
|
||||
_configService.Current.LightlessInfoNotification = location;
|
||||
_configService.Save();
|
||||
}, _configService.Current.LightlessDownloadNotification);
|
||||
}, _configService.Current.LightlessInfoNotification);
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
var availableWidth = ImGui.GetContentRegionAvail().X;
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
if (ImGui.Button($"{FontAwesomeIcon.Play.ToIconString()}##test_info", new Vector2(availableWidth, 0)))
|
||||
{
|
||||
Mediator.Publish(new NotificationMessage("Test Info",
|
||||
"This is a test info notification to let you know Chocola is cute :3", NotificationType.Info));
|
||||
}
|
||||
}
|
||||
UiSharedService.AttachToolTip("Test info notification");
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Warning Notifications");
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
_uiShared.DrawCombo("###enhanced_warning", lightlessLocations, GetNotificationLocationLabel,
|
||||
(location) =>
|
||||
{
|
||||
_configService.Current.LightlessWarningNotification = location;
|
||||
_configService.Save();
|
||||
}, _configService.Current.LightlessWarningNotification);
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
availableWidth = ImGui.GetContentRegionAvail().X;
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
if (ImGui.Button($"{FontAwesomeIcon.Play.ToIconString()}##test_warning", new Vector2(availableWidth, 0)))
|
||||
{
|
||||
Mediator.Publish(new NotificationMessage("Test Warning", "This is a test warning notification!",
|
||||
NotificationType.Warning));
|
||||
}
|
||||
}
|
||||
UiSharedService.AttachToolTip("Test warning notification");
|
||||
|
||||
ImGui.Unindent();
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Error Notifications");
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
_uiShared.DrawCombo("###enhanced_error", lightlessLocations, GetNotificationLocationLabel, (location) =>
|
||||
{
|
||||
_configService.Current.LightlessErrorNotification = location;
|
||||
_configService.Save();
|
||||
}, _configService.Current.LightlessErrorNotification);
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
availableWidth = ImGui.GetContentRegionAvail().X;
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
if (ImGui.Button($"{FontAwesomeIcon.Play.ToIconString()}##test_error", new Vector2(availableWidth, 0)))
|
||||
{
|
||||
Mediator.Publish(new NotificationMessage("Test Error", "This is a test error notification!",
|
||||
NotificationType.Error));
|
||||
}
|
||||
}
|
||||
UiSharedService.AttachToolTip("Test error notification");
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Pair Request Notifications");
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
_uiShared.DrawCombo("###enhanced_pairrequest", lightlessLocations, GetNotificationLocationLabel,
|
||||
(location) =>
|
||||
{
|
||||
_configService.Current.LightlessPairRequestNotification = location;
|
||||
_configService.Save();
|
||||
}, _configService.Current.LightlessPairRequestNotification);
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
availableWidth = ImGui.GetContentRegionAvail().X;
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
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));
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
UiSharedService.AttachToolTip("Test pair request notification");
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted("Download Progress Notifications");
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
_uiShared.DrawCombo("###enhanced_download", downloadLocations, GetNotificationLocationLabel,
|
||||
(location) =>
|
||||
{
|
||||
_configService.Current.LightlessDownloadNotification = location;
|
||||
_configService.Save();
|
||||
}, _configService.Current.LightlessDownloadNotification);
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
availableWidth = ImGui.GetContentRegionAvail().X;
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
if (ImGui.Button($"{FontAwesomeIcon.Play.ToIconString()}##test_download", new Vector2(availableWidth, 0)))
|
||||
{
|
||||
_lightlessNotificationService.ShowPairDownloadNotification(
|
||||
new List<(string playerName, float progress, string status)>
|
||||
{
|
||||
("Player One", 0.35f, "downloading"),
|
||||
("Player Two", 0.75f, "downloading"),
|
||||
("Player Three", 1.0f, "downloading")
|
||||
},
|
||||
queueWaiting: 2
|
||||
);
|
||||
}
|
||||
}
|
||||
UiSharedService.AttachToolTip("Test download progress notification");
|
||||
|
||||
ImGui.EndTable();
|
||||
}
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.Trash, "Clear All Notifications"))
|
||||
{
|
||||
Mediator.Publish(new ClearAllNotificationsMessage());
|
||||
}
|
||||
_uiShared.DrawHelpText("Dismiss all active notifications immediately.");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3602,73 +3695,6 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.Separator();
|
||||
if (useLightlessNotifications)
|
||||
{
|
||||
if (_uiShared.MediumTreeNode("Test Notifications", UIColors.Get("LightlessPurple")))
|
||||
{
|
||||
ImGui.Indent();
|
||||
|
||||
// Test notification buttons
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.Bell, "Test Info"))
|
||||
{
|
||||
Mediator.Publish(new NotificationMessage("Test Info",
|
||||
"This is a test info notification to let you know Chocola is cute :3", NotificationType.Info));
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.ExclamationTriangle, "Test Warning"))
|
||||
{
|
||||
Mediator.Publish(new NotificationMessage("Test Warning", "This is a test warning notification!",
|
||||
NotificationType.Warning));
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.ExclamationCircle, "Test Error"))
|
||||
{
|
||||
Mediator.Publish(new NotificationMessage("Test Error", "This is a test error notification!",
|
||||
NotificationType.Error));
|
||||
}
|
||||
|
||||
ImGuiHelpers.ScaledDummy(3);
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.UserPlus, "Test Pair Request"))
|
||||
{
|
||||
_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));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.Download, "Test Download Progress"))
|
||||
{
|
||||
_lightlessNotificationService.ShowPairDownloadNotification(
|
||||
new List<(string playerName, float progress, string status)>
|
||||
{
|
||||
("Player One", 0.35f, "downloading"),
|
||||
("Player Two", 0.75f, "downloading"),
|
||||
("Player Three", 1.0f, "downloading")
|
||||
},
|
||||
queueWaiting: 2
|
||||
);
|
||||
}
|
||||
|
||||
_uiShared.DrawHelpText("Preview how notifications will appear with your current settings.");
|
||||
|
||||
ImGui.Unindent();
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
if (_uiShared.MediumTreeNode("Basic Settings", UIColors.Get("LightlessPurple")))
|
||||
{
|
||||
int maxNotifications = _configService.Current.MaxSimultaneousNotifications;
|
||||
@@ -3768,10 +3794,28 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.Spacing();
|
||||
ImGui.TextUnformatted("Position");
|
||||
|
||||
int offsetY = _configService.Current.NotificationOffsetY;
|
||||
if (ImGui.SliderInt("Vertical Offset", ref offsetY, 0, 500))
|
||||
var currentCorner = _configService.Current.NotificationCorner;
|
||||
if (ImGui.BeginCombo("Notification Position", GetNotificationCornerLabel(currentCorner)))
|
||||
{
|
||||
_configService.Current.NotificationOffsetY = Math.Clamp(offsetY, 0, 500);
|
||||
foreach (NotificationCorner corner in Enum.GetValues(typeof(NotificationCorner)))
|
||||
{
|
||||
bool isSelected = currentCorner == corner;
|
||||
if (ImGui.Selectable(GetNotificationCornerLabel(corner), isSelected))
|
||||
{
|
||||
_configService.Current.NotificationCorner = corner;
|
||||
_configService.Save();
|
||||
}
|
||||
if (isSelected)
|
||||
ImGui.SetItemDefaultFocus();
|
||||
}
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
_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))
|
||||
{
|
||||
_configService.Current.NotificationOffsetY = Math.Clamp(offsetY, 0, 1000);
|
||||
_configService.Save();
|
||||
}
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
@@ -3781,7 +3825,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip("Right click to reset to default (50).");
|
||||
_uiShared.DrawHelpText("Move notifications down from the top-right corner.");
|
||||
_uiShared.DrawHelpText("Distance from the top edge of the screen.");
|
||||
|
||||
int offsetX = _configService.Current.NotificationOffsetX;
|
||||
if (ImGui.SliderInt("Horizontal Offset", ref offsetX, 0, 500))
|
||||
@@ -3802,9 +3846,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.TextUnformatted("Animation Settings");
|
||||
|
||||
float animSpeed = _configService.Current.NotificationAnimationSpeed;
|
||||
if (ImGui.SliderFloat("Animation Speed", ref animSpeed, 1f, 30f, "%.1f"))
|
||||
if (ImGui.SliderFloat("Animation Speed", ref animSpeed, 1f, 20f, "%.1f"))
|
||||
{
|
||||
_configService.Current.NotificationAnimationSpeed = Math.Clamp(animSpeed, 1f, 30f);
|
||||
_configService.Current.NotificationAnimationSpeed = Math.Clamp(animSpeed, 1f, 20f);
|
||||
_configService.Save();
|
||||
}
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
@@ -3816,6 +3860,21 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.SetTooltip("Right click to reset to default (10).");
|
||||
_uiShared.DrawHelpText("How fast notifications slide in/out. Higher = faster.");
|
||||
|
||||
float slideSpeed = _configService.Current.NotificationSlideSpeed;
|
||||
if (ImGui.SliderFloat("Slide Speed", ref slideSpeed, 1f, 20f, "%.1f"))
|
||||
{
|
||||
_configService.Current.NotificationSlideSpeed = Math.Clamp(slideSpeed, 1f, 20f);
|
||||
_configService.Save();
|
||||
}
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
{
|
||||
_configService.Current.NotificationSlideSpeed = 10f;
|
||||
_configService.Save();
|
||||
}
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip("Right click to reset to default (10).");
|
||||
_uiShared.DrawHelpText("How fast notifications slide into position when others disappear. Higher = faster.");
|
||||
|
||||
ImGui.Spacing();
|
||||
ImGui.TextUnformatted("Visual Effects");
|
||||
|
||||
@@ -3999,6 +4058,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Separator();
|
||||
// Location descriptions removed - information is now inline with each setting
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4043,6 +4103,16 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
};
|
||||
}
|
||||
|
||||
private string GetNotificationCornerLabel(NotificationCorner corner)
|
||||
{
|
||||
return corner switch
|
||||
{
|
||||
NotificationCorner.Right => "Right",
|
||||
NotificationCorner.Left => "Left",
|
||||
_ => corner.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
private void DrawSoundTable()
|
||||
{
|
||||
var soundEffects = new[]
|
||||
@@ -4087,7 +4157,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
var currentIndex = Array.FindIndex(soundEffects, s => s.Item1 == currentSoundId);
|
||||
if (currentIndex == -1) currentIndex = 1;
|
||||
|
||||
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
if (ImGui.Combo($"##sound_{typeIndex}", ref currentIndex,
|
||||
soundEffects.Select(s => s.Item2).ToArray(), soundEffects.Length))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user