more to notification system with new settings tab
This commit is contained in:
@@ -70,6 +70,31 @@ public class LightlessConfig : ILightlessConfiguration
|
|||||||
public bool AutoPopulateEmptyNotesFromCharaName { get; set; } = false;
|
public bool AutoPopulateEmptyNotesFromCharaName { get; set; } = false;
|
||||||
public int Version { get; set; } = 1;
|
public int Version { get; set; } = 1;
|
||||||
public NotificationLocation WarningNotification { get; set; } = NotificationLocation.Both;
|
public NotificationLocation WarningNotification { get; set; } = NotificationLocation.Both;
|
||||||
|
|
||||||
|
// Lightless Notification Configuration
|
||||||
|
// TODO: clean these
|
||||||
|
public bool UseLightlessNotifications { get; set; } = true;
|
||||||
|
public bool EnableNotificationSounds { get; set; } = true;
|
||||||
|
public int DefaultNotificationDurationSeconds { get; set; } = 10;
|
||||||
|
public bool ShowNotificationProgress { get; set; } = true;
|
||||||
|
public NotificationLocation LightlessInfoNotification { get; set; } = NotificationLocation.LightlessUI;
|
||||||
|
public NotificationLocation LightlessWarningNotification { get; set; } = NotificationLocation.LightlessUI;
|
||||||
|
public NotificationLocation LightlessErrorNotification { get; set; } = NotificationLocation.ChatAndLightlessUI;
|
||||||
|
|
||||||
|
public float NotificationOpacity { get; set; } = 0.95f;
|
||||||
|
public bool EnableNotificationAnimations { get; set; } = true;
|
||||||
|
public int MaxSimultaneousNotifications { get; set; } = 5;
|
||||||
|
public bool AutoDismissOnAction { get; set; } = true;
|
||||||
|
public bool ShowNotificationTimestamp { get; set; } = false;
|
||||||
|
public bool EnableNotificationHistory { get; set; } = true;
|
||||||
|
public int NotificationHistorySize { get; set; } = 50;
|
||||||
|
|
||||||
|
public uint CustomInfoSoundId { get; set; } = 2; // Se2
|
||||||
|
public uint CustomWarningSoundId { get; set; } = 15; // Se15
|
||||||
|
public uint CustomErrorSoundId { get; set; } = 16; // Se16
|
||||||
|
public bool UseCustomSounds { get; set; } = false;
|
||||||
|
public float NotificationSoundVolume { get; set; } = 1.0f;
|
||||||
|
// till here c:
|
||||||
public bool UseFocusTarget { get; set; } = false;
|
public bool UseFocusTarget { get; set; } = false;
|
||||||
public bool overrideFriendColor { get; set; } = false;
|
public bool overrideFriendColor { get; set; } = false;
|
||||||
public bool overridePartyColor { get; set; } = false;
|
public bool overridePartyColor { get; set; } = false;
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
namespace LightlessSync.LightlessConfiguration.Models;
|
namespace LightlessSync.LightlessConfiguration.Models;
|
||||||
|
|
||||||
public enum NotificationLocation
|
public enum NotificationLocation
|
||||||
{
|
{
|
||||||
Nowhere,
|
Nowhere,
|
||||||
Chat,
|
Chat,
|
||||||
Toast,
|
Toast,
|
||||||
Both
|
Both,
|
||||||
|
LightlessUI,
|
||||||
|
ChatAndLightlessUI,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum NotificationType
|
public enum NotificationType
|
||||||
|
|||||||
@@ -179,6 +179,8 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
s.GetRequiredService<ILogger<LightlessNotificationService>>(),
|
s.GetRequiredService<ILogger<LightlessNotificationService>>(),
|
||||||
s.GetRequiredService<LightlessConfigService>(),
|
s.GetRequiredService<LightlessConfigService>(),
|
||||||
s.GetRequiredService<DalamudUtilService>(),
|
s.GetRequiredService<DalamudUtilService>(),
|
||||||
|
notificationManager,
|
||||||
|
chatGui,
|
||||||
s.GetRequiredService<LightlessMediator>()));
|
s.GetRequiredService<LightlessMediator>()));
|
||||||
collection.AddSingleton((s) =>
|
collection.AddSingleton((s) =>
|
||||||
{
|
{
|
||||||
@@ -244,7 +246,8 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
new LightlessNotificationUI(
|
new LightlessNotificationUI(
|
||||||
s.GetRequiredService<ILogger<LightlessNotificationUI>>(),
|
s.GetRequiredService<ILogger<LightlessNotificationUI>>(),
|
||||||
s.GetRequiredService<LightlessMediator>(),
|
s.GetRequiredService<LightlessMediator>(),
|
||||||
s.GetRequiredService<PerformanceCollectorService>()));
|
s.GetRequiredService<PerformanceCollectorService>(),
|
||||||
|
s.GetRequiredService<LightlessConfigService>()));
|
||||||
collection.AddScoped<IPopupHandler, CensusPopupHandler>();
|
collection.AddScoped<IPopupHandler, CensusPopupHandler>();
|
||||||
collection.AddScoped<CacheCreationService>();
|
collection.AddScoped<CacheCreationService>();
|
||||||
collection.AddScoped<PlayerDataFactory>();
|
collection.AddScoped<PlayerDataFactory>();
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using LightlessSync.LightlessConfiguration;
|
using LightlessSync.LightlessConfiguration;
|
||||||
using LightlessSync.LightlessConfiguration.Models;
|
using LightlessSync.LightlessConfiguration.Models;
|
||||||
@@ -8,6 +10,7 @@ using LightlessSync.UI.Models;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
|
using NotificationType = LightlessSync.LightlessConfiguration.Models.NotificationType;
|
||||||
|
|
||||||
namespace LightlessSync.Services;
|
namespace LightlessSync.Services;
|
||||||
public class LightlessNotificationService : DisposableMediatorSubscriberBase, IHostedService
|
public class LightlessNotificationService : DisposableMediatorSubscriberBase, IHostedService
|
||||||
@@ -15,19 +18,26 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
|
|||||||
private readonly ILogger<LightlessNotificationService> _logger;
|
private readonly ILogger<LightlessNotificationService> _logger;
|
||||||
private readonly LightlessConfigService _configService;
|
private readonly LightlessConfigService _configService;
|
||||||
private readonly DalamudUtilService _dalamudUtilService;
|
private readonly DalamudUtilService _dalamudUtilService;
|
||||||
|
private readonly INotificationManager _notificationManager;
|
||||||
|
private readonly IChatGui _chatGui;
|
||||||
private LightlessNotificationUI? _notificationUI;
|
private LightlessNotificationUI? _notificationUI;
|
||||||
public LightlessNotificationService(
|
public LightlessNotificationService(
|
||||||
ILogger<LightlessNotificationService> logger,
|
ILogger<LightlessNotificationService> logger,
|
||||||
LightlessConfigService configService,
|
LightlessConfigService configService,
|
||||||
DalamudUtilService dalamudUtilService,
|
DalamudUtilService dalamudUtilService,
|
||||||
|
INotificationManager notificationManager,
|
||||||
|
IChatGui chatGui,
|
||||||
LightlessMediator mediator) : base(logger, mediator)
|
LightlessMediator mediator) : base(logger, mediator)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_dalamudUtilService = dalamudUtilService;
|
_dalamudUtilService = dalamudUtilService;
|
||||||
|
_notificationManager = notificationManager;
|
||||||
|
_chatGui = chatGui;
|
||||||
}
|
}
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
Mediator.Subscribe<NotificationMessage>(this, HandleNotificationMessage);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
public Task StopAsync(CancellationToken cancellationToken)
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
@@ -46,12 +56,31 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
|
|||||||
Title = title,
|
Title = title,
|
||||||
Message = message,
|
Message = message,
|
||||||
Type = type,
|
Type = type,
|
||||||
Duration = duration ?? TimeSpan.FromSeconds(10),
|
Duration = duration ?? TimeSpan.FromSeconds(_configService.Current.DefaultNotificationDurationSeconds),
|
||||||
Actions = actions ?? new List<LightlessNotificationAction>(),
|
Actions = actions ?? new List<LightlessNotificationAction>(),
|
||||||
SoundEffectId = soundEffectId ?? NotificationSounds.GetDefaultSound(type)
|
SoundEffectId = GetSoundEffectId(type, soundEffectId),
|
||||||
|
ShowProgress = _configService.Current.ShowNotificationProgress,
|
||||||
|
CreatedAt = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
|
|
||||||
if (notification.SoundEffectId.HasValue)
|
if (_configService.Current.AutoDismissOnAction && notification.Actions.Any())
|
||||||
|
{
|
||||||
|
foreach (var action in notification.Actions)
|
||||||
|
{
|
||||||
|
var originalOnClick = action.OnClick;
|
||||||
|
action.OnClick = (n) =>
|
||||||
|
{
|
||||||
|
originalOnClick(n);
|
||||||
|
if (_configService.Current.AutoDismissOnAction)
|
||||||
|
{
|
||||||
|
n.IsDismissed = true;
|
||||||
|
n.IsAnimatingOut = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notification.SoundEffectId.HasValue && _configService.Current.EnableNotificationSounds)
|
||||||
{
|
{
|
||||||
PlayNotificationSound(notification.SoundEffectId.Value);
|
PlayNotificationSound(notification.SoundEffectId.Value);
|
||||||
}
|
}
|
||||||
@@ -260,6 +289,28 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
|
|||||||
Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress"));
|
Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private uint? GetSoundEffectId(NotificationType type, uint? overrideSoundId)
|
||||||
|
{
|
||||||
|
if (!_configService.Current.EnableNotificationSounds)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (overrideSoundId.HasValue)
|
||||||
|
return overrideSoundId;
|
||||||
|
|
||||||
|
if (_configService.Current.UseCustomSounds)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
NotificationType.Info => _configService.Current.CustomInfoSoundId,
|
||||||
|
NotificationType.Warning => _configService.Current.CustomWarningSoundId,
|
||||||
|
NotificationType.Error => _configService.Current.CustomErrorSoundId,
|
||||||
|
_ => NotificationSounds.GetDefaultSound(type)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return NotificationSounds.GetDefaultSound(type);
|
||||||
|
}
|
||||||
|
|
||||||
private void PlayNotificationSound(uint soundEffectId)
|
private void PlayNotificationSound(uint soundEffectId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -279,4 +330,172 @@ public class LightlessNotificationService : DisposableMediatorSubscriberBase, IH
|
|||||||
_logger.LogWarning(ex, "Failed to play notification sound effect {SoundId}", soundEffectId);
|
_logger.LogWarning(ex, "Failed to play notification sound effect {SoundId}", soundEffectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleNotificationMessage(NotificationMessage msg)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("{msg}", msg.ToString());
|
||||||
|
|
||||||
|
if (!_dalamudUtilService.IsLoggedIn) return;
|
||||||
|
|
||||||
|
// Get both old and new notification locations
|
||||||
|
var oldLocation = msg.Type switch
|
||||||
|
{
|
||||||
|
NotificationType.Info => _configService.Current.InfoNotification,
|
||||||
|
NotificationType.Warning => _configService.Current.WarningNotification,
|
||||||
|
NotificationType.Error => _configService.Current.ErrorNotification,
|
||||||
|
_ => NotificationLocation.Nowhere
|
||||||
|
};
|
||||||
|
|
||||||
|
var newLocation = msg.Type switch
|
||||||
|
{
|
||||||
|
NotificationType.Info => _configService.Current.LightlessInfoNotification,
|
||||||
|
NotificationType.Warning => _configService.Current.LightlessWarningNotification,
|
||||||
|
NotificationType.Error => _configService.Current.LightlessErrorNotification,
|
||||||
|
_ => NotificationLocation.LightlessUI
|
||||||
|
};
|
||||||
|
|
||||||
|
// Show notifications based on system selection with backwards compatibility
|
||||||
|
if (!_configService.Current.UseLightlessNotifications)
|
||||||
|
{
|
||||||
|
// Only use old system when new system is disabled
|
||||||
|
ShowNotificationLocationBased(msg, oldLocation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use new enhanced system as primary
|
||||||
|
ShowNotificationLocationBased(msg, newLocation);
|
||||||
|
|
||||||
|
// Also use old system as fallback for backwards compatibility
|
||||||
|
// Only if it's different from the new location and not "Nowhere"
|
||||||
|
if (oldLocation != NotificationLocation.Nowhere &&
|
||||||
|
oldLocation != newLocation &&
|
||||||
|
!IsLightlessLocation(oldLocation))
|
||||||
|
{
|
||||||
|
ShowNotificationLocationBased(msg, oldLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowNotificationLocationBased(NotificationMessage msg, NotificationLocation location)
|
||||||
|
{
|
||||||
|
switch (location)
|
||||||
|
{
|
||||||
|
case NotificationLocation.Toast:
|
||||||
|
ShowToast(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotificationLocation.Chat:
|
||||||
|
ShowChat(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotificationLocation.Both:
|
||||||
|
ShowToast(msg);
|
||||||
|
ShowChat(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotificationLocation.LightlessUI:
|
||||||
|
ShowLightlessNotification(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotificationLocation.ChatAndLightlessUI:
|
||||||
|
ShowChat(msg);
|
||||||
|
ShowLightlessNotification(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotificationLocation.Nowhere:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowLightlessNotification(NotificationMessage msg)
|
||||||
|
{
|
||||||
|
var duration = msg.TimeShownOnScreen ?? TimeSpan.FromSeconds(_configService.Current.DefaultNotificationDurationSeconds);
|
||||||
|
uint? soundId = null;
|
||||||
|
|
||||||
|
if (_configService.Current.EnableNotificationSounds)
|
||||||
|
{
|
||||||
|
if (_configService.Current.UseCustomSounds)
|
||||||
|
{
|
||||||
|
soundId = msg.Type switch
|
||||||
|
{
|
||||||
|
NotificationType.Info => _configService.Current.CustomInfoSoundId,
|
||||||
|
NotificationType.Warning => _configService.Current.CustomWarningSoundId,
|
||||||
|
NotificationType.Error => _configService.Current.CustomErrorSoundId,
|
||||||
|
_ => NotificationSounds.GetDefaultSound(msg.Type)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
soundId = NotificationSounds.GetDefaultSound(msg.Type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowNotification(msg.Title ?? "Lightless Sync", msg.Message ?? string.Empty, msg.Type, duration, null, soundId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowToast(NotificationMessage msg)
|
||||||
|
{
|
||||||
|
Dalamud.Interface.ImGuiNotification.NotificationType dalamudType = msg.Type switch
|
||||||
|
{
|
||||||
|
NotificationType.Error => Dalamud.Interface.ImGuiNotification.NotificationType.Error,
|
||||||
|
NotificationType.Warning => Dalamud.Interface.ImGuiNotification.NotificationType.Warning,
|
||||||
|
NotificationType.Info => Dalamud.Interface.ImGuiNotification.NotificationType.Info,
|
||||||
|
_ => Dalamud.Interface.ImGuiNotification.NotificationType.Info
|
||||||
|
};
|
||||||
|
|
||||||
|
_notificationManager.AddNotification(new Notification()
|
||||||
|
{
|
||||||
|
Content = msg.Message ?? string.Empty,
|
||||||
|
Title = msg.Title,
|
||||||
|
Type = dalamudType,
|
||||||
|
Minimized = false,
|
||||||
|
InitialDuration = msg.TimeShownOnScreen ?? TimeSpan.FromSeconds(3)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowChat(NotificationMessage msg)
|
||||||
|
{
|
||||||
|
switch (msg.Type)
|
||||||
|
{
|
||||||
|
case NotificationType.Info:
|
||||||
|
PrintInfoChat(msg.Message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotificationType.Warning:
|
||||||
|
PrintWarnChat(msg.Message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotificationType.Error:
|
||||||
|
PrintErrorChat(msg.Message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrintErrorChat(string? message)
|
||||||
|
{
|
||||||
|
SeStringBuilder se = new SeStringBuilder().AddText("[Lightless Sync] Error: " + message);
|
||||||
|
_chatGui.PrintError(se.BuiltString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrintInfoChat(string? message)
|
||||||
|
{
|
||||||
|
SeStringBuilder se = new SeStringBuilder().AddText("[Lightless Sync] Info: ").AddItalics(message ?? string.Empty);
|
||||||
|
_chatGui.Print(se.BuiltString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrintWarnChat(string? message)
|
||||||
|
{
|
||||||
|
SeStringBuilder se = new SeStringBuilder().AddText("[Lightless Sync] ").AddUiForeground("Warning: " + (message ?? string.Empty), 31).AddUiForegroundOff();
|
||||||
|
_chatGui.Print(se.BuiltString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsLightlessLocation(NotificationLocation location)
|
||||||
|
{
|
||||||
|
return location switch
|
||||||
|
{
|
||||||
|
NotificationLocation.LightlessUI => true,
|
||||||
|
NotificationLocation.ChatAndLightlessUI => true,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,11 +3,13 @@ using Dalamud.Interface.Colors;
|
|||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
|
using LightlessSync.LightlessConfiguration;
|
||||||
using LightlessSync.LightlessConfiguration.Models;
|
using LightlessSync.LightlessConfiguration.Models;
|
||||||
using LightlessSync.Services;
|
using LightlessSync.Services;
|
||||||
using LightlessSync.Services.Mediator;
|
using LightlessSync.Services.Mediator;
|
||||||
using LightlessSync.UI.Models;
|
using LightlessSync.UI.Models;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
|
||||||
@@ -17,18 +19,22 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
private readonly List<LightlessNotification> _notifications = new();
|
private readonly List<LightlessNotification> _notifications = new();
|
||||||
private readonly object _notificationLock = new();
|
private readonly object _notificationLock = new();
|
||||||
|
private readonly LightlessConfigService _configService;
|
||||||
|
|
||||||
private const float NotificationWidth = 350f;
|
private const float NotificationWidth = 350f;
|
||||||
private const float NotificationMinHeight = 60f;
|
private const float NotificationMinHeight = 60f;
|
||||||
|
private const float NotificationMaxHeight = 200f;
|
||||||
private const float NotificationSpacing = 8f;
|
private const float NotificationSpacing = 8f;
|
||||||
private const float AnimationSpeed = 10f;
|
private const float AnimationSpeed = 10f;
|
||||||
|
|
||||||
private const float EdgeXMargin = 0;
|
private const float EdgeXMargin = 0;
|
||||||
private const float EdgeYMargin = 30f;
|
private const float EdgeYMargin = 30f;
|
||||||
private const float SlideDistance = 100f;
|
private const float SlideDistance = 100f;
|
||||||
|
|
||||||
public LightlessNotificationUI(ILogger<LightlessNotificationUI> logger, LightlessMediator mediator, PerformanceCollectorService performanceCollector)
|
public LightlessNotificationUI(ILogger<LightlessNotificationUI> logger, LightlessMediator mediator, PerformanceCollectorService performanceCollector, LightlessConfigService configService)
|
||||||
: base(logger, mediator, "Lightless Notifications##LightlessNotifications", performanceCollector)
|
: base(logger, mediator, "Lightless Notifications##LightlessNotifications", performanceCollector)
|
||||||
{
|
{
|
||||||
|
_configService = configService;
|
||||||
Flags = ImGuiWindowFlags.NoDecoration |
|
Flags = ImGuiWindowFlags.NoDecoration |
|
||||||
ImGuiWindowFlags.NoMove |
|
ImGuiWindowFlags.NoMove |
|
||||||
ImGuiWindowFlags.NoResize |
|
ImGuiWindowFlags.NoResize |
|
||||||
@@ -141,6 +147,19 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
var deltaTime = ImGui.GetIO().DeltaTime;
|
var deltaTime = ImGui.GetIO().DeltaTime;
|
||||||
|
|
||||||
|
var maxNotifications = _configService.Current.MaxSimultaneousNotifications;
|
||||||
|
while (_notifications.Count(n => !n.IsAnimatingOut) > maxNotifications)
|
||||||
|
{
|
||||||
|
var oldestNotification = _notifications
|
||||||
|
.Where(n => !n.IsAnimatingOut)
|
||||||
|
.OrderBy(n => n.CreatedAt)
|
||||||
|
.FirstOrDefault();
|
||||||
|
if (oldestNotification != null)
|
||||||
|
{
|
||||||
|
oldestNotification.IsAnimatingOut = true;
|
||||||
|
oldestNotification.IsAnimatingIn = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (int i = _notifications.Count - 1; i >= 0; i--)
|
for (int i = _notifications.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var notification = _notifications[i];
|
var notification = _notifications[i];
|
||||||
@@ -174,9 +193,16 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
|||||||
private void DrawNotification(LightlessNotification notification, int index)
|
private void DrawNotification(LightlessNotification notification, int index)
|
||||||
{
|
{
|
||||||
var alpha = notification.AnimationProgress;
|
var alpha = notification.AnimationProgress;
|
||||||
if (alpha <= 0f) return;
|
|
||||||
|
|
||||||
var slideOffset = (1f - alpha) * SlideDistance;
|
if (_configService.Current.EnableNotificationAnimations && alpha <= 0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var slideOffset = 0f;
|
||||||
|
if (_configService.Current.EnableNotificationAnimations)
|
||||||
|
{
|
||||||
|
slideOffset = (1f - alpha) * SlideDistance;
|
||||||
|
}
|
||||||
|
|
||||||
var originalCursorPos = ImGui.GetCursorPos();
|
var originalCursorPos = ImGui.GetCursorPos();
|
||||||
ImGui.SetCursorPosX(originalCursorPos.X + slideOffset);
|
ImGui.SetCursorPosX(originalCursorPos.X + slideOffset);
|
||||||
|
|
||||||
@@ -198,13 +224,18 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
|||||||
var windowPos = ImGui.GetWindowPos();
|
var windowPos = ImGui.GetWindowPos();
|
||||||
var windowSize = ImGui.GetWindowSize();
|
var windowSize = ImGui.GetWindowSize();
|
||||||
|
|
||||||
var bgColor = new Vector4(30f/255f, 30f/255f, 30f/255f, 0.95f * alpha);
|
var baseOpacity = _configService.Current.NotificationOpacity;
|
||||||
|
var finalOpacity = _configService.Current.EnableNotificationAnimations ? baseOpacity * alpha : baseOpacity;
|
||||||
|
var bgColor = new Vector4(30f/255f, 30f/255f, 30f/255f, finalOpacity);
|
||||||
var accentColor = GetNotificationAccentColor(notification.Type);
|
var accentColor = GetNotificationAccentColor(notification.Type);
|
||||||
var progressBarColor = UIColors.Get("LightlessBlue");
|
var progressBarColor = UIColors.Get("LightlessBlue");
|
||||||
accentColor.W *= alpha;
|
|
||||||
|
var finalAccentAlpha = _configService.Current.EnableNotificationAnimations ? alpha : 1f;
|
||||||
|
accentColor.W *= finalAccentAlpha;
|
||||||
|
|
||||||
var shadowOffset = new Vector2(1f, 1f);
|
var shadowOffset = new Vector2(1f, 1f);
|
||||||
var shadowColor = new Vector4(0f, 0f, 0f, 0.4f * alpha);
|
var shadowAlpha = _configService.Current.EnableNotificationAnimations ? 0.4f * alpha : 0.4f;
|
||||||
|
var shadowColor = new Vector4(0f, 0f, 0f, shadowAlpha);
|
||||||
drawList.AddRectFilled(
|
drawList.AddRectFilled(
|
||||||
windowPos + shadowOffset,
|
windowPos + shadowOffset,
|
||||||
windowPos + windowSize + shadowOffset,
|
windowPos + windowSize + shadowOffset,
|
||||||
@@ -278,14 +309,31 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
|||||||
|
|
||||||
ImGui.SetCursorPos(contentPos);
|
ImGui.SetCursorPos(contentPos);
|
||||||
|
|
||||||
|
float titleHeight = 0f;
|
||||||
using (ImRaii.PushColor(ImGuiCol.Text, new Vector4(1f, 1f, 1f, alpha)))
|
using (ImRaii.PushColor(ImGuiCol.Text, new Vector4(1f, 1f, 1f, alpha)))
|
||||||
{
|
{
|
||||||
ImGui.Text(notification.Title);
|
// Set text wrap position to prevent title overflow
|
||||||
|
ImGui.PushTextWrapPos(ImGui.GetCursorPosX() + contentSize.X);
|
||||||
|
|
||||||
|
var titleStartY = ImGui.GetCursorPosY();
|
||||||
|
|
||||||
|
if (_configService.Current.ShowNotificationTimestamp)
|
||||||
|
{
|
||||||
|
var timestamp = notification.CreatedAt.ToLocalTime().ToString("HH:mm:ss");
|
||||||
|
ImGui.TextWrapped($"[{timestamp}] {notification.Title}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui.TextWrapped(notification.Title);
|
||||||
|
}
|
||||||
|
|
||||||
|
titleHeight = ImGui.GetCursorPosY() - titleStartY;
|
||||||
|
ImGui.PopTextWrapPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(notification.Message))
|
if (!string.IsNullOrEmpty(notification.Message))
|
||||||
{
|
{
|
||||||
ImGui.SetCursorPos(contentPos + new Vector2(0f, 18f));
|
ImGui.SetCursorPos(contentPos + new Vector2(0f, titleHeight + 4f));
|
||||||
ImGui.PushTextWrapPos(ImGui.GetCursorPosX() + contentSize.X);
|
ImGui.PushTextWrapPos(ImGui.GetCursorPosX() + contentSize.X);
|
||||||
using (ImRaii.PushColor(ImGuiCol.Text, new Vector4(0.9f, 0.9f, 0.9f, alpha)))
|
using (ImRaii.PushColor(ImGuiCol.Text, new Vector4(0.9f, 0.9f, 0.9f, alpha)))
|
||||||
{
|
{
|
||||||
@@ -436,24 +484,40 @@ public class LightlessNotificationUI : WindowMediatorSubscriberBase
|
|||||||
|
|
||||||
private float CalculateNotificationHeight(LightlessNotification notification)
|
private float CalculateNotificationHeight(LightlessNotification notification)
|
||||||
{
|
{
|
||||||
var height = 40f;
|
var contentWidth = NotificationWidth - 35f; // Account for padding and accent bar
|
||||||
if (!string.IsNullOrEmpty(notification.Message))
|
var height = 20f; // Base height for padding
|
||||||
|
|
||||||
|
var titleText = notification.Title;
|
||||||
|
if (_configService.Current.ShowNotificationTimestamp)
|
||||||
{
|
{
|
||||||
var textSize = ImGui.CalcTextSize(notification.Message, true, NotificationWidth - 35f);
|
var timestamp = notification.CreatedAt.ToLocalTime().ToString("HH:mm:ss");
|
||||||
height += textSize.Y + 4f;
|
titleText = $"[{timestamp}] {titleText}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var titleSize = ImGui.CalcTextSize(titleText, true, contentWidth);
|
||||||
|
height += titleSize.Y + 4f; // Title height + spacing
|
||||||
|
|
||||||
|
// Calculate message height
|
||||||
|
if (!string.IsNullOrEmpty(notification.Message))
|
||||||
|
{
|
||||||
|
var messageSize = ImGui.CalcTextSize(notification.Message, true, contentWidth);
|
||||||
|
height += messageSize.Y + 4f; // Message height + spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add height for progress bar
|
||||||
if (notification.ShowProgress)
|
if (notification.ShowProgress)
|
||||||
{
|
{
|
||||||
height += 12f;
|
height += 12f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add height for action buttons
|
||||||
if (notification.Actions.Count > 0)
|
if (notification.Actions.Count > 0)
|
||||||
{
|
{
|
||||||
height += 28f;
|
height += 28f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.Max(height, NotificationMinHeight);
|
// Allow notifications to grow taller but cap at maximum height
|
||||||
|
return Math.Clamp(height, NotificationMinHeight, NotificationMaxHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector4 GetNotificationAccentColor(NotificationType type)
|
private Vector4 GetNotificationAccentColor(NotificationType type)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
@@ -61,6 +61,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
private readonly IProgress<(int, int, FileCacheEntity)> _validationProgress;
|
private readonly IProgress<(int, int, FileCacheEntity)> _validationProgress;
|
||||||
private readonly NameplateService _nameplateService;
|
private readonly NameplateService _nameplateService;
|
||||||
private readonly NameplateHandler _nameplateHandler;
|
private readonly NameplateHandler _nameplateHandler;
|
||||||
|
private readonly LightlessNotificationService _lightlessNotificationService;
|
||||||
private (int, int, FileCacheEntity) _currentProgress;
|
private (int, int, FileCacheEntity) _currentProgress;
|
||||||
private bool _deleteAccountPopupModalShown = false;
|
private bool _deleteAccountPopupModalShown = false;
|
||||||
private bool _deleteFilesPopupModalShown = false;
|
private bool _deleteFilesPopupModalShown = false;
|
||||||
@@ -105,7 +106,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
IpcManager ipcManager, CacheMonitor cacheMonitor,
|
IpcManager ipcManager, CacheMonitor cacheMonitor,
|
||||||
DalamudUtilService dalamudUtilService, HttpClient httpClient,
|
DalamudUtilService dalamudUtilService, HttpClient httpClient,
|
||||||
NameplateService nameplateService,
|
NameplateService nameplateService,
|
||||||
NameplateHandler nameplateHandler) : base(logger, mediator, "Lightless Sync Settings", performanceCollector)
|
NameplateHandler nameplateHandler,
|
||||||
|
LightlessNotificationService lightlessNotificationService) : base(logger, mediator, "Lightless Sync Settings", performanceCollector)
|
||||||
{
|
{
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_pairManager = pairManager;
|
_pairManager = pairManager;
|
||||||
@@ -125,6 +127,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
_uiShared = uiShared;
|
_uiShared = uiShared;
|
||||||
_nameplateService = nameplateService;
|
_nameplateService = nameplateService;
|
||||||
_nameplateHandler = nameplateHandler;
|
_nameplateHandler = nameplateHandler;
|
||||||
|
_lightlessNotificationService = lightlessNotificationService;
|
||||||
AllowClickthrough = false;
|
AllowClickthrough = false;
|
||||||
AllowPinning = true;
|
AllowPinning = true;
|
||||||
_validationProgress = new Progress<(int, int, FileCacheEntity)>(v => _currentProgress = v);
|
_validationProgress = new Progress<(int, int, FileCacheEntity)>(v => _currentProgress = v);
|
||||||
@@ -351,13 +354,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
_uiShared.UnderlinedBigText("Transfer UI", UIColors.Get("LightlessBlue"));
|
_uiShared.UnderlinedBigText("Transfer UI", UIColors.Get("LightlessBlue"));
|
||||||
ImGuiHelpers.ScaledDummy(5);
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
|
|
||||||
bool useNotificationsForDownloads = _configService.Current.UseNotificationsForDownloads;
|
_uiShared.DrawHelpText("Download progress notification settings have been moved to the 'Enhanced Notifications' tab for better organization.");
|
||||||
if (ImGui.Checkbox("Use notifications for download progress", ref useNotificationsForDownloads))
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
{
|
|
||||||
_configService.Current.UseNotificationsForDownloads = useNotificationsForDownloads;
|
|
||||||
_configService.Save();
|
|
||||||
}
|
|
||||||
_uiShared.DrawHelpText("Show download progress as clean notifications instead of overlay text. Notifications update in real-time.");
|
|
||||||
|
|
||||||
bool showTransferWindow = _configService.Current.ShowTransferWindow;
|
bool showTransferWindow = _configService.Current.ShowTransferWindow;
|
||||||
if (ImGui.Checkbox("Show separate transfer window", ref showTransferWindow))
|
if (ImGui.Checkbox("Show separate transfer window", ref showTransferWindow))
|
||||||
@@ -1645,48 +1643,10 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
ImGui.Dummy(new Vector2(10));
|
ImGui.Dummy(new Vector2(10));
|
||||||
_uiShared.BigText("Notifications");
|
_uiShared.BigText("Notifications");
|
||||||
|
|
||||||
var disableOptionalPluginWarnings = _configService.Current.DisableOptionalPluginWarnings;
|
|
||||||
var onlineNotifs = _configService.Current.ShowOnlineNotifications;
|
|
||||||
var onlineNotifsPairsOnly = _configService.Current.ShowOnlineNotificationsOnlyForIndividualPairs;
|
|
||||||
var onlineNotifsNamedOnly = _configService.Current.ShowOnlineNotificationsOnlyForNamedPairs;
|
|
||||||
|
|
||||||
if (_uiShared.MediumTreeNode("Display", UIColors.Get("LightlessPurple")))
|
if (_uiShared.MediumTreeNode("Display", UIColors.Get("LightlessPurple")))
|
||||||
{
|
{
|
||||||
_uiShared.DrawCombo("Info Notification Display##settingsUi", (NotificationLocation[])Enum.GetValues(typeof(NotificationLocation)), (i) => i.ToString(),
|
_uiShared.DrawHelpText("Notification settings have been moved to the 'Enhanced Notifications' tab for better organization. You can configure where all notifications appear from there.");
|
||||||
(i) =>
|
|
||||||
{
|
|
||||||
_configService.Current.InfoNotification = i;
|
|
||||||
_configService.Save();
|
|
||||||
}, _configService.Current.InfoNotification);
|
|
||||||
_uiShared.DrawHelpText("The location where \"Info\" notifications will display."
|
|
||||||
+ Environment.NewLine + "'Nowhere' will not show any Info notifications"
|
|
||||||
+ Environment.NewLine + "'Chat' will print Info notifications in chat"
|
|
||||||
+ Environment.NewLine + "'Toast' will show Warning toast notifications in the bottom right corner"
|
|
||||||
+ Environment.NewLine + "'Both' will show chat as well as the toast notification");
|
|
||||||
|
|
||||||
_uiShared.DrawCombo("Warning Notification Display##settingsUi", (NotificationLocation[])Enum.GetValues(typeof(NotificationLocation)), (i) => i.ToString(),
|
|
||||||
(i) =>
|
|
||||||
{
|
|
||||||
_configService.Current.WarningNotification = i;
|
|
||||||
_configService.Save();
|
|
||||||
}, _configService.Current.WarningNotification);
|
|
||||||
_uiShared.DrawHelpText("The location where \"Warning\" notifications will display."
|
|
||||||
+ Environment.NewLine + "'Nowhere' will not show any Warning notifications"
|
|
||||||
+ Environment.NewLine + "'Chat' will print Warning notifications in chat"
|
|
||||||
+ Environment.NewLine + "'Toast' will show Warning toast notifications in the bottom right corner"
|
|
||||||
+ Environment.NewLine + "'Both' will show chat as well as the toast notification");
|
|
||||||
|
|
||||||
_uiShared.DrawCombo("Error Notification Display##settingsUi", (NotificationLocation[])Enum.GetValues(typeof(NotificationLocation)), (i) => i.ToString(),
|
|
||||||
(i) =>
|
|
||||||
{
|
|
||||||
_configService.Current.ErrorNotification = i;
|
|
||||||
_configService.Save();
|
|
||||||
}, _configService.Current.ErrorNotification);
|
|
||||||
_uiShared.DrawHelpText("The location where \"Error\" notifications will display."
|
|
||||||
+ Environment.NewLine + "'Nowhere' will not show any Error notifications"
|
|
||||||
+ Environment.NewLine + "'Chat' will print Error notifications in chat"
|
|
||||||
+ Environment.NewLine + "'Toast' will show Error toast notifications in the bottom right corner"
|
|
||||||
+ Environment.NewLine + "'Both' will show chat as well as the toast notification");
|
|
||||||
|
|
||||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||||
ImGui.TreePop();
|
ImGui.TreePop();
|
||||||
@@ -1694,38 +1654,6 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
if (_uiShared.MediumTreeNode("Toggles", UIColors.Get("LightlessPurple")))
|
|
||||||
{
|
|
||||||
if (ImGui.Checkbox("Disable optional plugin warnings", ref disableOptionalPluginWarnings))
|
|
||||||
{
|
|
||||||
_configService.Current.DisableOptionalPluginWarnings = disableOptionalPluginWarnings;
|
|
||||||
_configService.Save();
|
|
||||||
}
|
|
||||||
_uiShared.DrawHelpText("Enabling this will not show any \"Warning\" labeled messages for missing optional plugins.");
|
|
||||||
if (ImGui.Checkbox("Enable online notifications", ref onlineNotifs))
|
|
||||||
{
|
|
||||||
_configService.Current.ShowOnlineNotifications = onlineNotifs;
|
|
||||||
_configService.Save();
|
|
||||||
}
|
|
||||||
_uiShared.DrawHelpText("Enabling this will show a small notification (type: Info) in the bottom right corner when pairs go online.");
|
|
||||||
|
|
||||||
using var disabled = ImRaii.Disabled(!onlineNotifs);
|
|
||||||
if (ImGui.Checkbox("Notify only for individual pairs", ref onlineNotifsPairsOnly))
|
|
||||||
{
|
|
||||||
_configService.Current.ShowOnlineNotificationsOnlyForIndividualPairs = onlineNotifsPairsOnly;
|
|
||||||
_configService.Save();
|
|
||||||
}
|
|
||||||
_uiShared.DrawHelpText("Enabling this will only show online notifications (type: Info) for individual pairs.");
|
|
||||||
if (ImGui.Checkbox("Notify only for named pairs", ref onlineNotifsNamedOnly))
|
|
||||||
{
|
|
||||||
_configService.Current.ShowOnlineNotificationsOnlyForNamedPairs = onlineNotifsNamedOnly;
|
|
||||||
_configService.Save();
|
|
||||||
}
|
|
||||||
_uiShared.DrawHelpText("Enabling this will only show online notifications (type: Info) for pairs where you have set an individual note.");
|
|
||||||
|
|
||||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
|
||||||
ImGui.TreePop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawPerformance()
|
private void DrawPerformance()
|
||||||
@@ -2661,6 +2589,12 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
ImGui.EndTabItem();
|
ImGui.EndTabItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui.BeginTabItem("Notifications"))
|
||||||
|
{
|
||||||
|
DrawNotificationSettings();
|
||||||
|
ImGui.EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui.BeginTabItem("Debug"))
|
if (ImGui.BeginTabItem("Debug"))
|
||||||
{
|
{
|
||||||
DrawDebug();
|
DrawDebug();
|
||||||
@@ -2681,4 +2615,568 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
_wasOpen = IsOpen;
|
_wasOpen = IsOpen;
|
||||||
IsOpen = false;
|
IsOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawNotificationSettings()
|
||||||
|
{
|
||||||
|
_lastTab = "Notifications";
|
||||||
|
_uiShared.UnderlinedBigText("Notification System", UIColors.Get("LightlessBlue"));
|
||||||
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
|
|
||||||
|
bool useLightlessNotifications = _configService.Current.UseLightlessNotifications;
|
||||||
|
if (ImGui.Checkbox("Use Enhanced Lightless Notifications", ref useLightlessNotifications))
|
||||||
|
{
|
||||||
|
_configService.Current.UseLightlessNotifications = useLightlessNotifications;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Enable the new enhanced notification system with interactive buttons, animations, and better visual design.");
|
||||||
|
ImGui.Separator();
|
||||||
|
_uiShared.UnderlinedBigText("Notification Locations", UIColors.Get("LightlessBlue"));
|
||||||
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
|
|
||||||
|
UiSharedService.ColorTextWrapped("Configure where different types of notifications appear. Enhanced notifications provide modern interactive notifications with backwards compatibility support for classic toast/chat notifications.", ImGuiColors.DalamudGrey);
|
||||||
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
|
|
||||||
|
if (useLightlessNotifications)
|
||||||
|
{
|
||||||
|
// Enhanced notification locations (primary)
|
||||||
|
_uiShared.BigText("Enhanced Notification Locations");
|
||||||
|
ImGuiHelpers.ScaledDummy(3);
|
||||||
|
|
||||||
|
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(5);
|
||||||
|
|
||||||
|
// Classic notification locations (backwards compatibility)
|
||||||
|
if (ImGui.CollapsingHeader("Classic Notification Settings (Backwards Compatibility)"))
|
||||||
|
{
|
||||||
|
_uiShared.DrawHelpText("These settings provide backwards compatibility. They will also be used if they're different from the enhanced settings above and don't conflict.");
|
||||||
|
ImGuiHelpers.ScaledDummy(3);
|
||||||
|
|
||||||
|
var classicLocations = GetClassicNotificationLocations();
|
||||||
|
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("Info Fallback:");
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||||
|
_uiShared.DrawCombo("###classic_info", classicLocations, GetNotificationLocationLabel, (location) =>
|
||||||
|
{
|
||||||
|
_configService.Current.InfoNotification = location;
|
||||||
|
_configService.Save();
|
||||||
|
}, _configService.Current.InfoNotification);
|
||||||
|
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("Warning Fallback:");
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||||
|
_uiShared.DrawCombo("###classic_warning", classicLocations, GetNotificationLocationLabel, (location) =>
|
||||||
|
{
|
||||||
|
_configService.Current.WarningNotification = location;
|
||||||
|
_configService.Save();
|
||||||
|
}, _configService.Current.WarningNotification);
|
||||||
|
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("Error Fallback:");
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||||
|
_uiShared.DrawCombo("###classic_error", classicLocations, GetNotificationLocationLabel, (location) =>
|
||||||
|
{
|
||||||
|
_configService.Current.ErrorNotification = location;
|
||||||
|
_configService.Save();
|
||||||
|
}, _configService.Current.ErrorNotification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Only classic notifications when enhanced is disabled
|
||||||
|
var classicLocations = GetClassicNotificationLocations();
|
||||||
|
_uiShared.BigText("Classic Notification Locations");
|
||||||
|
ImGuiHelpers.ScaledDummy(3);
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("Info Notifications:");
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||||
|
_uiShared.DrawCombo("###info", classicLocations, GetNotificationLocationLabel, (location) =>
|
||||||
|
{
|
||||||
|
_configService.Current.InfoNotification = location;
|
||||||
|
_configService.Save();
|
||||||
|
}, _configService.Current.InfoNotification);
|
||||||
|
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("Warning Notifications:");
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||||
|
_uiShared.DrawCombo("###warning", classicLocations, GetNotificationLocationLabel, (location) =>
|
||||||
|
{
|
||||||
|
_configService.Current.WarningNotification = location;
|
||||||
|
_configService.Save();
|
||||||
|
}, _configService.Current.WarningNotification);
|
||||||
|
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("Error Notifications:");
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||||
|
_uiShared.DrawCombo("###error", classicLocations, GetNotificationLocationLabel, (location) =>
|
||||||
|
{
|
||||||
|
_configService.Current.ErrorNotification = location;
|
||||||
|
_configService.Save();
|
||||||
|
}, _configService.Current.ErrorNotification);
|
||||||
|
}
|
||||||
|
ImGui.Separator();
|
||||||
|
if (useLightlessNotifications)
|
||||||
|
{
|
||||||
|
UiSharedService.ColorTextWrapped("• Lightless Notifications: Modern animated notifications with interactive buttons", ImGuiColors.DalamudGrey);
|
||||||
|
UiSharedService.ColorTextWrapped("• Chat: Traditional chat messages with colored text", ImGuiColors.DalamudGrey);
|
||||||
|
UiSharedService.ColorTextWrapped("• Combined options: Show in multiple locations simultaneously", ImGuiColors.DalamudGrey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UiSharedService.ColorTextWrapped("• Toast: Dalamud's built-in notification toasts", ImGuiColors.DalamudGrey);
|
||||||
|
UiSharedService.ColorTextWrapped("• Chat: Traditional chat messages with colored text", ImGuiColors.DalamudGrey);
|
||||||
|
UiSharedService.ColorTextWrapped("• Both: Show in both toast and chat", ImGuiColors.DalamudGrey);
|
||||||
|
}
|
||||||
|
ImGui.Separator();
|
||||||
|
if (useLightlessNotifications)
|
||||||
|
{
|
||||||
|
ImGui.Indent();
|
||||||
|
|
||||||
|
// Test notification buttons
|
||||||
|
if (_uiShared.IconTextButton(FontAwesomeIcon.Bell, "Test Info"))
|
||||||
|
{
|
||||||
|
Mediator.Publish(new NotificationMessage("Test Info", "This is a test info notification with the current settings!", 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));
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Click to preview different notification types with your current settings.");
|
||||||
|
|
||||||
|
ImGui.Unindent();
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
_uiShared.UnderlinedBigText("Basic Settings", UIColors.Get("LightlessBlue"));
|
||||||
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
|
|
||||||
|
int defaultDuration = _configService.Current.DefaultNotificationDurationSeconds;
|
||||||
|
if (ImGui.SliderInt("Default Duration (seconds)", ref defaultDuration, 3, 60))
|
||||||
|
{
|
||||||
|
_configService.Current.DefaultNotificationDurationSeconds = defaultDuration;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("How long notifications stay visible by default.");
|
||||||
|
|
||||||
|
bool showProgress = _configService.Current.ShowNotificationProgress;
|
||||||
|
if (ImGui.Checkbox("Show Progress Bars", ref showProgress))
|
||||||
|
{
|
||||||
|
_configService.Current.ShowNotificationProgress = showProgress;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Display progress bars for download and other progress-based notifications.");
|
||||||
|
|
||||||
|
bool showTimestamp = _configService.Current.ShowNotificationTimestamp;
|
||||||
|
if (ImGui.Checkbox("Show Timestamps", ref showTimestamp))
|
||||||
|
{
|
||||||
|
_configService.Current.ShowNotificationTimestamp = showTimestamp;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Display the time when each notification was created.");
|
||||||
|
|
||||||
|
bool autoDismiss = _configService.Current.AutoDismissOnAction;
|
||||||
|
if (ImGui.Checkbox("Auto-dismiss on Action", ref autoDismiss))
|
||||||
|
{
|
||||||
|
_configService.Current.AutoDismissOnAction = autoDismiss;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Automatically close notifications when you click an action button.");
|
||||||
|
|
||||||
|
if (useLightlessNotifications)
|
||||||
|
{
|
||||||
|
ImGui.Separator();
|
||||||
|
_uiShared.UnderlinedBigText("Appearance & Animation", UIColors.Get("LightlessBlue"));
|
||||||
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
|
|
||||||
|
float opacity = _configService.Current.NotificationOpacity;
|
||||||
|
if (ImGui.SliderFloat("Notification Opacity", ref opacity, 0.1f, 1.0f, "%.2f"))
|
||||||
|
{
|
||||||
|
_configService.Current.NotificationOpacity = opacity;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Transparency level of notification windows.");
|
||||||
|
|
||||||
|
bool enableAnimations = _configService.Current.EnableNotificationAnimations;
|
||||||
|
if (ImGui.Checkbox("Enable Animations", ref enableAnimations))
|
||||||
|
{
|
||||||
|
_configService.Current.EnableNotificationAnimations = enableAnimations;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Enable slide-in/out animations for notifications.");
|
||||||
|
|
||||||
|
int maxNotifications = _configService.Current.MaxSimultaneousNotifications;
|
||||||
|
if (ImGui.SliderInt("Max Simultaneous Notifications", ref maxNotifications, 1, 10))
|
||||||
|
{
|
||||||
|
_configService.Current.MaxSimultaneousNotifications = maxNotifications;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Maximum number of notifications that can be shown at once.");
|
||||||
|
|
||||||
|
bool enableHistory = _configService.Current.EnableNotificationHistory;
|
||||||
|
if (ImGui.Checkbox("Enable Notification History", ref enableHistory))
|
||||||
|
{
|
||||||
|
_configService.Current.EnableNotificationHistory = enableHistory;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Keep a history of recent notifications that you can review.");
|
||||||
|
|
||||||
|
if (enableHistory)
|
||||||
|
{
|
||||||
|
ImGui.Indent();
|
||||||
|
int historySize = _configService.Current.NotificationHistorySize;
|
||||||
|
if (ImGui.SliderInt("History Size", ref historySize, 10, 200))
|
||||||
|
{
|
||||||
|
_configService.Current.NotificationHistorySize = historySize;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Number of notifications to keep in history.");
|
||||||
|
ImGui.Unindent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
_uiShared.UnderlinedBigText("Sound Settings", UIColors.Get("LightlessBlue"));
|
||||||
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
|
|
||||||
|
bool enableSounds = _configService.Current.EnableNotificationSounds;
|
||||||
|
if (ImGui.Checkbox("Enable Notification Sounds", ref enableSounds))
|
||||||
|
{
|
||||||
|
_configService.Current.EnableNotificationSounds = enableSounds;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Play FFXIV sound effects when notifications appear.");
|
||||||
|
|
||||||
|
if (enableSounds)
|
||||||
|
{
|
||||||
|
ImGui.Indent();
|
||||||
|
|
||||||
|
// float soundVolume = _configService.Current.NotificationSoundVolume;
|
||||||
|
// if (ImGui.SliderFloat("Sound Volume", ref soundVolume, 0.0f, 1.0f, "%.2f"))
|
||||||
|
// {
|
||||||
|
// _configService.Current.NotificationSoundVolume = soundVolume;
|
||||||
|
// _configService.Save();
|
||||||
|
// }
|
||||||
|
// _uiShared.DrawHelpText("Volume level for notification sounds (Note: FFXIV doesn't support volume control for SE sounds).");
|
||||||
|
|
||||||
|
// bool useCustomSounds = _configService.Current.UseCustomSounds;
|
||||||
|
// if (ImGui.Checkbox("Use Custom Sound Effects", ref useCustomSounds))
|
||||||
|
// {
|
||||||
|
// _configService.Current.UseCustomSounds = useCustomSounds;
|
||||||
|
// _configService.Save();
|
||||||
|
// }
|
||||||
|
// _uiShared.DrawHelpText("Override default sounds with custom FFXIV sound effects.");
|
||||||
|
DrawSoundCustomization();
|
||||||
|
|
||||||
|
// if (useCustomSounds)
|
||||||
|
// {
|
||||||
|
// ImGui.Indent();
|
||||||
|
// DrawSoundCustomization();
|
||||||
|
// ImGui.Unindent();
|
||||||
|
// }
|
||||||
|
|
||||||
|
ImGui.Unindent();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
_uiShared.UnderlinedBigText("Specific Notification Types", UIColors.Get("LightlessBlue"));
|
||||||
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
|
|
||||||
|
UiSharedService.ColorTextWrapped("Configure specific types of notifications and their behavior.", ImGuiColors.DalamudGrey);
|
||||||
|
ImGuiHelpers.ScaledDummy(3);
|
||||||
|
|
||||||
|
// Online Notifications Section
|
||||||
|
if (_uiShared.MediumTreeNode("Online Status Notifications", UIColors.Get("LightlessGreen")))
|
||||||
|
{
|
||||||
|
var onlineNotifs = _configService.Current.ShowOnlineNotifications;
|
||||||
|
var onlineNotifsPairsOnly = _configService.Current.ShowOnlineNotificationsOnlyForIndividualPairs;
|
||||||
|
var onlineNotifsNamedOnly = _configService.Current.ShowOnlineNotificationsOnlyForNamedPairs;
|
||||||
|
|
||||||
|
if (ImGui.Checkbox("Enable online notifications", ref onlineNotifs))
|
||||||
|
{
|
||||||
|
_configService.Current.ShowOnlineNotifications = onlineNotifs;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Show notifications when pairs come online. These will use the Info notification location settings above.");
|
||||||
|
|
||||||
|
using var disabled = ImRaii.Disabled(!onlineNotifs);
|
||||||
|
ImGui.Indent();
|
||||||
|
if (ImGui.Checkbox("Notify only for individual pairs", ref onlineNotifsPairsOnly))
|
||||||
|
{
|
||||||
|
_configService.Current.ShowOnlineNotificationsOnlyForIndividualPairs = onlineNotifsPairsOnly;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Only show online notifications for individual pairs (not syncshell members).");
|
||||||
|
|
||||||
|
if (ImGui.Checkbox("Notify only for named pairs", ref onlineNotifsNamedOnly))
|
||||||
|
{
|
||||||
|
_configService.Current.ShowOnlineNotificationsOnlyForNamedPairs = onlineNotifsNamedOnly;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Only show online notifications for pairs where you have set an individual note.");
|
||||||
|
ImGui.Unindent();
|
||||||
|
|
||||||
|
_uiShared.ColoredSeparator(UIColors.Get("LightlessGreen"), 1.5f);
|
||||||
|
ImGui.TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pairing Request Notifications Section
|
||||||
|
if (_uiShared.MediumTreeNode("Pairing Request Notifications", UIColors.Get("LightlessBlue")))
|
||||||
|
{
|
||||||
|
UiSharedService.ColorTextWrapped("Pairing requests always show as interactive notifications with Accept/Decline buttons. These settings control additional behavior.", ImGuiColors.DalamudGrey);
|
||||||
|
ImGuiHelpers.ScaledDummy(3);
|
||||||
|
|
||||||
|
// Note: Pairing requests are always shown as interactive notifications
|
||||||
|
// This section can be expanded later with additional pairing notification settings
|
||||||
|
|
||||||
|
_uiShared.ColoredSeparator(UIColors.Get("LightlessBlue"), 1.5f);
|
||||||
|
ImGui.TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download Progress Notifications Section
|
||||||
|
if (_uiShared.MediumTreeNode("Download Progress Notifications", UIColors.Get("LightlessPurple")))
|
||||||
|
{
|
||||||
|
var useNotificationsForDownloads = _configService.Current.UseNotificationsForDownloads;
|
||||||
|
if (ImGui.Checkbox("Show download progress as notifications", ref useNotificationsForDownloads))
|
||||||
|
{
|
||||||
|
_configService.Current.UseNotificationsForDownloads = useNotificationsForDownloads;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Show download progress as clean notifications instead of overlay text. Notifications update in real-time and use the Info notification location settings above.");
|
||||||
|
|
||||||
|
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||||
|
ImGui.TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// System Notifications Section
|
||||||
|
if (_uiShared.MediumTreeNode("System Notifications", UIColors.Get("LightlessYellow")))
|
||||||
|
{
|
||||||
|
var disableOptionalPluginWarnings = _configService.Current.DisableOptionalPluginWarnings;
|
||||||
|
if (ImGui.Checkbox("Disable optional plugin warnings", ref disableOptionalPluginWarnings))
|
||||||
|
{
|
||||||
|
_configService.Current.DisableOptionalPluginWarnings = disableOptionalPluginWarnings;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Disable warning notifications for missing optional plugins.");
|
||||||
|
|
||||||
|
_uiShared.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
||||||
|
ImGui.TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
_uiShared.UnderlinedBigText("Location Descriptions", UIColors.Get("LightlessBlue"));
|
||||||
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private NotificationLocation[] GetLightlessNotificationLocations()
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
NotificationLocation.LightlessUI,
|
||||||
|
NotificationLocation.ChatAndLightlessUI,
|
||||||
|
NotificationLocation.Nowhere
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private NotificationLocation[] GetClassicNotificationLocations()
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
NotificationLocation.Toast,
|
||||||
|
NotificationLocation.Chat,
|
||||||
|
NotificationLocation.Both,
|
||||||
|
NotificationLocation.Nowhere
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetNotificationLocationLabel(NotificationLocation location)
|
||||||
|
{
|
||||||
|
return location switch
|
||||||
|
{
|
||||||
|
NotificationLocation.Nowhere => "Nowhere",
|
||||||
|
NotificationLocation.Chat => "Chat",
|
||||||
|
NotificationLocation.Toast => "Toast",
|
||||||
|
NotificationLocation.Both => "Toast + Chat",
|
||||||
|
NotificationLocation.LightlessUI => "Lightless Notifications",
|
||||||
|
NotificationLocation.ChatAndLightlessUI => "Chat + Lightless Notifications",
|
||||||
|
_ => location.ToString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawSoundCustomization()
|
||||||
|
{
|
||||||
|
var soundEffects = new[]
|
||||||
|
{
|
||||||
|
(1u, "Se1 - Soft chime"),
|
||||||
|
(2u, "Se2 - Higher chime"),
|
||||||
|
(3u, "Se3 - Bell tone"),
|
||||||
|
(4u, "Se4 - Harp tone"),
|
||||||
|
(5u, "Se5 - Drum/percussion"),
|
||||||
|
(6u, "Se6 - Mechanical click"),
|
||||||
|
(7u, "Se7 - Metallic chime"),
|
||||||
|
(8u, "Se8 - Wooden tone"),
|
||||||
|
(9u, "Se9 - Wind/flute tone"),
|
||||||
|
(10u, "Se10 - Magical sparkle"),
|
||||||
|
(11u, "Se11 - Metallic ring"),
|
||||||
|
(12u, "Se12 - Deep thud"),
|
||||||
|
(13u, "Se13 - Tell received ping"),
|
||||||
|
(14u, "Se14 - Success fanfare"),
|
||||||
|
(15u, "Se15 - System warning"),
|
||||||
|
(16u, "Se16 - Error/failure")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Info Sound
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("Info Sound:");
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||||
|
var currentInfoSound = _configService.Current.CustomInfoSoundId;
|
||||||
|
var currentInfoIndex = Array.FindIndex(soundEffects, s => s.Item1 == currentInfoSound);
|
||||||
|
if (currentInfoIndex == -1) currentInfoIndex = 1; // Default to Se2
|
||||||
|
|
||||||
|
if (ImGui.Combo("###info_sound", ref currentInfoIndex, soundEffects.Select(s => s.Item2).ToArray(), soundEffects.Length))
|
||||||
|
{
|
||||||
|
_configService.Current.CustomInfoSoundId = soundEffects[currentInfoIndex].Item1;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.PushID("test_info");
|
||||||
|
if (_uiShared.IconButton(FontAwesomeIcon.Play))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FFXIVClientStructs.FFXIV.Client.UI.UIGlobals.PlayChatSoundEffect(_configService.Current.CustomInfoSoundId);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Failed to play test sound");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui.PopID();
|
||||||
|
UiSharedService.AttachToolTip("Test this sound");
|
||||||
|
|
||||||
|
// Warning Sound
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("Warning Sound:");
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||||
|
var currentWarningSound = _configService.Current.CustomWarningSoundId;
|
||||||
|
var currentWarningIndex = Array.FindIndex(soundEffects, s => s.Item1 == currentWarningSound);
|
||||||
|
if (currentWarningIndex == -1) currentWarningIndex = 14; // Default to Se15
|
||||||
|
|
||||||
|
if (ImGui.Combo("###warning_sound", ref currentWarningIndex, soundEffects.Select(s => s.Item2).ToArray(), soundEffects.Length))
|
||||||
|
{
|
||||||
|
_configService.Current.CustomWarningSoundId = soundEffects[currentWarningIndex].Item1;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.PushID("test_warning");
|
||||||
|
if (_uiShared.IconButton(FontAwesomeIcon.Play))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FFXIVClientStructs.FFXIV.Client.UI.UIGlobals.PlayChatSoundEffect(_configService.Current.CustomWarningSoundId);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Failed to play test sound");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui.PopID();
|
||||||
|
UiSharedService.AttachToolTip("Test this sound");
|
||||||
|
|
||||||
|
// Error Sound
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("Error Sound:");
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||||
|
var currentErrorSound = _configService.Current.CustomErrorSoundId;
|
||||||
|
var currentErrorIndex = Array.FindIndex(soundEffects, s => s.Item1 == currentErrorSound);
|
||||||
|
if (currentErrorIndex == -1) currentErrorIndex = 15; // Default to Se16
|
||||||
|
|
||||||
|
if (ImGui.Combo("###error_sound", ref currentErrorIndex, soundEffects.Select(s => s.Item2).ToArray(), soundEffects.Length))
|
||||||
|
{
|
||||||
|
_configService.Current.CustomErrorSoundId = soundEffects[currentErrorIndex].Item1;
|
||||||
|
_configService.Save();
|
||||||
|
}
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.PushID("test_error");
|
||||||
|
if (_uiShared.IconButton(FontAwesomeIcon.Play))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FFXIVClientStructs.FFXIV.Client.UI.UIGlobals.PlayChatSoundEffect(_configService.Current.CustomErrorSoundId);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Failed to play test sound");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui.PopID();
|
||||||
|
UiSharedService.AttachToolTip("Test this sound");
|
||||||
|
|
||||||
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
|
if (_uiShared.IconTextButton(FontAwesomeIcon.VolumeUp, "Test All Sounds"))
|
||||||
|
{
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FFXIVClientStructs.FFXIV.Client.UI.UIGlobals.PlayChatSoundEffect(_configService.Current.CustomInfoSoundId);
|
||||||
|
await Task.Delay(800);
|
||||||
|
FFXIVClientStructs.FFXIV.Client.UI.UIGlobals.PlayChatSoundEffect(_configService.Current.CustomWarningSoundId);
|
||||||
|
await Task.Delay(800);
|
||||||
|
FFXIVClientStructs.FFXIV.Client.UI.UIGlobals.PlayChatSoundEffect(_configService.Current.CustomErrorSoundId);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Failed to play test sounds");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Play all custom sounds in sequence: Info → Warning → Error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
@@ -204,19 +204,19 @@ public class TopTabMenu
|
|||||||
"debug-user-id",
|
"debug-user-id",
|
||||||
onAccept: () =>
|
onAccept: () =>
|
||||||
{
|
{
|
||||||
_lightlessNotificationService.ShowNotification(
|
_lightlessMediator.Publish(new NotificationMessage(
|
||||||
"Pair Accepted",
|
"Pair Accepted",
|
||||||
"Debug pair request was accepted!",
|
"Debug pair request was accepted!",
|
||||||
NotificationType.Info,
|
NotificationType.Info,
|
||||||
TimeSpan.FromSeconds(3));
|
TimeSpan.FromSeconds(3)));
|
||||||
},
|
},
|
||||||
onDecline: () =>
|
onDecline: () =>
|
||||||
{
|
{
|
||||||
_lightlessNotificationService.ShowNotification(
|
_lightlessMediator.Publish(new NotificationMessage(
|
||||||
"Pair Declined",
|
"Pair Declined",
|
||||||
"Debug pair request was declined.",
|
"Debug pair request was declined.",
|
||||||
NotificationType.Warning,
|
NotificationType.Warning,
|
||||||
TimeSpan.FromSeconds(3));
|
TimeSpan.FromSeconds(3)));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -224,31 +224,31 @@ public class TopTabMenu
|
|||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if (ImGui.Button("Test Info"))
|
if (ImGui.Button("Test Info"))
|
||||||
{
|
{
|
||||||
_lightlessNotificationService.ShowNotification(
|
_lightlessMediator.Publish(new NotificationMessage(
|
||||||
"Information",
|
"Information",
|
||||||
"This is a test ifno notification with some longer text to see how it wraps. This is a test ifno notification with some longer text to see how it wraps. This is a test ifno notification with some longer text to see how it wraps. This is a test ifno notification with some longer text to see how it wraps.",
|
"This is a test ifno notification with some longer text to see how it wraps. This is a test ifno notification with some longer text to see how it wraps. This is a test ifno notification with some longer text to see how it wraps. This is a test ifno notification with some longer text to see how it wraps.",
|
||||||
NotificationType.Info,
|
NotificationType.Info,
|
||||||
TimeSpan.FromSeconds(5));
|
TimeSpan.FromSeconds(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if (ImGui.Button("Test Warning"))
|
if (ImGui.Button("Test Warning"))
|
||||||
{
|
{
|
||||||
_lightlessNotificationService.ShowNotification(
|
_lightlessMediator.Publish(new NotificationMessage(
|
||||||
"Warning",
|
"Warning",
|
||||||
"This is a test warning notification.",
|
"This is a test warning notification.",
|
||||||
NotificationType.Warning,
|
NotificationType.Warning,
|
||||||
TimeSpan.FromSeconds(7));
|
TimeSpan.FromSeconds(7)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if (ImGui.Button("Test Error"))
|
if (ImGui.Button("Test Error"))
|
||||||
{
|
{
|
||||||
_lightlessNotificationService.ShowNotification(
|
_lightlessMediator.Publish(new NotificationMessage(
|
||||||
"Error",
|
"Error",
|
||||||
"This is a test error notification erp police",
|
"This is a test error notification erp police",
|
||||||
NotificationType.Error,
|
NotificationType.Error,
|
||||||
TimeSpan.FromSeconds(10));
|
TimeSpan.FromSeconds(10)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.Button("Test Download Progress"))
|
if (ImGui.Button("Test Download Progress"))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using LightlessSync.API.Data;
|
using LightlessSync.API.Data;
|
||||||
using LightlessSync.API.Data.Enum;
|
using LightlessSync.API.Data.Enum;
|
||||||
using LightlessSync.API.Dto;
|
using LightlessSync.API.Dto;
|
||||||
using LightlessSync.API.Dto.CharaData;
|
using LightlessSync.API.Dto.CharaData;
|
||||||
@@ -122,36 +122,38 @@ public partial class ApiController
|
|||||||
// Fire and forget async operation
|
// Fire and forget async operation
|
||||||
_ = Task.Run(async () =>
|
_ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var myCidHash = (await _dalamudUtil.GetCIDAsync().ConfigureAwait(false)).ToString().GetHash256();
|
var myCidHash = (await _dalamudUtil.GetCIDAsync().ConfigureAwait(false)).ToString().GetHash256();
|
||||||
|
try
|
||||||
|
{
|
||||||
await TryPairWithContentId(request.HashedCid, myCidHash).ConfigureAwait(false);
|
await TryPairWithContentId(request.HashedCid, myCidHash).ConfigureAwait(false);
|
||||||
_pairRequestService.RemoveRequest(request.HashedCid);
|
_pairRequestService.RemoveRequest(request.HashedCid);
|
||||||
|
|
||||||
_lightlessNotificationService.ShowNotification(
|
Mediator.Publish(new NotificationMessage(
|
||||||
"Pair Request Accepted",
|
"Pair Request Accepted",
|
||||||
$"Sent a pair request back to {senderName}.",
|
$"Sent a pair request back to {senderName}.",
|
||||||
NotificationType.Info,
|
NotificationType.Info,
|
||||||
TimeSpan.FromSeconds(3));
|
TimeSpan.FromSeconds(3)));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_lightlessNotificationService.ShowNotification(
|
Mediator.Publish(new NotificationMessage(
|
||||||
"Failed to Accept Pair Request",
|
"Failed to Accept Pair Request",
|
||||||
ex.Message,
|
ex.Message,
|
||||||
NotificationType.Error,
|
NotificationType.Error,
|
||||||
TimeSpan.FromSeconds(5));
|
TimeSpan.FromSeconds(5)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onDecline: () =>
|
onDecline: () =>
|
||||||
{
|
{
|
||||||
_pairRequestService.RemoveRequest(request.HashedCid);
|
_pairRequestService.RemoveRequest(request.HashedCid);
|
||||||
_lightlessNotificationService.ShowNotification(
|
Mediator.Publish(new NotificationMessage(
|
||||||
"Pair Request Declined",
|
"Pair Request Declined",
|
||||||
$"Declined {senderName}'s pair request.",
|
$"Declined {senderName}'s pair request.",
|
||||||
NotificationType.Info,
|
NotificationType.Info,
|
||||||
TimeSpan.FromSeconds(3));
|
TimeSpan.FromSeconds(3)));
|
||||||
});
|
});
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|||||||
Reference in New Issue
Block a user