From a9181d2592782292265398a99d612a48681176cf Mon Sep 17 00:00:00 2001 From: cake Date: Sun, 30 Nov 2025 08:09:58 +0100 Subject: [PATCH] Removed obselete functions, changed download bars a bit. renamed files correctly --- LightlessSync/FileCache/FileCacheManager.cs | 3 +- .../Factories/FileDownloadManagerFactory.cs | 2 +- .../PlayerData/Pairs/PairHandlerAdapter.cs | 1 + LightlessSync/Plugin.cs | 22 +- LightlessSync/Services/CharacterAnalyzer.cs | 2 +- .../Services/CommandManagerService.cs | 2 +- LightlessSync/Services/ContextMenuService.cs | 9 +- LightlessSync/Services/DalamudUtilService.cs | 24 +- .../LightFinderScannerService.cs} | 12 +- .../LightFinderService.cs} | 18 +- LightlessSync/Services/NameplateHandler.cs | 8 +- LightlessSync/Services/NotificationService.cs | 2 +- .../PairProcessingLimiter.cs | 3 +- .../Services/PlayerPerformanceService.cs | 3 - .../{ => Profiles}/LightlessProfileData.cs | 0 .../{ => Profiles}/LightlessProfileManager.cs | 8 + LightlessSync/UI/CompactUI.cs | 17 +- LightlessSync/UI/DownloadUi.cs | 378 ++++++++++++------ LightlessSync/UI/DtrEntry.cs | 9 +- .../UI/{BroadcastUI.cs => LightFinderUI.cs} | 15 +- LightlessSync/UI/SettingsUi.cs | 1 + LightlessSync/UI/SyncshellFinderUI.cs | 11 +- LightlessSync/UI/TopTabMenu.cs | 2 +- .../WebAPI/Files/FileDownloadManager.cs | 2 +- 24 files changed, 357 insertions(+), 197 deletions(-) rename LightlessSync/Services/{BroadcastScannerService.cs => LightFinder/LightFinderScannerService.cs} (95%) rename LightlessSync/Services/{BroadcastService.cs => LightFinder/LightFinderService.cs} (96%) rename LightlessSync/Services/{ => PairProcessing}/PairProcessingLimiter.cs (98%) rename LightlessSync/Services/{ => Profiles}/LightlessProfileData.cs (100%) rename LightlessSync/Services/{ => Profiles}/LightlessProfileManager.cs (99%) rename LightlessSync/UI/{BroadcastUI.cs => LightFinderUI.cs} (97%) diff --git a/LightlessSync/FileCache/FileCacheManager.cs b/LightlessSync/FileCache/FileCacheManager.cs index ff45c6a..e8b0cb8 100644 --- a/LightlessSync/FileCache/FileCacheManager.cs +++ b/LightlessSync/FileCache/FileCacheManager.cs @@ -636,8 +636,7 @@ public sealed class FileCacheManager : IHostedService private FileCacheEntity? CreateFileCacheEntity(FileInfo fileInfo, string prefixedPath, string? hash = null) { - var algo = Crypto.DetectAlgo(Path.GetFileNameWithoutExtension(fileInfo.Name)); - hash ??= Crypto.ComputeFileHash(fileInfo.FullName, algo); + hash ??= Crypto.ComputeFileHash(fileInfo.FullName, Crypto.HashAlgo.Sha1); var entity = new FileCacheEntity(hash, prefixedPath, fileInfo.LastWriteTimeUtc.Ticks.ToString(CultureInfo.InvariantCulture), fileInfo.Length); entity = ReplacePathPrefixes(entity); AddHashedFile(entity); diff --git a/LightlessSync/PlayerData/Factories/FileDownloadManagerFactory.cs b/LightlessSync/PlayerData/Factories/FileDownloadManagerFactory.cs index 81e3ecb..f9b522a 100644 --- a/LightlessSync/PlayerData/Factories/FileDownloadManagerFactory.cs +++ b/LightlessSync/PlayerData/Factories/FileDownloadManagerFactory.cs @@ -1,7 +1,7 @@ using LightlessSync.FileCache; using LightlessSync.LightlessConfiguration; -using LightlessSync.Services; using LightlessSync.Services.Mediator; +using LightlessSync.Services.PairProcessing; using LightlessSync.Services.TextureCompression; using LightlessSync.WebAPI.Files; using Microsoft.Extensions.Logging; diff --git a/LightlessSync/PlayerData/Pairs/PairHandlerAdapter.cs b/LightlessSync/PlayerData/Pairs/PairHandlerAdapter.cs index ad77bcb..c63bf31 100644 --- a/LightlessSync/PlayerData/Pairs/PairHandlerAdapter.cs +++ b/LightlessSync/PlayerData/Pairs/PairHandlerAdapter.cs @@ -10,6 +10,7 @@ using LightlessSync.PlayerData.Handlers; using LightlessSync.Services; using LightlessSync.Services.Events; using LightlessSync.Services.Mediator; +using LightlessSync.Services.PairProcessing; using LightlessSync.Services.ServerConfiguration; using LightlessSync.Services.TextureCompression; using LightlessSync.Utils; diff --git a/LightlessSync/Plugin.cs b/LightlessSync/Plugin.cs index 6e68f77..41d8569 100644 --- a/LightlessSync/Plugin.cs +++ b/LightlessSync/Plugin.cs @@ -38,6 +38,8 @@ using System.IO; using System.Net.Http.Headers; using System.Reflection; using OtterTex; +using LightlessSync.Services.LightFinder; +using LightlessSync.Services.PairProcessing; namespace LightlessSync; @@ -189,8 +191,8 @@ public sealed class Plugin : IDalamudPlugin s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), - s.GetRequiredService(), - s.GetRequiredService(), + s.GetRequiredService(), + s.GetRequiredService(), s.GetRequiredService())); collection.AddSingleton(s => new PairCoordinator( s.GetRequiredService>(), @@ -201,15 +203,15 @@ public sealed class Plugin : IDalamudPlugin s.GetRequiredService(), s.GetRequiredService())); collection.AddSingleton(); - collection.AddSingleton(); + collection.AddSingleton(); collection.AddSingleton(addonLifecycle); collection.AddSingleton(p => new ContextMenuService(contextMenu, pluginInterface, gameData, p.GetRequiredService>(), p.GetRequiredService(), p.GetRequiredService(), objectTable, p.GetRequiredService(), p.GetRequiredService(), p.GetRequiredService(), clientState, - p.GetRequiredService(), - p.GetRequiredService(), + p.GetRequiredService(), + p.GetRequiredService(), p.GetRequiredService(), p.GetRequiredService())); collection.AddSingleton((s) => new IpcCallerPenumbra(s.GetRequiredService>(), pluginInterface, @@ -288,7 +290,7 @@ public sealed class Plugin : IDalamudPlugin clientState, sp.GetRequiredService())); collection.AddSingleton(); - collection.AddSingleton(s => new BroadcastScannerService(s.GetRequiredService>(), framework, s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); + collection.AddSingleton(s => new LightFinderScannerService(s.GetRequiredService>(), framework, s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); // add scoped services @@ -314,8 +316,8 @@ public sealed class Plugin : IDalamudPlugin s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); collection.AddScoped(); - collection.AddScoped((s) => new BroadcastUI(s.GetRequiredService>(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); - collection.AddScoped((s) => new SyncshellFinderUI(s.GetRequiredService>(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); + collection.AddScoped((s) => new LightFinderUI(s.GetRequiredService>(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); + collection.AddScoped((s) => new SyncshellFinderUI(s.GetRequiredService>(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); collection.AddScoped(); collection.AddScoped((s) => new LightlessNotificationUi( @@ -343,7 +345,7 @@ public sealed class Plugin : IDalamudPlugin collection.AddScoped((s) => new NameplateService(s.GetRequiredService>(), s.GetRequiredService(), clientState, gameGui, objectTable, gameInteropProvider, s.GetRequiredService(),s.GetRequiredService())); collection.AddScoped((s) => new NameplateHandler(s.GetRequiredService>(), addonLifecycle, gameGui, - s.GetRequiredService(), s.GetRequiredService(), clientState, s.GetRequiredService())); + s.GetRequiredService(), s.GetRequiredService(), objectTable, s.GetRequiredService())); collection.AddHostedService(p => p.GetRequiredService()); collection.AddHostedService(p => p.GetRequiredService()); @@ -359,7 +361,7 @@ public sealed class Plugin : IDalamudPlugin collection.AddHostedService(p => p.GetRequiredService()); collection.AddHostedService(p => p.GetRequiredService()); collection.AddHostedService(p => p.GetRequiredService()); - collection.AddHostedService(p => p.GetRequiredService()); + collection.AddHostedService(p => p.GetRequiredService()); }) .Build(); diff --git a/LightlessSync/Services/CharacterAnalyzer.cs b/LightlessSync/Services/CharacterAnalyzer.cs index a56b6e3..2a0aa04 100644 --- a/LightlessSync/Services/CharacterAnalyzer.cs +++ b/LightlessSync/Services/CharacterAnalyzer.cs @@ -116,7 +116,7 @@ public sealed class CharacterAnalyzer : MediatorSubscriberBase, IDisposable { foreach (var entry in objectEntries.Values) { - if (!entry.FilePaths.Any(path => normalized.Contains(path))) + if (!entry.FilePaths.Exists(path => normalized.Contains(path))) { continue; } diff --git a/LightlessSync/Services/CommandManagerService.cs b/LightlessSync/Services/CommandManagerService.cs index 88f8780..51c57f9 100644 --- a/LightlessSync/Services/CommandManagerService.cs +++ b/LightlessSync/Services/CommandManagerService.cs @@ -131,7 +131,7 @@ public sealed class CommandManagerService : IDisposable } else if (string.Equals(splitArgs[0], "finder", StringComparison.OrdinalIgnoreCase)) { - _mediator.Publish(new UiToggleMessage(typeof(BroadcastUI))); + _mediator.Publish(new UiToggleMessage(typeof(LightFinderUI))); } } } \ No newline at end of file diff --git a/LightlessSync/Services/ContextMenuService.cs b/LightlessSync/Services/ContextMenuService.cs index 78e34a8..740f52b 100644 --- a/LightlessSync/Services/ContextMenuService.cs +++ b/LightlessSync/Services/ContextMenuService.cs @@ -12,6 +12,7 @@ using LightlessSync.UI.Services; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using LightlessSync.UI; +using LightlessSync.Services.LightFinder; namespace LightlessSync.Services; @@ -28,8 +29,8 @@ internal class ContextMenuService : IHostedService private readonly ApiController _apiController; private readonly IObjectTable _objectTable; private readonly LightlessConfigService _configService; - private readonly BroadcastScannerService _broadcastScannerService; - private readonly BroadcastService _broadcastService; + private readonly LightFinderScannerService _broadcastScannerService; + private readonly LightFinderService _broadcastService; private readonly LightlessProfileManager _lightlessProfileManager; private readonly LightlessMediator _mediator; @@ -47,8 +48,8 @@ internal class ContextMenuService : IHostedService PairRequestService pairRequestService, PairUiService pairUiService, IClientState clientState, - BroadcastScannerService broadcastScannerService, - BroadcastService broadcastService, + LightFinderScannerService broadcastScannerService, + LightFinderService broadcastService, LightlessProfileManager lightlessProfileManager, LightlessMediator mediator) { diff --git a/LightlessSync/Services/DalamudUtilService.cs b/LightlessSync/Services/DalamudUtilService.cs index 66045a1..3a2cb94 100644 --- a/LightlessSync/Services/DalamudUtilService.cs +++ b/LightlessSync/Services/DalamudUtilService.cs @@ -14,14 +14,12 @@ using LightlessSync.Interop; using LightlessSync.LightlessConfiguration; using LightlessSync.PlayerData.Factories; using LightlessSync.PlayerData.Handlers; -using LightlessSync.PlayerData.Pairs; using LightlessSync.Services.ActorTracking; using LightlessSync.Services.Mediator; using LightlessSync.Utils; using Lumina.Excel.Sheets; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; using System.Text; @@ -249,7 +247,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber public bool GetIsPlayerPresent() { EnsureIsOnFramework(); - return _clientState.LocalPlayer != null && _clientState.LocalPlayer.IsValid(); + return _objectTable.LocalPlayer != null && _objectTable.LocalPlayer.IsValid(); } public async Task GetIsPlayerPresentAsync() @@ -293,7 +291,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber public IPlayerCharacter GetPlayerCharacter() { EnsureIsOnFramework(); - return _clientState.LocalPlayer!; + return _objectTable.LocalPlayer!; } public IntPtr GetPlayerCharacterFromCachedTableByIdent(string characterName) @@ -306,7 +304,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber public string GetPlayerName() { EnsureIsOnFramework(); - return _clientState.LocalPlayer?.Name.ToString() ?? "--"; + return _objectTable.LocalPlayer?.Name.ToString() ?? "--"; } public async Task GetPlayerNameAsync() @@ -339,7 +337,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber public IntPtr GetPlayerPtr() { EnsureIsOnFramework(); - return _clientState.LocalPlayer?.Address ?? IntPtr.Zero; + return _objectTable.LocalPlayer?.Address ?? IntPtr.Zero; } public async Task GetPlayerPointerAsync() @@ -350,13 +348,13 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber public uint GetHomeWorldId() { EnsureIsOnFramework(); - return _clientState.LocalPlayer?.HomeWorld.RowId ?? 0; + return _objectTable.LocalPlayer?.HomeWorld.RowId ?? 0; } public uint GetWorldId() { EnsureIsOnFramework(); - return _clientState.LocalPlayer!.CurrentWorld.RowId; + return _objectTable.LocalPlayer!.CurrentWorld.RowId; } public unsafe LocationInfo GetMapData() @@ -365,8 +363,8 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber var agentMap = AgentMap.Instance(); var houseMan = HousingManager.Instance(); uint serverId = 0; - if (_clientState.LocalPlayer == null) serverId = 0; - else serverId = _clientState.LocalPlayer.CurrentWorld.RowId; + if (_objectTable.LocalPlayer == null) serverId = 0; + else serverId = _objectTable.LocalPlayer.CurrentWorld.RowId; uint mapId = agentMap == null ? 0 : agentMap->CurrentMapId; uint territoryId = agentMap == null ? 0 : agentMap->CurrentTerritoryId; uint divisionId = houseMan == null ? 0 : (uint)(houseMan->GetCurrentDivision()); @@ -494,7 +492,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber _framework.Update += FrameworkOnUpdate; if (IsLoggedIn) { - _classJobId = _clientState.LocalPlayer!.ClassJob.RowId; + _classJobId = _objectTable.LocalPlayer!.ClassJob.RowId; } _logger.LogInformation("Started DalamudUtilService"); @@ -647,7 +645,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber private unsafe void FrameworkOnUpdateInternal() { - if ((_clientState.LocalPlayer?.IsDead ?? false) && _condition[ConditionFlag.BoundByDuty]) + if ((_objectTable.LocalPlayer?.IsDead ?? false) && _condition[ConditionFlag.BoundByDuty]) { return; } @@ -805,7 +803,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber Mediator.Publish(new ResumeScanMessage(nameof(ConditionFlag.BetweenAreas))); } - var localPlayer = _clientState.LocalPlayer; + var localPlayer = _objectTable.LocalPlayer; if (localPlayer != null) { _classJobId = localPlayer.ClassJob.RowId; diff --git a/LightlessSync/Services/BroadcastScannerService.cs b/LightlessSync/Services/LightFinder/LightFinderScannerService.cs similarity index 95% rename from LightlessSync/Services/BroadcastScannerService.cs rename to LightlessSync/Services/LightFinder/LightFinderScannerService.cs index 96576d1..a0ea3e6 100644 --- a/LightlessSync/Services/BroadcastScannerService.cs +++ b/LightlessSync/Services/LightFinder/LightFinderScannerService.cs @@ -5,15 +5,15 @@ using LightlessSync.Services.Mediator; using Microsoft.Extensions.Logging; using System.Collections.Concurrent; -namespace LightlessSync.Services; +namespace LightlessSync.Services.LightFinder; -public class BroadcastScannerService : DisposableMediatorSubscriberBase +public class LightFinderScannerService : DisposableMediatorSubscriberBase { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ActorObjectService _actorTracker; private readonly IFramework _framework; - private readonly BroadcastService _broadcastService; + private readonly LightFinderService _broadcastService; private readonly NameplateHandler _nameplateHandler; private readonly ConcurrentDictionary _broadcastCache = new(StringComparer.Ordinal); @@ -37,9 +37,9 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase public IReadOnlyDictionary BroadcastCache => _broadcastCache; public readonly record struct BroadcastEntry(bool IsBroadcasting, DateTime ExpiryTime, string? GID); - public BroadcastScannerService(ILogger logger, + public LightFinderScannerService(ILogger logger, IFramework framework, - BroadcastService broadcastService, + LightFinderService broadcastService, LightlessMediator mediator, NameplateHandler nameplateHandler, ActorObjectService actorTracker) : base(logger, mediator) diff --git a/LightlessSync/Services/BroadcastService.cs b/LightlessSync/Services/LightFinder/LightFinderService.cs similarity index 96% rename from LightlessSync/Services/BroadcastService.cs rename to LightlessSync/Services/LightFinder/LightFinderService.cs index bc32c9c..82a51c7 100644 --- a/LightlessSync/Services/BroadcastService.cs +++ b/LightlessSync/Services/LightFinder/LightFinderService.cs @@ -1,21 +1,21 @@ using Dalamud.Interface; -using LightlessSync.LightlessConfiguration.Models; -using LightlessSync.UI; -using LightlessSync.UI.Models; using LightlessSync.API.Dto.Group; using LightlessSync.API.Dto.User; using LightlessSync.LightlessConfiguration; +using LightlessSync.LightlessConfiguration.Models; using LightlessSync.Services.Mediator; +using LightlessSync.UI; +using LightlessSync.UI.Models; using LightlessSync.Utils; using LightlessSync.WebAPI; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -namespace LightlessSync.Services; -public class BroadcastService : IHostedService, IMediatorSubscriber +namespace LightlessSync.Services.LightFinder; +public class LightFinderService : IHostedService, IMediatorSubscriber { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ApiController _apiController; private readonly LightlessMediator _mediator; private readonly LightlessConfigService _config; @@ -44,7 +44,7 @@ public class BroadcastService : IHostedService, IMediatorSubscriber } } - public BroadcastService(ILogger logger, LightlessMediator mediator, LightlessConfigService config, DalamudUtilService dalamudUtil, ApiController apiController) + public LightFinderService(ILogger logger, LightlessMediator mediator, LightlessConfigService config, DalamudUtilService dalamudUtil, ApiController apiController) { _logger = logger; _mediator = mediator; @@ -281,7 +281,7 @@ public class BroadcastService : IHostedService, IMediatorSubscriber if (!msg.Enabled) { ApplyBroadcastDisabled(forcePublish: true); - Mediator.Publish(new EventMessage(new Services.Events.Event(nameof(BroadcastService), Services.Events.EventSeverity.Informational, $"Disabled Lightfinder for Player: {msg.HashedCid}"))); + Mediator.Publish(new EventMessage(new Events.Event(nameof(LightFinderService), Services.Events.EventSeverity.Informational, $"Disabled Lightfinder for Player: {msg.HashedCid}"))); return; } @@ -294,7 +294,7 @@ public class BroadcastService : IHostedService, IMediatorSubscriber if (TryApplyBroadcastEnabled(ttl, "client request")) { _logger.LogDebug("Fetched TTL from server: {TTL}", ttl); - Mediator.Publish(new EventMessage(new Services.Events.Event(nameof(BroadcastService), Services.Events.EventSeverity.Informational, $"Enabled Lightfinder for Player: {msg.HashedCid}"))); + Mediator.Publish(new EventMessage(new Events.Event(nameof(LightFinderService), Services.Events.EventSeverity.Informational, $"Enabled Lightfinder for Player: {msg.HashedCid}"))); } else { diff --git a/LightlessSync/Services/NameplateHandler.cs b/LightlessSync/Services/NameplateHandler.cs index f117da9..808242d 100644 --- a/LightlessSync/Services/NameplateHandler.cs +++ b/LightlessSync/Services/NameplateHandler.cs @@ -26,7 +26,7 @@ public unsafe class NameplateHandler : IMediatorSubscriber private readonly ILogger _logger; private readonly IAddonLifecycle _addonLifecycle; private readonly IGameGui _gameGui; - private readonly IClientState _clientState; + private readonly IObjectTable _objectTable; private readonly LightlessConfigService _configService; private readonly PairUiService _pairUiService; private readonly LightlessMediator _mediator; @@ -48,14 +48,14 @@ public unsafe class NameplateHandler : IMediatorSubscriber private ImmutableHashSet _activeBroadcastingCids = []; - public NameplateHandler(ILogger logger, IAddonLifecycle addonLifecycle, IGameGui gameGui, LightlessConfigService configService, LightlessMediator mediator, IClientState clientState, PairUiService pairUiService) + public NameplateHandler(ILogger logger, IAddonLifecycle addonLifecycle, IGameGui gameGui, LightlessConfigService configService, LightlessMediator mediator, IObjectTable objectTable, PairUiService pairUiService) { _logger = logger; _addonLifecycle = addonLifecycle; _gameGui = gameGui; _configService = configService; _mediator = mediator; - _clientState = clientState; + _objectTable = objectTable; _pairUiService = pairUiService; System.Array.Fill(_cachedNameplateTextOffsets, int.MinValue); @@ -323,7 +323,7 @@ public unsafe class NameplateHandler : IMediatorSubscriber continue; } - var local = _clientState.LocalPlayer; + var local = _objectTable.LocalPlayer; if (!config.LightfinderLabelShowOwn && local != null && objectInfo->GameObject->GetGameObjectId() == local.GameObjectId) { diff --git a/LightlessSync/Services/NotificationService.cs b/LightlessSync/Services/NotificationService.cs index 02b5b05..cedb58b 100644 --- a/LightlessSync/Services/NotificationService.cs +++ b/LightlessSync/Services/NotificationService.cs @@ -28,7 +28,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ private readonly INotificationManager _notificationManager; private readonly IChatGui _chatGui; private readonly PairRequestService _pairRequestService; - private readonly HashSet _shownPairRequestNotifications = new(); + private readonly HashSet _shownPairRequestNotifications = []; private readonly PairUiService _pairUiService; private readonly PairFactory _pairFactory; diff --git a/LightlessSync/Services/PairProcessingLimiter.cs b/LightlessSync/Services/PairProcessing/PairProcessingLimiter.cs similarity index 98% rename from LightlessSync/Services/PairProcessingLimiter.cs rename to LightlessSync/Services/PairProcessing/PairProcessingLimiter.cs index 35b6d1c..1a860d3 100644 --- a/LightlessSync/Services/PairProcessingLimiter.cs +++ b/LightlessSync/Services/PairProcessing/PairProcessingLimiter.cs @@ -1,9 +1,8 @@ using LightlessSync.LightlessConfiguration; using LightlessSync.Services.Mediator; -using LightlessSync.Services.PairProcessing; using Microsoft.Extensions.Logging; -namespace LightlessSync.Services; +namespace LightlessSync.Services.PairProcessing; public sealed class PairProcessingLimiter : DisposableMediatorSubscriberBase { diff --git a/LightlessSync/Services/PlayerPerformanceService.cs b/LightlessSync/Services/PlayerPerformanceService.cs index 9382cf7..e77ccd7 100644 --- a/LightlessSync/Services/PlayerPerformanceService.cs +++ b/LightlessSync/Services/PlayerPerformanceService.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; using LightlessSync.API.Data; -using LightlessSync.API.Data.Extensions; using LightlessSync.FileCache; using LightlessSync.LightlessConfiguration; using LightlessSync.PlayerData.Pairs; diff --git a/LightlessSync/Services/LightlessProfileData.cs b/LightlessSync/Services/Profiles/LightlessProfileData.cs similarity index 100% rename from LightlessSync/Services/LightlessProfileData.cs rename to LightlessSync/Services/Profiles/LightlessProfileData.cs diff --git a/LightlessSync/Services/LightlessProfileManager.cs b/LightlessSync/Services/Profiles/LightlessProfileManager.cs similarity index 99% rename from LightlessSync/Services/LightlessProfileManager.cs rename to LightlessSync/Services/Profiles/LightlessProfileManager.cs index 7d60d66..2f854e8 100644 --- a/LightlessSync/Services/LightlessProfileManager.cs +++ b/LightlessSync/Services/Profiles/LightlessProfileManager.cs @@ -39,6 +39,7 @@ public class LightlessProfileManager : MediatorSubscriberBase Base64BannerPicture: _lightlessBanner, Description: _noUserDescription, Tags: _emptyTagSet); + private readonly LightlessUserProfileData _loadingProfileUserData = new( IsFlagged: false, IsNSFW: false, @@ -47,6 +48,7 @@ public class LightlessProfileManager : MediatorSubscriberBase Base64BannerPicture: _lightlessBanner, Description: _loadingData, Tags: _emptyTagSet); + private readonly LightlessGroupProfileData _loadingProfileGroupData = new( IsDisabled: false, IsNsfw: false, @@ -54,6 +56,7 @@ public class LightlessProfileManager : MediatorSubscriberBase Base64BannerPicture: _lightlessBanner, Description: _loadingData, Tags: _emptyTagSet); + private readonly LightlessGroupProfileData _defaultProfileGroupData = new( IsDisabled: false, IsNsfw: false, @@ -61,6 +64,7 @@ public class LightlessProfileManager : MediatorSubscriberBase Base64BannerPicture: _lightlessBanner, Description: _noGroupDescription, Tags: _emptyTagSet); + private readonly LightlessUserProfileData _nsfwProfileUserData = new( IsFlagged: false, IsNSFW: true, @@ -69,6 +73,7 @@ public class LightlessProfileManager : MediatorSubscriberBase Base64BannerPicture: string.Empty, Description: _nsfwDescription, Tags: _emptyTagSet); + private readonly LightlessGroupProfileData _nsfwProfileGroupData = new( IsDisabled: false, IsNsfw: true, @@ -76,6 +81,7 @@ public class LightlessProfileManager : MediatorSubscriberBase Base64BannerPicture: string.Empty, Description: _nsfwDescription, Tags: _emptyTagSet); + private const string _noDescription = "-- Profile has no description set --"; private readonly ConcurrentDictionary _lightlessProfiles = new(UserDataComparer.Instance); private readonly LightlessProfileData _defaultProfileData = new( @@ -86,6 +92,7 @@ public class LightlessProfileManager : MediatorSubscriberBase Base64BannerPicture: _lightlessBanner, Description: _noDescription, Tags: _emptyTagSet); + private readonly LightlessProfileData _loadingProfileData = new( IsFlagged: false, IsNSFW: false, @@ -94,6 +101,7 @@ public class LightlessProfileManager : MediatorSubscriberBase Base64BannerPicture: _lightlessBanner, Description: _loadingData, Tags: _emptyTagSet); + private readonly LightlessProfileData _nsfwProfileData = new( IsFlagged: false, IsNSFW: false, diff --git a/LightlessSync/UI/CompactUI.cs b/LightlessSync/UI/CompactUI.cs index 4c46fd4..d2715c9 100644 --- a/LightlessSync/UI/CompactUI.cs +++ b/LightlessSync/UI/CompactUI.cs @@ -9,6 +9,7 @@ using LightlessSync.LightlessConfiguration; using LightlessSync.PlayerData.Handlers; using LightlessSync.PlayerData.Pairs; using LightlessSync.Services; +using LightlessSync.Services.LightFinder; using LightlessSync.Services.Mediator; using LightlessSync.Services.ServerConfiguration; using LightlessSync.UI.Components; @@ -54,7 +55,7 @@ public class CompactUi : WindowMediatorSubscriberBase private readonly TopTabMenu _tabMenu; private readonly TagHandler _tagHandler; private readonly UiSharedService _uiSharedService; - private readonly BroadcastService _broadcastService; + private readonly LightFinderService _broadcastService; private List _drawFolders; private Pair? _lastAddedUser; @@ -66,7 +67,7 @@ public class CompactUi : WindowMediatorSubscriberBase private bool _wasOpen; private float _windowContentWidth; private readonly SeluneBrush _seluneBrush = new(); - private const float ConnectButtonHighlightThickness = 14f; + private const float _connectButtonHighlightThickness = 14f; public CompactUi( ILogger logger, @@ -87,7 +88,7 @@ public class CompactUi : WindowMediatorSubscriberBase RenameSyncshellTagUi renameSyncshellTagUi, PerformanceCollectorService performanceCollectorService, IpcManager ipcManager, - BroadcastService broadcastService, + LightFinderService broadcastService, CharacterAnalyzer characterAnalyzer, PlayerPerformanceConfigService playerPerformanceConfig, PairRequestService pairRequestService, DalamudUtilService dalamudUtilService, NotificationService lightlessNotificationService, PairLedger pairLedger) : base(logger, mediator, "###LightlessSyncMainUI", performanceCollectorService) { @@ -112,8 +113,8 @@ public class CompactUi : WindowMediatorSubscriberBase AllowPinning = true; AllowClickthrough = false; - TitleBarButtons = new() - { + TitleBarButtons = + [ new TitleBarButton() { Icon = FontAwesomeIcon.Cog, @@ -144,7 +145,7 @@ public class CompactUi : WindowMediatorSubscriberBase ImGui.EndTooltip(); } }, - }; + ]; _drawFolders = [.. DrawFolders]; @@ -406,7 +407,7 @@ public class CompactUi : WindowMediatorSubscriberBase ImGui.GetItemRectMax(), SeluneHighlightMode.Both, borderOnly: true, - borderThicknessOverride: ConnectButtonHighlightThickness, + borderThicknessOverride: _connectButtonHighlightThickness, exactSize: true, clipToElement: true, roundingOverride: ImGui.GetStyle().FrameRounding); @@ -634,7 +635,7 @@ public class CompactUi : WindowMediatorSubscriberBase } if (ImGui.IsItemClicked()) - _lightlessMediator.Publish(new UiToggleMessage(typeof(BroadcastUI))); + _lightlessMediator.Publish(new UiToggleMessage(typeof(LightFinderUI))); } ImGui.SetCursorPosY(cursorY); diff --git a/LightlessSync/UI/DownloadUi.cs b/LightlessSync/UI/DownloadUi.cs index 1902124..6d6d7dd 100644 --- a/LightlessSync/UI/DownloadUi.cs +++ b/LightlessSync/UI/DownloadUi.cs @@ -24,6 +24,15 @@ public class DownloadUi : WindowMediatorSubscriberBase private readonly PairProcessingLimiter _pairProcessingLimiter; private readonly ConcurrentDictionary _uploadingPlayers = new(); private readonly Dictionary _smoothed = []; + private readonly Dictionary _downloadSpeeds = new(); + + private sealed class DownloadSpeedTracker + { + public long LastBytes; + public double LastTime; + public double SpeedBytesPerSecond; + } + private bool _notificationDismissed = true; private int _lastDownloadStateHash = 0; @@ -96,117 +105,52 @@ public class DownloadUi : WindowMediatorSubscriberBase { if (_configService.Current.ShowTransferWindow) { - var limiterSnapshot = _pairProcessingLimiter.GetSnapshot(); - - try + DrawDownloadSummaryBox(); + + if (_configService.Current.ShowUploading) { - if (_fileTransferManager.IsUploading) + const int transparency = 100; + foreach (var player in _uploadingPlayers.Select(p => p.Key).ToList()) { - var currentUploads = _fileTransferManager.GetCurrentUploadsSnapshot(); - var totalUploads = currentUploads.Count; + var screenPos = _dalamudUtilService.WorldToScreen(player.GetGameObject()); + if (screenPos == Vector2.Zero) continue; - var doneUploads = currentUploads.Count(c => c.IsTransferred); - var totalUploaded = currentUploads.Sum(c => c.Transferred); - var totalToUpload = currentUploads.Sum(c => c.Total); + try + { + using var _ = _uiShared.UidFont.Push(); + var uploadText = "Uploading"; + var textSize = ImGui.CalcTextSize(uploadText); - UiSharedService.DrawOutlinedFont($"▲", ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1); - ImGui.SameLine(); - var xDistance = ImGui.GetCursorPosX(); - UiSharedService.DrawOutlinedFont($"Compressing+Uploading {doneUploads}/{totalUploads}", - ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1); - ImGui.NewLine(); - ImGui.SameLine(xDistance); - UiSharedService.DrawOutlinedFont( - $"{UiSharedService.ByteToString(totalUploaded, addSuffix: false)}/{UiSharedService.ByteToString(totalToUpload)}", - ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1); - - if (_currentDownloads.Any()) ImGui.Separator(); - } - } - catch - { - _logger.LogDebug("Error drawing upload progress"); - } - - try - { - // Check if download notifications are enabled (not set to TextOverlay) - var useNotifications = _configService.Current.UseLightlessNotifications - ? _configService.Current.LightlessDownloadNotification != NotificationLocation.TextOverlay - : _configService.Current.UseNotificationsForDownloads; - - if (useNotifications) - { - // Use notification system - if (_currentDownloads.Any()) - { - UpdateDownloadNotificationIfChanged(limiterSnapshot); - _notificationDismissed = false; - } - else if (!_notificationDismissed) - { - Mediator.Publish(new LightlessNotificationDismissMessage("pair_download_progress")); - _notificationDismissed = true; - _lastDownloadStateHash = 0; - } - } - else - { - // Use text overlay - if (limiterSnapshot.IsEnabled) - { - var queueColor = limiterSnapshot.Waiting > 0 ? ImGuiColors.DalamudYellow : ImGuiColors.DalamudGrey; - var queueText = $"Pair queue {limiterSnapshot.InFlight}/{limiterSnapshot.Limit}"; - queueText += limiterSnapshot.Waiting > 0 ? $" ({limiterSnapshot.Waiting} waiting, {limiterSnapshot.Remaining} free)" : $" ({limiterSnapshot.Remaining} free)"; - UiSharedService.DrawOutlinedFont(queueText, queueColor, new Vector4(0, 0, 0, 255), 1); - ImGui.NewLine(); - } - else - { - UiSharedService.DrawOutlinedFont("Pair apply limiter disabled", ImGuiColors.DalamudGrey, new Vector4(0, 0, 0, 255), 1); - ImGui.NewLine(); - } - - foreach (var item in _currentDownloads.ToList()) - { - var dlSlot = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.WaitingForSlot); - var dlQueue = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.WaitingForQueue); - var dlProg = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.Downloading); - var dlDecomp = item.Value.Count(c => c.Value.DownloadStatus == DownloadStatus.Decompressing); - var totalFiles = item.Value.Sum(c => c.Value.TotalFiles); - var transferredFiles = item.Value.Sum(c => c.Value.TransferredFiles); - var totalBytes = item.Value.Sum(c => c.Value.TotalBytes); - var transferredBytes = item.Value.Sum(c => c.Value.TransferredBytes); - - UiSharedService.DrawOutlinedFont($"▼", ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1); - ImGui.SameLine(); - var xDistance = ImGui.GetCursorPosX(); + var drawList = ImGui.GetBackgroundDrawList(); UiSharedService.DrawOutlinedFont( - $"{item.Key.Name} [W:{dlSlot}/Q:{dlQueue}/P:{dlProg}/D:{dlDecomp}]", - ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1); - ImGui.NewLine(); - ImGui.SameLine(xDistance); - UiSharedService.DrawOutlinedFont( - $"{transferredFiles}/{totalFiles} ({UiSharedService.ByteToString(transferredBytes, addSuffix: false)}/{UiSharedService.ByteToString(totalBytes)})", - ImGuiColors.DalamudWhite, new Vector4(0, 0, 0, 255), 1); + drawList, + uploadText, + screenPos with { X = screenPos.X - textSize.X / 2f - 1, Y = screenPos.Y - textSize.Y / 2f - 1 }, + UiSharedService.Color(255, 255, 0, transparency), + UiSharedService.Color(0, 0, 0, transparency), + 2 + ); + } + catch + { + _logger.LogDebug("Error drawing upload progress"); } } } - catch - { - _logger.LogDebug("Error drawing download progress"); - } } if (_configService.Current.ShowTransferBars) { const int transparency = 100; const int dlBarBorder = 3; + const float rounding = 6f; + var shadowOffset = new Vector2(2, 2); foreach (var transfer in _currentDownloads.ToList()) { var transferKey = transfer.Key; var rawPos = _dalamudUtilService.WorldToScreen(transferKey.GetGameObject()); + //If RawPos is zero, remove it from smoothed dictionary if (rawPos == Vector2.Zero) { @@ -214,43 +158,66 @@ public class DownloadUi : WindowMediatorSubscriberBase continue; } //Smoothing out the movement and fix jitter around the position. - Vector2 screenPos = _smoothed.TryGetValue(transferKey, out var lastPos) ? (rawPos - lastPos).Length() < 4f ? lastPos : rawPos : rawPos; - _smoothed[transferKey] = screenPos; + Vector2 screenPos = _smoothed.TryGetValue(transferKey, out var lastPos) + ? (rawPos - lastPos).Length() < 4f ? lastPos : rawPos + : rawPos; + _smoothed[transferKey] = screenPos; var totalBytes = transfer.Value.Sum(c => c.Value.TotalBytes); var transferredBytes = transfer.Value.Sum(c => c.Value.TransferredBytes); var maxDlText = $"{UiSharedService.ByteToString(totalBytes, addSuffix: false)}/{UiSharedService.ByteToString(totalBytes)}"; - var textSize = _configService.Current.TransferBarsShowText ? ImGui.CalcTextSize(maxDlText) : new Vector2(10, 10); + var textSize = _configService.Current.TransferBarsShowText + ? ImGui.CalcTextSize(maxDlText) + : new Vector2(10, 10); - int dlBarHeight = _configService.Current.TransferBarsHeight > ((int)textSize.Y + 5) ? _configService.Current.TransferBarsHeight : (int)textSize.Y + 5; - int dlBarWidth = _configService.Current.TransferBarsWidth > ((int)textSize.X + 10) ? _configService.Current.TransferBarsWidth : (int)textSize.X + 10; + int dlBarHeight = _configService.Current.TransferBarsHeight > ((int)textSize.Y + 5) + ? _configService.Current.TransferBarsHeight + : (int)textSize.Y + 5; + int dlBarWidth = _configService.Current.TransferBarsWidth > ((int)textSize.X + 10) + ? _configService.Current.TransferBarsWidth + : (int)textSize.X + 10; var dlBarStart = new Vector2(screenPos.X - dlBarWidth / 2f, screenPos.Y - dlBarHeight / 2f); var dlBarEnd = new Vector2(screenPos.X + dlBarWidth / 2f, screenPos.Y + dlBarHeight / 2f); + + // Precompute rects + var outerStart = new Vector2(dlBarStart.X - dlBarBorder - 1, dlBarStart.Y - dlBarBorder - 1); + var outerEnd = new Vector2(dlBarEnd.X + dlBarBorder + 1, dlBarEnd.Y + dlBarBorder + 1); + var borderStart = new Vector2(dlBarStart.X - dlBarBorder, dlBarStart.Y - dlBarBorder); + var borderEnd = new Vector2(dlBarEnd.X + dlBarBorder, dlBarEnd.Y + dlBarBorder); + var drawList = ImGui.GetBackgroundDrawList(); - drawList.AddRectFilled( - dlBarStart with { X = dlBarStart.X - dlBarBorder - 1, Y = dlBarStart.Y - dlBarBorder - 1 }, - dlBarEnd with { X = dlBarEnd.X + dlBarBorder + 1, Y = dlBarEnd.Y + dlBarBorder + 1 }, - UiSharedService.Color(0, 0, 0, transparency), 1); - drawList.AddRectFilled(dlBarStart with { X = dlBarStart.X - dlBarBorder, Y = dlBarStart.Y - dlBarBorder }, - dlBarEnd with { X = dlBarEnd.X + dlBarBorder, Y = dlBarEnd.Y + dlBarBorder }, - UiSharedService.Color(220, 220, 220, transparency), 1); - drawList.AddRectFilled(dlBarStart, dlBarEnd, - UiSharedService.Color(0, 0, 0, transparency), 1); + + //Shadow, background, border, bar background + drawList.AddRectFilled(outerStart + shadowOffset, outerEnd + shadowOffset, UiSharedService.Color(0, 0, 0, transparency / 2), rounding + 2); + drawList.AddRectFilled(outerStart, outerEnd, UiSharedService.Color(0, 0, 0, transparency), rounding + 2); + drawList.AddRectFilled(borderStart, borderEnd, UiSharedService.Color(220, 220, 220, transparency), rounding); + drawList.AddRectFilled(dlBarStart, dlBarEnd, UiSharedService.Color(0, 0, 0, transparency), rounding); + var dlProgressPercent = transferredBytes / (double)totalBytes; - drawList.AddRectFilled(dlBarStart, - dlBarEnd with { X = dlBarStart.X + (float)(dlProgressPercent * dlBarWidth) }, - UiSharedService.Color(UIColors.Get("LightlessPurple"))); + var progressEndX = dlBarStart.X + (float)(dlProgressPercent * dlBarWidth); + var progressEnd = new Vector2(progressEndX, dlBarEnd.Y); + + drawList.AddRectFilled( + dlBarStart, + progressEnd, + UiSharedService.Color(UIColors.Get("LightlessPurple")), + rounding + ); if (_configService.Current.TransferBarsShowText) { var downloadText = $"{UiSharedService.ByteToString(transferredBytes, addSuffix: false)}/{UiSharedService.ByteToString(totalBytes)}"; - UiSharedService.DrawOutlinedFont(drawList, downloadText, + UiSharedService.DrawOutlinedFont( + drawList, + downloadText, screenPos with { X = screenPos.X - textSize.X / 2f - 1, Y = screenPos.Y - textSize.Y / 2f - 1 }, UiSharedService.Color(255, 255, 255, transparency), - UiSharedService.Color(0, 0, 0, transparency), 1); + UiSharedService.Color(0, 0, 0, transparency), + 1 + ); } } @@ -269,20 +236,203 @@ public class DownloadUi : WindowMediatorSubscriberBase var textSize = ImGui.CalcTextSize(uploadText); var drawList = ImGui.GetBackgroundDrawList(); - UiSharedService.DrawOutlinedFont(drawList, uploadText, + UiSharedService.DrawOutlinedFont( + drawList, + uploadText, screenPos with { X = screenPos.X - textSize.X / 2f - 1, Y = screenPos.Y - textSize.Y / 2f - 1 }, UiSharedService.Color(255, 255, 0, transparency), - UiSharedService.Color(0, 0, 0, transparency), 2); + UiSharedService.Color(0, 0, 0, transparency), + 2 + ); } catch { - _logger.LogDebug("Error drawing upload progress"); + _logger.LogDebug("Error drawing upload progress"); } } } } } + private void DrawDownloadSummaryBox() + { + if (!_currentDownloads.Any()) + return; + + const int transparency = 150; + const float padding = 6f; + const float spacingY = 2f; + const float minBoxWidth = 320f; + + var now = ImGui.GetTime(); + + int totalFiles = 0; + int transferredFiles = 0; + long totalBytes = 0; + long transferredBytes = 0; + + var perPlayer = new List<(string Name, int TransferredFiles, int TotalFiles, long TransferredBytes, long TotalBytes, double SpeedBytesPerSecond)>(); + + foreach (var transfer in _currentDownloads.ToList()) + { + var handler = transfer.Key; + var statuses = transfer.Value.Values; + + var playerTotalFiles = statuses.Sum(s => s.TotalFiles); + var playerTransferredFiles = statuses.Sum(s => s.TransferredFiles); + var playerTotalBytes = statuses.Sum(s => s.TotalBytes); + var playerTransferredBytes = statuses.Sum(s => s.TransferredBytes); + + totalFiles += playerTotalFiles; + transferredFiles += playerTransferredFiles; + totalBytes += playerTotalBytes; + transferredBytes += playerTransferredBytes; + + double speed = 0; + if (playerTotalBytes > 0) + { + if (!_downloadSpeeds.TryGetValue(handler, out var tracker)) + { + tracker = new DownloadSpeedTracker + { + LastBytes = playerTransferredBytes, + LastTime = now, + SpeedBytesPerSecond = 0 + }; + _downloadSpeeds[handler] = tracker; + } + + var dt = now - tracker.LastTime; + var dBytes = playerTransferredBytes - tracker.LastBytes; + + if (dt > 0.1 && dBytes >= 0) + { + var instant = dBytes / dt; + tracker.SpeedBytesPerSecond = tracker.SpeedBytesPerSecond <= 0 + ? instant + : tracker.SpeedBytesPerSecond * 0.8 + instant * 0.2; + } + + tracker.LastTime = now; + tracker.LastBytes = playerTransferredBytes; + speed = tracker.SpeedBytesPerSecond; + } + + perPlayer.Add(( + handler.Name, + playerTransferredFiles, + playerTotalFiles, + playerTransferredBytes, + playerTotalBytes, + speed + )); + } + + foreach (var handler in _downloadSpeeds.Keys.ToList()) + { + if (!_currentDownloads.ContainsKey(handler)) + _downloadSpeeds.Remove(handler); + } + + if (totalFiles == 0 || totalBytes == 0) + return; + + var drawList = ImGui.GetBackgroundDrawList(); + var windowPos = ImGui.GetWindowPos(); + + var headerText = $"Downloading {transferredFiles}/{totalFiles} files"; + var bytesText = $"{UiSharedService.ByteToString(transferredBytes, addSuffix: false)}/{UiSharedService.ByteToString(totalBytes)}"; + + var totalSpeed = perPlayer.Sum(p => p.SpeedBytesPerSecond); + var speedText = totalSpeed > 0 + ? $"{UiSharedService.ByteToString((long)totalSpeed)}/s" + : "Calculating lightspeed..."; + + var headerSize = ImGui.CalcTextSize(headerText); + var bytesSize = ImGui.CalcTextSize(bytesText); + var speedSize = ImGui.CalcTextSize(speedText); + + float contentWidth = headerSize.X; + if (bytesSize.X > contentWidth) contentWidth = bytesSize.X; + if (speedSize.X > contentWidth) contentWidth = speedSize.X; + + foreach (var p in perPlayer) + { + var playerSpeedText = p.SpeedBytesPerSecond > 0 + ? $"{UiSharedService.ByteToString((long)p.SpeedBytesPerSecond)}/s" + : "-"; + + var line = $"{p.Name}: {p.TransferredFiles}/{p.TotalFiles} " + + $"({UiSharedService.ByteToString(p.TransferredBytes, addSuffix: false)}/{UiSharedService.ByteToString(p.TotalBytes)}) " + + $"@ {playerSpeedText}"; + + var lineSize = ImGui.CalcTextSize(line); + if (lineSize.X > contentWidth) + contentWidth = lineSize.X; + } + + var boxWidth = contentWidth + padding * 2; + if (boxWidth < minBoxWidth) + boxWidth = minBoxWidth; + + var lineHeight = ImGui.GetTextLineHeight(); + var numTextLines = 3 + perPlayer.Count; + var barHeight = lineHeight * 0.8f; + var boxHeight = padding * 3 + barHeight + numTextLines * (lineHeight + spacingY); + + var origin = windowPos; + + var boxMin = origin; + var boxMax = origin + new Vector2(boxWidth, boxHeight); + + drawList.AddRectFilled(boxMin, boxMax, UiSharedService.Color(0, 0, 0, transparency), 5f); + drawList.AddRect(boxMin, boxMax, UiSharedService.Color(220, 220, 220, transparency), 5f); + + // Progress bar + var cursor = boxMin + new Vector2(padding, padding); + var barMin = cursor; + var barMax = new Vector2(boxMin.X + boxWidth - padding, cursor.Y + barHeight); + + var progress = (float)transferredBytes / totalBytes; + drawList.AddRectFilled(barMin, barMax, UiSharedService.Color(40, 40, 40, transparency), 3f); + drawList.AddRectFilled( + barMin, + new Vector2(barMin.X + (barMax.X - barMin.X) * progress, barMax.Y), + UiSharedService.Color(UIColors.Get("LightlessPurple")), + 3f + ); + + cursor.Y = barMax.Y + padding; + + // Header + UiSharedService.DrawOutlinedFont(drawList, headerText, cursor, UiSharedService.Color(255, 255, 255, transparency), UiSharedService.Color(0, 0, 0, transparency), 1); + cursor.Y += lineHeight + spacingY; + + // Bytes + UiSharedService.DrawOutlinedFont(drawList, bytesText, cursor, UiSharedService.Color(255, 255, 255, transparency), UiSharedService.Color(0, 0, 0, transparency), 1); + cursor.Y += lineHeight + spacingY; + + // Total speed WIP + UiSharedService.DrawOutlinedFont(drawList, speedText, cursor, UiSharedService.Color(200, 255, 200, transparency), UiSharedService.Color(0, 0, 0, transparency), 1); + cursor.Y += lineHeight * 1.4f; + + // Per-player lines + foreach (var p in perPlayer.OrderByDescending(p => p.TotalBytes)) + { + var playerSpeedText = p.SpeedBytesPerSecond > 0 + ? $"{UiSharedService.ByteToString((long)p.SpeedBytesPerSecond)}/s" + : "-"; + + var line = $"{p.Name}: {p.TransferredFiles}/{p.TotalFiles} " + + $"({UiSharedService.ByteToString(p.TransferredBytes, addSuffix: false)}/{UiSharedService.ByteToString(p.TotalBytes)}) " + + $"@ {playerSpeedText}"; + + UiSharedService.DrawOutlinedFont(drawList, line, cursor, UiSharedService.Color(255, 255, 255, transparency), UiSharedService.Color(0, 0, 0, transparency), 1); + + cursor.Y += lineHeight + spacingY; + } + } + public override bool DrawConditions() { if (_uiShared.EditTrackerPosition) return true; diff --git a/LightlessSync/UI/DtrEntry.cs b/LightlessSync/UI/DtrEntry.cs index 5bff130..834265f 100644 --- a/LightlessSync/UI/DtrEntry.cs +++ b/LightlessSync/UI/DtrEntry.cs @@ -19,6 +19,7 @@ using System.Text; using LightlessSync.UI.Services; using LightlessSync.PlayerData.Pairs; using static LightlessSync.Services.PairRequestService; +using LightlessSync.Services.LightFinder; namespace LightlessSync.UI; @@ -35,8 +36,8 @@ public sealed class DtrEntry : IDisposable, IHostedService private readonly Lazy _statusEntry; private readonly Lazy _lightfinderEntry; private readonly ILogger _logger; - private readonly BroadcastService _broadcastService; - private readonly BroadcastScannerService _broadcastScannerService; + private readonly LightFinderService _broadcastService; + private readonly LightFinderScannerService _broadcastScannerService; private readonly LightlessMediator _lightlessMediator; private readonly PairUiService _pairUiService; private readonly PairRequestService _pairRequestService; @@ -62,8 +63,8 @@ public sealed class DtrEntry : IDisposable, IHostedService PairRequestService pairRequestService, ApiController apiController, ServerConfigurationManager serverManager, - BroadcastService broadcastService, - BroadcastScannerService broadcastScannerService, + LightFinderService broadcastService, + LightFinderScannerService broadcastScannerService, DalamudUtilService dalamudUtilService) { _logger = logger; diff --git a/LightlessSync/UI/BroadcastUI.cs b/LightlessSync/UI/LightFinderUI.cs similarity index 97% rename from LightlessSync/UI/BroadcastUI.cs rename to LightlessSync/UI/LightFinderUI.cs index 1efb1fa..9f118a3 100644 --- a/LightlessSync/UI/BroadcastUI.cs +++ b/LightlessSync/UI/LightFinderUI.cs @@ -7,6 +7,7 @@ using LightlessSync.API.Data.Extensions; using LightlessSync.API.Dto.Group; using LightlessSync.LightlessConfiguration; using LightlessSync.Services; +using LightlessSync.Services.LightFinder; using LightlessSync.Services.Mediator; using LightlessSync.Utils; using LightlessSync.WebAPI; @@ -15,28 +16,28 @@ using System.Numerics; namespace LightlessSync.UI { - public class BroadcastUI : WindowMediatorSubscriberBase + public class LightFinderUI : WindowMediatorSubscriberBase { private readonly ApiController _apiController; private readonly LightlessConfigService _configService; - private readonly BroadcastService _broadcastService; + private readonly LightFinderService _broadcastService; private readonly UiSharedService _uiSharedService; - private readonly BroadcastScannerService _broadcastScannerService; + private readonly LightFinderScannerService _broadcastScannerService; private IReadOnlyList _allSyncshells = Array.Empty(); private string _userUid = string.Empty; private readonly List<(string Label, string? GID, bool IsAvailable)> _syncshellOptions = new(); - public BroadcastUI( - ILogger logger, + public LightFinderUI( + ILogger logger, LightlessMediator mediator, PerformanceCollectorService performanceCollectorService, - BroadcastService broadcastService, + LightFinderService broadcastService, LightlessConfigService configService, UiSharedService uiShared, ApiController apiController, - BroadcastScannerService broadcastScannerService + LightFinderScannerService broadcastScannerService ) : base(logger, mediator, "Lightfinder###LightlessLightfinderUI", performanceCollectorService) { _broadcastService = broadcastService; diff --git a/LightlessSync/UI/SettingsUi.cs b/LightlessSync/UI/SettingsUi.cs index c0f0a68..1820ed0 100644 --- a/LightlessSync/UI/SettingsUi.cs +++ b/LightlessSync/UI/SettingsUi.cs @@ -38,6 +38,7 @@ using System.Net.Http.Json; using System.Numerics; using System.Text; using System.Text.Json; +using LightlessSync.Services.PairProcessing; namespace LightlessSync.UI; diff --git a/LightlessSync/UI/SyncshellFinderUI.cs b/LightlessSync/UI/SyncshellFinderUI.cs index 4d4dca7..5d67544 100644 --- a/LightlessSync/UI/SyncshellFinderUI.cs +++ b/LightlessSync/UI/SyncshellFinderUI.cs @@ -15,15 +15,16 @@ using LightlessSync.WebAPI; using LightlessSync.UI.Services; using Microsoft.Extensions.Logging; using System.Numerics; +using LightlessSync.Services.LightFinder; namespace LightlessSync.UI; public class SyncshellFinderUI : WindowMediatorSubscriberBase { private readonly ApiController _apiController; - private readonly BroadcastService _broadcastService; + private readonly LightFinderService _broadcastService; private readonly UiSharedService _uiSharedService; - private readonly BroadcastScannerService _broadcastScannerService; + private readonly LightFinderScannerService _broadcastScannerService; private readonly PairUiService _pairUiService; private readonly DalamudUtilService _dalamudUtilService; @@ -44,10 +45,10 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase ILogger logger, LightlessMediator mediator, PerformanceCollectorService performanceCollectorService, - BroadcastService broadcastService, + LightFinderService broadcastService, UiSharedService uiShared, ApiController apiController, - BroadcastScannerService broadcastScannerService, + LightFinderScannerService broadcastScannerService, PairUiService pairUiService, DalamudUtilService dalamudUtilService) : base(logger, mediator, "Shellfinder###LightlessSyncshellFinderUI", performanceCollectorService) { @@ -111,7 +112,7 @@ public class SyncshellFinderUI : WindowMediatorSubscriberBase if (ImGui.Button("Open Lightfinder", new Vector2(200 * ImGuiHelpers.GlobalScale, 0))) { - Mediator.Publish(new UiToggleMessage(typeof(BroadcastUI))); + Mediator.Publish(new UiToggleMessage(typeof(LightFinderUI))); } ImGui.PopStyleColor(); diff --git a/LightlessSync/UI/TopTabMenu.cs b/LightlessSync/UI/TopTabMenu.cs index 8562595..dabe8c0 100644 --- a/LightlessSync/UI/TopTabMenu.cs +++ b/LightlessSync/UI/TopTabMenu.cs @@ -781,7 +781,7 @@ public class TopTabMenu if (_uiSharedService.IconTextButton(FontAwesomeIcon.PersonCirclePlus, "Lightfinder", buttonX, center: true)) { - _lightlessMediator.Publish(new UiToggleMessage(typeof(BroadcastUI))); + _lightlessMediator.Publish(new UiToggleMessage(typeof(LightFinderUI))); } ImGui.SameLine(); diff --git a/LightlessSync/WebAPI/Files/FileDownloadManager.cs b/LightlessSync/WebAPI/Files/FileDownloadManager.cs index 94df4fa..181b02a 100644 --- a/LightlessSync/WebAPI/Files/FileDownloadManager.cs +++ b/LightlessSync/WebAPI/Files/FileDownloadManager.cs @@ -4,7 +4,6 @@ using LightlessSync.API.Dto.Files; using LightlessSync.API.Routes; using LightlessSync.FileCache; using LightlessSync.PlayerData.Handlers; -using LightlessSync.Services; using LightlessSync.Services.Mediator; using LightlessSync.Services.TextureCompression; using LightlessSync.WebAPI.Files.Models; @@ -13,6 +12,7 @@ using System.Collections.Concurrent; using System.Net; using System.Net.Http.Json; using LightlessSync.LightlessConfiguration; +using LightlessSync.Services.PairProcessing; namespace LightlessSync.WebAPI.Files;