Compare commits

...

31 Commits

Author SHA1 Message Date
f35052638a Merge pull request '#19: Fixed massive font size on the threshhold warning.' (#24) from show-own-threshold into 1.11.6
Reviewed-on: #24
2025-09-11 01:52:31 +02:00
1d70c8777e Merge pull request '#19: Added the treshhold information in compactUI to show in the UID header.' (#23) from show-own-threshold into 1.11.6
Reviewed-on: #23
Reviewed-by: defnotken <defnotken@noreply.git.lightless-sync.org>
2025-09-11 01:32:27 +02:00
880299997f Merge pull request '#9: Added validation on saving/creation of folders on name check.' (#22) from folders-name-limit into 1.11.6
Reviewed-on: #22
Reviewed-by: defnotken <defnotken@noreply.git.lightless-sync.org>
2025-09-11 01:32:19 +02:00
CakeAndBanana
1842cb3954 Fixed massive font size on the threshhold warning. 2025-09-10 22:04:07 +02:00
3e46014e5f Merge branch '1.11.6' into folders-name-limit 2025-09-10 16:02:48 +02:00
defnotken
f69ad70f0c updates to submodules 2025-09-10 09:02:10 -05:00
defnotken
7e7f88a072 Merge branch '1.11.6' of https://git.lightless-sync.org/Lightless-Sync/LightlessClient into 1.11.6 2025-09-10 08:59:54 -05:00
defnotken
bd98a630c8 Fixing PVP Nameplate 2025-09-10 08:58:04 -05:00
CakeAndBanana
523dfc7295 Added the treshhold information in compactUI to show in the UID header. 2025-09-10 06:08:02 +02:00
CakeAndBanana
e07863ddd4 Added validation on saving/creation of folders on name check. 2025-09-10 05:18:19 +02:00
2361b30e9f Merge pull request 'add UI colors in config file' (#21) from color-picker-fix into 1.11.6
Reviewed-on: #21
Reviewed-by: defnotken <defnotken@noreply.git.lightless-sync.org>
2025-09-10 00:09:13 +02:00
cc03bb576d Merge branch '1.11.6' into color-picker-fix 2025-09-10 00:05:47 +02:00
choco
1511090f63 add UI colors in config file 2025-09-09 23:55:02 +02:00
defnotken
dfc6f4ec3c update API 2025-09-09 16:36:57 -05:00
25a0eeadc8 #9: Functionality to have Syncshell folders. (#20)
Co-authored-by: CakeAndBanana <admin@cakeandbanana.nl>
Reviewed-on: #20
Reviewed-by: defnotken <defnotken@noreply.git.lightless-sync.org>
Co-authored-by: cake <cake@noreply.git.lightless-sync.org>
Co-committed-by: cake <cake@noreply.git.lightless-sync.org>
2025-09-09 23:31:50 +02:00
9416e376b8 Pause at duty (#18)
Co-authored-by: defnotken <itsdefnotken@gmail.com>
Reviewed-on: #18
Reviewed-by: cake <cake@noreply.git.lightless-sync.org>
2025-09-07 23:43:19 +02:00
1bc120c8aa Merge pull request 'choco-ui-color-picker' (#17) from choco/LightlessClient:choco-ui-color-picker into 1.11.6
Reviewed-on: #17
Reviewed-by: cake <cake@noreply.git.lightless-sync.org>
2025-09-07 21:06:44 +02:00
choco
46bc99a932 merges 2025-09-07 20:51:07 +02:00
choco
3605db0969 Merge branch '1.11.6' of https://git.lightless-sync.org/choco/LightlessClient into choco-ui-color-picker 2025-09-07 20:46:29 +02:00
c64091d997 Merge pull request '#12: Added different event listener for DtrInteractionEvent.' (#15) from dtrbar-change into 1.11.6
Reviewed-on: #15
Reviewed-by: defnotken <defnotken@noreply.git.lightless-sync.org>
2025-09-07 20:29:43 +02:00
65d483e0f8 Merge pull request '#7: Redoing of the admin syncshell screen' (#6) from syncshell_admin_user_list into 1.11.6
Reviewed-on: #6
Reviewed-by: defnotken <defnotken@noreply.git.lightless-sync.org>
2025-09-07 20:29:36 +02:00
8c1751fe61 Merge branch '1.11.6' into ui-color-picker 2025-09-07 20:14:57 +02:00
thijmenh
1b6eb149b8 change color theme feature with reset functionality to settings UI also changed dalamudyellow to lightlessyellow 2025-09-07 19:19:49 +02:00
CakeAndBanana
2f6dbc273c Changed some strings 2025-09-07 16:42:33 +02:00
CakeAndBanana
7bb4e89a0d Added 1 and 3 option in the inactive setting. 2025-09-07 16:39:34 +02:00
CakeAndBanana
8facbafff9 Added different left and right click function. Added disconnect on right click, settings if you shift+leftclick. 2025-09-07 16:00:46 +02:00
defnotken
5e30cb7bea Update LightlessAPI submodule + allow pinning 2025-09-06 08:00:40 -05:00
CakeAndBanana
4b8445a120 Redid syncshell admin panel with same style as settings 2025-09-04 03:53:24 +02:00
CakeAndBanana
d9cf5aecf4 Added owner icon and removed ban/kick/pin buttons for owner if he/she is in list. 2025-09-03 23:04:33 +02:00
defnotken
d2ac922881 wrong letter oops 2025-09-02 10:38:27 -05:00
defnotken
b31f59a7b5 Starting 1.11.6 off with a Library Update 2025-09-02 10:34:10 -05:00
52 changed files with 1557 additions and 631 deletions

2
.gitmodules vendored
View File

@@ -1,6 +1,6 @@
[submodule "LightlessAPI"] [submodule "LightlessAPI"]
path = LightlessAPI path = LightlessAPI
url = https://github.com/Light-Public-Syncshells/LightlessAPI url = https://git.lightless-sync.org/Lightless-Sync/LightlessAPI.git
[submodule "PenumbraAPI"] [submodule "PenumbraAPI"]
path = PenumbraAPI path = PenumbraAPI
url = https://github.com/Ottermandias/Penumbra.Api.git url = https://github.com/Ottermandias/Penumbra.Api.git

View File

@@ -1,4 +1,4 @@
using LightlessSync.LightlessConfiguration.Models; using LightlessSync.LightlessConfiguration.Models;
using LightlessSync.UI; using LightlessSync.UI;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -15,6 +15,7 @@ public class LightlessConfig : ILightlessConfiguration
public bool PreferNoteInDtrTooltip { get; set; } = false; public bool PreferNoteInDtrTooltip { get; set; } = false;
public bool IsNameplateColorsEnabled { get; set; } = false; public bool IsNameplateColorsEnabled { get; set; } = false;
public DtrEntry.Colors NameplateColors { get; set; } = new(Foreground: 0xE69138u, Glow: 0xFFBA47u); public DtrEntry.Colors NameplateColors { get; set; } = new(Foreground: 0xE69138u, Glow: 0xFFBA47u);
public Dictionary<string, string> CustomUIColors { get; set; } = new(StringComparer.OrdinalIgnoreCase);
public bool UseColorsInDtr { get; set; } = true; public bool UseColorsInDtr { get; set; } = true;
public DtrEntry.Colors DtrColorsDefault { get; set; } = default; public DtrEntry.Colors DtrColorsDefault { get; set; } = default;
public DtrEntry.Colors DtrColorsNotConnected { get; set; } = new(Glow: 0x0428FFu); public DtrEntry.Colors DtrColorsNotConnected { get; set; } = new(Glow: 0x0428FFu);

View File

@@ -0,0 +1,7 @@
namespace LightlessSync.LightlessConfiguration.Configurations;
public class PairTagStorage : ILightlessConfiguration
{
public Dictionary<string, Models.PairTagStorage> ServerTagStorage { get; set; } = new(StringComparer.OrdinalIgnoreCase);
public int Version { get; set; } = 0;
}

View File

@@ -13,4 +13,5 @@ public class PlayerPerformanceConfig : ILightlessConfiguration
public int VRAMSizeAutoPauseThresholdMiB { get; set; } = 550; public int VRAMSizeAutoPauseThresholdMiB { get; set; } = 550;
public int TrisAutoPauseThresholdThousands { get; set; } = 250; public int TrisAutoPauseThresholdThousands { get; set; } = 250;
public List<string> UIDsToIgnore { get; set; } = new(); public List<string> UIDsToIgnore { get; set; } = new();
public bool PauseInInstanceDuty { get; set; } = false;
} }

View File

@@ -1,9 +0,0 @@
using LightlessSync.LightlessConfiguration.Models;
namespace LightlessSync.LightlessConfiguration.Configurations;
public class ServerTagConfig : ILightlessConfiguration
{
public Dictionary<string, ServerTagStorage> ServerTagStorage { get; set; } = new(StringComparer.OrdinalIgnoreCase);
public int Version { get; set; } = 0;
}

View File

@@ -0,0 +1,7 @@
namespace LightlessSync.LightlessConfiguration.Configurations;
public class SyncshellTagStorage : ILightlessConfiguration
{
public Dictionary<string, Models.SyncshellTagStorage> ServerTagStorage { get; set; } = new(StringComparer.OrdinalIgnoreCase);
public int Version { get; set; } = 0;
}

View File

@@ -1,7 +1,7 @@
namespace LightlessSync.LightlessConfiguration.Models; namespace LightlessSync.LightlessConfiguration.Models;
[Serializable] [Serializable]
public class ServerTagStorage public class PairTagStorage
{ {
public HashSet<string> OpenPairTags { get; set; } = new(StringComparer.Ordinal); public HashSet<string> OpenPairTags { get; set; } = new(StringComparer.Ordinal);
public HashSet<string> ServerAvailablePairTags { get; set; } = new(StringComparer.Ordinal); public HashSet<string> ServerAvailablePairTags { get; set; } = new(StringComparer.Ordinal);

View File

@@ -0,0 +1,8 @@
namespace LightlessSync.LightlessConfiguration.Models;
[Serializable]
public class SyncshellTagStorage
{
public HashSet<string> ServerAvailableSyncshellTags { get; set; } = new(StringComparer.Ordinal);
public Dictionary<string, List<string>> SyncshellPairedTags { get; set; } = new(StringComparer.Ordinal);
}

View File

@@ -2,11 +2,11 @@
namespace LightlessSync.LightlessConfiguration; namespace LightlessSync.LightlessConfiguration;
public class ServerTagConfigService : ConfigurationServiceBase<ServerTagConfig> public class PairTagConfigService : ConfigurationServiceBase<PairTagStorage>
{ {
public const string ConfigName = "servertags.json"; public const string ConfigName = "servertags.json";
public ServerTagConfigService(string configDir) : base(configDir) public PairTagConfigService(string configDir) : base(configDir)
{ {
} }

View File

@@ -0,0 +1,14 @@
using LightlessSync.LightlessConfiguration.Configurations;
namespace LightlessSync.LightlessConfiguration;
public class SyncshellTagConfigService : ConfigurationServiceBase<SyncshellTagStorage>
{
public const string ConfigName = "syncshelltags.json";
public SyncshellTagConfigService(string configDir) : base(configDir)
{
}
public override string ConfigurationName => ConfigName;
}

View File

@@ -1,10 +1,11 @@
using LightlessSync.FileCache; using LightlessSync.FileCache;
using LightlessSync.LightlessConfiguration; using LightlessSync.LightlessConfiguration;
using LightlessSync.PlayerData.Pairs; using LightlessSync.PlayerData.Pairs;
using LightlessSync.PlayerData.Services; using LightlessSync.PlayerData.Services;
using LightlessSync.Services; using LightlessSync.Services;
using LightlessSync.Services.Mediator; using LightlessSync.Services.Mediator;
using LightlessSync.Services.ServerConfiguration; using LightlessSync.Services.ServerConfiguration;
using LightlessSync.UI;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -98,6 +99,7 @@ public class LightlessPlugin : MediatorSubscriberBase, IHostedService
Mediator.Subscribe<DalamudLoginMessage>(this, (_) => DalamudUtilOnLogIn()); Mediator.Subscribe<DalamudLoginMessage>(this, (_) => DalamudUtilOnLogIn());
Mediator.Subscribe<DalamudLogoutMessage>(this, (_) => DalamudUtilOnLogOut()); Mediator.Subscribe<DalamudLogoutMessage>(this, (_) => DalamudUtilOnLogOut());
UIColors.Initialize(_lightlessConfigService);
Mediator.StartQueueProcessing(); Mediator.StartQueueProcessing();
return Task.CompletedTask; return Task.CompletedTask;

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Dalamud.NET.Sdk/13.0.0"> <Project Sdk="Dalamud.NET.Sdk/13.1.0">
<PropertyGroup> <PropertyGroup>
<Authors></Authors> <Authors></Authors>
<Company></Company> <Company></Company>
<Version>1.11.5</Version> <Version>1.11.6</Version>
<Description></Description> <Description></Description>
<Copyright></Copyright> <Copyright></Copyright>
<PackageProjectUrl>https://github.com/Light-Public-Syncshells/LightlessClient</PackageProjectUrl> <PackageProjectUrl>https://github.com/Light-Public-Syncshells/LightlessClient</PackageProjectUrl>

View File

@@ -90,18 +90,20 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
}); });
Mediator.Subscribe<CombatOrPerformanceEndMessage>(this, (msg) => Mediator.Subscribe<CombatOrPerformanceEndMessage>(this, (msg) =>
{ {
if (IsVisible && _dataReceivedInDowntime != null) EnableSync();
{
ApplyCharacterData(_dataReceivedInDowntime.ApplicationId,
_dataReceivedInDowntime.CharacterData, _dataReceivedInDowntime.Forced);
_dataReceivedInDowntime = null;
}
}); });
Mediator.Subscribe<CombatOrPerformanceStartMessage>(this, _ => Mediator.Subscribe<CombatOrPerformanceStartMessage>(this, _ =>
{ {
_dataReceivedInDowntime = null; DisableSync();
_downloadCancellationTokenSource = _downloadCancellationTokenSource?.CancelRecreate(); });
_applicationCancellationTokenSource = _applicationCancellationTokenSource?.CancelRecreate(); Mediator.Subscribe<InstanceOrDutyStartMessage>(this, _ =>
{
DisableSync();
});
Mediator.Subscribe<InstanceOrDutyEndMessage>(this, (msg) =>
{
EnableSync();
}); });
LastAppliedDataBytes = -1; LastAppliedDataBytes = -1;
@@ -145,6 +147,16 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
return; return;
} }
if (_dalamudUtil.IsInInstance)
{
Mediator.Publish(new EventMessage(new Event(PlayerName, Pair.UserData, nameof(PairHandler), EventSeverity.Warning,
"Cannot apply character data: you are in an instance, deferring application")));
Logger.LogDebug("[BASE-{appBase}] Received data but player is in instance", applicationBase);
_dataReceivedInDowntime = new(applicationBase, characterData, forceApplyCustomization);
SetUploading(isUploading: false);
return;
}
if (_charaHandler == null || (PlayerCharacter == IntPtr.Zero)) if (_charaHandler == null || (PlayerCharacter == IntPtr.Zero))
{ {
Mediator.Publish(new EventMessage(new Event(PlayerName, Pair.UserData, nameof(PairHandler), EventSeverity.Warning, Mediator.Publish(new EventMessage(new Event(PlayerName, Pair.UserData, nameof(PairHandler), EventSeverity.Warning,
@@ -716,4 +728,21 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
Logger.LogDebug("[BASE-{appBase}] ModdedPaths calculated in {time}ms, missing files: {count}, total files: {total}", applicationBase, st.ElapsedMilliseconds, missingFiles.Count, moddedDictionary.Keys.Count); Logger.LogDebug("[BASE-{appBase}] ModdedPaths calculated in {time}ms, missing files: {count}, total files: {total}", applicationBase, st.ElapsedMilliseconds, missingFiles.Count, moddedDictionary.Keys.Count);
return [.. missingFiles]; return [.. missingFiles];
} }
private void DisableSync()
{
_dataReceivedInDowntime = null;
_downloadCancellationTokenSource = _downloadCancellationTokenSource?.CancelRecreate();
_applicationCancellationTokenSource = _applicationCancellationTokenSource?.CancelRecreate();
}
private void EnableSync()
{
if (IsVisible && _dataReceivedInDowntime != null)
{
ApplyCharacterData(_dataReceivedInDowntime.ApplicationId,
_dataReceivedInDowntime.CharacterData, _dataReceivedInDowntime.Forced);
_dataReceivedInDowntime = null;
}
}
} }

View File

@@ -130,15 +130,17 @@ public sealed class Plugin : IDalamudPlugin
s.GetRequiredService<CharaDataManager>(), s.GetRequiredService<CharaDataManager>(),
s.GetRequiredService<LightlessMediator>())); s.GetRequiredService<LightlessMediator>()));
collection.AddSingleton<SelectPairForTagUi>(); collection.AddSingleton<SelectPairForTagUi>();
collection.AddSingleton<RenameTagUi>(); collection.AddSingleton<RenamePairTagUi>();
collection.AddSingleton<SelectSyncshellForTagUi>();
collection.AddSingleton<RenameSyncshellTagUi>();
collection.AddSingleton((s) => new EventAggregator(pluginInterface.ConfigDirectory.FullName, collection.AddSingleton((s) => new EventAggregator(pluginInterface.ConfigDirectory.FullName,
s.GetRequiredService<ILogger<EventAggregator>>(), s.GetRequiredService<LightlessMediator>())); s.GetRequiredService<ILogger<EventAggregator>>(), s.GetRequiredService<LightlessMediator>()));
collection.AddSingleton((s) => new DalamudUtilService(s.GetRequiredService<ILogger<DalamudUtilService>>(), collection.AddSingleton((s) => new DalamudUtilService(s.GetRequiredService<ILogger<DalamudUtilService>>(),
clientState, objectTable, framework, gameGui, condition, gameData, targetManager, gameConfig, clientState, objectTable, framework, gameGui, condition, gameData, targetManager, gameConfig,
s.GetRequiredService<BlockedCharacterHandler>(), s.GetRequiredService<LightlessMediator>(), s.GetRequiredService<PerformanceCollectorService>(), s.GetRequiredService<BlockedCharacterHandler>(), s.GetRequiredService<LightlessMediator>(), s.GetRequiredService<PerformanceCollectorService>(),
s.GetRequiredService<LightlessConfigService>())); s.GetRequiredService<LightlessConfigService>(), s.GetRequiredService<PlayerPerformanceConfigService>()));
collection.AddSingleton((s) => new DtrEntry(s.GetRequiredService<ILogger<DtrEntry>>(), dtrBar, s.GetRequiredService<LightlessConfigService>(), collection.AddSingleton((s) => new DtrEntry(s.GetRequiredService<ILogger<DtrEntry>>(), dtrBar, s.GetRequiredService<LightlessConfigService>(),
s.GetRequiredService<LightlessMediator>(), s.GetRequiredService<PairManager>(), s.GetRequiredService<ApiController>())); s.GetRequiredService<LightlessMediator>(), s.GetRequiredService<PairManager>(), s.GetRequiredService<ApiController>(), s.GetRequiredService<ServerConfigurationManager>()));
collection.AddSingleton(s => new PairManager(s.GetRequiredService<ILogger<PairManager>>(), s.GetRequiredService<PairFactory>(), collection.AddSingleton(s => new PairManager(s.GetRequiredService<ILogger<PairManager>>(), s.GetRequiredService<PairFactory>(),
s.GetRequiredService<LightlessConfigService>(), s.GetRequiredService<LightlessMediator>(), contextMenu)); s.GetRequiredService<LightlessConfigService>(), s.GetRequiredService<LightlessMediator>(), contextMenu));
collection.AddSingleton<RedrawManager>(); collection.AddSingleton<RedrawManager>();
@@ -175,7 +177,8 @@ public sealed class Plugin : IDalamudPlugin
collection.AddSingleton((s) => new LightlessConfigService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new LightlessConfigService(pluginInterface.ConfigDirectory.FullName));
collection.AddSingleton((s) => new ServerConfigService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new ServerConfigService(pluginInterface.ConfigDirectory.FullName));
collection.AddSingleton((s) => new NotesConfigService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new NotesConfigService(pluginInterface.ConfigDirectory.FullName));
collection.AddSingleton((s) => new ServerTagConfigService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new PairTagConfigService(pluginInterface.ConfigDirectory.FullName));
collection.AddSingleton((s) => new SyncshellTagConfigService(pluginInterface.ConfigDirectory.FullName));
collection.AddSingleton((s) => new TransientConfigService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new TransientConfigService(pluginInterface.ConfigDirectory.FullName));
collection.AddSingleton((s) => new XivDataStorageService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new XivDataStorageService(pluginInterface.ConfigDirectory.FullName));
collection.AddSingleton((s) => new PlayerPerformanceConfigService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new PlayerPerformanceConfigService(pluginInterface.ConfigDirectory.FullName));
@@ -183,7 +186,8 @@ public sealed class Plugin : IDalamudPlugin
collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<LightlessConfigService>()); collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<LightlessConfigService>());
collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<ServerConfigService>()); collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<ServerConfigService>());
collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<NotesConfigService>()); collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<NotesConfigService>());
collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<ServerTagConfigService>()); collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<PairTagConfigService>());
collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<SyncshellTagConfigService>());
collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<TransientConfigService>()); collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<TransientConfigService>());
collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<XivDataStorageService>()); collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<XivDataStorageService>());
collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<PlayerPerformanceConfigService>()); collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<PlayerPerformanceConfigService>());
@@ -198,6 +202,7 @@ public sealed class Plugin : IDalamudPlugin
collection.AddScoped<CacheMonitor>(); collection.AddScoped<CacheMonitor>();
collection.AddScoped<UiFactory>(); collection.AddScoped<UiFactory>();
collection.AddScoped<SelectTagForPairUi>(); collection.AddScoped<SelectTagForPairUi>();
collection.AddScoped<SelectTagForSyncshellUi>();
collection.AddScoped<WindowMediatorSubscriberBase, SettingsUi>(); collection.AddScoped<WindowMediatorSubscriberBase, SettingsUi>();
collection.AddScoped<WindowMediatorSubscriberBase, CompactUi>(); collection.AddScoped<WindowMediatorSubscriberBase, CompactUi>();
collection.AddScoped<WindowMediatorSubscriberBase, IntroUi>(); collection.AddScoped<WindowMediatorSubscriberBase, IntroUi>();

View File

