2.0.0 (#92)
All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m27s

2.0.0 Changes:

- Reworked shell finder UI with compact or list view with profile tags showing with the listing, allowing moderators to broadcast the syncshell as well to have it be used more.
- Reworked user list in syncshell admin screen to have filter visible and moved away from table to its own thing, allowing to copy uid/note/alias when clicking on the name.
- Reworked download bars and download box to make it look more modern, removed the jitter around, so it shouldn't vibrate around much.
- Chat has been added to the top menu, working in Zone or in Syncshells to be used there.
- Paired system has been revamped to make pausing and unpausing faster, and loading people should be faster as well.
- Moved to the internal object table to have faster load times for users; people should load in faster
- Compactor is running on a multi-threaded level instead of single-threaded; this should increase the speed of compacting files
- Nameplate Service has been reworked so it wouldn't use the nameplate handler anymore.
- Files can be resized when downloading to reduce load on users if they aren't compressed. (can be toggled to resize all).
- Penumbra Collections are now only made when people are visible, reducing the load on boot-up when having many syncshells in your list.
- Lightfinder plates have been moved away from using Nameplates, but will use an overlay.
- Main UI has been changed a bit with a gradient, and on hover will glow up now.
- Reworked Profile UI for Syncshell and Users to be more user-facing with more customizable items.
- Reworked Settings UI to look more modern.
- Performance should be better due to new systems that would dispose of the collections and better caching of items.

Co-authored-by: defnotken <itsdefnotken@gmail.com>
Co-authored-by: azyges <aaaaaa@aaa.aaa>
Co-authored-by: choco <choco@patat.nl>
Co-authored-by: cake <admin@cakeandbanana.nl>
Co-authored-by: Minmoose <KennethBohr@outlook.com>
Reviewed-on: #92
This commit was merged in pull request #92.
This commit is contained in:
2025-12-21 17:19:34 +00:00
parent 906f401940
commit 835a0a637d
191 changed files with 32636 additions and 8841 deletions

View File

@@ -4,9 +4,14 @@ using Dalamud.Interface.ImGuiNotification;
using Dalamud.Plugin.Services;
using LightlessSync.LightlessConfiguration;
using LightlessSync.LightlessConfiguration.Models;
using LightlessSync;
using LightlessSync.PlayerData.Factories;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.Services.Mediator;
using LightlessSync.UI;
using LightlessSync.UI.Models;
using LightlessSync.UI.Services;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using FFXIVClientStructs.FFXIV.Client.UI;
@@ -23,7 +28,9 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
private readonly INotificationManager _notificationManager;
private readonly IChatGui _chatGui;
private readonly PairRequestService _pairRequestService;
private readonly HashSet<string> _shownPairRequestNotifications = new();
private readonly HashSet<string> _shownPairRequestNotifications = [];
private readonly PairUiService _pairUiService;
private readonly PairFactory _pairFactory;
public NotificationService(
ILogger<NotificationService> logger,
@@ -32,7 +39,9 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
INotificationManager notificationManager,
IChatGui chatGui,
LightlessMediator mediator,
PairRequestService pairRequestService) : base(logger, mediator)
PairRequestService pairRequestService,
PairUiService pairUiService,
PairFactory pairFactory) : base(logger, mediator)
{
_logger = logger;
_configService = configService;
@@ -40,6 +49,8 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
_notificationManager = notificationManager;
_chatGui = chatGui;
_pairRequestService = pairRequestService;
_pairUiService = pairUiService;
_pairFactory = pairFactory;
}
public Task StartAsync(CancellationToken cancellationToken)
@@ -59,7 +70,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
{
var notification = CreateNotification(title, message, type, duration, actions, soundEffectId);
if (_configService.Current.AutoDismissOnAction && notification.Actions.Any())
if (_configService.Current.AutoDismissOnAction && notification.Actions.Count != 0)
{
WrapActionsWithAutoDismiss(notification);
}
@@ -104,7 +115,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
}
}
private void DismissNotification(LightlessNotification notification)
private static void DismissNotification(LightlessNotification notification)
{
notification.IsDismissed = true;
notification.IsAnimatingOut = true;
@@ -208,10 +219,12 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
Mediator.Publish(new LightlessNotificationMessage(notification));
}
private string FormatDownloadCompleteMessage(string fileName, int fileCount) =>
fileCount > 1
private static string FormatDownloadCompleteMessage(string fileName, int fileCount)
{
return fileCount > 1
? $"Downloaded {fileCount} files successfully."
: $"Downloaded {fileName} successfully.";
}
private List<LightlessNotificationAction> CreateDownloadCompleteActions(Action? onOpenFolder)
{
@@ -257,8 +270,10 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
Mediator.Publish(new LightlessNotificationMessage(notification));
}
private string FormatErrorMessage(string message, Exception? exception) =>
exception != null ? $"{message}\n\nError: {exception.Message}" : message;
private static string FormatErrorMessage(string message, Exception? exception)
{
return exception != null ? $"{message}\n\nError: {exception.Message}" : message;
}
private List<LightlessNotificationAction> CreateErrorActions(Action? onRetry, Action? onViewLog)
{
@@ -332,8 +347,9 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
return string.Join("\n", activeDownloads.Select(x => $"• {x.PlayerName}: {FormatDownloadStatus(x)}"));
}
private string FormatDownloadStatus((string PlayerName, float Progress, string Status) download) =>
download.Status switch
private static string FormatDownloadStatus((string PlayerName, float Progress, string Status) download)
{
return download.Status switch
{
"downloading" => $"{download.Progress:P0}",
"decompressing" => "decompressing",
@@ -341,6 +357,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
"waiting" => "waiting for slot",
_ => download.Status
};
}
private TimeSpan GetDefaultDurationForType(NotificationType type) => type switch
{
@@ -391,6 +408,17 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
_logger.LogWarning(ex, "Failed to play notification sound effect {SoundId}", soundEffectId);
}
}
private Pair? ResolvePair(UserData userData)
{
var snapshot = _pairUiService.GetSnapshot();
if (snapshot.PairsByUid.TryGetValue(userData.UID, out var pair))
{
return pair;
}
var ident = new PairUniqueIdentifier(userData.UID);
return _pairFactory.Create(ident);
}
private void HandleNotificationMessage(NotificationMessage msg)
{
@@ -478,13 +506,16 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
});
}
private Dalamud.Interface.ImGuiNotification.NotificationType
ConvertToDalamudNotificationType(NotificationType type) => type switch
private static Dalamud.Interface.ImGuiNotification.NotificationType
ConvertToDalamudNotificationType(NotificationType type)
{
NotificationType.Error => Dalamud.Interface.ImGuiNotification.NotificationType.Error,
NotificationType.Warning => Dalamud.Interface.ImGuiNotification.NotificationType.Warning,
_ => Dalamud.Interface.ImGuiNotification.NotificationType.Info
};
return type switch
{
NotificationType.Error => Dalamud.Interface.ImGuiNotification.NotificationType.Error,
NotificationType.Warning => Dalamud.Interface.ImGuiNotification.NotificationType.Warning,
_ => Dalamud.Interface.ImGuiNotification.NotificationType.Info
};
}
private void ShowChat(NotificationMessage msg)
{
@@ -568,7 +599,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
private void HandlePairRequestsUpdated(PairRequestsUpdatedMessage _)
{
var activeRequests = _pairRequestService.GetActiveRequests();
var activeRequestIds = activeRequests.Select(r => r.HashedCid).ToHashSet();
var activeRequestIds = activeRequests.Select(r => r.HashedCid).ToHashSet(StringComparer.Ordinal);
// Dismiss notifications for requests that are no longer active (expired)
var notificationsToRemove = _shownPairRequestNotifications
@@ -585,7 +616,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
private void HandlePairDownloadStatus(PairDownloadStatusMessage msg)
{
var userDownloads = msg.DownloadStatus.Where(x => x.PlayerName != "Pair Queue").ToList();
var userDownloads = msg.DownloadStatus.Where(x => !string.Equals(x.PlayerName, "Pair Queue", StringComparison.Ordinal)).ToList();
var totalProgress = userDownloads.Count > 0 ? userDownloads.Average(x => x.Progress) : 0f;
var message = BuildPairDownloadMessage(userDownloads, msg.QueueWaiting);
@@ -659,7 +690,14 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
{
try
{
Mediator.Publish(new CyclePauseMessage(userData));
var pair = ResolvePair(userData);
if (pair == null)
{
_logger.LogWarning("Cannot cycle pause {uid} because pair is missing", userData.UID);
throw new InvalidOperationException("Pair not available");
}
Mediator.Publish(new CyclePauseMessage(pair));
DismissNotification(notification);
var displayName = GetUserDisplayName(userData, playerName);
@@ -734,7 +772,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
return actions;
}
private string GetUserDisplayName(UserData userData, string playerName)
private static string GetUserDisplayName(UserData userData, string playerName)
{
if (!string.IsNullOrEmpty(userData.Alias) && !string.Equals(userData.Alias, userData.UID, StringComparison.Ordinal))
{