@@ -39,6 +39,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
private readonly IObjectTable _objectTable; private readonly IObjectTable _objectTable;
private readonly PerformanceCollectorService _performanceCollector; private readonly PerformanceCollectorService _performanceCollector;
private readonly LightlessConfigService _configService; private readonly LightlessConfigService _configService;
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
private uint? _classJobId = 0; private uint? _classJobId = 0;
private DateTime _delayedFrameworkUpdateCheck = DateTime.UtcNow; private DateTime _delayedFrameworkUpdateCheck = DateTime.UtcNow;
private string _lastGlobalBlockPlayer = string.Empty; private string _lastGlobalBlockPlayer = string.Empty;
@@ -52,7 +53,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
public DalamudUtilService(ILogger<DalamudUtilService> logger, IClientState clientState, IObjectTable objectTable, IFramework framework, public DalamudUtilService(ILogger<DalamudUtilService> logger, IClientState clientState, IObjectTable objectTable, IFramework framework,
IGameGui gameGui, ICondition condition, IDataManager gameData, ITargetManager targetManager, IGameConfig gameConfig, IGameGui gameGui, ICondition condition, IDataManager gameData, ITargetManager targetManager, IGameConfig gameConfig,
BlockedCharacterHandler blockedCharacterHandler, LightlessMediator mediator, PerformanceCollectorService performanceCollector, BlockedCharacterHandler blockedCharacterHandler, LightlessMediator mediator, PerformanceCollectorService performanceCollector,
LightlessConfigService configService) LightlessConfigService configService, PlayerPerformanceConfigService playerPerformanceConfigService)
{ {
_logger = logger; _logger = logger;
_clientState = clientState; _clientState = clientState;
@@ -66,6 +67,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
Mediator = mediator; Mediator = mediator;
_performanceCollector = performanceCollector; _performanceCollector = performanceCollector;
_configService = configService; _configService = configService;
_playerPerformanceConfigService = playerPerformanceConfigService;
WorldData = new(() => WorldData = new(() =>
{ {
return gameData.GetExcelSheet<Lumina.Excel.Sheets.World>(Dalamud.Game.ClientLanguage.English)! return gameData.GetExcelSheet<Lumina.Excel.Sheets.World>(Dalamud.Game.ClientLanguage.English)!
@@ -161,6 +163,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
public bool IsOnFrameworkThread => _framework.IsInFrameworkUpdateThread; public bool IsOnFrameworkThread => _framework.IsInFrameworkUpdateThread;
public bool IsZoning => _condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51]; public bool IsZoning => _condition[ConditionFlag.BetweenAreas] || _condition[ConditionFlag.BetweenAreas51];
public bool IsInCombatOrPerforming { get; private set; } = false; public bool IsInCombatOrPerforming { get; private set; } = false;
public bool IsInInstance { get; private set; } = false;
public bool HasModifiedGameFiles => _gameData.HasModifiedGameDataFiles; public bool HasModifiedGameFiles => _gameData.HasModifiedGameDataFiles;
public uint ClassJobId => _classJobId!.Value; public uint ClassJobId => _classJobId!.Value;
public Lazy<Dictionary<uint, string>> JobData { get; private set; } public Lazy<Dictionary<uint, string>> JobData { get; private set; }
@@ -667,20 +670,34 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
Mediator.Publish(new GposeEndMessage()); Mediator.Publish(new GposeEndMessage());
} }
if ((_condition[ConditionFlag.Performing] || _condition[ConditionFlag.InCombat]) && !IsInCombatOrPerforming) if ((_condition[ConditionFlag.Performing] || _condition[ConditionFlag.InCombat]) && !IsInCombatOrPerforming && (_condition[ConditionFlag.BoundByDuty] && !_playerPerformanceConfigService.Current.PauseInInstanceDuty))
{ {
_logger.LogDebug("Combat/Performance start"); _logger.LogDebug("Combat/Performance start");
IsInCombatOrPerforming = true; IsInCombatOrPerforming = true;
Mediator.Publish(new CombatOrPerformanceStartMessage()); Mediator.Publish(new CombatOrPerformanceStartMessage());
Mediator.Publish(new HaltScanMessage(nameof(IsInCombatOrPerforming))); Mediator.Publish(new HaltScanMessage(nameof(IsInCombatOrPerforming)));
} }
else if ((!_condition[ConditionFlag.Performing] && !_condition[ConditionFlag.InCombat]) && IsInCombatOrPerforming) else if ((!_condition[ConditionFlag.Performing] && !_condition[ConditionFlag.InCombat]) && IsInCombatOrPerforming && (_condition[ConditionFlag.BoundByDuty] && !_playerPerformanceConfigService.Current.PauseInInstanceDuty))
{ {
_logger.LogDebug("Combat/Performance end"); _logger.LogDebug("Combat/Performance end");
IsInCombatOrPerforming = false; IsInCombatOrPerforming = false;
Mediator.Publish(new CombatOrPerformanceEndMessage()); Mediator.Publish(new CombatOrPerformanceEndMessage());
Mediator.Publish(new ResumeScanMessage(nameof(IsInCombatOrPerforming))); Mediator.Publish(new ResumeScanMessage(nameof(IsInCombatOrPerforming)));
} }
if ((_condition[ConditionFlag.BoundByDuty]) && !IsInInstance && _playerPerformanceConfigService.Current.PauseInInstanceDuty)
{
_logger.LogDebug("Instance start");
IsInInstance = true;
Mediator.Publish(new InstanceOrDutyStartMessage());
Mediator.Publish(new HaltScanMessage(nameof(IsInInstance)));
}
else if (((!_condition[ConditionFlag.BoundByDuty]) && IsInInstance && _playerPerformanceConfigService.Current.PauseInInstanceDuty) || ((_condition[ConditionFlag.BoundByDuty]) && IsInInstance && !_playerPerformanceConfigService.Current.PauseInInstanceDuty))
{
_logger.LogDebug("Instance end");
IsInInstance = false;
Mediator.Publish(new InstanceOrDutyEndMessage());
Mediator.Publish(new ResumeScanMessage(nameof(IsInInstance)));
}
if (_condition[ConditionFlag.WatchingCutscene] && !IsInCutscene) if (_condition[ConditionFlag.WatchingCutscene] && !IsInCutscene)
{ {

View File

@@ -81,6 +81,8 @@ public record CensusUpdateMessage(byte Gender, byte RaceId, byte TribeId) : Mess
public record TargetPairMessage(Pair Pair) : MessageBase; public record TargetPairMessage(Pair Pair) : MessageBase;
public record CombatOrPerformanceStartMessage : MessageBase; public record CombatOrPerformanceStartMessage : MessageBase;
public record CombatOrPerformanceEndMessage : MessageBase; public record CombatOrPerformanceEndMessage : MessageBase;
public record InstanceOrDutyStartMessage : MessageBase;
public record InstanceOrDutyEndMessage : MessageBase;
public record EventMessage(Event Event) : MessageBase; public record EventMessage(Event Event) : MessageBase;
public record PenumbraDirectoryChangedMessage(string? ModDirectory) : MessageBase; public record PenumbraDirectoryChangedMessage(string? ModDirectory) : MessageBase;
public record PenumbraRedrawCharacterMessage(ICharacter Character) : SameThreadMessage; public record PenumbraRedrawCharacterMessage(ICharacter Character) : SameThreadMessage;

View File

@@ -17,6 +17,7 @@ public class NameplateService : DisposableMediatorSubscriberBase
private readonly INamePlateGui _namePlateGui; private readonly INamePlateGui _namePlateGui;
private readonly PairManager _pairManager; private readonly PairManager _pairManager;
public NameplateService(ILogger<NameplateService> logger, public NameplateService(ILogger<NameplateService> logger,
LightlessConfigService configService, LightlessConfigService configService,
INamePlateGui namePlateGui, INamePlateGui namePlateGui,
@@ -36,11 +37,9 @@ public class NameplateService : DisposableMediatorSubscriberBase
private void OnNamePlateUpdate(INamePlateUpdateContext context, IReadOnlyList<INamePlateUpdateHandler> handlers) private void OnNamePlateUpdate(INamePlateUpdateContext context, IReadOnlyList<INamePlateUpdateHandler> handlers)
{ {
if (!_configService.Current.IsNameplateColorsEnabled || (_configService.Current.IsNameplateColorsEnabled && _clientState.IsPvPExcludingDen)) return;
if (!_configService.Current.IsNameplateColorsEnabled && !_clientState.IsPvPExcludingDen) return;
var visibleUsersIds = _pairManager.GetOnlineUserPairs().Where(u => u.IsVisible && u.PlayerCharacterId != uint.MaxValue).Select(u => (ulong)u.PlayerCharacterId).ToHashSet(); var visibleUsersIds = _pairManager.GetOnlineUserPairs().Where(u => u.IsVisible && u.PlayerCharacterId != uint.MaxValue).Select(u => (ulong)u.PlayerCharacterId).ToHashSet();
var colors = _configService.Current.NameplateColors; var colors = _configService.Current.NameplateColors;
foreach (var handler in handlers) foreach (var handler in handlers)
{ {
var playerCharacter = handler.PlayerCharacter; var playerCharacter = handler.PlayerCharacter;
@@ -63,6 +62,7 @@ public class NameplateService : DisposableMediatorSubscriberBase
public void RequestRedraw() public void RequestRedraw()
{ {
_namePlateGui.RequestRedraw(); _namePlateGui.RequestRedraw();
} }

View File

@@ -23,15 +23,18 @@ public class ServerConfigurationManager
private readonly ILogger<ServerConfigurationManager> _logger; private readonly ILogger<ServerConfigurationManager> _logger;
private readonly LightlessMediator _lightlessMediator; private readonly LightlessMediator _lightlessMediator;
private readonly NotesConfigService _notesConfig; private readonly NotesConfigService _notesConfig;
private readonly ServerTagConfigService _serverTagConfig; private readonly PairTagConfigService _pairTagConfig;
private readonly SyncshellTagConfigService _syncshellTagConfig;
private readonly int _maxCharactersFolder = 20;
public ServerConfigurationManager(ILogger<ServerConfigurationManager> logger, ServerConfigService configService, public ServerConfigurationManager(ILogger<ServerConfigurationManager> logger, ServerConfigService configService,
ServerTagConfigService serverTagConfig, NotesConfigService notesConfig, DalamudUtilService dalamudUtil, PairTagConfigService pairTagConfig, SyncshellTagConfigService syncshellTagConfig, NotesConfigService notesConfig, DalamudUtilService dalamudUtil,
LightlessConfigService lightlessConfigService, HttpClient httpClient, LightlessMediator lightlessMediator) LightlessConfigService lightlessConfigService, HttpClient httpClient, LightlessMediator lightlessMediator)
{ {
_logger = logger; _logger = logger;
_configService = configService; _configService = configService;
_serverTagConfig = serverTagConfig; _pairTagConfig = pairTagConfig;
_syncshellTagConfig = syncshellTagConfig;
_notesConfig = notesConfig; _notesConfig = notesConfig;
_dalamudUtil = dalamudUtil; _dalamudUtil = dalamudUtil;
_lightlessConfigService = lightlessConfigService; _lightlessConfigService = lightlessConfigService;
@@ -258,7 +261,7 @@ public class ServerConfigurationManager
{ {
if (serverSelectionIndex == -1) serverSelectionIndex = CurrentServerIndex; if (serverSelectionIndex == -1) serverSelectionIndex = CurrentServerIndex;
var server = GetServerByIndex(serverSelectionIndex); var server = GetServerByIndex(serverSelectionIndex);
if (server.Authentications.Any(c => string.Equals(c.CharacterName, _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(), StringComparison.Ordinal) if (server.Authentications.Exists(c => string.Equals(c.CharacterName, _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(), StringComparison.Ordinal)
&& c.WorldId == _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult())) && c.WorldId == _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult()))
return; return;
@@ -277,15 +280,15 @@ public class ServerConfigurationManager
var server = GetServerByIndex(serverSelectionIndex); var server = GetServerByIndex(serverSelectionIndex);
server.Authentications.Add(new Authentication() server.Authentications.Add(new Authentication()
{ {
SecretKeyIdx = server.SecretKeys.Any() ? server.SecretKeys.First().Key : -1, SecretKeyIdx = server.SecretKeys.Count != 0 ? server.SecretKeys.First().Key : -1,
}); });
Save(); Save();
} }
internal void AddOpenPairTag(string tag) internal void AddOpenPairTag(string tag)
{ {
CurrentServerTagStorage().OpenPairTags.Add(tag); CurrentPairTagStorage().OpenPairTags.Add(tag);
_serverTagConfig.Save(); _pairTagConfig.Save();
} }
internal void AddServer(ServerStorage serverStorage) internal void AddServer(ServerStorage serverStorage)
@@ -294,36 +297,79 @@ public class ServerConfigurationManager
Save(); Save();
} }
internal void AddTag(string tag) internal void AddPairTag(string tag)
{ {
CurrentServerTagStorage().ServerAvailablePairTags.Add(tag); if (tag.Length > _maxCharactersFolder)
_serverTagConfig.Save(); {
_lightlessMediator.Publish(new RefreshUiMessage()); CurrentPairTagStorage().ServerAvailablePairTags.Add(tag);
_pairTagConfig.Save();
_lightlessMediator.Publish(new RefreshUiMessage());
}
else
{
_logger.LogInformation("Couldn't save/add {tag}. Name too long to be saved", tag);
}
}
internal void AddSyncshellTag(string tag)
{
if (tag.Length > _maxCharactersFolder)
{
CurrentSyncshellTagStorage().ServerAvailableSyncshellTags.Add(tag);
_syncshellTagConfig.Save();
_lightlessMediator.Publish(new RefreshUiMessage());
}
else
{
_logger.LogInformation("Couldn't save/add {tag}. Name too long to be saved", tag);
}
} }
internal void AddTagForUid(string uid, string tagName) internal void AddTagForUid(string uid, string tagName)
{ {
if (CurrentServerTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags)) if (CurrentPairTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags))
{ {
tags.Add(tagName); tags.Add(tagName);
_lightlessMediator.Publish(new RefreshUiMessage()); _lightlessMediator.Publish(new RefreshUiMessage());
} }
else else
{ {
CurrentServerTagStorage().UidServerPairedUserTags[uid] = [tagName]; CurrentPairTagStorage().UidServerPairedUserTags[uid] = [tagName];
} }
_serverTagConfig.Save(); _pairTagConfig.Save();
} }
internal bool ContainsOpenPairTag(string tag) internal void AddTagForSyncshell(string syncshellName, string tagName)
{ {
return CurrentServerTagStorage().OpenPairTags.Contains(tag); if (CurrentSyncshellTagStorage().SyncshellPairedTags.TryGetValue(syncshellName, out var tags))
{
tags.Add(tagName);
_lightlessMediator.Publish(new RefreshUiMessage());
}
else
{
CurrentSyncshellTagStorage().SyncshellPairedTags[syncshellName] = [tagName];
}
_syncshellTagConfig.Save();
} }
internal bool ContainsTag(string uid, string tag) internal bool ContainsOpenPairTag(string tag) => CurrentPairTagStorage().OpenPairTags.Contains(tag);
internal bool ContainsPairTag(string uid, string tag)
{ {
if (CurrentServerTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags)) if (CurrentPairTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags))
{
return tags.Contains(tag, StringComparer.Ordinal);
}
return false;
}
internal bool ContainsSyncshellTag(string name, string tag)
{
if (CurrentSyncshellTagStorage().SyncshellPairedTags.TryGetValue(name, out var tags))
{ {
return tags.Contains(tag, StringComparer.Ordinal); return tags.Contains(tag, StringComparer.Ordinal);
} }
@@ -364,30 +410,19 @@ public class ServerConfigurationManager
return null; return null;
} }
internal HashSet<string> GetServerAvailablePairTags() internal HashSet<string> GetServerAvailablePairTags() => CurrentPairTagStorage().ServerAvailablePairTags;
{
return CurrentServerTagStorage().ServerAvailablePairTags;
}
internal Dictionary<string, List<string>> GetUidServerPairedUserTags() internal HashSet<string> GetServerAvailableSyncshellTags() => CurrentSyncshellTagStorage().ServerAvailableSyncshellTags;
{
return CurrentServerTagStorage().UidServerPairedUserTags;
}
internal HashSet<string> GetUidsForTag(string tag) internal Dictionary<string, List<string>> GetUidServerPairedUserTags() => CurrentPairTagStorage().UidServerPairedUserTags;
{
return CurrentServerTagStorage().UidServerPairedUserTags.Where(p => p.Value.Contains(tag, StringComparer.Ordinal)).Select(p => p.Key).ToHashSet(StringComparer.Ordinal);
}
internal bool HasTags(string uid) internal HashSet<string> GetUidsForPairTag(string tag) => CurrentPairTagStorage().UidServerPairedUserTags.Where(p => p.Value.Contains(tag, StringComparer.Ordinal)).Select(p => p.Key).ToHashSet(StringComparer.Ordinal);
{
if (CurrentServerTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags))
{
return tags.Any();
}
return false; internal HashSet<string> GetNamesForSyncshellTag(string tag) => CurrentSyncshellTagStorage().SyncshellPairedTags.Where(p => p.Value.Contains(tag, StringComparer.Ordinal)).Select(p => p.Key).ToHashSet(StringComparer.Ordinal);
}
internal bool HasPairTags(string uid) => CurrentPairTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags) && tags.Count != 0;
internal bool HasSyncshellTags(string name) => CurrentSyncshellTagStorage().SyncshellPairedTags.TryGetValue(name, out var tags) && tags.Count != 0;
internal void RemoveCharacterFromServer(int serverSelectionIndex, Authentication item) internal void RemoveCharacterFromServer(int serverSelectionIndex, Authentication item)
{ {
@@ -398,51 +433,96 @@ public class ServerConfigurationManager
internal void RemoveOpenPairTag(string tag) internal void RemoveOpenPairTag(string tag)
{ {
CurrentServerTagStorage().OpenPairTags.Remove(tag); CurrentPairTagStorage().OpenPairTags.Remove(tag);
_serverTagConfig.Save(); _pairTagConfig.Save();
} }
internal void RemoveTag(string tag) internal void RemovePairTag(string tag)
{ {
CurrentServerTagStorage().ServerAvailablePairTags.Remove(tag); RemoveTag(CurrentPairTagStorage().ServerAvailablePairTags, tag);
foreach (var uid in GetUidsForTag(tag)) _pairTagConfig.Save();
{
RemoveTagForUid(uid, tag, save: false);
}
_serverTagConfig.Save();
_lightlessMediator.Publish(new RefreshUiMessage()); _lightlessMediator.Publish(new RefreshUiMessage());
} }
internal void RemoveSyncshellTag(string tag)
{
RemoveTag(CurrentSyncshellTagStorage().ServerAvailableSyncshellTags, tag, true);
_syncshellTagConfig.Save();
_lightlessMediator.Publish(new RefreshUiMessage());
}
internal void RemoveTag(HashSet<string> storage, string tag, bool syncshell = false)
{
storage.Remove(tag);
if (syncshell)
{
foreach (var uid in GetNamesForSyncshellTag(tag))
{
RemoveTagForSyncshell(uid, tag, save: false);
}
}
else
{
foreach (var uid in GetUidsForPairTag(tag))
{
RemoveTagForUid(uid, tag, save: false);
}
}
}
internal void RemoveTagForUid(string uid, string tagName, bool save = true) internal void RemoveTagForUid(string uid, string tagName, bool save = true)
{ {
if (CurrentServerTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags)) if (CurrentPairTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags))
{ {
tags.Remove(tagName); tags.Remove(tagName);
if (save) if (save)
{ {
_serverTagConfig.Save(); _pairTagConfig.Save();
_lightlessMediator.Publish(new RefreshUiMessage()); _lightlessMediator.Publish(new RefreshUiMessage());
} }
} }
} }
internal void RenameTag(string oldName, string newName) internal void RemoveTagForSyncshell(string name, string tagName, bool save = true)
{ {
CurrentServerTagStorage().ServerAvailablePairTags.Remove(oldName); if (CurrentSyncshellTagStorage().SyncshellPairedTags.TryGetValue(name, out var tags))
CurrentServerTagStorage().ServerAvailablePairTags.Add(newName);
foreach (var existingTags in CurrentServerTagStorage().UidServerPairedUserTags.Select(k => k.Value))
{ {
if (existingTags.Remove(oldName)) tags.Remove(tagName);
existingTags.Add(newName);
if (save)
{
_syncshellTagConfig.Save();
_lightlessMediator.Publish(new RefreshUiMessage());
}
} }
} }
internal void SaveNotes() internal void RenamePairTag(string oldName, string newName) => RenameTag(CurrentPairTagStorage().UidServerPairedUserTags, CurrentPairTagStorage().ServerAvailablePairTags, oldName, newName);
internal void RenameSyncshellTag(string oldName, string newName) => RenameTag(CurrentSyncshellTagStorage().SyncshellPairedTags, CurrentSyncshellTagStorage().ServerAvailableSyncshellTags, oldName, newName);
internal void RenameTag(Dictionary<string, List<string>> tags, HashSet<string> storage, string oldName, string newName)
{ {
_notesConfig.Save(); if (newName.Length > _maxCharactersFolder)
{
storage.Remove(oldName);
storage.Add(newName);
foreach (var existingTags in tags.Select(k => k.Value))
{
if (existingTags.Remove(oldName))
existingTags.Add(newName);
}
_lightlessMediator.Publish(new RefreshUiMessage());
}
else
{
_logger.LogInformation("Couldn't save/add {tag}. Name too long to be saved", newName);
}
} }
internal void SaveNotes() => _notesConfig.Save();
internal void SetNoteForGid(string gid, string note, bool save = true) internal void SetNoteForGid(string gid, string note, bool save = true)
{ {
if (string.IsNullOrEmpty(gid)) return; if (string.IsNullOrEmpty(gid)) return;
@@ -476,10 +556,16 @@ public class ServerConfigurationManager
return _notesConfig.Current.ServerNotes[CurrentApiUrl]; return _notesConfig.Current.ServerNotes[CurrentApiUrl];
} }
private ServerTagStorage CurrentServerTagStorage() private PairTagStorage CurrentPairTagStorage()
{ {
TryCreateCurrentServerTagStorage(); TryCreateCurrentPairTagStorage();
return _serverTagConfig.Current.ServerTagStorage[CurrentApiUrl]; return _pairTagConfig.Current.ServerTagStorage[CurrentApiUrl];
}
private SyncshellTagStorage CurrentSyncshellTagStorage()
{
TryCreateCurrentSyncshellTagStorage();
return _syncshellTagConfig.Current.ServerTagStorage[CurrentApiUrl];
} }
private void EnsureMainExists() private void EnsureMainExists()
@@ -499,11 +585,19 @@ public class ServerConfigurationManager
} }
} }
private void TryCreateCurrentServerTagStorage() private void TryCreateCurrentPairTagStorage()
{ {
if (!_serverTagConfig.Current.ServerTagStorage.ContainsKey(CurrentApiUrl)) if (!_pairTagConfig.Current.ServerTagStorage.ContainsKey(CurrentApiUrl))
{ {
_serverTagConfig.Current.ServerTagStorage[CurrentApiUrl] = new(); _pairTagConfig.Current.ServerTagStorage[CurrentApiUrl] = new();
}
}
private void TryCreateCurrentSyncshellTagStorage()
{
if (!_syncshellTagConfig.Current.ServerTagStorage.ContainsKey(CurrentApiUrl))
{
_syncshellTagConfig.Current.ServerTagStorage[CurrentApiUrl] = new();
} }
} }

View File

@@ -3,7 +3,6 @@ using LightlessSync.PlayerData.Pairs;
using LightlessSync.Services.Mediator; using LightlessSync.Services.Mediator;
using LightlessSync.Services.ServerConfiguration; using LightlessSync.Services.ServerConfiguration;
using LightlessSync.UI; using LightlessSync.UI;
using LightlessSync.UI.Components.Popup;
using LightlessSync.WebAPI; using LightlessSync.WebAPI;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@@ -4,7 +4,6 @@ using Dalamud.Interface.Windowing;
using LightlessSync.LightlessConfiguration; using LightlessSync.LightlessConfiguration;
using LightlessSync.Services.Mediator; using LightlessSync.Services.Mediator;
using LightlessSync.UI; using LightlessSync.UI;
using LightlessSync.UI.Components.Popup;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace LightlessSync.Services; namespace LightlessSync.Services;

View File

@@ -90,7 +90,7 @@ internal sealed partial class CharaDataHubUi
if (!_uiSharedService.IsInGpose) if (!_uiSharedService.IsInGpose)
{ {
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
UiSharedService.DrawGroupedCenteredColorText("Assigning users to characters is only available in GPose.", ImGuiColors.DalamudYellow, 300); UiSharedService.DrawGroupedCenteredColorText("Assigning users to characters is only available in GPose.", UIColors.Get("LightlessYellow"), 300);
} }
UiSharedService.DistanceSeparator(); UiSharedService.DistanceSeparator();
ImGui.TextUnformatted("Users In Lobby"); ImGui.TextUnformatted("Users In Lobby");
@@ -104,7 +104,7 @@ internal sealed partial class CharaDataHubUi
if (!_charaDataGposeTogetherManager.UsersInLobby.Any() && !string.IsNullOrEmpty(_charaDataGposeTogetherManager.CurrentGPoseLobbyId)) if (!_charaDataGposeTogetherManager.UsersInLobby.Any() && !string.IsNullOrEmpty(_charaDataGposeTogetherManager.CurrentGPoseLobbyId))
{ {
UiSharedService.DrawGroupedCenteredColorText("No other users in current GPose lobby", ImGuiColors.DalamudYellow); UiSharedService.DrawGroupedCenteredColorText("No other users in current GPose lobby", UIColors.Get("LightlessYellow"));
} }
else else
{ {

View File

@@ -23,7 +23,7 @@ internal sealed partial class CharaDataHubUi
if (dataDto == null) if (dataDto == null)
{ {
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
UiSharedService.DrawGroupedCenteredColorText("Select an entry above to edit its data.", ImGuiColors.DalamudYellow); UiSharedService.DrawGroupedCenteredColorText("Select an entry above to edit its data.", UIColors.Get("LightlessYellow"));
return; return;
} }
@@ -31,7 +31,7 @@ internal sealed partial class CharaDataHubUi
if (updateDto == null) if (updateDto == null)
{ {
UiSharedService.DrawGroupedCenteredColorText("Something went awfully wrong and there's no update DTO. Try updating Character Data via the button above.", ImGuiColors.DalamudYellow); UiSharedService.DrawGroupedCenteredColorText("Something went awfully wrong and there's no update DTO. Try updating Character Data via the button above.", UIColors.Get("LightlessYellow"));
return; return;
} }
@@ -75,7 +75,7 @@ internal sealed partial class CharaDataHubUi
} }
if (_charaDataManager.CharaUpdateTask != null && !_charaDataManager.CharaUpdateTask.IsCompleted) if (_charaDataManager.CharaUpdateTask != null && !_charaDataManager.CharaUpdateTask.IsCompleted)
{ {
UiSharedService.ColorTextWrapped("Updating data on server, please wait.", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("Updating data on server, please wait.", UIColors.Get("LightlessYellow"));
} }
} }
@@ -85,7 +85,7 @@ internal sealed partial class CharaDataHubUi
{ {
if (_charaDataManager.UploadProgress != null) if (_charaDataManager.UploadProgress != null)
{ {
UiSharedService.ColorTextWrapped(_charaDataManager.UploadProgress.Value ?? string.Empty, ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped(_charaDataManager.UploadProgress.Value ?? string.Empty, UIColors.Get("LightlessYellow"));
} }
if ((!_charaDataManager.UploadTask?.IsCompleted ?? false) && _uiSharedService.IconTextButton(FontAwesomeIcon.Ban, "Cancel Upload")) if ((!_charaDataManager.UploadTask?.IsCompleted ?? false) && _uiSharedService.IconTextButton(FontAwesomeIcon.Ban, "Cancel Upload"))
{ {
@@ -112,7 +112,7 @@ internal sealed partial class CharaDataHubUi
UiSharedService.DrawGrouped(() => UiSharedService.DrawGrouped(() =>
{ {
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
UiSharedService.ColorTextWrapped($"You have {otherUpdates} other entries with unsaved changes.", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped($"You have {otherUpdates} other entries with unsaved changes.", UIColors.Get("LightlessYellow"));
ImGui.SameLine(); ImGui.SameLine();
using (ImRaii.Disabled(_charaDataManager.CharaUpdateTask != null && !_charaDataManager.CharaUpdateTask.IsCompleted)) using (ImRaii.Disabled(_charaDataManager.CharaUpdateTask != null && !_charaDataManager.CharaUpdateTask.IsCompleted))
{ {
@@ -259,7 +259,7 @@ internal sealed partial class CharaDataHubUi
ImGui.SameLine(); ImGui.SameLine();
ImGuiHelpers.ScaledDummy(20, 1); ImGuiHelpers.ScaledDummy(20, 1);
ImGui.SameLine(); ImGui.SameLine();
UiSharedService.ColorTextWrapped("New data was set. It may contain files that require to be uploaded (will happen on Saving to server)", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("New data was set. It may contain files that require to be uploaded (will happen on Saving to server)", UIColors.Get("LightlessYellow"));
} }
ImGui.TextUnformatted("Contains Manipulation Data"); ImGui.TextUnformatted("Contains Manipulation Data");
@@ -414,7 +414,7 @@ internal sealed partial class CharaDataHubUi
} }
} }
ImGui.SameLine(); ImGui.SameLine();
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudYellow, poseCount == maxPoses)) using (ImRaii.PushColor(ImGuiCol.Text, UIColors.Get("LightlessYellow"), poseCount == maxPoses))
ImGui.TextUnformatted($"{poseCount}/{maxPoses} poses attached"); ImGui.TextUnformatted($"{poseCount}/{maxPoses} poses attached");
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
@@ -424,7 +424,7 @@ internal sealed partial class CharaDataHubUi
if (!_uiSharedService.IsInGpose && _charaDataManager.BrioAvailable) if (!_uiSharedService.IsInGpose && _charaDataManager.BrioAvailable)
{ {
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
UiSharedService.DrawGroupedCenteredColorText("To attach pose and world data you need to be in GPose.", ImGuiColors.DalamudYellow); UiSharedService.DrawGroupedCenteredColorText("To attach pose and world data you need to be in GPose.", UIColors.Get("LightlessYellow"));
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
} }
else if (!_charaDataManager.BrioAvailable) else if (!_charaDataManager.BrioAvailable)
@@ -443,7 +443,7 @@ internal sealed partial class CharaDataHubUi
if (pose.Id == null) if (pose.Id == null)
{ {
UiSharedService.ScaledSameLine(50); UiSharedService.ScaledSameLine(50);
_uiSharedService.IconText(FontAwesomeIcon.Plus, ImGuiColors.DalamudYellow); _uiSharedService.IconText(FontAwesomeIcon.Plus, UIColors.Get("LightlessYellow"));
UiSharedService.AttachToolTip("This pose has not been added to the server yet. Save changes to upload this Pose data."); UiSharedService.AttachToolTip("This pose has not been added to the server yet. Save changes to upload this Pose data.");
} }
@@ -451,14 +451,14 @@ internal sealed partial class CharaDataHubUi
if (poseHasChanges) if (poseHasChanges)
{ {
UiSharedService.ScaledSameLine(50); UiSharedService.ScaledSameLine(50);
_uiSharedService.IconText(FontAwesomeIcon.ExclamationTriangle, ImGuiColors.DalamudYellow); _uiSharedService.IconText(FontAwesomeIcon.ExclamationTriangle, UIColors.Get("LightlessYellow"));
UiSharedService.AttachToolTip("This pose has changes that have not been saved to the server yet."); UiSharedService.AttachToolTip("This pose has changes that have not been saved to the server yet.");
} }
UiSharedService.ScaledSameLine(75); UiSharedService.ScaledSameLine(75);
if (pose.Description == null && pose.WorldData == null && pose.PoseData == null) if (pose.Description == null && pose.WorldData == null && pose.PoseData == null)
{ {
UiSharedService.ColorText("Pose scheduled for deletion", ImGuiColors.DalamudYellow); UiSharedService.ColorText("Pose scheduled for deletion", UIColors.Get("LightlessYellow"));
} }
else else
{ {
@@ -669,7 +669,7 @@ internal sealed partial class CharaDataHubUi
var idText = entry.FullId; var idText = entry.FullId;
if (uDto?.HasChanges ?? false) if (uDto?.HasChanges ?? false)
{ {
UiSharedService.ColorText(idText, ImGuiColors.DalamudYellow); UiSharedService.ColorText(idText, UIColors.Get("LightlessYellow"));
UiSharedService.AttachToolTip("This entry has unsaved changes"); UiSharedService.AttachToolTip("This entry has unsaved changes");
} }
else else
@@ -724,7 +724,7 @@ internal sealed partial class CharaDataHubUi
FontAwesomeIcon eIcon = FontAwesomeIcon.None; FontAwesomeIcon eIcon = FontAwesomeIcon.None;
if (!Equals(DateTime.MaxValue, entry.ExpiryDate)) if (!Equals(DateTime.MaxValue, entry.ExpiryDate))
eIcon = FontAwesomeIcon.Clock; eIcon = FontAwesomeIcon.Clock;
_uiSharedService.IconText(eIcon, ImGuiColors.DalamudYellow); _uiSharedService.IconText(eIcon, UIColors.Get("LightlessYellow"));
if (ImGui.IsItemClicked()) SelectedDtoId = entry.Id; if (ImGui.IsItemClicked()) SelectedDtoId = entry.Id;
if (eIcon != FontAwesomeIcon.None) if (eIcon != FontAwesomeIcon.None)
{ {
@@ -759,13 +759,13 @@ internal sealed partial class CharaDataHubUi
if (_charaDataManager.OwnCharaData.Count == _charaDataManager.MaxCreatableCharaData) if (_charaDataManager.OwnCharaData.Count == _charaDataManager.MaxCreatableCharaData)
{ {
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
UiSharedService.ColorTextWrapped("You have reached the maximum Character Data entries and cannot create more.", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("You have reached the maximum Character Data entries and cannot create more.", UIColors.Get("LightlessYellow"));
} }
} }
if (_charaDataManager.DataCreationTask != null && !_charaDataManager.DataCreationTask.IsCompleted) if (_charaDataManager.DataCreationTask != null && !_charaDataManager.DataCreationTask.IsCompleted)
{ {
UiSharedService.ColorTextWrapped("Creating new character data entry on server...", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("Creating new character data entry on server...", UIColors.Get("LightlessYellow"));
} }
else if (_charaDataManager.DataCreationTask != null && _charaDataManager.DataCreationTask.IsCompleted) else if (_charaDataManager.DataCreationTask != null && _charaDataManager.DataCreationTask.IsCompleted)
{ {

View File

@@ -78,7 +78,7 @@ internal partial class CharaDataHubUi
if (!_uiSharedService.IsInGpose) if (!_uiSharedService.IsInGpose)
{ {
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
UiSharedService.DrawGroupedCenteredColorText("Spawning and applying pose data is only available in GPose.", ImGuiColors.DalamudYellow); UiSharedService.DrawGroupedCenteredColorText("Spawning and applying pose data is only available in GPose.", UIColors.Get("LightlessYellow"));
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
} }
@@ -93,7 +93,7 @@ internal partial class CharaDataHubUi
using var indent = ImRaii.PushIndent(5f); using var indent = ImRaii.PushIndent(5f);
if (_charaDataNearbyManager.NearbyData.Count == 0) if (_charaDataNearbyManager.NearbyData.Count == 0)
{ {
UiSharedService.DrawGroupedCenteredColorText("No Shared World Poses found nearby.", ImGuiColors.DalamudYellow); UiSharedService.DrawGroupedCenteredColorText("No Shared World Poses found nearby.", UIColors.Get("LightlessYellow"));
} }
bool wasAnythingHovered = false; bool wasAnythingHovered = false;

View File

@@ -190,7 +190,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
} }
if (!string.IsNullOrEmpty(_charaDataManager.DataApplicationProgress)) if (!string.IsNullOrEmpty(_charaDataManager.DataApplicationProgress))
{ {
UiSharedService.ColorTextWrapped(_charaDataManager.DataApplicationProgress, ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped(_charaDataManager.DataApplicationProgress, UIColors.Get("LightlessYellow"));
} }
if (_charaDataManager.DataApplicationTask != null) if (_charaDataManager.DataApplicationTask != null)
{ {
@@ -436,7 +436,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
if (!_hasValidGposeTarget) if (!_hasValidGposeTarget)
{ {
ImGuiHelpers.ScaledDummy(3); ImGuiHelpers.ScaledDummy(3);
UiSharedService.DrawGroupedCenteredColorText("Applying data is only available in GPose with a valid selected GPose target.", ImGuiColors.DalamudYellow, 350); UiSharedService.DrawGroupedCenteredColorText("Applying data is only available in GPose with a valid selected GPose target.", UIColors.Get("LightlessYellow"), 350);
} }
ImGuiHelpers.ScaledDummy(10); ImGuiHelpers.ScaledDummy(10);
@@ -595,7 +595,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
if (_configService.Current.FavoriteCodes.Count == 0) if (_configService.Current.FavoriteCodes.Count == 0)
{ {
UiSharedService.ColorTextWrapped("You have no favorites added. Add Favorites through the other tabs before you can use this tab.", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("You have no favorites added. Add Favorites through the other tabs before you can use this tab.", UIColors.Get("LightlessYellow"));
} }
} }
} }
@@ -644,7 +644,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
ImGui.NewLine(); ImGui.NewLine();
if (!_charaDataManager.DownloadMetaInfoTask?.IsCompleted ?? false) if (!_charaDataManager.DownloadMetaInfoTask?.IsCompleted ?? false)
{ {
UiSharedService.ColorTextWrapped("Downloading meta info. Please wait.", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("Downloading meta info. Please wait.", UIColors.Get("LightlessYellow"));
} }
if ((_charaDataManager.DownloadMetaInfoTask?.IsCompleted ?? false) && !_charaDataManager.DownloadMetaInfoTask.Result.Success) if ((_charaDataManager.DownloadMetaInfoTask?.IsCompleted ?? false) && !_charaDataManager.DownloadMetaInfoTask.Result.Success)
{ {
@@ -850,12 +850,12 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
UiSharedService.ColorTextWrapped("Failure to read MCDF file. MCDF file is possibly corrupt. Re-export the MCDF file and try again.", UiSharedService.ColorTextWrapped("Failure to read MCDF file. MCDF file is possibly corrupt. Re-export the MCDF file and try again.",
ImGuiColors.DalamudRed); ImGuiColors.DalamudRed);
UiSharedService.ColorTextWrapped("Note: if this is your MCDF, try redrawing yourself, wait and re-export the file. " + UiSharedService.ColorTextWrapped("Note: if this is your MCDF, try redrawing yourself, wait and re-export the file. " +
"If you received it from someone else have them do the same.", ImGuiColors.DalamudYellow); "If you received it from someone else have them do the same.", UIColors.Get("LightlessYellow"));
} }
} }
else else
{ {
UiSharedService.ColorTextWrapped("Loading Character...", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("Loading Character...", UIColors.Get("LightlessYellow"));
} }
} }
} }
@@ -896,7 +896,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase
}, Directory.Exists(_configService.Current.LastSavedCharaDataLocation) ? _configService.Current.LastSavedCharaDataLocation : null); }, Directory.Exists(_configService.Current.LastSavedCharaDataLocation) ? _configService.Current.LastSavedCharaDataLocation : null);
} }
UiSharedService.ColorTextWrapped("Note: For best results make sure you have everything you want to be shared as well as the correct character appearance" + UiSharedService.ColorTextWrapped("Note: For best results make sure you have everything you want to be shared as well as the correct character appearance" +
" equipped and redraw your character before exporting.", ImGuiColors.DalamudYellow); " equipped and redraw your character before exporting.", UIColors.Get("LightlessYellow"));
ImGui.Unindent(); ImGui.Unindent();
} }

View File

@@ -1,13 +1,14 @@
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using Dalamud.Utility; using Dalamud.Utility;
using LightlessSync.API.Data.Enum;
using LightlessSync.API.Data.Extensions; using LightlessSync.API.Data.Extensions;
using LightlessSync.API.Dto.Group; using LightlessSync.API.Dto.Group;
using LightlessSync.Interop.Ipc; using LightlessSync.Interop.Ipc;
using LightlessSync.LightlessConfiguration; using LightlessSync.LightlessConfiguration;
using LightlessSync.LightlessConfiguration.Configurations;
using LightlessSync.PlayerData.Handlers; using LightlessSync.PlayerData.Handlers;
using LightlessSync.PlayerData.Pairs; using LightlessSync.PlayerData.Pairs;
using LightlessSync.Services; using LightlessSync.Services;
@@ -15,6 +16,7 @@ using LightlessSync.Services.Mediator;
using LightlessSync.Services.ServerConfiguration; using LightlessSync.Services.ServerConfiguration;
using LightlessSync.UI.Components; using LightlessSync.UI.Components;
using LightlessSync.UI.Handlers; using LightlessSync.UI.Handlers;
using LightlessSync.Utils;
using LightlessSync.WebAPI; using LightlessSync.WebAPI;
using LightlessSync.WebAPI.Files; using LightlessSync.WebAPI.Files;
using LightlessSync.WebAPI.Files.Models; using LightlessSync.WebAPI.Files.Models;
@@ -30,21 +32,27 @@ namespace LightlessSync.UI;
public class CompactUi : WindowMediatorSubscriberBase public class CompactUi : WindowMediatorSubscriberBase
{ {
private readonly CharacterAnalyzer _characterAnalyzer;
private readonly ApiController _apiController; private readonly ApiController _apiController;
private readonly LightlessConfigService _configService; private readonly LightlessConfigService _configService;
private readonly ConcurrentDictionary<GameObjectHandler, Dictionary<string, FileDownloadStatus>> _currentDownloads = new(); private readonly ConcurrentDictionary<GameObjectHandler, Dictionary<string, FileDownloadStatus>> _currentDownloads = new();
private readonly DrawEntityFactory _drawEntityFactory; private readonly DrawEntityFactory _drawEntityFactory;
private readonly FileUploadManager _fileTransferManager; private readonly FileUploadManager _fileTransferManager;
private readonly PlayerPerformanceConfigService _playerPerformanceConfig;
private readonly PairManager _pairManager; private readonly PairManager _pairManager;
private readonly SelectTagForPairUi _selectGroupForPairUi; private readonly SelectTagForPairUi _selectTagForPairUi;
private readonly SelectTagForSyncshellUi _selectTagForSyncshellUi;
private readonly SelectSyncshellForTagUi _selectSyncshellForTagUi;
private readonly RenameSyncshellTagUi _renameSyncshellTagUi;
private readonly SelectPairForTagUi _selectPairsForGroupUi; private readonly SelectPairForTagUi _selectPairsForGroupUi;
private readonly RenameTagUi _renameTagUi; private readonly RenamePairTagUi _renamePairTagUi;
private readonly IpcManager _ipcManager; private readonly IpcManager _ipcManager;
private readonly ServerConfigurationManager _serverManager; private readonly ServerConfigurationManager _serverManager;
private readonly TopTabMenu _tabMenu; private readonly TopTabMenu _tabMenu;
private readonly TagHandler _tagHandler; private readonly TagHandler _tagHandler;
private readonly UiSharedService _uiSharedService; private readonly UiSharedService _uiSharedService;
private List<IDrawFolder> _drawFolders; private List<IDrawFolder> _drawFolders;
private Dictionary<ObjectKind, Dictionary<string, CharacterAnalyzer.FileDataEntry>>? _cachedAnalysis;
private Pair? _lastAddedUser; private Pair? _lastAddedUser;
private string _lastAddedUserComment = string.Empty; private string _lastAddedUserComment = string.Empty;
private Vector2 _lastPosition = Vector2.One; private Vector2 _lastPosition = Vector2.One;
@@ -57,8 +65,10 @@ public class CompactUi : WindowMediatorSubscriberBase
public CompactUi(ILogger<CompactUi> logger, UiSharedService uiShared, LightlessConfigService configService, ApiController apiController, PairManager pairManager, public CompactUi(ILogger<CompactUi> logger, UiSharedService uiShared, LightlessConfigService configService, ApiController apiController, PairManager pairManager,
ServerConfigurationManager serverManager, LightlessMediator mediator, FileUploadManager fileTransferManager, ServerConfigurationManager serverManager, LightlessMediator mediator, FileUploadManager fileTransferManager,
TagHandler tagHandler, DrawEntityFactory drawEntityFactory, SelectTagForPairUi selectTagForPairUi, SelectPairForTagUi selectPairForTagUi, RenameTagUi renameTagUi, TagHandler tagHandler, DrawEntityFactory drawEntityFactory,
PerformanceCollectorService performanceCollectorService, IpcManager ipcManager) SelectTagForPairUi selectTagForPairUi, SelectPairForTagUi selectPairForTagUi, RenamePairTagUi renameTagUi,
SelectTagForSyncshellUi selectTagForSyncshellUi, SelectSyncshellForTagUi selectSyncshellForTagUi, RenameSyncshellTagUi renameSyncshellTagUi,
PerformanceCollectorService performanceCollectorService, IpcManager ipcManager, CharacterAnalyzer characterAnalyzer, PlayerPerformanceConfigService playerPerformanceConfig)
: base(logger, mediator, "###LightlessSyncMainUI", performanceCollectorService) : base(logger, mediator, "###LightlessSyncMainUI", performanceCollectorService)
{ {
_uiSharedService = uiShared; _uiSharedService = uiShared;
@@ -69,13 +79,16 @@ public class CompactUi : WindowMediatorSubscriberBase
_fileTransferManager = fileTransferManager; _fileTransferManager = fileTransferManager;
_tagHandler = tagHandler; _tagHandler = tagHandler;
_drawEntityFactory = drawEntityFactory; _drawEntityFactory = drawEntityFactory;
_selectGroupForPairUi = selectTagForPairUi; _selectTagForPairUi = selectTagForPairUi;
_selectTagForSyncshellUi = selectTagForSyncshellUi;
_selectSyncshellForTagUi = selectSyncshellForTagUi;
_renameSyncshellTagUi = renameSyncshellTagUi;
_selectPairsForGroupUi = selectPairForTagUi; _selectPairsForGroupUi = selectPairForTagUi;
_renameTagUi = renameTagUi; _renamePairTagUi = renameTagUi;
_ipcManager = ipcManager; _ipcManager = ipcManager;
_tabMenu = new TopTabMenu(Mediator, _apiController, _pairManager, _uiSharedService); _tabMenu = new TopTabMenu(Mediator, _apiController, _pairManager, _uiSharedService);
AllowPinning = false; AllowPinning = true;
AllowClickthrough = false; AllowClickthrough = false;
TitleBarButtons = new() TitleBarButtons = new()
{ {
@@ -137,6 +150,8 @@ public class CompactUi : WindowMediatorSubscriberBase
MinimumSize = new Vector2(375, 400), MinimumSize = new Vector2(375, 400),
MaximumSize = new Vector2(375, 2000), MaximumSize = new Vector2(375, 2000),
}; };
_characterAnalyzer = characterAnalyzer;
_playerPerformanceConfig = playerPerformanceConfig;
} }
protected override void DrawInternal() protected override void DrawInternal()
@@ -199,9 +214,12 @@ public class CompactUi : WindowMediatorSubscriberBase
float pairlistEnd = ImGui.GetCursorPosY(); float pairlistEnd = ImGui.GetCursorPosY();
using (ImRaii.PushId("transfers")) DrawTransfers(); using (ImRaii.PushId("transfers")) DrawTransfers();
_transferPartHeight = ImGui.GetCursorPosY() - pairlistEnd - ImGui.GetTextLineHeight(); _transferPartHeight = ImGui.GetCursorPosY() - pairlistEnd - ImGui.GetTextLineHeight();
using (ImRaii.PushId("group-user-popup")) _selectPairsForGroupUi.Draw(_pairManager.DirectPairs); using (ImRaii.PushId("group-pair-popup")) _selectPairsForGroupUi.Draw(_pairManager.DirectPairs);
using (ImRaii.PushId("group-user-edit")) _renameTagUi.Draw(_pairManager.DirectPairs); using (ImRaii.PushId("group-syncshell-popup")) _selectSyncshellForTagUi.Draw([.. _pairManager.Groups.Values]);
using (ImRaii.PushId("grouping-popup")) _selectGroupForPairUi.Draw(); using (ImRaii.PushId("group-pair-edit")) _renamePairTagUi.Draw();
using (ImRaii.PushId("group-syncshell-edit")) _renameSyncshellTagUi.Draw();
using (ImRaii.PushId("grouping-pair-popup")) _selectTagForPairUi.Draw();
using (ImRaii.PushId("grouping-syncshell-popup")) _selectTagForSyncshellUi.Draw();
} }
if (_configService.Current.OpenPopupOnAdd && _pairManager.LastAddedUser != null) if (_configService.Current.OpenPopupOnAdd && _pairManager.LastAddedUser != null)
@@ -396,6 +414,13 @@ public class CompactUi : WindowMediatorSubscriberBase
{ {
var uidText = GetUidText(); var uidText = GetUidText();
//Getting information of character and triangles threshold to show overlimit status in UID bar.
_cachedAnalysis = _characterAnalyzer.LastAnalysis.DeepClone();
var groupedfiles = _cachedAnalysis.First().Value.Select(v => v.Value).GroupBy(f => f.FileType, StringComparer.Ordinal)
.OrderBy(k => k.Key, StringComparer.Ordinal).ToList();
var actualTriCount = _cachedAnalysis.First().Value.Sum(f => f.Value.Triangles);
var isOverTriHold = actualTriCount > (_playerPerformanceConfig.Current.TrisWarningThresholdThousands * 1000);
using (_uiSharedService.UidFont.Push()) using (_uiSharedService.UidFont.Push())
{ {
var uidTextSize = ImGui.CalcTextSize(uidText); var uidTextSize = ImGui.CalcTextSize(uidText);
@@ -403,24 +428,50 @@ public class CompactUi : WindowMediatorSubscriberBase
ImGui.TextColored(GetUidColor(), uidText); ImGui.TextColored(GetUidColor(), uidText);
} }
if (groupedfiles != null)
{
//Checking of VRAM threshhold
var actualVramUsage = groupedfiles.SingleOrDefault(v => string.Equals(v.Key, "tex", StringComparison.Ordinal)).Sum(f => f.OriginalSize);
var isOverVRAMUsage = _playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB * 1024 * 1024 < actualVramUsage;
if (isOverTriHold || isOverVRAMUsage)
{
ImGui.SameLine();
_uiSharedService.IconText(FontAwesomeIcon.ExclamationTriangle, UIColors.Get("LightlessYellow"));
string warningMessage = "";
if (isOverTriHold)
{
warningMessage += $"You exceed your own triangles threshold by " +
$"{actualTriCount - _playerPerformanceConfig.Current.TrisWarningThresholdThousands * 1000} triangles.";
warningMessage += Environment.NewLine;
}
if (isOverVRAMUsage)
{
warningMessage += $"You exceed your own VRAM threshold by " +
$"{UiSharedService.ByteToString(actualVramUsage - (_playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB * 1024 * 1024))}.";
}
UiSharedService.AttachToolTip(warningMessage);
}
}
if (_apiController.ServerState is ServerState.Connected) if (_apiController.ServerState is ServerState.Connected)
{ {
if (ImGui.IsItemClicked()) if (ImGui.IsItemClicked())
{ {
ImGui.SetClipboardText(_apiController.DisplayName); ImGui.SetClipboardText(_apiController.DisplayName);
} }
UiSharedService.AttachToolTip("Click to copy");
if (!string.Equals(_apiController.DisplayName, _apiController.UID, StringComparison.Ordinal)) if (!string.Equals(_apiController.DisplayName, _apiController.UID, StringComparison.Ordinal))
{ {
var origTextSize = ImGui.CalcTextSize(_apiController.UID); var origTextSize = ImGui.CalcTextSize(_apiController.UID);
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X) / 2 - (origTextSize.X / 2)); ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X) / 2 - (origTextSize.X / 2));
ImGui.TextColored(GetUidColor(), _apiController.UID); ImGui.TextColored(GetUidColor(), _apiController.UID);
UiSharedService.AttachToolTip("Click to copy");
if (ImGui.IsItemClicked()) if (ImGui.IsItemClicked())
{ {
ImGui.SetClipboardText(_apiController.UID); ImGui.SetClipboardText(_apiController.UID);
} }
UiSharedService.AttachToolTip("Click to copy");
} }
} }
else else
@@ -462,12 +513,12 @@ public class CompactUi : WindowMediatorSubscriberBase
bool FilterVisibleUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u) bool FilterVisibleUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u)
=> u.Key.IsVisible => u.Key.IsVisible
&& (_configService.Current.ShowSyncshellUsersInVisible || !(!_configService.Current.ShowSyncshellUsersInVisible && !u.Key.IsDirectlyPaired)); && (_configService.Current.ShowSyncshellUsersInVisible || !(!_configService.Current.ShowSyncshellUsersInVisible && !u.Key.IsDirectlyPaired));
bool FilterTagusers(KeyValuePair<Pair, List<GroupFullInfoDto>> u, string tag) bool FilterTagUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u, string tag)
=> u.Key.IsDirectlyPaired && !u.Key.IsOneSidedPair && _tagHandler.HasTag(u.Key.UserData.UID, tag); => u.Key.IsDirectlyPaired && !u.Key.IsOneSidedPair && _tagHandler.HasPairTag(u.Key.UserData.UID, tag);
bool FilterGroupUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u, GroupFullInfoDto group) bool FilterGroupUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u, GroupFullInfoDto group)
=> u.Value.Exists(g => string.Equals(g.GID, group.GID, StringComparison.Ordinal)); => u.Value.Exists(g => string.Equals(g.GID, group.GID, StringComparison.Ordinal));
bool FilterNotTaggedUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u) bool FilterNotTaggedUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u)
=> u.Key.IsDirectlyPaired && !u.Key.IsOneSidedPair && !_tagHandler.HasAnyTag(u.Key.UserData.UID); => u.Key.IsDirectlyPaired && !u.Key.IsOneSidedPair && !_tagHandler.HasAnyPairTag(u.Key.UserData.UID);
bool FilterOfflineUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u) bool FilterOfflineUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u)
=> ((u.Key.IsDirectlyPaired && _configService.Current.ShowSyncshellOfflineUsersSeparately) => ((u.Key.IsDirectlyPaired && _configService.Current.ShowSyncshellOfflineUsersSeparately)
|| !_configService.Current.ShowSyncshellOfflineUsersSeparately) || !_configService.Current.ShowSyncshellOfflineUsersSeparately)
@@ -487,46 +538,48 @@ public class CompactUi : WindowMediatorSubscriberBase
} }
List<IDrawFolder> groupFolders = new(); List<IDrawFolder> groupFolders = new();
foreach (var group in _pairManager.GroupPairs.Select(g => g.Key).OrderBy(g => g.GroupAliasOrGID, StringComparer.OrdinalIgnoreCase)) foreach (var group in _pairManager.GroupPairs.Select(g => g.Key).OrderBy(g => g.GroupAliasOrGID, StringComparer.OrdinalIgnoreCase))
{ {
var allGroupPairs = ImmutablePairList(allPairs GetGroups(allPairs, filteredPairs, group, out ImmutableList<Pair> allGroupPairs, out Dictionary<Pair, List<GroupFullInfoDto>> filteredGroupPairs);
.Where(u => FilterGroupUsers(u, group)));
var filteredGroupPairs = filteredPairs
.Where(u => FilterGroupUsers(u, group) && FilterOnlineOrPausedSelf(u))
.OrderByDescending(u => u.Key.IsOnline)
.ThenBy(u =>
{
if (string.Equals(u.Key.UserData.UID, group.OwnerUID, StringComparison.Ordinal)) return 0;
if (group.GroupPairUserInfos.TryGetValue(u.Key.UserData.UID, out var info))
{
if (info.IsModerator()) return 1;
if (info.IsPinned()) return 2;
}
return u.Key.IsVisible ? 3 : 4;
})
.ThenBy(AlphabeticalSort, StringComparer.OrdinalIgnoreCase)
.ToDictionary(k => k.Key, k => k.Value);
groupFolders.Add(_drawEntityFactory.CreateDrawGroupFolder(group, filteredGroupPairs, allGroupPairs)); groupFolders.Add(_drawEntityFactory.CreateDrawGroupFolder(group, filteredGroupPairs, allGroupPairs));
} }
if (_configService.Current.GroupUpSyncshells) if (_configService.Current.GroupUpSyncshells)
drawFolders.Add(new DrawGroupedGroupFolder(groupFolders, _tagHandler, _uiSharedService)); drawFolders.Add(new DrawGroupedGroupFolder(groupFolders, _tagHandler, _uiSharedService, _selectSyncshellForTagUi, _renameSyncshellTagUi, ""));
else else
drawFolders.AddRange(groupFolders); drawFolders.AddRange(groupFolders);
var tags = _tagHandler.GetAllTagsSorted(); var tags = _tagHandler.GetAllPairTagsSorted();
foreach (var tag in tags) foreach (var tag in tags)
{ {
var allTagPairs = ImmutablePairList(allPairs var allTagPairs = ImmutablePairList(allPairs
.Where(u => FilterTagusers(u, tag))); .Where(u => FilterTagUsers(u, tag)));
var filteredTagPairs = BasicSortedDictionary(filteredPairs var filteredTagPairs = BasicSortedDictionary(filteredPairs
.Where(u => FilterTagusers(u, tag) && FilterOnlineOrPausedSelf(u))); .Where(u => FilterTagUsers(u, tag) && FilterOnlineOrPausedSelf(u)));
drawFolders.Add(_drawEntityFactory.CreateDrawTagFolder(tag, filteredTagPairs, allTagPairs)); drawFolders.Add(_drawEntityFactory.CreateDrawTagFolder(tag, filteredTagPairs, allTagPairs));
} }
var syncshellTags = _tagHandler.GetAllSyncshellTagsSorted();
foreach (var syncshelltag in syncshellTags)
{
List<IDrawFolder> syncshellFolderTags = [];
foreach (var group in _pairManager.GroupPairs.Select(g => g.Key).OrderBy(g => g.GroupAliasOrGID, StringComparer.OrdinalIgnoreCase))
{
if (_tagHandler.HasSyncshellTag(group.GID, syncshelltag))
{
GetGroups(allPairs, filteredPairs, group, out ImmutableList<Pair> allGroupPairs, out Dictionary<Pair, List<GroupFullInfoDto>> filteredGroupPairs);
syncshellFolderTags.Add(_drawEntityFactory.CreateDrawGroupFolder($"tag_{group.GID}", group, filteredGroupPairs, allGroupPairs));
}
}
if (syncshellFolderTags.Count > 0)
{
drawFolders.Add(new DrawGroupedGroupFolder(syncshellFolderTags, _tagHandler, _uiSharedService, _selectSyncshellForTagUi, _renameSyncshellTagUi, syncshelltag));
}
}
var allOnlineNotTaggedPairs = ImmutablePairList(allPairs var allOnlineNotTaggedPairs = ImmutablePairList(allPairs
.Where(FilterNotTaggedUsers)); .Where(FilterNotTaggedUsers));
var onlineNotTaggedPairs = BasicSortedDictionary(filteredPairs var onlineNotTaggedPairs = BasicSortedDictionary(filteredPairs
@@ -561,6 +614,27 @@ public class CompactUi : WindowMediatorSubscriberBase
ImmutablePairList(allPairs.Where(u => u.Key.IsOneSidedPair)))); ImmutablePairList(allPairs.Where(u => u.Key.IsOneSidedPair))));
return drawFolders; return drawFolders;
void GetGroups(Dictionary<Pair, List<GroupFullInfoDto>> allPairs, Dictionary<Pair, List<GroupFullInfoDto>> filteredPairs, GroupFullInfoDto group, out ImmutableList<Pair> allGroupPairs, out Dictionary<Pair, List<GroupFullInfoDto>> filteredGroupPairs)
{
allGroupPairs = ImmutablePairList(allPairs
.Where(u => FilterGroupUsers(u, group)));
filteredGroupPairs = filteredPairs
.Where(u => FilterGroupUsers(u, group) && FilterOnlineOrPausedSelf(u))
.OrderByDescending(u => u.Key.IsOnline)
.ThenBy(u =>
{
if (string.Equals(u.Key.UserData.UID, group.OwnerUID, StringComparison.Ordinal)) return 0;
if (group.GroupPairUserInfos.TryGetValue(u.Key.UserData.UID, out var info))
{
if (info.IsModerator()) return 1;
if (info.IsPinned()) return 2;
}
return u.Key.IsVisible ? 3 : 4;
})
.ThenBy(AlphabeticalSort, StringComparer.OrdinalIgnoreCase)
.ToDictionary(k => k.Key, k => k.Value);
}
} }
private string GetServerError() private string GetServerError()

View File

@@ -19,16 +19,18 @@ public class DrawFolderGroup : DrawFolderBase
private readonly GroupFullInfoDto _groupFullInfoDto; private readonly GroupFullInfoDto _groupFullInfoDto;
private readonly IdDisplayHandler _idDisplayHandler; private readonly IdDisplayHandler _idDisplayHandler;
private readonly LightlessMediator _lightlessMediator; private readonly LightlessMediator _lightlessMediator;
private readonly SelectTagForSyncshellUi _selectTagForSyncshellUi;
public DrawFolderGroup(string id, GroupFullInfoDto groupFullInfoDto, ApiController apiController, public DrawFolderGroup(string id, GroupFullInfoDto groupFullInfoDto, ApiController apiController,
IImmutableList<DrawUserPair> drawPairs, IImmutableList<Pair> allPairs, TagHandler tagHandler, IdDisplayHandler idDisplayHandler, IImmutableList<DrawUserPair> drawPairs, IImmutableList<Pair> allPairs, TagHandler tagHandler, IdDisplayHandler idDisplayHandler,
LightlessMediator lightlessMediator, UiSharedService uiSharedService) : LightlessMediator lightlessMediator, UiSharedService uiSharedService, SelectTagForSyncshellUi selectTagForSyncshellUi) :
base(id, drawPairs, allPairs, tagHandler, uiSharedService) base(id, drawPairs, allPairs, tagHandler, uiSharedService)
{ {
_groupFullInfoDto = groupFullInfoDto; _groupFullInfoDto = groupFullInfoDto;
_apiController = apiController; _apiController = apiController;
_idDisplayHandler = idDisplayHandler; _idDisplayHandler = idDisplayHandler;
_lightlessMediator = lightlessMediator; _lightlessMediator = lightlessMediator;
_selectTagForSyncshellUi = selectTagForSyncshellUi;
} }
protected override bool RenderIfEmpty => true; protected override bool RenderIfEmpty => true;
@@ -99,6 +101,13 @@ public class DrawFolderGroup : DrawFolderBase
} }
UiSharedService.AttachToolTip("Copies all your notes for all users in this Syncshell to the clipboard." + Environment.NewLine + "They can be imported via Settings -> General -> Notes -> Import notes from clipboard"); UiSharedService.AttachToolTip("Copies all your notes for all users in this Syncshell to the clipboard." + Environment.NewLine + "They can be imported via Settings -> General -> Notes -> Import notes from clipboard");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Folder, "Syncshell Groups", menuWidth, true))
{
ImGui.CloseCurrentPopup();
_selectTagForSyncshellUi.Open(_groupFullInfoDto);
}
UiSharedService.AttachToolTip("Choose syncshell groups for " + _groupFullInfoDto.GID);
if (_uiSharedService.IconTextButton(FontAwesomeIcon.ArrowCircleLeft, "Leave Syncshell", menuWidth, true) && UiSharedService.CtrlPressed()) if (_uiSharedService.IconTextButton(FontAwesomeIcon.ArrowCircleLeft, "Leave Syncshell", menuWidth, true) && UiSharedService.CtrlPressed())
{ {
_ = _apiController.GroupLeave(_groupFullInfoDto); _ = _apiController.GroupLeave(_groupFullInfoDto);
@@ -185,7 +194,7 @@ public class DrawFolderGroup : DrawFolderBase
_uiSharedService.IconText(FontAwesomeIcon.UsersCog, (_groupFullInfoDto.GroupPermissions.IsPreferDisableAnimations() != individualAnimDisabled _uiSharedService.IconText(FontAwesomeIcon.UsersCog, (_groupFullInfoDto.GroupPermissions.IsPreferDisableAnimations() != individualAnimDisabled
|| _groupFullInfoDto.GroupPermissions.IsPreferDisableSounds() != individualSoundsDisabled || _groupFullInfoDto.GroupPermissions.IsPreferDisableSounds() != individualSoundsDisabled
|| _groupFullInfoDto.GroupPermissions.IsPreferDisableVFX() != individualVFXDisabled) ? ImGuiColors.DalamudYellow : null); || _groupFullInfoDto.GroupPermissions.IsPreferDisableVFX() != individualVFXDisabled) ? UIColors.Get("LightlessYellow") : null);
if (ImGui.IsItemHovered()) if (ImGui.IsItemHovered())
{ {
ImGui.BeginTooltip(); ImGui.BeginTooltip();

View File

@@ -13,10 +13,10 @@ public class DrawFolderTag : DrawFolderBase
{ {
private readonly ApiController _apiController; private readonly ApiController _apiController;
private readonly SelectPairForTagUi _selectPairForTagUi; private readonly SelectPairForTagUi _selectPairForTagUi;
private readonly RenameTagUi _renameTagUi; private readonly RenamePairTagUi _renameTagUi;
public DrawFolderTag(string id, IImmutableList<DrawUserPair> drawPairs, IImmutableList<Pair> allPairs, public DrawFolderTag(string id, IImmutableList<DrawUserPair> drawPairs, IImmutableList<Pair> allPairs,
TagHandler tagHandler, ApiController apiController, SelectPairForTagUi selectPairForTagUi, RenameTagUi renameTagUi, UiSharedService uiSharedService) TagHandler tagHandler, ApiController apiController, SelectPairForTagUi selectPairForTagUi, RenamePairTagUi renameTagUi, UiSharedService uiSharedService)
: base(id, drawPairs, allPairs, tagHandler, uiSharedService) : base(id, drawPairs, allPairs, tagHandler, uiSharedService)
{ {
_apiController = apiController; _apiController = apiController;
@@ -112,7 +112,7 @@ public class DrawFolderTag : DrawFolderBase
} }
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete Pair Group", menuWidth, isInPopup: true) && UiSharedService.CtrlPressed()) if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete Pair Group", menuWidth, isInPopup: true) && UiSharedService.CtrlPressed())
{ {
_tagHandler.RemoveTag(_id); _tagHandler.RemovePairTag(_id);
} }
UiSharedService.AttachToolTip("Hold CTRL to remove this Group permanently." + Environment.NewLine + UiSharedService.AttachToolTip("Hold CTRL to remove this Group permanently." + Environment.NewLine +
"Note: this will not unpair with users in this Group."); "Note: this will not unpair with users in this Group.");

View File

@@ -9,20 +9,27 @@ namespace LightlessSync.UI.Components;
public class DrawGroupedGroupFolder : IDrawFolder public class DrawGroupedGroupFolder : IDrawFolder
{ {
private readonly string _tag;
private readonly IEnumerable<IDrawFolder> _groups; private readonly IEnumerable<IDrawFolder> _groups;
private readonly TagHandler _tagHandler; private readonly TagHandler _tagHandler;
private readonly UiSharedService _uiSharedService; private readonly UiSharedService _uiSharedService;
private readonly SelectSyncshellForTagUi _selectSyncshellForTagUi;
private readonly RenameSyncshellTagUi _renameSyncshellTagUi;
private bool _wasHovered = false; private bool _wasHovered = false;
private float _menuWidth;
public IImmutableList<DrawUserPair> DrawPairs => throw new NotSupportedException(); public IImmutableList<DrawUserPair> DrawPairs => throw new NotSupportedException();
public int OnlinePairs => _groups.SelectMany(g => g.DrawPairs).Where(g => g.Pair.IsOnline).DistinctBy(g => g.Pair.UserData.UID).Count(); public int OnlinePairs => _groups.SelectMany(g => g.DrawPairs).Where(g => g.Pair.IsOnline).DistinctBy(g => g.Pair.UserData.UID).Count();
public int TotalPairs => _groups.Sum(g => g.TotalPairs); public int TotalPairs => _groups.Sum(g => g.TotalPairs);
public DrawGroupedGroupFolder(IEnumerable<IDrawFolder> groups, TagHandler tagHandler, UiSharedService uiSharedService) public DrawGroupedGroupFolder(IEnumerable<IDrawFolder> groups, TagHandler tagHandler, UiSharedService uiSharedService, SelectSyncshellForTagUi selectSyncshellForTagUi, RenameSyncshellTagUi renameSyncshellTagUi, string tag)
{ {
_groups = groups; _groups = groups;
_tagHandler = tagHandler; _tagHandler = tagHandler;
_uiSharedService = uiSharedService; _uiSharedService = uiSharedService;
_selectSyncshellForTagUi = selectSyncshellForTagUi;
_renameSyncshellTagUi = renameSyncshellTagUi;
_tag = tag;
} }
public void Draw() public void Draw()
@@ -30,6 +37,11 @@ public class DrawGroupedGroupFolder : IDrawFolder
if (!_groups.Any()) return; if (!_groups.Any()) return;
string _id = "__folder_syncshells"; string _id = "__folder_syncshells";
if (_tag != "")
{
_id = $"__folder_{_tag}";
}
using var id = ImRaii.PushId(_id); using var id = ImRaii.PushId(_id);
var color = ImRaii.PushColor(ImGuiCol.ChildBg, ImGui.GetColorU32(ImGuiCol.FrameBgHovered), _wasHovered); var color = ImRaii.PushColor(ImGuiCol.ChildBg, ImGui.GetColorU32(ImGuiCol.FrameBgHovered), _wasHovered);
using (ImRaii.Child("folder__" + _id, new System.Numerics.Vector2(UiSharedService.GetWindowContentRegionWidth() - ImGui.GetCursorPosX(), ImGui.GetFrameHeight()))) using (ImRaii.Child("folder__" + _id, new System.Numerics.Vector2(UiSharedService.GetWindowContentRegionWidth() - ImGui.GetCursorPosX(), ImGui.GetFrameHeight())))
@@ -49,18 +61,36 @@ public class DrawGroupedGroupFolder : IDrawFolder
ImGui.SameLine(); ImGui.SameLine();
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
_uiSharedService.IconText(FontAwesomeIcon.UsersRectangle);
using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing with { X = ImGui.GetStyle().ItemSpacing.X / 2f })) if (_tag != "")
{ {
ImGui.SameLine(); _uiSharedService.IconText(FontAwesomeIcon.FolderPlus);
ImGui.AlignTextToFramePadding(); }
ImGui.TextUnformatted("[" + OnlinePairs.ToString() + "]"); else
{
_uiSharedService.IconText(FontAwesomeIcon.UsersRectangle);
} }
using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing with { X = ImGui.GetStyle().ItemSpacing.X / 2f }))
{
ImGui.SameLine();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted("[" + OnlinePairs.ToString() + "]");
}
UiSharedService.AttachToolTip(OnlinePairs + " online in all of your joined syncshells" + Environment.NewLine + UiSharedService.AttachToolTip(OnlinePairs + " online in all of your joined syncshells" + Environment.NewLine +
TotalPairs + " pairs combined in all of your joined syncshells"); TotalPairs + " pairs combined in all of your joined syncshells");
ImGui.SameLine(); ImGui.SameLine();
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted("All Syncshells"); if (_tag != "")
{
ImGui.TextUnformatted(_tag);
ImGui.SameLine();
DrawMenu();
} else
{
ImGui.TextUnformatted("All Syncshells");
}
} }
color.Dispose(); color.Dispose();
_wasHovered = ImGui.IsItemHovered(); _wasHovered = ImGui.IsItemHovered();
@@ -76,4 +106,40 @@ public class DrawGroupedGroupFolder : IDrawFolder
} }
} }
} }
protected void DrawMenu()
{
var barButtonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.EllipsisV);
var windowEndX = ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth();
ImGui.SameLine(windowEndX - barButtonSize.X);
if (_uiSharedService.IconButton(FontAwesomeIcon.EllipsisV))
{
ImGui.OpenPopup("User Flyout Menu");
}
if (ImGui.BeginPopup("User Flyout Menu"))
{
using (ImRaii.PushId($"buttons-syncshell-{_tag}")) GroupMenu(_menuWidth);
_menuWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
ImGui.EndPopup();
}
}
protected void GroupMenu(float menuWidth)
{
ImGui.TextUnformatted("Syncshell Group Menu");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Users, "Select Syncshells", menuWidth, isInPopup: true))
{
_selectSyncshellForTagUi.Open(_tag);
}
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Edit, "Rename Syncshell Group", menuWidth, isInPopup: true))
{
_renameSyncshellTagUi.Open(_tag);
}
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete Syncshell Group", menuWidth, isInPopup: true) && UiSharedService.CtrlPressed())
{
_tagHandler.RemoveSyncshellTag(_tag);
}
UiSharedService.AttachToolTip("Hold CTRL to remove this Group permanently.");
}
} }

View File

@@ -196,7 +196,7 @@ public class DrawUserPair
if (_pair.IsPaused) if (_pair.IsPaused)
{ {
using var _ = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudYellow); using var _ = ImRaii.PushColor(ImGuiCol.Text, UIColors.Get("LightlessYellow"));
_uiSharedService.IconText(FontAwesomeIcon.PauseCircle); _uiSharedService.IconText(FontAwesomeIcon.PauseCircle);
userPairText = _pair.UserData.AliasOrUID + " is paused"; userPairText = _pair.UserData.AliasOrUID + " is paused";
} }
@@ -274,7 +274,7 @@ public class DrawUserPair
{ {
ImGui.SameLine(); ImGui.SameLine();
_uiSharedService.IconText(FontAwesomeIcon.ExclamationTriangle, ImGuiColors.DalamudYellow); _uiSharedService.IconText(FontAwesomeIcon.ExclamationTriangle, UIColors.Get("LightlessYellow"));
string userWarningText = "WARNING: This user exceeds one or more of your defined thresholds:" + UiSharedService.TooltipSeparator; string userWarningText = "WARNING: This user exceeds one or more of your defined thresholds:" + UiSharedService.TooltipSeparator;
bool shownVram = false; bool shownVram = false;
@@ -376,7 +376,7 @@ public class DrawUserPair
currentRightSide -= (_uiSharedService.GetIconSize(individualIcon).X + spacingX); currentRightSide -= (_uiSharedService.GetIconSize(individualIcon).X + spacingX);
ImGui.SameLine(currentRightSide); ImGui.SameLine(currentRightSide);
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudYellow, individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled)) using (ImRaii.PushColor(ImGuiCol.Text, UIColors.Get("LightlessYellow"), individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled))
_uiSharedService.IconText(individualIcon); _uiSharedService.IconText(individualIcon);
if (ImGui.IsItemHovered()) if (ImGui.IsItemHovered())
{ {

View File

@@ -1,36 +1,34 @@
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.UI.Handlers; using LightlessSync.UI.Handlers;
using System.Numerics; using System.Numerics;
namespace LightlessSync.UI.Components; namespace LightlessSync.UI.Components;
public class RenameTagUi public class RenamePairTagUi
{ {
private readonly TagHandler _tagHandler; private readonly TagHandler _tagHandler;
private readonly UiSharedService _uiSharedService; private readonly UiSharedService _uiSharedService;
private string _desiredName = string.Empty; private string _desiredName = string.Empty;
private bool _opened = false; private bool _opened = false;
private HashSet<string> _peopleInGroup = new(StringComparer.Ordinal);
private bool _show = false; private bool _show = false;
private string _tag = string.Empty; private string _tag = string.Empty;
public RenameTagUi(TagHandler tagHandler, UiSharedService uiSharedService) public RenamePairTagUi(TagHandler tagHandler, UiSharedService uiSharedService)
{ {
_tagHandler = tagHandler; _tagHandler = tagHandler;
_uiSharedService = uiSharedService; _uiSharedService = uiSharedService;
} }
public void Draw(List<Pair> pairs) public void Draw()
{ {
var workHeight = ImGui.GetMainViewport().WorkSize.Y / ImGuiHelpers.GlobalScale; var workHeight = ImGui.GetMainViewport().WorkSize.Y / ImGuiHelpers.GlobalScale;
var minSize = new Vector2(300, workHeight < 110 ? workHeight : 110) * ImGuiHelpers.GlobalScale; var minSize = new Vector2(300, workHeight < 110 ? workHeight : 110) * ImGuiHelpers.GlobalScale;
var maxSize = new Vector2(300, 110) * ImGuiHelpers.GlobalScale; var maxSize = new Vector2(300, 110) * ImGuiHelpers.GlobalScale;
var popupName = $"Renaming Group {_tag}"; var popupName = $"Renaming Pair Group {_tag}";
if (!_show) if (!_show)
{ {
@@ -50,12 +48,12 @@ public class RenameTagUi
{ {
ImGui.TextUnformatted($"Renaming {_tag}"); ImGui.TextUnformatted($"Renaming {_tag}");
ImGui.InputTextWithHint("##desiredname", "Enter new group name", ref _desiredName, 255, ImGuiInputTextFlags.None); ImGui.InputTextWithHint("##desiredname", "Enter new group name", ref _desiredName, 20, ImGuiInputTextFlags.None);
using (ImRaii.Disabled(string.IsNullOrEmpty(_desiredName))) using (ImRaii.Disabled(string.IsNullOrEmpty(_desiredName)))
{ {
if (_uiSharedService.IconTextButton(Dalamud.Interface.FontAwesomeIcon.Plus, "Rename Group")) if (_uiSharedService.IconTextButton(Dalamud.Interface.FontAwesomeIcon.Plus, "Rename Group"))
{ {
RenameTag(pairs, _tag, _desiredName); RenameTag(_tag, _desiredName);
_show = false; _show = false;
} }
} }
@@ -69,25 +67,13 @@ public class RenameTagUi
public void Open(string tag) public void Open(string tag)
{ {
_peopleInGroup = _tagHandler.GetOtherUidsForTag(tag);
_tag = tag; _tag = tag;
_desiredName = ""; _desiredName = "";
_show = true; _show = true;
} }
public void RenameTag(List<Pair> pairs, string oldTag, string newTag)
{
//Removal of old tag
_tagHandler.RemoveTag(oldTag);
//Creation of new tag and adding of old group pairs in new one. public void RenameTag(string oldTag, string newTag)
_tagHandler.AddTag(newTag); {
foreach (Pair pair in pairs) _tagHandler.RenamePairTag(oldTag, newTag);
{
var isInTag = _peopleInGroup.Contains(pair.UserData.UID);
if (isInTag)
{
_tagHandler.AddTagToPairedUid(pair.UserData.UID, newTag);
}
}
} }
} }

View File

@@ -0,0 +1,79 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using LightlessSync.UI.Handlers;
using System.Numerics;
namespace LightlessSync.UI.Components;
public class RenameSyncshellTagUi
{
private readonly TagHandler _tagHandler;
private readonly UiSharedService _uiSharedService;
private string _desiredName = string.Empty;
private bool _opened = false;
private bool _show = false;
private string _tag = string.Empty;
public RenameSyncshellTagUi(TagHandler tagHandler, UiSharedService uiSharedService)
{
_tagHandler = tagHandler;
_uiSharedService = uiSharedService;
}
public void Draw()
{
var workHeight = ImGui.GetMainViewport().WorkSize.Y / ImGuiHelpers.GlobalScale;
var minSize = new Vector2(300, workHeight < 110 ? workHeight : 110) * ImGuiHelpers.GlobalScale;
var maxSize = new Vector2(300, 110) * ImGuiHelpers.GlobalScale;
var popupName = $"Renaming Syncshell Group {_tag}";
if (!_show)
{
_opened = false;
}
if (_show && !_opened)
{
ImGui.SetNextWindowSize(minSize);
UiSharedService.CenterNextWindow(minSize.X, minSize.Y, ImGuiCond.Always);
ImGui.OpenPopup(popupName);
_opened = true;
}
ImGui.SetNextWindowSizeConstraints(minSize, maxSize);
if (ImGui.BeginPopupModal(popupName, ref _show, ImGuiWindowFlags.Popup | ImGuiWindowFlags.Modal))
{
ImGui.TextUnformatted($"Renaming {_tag}");
ImGui.InputTextWithHint("##desiredname", "Enter new group name", ref _desiredName, 20, ImGuiInputTextFlags.None);
using (ImRaii.Disabled(string.IsNullOrEmpty(_desiredName)))
{
if (_uiSharedService.IconTextButton(Dalamud.Interface.FontAwesomeIcon.Plus, "Rename Group"))
{
RenameTag(_tag, _desiredName);
_show = false;
}
}
ImGui.EndPopup();
}
else
{
_show = false;
}
}
public void Open(string tag)
{
_tag = tag;
_desiredName = "";
_show = true;
}
public void RenameTag(string oldTag, string newTag)
{
_tagHandler.RenameSyncshellTag(oldTag, newTag);
}
}

View File

@@ -60,7 +60,7 @@ public class SelectPairForTagUi
{ {
if (isInGroup) if (isInGroup)
{ {
_tagHandler.AddTagToPairedUid(item.UserData.UID, _tag); _tagHandler.AddPairTagToPairedUid(item.UserData.UID, _tag);
_peopleInGroup.Add(item.UserData.UID); _peopleInGroup.Add(item.UserData.UID);
} }
else else

View File

@@ -0,0 +1,86 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Utility;
using LightlessSync.API.Dto.Group;
using LightlessSync.UI.Handlers;
using System.Numerics;
namespace LightlessSync.UI.Components;
public class SelectSyncshellForTagUi
{
private readonly TagHandler _tagHandler;
private string _filter = string.Empty;
private bool _opened = false;
private HashSet<string> _syncshellsInGroup = new(StringComparer.Ordinal);
private bool _show = false;
private string _tag = string.Empty;
public SelectSyncshellForTagUi(TagHandler tagHandler)
{
_tagHandler = tagHandler;
}
public void Draw(List<GroupFullInfoDto> groups)
{
var workHeight = ImGui.GetMainViewport().WorkSize.Y / ImGuiHelpers.GlobalScale;
var minSize = new Vector2(300, workHeight < 400 ? workHeight : 400) * ImGuiHelpers.GlobalScale;
var maxSize = new Vector2(300, 1000) * ImGuiHelpers.GlobalScale;
var popupName = $"Choose Syncshells for Group {_tag}";
if (!_show)
{
_opened = false;
}
if (_show && !_opened)
{
ImGui.SetNextWindowSize(minSize);
UiSharedService.CenterNextWindow(minSize.X, minSize.Y, ImGuiCond.Always);
ImGui.OpenPopup(popupName);
_opened = true;
}
ImGui.SetNextWindowSizeConstraints(minSize, maxSize);
if (ImGui.BeginPopupModal(popupName, ref _show, ImGuiWindowFlags.Popup | ImGuiWindowFlags.Modal))
{
ImGui.TextUnformatted($"Select syncshells for group {_tag}");
ImGui.InputTextWithHint("##filter", "Filter", ref _filter, 255, ImGuiInputTextFlags.None);
foreach (var group in groups
.Where(g => string.IsNullOrEmpty(_filter) || g.GID.Contains(_filter, StringComparison.OrdinalIgnoreCase))
.OrderBy(g => g.GroupAliasOrGID, StringComparer.OrdinalIgnoreCase)
.ToList())
{
var isInGroup = _syncshellsInGroup.Contains(group.GID);
if (ImGui.Checkbox(group.GroupAliasOrGID, ref isInGroup))
{
if (isInGroup)
{
_tagHandler.AddTagToSyncshell(group.GID, _tag);
_syncshellsInGroup.Add(group.GID);
}
else
{
_tagHandler.RemoveTagFromSyncshell(group.GID, _tag);
_syncshellsInGroup.Remove(group.GID);
}
}
}
ImGui.EndPopup();
}
else
{
_filter = string.Empty;
_show = false;
}
}
public void Open(string tag)
{
_syncshellsInGroup = _tagHandler.GetOtherSyncshellsForTag(tag);
_tag = tag;
_show = true;
}
}

View File

@@ -59,7 +59,7 @@ public class SelectTagForPairUi
if (ImGui.BeginPopup(popupName)) if (ImGui.BeginPopup(popupName))
{ {
var tags = _tagHandler.GetAllTagsSorted(); var tags = _tagHandler.GetAllPairTagsSorted();
var childHeight = tags.Count != 0 ? tags.Count * 25 : 1; var childHeight = tags.Count != 0 ? tags.Count * 25 : 1;
var childSize = new Vector2(0, childHeight > 100 ? 100 : childHeight) * ImGuiHelpers.GlobalScale; var childSize = new Vector2(0, childHeight > 100 ? 100 : childHeight) * ImGuiHelpers.GlobalScale;
@@ -80,7 +80,7 @@ public class SelectTagForPairUi
HandleAddTag(); HandleAddTag();
} }
ImGui.SameLine(); ImGui.SameLine();
ImGui.InputTextWithHint("##category_name", "New Group", ref _tagNameToAdd, 40); ImGui.InputTextWithHint("##category_name", "New Group", ref _tagNameToAdd, 20);
if (ImGui.IsKeyDown(ImGuiKey.Enter)) if (ImGui.IsKeyDown(ImGuiKey.Enter))
{ {
HandleAddTag(); HandleAddTag();
@@ -101,13 +101,13 @@ public class SelectTagForPairUi
private void DrawGroupName(Pair pair, string name) private void DrawGroupName(Pair pair, string name)
{ {
var hasTagBefore = _tagHandler.HasTag(pair.UserData.UID, name); var hasTagBefore = _tagHandler.HasPairTag(pair.UserData.UID, name);
var hasTag = hasTagBefore; var hasTag = hasTagBefore;
if (ImGui.Checkbox(name, ref hasTag)) if (ImGui.Checkbox(name, ref hasTag))
{ {
if (hasTag) if (hasTag)
{ {
_tagHandler.AddTagToPairedUid(pair.UserData.UID, name); _tagHandler.AddPairTagToPairedUid(pair.UserData.UID, name);
} }
else else
{ {
@@ -120,10 +120,10 @@ public class SelectTagForPairUi
{ {
if (!_tagNameToAdd.IsNullOrWhitespace() && _tagNameToAdd is not (TagHandler.CustomOfflineTag or TagHandler.CustomOnlineTag or TagHandler.CustomVisibleTag)) if (!_tagNameToAdd.IsNullOrWhitespace() && _tagNameToAdd is not (TagHandler.CustomOfflineTag or TagHandler.CustomOnlineTag or TagHandler.CustomVisibleTag))
{ {
_tagHandler.AddTag(_tagNameToAdd); _tagHandler.AddPairTag(_tagNameToAdd);
if (_pair != null) if (_pair != null)
{ {
_tagHandler.AddTagToPairedUid(_pair.UserData.UID, _tagNameToAdd); _tagHandler.AddPairTagToPairedUid(_pair.UserData.UID, _tagNameToAdd);
} }
_tagNameToAdd = string.Empty; _tagNameToAdd = string.Empty;
} }

View File

@@ -0,0 +1,132 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Utility;
using LightlessSync.API.Dto.Group;
using LightlessSync.UI.Handlers;
using System.Numerics;
namespace LightlessSync.UI.Components;
public class SelectTagForSyncshellUi
{
private readonly TagHandler _tagHandler;
private readonly UiSharedService _uiSharedService;
/// <summary>
/// The group UI is always open for a specific pair. This defines which pair the UI is open for.
/// </summary>
/// <returns></returns>
private GroupFullInfoDto? _group;
/// <summary>
/// Should the panel show, yes/no
/// </summary>
private bool _show;
/// <summary>
/// For the add category option, this stores the currently typed in tag name
/// </summary>
private string _tagNameToAdd = "";
public SelectTagForSyncshellUi(TagHandler tagHandler, UiSharedService uiSharedService)
{
_show = false;
_group = null;
_tagHandler = tagHandler;
_uiSharedService = uiSharedService;
}
public void Draw()
{
if (_group == null)
{
return;
}
var name = _group.GroupAliasOrGID;
var popupName = $"Choose Groups for {_group.GroupAliasOrGID}";
// Is the popup supposed to show but did not open yet? Open it
if (_show)
{
ImGui.OpenPopup(popupName);
_show = false;
}
if (ImGui.BeginPopup(popupName))
{
var tags = _tagHandler.GetAllSyncshellTagsSorted();
var childHeight = tags.Count != 0 ? tags.Count * 25 : 1;
var childSize = new Vector2(0, childHeight > 100 ? 100 : childHeight) * ImGuiHelpers.GlobalScale;
ImGui.TextUnformatted($"Select the groups you want {name} to be in.");
if (ImGui.BeginChild(name + "##listGroups", childSize))
{
foreach (var tag in tags)
{
using (ImRaii.PushId($"groups-syncshell-{_group.GID}-{tag}")) DrawGroupName(_group, tag);
}
ImGui.EndChild();
}
ImGui.Separator();
ImGui.TextUnformatted($"Create a new group for {name}.");
if (_uiSharedService.IconButton(FontAwesomeIcon.Plus))
{
HandleAddTag();
}
ImGui.SameLine();
ImGui.InputTextWithHint("##category_name", "New Group", ref _tagNameToAdd, 20);
if (ImGui.IsKeyDown(ImGuiKey.Enter))
{
HandleAddTag();
}
ImGui.EndPopup();
}
}
public void Open(GroupFullInfoDto group)
{
_group = group;
// Using "_show" here to de-couple the opening of the popup
// The popup name is derived from the name the user currently sees, which is
// based on the showUidForEntry dictionary.
// We'd have to derive the name here to open it popup modal here, when the Open() is called
_show = true;
}
private void DrawGroupName(GroupFullInfoDto group, string name)
{
var hasTag = _tagHandler.HasSyncshellTag(group.GID, name);
if (ImGui.Checkbox(name, ref hasTag))
{
if (hasTag)
{
_tagHandler.AddTagToSyncshell(group.GID, name);
}
else
{
_tagHandler.RemoveTagFromSyncshell(group.GID, name);
}
}
}
private void HandleAddTag()
{
if (!_tagNameToAdd.IsNullOrWhitespace())
{
_tagHandler.AddSyncshellTag(_tagNameToAdd);
if (_group != null)
{
_tagHandler.AddTagToSyncshell(_group.GID, _tagNameToAdd);
}
_tagNameToAdd = string.Empty;
}
else
{
_tagNameToAdd = string.Empty;
}
}
}

View File

@@ -371,7 +371,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
UiSharedService.DrawGroupedCenteredColorText("Important Note: If you need to fix an animation that should apply across multiple jobs, you need to repeat this process with at least one additional job, " + UiSharedService.DrawGroupedCenteredColorText("Important Note: If you need to fix an animation that should apply across multiple jobs, you need to repeat this process with at least one additional job, " +
"otherwise the animation will only be fixed for the currently active job. This goes primarily for emotes that are used across multiple jobs.", "otherwise the animation will only be fixed for the currently active job. This goes primarily for emotes that are used across multiple jobs.",
ImGuiColors.DalamudYellow, 800); UIColors.Get("LightlessYellow"), 800);
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
UiSharedService.DrawGroupedCenteredColorText("WARNING: WHILE RECORDING TRANSIENT DATA, DO NOT CHANGE YOUR APPEARANCE, ENABLED MODS OR ANYTHING. JUST DO THE ANIMATION(S) OR WHATEVER YOU NEED DOING AND STOP THE RECORDING.", UiSharedService.DrawGroupedCenteredColorText("WARNING: WHILE RECORDING TRANSIENT DATA, DO NOT CHANGE YOUR APPEARANCE, ENABLED MODS OR ANYTHING. JUST DO THE ANIMATION(S) OR WHATEVER YOU NEED DOING AND STOP THE RECORDING.",
ImGuiColors.DalamudRed, 800); ImGuiColors.DalamudRed, 800);
@@ -399,7 +399,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
if (_transientResourceManager.IsTransientRecording) if (_transientResourceManager.IsTransientRecording)
{ {
ImGui.SameLine(); ImGui.SameLine();
UiSharedService.ColorText($"RECORDING - Time Remaining: {_transientResourceManager.RecordTimeRemaining.Value}", ImGuiColors.DalamudYellow); UiSharedService.ColorText($"RECORDING - Time Remaining: {_transientResourceManager.RecordTimeRemaining.Value}", UIColors.Get("LightlessYellow"));
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
UiSharedService.DrawGroupedCenteredColorText("DO NOT CHANGE YOUR APPEARANCE OR MODS WHILE RECORDING, YOU CAN ACCIDENTALLY MAKE SOME OF YOUR APPEARANCE RELATED MODS PERMANENT.", ImGuiColors.DalamudRed, 800); UiSharedService.DrawGroupedCenteredColorText("DO NOT CHANGE YOUR APPEARANCE OR MODS WHILE RECORDING, YOU CAN ACCIDENTALLY MAKE SOME OF YOUR APPEARANCE RELATED MODS PERMANENT.", ImGuiColors.DalamudRed, 800);
} }
@@ -422,7 +422,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
if (_transientResourceManager.RecordedTransients.Any(k => !k.AlreadyTransient)) if (_transientResourceManager.RecordedTransients.Any(k => !k.AlreadyTransient))
{ {
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
UiSharedService.DrawGroupedCenteredColorText("Please review the recorded mod files before saving and deselect files that got into the recording on accident.", ImGuiColors.DalamudYellow); UiSharedService.DrawGroupedCenteredColorText("Please review the recorded mod files before saving and deselect files that got into the recording on accident.", UIColors.Get("LightlessYellow"));
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
} }
@@ -485,7 +485,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
if (isAnalyzing) if (isAnalyzing)
{ {
UiSharedService.ColorTextWrapped($"Analyzing {_characterAnalyzer.CurrentFile}/{_characterAnalyzer.TotalFiles}", UiSharedService.ColorTextWrapped($"Analyzing {_characterAnalyzer.CurrentFile}/{_characterAnalyzer.TotalFiles}",
ImGuiColors.DalamudYellow); UIColors.Get("LightlessYellow"));
if (_uiSharedService.IconTextButton(FontAwesomeIcon.StopCircle, "Cancel analysis")) if (_uiSharedService.IconTextButton(FontAwesomeIcon.StopCircle, "Cancel analysis"))
{ {
_characterAnalyzer.CancelAnalyze(); _characterAnalyzer.CancelAnalyze();
@@ -496,7 +496,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
if (_cachedAnalysis!.Any(c => c.Value.Any(f => !f.Value.IsComputed))) if (_cachedAnalysis!.Any(c => c.Value.Any(f => !f.Value.IsComputed)))
{ {
UiSharedService.ColorTextWrapped("Some entries in the analysis have file size not determined yet, press the button below to analyze your current data", UiSharedService.ColorTextWrapped("Some entries in the analysis have file size not determined yet, press the button below to analyze your current data",
ImGuiColors.DalamudYellow); UIColors.Get("LightlessYellow"));
if (_uiSharedService.IconTextButton(FontAwesomeIcon.PlayCircle, "Start analysis (missing entries)")) if (_uiSharedService.IconTextButton(FontAwesomeIcon.PlayCircle, "Start analysis (missing entries)"))
{ {
_ = _characterAnalyzer.ComputeAnalysis(print: false); _ = _characterAnalyzer.ComputeAnalysis(print: false);
@@ -592,7 +592,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
{ {
UiSharedService.ColorText($"You exceed your own threshold by " + UiSharedService.ColorText($"You exceed your own threshold by " +
$"{UiSharedService.ByteToString(actualVramUsage - (currentVramWarning * 1024 * 1024))}.", $"{UiSharedService.ByteToString(actualVramUsage - (currentVramWarning * 1024 * 1024))}.",
ImGuiColors.DalamudYellow); UIColors.Get("LightlessYellow"));
} }
} }
} }
@@ -609,7 +609,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
{ {
UiSharedService.ColorText($"You exceed your own threshold by " + UiSharedService.ColorText($"You exceed your own threshold by " +
$"{actualTriCount - (currentTriWarning * 1000)} triangles.", $"{actualTriCount - (currentTriWarning * 1000)} triangles.",
ImGuiColors.DalamudYellow); UIColors.Get("LightlessYellow"));
} }
} }
@@ -629,7 +629,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
{ {
string fileGroupText = fileGroup.Key + " [" + fileGroup.Count() + "]"; string fileGroupText = fileGroup.Key + " [" + fileGroup.Count() + "]";
var requiresCompute = fileGroup.Any(k => !k.IsComputed); var requiresCompute = fileGroup.Any(k => !k.IsComputed);
using var tabcol = ImRaii.PushColor(ImGuiCol.Tab, UiSharedService.Color(ImGuiColors.DalamudYellow), requiresCompute); using var tabcol = ImRaii.PushColor(ImGuiCol.Tab, UiSharedService.Color(UIColors.Get("LightlessYellow")), requiresCompute);
if (requiresCompute) if (requiresCompute)
{ {
fileGroupText += " (!)"; fileGroupText += " (!)";
@@ -668,7 +668,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
ImGui.Checkbox("Enable BC7 Conversion Mode", ref _enableBc7ConversionMode); ImGui.Checkbox("Enable BC7 Conversion Mode", ref _enableBc7ConversionMode);
if (_enableBc7ConversionMode) if (_enableBc7ConversionMode)
{ {
UiSharedService.ColorText("WARNING BC7 CONVERSION:", ImGuiColors.DalamudYellow); UiSharedService.ColorText("WARNING BC7 CONVERSION:", UIColors.Get("LightlessYellow"));
ImGui.SameLine(); ImGui.SameLine();
UiSharedService.ColorText("Converting textures to BC7 is irreversible!", ImGuiColors.DalamudRed); UiSharedService.ColorText("Converting textures to BC7 is irreversible!", ImGuiColors.DalamudRed);
UiSharedService.ColorTextWrapped("- Converting textures to BC7 will reduce their size (compressed and uncompressed) drastically. It is recommended to be used for large (4k+) textures." + UiSharedService.ColorTextWrapped("- Converting textures to BC7 will reduce their size (compressed and uncompressed) drastically. It is recommended to be used for large (4k+) textures." +
@@ -676,7 +676,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
Environment.NewLine + "- Before converting textures, make sure to have the original files of the mod you are converting so you can reimport it in case of issues." + Environment.NewLine + "- Before converting textures, make sure to have the original files of the mod you are converting so you can reimport it in case of issues." +
Environment.NewLine + "- Conversion will convert all found texture duplicates (entries with more than 1 file path) automatically." + Environment.NewLine + "- Conversion will convert all found texture duplicates (entries with more than 1 file path) automatically." +
Environment.NewLine + "- Converting textures to BC7 is a very expensive operation and, depending on the amount of textures to convert, will take a while to complete." Environment.NewLine + "- Converting textures to BC7 is a very expensive operation and, depending on the amount of textures to convert, will take a while to complete."
, ImGuiColors.DalamudYellow); , UIColors.Get("LightlessYellow"));
if (_texturesToConvert.Count > 0 && _uiSharedService.IconTextButton(FontAwesomeIcon.PlayCircle, "Start conversion of " + _texturesToConvert.Count + " texture(s)")) if (_texturesToConvert.Count > 0 && _uiSharedService.IconTextButton(FontAwesomeIcon.PlayCircle, "Start conversion of " + _texturesToConvert.Count + " texture(s)"))
{ {
_conversionCancellationTokenSource = _conversionCancellationTokenSource.CancelRecreate(); _conversionCancellationTokenSource = _conversionCancellationTokenSource.CancelRecreate();
@@ -697,7 +697,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
ImGui.TextUnformatted("Selected file:"); ImGui.TextUnformatted("Selected file:");
ImGui.SameLine(); ImGui.SameLine();
UiSharedService.ColorText(_selectedHash, ImGuiColors.DalamudYellow); UiSharedService.ColorText(_selectedHash, UIColors.Get("LightlessYellow"));
if (_cachedAnalysis[_selectedObjectTab].TryGetValue(_selectedHash, out CharacterAnalyzer.FileDataEntry? item)) if (_cachedAnalysis[_selectedObjectTab].TryGetValue(_selectedHash, out CharacterAnalyzer.FileDataEntry? item))
{ {
@@ -823,8 +823,8 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
} }
if (string.Equals(_selectedHash, item.Hash, StringComparison.Ordinal)) if (string.Equals(_selectedHash, item.Hash, StringComparison.Ordinal))
{ {
ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg1, UiSharedService.Color(ImGuiColors.DalamudYellow)); ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg1, UiSharedService.Color(UIColors.Get("LightlessYellow")));
ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg0, UiSharedService.Color(ImGuiColors.DalamudYellow)); ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg0, UiSharedService.Color(UIColors.Get("LightlessYellow")));
} }
ImGui.TextUnformatted(item.Hash); ImGui.TextUnformatted(item.Hash);
if (ImGui.IsItemClicked()) _selectedHash = item.Hash; if (ImGui.IsItemClicked()) _selectedHash = item.Hash;

View File

@@ -23,21 +23,25 @@ public class DrawEntityFactory
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService; private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
private readonly CharaDataManager _charaDataManager; private readonly CharaDataManager _charaDataManager;
private readonly SelectTagForPairUi _selectTagForPairUi; private readonly SelectTagForPairUi _selectTagForPairUi;
private readonly RenameTagUi _renameTagUi; private readonly RenamePairTagUi _renamePairTagUi;
private readonly SelectTagForSyncshellUi _selectTagForSyncshellUi;
private readonly RenameSyncshellTagUi _renameSyncshellTagUi;
private readonly SelectSyncshellForTagUi _selectSyncshellForTagUi;
private readonly TagHandler _tagHandler; private readonly TagHandler _tagHandler;
private readonly IdDisplayHandler _uidDisplayHandler; private readonly IdDisplayHandler _uidDisplayHandler;
public DrawEntityFactory(ILogger<DrawEntityFactory> logger, ApiController apiController, IdDisplayHandler uidDisplayHandler, public DrawEntityFactory(ILogger<DrawEntityFactory> logger, ApiController apiController, IdDisplayHandler uidDisplayHandler,
SelectTagForPairUi selectTagForPairUi, RenameTagUi renameTagUi, LightlessMediator mediator, SelectTagForPairUi selectTagForPairUi, RenamePairTagUi renamePairTagUi, LightlessMediator mediator,
TagHandler tagHandler, SelectPairForTagUi selectPairForTagUi, TagHandler tagHandler, SelectPairForTagUi selectPairForTagUi,
ServerConfigurationManager serverConfigurationManager, UiSharedService uiSharedService, ServerConfigurationManager serverConfigurationManager, UiSharedService uiSharedService,
PlayerPerformanceConfigService playerPerformanceConfigService, CharaDataManager charaDataManager) PlayerPerformanceConfigService playerPerformanceConfigService, CharaDataManager charaDataManager,
SelectTagForSyncshellUi selectTagForSyncshellUi, RenameSyncshellTagUi renameSyncshellTagUi, SelectSyncshellForTagUi selectSyncshellForTagUi)
{ {
_logger = logger; _logger = logger;
_apiController = apiController; _apiController = apiController;
_uidDisplayHandler = uidDisplayHandler; _uidDisplayHandler = uidDisplayHandler;
_selectTagForPairUi = selectTagForPairUi; _selectTagForPairUi = selectTagForPairUi;
_renameTagUi = renameTagUi; _renamePairTagUi = renamePairTagUi;
_mediator = mediator; _mediator = mediator;
_tagHandler = tagHandler; _tagHandler = tagHandler;
_selectPairForTagUi = selectPairForTagUi; _selectPairForTagUi = selectPairForTagUi;
@@ -45,6 +49,9 @@ public class DrawEntityFactory
_uiSharedService = uiSharedService; _uiSharedService = uiSharedService;
_playerPerformanceConfigService = playerPerformanceConfigService; _playerPerformanceConfigService = playerPerformanceConfigService;
_charaDataManager = charaDataManager; _charaDataManager = charaDataManager;
_selectTagForSyncshellUi = selectTagForSyncshellUi;
_renameSyncshellTagUi = renameSyncshellTagUi;
_selectSyncshellForTagUi = selectSyncshellForTagUi;
} }
public DrawFolderGroup CreateDrawGroupFolder(GroupFullInfoDto groupFullInfoDto, public DrawFolderGroup CreateDrawGroupFolder(GroupFullInfoDto groupFullInfoDto,
@@ -53,7 +60,16 @@ public class DrawEntityFactory
{ {
return new DrawFolderGroup(groupFullInfoDto.Group.GID, groupFullInfoDto, _apiController, return new DrawFolderGroup(groupFullInfoDto.Group.GID, groupFullInfoDto, _apiController,
filteredPairs.Select(p => CreateDrawPair(groupFullInfoDto.Group.GID + p.Key.UserData.UID, p.Key, p.Value, groupFullInfoDto)).ToImmutableList(), filteredPairs.Select(p => CreateDrawPair(groupFullInfoDto.Group.GID + p.Key.UserData.UID, p.Key, p.Value, groupFullInfoDto)).ToImmutableList(),
allPairs, _tagHandler, _uidDisplayHandler, _mediator, _uiSharedService); allPairs, _tagHandler, _uidDisplayHandler, _mediator, _uiSharedService, _selectTagForSyncshellUi);
}
public DrawFolderGroup CreateDrawGroupFolder(string id, GroupFullInfoDto groupFullInfoDto,
Dictionary<Pair, List<GroupFullInfoDto>> filteredPairs,
IImmutableList<Pair> allPairs)
{
return new DrawFolderGroup(id, groupFullInfoDto, _apiController,
filteredPairs.Select(p => CreateDrawPair(groupFullInfoDto.Group.GID + p.Key.UserData.UID, p.Key, p.Value, groupFullInfoDto)).ToImmutableList(),
allPairs, _tagHandler, _uidDisplayHandler, _mediator, _uiSharedService, _selectTagForSyncshellUi);
} }
public DrawFolderTag CreateDrawTagFolder(string tag, public DrawFolderTag CreateDrawTagFolder(string tag,
@@ -61,7 +77,7 @@ public class DrawEntityFactory
IImmutableList<Pair> allPairs) IImmutableList<Pair> allPairs)
{ {
return new(tag, filteredPairs.Select(u => CreateDrawPair(tag, u.Key, u.Value, currentGroup: null)).ToImmutableList(), return new(tag, filteredPairs.Select(u => CreateDrawPair(tag, u.Key, u.Value, currentGroup: null)).ToImmutableList(),
allPairs, _tagHandler, _apiController, _selectPairForTagUi, _renameTagUi, _uiSharedService); allPairs, _tagHandler, _apiController, _selectPairForTagUi, _renamePairTagUi, _uiSharedService);
} }
public DrawUserPair CreateDrawPair(string id, Pair user, List<GroupFullInfoDto> groups, GroupFullInfoDto? currentGroup) public DrawUserPair CreateDrawPair(string id, Pair user, List<GroupFullInfoDto> groups, GroupFullInfoDto? currentGroup)

View File

@@ -6,7 +6,9 @@ using LightlessSync.LightlessConfiguration;
using LightlessSync.LightlessConfiguration.Configurations; using LightlessSync.LightlessConfiguration.Configurations;
using LightlessSync.PlayerData.Pairs; using LightlessSync.PlayerData.Pairs;
using LightlessSync.Services.Mediator; using LightlessSync.Services.Mediator;
using LightlessSync.Services.ServerConfiguration;
using LightlessSync.WebAPI; using LightlessSync.WebAPI;
using LightlessSync.WebAPI.SignalR.Utils;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -16,6 +18,7 @@ namespace LightlessSync.UI;
public sealed class DtrEntry : IDisposable, IHostedService public sealed class DtrEntry : IDisposable, IHostedService
{ {
private readonly ApiController _apiController; private readonly ApiController _apiController;
private readonly ServerConfigurationManager _serverManager;
private readonly CancellationTokenSource _cancellationTokenSource = new(); private readonly CancellationTokenSource _cancellationTokenSource = new();
private readonly ConfigurationServiceBase<LightlessConfig> _configService; private readonly ConfigurationServiceBase<LightlessConfig> _configService;
private readonly IDtrBar _dtrBar; private readonly IDtrBar _dtrBar;
@@ -28,7 +31,7 @@ public sealed class DtrEntry : IDisposable, IHostedService
private string? _tooltip; private string? _tooltip;
private Colors _colors; private Colors _colors;
public DtrEntry(ILogger<DtrEntry> logger, IDtrBar dtrBar, ConfigurationServiceBase<LightlessConfig> configService, LightlessMediator lightlessMediator, PairManager pairManager, ApiController apiController) public DtrEntry(ILogger<DtrEntry> logger, IDtrBar dtrBar, ConfigurationServiceBase<LightlessConfig> configService, LightlessMediator lightlessMediator, PairManager pairManager, ApiController apiController, ServerConfigurationManager serverManager)
{ {
_logger = logger; _logger = logger;
_dtrBar = dtrBar; _dtrBar = dtrBar;
@@ -37,6 +40,7 @@ public sealed class DtrEntry : IDisposable, IHostedService
_lightlessMediator = lightlessMediator; _lightlessMediator = lightlessMediator;
_pairManager = pairManager; _pairManager = pairManager;
_apiController = apiController; _apiController = apiController;
_serverManager = serverManager;
} }
public void Dispose() public void Dispose()
@@ -59,7 +63,7 @@ public sealed class DtrEntry : IDisposable, IHostedService
public async Task StopAsync(CancellationToken cancellationToken) public async Task StopAsync(CancellationToken cancellationToken)
{ {
_cancellationTokenSource.Cancel(); await _cancellationTokenSource.CancelAsync().ConfigureAwait(false);
try try
{ {
await _runTask!.ConfigureAwait(false); await _runTask!.ConfigureAwait(false);
@@ -89,10 +93,43 @@ public sealed class DtrEntry : IDisposable, IHostedService
{ {
_logger.LogTrace("Creating new DtrBar entry"); _logger.LogTrace("Creating new DtrBar entry");
var entry = _dtrBar.Get("Lightless Sync"); var entry = _dtrBar.Get("Lightless Sync");
entry.OnClick = _ => _lightlessMediator.Publish(new UiToggleMessage(typeof(CompactUi))); entry.OnClick = interactionEvent => OnClickEvent(interactionEvent);
return entry; return entry;
} }
private void OnClickEvent(DtrInteractionEvent interactionEvent)
{
if (interactionEvent.ClickType.Equals(MouseClickType.Left) && !interactionEvent.ModifierKeys.Equals(ClickModifierKeys.Shift))
{
_lightlessMediator.Publish(new UiToggleMessage(typeof(CompactUi)));
}
else if (interactionEvent.ClickType.Equals(MouseClickType.Left) && interactionEvent.ModifierKeys.Equals(ClickModifierKeys.Shift))
{
_lightlessMediator.Publish(new UiToggleMessage(typeof(SettingsUi)));
}
if (interactionEvent.ClickType.Equals(MouseClickType.Right))
{
bool isConnectingOrConnected = _apiController.ServerState is ServerState.Connected or ServerState.Connecting or ServerState.Reconnecting;
if (_apiController.ServerState is not (ServerState.Reconnecting or ServerState.Disconnecting))
{
if (isConnectingOrConnected && !_serverManager.CurrentServer.FullPause)
{
_serverManager.CurrentServer.FullPause = true;
_serverManager.Save();
}
else if (!isConnectingOrConnected && _serverManager.CurrentServer.FullPause)
{
_serverManager.CurrentServer.FullPause = false;
_serverManager.Save();
}
_ = _apiController.CreateConnectionsAsync();
}
}
}
private async Task RunAsync() private async Task RunAsync()
{ {

View File

@@ -110,7 +110,7 @@ internal class EventViewerUI : WindowMediatorSubscriberBase
{ {
ImGui.SameLine(); ImGui.SameLine();
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
UiSharedService.ColorTextWrapped("New events are available, press refresh to update", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("New events are available, press refresh to update", UIColors.Get("LightlessYellow"));
} }
var buttonSize = _uiSharedService.GetIconTextButtonSize(FontAwesomeIcon.FolderOpen, "Open EventLog Folder"); var buttonSize = _uiSharedService.GetIconTextButtonSize(FontAwesomeIcon.FolderOpen, "Open EventLog Folder");
@@ -180,7 +180,7 @@ internal class EventViewerUI : WindowMediatorSubscriberBase
var iconColor = ev.EventSeverity switch var iconColor = ev.EventSeverity switch
{ {
EventSeverity.Informational => new Vector4(), EventSeverity.Informational => new Vector4(),
EventSeverity.Warning => ImGuiColors.DalamudYellow, EventSeverity.Warning => UIColors.Get("LightlessYellow"),
EventSeverity.Error => ImGuiColors.DalamudRed, EventSeverity.Error => ImGuiColors.DalamudRed,
_ => new Vector4() _ => new Vector4()
}; };

View File

@@ -43,9 +43,9 @@ public class IdDisplayHandler
if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) if (ImGui.IsItemClicked(ImGuiMouseButton.Left))
{ {
var prevState = textIsUid; var prevState = textIsUid;
if (_showIdForEntry.ContainsKey(group.GID)) if (_showIdForEntry.TryGetValue(group.GID, out bool value))
{ {
prevState = _showIdForEntry[group.GID]; prevState = value;
} }
_showIdForEntry[group.GID] = !prevState; _showIdForEntry[group.GID] = !prevState;
} }

View File

@@ -17,61 +17,146 @@ public class TagHandler
_serverConfigurationManager = serverConfigurationManager; _serverConfigurationManager = serverConfigurationManager;
} }
public void AddTag(string tag) /// <summary>
{ /// Creation of an pair tag
_serverConfigurationManager.AddTag(tag); /// </summary>
} /// <param name="tag">Name of the tag</param>
public void AddPairTag(string tag) => _serverConfigurationManager.AddPairTag(tag);
public void AddTagToPairedUid(string uid, string tagName) /// <summary>
{ /// Creation of an syncshell tag
_serverConfigurationManager.AddTagForUid(uid, tagName); /// </summary>
} /// <param name="tag">Name of the tag</param>
public void AddSyncshellTag(string tag) => _serverConfigurationManager.AddSyncshellTag(tag);
public List<string> GetAllTagsSorted() /// <summary>
{ /// Add pair to tag
return /// </summary>
[ /// <param name="uid">UID that will be added to tag/param>
/// <param name="tagName">Name of the tag</param>
public void AddPairTagToPairedUid(string uid, string tagName) => _serverConfigurationManager.AddTagForUid(uid, tagName);
/// <summary>
/// Add syncshell to tag
/// </summary>
/// <param name="name">Syncshell that will be added to tag/param>
/// <param name="tagName">Name of the tag</param>
public void AddTagToSyncshell(string name, string tagName) => _serverConfigurationManager.AddTagForSyncshell(name, tagName);
/// <summary>
/// Get all pair tags
/// </summary>
public List<string> GetAllPairTagsSorted() => [
.. _serverConfigurationManager.GetServerAvailablePairTags() .. _serverConfigurationManager.GetServerAvailablePairTags()
.OrderBy(s => s, StringComparer.OrdinalIgnoreCase) .Order(StringComparer.OrdinalIgnoreCase)
, ,
]; ];
}
public HashSet<string> GetOtherUidsForTag(string tag) /// <summary>
{ /// Get all syncshell tags
return _serverConfigurationManager.GetUidsForTag(tag); /// </summary>
} public List<string> GetAllSyncshellTagsSorted() => [
.. _serverConfigurationManager.GetServerAvailableSyncshellTags()
.Order(StringComparer.OrdinalIgnoreCase)
,
];
public bool HasAnyTag(string uid) /// <summary>
{ /// Get all UIDs bound to an given tag
return _serverConfigurationManager.HasTags(uid); /// </summary>
} /// <param name="name">Name of the tag</param>
public HashSet<string> GetOtherUidsForTag(string tag) => _serverConfigurationManager.GetUidsForPairTag(tag);
public bool HasTag(string uid, string tagName) /// <summary>
{ /// Get all syncshells bound to an given tag
return _serverConfigurationManager.ContainsTag(uid, tagName); /// </summary>
} /// <param name="name">Name of the tag</param>
public HashSet<string> GetOtherSyncshellsForTag(string tag) => _serverConfigurationManager.GetNamesForSyncshellTag(tag);
/// <summary>
/// Checking if the UID is connected to any tag
/// </summary>
/// <param name="uid">Syncshell that needs to be checked</param>
public bool HasAnyPairTag(string uid) => _serverConfigurationManager.HasPairTags(uid);
/// <summary>
/// Checking if the syncshell is connected to the tag
/// </summary>
/// <param name="name">Syncshell that needs to be checked</param>
public bool HasAnySyncshellTag(string name) => _serverConfigurationManager.HasSyncshellTags(name);
/// <summary>
/// Checking if the UID is connected to the tag
/// </summary>
/// <param name="uid">UID that needs to be checked</param>
/// <param name="tagName">Name of the tag</param>
public bool HasPairTag(string uid, string tagName) => _serverConfigurationManager.ContainsPairTag(uid, tagName);
/// <summary>
/// Checking if the syncshell is connected to the tag
/// </summary>
/// <param name="name">Syncshell that needs to be checked</param>
/// <param name="tagName">Name of the tag</param>
public bool HasSyncshellTag(string name, string tagName) => _serverConfigurationManager.ContainsSyncshellTag(name, tagName);
/// <summary> /// <summary>
/// Is this tag opened in the paired clients UI? /// Is this tag opened in the paired clients UI?
/// </summary> /// </summary>
/// <param name="tag">the tag</param> /// <param name="tag">the tag</param>
/// <returns>open true/false</returns> /// <returns>open true/false</returns>
public bool IsTagOpen(string tag) public bool IsTagOpen(string tag) => _serverConfigurationManager.ContainsOpenPairTag(tag);
/// <summary>
/// Removal of Pair Tags from Storage
/// </summary>
/// <param name="tag">Name of the tag</param>
public void RemovePairTag(string tag) => _serverConfigurationManager.RemovePairTag(tag);
/// <summary>
/// Removal of Syncshell Tags from Storage
/// </summary>
/// <param name="tag">Name of the tag</param>
public void RemoveSyncshellTag(string tag) => _serverConfigurationManager.RemoveSyncshellTag(tag);
/// <summary>
/// Removal of UID in a Tag
/// </summary>
/// <param name="uid">UID of user thats bound to the tag</param>
/// <param name="tagName">Name of the tag</param>
public void RemoveTagFromPairedUid(string uid, string tagName) => _serverConfigurationManager.RemoveTagForUid(uid, tagName);
/// <summary>
/// Removal of Syncshell in a Tag
/// </summary>
/// <param name="name">Syncshell thats bound to the tag</param>
/// <param name="tagName">Name of the tag</param>
public void RemoveTagFromSyncshell(string name, string tagName) => _serverConfigurationManager.RemoveTagForSyncshell(name, tagName);
/// <summary>
/// Rename of a pair tag
/// </summary>
/// <param name="oldName">Old pair tag name</param>
/// <param name="newName">New pair tag name</param>
public void RenamePairTag(string oldName, string newName)
{ {
return _serverConfigurationManager.ContainsOpenPairTag(tag); _serverConfigurationManager.RenamePairTag(oldName, newName);
} }
public void RemoveTag(string tag) /// <summary>
/// Rename of a syncshell tag
/// </summary>
/// <param name="oldName">Old syncshell tag name</param>
/// <param name="newName">New syncshell tag name</param>
public void RenameSyncshellTag(string oldName, string newName)
{ {
_serverConfigurationManager.RemoveTag(tag); _serverConfigurationManager.RenameSyncshellTag(oldName, newName);
}
public void RemoveTagFromPairedUid(string uid, string tagName)
{
_serverConfigurationManager.RemoveTagForUid(uid, tagName);
} }
/// <summary>
/// Changes the tag to open/close
/// </summary>
/// <param name="tag">The Tag that will be modified</param>
/// <param name="open">True/False</param>
public void SetTagOpen(string tag, bool open) public void SetTagOpen(string tag, bool open)
{ {
if (open) if (open)

View File

@@ -78,7 +78,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
UiSharedService.ColorTextWrapped("Note: Any modifications you have applied through anything but Penumbra cannot be shared and your character state on other clients " + UiSharedService.ColorTextWrapped("Note: Any modifications you have applied through anything but Penumbra cannot be shared and your character state on other clients " +
"might look broken because of this or others players mods might not apply on your end altogether. " + "might look broken because of this or others players mods might not apply on your end altogether. " +
"If you want to use this plugin you will have to move your mods to Penumbra.", ImGuiColors.DalamudYellow); "If you want to use this plugin you will have to move your mods to Penumbra.", UIColors.Get("LightlessYellow"));
if (!_uiShared.DrawOtherPluginState()) return; if (!_uiShared.DrawOtherPluginState()) return;
ImGui.Separator(); ImGui.Separator();
if (ImGui.Button("Next##toAgreement")) if (ImGui.Button("Next##toAgreement"))
@@ -172,8 +172,8 @@ public partial class IntroUi : WindowMediatorSubscriberBase
"Once the storage folder is set and the scan complete, this page will automatically forward to registration at a service."); "Once the storage folder is set and the scan complete, this page will automatically forward to registration at a service.");
UiSharedService.TextWrapped("Note: The initial scan, depending on the amount of mods you have, might take a while. Please wait until it is completed."); UiSharedService.TextWrapped("Note: The initial scan, depending on the amount of mods you have, might take a while. Please wait until it is completed.");
UiSharedService.ColorTextWrapped("Warning: once past this step you should not delete the FileCache.csv of Lightless Sync in the Plugin Configurations folder of Dalamud. " + UiSharedService.ColorTextWrapped("Warning: once past this step you should not delete the FileCache.csv of Lightless Sync in the Plugin Configurations folder of Dalamud. " +
"Otherwise on the next launch a full re-scan of the file cache database will be initiated.", ImGuiColors.DalamudYellow); "Otherwise on the next launch a full re-scan of the file cache database will be initiated.", UIColors.Get("LightlessYellow"));
UiSharedService.ColorTextWrapped("Warning: if the scan is hanging and does nothing for a long time, chances are high your Penumbra folder is not set up properly.", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("Warning: if the scan is hanging and does nothing for a long time, chances are high your Penumbra folder is not set up properly.", UIColors.Get("LightlessYellow"));
_uiShared.DrawCacheDirectorySetting(); _uiShared.DrawCacheDirectorySetting();
} }
@@ -197,7 +197,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
_configService.Save(); _configService.Save();
} }
UiSharedService.ColorTextWrapped("The File Compactor can save a tremendeous amount of space on the hard disk for downloads through Lightless. It will incur a minor CPU penalty on download but can speed up " + UiSharedService.ColorTextWrapped("The File Compactor can save a tremendeous amount of space on the hard disk for downloads through Lightless. It will incur a minor CPU penalty on download but can speed up " +
"loading of other characters. It is recommended to keep it enabled. You can change this setting later anytime in the Lightless settings.", ImGuiColors.DalamudYellow); "loading of other characters. It is recommended to keep it enabled. You can change this setting later anytime in the Lightless settings.", UIColors.Get("LightlessYellow"));
} }
} }
else if (!_uiShared.ApiController.ServerAlive) else if (!_uiShared.ApiController.ServerAlive)
@@ -255,7 +255,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
UiSharedService.DrawGroupedCenteredColorText("Strongly consider to use OAuth2 to authenticate, if the server supports it (the current main server does). " + UiSharedService.DrawGroupedCenteredColorText("Strongly consider to use OAuth2 to authenticate, if the server supports it (the current main server does). " +
"The authentication flow is simpler and you do not require to store or maintain Secret Keys. " + "The authentication flow is simpler and you do not require to store or maintain Secret Keys. " +
"You already implicitly register using Discord, so the OAuth2 method will be cleaner and more straight-forward to use.", ImGuiColors.DalamudYellow, 500); "You already implicitly register using Discord, so the OAuth2 method will be cleaner and more straight-forward to use.", UIColors.Get("LightlessYellow"), 500);
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();

View File

@@ -88,7 +88,7 @@ internal class JoinSyncshellUI : WindowMediatorSubscriberBase
UiSharedService.ColorTextWrapped("Failed to join the Syncshell. This is due to one of following reasons:" + Environment.NewLine + UiSharedService.ColorTextWrapped("Failed to join the Syncshell. This is due to one of following reasons:" + Environment.NewLine +
"- The Syncshell does not exist or the password is incorrect" + Environment.NewLine + "- The Syncshell does not exist or the password is incorrect" + Environment.NewLine +
"- You are already in that Syncshell or are banned from that Syncshell" + Environment.NewLine + "- You are already in that Syncshell or are banned from that Syncshell" + Environment.NewLine +
"- The Syncshell is at capacity or has invites disabled" + Environment.NewLine, ImGuiColors.DalamudYellow); "- The Syncshell is at capacity or has invites disabled" + Environment.NewLine, UIColors.Get("LightlessYellow"));
} }
} }
else else
@@ -111,7 +111,7 @@ internal class JoinSyncshellUI : WindowMediatorSubscriberBase
|| _groupJoinInfo.GroupPermissions.IsPreferDisableAnimations() != _ownPermissions.DisableGroupAnimations) || _groupJoinInfo.GroupPermissions.IsPreferDisableAnimations() != _ownPermissions.DisableGroupAnimations)
{ {
ImGuiHelpers.ScaledDummy(2f); ImGuiHelpers.ScaledDummy(2f);
UiSharedService.ColorText("Your current preferred default Syncshell permissions deviate from the suggested permissions:", ImGuiColors.DalamudYellow); UiSharedService.ColorText("Your current preferred default Syncshell permissions deviate from the suggested permissions:", UIColors.Get("LightlessYellow"));
if (_groupJoinInfo.GroupPermissions.IsPreferDisableSounds() != _ownPermissions.DisableGroupSounds) if (_groupJoinInfo.GroupPermissions.IsPreferDisableSounds() != _ownPermissions.DisableGroupSounds)
{ {
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();

View File

@@ -135,12 +135,12 @@ public class PopoutProfileUi : WindowMediatorSubscriberBase
if (_pair.UserPair.OwnPermissions.IsPaused()) if (_pair.UserPair.OwnPermissions.IsPaused())
{ {
ImGui.SameLine(); ImGui.SameLine();
UiSharedService.ColorText("You: paused", ImGuiColors.DalamudYellow); UiSharedService.ColorText("You: paused", UIColors.Get("LightlessYellow"));
} }
if (_pair.UserPair.OtherPermissions.IsPaused()) if (_pair.UserPair.OtherPermissions.IsPaused())
{ {
ImGui.SameLine(); ImGui.SameLine();
UiSharedService.ColorText("They: paused", ImGuiColors.DalamudYellow); UiSharedService.ColorText("They: paused", UIColors.Get("LightlessYellow"));
} }
} }
if (_pair.UserPair.Groups.Any()) if (_pair.UserPair.Groups.Any())

View File

@@ -98,7 +98,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
_uiShared = uiShared; _uiShared = uiShared;
_nameplateService = nameplateService; _nameplateService = nameplateService;
AllowClickthrough = false; AllowClickthrough = false;
AllowPinning = false; AllowPinning = true;
_validationProgress = new Progress<(int, int, FileCacheEntity)>(v => _currentProgress = v); _validationProgress = new Progress<(int, int, FileCacheEntity)>(v => _currentProgress = v);
SizeConstraints = new WindowSizeConstraints() SizeConstraints = new WindowSizeConstraints()
@@ -373,8 +373,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
} }
else if (!_speedTestTask.IsCompleted) else if (!_speedTestTask.IsCompleted)
{ {
UiSharedService.ColorTextWrapped("Running Speedtest to File Servers...", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("Running Speedtest to File Servers...", UIColors.Get("LightlessYellow"));
UiSharedService.ColorTextWrapped("Please be patient, depending on usage and load this can take a while.", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("Please be patient, depending on usage and load this can take a while.", UIColors.Get("LightlessYellow"));
if (_uiShared.IconTextButton(FontAwesomeIcon.Ban, "Cancel speedtest")) if (_uiShared.IconTextButton(FontAwesomeIcon.Ban, "Cancel speedtest"))
{ {
_speedTestCts?.Cancel(); _speedTestCts?.Cancel();
@@ -393,7 +393,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
} }
else else
{ {
UiSharedService.ColorTextWrapped("Speedtest completed with no results", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("Speedtest completed with no results", UIColors.Get("LightlessYellow"));
} }
} }
} }
@@ -637,7 +637,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
ImGuiHelpers.ScaledDummy(10); ImGuiHelpers.ScaledDummy(10);
UiSharedService.ColorTextWrapped("Exporting MCDF has moved.", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("Exporting MCDF has moved.", UIColors.Get("LightlessYellow"));
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
UiSharedService.TextWrapped("It is now found in the Main UI under \"Your User Menu\" ("); UiSharedService.TextWrapped("It is now found in the Main UI under \"Your User Menu\" (");
ImGui.SameLine(); ImGui.SameLine();
@@ -720,7 +720,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
bool isLinux = _dalamudUtilService.IsWine; bool isLinux = _dalamudUtilService.IsWine;
if (!useFileCompactor && !isLinux) if (!useFileCompactor && !isLinux)
{ {
UiSharedService.ColorTextWrapped("Hint: To free up space when using Lightless consider enabling the File Compactor", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("Hint: To free up space when using Lightless consider enabling the File Compactor", UIColors.Get("LightlessYellow"));
} }
if (isLinux || !_cacheMonitor.StorageisNTFS) ImGui.BeginDisabled(); if (isLinux || !_cacheMonitor.StorageisNTFS) ImGui.BeginDisabled();
if (ImGui.Checkbox("Use file compactor", ref useFileCompactor)) if (ImGui.Checkbox("Use file compactor", ref useFileCompactor))
@@ -756,7 +756,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
} }
else else
{ {
UiSharedService.ColorText($"File compactor currently running ({_fileCompactor.Progress})", ImGuiColors.DalamudYellow); UiSharedService.ColorText($"File compactor currently running ({_fileCompactor.Progress})", UIColors.Get("LightlessYellow"));
} }
if (isLinux || !_cacheMonitor.StorageisNTFS) if (isLinux || !_cacheMonitor.StorageisNTFS)
{ {
@@ -974,37 +974,98 @@ public class SettingsUi : WindowMediatorSubscriberBase
_configService.Save(); _configService.Save();
} }
if (ImGui.Checkbox("Color-code the Server Info Bar entry according to status", ref useColorsInDtr)) }
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
if (_uiShared.MediumTreeNode("Colors", UIColors.Get("LightlessPurple")))
{
ImGui.TextUnformatted("UI Theme Colors");
var colorNames = new[]
{
("LightlessPurple", "Lightless Purple", "Primary colors"),
("LightlessBlue", "Lightless Blue", "Secondary colors"),
("LightlessYellow", "Lightless Yellow", "Warning colors"),
("PairBlue", "Pair Blue", "Pair UI elements"),
("DimRed", "Dim Red", "Error and offline")
};
foreach (var (colorKey, displayName, description) in colorNames)
{
var currentColor = UIColors.Get(colorKey);
var colorToEdit = currentColor;
ImGui.AlignTextToFramePadding();
if (ImGui.ColorEdit4($"##color_{colorKey}", ref colorToEdit, ImGuiColorEditFlags.NoInputs | ImGuiColorEditFlags.AlphaPreviewHalf))
{ {
_configService.Current.UseColorsInDtr = useColorsInDtr; UIColors.Set(colorKey, colorToEdit);
}
ImGui.SameLine();
ImGui.TextUnformatted($"{displayName} - {description}");
if (UIColors.IsCustom(colorKey))
{
ImGui.SameLine();
if (_uiShared.IconTextButton(FontAwesomeIcon.Undo, $"Reset {colorKey}"))
{
UIColors.Reset(colorKey);
}
UiSharedService.AttachToolTip("Reset this color to default");
}
}
ImGui.Spacing();
if (_uiShared.IconTextButton(FontAwesomeIcon.Undo, "Reset All Theme Colors"))
{
UIColors.ResetAll();
}
_uiShared.DrawHelpText("This will reset all theme colors to their default values");
ImGui.Spacing();
ImGui.TextUnformatted("Server Info Bar Colors");
if (ImGui.Checkbox("Color-code the Server Info Bar entry according to status", ref useColorsInDtr))
{
_configService.Current.UseColorsInDtr = useColorsInDtr;
_configService.Save();
}
_uiShared.DrawHelpText("This will color the Server Info Bar entry based on connection status and visible pairs.");
using (ImRaii.Disabled(!useColorsInDtr))
{
using var indent = ImRaii.PushIndent();
if (InputDtrColors("Default", ref dtrColorsDefault))
{
_configService.Current.DtrColorsDefault = dtrColorsDefault;
_configService.Save(); _configService.Save();
} }
using (ImRaii.Disabled(!useColorsInDtr)) ImGui.SameLine();
if (InputDtrColors("Not Connected", ref dtrColorsNotConnected))
{ {
using var indent2 = ImRaii.PushIndent(); _configService.Current.DtrColorsNotConnected = dtrColorsNotConnected;
if (InputDtrColors("Default", ref dtrColorsDefault)) _configService.Save();
{ }
_configService.Current.DtrColorsDefault = dtrColorsDefault;
_configService.Save();
}
ImGui.SameLine(); ImGui.SameLine();
if (InputDtrColors("Not Connected", ref dtrColorsNotConnected)) if (InputDtrColors("Pairs in Range", ref dtrColorsPairsInRange))
{ {
_configService.Current.DtrColorsNotConnected = dtrColorsNotConnected; _configService.Current.DtrColorsPairsInRange = dtrColorsPairsInRange;
_configService.Save(); _configService.Save();
}
ImGui.SameLine();
if (InputDtrColors("Pairs in Range", ref dtrColorsPairsInRange))
{
_configService.Current.DtrColorsPairsInRange = dtrColorsPairsInRange;
_configService.Save();
}
} }
} }
ImGui.Spacing();
ImGui.TextUnformatted("Nameplate Colors");
var nameColorsEnabled = _configService.Current.IsNameplateColorsEnabled; var nameColorsEnabled = _configService.Current.IsNameplateColorsEnabled;
var nameColors = _configService.Current.NameplateColors; var nameColors = _configService.Current.NameplateColors;
var isFriendOverride = _configService.Current.overrideFriendColor; var isFriendOverride = _configService.Current.overrideFriendColor;
@@ -1016,6 +1077,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
_configService.Save(); _configService.Save();
_nameplateService.RequestRedraw(); _nameplateService.RequestRedraw();
} }
_uiShared.DrawHelpText("This will override the nameplate colors for visible paired players in-game.");
using (ImRaii.Disabled(!nameColorsEnabled)) using (ImRaii.Disabled(!nameColorsEnabled))
{ {
@@ -1119,7 +1181,6 @@ public class SettingsUi : WindowMediatorSubscriberBase
_configService.Current.UseFocusTarget = useFocusTarget; _configService.Current.UseFocusTarget = useFocusTarget;
_configService.Save(); _configService.Save();
} }
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f); _uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop(); ImGui.TreePop();
} }
@@ -1318,9 +1379,18 @@ public class SettingsUi : WindowMediatorSubscriberBase
bool autoPause = _playerPerformanceConfigService.Current.AutoPausePlayersExceedingThresholds; bool autoPause = _playerPerformanceConfigService.Current.AutoPausePlayersExceedingThresholds;
bool autoPauseEveryone = _playerPerformanceConfigService.Current.AutoPausePlayersWithPreferredPermissionsExceedingThresholds; bool autoPauseEveryone = _playerPerformanceConfigService.Current.AutoPausePlayersWithPreferredPermissionsExceedingThresholds;
bool autoPauseInDuty = _playerPerformanceConfigService.Current.PauseInInstanceDuty;
if (_uiShared.MediumTreeNode("Auto Pause", UIColors.Get("LightlessPurple"))) if (_uiShared.MediumTreeNode("Auto Pause", UIColors.Get("LightlessPurple")))
{ {
if (ImGui.Checkbox("Auto pause sync while in instances and duties", ref autoPauseInDuty))
{
_playerPerformanceConfigService.Current.PauseInInstanceDuty = autoPauseInDuty;
_playerPerformanceConfigService.Save();
}
_uiShared.DrawHelpText("When enabled, it will automatically pause all players while you are in an instance, such as a dungeon or raid." + Environment.NewLine
+ UiSharedService.TooltipSeparator + "Warning: You many have to leave the dungeon to resync with people again");
if (ImGui.Checkbox("Automatically pause players exceeding thresholds", ref autoPause)) if (ImGui.Checkbox("Automatically pause players exceeding thresholds", ref autoPause))
{ {
_playerPerformanceConfigService.Current.AutoPausePlayersExceedingThresholds = autoPause; _playerPerformanceConfigService.Current.AutoPausePlayersExceedingThresholds = autoPause;
@@ -1544,7 +1614,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
var selectedServer = _serverConfigurationManager.GetServerByIndex(idx); var selectedServer = _serverConfigurationManager.GetServerByIndex(idx);
if (selectedServer == _serverConfigurationManager.CurrentServer) if (selectedServer == _serverConfigurationManager.CurrentServer)
{ {
UiSharedService.ColorTextWrapped("For any changes to be applied to the current service you need to reconnect to the service.", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("For any changes to be applied to the current service you need to reconnect to the service.", UIColors.Get("LightlessYellow"));
} }
bool useOauth = selectedServer.UseOAuth2; bool useOauth = selectedServer.UseOAuth2;
@@ -1556,7 +1626,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
if (selectedServer.SecretKeys.Any() || useOauth) if (selectedServer.SecretKeys.Any() || useOauth)
{ {
UiSharedService.ColorTextWrapped("Characters listed here will automatically connect to the selected Lightless service with the settings as provided below." + UiSharedService.ColorTextWrapped("Characters listed here will automatically connect to the selected Lightless service with the settings as provided below." +
" Make sure to enter the character names correctly or use the 'Add current character' button at the bottom.", ImGuiColors.DalamudYellow); " Make sure to enter the character names correctly or use the 'Add current character' button at the bottom.", UIColors.Get("LightlessYellow"));
int i = 0; int i = 0;
_uiShared.DrawUpdateOAuthUIDsButton(selectedServer); _uiShared.DrawUpdateOAuthUIDsButton(selectedServer);
@@ -1577,14 +1647,14 @@ public class SettingsUi : WindowMediatorSubscriberBase
} }
if (_secretKeysConversionTask != null && !_secretKeysConversionTask.IsCompleted) if (_secretKeysConversionTask != null && !_secretKeysConversionTask.IsCompleted)
{ {
UiSharedService.ColorTextWrapped("Converting Secret Keys to UIDs", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("Converting Secret Keys to UIDs", UIColors.Get("LightlessYellow"));
} }
if (_secretKeysConversionTask != null && _secretKeysConversionTask.IsCompletedSuccessfully) if (_secretKeysConversionTask != null && _secretKeysConversionTask.IsCompletedSuccessfully)
{ {
Vector4? textColor = null; Vector4? textColor = null;
if (_secretKeysConversionTask.Result.PartialSuccess) if (_secretKeysConversionTask.Result.PartialSuccess)
{ {
textColor = ImGuiColors.DalamudYellow; textColor = UIColors.Get("LightlessYellow");
} }
if (!_secretKeysConversionTask.Result.Success) if (!_secretKeysConversionTask.Result.Success)
{ {
@@ -1618,10 +1688,10 @@ public class SettingsUi : WindowMediatorSubscriberBase
if (authWithCid != null) if (authWithCid != null)
{ {
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
UiSharedService.ColorText("A potential rename/world change from this character was detected:", ImGuiColors.DalamudYellow); UiSharedService.ColorText("A potential rename/world change from this character was detected:", UIColors.Get("LightlessYellow"));
using (ImRaii.PushIndent(10f)) using (ImRaii.PushIndent(10f))
UiSharedService.ColorText("Entry: " + authWithCid.CharacterName + " - " + _dalamudUtilService.WorldData.Value[(ushort)authWithCid.WorldId], UIColors.Get("LightlessBlue")); UiSharedService.ColorText("Entry: " + authWithCid.CharacterName + " - " + _dalamudUtilService.WorldData.Value[(ushort)authWithCid.WorldId], UIColors.Get("LightlessBlue"));
UiSharedService.ColorText("Press the button below to adjust that entry to your current character:", ImGuiColors.DalamudYellow); UiSharedService.ColorText("Press the button below to adjust that entry to your current character:", UIColors.Get("LightlessYellow"));
using (ImRaii.PushIndent(10f)) using (ImRaii.PushIndent(10f))
UiSharedService.ColorText("Current: " + youName + " - " + _dalamudUtilService.WorldData.Value[(ushort)youWorld], UIColors.Get("LightlessBlue")); UiSharedService.ColorText("Current: " + youName + " - " + _dalamudUtilService.WorldData.Value[(ushort)youWorld], UIColors.Get("LightlessBlue"));
ImGuiHelpers.ScaledDummy(5); ImGuiHelpers.ScaledDummy(5);
@@ -1767,7 +1837,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
} }
else else
{ {
UiSharedService.ColorTextWrapped("You need to add a Secret Key first before adding Characters.", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("You need to add a Secret Key first before adding Characters.", UIColors.Get("LightlessYellow"));
} }
ImGui.EndTabItem(); ImGui.EndTabItem();
@@ -1801,7 +1871,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
} }
else else
{ {
UiSharedService.ColorTextWrapped("This key is in use and cannot be deleted", ImGuiColors.DalamudYellow); UiSharedService.ColorTextWrapped("This key is in use and cannot be deleted", UIColors.Get("LightlessYellow"));
} }
if (item.Key != selectedServer.SecretKeys.Keys.LastOrDefault()) if (item.Key != selectedServer.SecretKeys.Keys.LastOrDefault())
@@ -1981,7 +2051,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
else else
{ {
UiSharedService.ColorTextWrapped("Default Permission Settings unavailable for this service. " + UiSharedService.ColorTextWrapped("Default Permission Settings unavailable for this service. " +
"You need to connect to this service to change the default permissions since they are stored on the service.", ImGuiColors.DalamudYellow); "You need to connect to this service to change the default permissions since they are stored on the service.", UIColors.Get("LightlessYellow"));
} }
ImGui.EndTabItem(); ImGui.EndTabItem();

View File

@@ -130,12 +130,12 @@ public class StandaloneProfileUi : WindowMediatorSubscriberBase
if (Pair.UserPair.OwnPermissions.IsPaused()) if (Pair.UserPair.OwnPermissions.IsPaused())
{ {
ImGui.SameLine(); ImGui.SameLine();
UiSharedService.ColorText("You: paused", ImGuiColors.DalamudYellow); UiSharedService.ColorText("You: paused", UIColors.Get("LightlessYellow"));
} }
if (Pair.UserPair.OtherPermissions.IsPaused()) if (Pair.UserPair.OtherPermissions.IsPaused())
{ {
ImGui.SameLine(); ImGui.SameLine();
UiSharedService.ColorText("They: paused", ImGuiColors.DalamudYellow); UiSharedService.ColorText("They: paused", UIColors.Get("LightlessYellow"));
} }
} }

View File

@@ -13,7 +13,7 @@ using LightlessSync.WebAPI;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Globalization; using System.Globalization;
namespace LightlessSync.UI.Components.Popup; namespace LightlessSync.UI;
public class SyncshellAdminUI : WindowMediatorSubscriberBase public class SyncshellAdminUI : WindowMediatorSubscriberBase
{ {
@@ -63,7 +63,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
using var id = ImRaii.PushId("syncshell_admin_" + GroupFullInfo.GID); using var id = ImRaii.PushId("syncshell_admin_" + GroupFullInfo.GID);
using (_uiSharedService.UidFont.Push()) using (_uiSharedService.UidFont.Push())
ImGui.TextUnformatted(GroupFullInfo.GroupAliasOrGID + " Administrative Panel"); _uiSharedService.UnderlinedBigText(GroupFullInfo.GroupAliasOrGID + " Administrative Panel", UIColors.Get("LightlessBlue"));
ImGui.Separator(); ImGui.Separator();
var perm = GroupFullInfo.GroupPermissions; var perm = GroupFullInfo.GroupPermissions;
@@ -72,133 +72,203 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
if (tabbar) if (tabbar)
{ {
var inviteTab = ImRaii.TabItem("Invites"); DrawInvites(perm);
if (inviteTab)
{
bool isInvitesDisabled = perm.IsDisableInvites();
if (_uiSharedService.IconTextButton(isInvitesDisabled ? FontAwesomeIcon.Unlock : FontAwesomeIcon.Lock, DrawManagement();
isInvitesDisabled ? "Unlock Syncshell" : "Lock Syncshell"))
DrawPermission(perm);
}
}
private void DrawPermission(GroupPermissions perm)
{
var permissionTab = ImRaii.TabItem("Permissions");
if (permissionTab)
{
bool isDisableAnimations = perm.IsPreferDisableAnimations();
bool isDisableSounds = perm.IsPreferDisableSounds();
bool isDisableVfx = perm.IsPreferDisableVFX();
ImGui.AlignTextToFramePadding();
ImGui.Text("Suggest Sound Sync");
_uiSharedService.BooleanToColoredIcon(!isDisableSounds);
ImGui.SameLine(230);
using (ImRaii.PushColor(ImGuiCol.Text, isDisableSounds ? UIColors.Get("PairBlue") : UIColors.Get("DimRed")))
{
if (_uiSharedService.IconTextButton(isDisableSounds ? FontAwesomeIcon.VolumeUp : FontAwesomeIcon.VolumeMute,
isDisableSounds ? "Suggest to enable sound sync" : "Suggest to disable sound sync"))
{ {
perm.SetDisableInvites(!isInvitesDisabled); perm.SetPreferDisableSounds(!perm.IsPreferDisableSounds());
_ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm)); _ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm));
} }
}
ImGuiHelpers.ScaledDummy(2f); ImGui.AlignTextToFramePadding();
ImGui.Text("Suggest Animation Sync");
UiSharedService.TextWrapped("One-time invites work as single-use passwords. Use those if you do not want to distribute your Syncshell password."); _uiSharedService.BooleanToColoredIcon(!isDisableAnimations);
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Envelope, "Single one-time invite")) ImGui.SameLine(230);
using (ImRaii.PushColor(ImGuiCol.Text, isDisableAnimations ? UIColors.Get("PairBlue") : UIColors.Get("DimRed")))
{
if (_uiSharedService.IconTextButton(isDisableAnimations ? FontAwesomeIcon.Running : FontAwesomeIcon.Stop,
isDisableAnimations ? "Suggest to enable animation sync" : "Suggest to disable animation sync"))
{ {
ImGui.SetClipboardText(_apiController.GroupCreateTempInvite(new(GroupFullInfo.Group), 1).Result.FirstOrDefault() ?? string.Empty); perm.SetPreferDisableAnimations(!perm.IsPreferDisableAnimations());
} _ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm));
UiSharedService.AttachToolTip("Creates a single-use password for joining the syncshell which is valid for 24h and copies it to the clipboard.");
ImGui.InputInt("##amountofinvites", ref _multiInvites);
ImGui.SameLine();
using (ImRaii.Disabled(_multiInvites <= 1 || _multiInvites > 100))
{
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Envelope, "Generate " + _multiInvites + " one-time invites"))
{
_oneTimeInvites.AddRange(_apiController.GroupCreateTempInvite(new(GroupFullInfo.Group), _multiInvites).Result);
}
}
if (_oneTimeInvites.Any())
{
var invites = string.Join(Environment.NewLine, _oneTimeInvites);
ImGui.InputTextMultiline("Generated Multi Invites", ref invites, 5000, new(0, 0), ImGuiInputTextFlags.ReadOnly);
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Copy, "Copy Invites to clipboard"))
{
ImGui.SetClipboardText(invites);
}
} }
} }
inviteTab.Dispose();
var mgmtTab = ImRaii.TabItem("User Management"); ImGui.AlignTextToFramePadding();
if (mgmtTab) ImGui.Text("Suggest VFX Sync");
_uiSharedService.BooleanToColoredIcon(!isDisableVfx);
ImGui.SameLine(230);
using (ImRaii.PushColor(ImGuiCol.Text, isDisableVfx ? UIColors.Get("PairBlue") : UIColors.Get("DimRed")))
{ {
var userNode = ImRaii.TreeNode("User List & Administration"); if (_uiSharedService.IconTextButton(isDisableVfx ? FontAwesomeIcon.Sun : FontAwesomeIcon.Circle,
if (userNode) isDisableVfx ? "Suggest to enable vfx sync" : "Suggest to disable vfx sync"))
{ {
if (!_pairManager.GroupPairs.TryGetValue(GroupFullInfo, out var pairs)) perm.SetPreferDisableVFX(!perm.IsPreferDisableVFX());
_ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm));
}
}
UiSharedService.TextWrapped("Note: those suggested permissions will be shown to users on joining the Syncshell.");
}
permissionTab.Dispose();
if (_isOwner)
{
var ownerTab = ImRaii.TabItem("Owner Settings");
if (ownerTab)
{
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted("New Password");
var availableWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
var buttonSize = _uiSharedService.GetIconTextButtonSize(FontAwesomeIcon.Passport, "Change Password");
var textSize = ImGui.CalcTextSize("New Password").X;
var spacing = ImGui.GetStyle().ItemSpacing.X;
ImGui.SameLine();
ImGui.SetNextItemWidth(availableWidth - buttonSize - textSize - spacing * 2);
ImGui.InputTextWithHint("##changepw", "Min 10 characters", ref _newPassword, 50);
ImGui.SameLine();
using (ImRaii.Disabled(_newPassword.Length < 10))
{
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Passport, "Change Password"))
{ {
UiSharedService.ColorTextWrapped("No users found in this Syncshell", ImGuiColors.DalamudYellow); _pwChangeSuccess = _apiController.GroupChangePassword(new GroupPasswordDto(GroupFullInfo.Group, _newPassword)).Result;
_newPassword = string.Empty;
} }
else }
UiSharedService.AttachToolTip("Password requires to be at least 10 characters long. This action is irreversible.");
if (!_pwChangeSuccess)
{
UiSharedService.ColorTextWrapped("Failed to change the password. Password requires to be at least 10 characters long.", ImGuiColors.DalamudYellow);
}
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete Syncshell") && UiSharedService.CtrlPressed() && UiSharedService.ShiftPressed())
{
IsOpen = false;
_ = _apiController.GroupDelete(new(GroupFullInfo.Group));
}
UiSharedService.AttachToolTip("Hold CTRL and Shift and click to delete this Syncshell." + Environment.NewLine + "WARNING: this action is irreversible.");
}
ownerTab.Dispose();
}
}
private void DrawManagement()
{
var mgmtTab = ImRaii.TabItem("User Management");
if (mgmtTab)
{
if (_uiSharedService.MediumTreeNode("User List & Administration", UIColors.Get("LightlessPurple")))
{
if (!_pairManager.GroupPairs.TryGetValue(GroupFullInfo, out var pairs))
{
UiSharedService.ColorTextWrapped("No users found in this Syncshell", ImGuiColors.DalamudYellow);
}
else
{
var tableFlags = ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingStretchProp;
if (pairs.Count > 10) tableFlags |= ImGuiTableFlags.ScrollY;
using var table = ImRaii.Table("userList#" + GroupFullInfo.Group.GID, 3, tableFlags);
if (table)
{ {
using var table = ImRaii.Table("userList#" + GroupFullInfo.Group.GID, 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingStretchProp | ImGuiTableFlags.ScrollY); ImGui.TableSetupColumn("Alias/UID/Note", ImGuiTableColumnFlags.None, 5);
if (table) ImGui.TableSetupColumn("Flags", ImGuiTableColumnFlags.None, 1);
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 2);
ImGui.TableHeadersRow();
var groupedPairs = new Dictionary<Pair, GroupPairUserInfo?>(pairs.Select(p => new KeyValuePair<Pair, GroupPairUserInfo?>(p,
GroupFullInfo.GroupPairUserInfos.TryGetValue(p.UserData.UID, out GroupPairUserInfo value) ? value : null)));
foreach (var pair in groupedPairs.OrderBy(p =>
{ {
ImGui.TableSetupColumn("Alias/UID/Note", ImGuiTableColumnFlags.None, 3); if (p.Value == null) return 10;
ImGui.TableSetupColumn("Online/Name", ImGuiTableColumnFlags.None, 2); if (string.Equals(p.Key.UserData.UID, GroupFullInfo.OwnerUID, StringComparison.Ordinal)) return 0;
ImGui.TableSetupColumn("Flags", ImGuiTableColumnFlags.None, 1); if (p.Value.Value.IsModerator()) return 1;
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 2); if (p.Value.Value.IsPinned()) return 2;
ImGui.TableHeadersRow(); return 10;
}).ThenBy(p => p.Key.GetNote() ?? p.Key.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase))
{
using var tableId = ImRaii.PushId("userTable_" + pair.Key.UserData.UID);
var isUserOwner = string.Equals(pair.Key.UserData.UID, GroupFullInfo.OwnerUID, StringComparison.Ordinal);
var groupedPairs = new Dictionary<Pair, GroupPairUserInfo?>(pairs.Select(p => new KeyValuePair<Pair, GroupPairUserInfo?>(p, ImGui.TableNextColumn(); // alias/uid/note
GroupFullInfo.GroupPairUserInfos.TryGetValue(p.UserData.UID, out GroupPairUserInfo value) ? value : null))); var note = pair.Key.GetNote();
var text = note == null ? pair.Key.UserData.AliasOrUID : note + " (" + pair.Key.UserData.AliasOrUID + ")";
foreach (var pair in groupedPairs.OrderBy(p => ImGui.AlignTextToFramePadding();
var boolcolor = UiSharedService.GetBoolColor(pair.Key.IsOnline);
UiSharedService.ColorText(text, boolcolor);
if (!string.IsNullOrEmpty(pair.Key.PlayerName))
{ {
if (p.Value == null) return 10; UiSharedService.AttachToolTip(pair.Key.PlayerName);
if (p.Value.Value.IsModerator()) return 0; ImGui.SameLine();
if (p.Value.Value.IsPinned()) return 1; }
return 10;
}).ThenBy(p => p.Key.GetNote() ?? p.Key.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase)) ImGui.TableNextColumn(); // special flags
if (pair.Value != null && (pair.Value.Value.IsModerator() || pair.Value.Value.IsPinned() || isUserOwner))
{ {
using var tableId = ImRaii.PushId("userTable_" + pair.Key.UserData.UID); if (pair.Value.Value.IsModerator())
ImGui.TableNextColumn(); // alias/uid/note
var note = pair.Key.GetNote();
var text = note == null ? pair.Key.UserData.AliasOrUID : note + " (" + pair.Key.UserData.AliasOrUID + ")";
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(text);
ImGui.TableNextColumn(); // online/name
string onlineText = pair.Key.IsOnline ? "Online" : "Offline";
if (!string.IsNullOrEmpty(pair.Key.PlayerName))
{ {
onlineText += " (" + pair.Key.PlayerName + ")"; _uiSharedService.IconText(FontAwesomeIcon.UserShield, UIColors.Get("LightlessPurple"));
UiSharedService.AttachToolTip("Moderator");
} }
var boolcolor = UiSharedService.GetBoolColor(pair.Key.IsOnline); if (pair.Value.Value.IsPinned() && !isUserOwner)
ImGui.AlignTextToFramePadding();
UiSharedService.ColorText(onlineText, boolcolor);
ImGui.TableNextColumn(); // special flags
if (pair.Value != null && (pair.Value.Value.IsModerator() || pair.Value.Value.IsPinned()))
{ {
if (pair.Value.Value.IsModerator()) _uiSharedService.IconText(FontAwesomeIcon.Thumbtack);
{ UiSharedService.AttachToolTip("Pinned");
_uiSharedService.IconText(FontAwesomeIcon.UserShield);
UiSharedService.AttachToolTip("Moderator");
}
if (pair.Value.Value.IsPinned())
{
_uiSharedService.IconText(FontAwesomeIcon.Thumbtack);
UiSharedService.AttachToolTip("Pinned");
}
} }
else if (isUserOwner)
{ {
_uiSharedService.IconText(FontAwesomeIcon.None); _uiSharedService.IconText(FontAwesomeIcon.Crown, UIColors.Get("LightlessYellow"));
UiSharedService.AttachToolTip("Owner");
} }
}
else
{
_uiSharedService.IconText(FontAwesomeIcon.None);
}
ImGui.TableNextColumn(); // actions ImGui.TableNextColumn(); // actions
if (_isOwner) if (_isOwner)
{
if (_uiSharedService.IconButton(FontAwesomeIcon.UserShield))
{ {
if (_uiSharedService.IconButton(FontAwesomeIcon.UserShield)) GroupPairUserInfo userInfo = pair.Value ?? GroupPairUserInfo.None;
{
GroupPairUserInfo userInfo = pair.Value ?? GroupPairUserInfo.None;
userInfo.SetModerator(!userInfo.IsModerator()); userInfo.SetModerator(!userInfo.IsModerator());
_ = _apiController.GroupSetUserInfo(new GroupPairUserInfoDto(GroupFullInfo.Group, pair.Key.UserData, userInfo)); _ = _apiController.GroupSetUserInfo(new GroupPairUserInfoDto(GroupFullInfo.Group, pair.Key.UserData, userInfo));
}
UiSharedService.AttachToolTip(pair.Value != null && pair.Value.Value.IsModerator() ? "Demod user" : "Mod user");
ImGui.SameLine();
} }
UiSharedService.AttachToolTip(pair.Value != null && pair.Value.Value.IsModerator() ? "Demod user" : "Mod user");
ImGui.SameLine();
}
if (_isOwner || (pair.Value == null || (pair.Value != null && !pair.Value.Value.IsModerator()))) if (pair.Value == null || pair.Value != null && !pair.Value.Value.IsModerator() && !isUserOwner)
{
using (ImRaii.PushColor(ImGuiCol.Text, pair.Value != null && pair.Value.Value.IsPinned() ? UIColors.Get("DimRed") : UIColors.Get("PairBlue")))
{ {
if (_uiSharedService.IconButton(FontAwesomeIcon.Thumbtack)) if (_uiSharedService.IconButton(FontAwesomeIcon.Thumbtack))
{ {
@@ -208,9 +278,12 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
_ = _apiController.GroupSetUserInfo(new GroupPairUserInfoDto(GroupFullInfo.Group, pair.Key.UserData, userInfo)); _ = _apiController.GroupSetUserInfo(new GroupPairUserInfoDto(GroupFullInfo.Group, pair.Key.UserData, userInfo));
} }
UiSharedService.AttachToolTip(pair.Value != null && pair.Value.Value.IsPinned() ? "Unpin user" : "Pin user"); }
ImGui.SameLine(); UiSharedService.AttachToolTip(pair.Value != null && pair.Value.Value.IsPinned() ? "Unpin user" : "Pin user");
ImGui.SameLine();
using (ImRaii.PushColor(ImGuiCol.Text, UIColors.Get("DimRed")))
{
using (ImRaii.Disabled(!UiSharedService.CtrlPressed())) using (ImRaii.Disabled(!UiSharedService.CtrlPressed()))
{ {
if (_uiSharedService.IconButton(FontAwesomeIcon.Trash)) if (_uiSharedService.IconButton(FontAwesomeIcon.Trash))
@@ -218,10 +291,13 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
_ = _apiController.GroupRemoveUser(new GroupPairDto(GroupFullInfo.Group, pair.Key.UserData)); _ = _apiController.GroupRemoveUser(new GroupPairDto(GroupFullInfo.Group, pair.Key.UserData));
} }
} }
UiSharedService.AttachToolTip("Remove user from Syncshell" }
+ UiSharedService.TooltipSeparator + "Hold CTRL to enable this button"); UiSharedService.AttachToolTip("Remove user from Syncshell"
+ UiSharedService.TooltipSeparator + "Hold CTRL to enable this button");
ImGui.SameLine();
ImGui.SameLine(); using (ImRaii.PushColor(ImGuiCol.Text, UIColors.Get("DimRed")))
{
using (ImRaii.Disabled(!UiSharedService.CtrlPressed())) using (ImRaii.Disabled(!UiSharedService.CtrlPressed()))
{ {
if (_uiSharedService.IconButton(FontAwesomeIcon.Ban)) if (_uiSharedService.IconButton(FontAwesomeIcon.Ban))
@@ -229,224 +305,190 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase
Mediator.Publish(new OpenBanUserPopupMessage(pair.Key, GroupFullInfo)); Mediator.Publish(new OpenBanUserPopupMessage(pair.Key, GroupFullInfo));
} }
} }
UiSharedService.AttachToolTip("Ban user from Syncshell"
+ UiSharedService.TooltipSeparator + "Hold CTRL to enable this button");
} }
} UiSharedService.AttachToolTip("Ban user from Syncshell"
}
}
}
userNode.Dispose();
var clearNode = ImRaii.TreeNode("Mass Cleanup");
if (clearNode)
{
using (ImRaii.Disabled(!UiSharedService.CtrlPressed()))
{
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Broom, "Clear Syncshell"))
{
_ = _apiController.GroupClear(new(GroupFullInfo.Group));
}
}
UiSharedService.AttachToolTip("This will remove all non-pinned, non-moderator users from the Syncshell."
+ UiSharedService.TooltipSeparator + "Hold CTRL to enable this button");
ImGuiHelpers.ScaledDummy(2f);
ImGui.Separator();
ImGuiHelpers.ScaledDummy(2f);
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Unlink, "Check for Inactive Users"))
{
_pruneTestTask = _apiController.GroupPrune(new(GroupFullInfo.Group), _pruneDays, execute: false);
_pruneTask = null;
}
UiSharedService.AttachToolTip($"This will start the prune process for this Syncshell of inactive Lightless users that have not logged in in the past {_pruneDays} days."
+ Environment.NewLine + "You will be able to review the amount of inactive users before executing the prune."
+ UiSharedService.TooltipSeparator + "Note: this check excludes pinned users and moderators of this Syncshell.");
ImGui.SameLine();
ImGui.SetNextItemWidth(150);
_uiSharedService.DrawCombo("Days of inactivity", [7, 14, 30, 90], (count) =>
{
return count + " days";
},
(selected) =>
{
_pruneDays = selected;
_pruneTestTask = null;
_pruneTask = null;
},
_pruneDays);
if (_pruneTestTask != null)
{
if (!_pruneTestTask.IsCompleted)
{
UiSharedService.ColorTextWrapped("Calculating inactive users...", ImGuiColors.DalamudYellow);
}
else
{
ImGui.AlignTextToFramePadding();
UiSharedService.TextWrapped($"Found {_pruneTestTask.Result} user(s) that have not logged into Lightless in the past {_pruneDays} days.");
if (_pruneTestTask.Result > 0)
{
using (ImRaii.Disabled(!UiSharedService.CtrlPressed()))
{
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Broom, "Prune Inactive Users"))
{
_pruneTask = _apiController.GroupPrune(new(GroupFullInfo.Group), _pruneDays, execute: true);
_pruneTestTask = null;
}
}
UiSharedService.AttachToolTip($"Pruning will remove {_pruneTestTask?.Result ?? 0} inactive user(s)."
+ UiSharedService.TooltipSeparator + "Hold CTRL to enable this button"); + UiSharedService.TooltipSeparator + "Hold CTRL to enable this button");
} }
} }
} }
if (_pruneTask != null) }
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
if (_uiSharedService.MediumTreeNode("Mass Cleanup", UIColors.Get("LightlessPurple")))
{
using (ImRaii.Disabled(!UiSharedService.CtrlPressed()))
{
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Broom, "Clear Syncshell"))
{ {
if (!_pruneTask.IsCompleted) _ = _apiController.GroupClear(new(GroupFullInfo.Group));
{
UiSharedService.ColorTextWrapped("Pruning Syncshell...", ImGuiColors.DalamudYellow);
}
else
{
UiSharedService.TextWrapped($"Syncshell was pruned and {_pruneTask.Result} inactive user(s) have been removed.");
}
} }
} }
clearNode.Dispose(); UiSharedService.AttachToolTip("This will remove all non-pinned, non-moderator users from the Syncshell."
+ UiSharedService.TooltipSeparator + "Hold CTRL to enable this button");
var banNode = ImRaii.TreeNode("User Bans"); ImGuiHelpers.ScaledDummy(2f);
if (banNode) ImGui.Separator();
ImGuiHelpers.ScaledDummy(2f);
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Unlink, "Check for Inactive Users"))
{ {
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Retweet, "Refresh Banlist from Server")) _pruneTestTask = _apiController.GroupPrune(new(GroupFullInfo.Group), _pruneDays, execute: false);
_pruneTask = null;
}
UiSharedService.AttachToolTip($"This will start the prune process for this Syncshell of inactive Lightless users that have not logged in in the past {_pruneDays} day(s)."
+ Environment.NewLine + "You will be able to review the amount of inactive users before executing the prune."
+ UiSharedService.TooltipSeparator + "Note: this check excludes pinned users and moderators of this Syncshell.");
ImGui.SameLine();
ImGui.SetNextItemWidth(150);
_uiSharedService.DrawCombo("Day(s) of inactivity", [1, 3, 7, 14, 30, 90], (count) =>
{
return count + " day(s)";
},
(selected) =>
{
_pruneDays = selected;
_pruneTestTask = null;
_pruneTask = null;
},
_pruneDays);
if (_pruneTestTask != null)
{
if (!_pruneTestTask.IsCompleted)
{ {
_bannedUsers = _apiController.GroupGetBannedUsers(new GroupDto(GroupFullInfo.Group)).Result; UiSharedService.ColorTextWrapped("Calculating inactive users...", ImGuiColors.DalamudYellow);
} }
else
if (ImGui.BeginTable("bannedusertable" + GroupFullInfo.GID, 6, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingStretchProp | ImGuiTableFlags.ScrollY))
{ {
ImGui.TableSetupColumn("UID", ImGuiTableColumnFlags.None, 1); ImGui.AlignTextToFramePadding();
ImGui.TableSetupColumn("Alias", ImGuiTableColumnFlags.None, 1); UiSharedService.TextWrapped($"Found {_pruneTestTask.Result} user(s) that have not logged into Lightless in the past {_pruneDays} day(s).");
ImGui.TableSetupColumn("By", ImGuiTableColumnFlags.None, 1); if (_pruneTestTask.Result > 0)
ImGui.TableSetupColumn("Date", ImGuiTableColumnFlags.None, 2);
ImGui.TableSetupColumn("Reason", ImGuiTableColumnFlags.None, 3);
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 1);
ImGui.TableHeadersRow();
foreach (var bannedUser in _bannedUsers.ToList())
{ {
ImGui.TableNextColumn(); using (ImRaii.Disabled(!UiSharedService.CtrlPressed()))
ImGui.TextUnformatted(bannedUser.UID);
ImGui.TableNextColumn();
ImGui.TextUnformatted(bannedUser.UserAlias ?? string.Empty);
ImGui.TableNextColumn();
ImGui.TextUnformatted(bannedUser.BannedBy);
ImGui.TableNextColumn();
ImGui.TextUnformatted(bannedUser.BannedOn.ToLocalTime().ToString(CultureInfo.CurrentCulture));
ImGui.TableNextColumn();
UiSharedService.TextWrapped(bannedUser.Reason);
ImGui.TableNextColumn();
using var _ = ImRaii.PushId(bannedUser.UID);
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Check, "Unban"))
{ {
_apiController.GroupUnbanUser(bannedUser); if (_uiSharedService.IconTextButton(FontAwesomeIcon.Broom, "Prune Inactive Users"))
_bannedUsers.RemoveAll(b => string.Equals(b.UID, bannedUser.UID, StringComparison.Ordinal)); {
_pruneTask = _apiController.GroupPrune(new(GroupFullInfo.Group), _pruneDays, execute: true);
_pruneTestTask = null;
}
} }
UiSharedService.AttachToolTip($"Pruning will remove {_pruneTestTask?.Result ?? 0} inactive user(s)."
+ UiSharedService.TooltipSeparator + "Hold CTRL to enable this button");
} }
ImGui.EndTable();
} }
} }
banNode.Dispose(); if (_pruneTask != null)
}
mgmtTab.Dispose();
var permissionTab = ImRaii.TabItem("Permissions");
if (permissionTab)
{
bool isDisableAnimations = perm.IsPreferDisableAnimations();
bool isDisableSounds = perm.IsPreferDisableSounds();
bool isDisableVfx = perm.IsPreferDisableVFX();
ImGui.AlignTextToFramePadding();
ImGui.Text("Suggest Sound Sync");
_uiSharedService.BooleanToColoredIcon(!isDisableSounds);
ImGui.SameLine(230);
if (_uiSharedService.IconTextButton(isDisableSounds ? FontAwesomeIcon.VolumeUp : FontAwesomeIcon.VolumeMute,
isDisableSounds ? "Suggest to enable sound sync" : "Suggest to disable sound sync"))
{ {
perm.SetPreferDisableSounds(!perm.IsPreferDisableSounds()); if (!_pruneTask.IsCompleted)
_ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm));
}
ImGui.AlignTextToFramePadding();
ImGui.Text("Suggest Animation Sync");
_uiSharedService.BooleanToColoredIcon(!isDisableAnimations);
ImGui.SameLine(230);
if (_uiSharedService.IconTextButton(isDisableAnimations ? FontAwesomeIcon.Running : FontAwesomeIcon.Stop,
isDisableAnimations ? "Suggest to enable animation sync" : "Suggest to disable animation sync"))
{
perm.SetPreferDisableAnimations(!perm.IsPreferDisableAnimations());
_ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm));
}
ImGui.AlignTextToFramePadding();
ImGui.Text("Suggest VFX Sync");
_uiSharedService.BooleanToColoredIcon(!isDisableVfx);
ImGui.SameLine(230);
if (_uiSharedService.IconTextButton(isDisableVfx ? FontAwesomeIcon.Sun : FontAwesomeIcon.Circle,
isDisableVfx ? "Suggest to enable vfx sync" : "Suggest to disable vfx sync"))
{
perm.SetPreferDisableVFX(!perm.IsPreferDisableVFX());
_ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm));
}
UiSharedService.TextWrapped("Note: those suggested permissions will be shown to users on joining the Syncshell.");
}
permissionTab.Dispose();
if (_isOwner)
{
var ownerTab = ImRaii.TabItem("Owner Settings");
if (ownerTab)
{
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted("New Password");
var availableWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
var buttonSize = _uiSharedService.GetIconTextButtonSize(FontAwesomeIcon.Passport, "Change Password");
var textSize = ImGui.CalcTextSize("New Password").X;
var spacing = ImGui.GetStyle().ItemSpacing.X;
ImGui.SameLine();
ImGui.SetNextItemWidth(availableWidth - buttonSize - textSize - spacing * 2);
ImGui.InputTextWithHint("##changepw", "Min 10 characters", ref _newPassword, 50);
ImGui.SameLine();
using (ImRaii.Disabled(_newPassword.Length < 10))
{ {
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Passport, "Change Password")) UiSharedService.ColorTextWrapped("Pruning Syncshell...", ImGuiColors.DalamudYellow);
}
else
{
UiSharedService.TextWrapped($"Syncshell was pruned and {_pruneTask.Result} inactive user(s) have been removed.");
}
}
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
ImGui.TreePop();
}
ImGui.Separator();
if (_uiSharedService.MediumTreeNode("User Bans", UIColors.Get("LightlessPurple")))
{
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Retweet, "Refresh Banlist from Server"))
{
_bannedUsers = _apiController.GroupGetBannedUsers(new GroupDto(GroupFullInfo.Group)).Result;
}
var tableFlags = ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingStretchProp;
if (_bannedUsers.Count > 10) tableFlags |= ImGuiTableFlags.ScrollY;
if (ImGui.BeginTable("bannedusertable" + GroupFullInfo.GID, 6, tableFlags))
{
ImGui.TableSetupColumn("UID", ImGuiTableColumnFlags.None, 1);
ImGui.TableSetupColumn("Alias", ImGuiTableColumnFlags.None, 1);
ImGui.TableSetupColumn("By", ImGuiTableColumnFlags.None, 1);
ImGui.TableSetupColumn("Date", ImGuiTableColumnFlags.None, 2);
ImGui.TableSetupColumn("Reason", ImGuiTableColumnFlags.None, 3);
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 1);
ImGui.TableHeadersRow();
foreach (var bannedUser in _bannedUsers.ToList())
{
ImGui.TableNextColumn();
ImGui.TextUnformatted(bannedUser.UID);
ImGui.TableNextColumn();
ImGui.TextUnformatted(bannedUser.UserAlias ?? string.Empty);
ImGui.TableNextColumn();
ImGui.TextUnformatted(bannedUser.BannedBy);
ImGui.TableNextColumn();
ImGui.TextUnformatted(bannedUser.BannedOn.ToLocalTime().ToString(CultureInfo.CurrentCulture));
ImGui.TableNextColumn();
UiSharedService.TextWrapped(bannedUser.Reason);
ImGui.TableNextColumn();
using var _ = ImRaii.PushId(bannedUser.UID);
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Check, "Unban"))
{ {
_pwChangeSuccess = _apiController.GroupChangePassword(new GroupPasswordDto(GroupFullInfo.Group, _newPassword)).Result; _apiController.GroupUnbanUser(bannedUser);
_newPassword = string.Empty; _bannedUsers.RemoveAll(b => string.Equals(b.UID, bannedUser.UID, StringComparison.Ordinal));
} }
} }
UiSharedService.AttachToolTip("Password requires to be at least 10 characters long. This action is irreversible."); ImGui.EndTable();
}
if (!_pwChangeSuccess) _uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
{ ImGui.TreePop();
UiSharedService.ColorTextWrapped("Failed to change the password. Password requires to be at least 10 characters long.", ImGuiColors.DalamudYellow); }
} ImGui.Separator();
}
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete Syncshell") && UiSharedService.CtrlPressed() && UiSharedService.ShiftPressed()) mgmtTab.Dispose();
{
IsOpen = false; }
_ = _apiController.GroupDelete(new(GroupFullInfo.Group));
} private void DrawInvites(GroupPermissions perm)
UiSharedService.AttachToolTip("Hold CTRL and Shift and click to delete this Syncshell." + Environment.NewLine + "WARNING: this action is irreversible."); {
var inviteTab = ImRaii.TabItem("Invites");
if (inviteTab)
{
bool isInvitesDisabled = perm.IsDisableInvites();
if (_uiSharedService.IconTextButton(isInvitesDisabled ? FontAwesomeIcon.Unlock : FontAwesomeIcon.Lock,
isInvitesDisabled ? "Unlock Syncshell" : "Lock Syncshell"))
{
perm.SetDisableInvites(!isInvitesDisabled);
_ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm));
}
ImGuiHelpers.ScaledDummy(2f);
UiSharedService.TextWrapped("One-time invites work as single-use passwords. Use those if you do not want to distribute your Syncshell password.");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Envelope, "Single one-time invite"))
{
ImGui.SetClipboardText(_apiController.GroupCreateTempInvite(new(GroupFullInfo.Group), 1).Result.FirstOrDefault() ?? string.Empty);
}
UiSharedService.AttachToolTip("Creates a single-use password for joining the syncshell which is valid for 24h and copies it to the clipboard.");
ImGui.InputInt("##amountofinvites", ref _multiInvites);
ImGui.SameLine();
using (ImRaii.Disabled(_multiInvites <= 1 || _multiInvites > 100))
{
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Envelope, "Generate " + _multiInvites + " one-time invites"))
{
_oneTimeInvites.AddRange(_apiController.GroupCreateTempInvite(new(GroupFullInfo.Group), _multiInvites).Result);
}
}
if (_oneTimeInvites.Any())
{
var invites = string.Join(Environment.NewLine, _oneTimeInvites);
ImGui.InputTextMultiline("Generated Multi Invites", ref invites, 5000, new(0, 0), ImGuiInputTextFlags.ReadOnly);
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Copy, "Copy Invites to clipboard"))
{
ImGui.SetClipboardText(invites);
} }
ownerTab.Dispose();
} }
} }
inviteTab.Dispose();
} }
public override void OnClose() public override void OnClose()

View File

@@ -1,11 +1,12 @@
using System.Globalization; using System.Globalization;
using System.Numerics; using System.Numerics;
using LightlessSync.LightlessConfiguration;
namespace LightlessSync.UI namespace LightlessSync.UI
{ {
internal static class UIColors internal static class UIColors
{ {
private static readonly Dictionary<string, string> HexColors = new(StringComparer.OrdinalIgnoreCase) private static readonly Dictionary<string, string> DefaultHexColors = new(StringComparer.OrdinalIgnoreCase)
{ {
{ "LightlessPurple", "#ad8af5" }, { "LightlessPurple", "#ad8af5" },
{ "LightlessBlue", "#a6c2ff" }, { "LightlessBlue", "#a6c2ff" },
@@ -14,14 +15,72 @@ namespace LightlessSync.UI
{ "DimRed", "#d44444" }, { "DimRed", "#d44444" },
}; };
private static LightlessConfigService? _configService;
public static void Initialize(LightlessConfigService configService)
{
_configService = configService;
}
public static Vector4 Get(string name) public static Vector4 Get(string name)
{ {
if (!HexColors.TryGetValue(name, out var hex)) if (_configService?.Current.CustomUIColors.TryGetValue(name, out var customColorHex) == true)
return HexToRgba(customColorHex);
if (!DefaultHexColors.TryGetValue(name, out var hex))
throw new ArgumentException($"Color '{name}' not found in UIColors."); throw new ArgumentException($"Color '{name}' not found in UIColors.");
return HexToRgba(hex); return HexToRgba(hex);
} }
public static void Set(string name, Vector4 color)
{
if (!DefaultHexColors.ContainsKey(name))
throw new ArgumentException($"Color '{name}' not found in UIColors.");
if (_configService != null)
{
_configService.Current.CustomUIColors[name] = RgbaToHex(color);
_configService.Save();
}
}
public static void Reset(string name)
{
if (_configService != null)
{
_configService.Current.CustomUIColors.Remove(name);
_configService.Save();
}
}
public static void ResetAll()
{
if (_configService != null)
{
_configService.Current.CustomUIColors.Clear();
_configService.Save();
}
}
public static Vector4 GetDefault(string name)
{
if (!DefaultHexColors.TryGetValue(name, out var hex))
throw new ArgumentException($"Color '{name}' not found in UIColors.");
return HexToRgba(hex);
}
public static bool IsCustom(string name)
{
return _configService?.Current.CustomUIColors.ContainsKey(name) == true;
}
public static IEnumerable<string> GetColorNames()
{
return DefaultHexColors.Keys;
}
public static Vector4 HexToRgba(string hexColor) public static Vector4 HexToRgba(string hexColor)
{ {
hexColor = hexColor.TrimStart('#'); hexColor = hexColor.TrimStart('#');
@@ -31,5 +90,14 @@ namespace LightlessSync.UI
int a = hexColor.Length == 8 ? int.Parse(hexColor.Substring(6, 2), NumberStyles.HexNumber) : 255; int a = hexColor.Length == 8 ? int.Parse(hexColor.Substring(6, 2), NumberStyles.HexNumber) : 255;
return new Vector4(r / 255f, g / 255f, b / 255f, a / 255f); return new Vector4(r / 255f, g / 255f, b / 255f, a / 255f);
} }
public static string RgbaToHex(Vector4 color)
{
int r = (int)(color.X * 255);
int g = (int)(color.Y * 255);
int b = (int)(color.Z * 255);
int a = (int)(color.W * 255);
return $"#{r:X2}{g:X2}{b:X2}{(a != 255 ? a.ToString("X2") : "")}";
}
} }
} }

View File

@@ -405,7 +405,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
} }
public static Vector4 UploadColor((long, long) data) => data.Item1 == 0 ? ImGuiColors.DalamudGrey : public static Vector4 UploadColor((long, long) data) => data.Item1 == 0 ? ImGuiColors.DalamudGrey :
data.Item1 == data.Item2 ? UIColors.Get("LightlessBlue") : ImGuiColors.DalamudYellow; data.Item1 == data.Item2 ? UIColors.Get("LightlessBlue") : UIColors.Get("LightlessYellow");
public bool ApplyNotesFromClipboard(string notes, bool overwrite) public bool ApplyNotesFromClipboard(string notes, bool overwrite)
{ {
@@ -537,7 +537,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
public void DrawCacheDirectorySetting() public void DrawCacheDirectorySetting()
{ {
ColorTextWrapped("Note: The storage folder should be somewhere close to root (i.e. C:\\LightlessStorage) in a new empty folder. DO NOT point this to your game folder. DO NOT point this to your Penumbra folder.", ImGuiColors.DalamudYellow); ColorTextWrapped("Note: The storage folder should be somewhere close to root (i.e. C:\\LightlessStorage) in a new empty folder. DO NOT point this to your game folder. DO NOT point this to your Penumbra folder.", UIColors.Get("LightlessYellow"));
var cacheDirectory = _configService.Current.CacheFolder; var cacheDirectory = _configService.Current.CacheFolder;
ImGui.InputText("Storage Folder##cache", ref cacheDirectory, 255, ImGuiInputTextFlags.ReadOnly); ImGui.InputText("Storage Folder##cache", ref cacheDirectory, 255, ImGuiInputTextFlags.ReadOnly);
@@ -723,7 +723,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
{ {
if (!_discordOAuthCheck.IsCompleted) if (!_discordOAuthCheck.IsCompleted)
{ {
ColorTextWrapped($"Checking OAuth2 compatibility with {selectedServer.ServerUri}", ImGuiColors.DalamudYellow); ColorTextWrapped($"Checking OAuth2 compatibility with {selectedServer.ServerUri}", UIColors.Get("LightlessYellow"));
} }
else else
{ {
@@ -814,7 +814,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
{ {
if (!_discordOAuthUIDs.IsCompleted) if (!_discordOAuthUIDs.IsCompleted)
{ {
ColorTextWrapped("Checking UIDs on Server", ImGuiColors.DalamudYellow); ColorTextWrapped("Checking UIDs on Server", UIColors.Get("LightlessYellow"));
} }
else else
{ {

View File

@@ -4,9 +4,9 @@
"net9.0-windows7.0": { "net9.0-windows7.0": {
"DalamudPackager": { "DalamudPackager": {
"type": "Direct", "type": "Direct",
"requested": "[13.0.0, )", "requested": "[13.1.0, )",
"resolved": "13.0.0", "resolved": "13.1.0",
"contentHash": "Mb3cUDSK/vDPQ8gQIeuCw03EMYrej1B4J44a1AvIJ9C759p9XeqdU9Hg4WgOmlnlPe0G7ILTD32PKSUpkQNa8w==" "contentHash": "XdoNhJGyFby5M/sdcRhnc5xTop9PHy+H50PTWpzLhJugjB19EDBiHD/AsiDF66RETM+0qKUdJBZrNuebn7qswQ=="
}, },
"DotNet.ReproducibleBuilds": { "DotNet.ReproducibleBuilds": {
"type": "Direct", "type": "Direct",