#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>
This commit was merged in pull request #20.
This commit is contained in:
2025-09-09 23:31:50 +02:00
committed by defnotken
parent 9416e376b8
commit 25a0eeadc8
22 changed files with 793 additions and 194 deletions

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

@@ -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;
[Serializable]
public class ServerTagStorage
public class PairTagStorage
{
public HashSet<string> OpenPairTags { 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;
public class ServerTagConfigService : ConfigurationServiceBase<ServerTagConfig>
public class PairTagConfigService : ConfigurationServiceBase<PairTagStorage>
{
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

@@ -130,7 +130,9 @@ public sealed class Plugin : IDalamudPlugin
s.GetRequiredService<CharaDataManager>(),
s.GetRequiredService<LightlessMediator>()));
collection.AddSingleton<SelectPairForTagUi>();
collection.AddSingleton<RenameTagUi>();
collection.AddSingleton<RenamePairTagUi>();
collection.AddSingleton<SelectSyncshellForTagUi>();
collection.AddSingleton<RenameSyncshellTagUi>();
collection.AddSingleton((s) => new EventAggregator(pluginInterface.ConfigDirectory.FullName,
s.GetRequiredService<ILogger<EventAggregator>>(), s.GetRequiredService<LightlessMediator>()));
collection.AddSingleton((s) => new DalamudUtilService(s.GetRequiredService<ILogger<DalamudUtilService>>(),
@@ -175,7 +177,8 @@ public sealed class Plugin : IDalamudPlugin
collection.AddSingleton((s) => new LightlessConfigService(pluginInterface.ConfigDirectory.FullName));
collection.AddSingleton((s) => new ServerConfigService(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 XivDataStorageService(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<ServerConfigService>());
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<XivDataStorageService>());
collection.AddSingleton<IConfigService<ILightlessConfiguration>>(s => s.GetRequiredService<PlayerPerformanceConfigService>());
@@ -198,6 +202,7 @@ public sealed class Plugin : IDalamudPlugin
collection.AddScoped<CacheMonitor>();
collection.AddScoped<UiFactory>();
collection.AddScoped<SelectTagForPairUi>();
collection.AddScoped<SelectTagForSyncshellUi>();
collection.AddScoped<WindowMediatorSubscriberBase, SettingsUi>();
collection.AddScoped<WindowMediatorSubscriberBase, CompactUi>();
collection.AddScoped<WindowMediatorSubscriberBase, IntroUi>();

View File

@@ -3,6 +3,7 @@ using LightlessSync.API.Routes;
using LightlessSync.LightlessConfiguration;
using LightlessSync.LightlessConfiguration.Models;
using LightlessSync.Services.Mediator;
using LightlessSync.UI.Components;
using LightlessSync.WebAPI;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.Extensions.Logging;
@@ -23,15 +24,17 @@ public class ServerConfigurationManager
private readonly ILogger<ServerConfigurationManager> _logger;
private readonly LightlessMediator _lightlessMediator;
private readonly NotesConfigService _notesConfig;
private readonly ServerTagConfigService _serverTagConfig;
private readonly PairTagConfigService _pairTagConfig;
private readonly SyncshellTagConfigService _syncshellTagConfig;
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)
{
_logger = logger;
_configService = configService;
_serverTagConfig = serverTagConfig;
_pairTagConfig = pairTagConfig;
_syncshellTagConfig = syncshellTagConfig;
_notesConfig = notesConfig;
_dalamudUtil = dalamudUtil;
_lightlessConfigService = lightlessConfigService;
@@ -258,7 +261,7 @@ public class ServerConfigurationManager
{
if (serverSelectionIndex == -1) serverSelectionIndex = CurrentServerIndex;
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()))
return;
@@ -277,15 +280,15 @@ public class ServerConfigurationManager
var server = GetServerByIndex(serverSelectionIndex);
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();
}
internal void AddOpenPairTag(string tag)
{
CurrentServerTagStorage().OpenPairTags.Add(tag);
_serverTagConfig.Save();
CurrentPairTagStorage().OpenPairTags.Add(tag);
_pairTagConfig.Save();
}
internal void AddServer(ServerStorage serverStorage)
@@ -294,36 +297,65 @@ public class ServerConfigurationManager
Save();
}
internal void AddTag(string tag)
internal void AddPairTag(string tag)
{
CurrentServerTagStorage().ServerAvailablePairTags.Add(tag);
_serverTagConfig.Save();
CurrentPairTagStorage().ServerAvailablePairTags.Add(tag);
_pairTagConfig.Save();
_lightlessMediator.Publish(new RefreshUiMessage());
}
internal void AddSyncshellTag(string tag)
{
CurrentSyncshellTagStorage().ServerAvailableSyncshellTags.Add(tag);
_syncshellTagConfig.Save();
_lightlessMediator.Publish(new RefreshUiMessage());
}
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);
_lightlessMediator.Publish(new RefreshUiMessage());
}
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);
}
@@ -364,30 +396,19 @@ public class ServerConfigurationManager
return null;
}
internal HashSet<string> GetServerAvailablePairTags()
{
return CurrentServerTagStorage().ServerAvailablePairTags;
}
internal HashSet<string> GetServerAvailablePairTags() => CurrentPairTagStorage().ServerAvailablePairTags;
internal Dictionary<string, List<string>> GetUidServerPairedUserTags()
{
return CurrentServerTagStorage().UidServerPairedUserTags;
}
internal HashSet<string> GetServerAvailableSyncshellTags() => CurrentSyncshellTagStorage().ServerAvailableSyncshellTags;
internal HashSet<string> GetUidsForTag(string tag)
{
return CurrentServerTagStorage().UidServerPairedUserTags.Where(p => p.Value.Contains(tag, StringComparer.Ordinal)).Select(p => p.Key).ToHashSet(StringComparer.Ordinal);
}
internal Dictionary<string, List<string>> GetUidServerPairedUserTags() => CurrentPairTagStorage().UidServerPairedUserTags;
internal bool HasTags(string uid)
{
if (CurrentServerTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags))
{
return tags.Any();
}
internal HashSet<string> GetUidsForPairTag(string tag) => CurrentPairTagStorage().UidServerPairedUserTags.Where(p => p.Value.Contains(tag, StringComparer.Ordinal)).Select(p => p.Key).ToHashSet(StringComparer.Ordinal);
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)
{
@@ -398,50 +419,89 @@ public class ServerConfigurationManager
internal void RemoveOpenPairTag(string tag)
{
CurrentServerTagStorage().OpenPairTags.Remove(tag);
_serverTagConfig.Save();
CurrentPairTagStorage().OpenPairTags.Remove(tag);
_pairTagConfig.Save();
}
internal void RemoveTag(string tag)
internal void RemovePairTag(string tag)
{
CurrentServerTagStorage().ServerAvailablePairTags.Remove(tag);
foreach (var uid in GetUidsForTag(tag))
{
RemoveTagForUid(uid, tag, save: false);
}
_serverTagConfig.Save();
RemoveTag(CurrentPairTagStorage().ServerAvailablePairTags, tag);
_pairTagConfig.Save();
_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)
{
if (CurrentServerTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags))
if (CurrentPairTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags))
{
tags.Remove(tagName);
if (save)
{
_serverTagConfig.Save();
_pairTagConfig.Save();
_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);
CurrentServerTagStorage().ServerAvailablePairTags.Add(newName);
foreach (var existingTags in CurrentServerTagStorage().UidServerPairedUserTags.Select(k => k.Value))
if (CurrentSyncshellTagStorage().SyncshellPairedTags.TryGetValue(name, out var tags))
{
tags.Remove(tagName);
if (save)
{
_syncshellTagConfig.Save();
_lightlessMediator.Publish(new RefreshUiMessage());
}
}
}
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)
{
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());
}
internal void SaveNotes()
{
_notesConfig.Save();
}
internal void SaveNotes() => _notesConfig.Save();
internal void SetNoteForGid(string gid, string note, bool save = true)
{
@@ -476,10 +536,16 @@ public class ServerConfigurationManager
return _notesConfig.Current.ServerNotes[CurrentApiUrl];
}
private ServerTagStorage CurrentServerTagStorage()
private PairTagStorage CurrentPairTagStorage()
{
TryCreateCurrentServerTagStorage();
return _serverTagConfig.Current.ServerTagStorage[CurrentApiUrl];
TryCreateCurrentPairTagStorage();
return _pairTagConfig.Current.ServerTagStorage[CurrentApiUrl];
}
private SyncshellTagStorage CurrentSyncshellTagStorage()
{
TryCreateCurrentSyncshellTagStorage();
return _syncshellTagConfig.Current.ServerTagStorage[CurrentApiUrl];
}
private void EnsureMainExists()
@@ -499,11 +565,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

@@ -1,6 +1,5 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Utility;
@@ -8,6 +7,7 @@ using LightlessSync.API.Data.Extensions;
using LightlessSync.API.Dto.Group;
using LightlessSync.Interop.Ipc;
using LightlessSync.LightlessConfiguration;
using LightlessSync.LightlessConfiguration.Configurations;
using LightlessSync.PlayerData.Handlers;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.Services;
@@ -36,9 +36,12 @@ public class CompactUi : WindowMediatorSubscriberBase
private readonly DrawEntityFactory _drawEntityFactory;
private readonly FileUploadManager _fileTransferManager;
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 RenameTagUi _renameTagUi;
private readonly RenamePairTagUi _renamePairTagUi;
private readonly IpcManager _ipcManager;
private readonly ServerConfigurationManager _serverManager;
private readonly TopTabMenu _tabMenu;
@@ -57,7 +60,9 @@ public class CompactUi : WindowMediatorSubscriberBase
public CompactUi(ILogger<CompactUi> logger, UiSharedService uiShared, LightlessConfigService configService, ApiController apiController, PairManager pairManager,
ServerConfigurationManager serverManager, LightlessMediator mediator, FileUploadManager fileTransferManager,
TagHandler tagHandler, DrawEntityFactory drawEntityFactory, SelectTagForPairUi selectTagForPairUi, SelectPairForTagUi selectPairForTagUi, RenameTagUi renameTagUi,
TagHandler tagHandler, DrawEntityFactory drawEntityFactory,
SelectTagForPairUi selectTagForPairUi, SelectPairForTagUi selectPairForTagUi, RenamePairTagUi renameTagUi,
SelectTagForSyncshellUi selectTagForSyncshellUi, SelectSyncshellForTagUi selectSyncshellForTagUi, RenameSyncshellTagUi renameSyncshellTagUi,
PerformanceCollectorService performanceCollectorService, IpcManager ipcManager)
: base(logger, mediator, "###LightlessSyncMainUI", performanceCollectorService)
{
@@ -69,9 +74,12 @@ public class CompactUi : WindowMediatorSubscriberBase
_fileTransferManager = fileTransferManager;
_tagHandler = tagHandler;
_drawEntityFactory = drawEntityFactory;
_selectGroupForPairUi = selectTagForPairUi;
_selectTagForPairUi = selectTagForPairUi;
_selectTagForSyncshellUi = selectTagForSyncshellUi;
_selectSyncshellForTagUi = selectSyncshellForTagUi;
_renameSyncshellTagUi = renameSyncshellTagUi;
_selectPairsForGroupUi = selectPairForTagUi;
_renameTagUi = renameTagUi;
_renamePairTagUi = renameTagUi;
_ipcManager = ipcManager;
_tabMenu = new TopTabMenu(Mediator, _apiController, _pairManager, _uiSharedService);
@@ -199,9 +207,12 @@ public class CompactUi : WindowMediatorSubscriberBase
float pairlistEnd = ImGui.GetCursorPosY();
using (ImRaii.PushId("transfers")) DrawTransfers();
_transferPartHeight = ImGui.GetCursorPosY() - pairlistEnd - ImGui.GetTextLineHeight();
using (ImRaii.PushId("group-user-popup")) _selectPairsForGroupUi.Draw(_pairManager.DirectPairs);
using (ImRaii.PushId("group-user-edit")) _renameTagUi.Draw(_pairManager.DirectPairs);
using (ImRaii.PushId("grouping-popup")) _selectGroupForPairUi.Draw();
using (ImRaii.PushId("group-pair-popup")) _selectPairsForGroupUi.Draw(_pairManager.DirectPairs);
using (ImRaii.PushId("group-syncshell-popup")) _selectSyncshellForTagUi.Draw([.. _pairManager.Groups.Values]);
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)
@@ -462,12 +473,12 @@ public class CompactUi : WindowMediatorSubscriberBase
bool FilterVisibleUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u)
=> u.Key.IsVisible
&& (_configService.Current.ShowSyncshellUsersInVisible || !(!_configService.Current.ShowSyncshellUsersInVisible && !u.Key.IsDirectlyPaired));
bool FilterTagusers(KeyValuePair<Pair, List<GroupFullInfoDto>> u, string tag)
=> u.Key.IsDirectlyPaired && !u.Key.IsOneSidedPair && _tagHandler.HasTag(u.Key.UserData.UID, tag);
bool FilterTagUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u, string tag)
=> u.Key.IsDirectlyPaired && !u.Key.IsOneSidedPair && _tagHandler.HasPairTag(u.Key.UserData.UID, tag);
bool FilterGroupUsers(KeyValuePair<Pair, List<GroupFullInfoDto>> u, GroupFullInfoDto group)
=> u.Value.Exists(g => string.Equals(g.GID, group.GID, StringComparison.Ordinal));
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)
=> ((u.Key.IsDirectlyPaired && _configService.Current.ShowSyncshellOfflineUsersSeparately)
|| !_configService.Current.ShowSyncshellOfflineUsersSeparately)
@@ -487,46 +498,48 @@ public class CompactUi : WindowMediatorSubscriberBase
}
List<IDrawFolder> groupFolders = new();
foreach (var group in _pairManager.GroupPairs.Select(g => g.Key).OrderBy(g => g.GroupAliasOrGID, StringComparer.OrdinalIgnoreCase))
{
var allGroupPairs = ImmutablePairList(allPairs
.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);
GetGroups(allPairs, filteredPairs, group, out ImmutableList<Pair> allGroupPairs, out Dictionary<Pair, List<GroupFullInfoDto>> filteredGroupPairs);
groupFolders.Add(_drawEntityFactory.CreateDrawGroupFolder(group, filteredGroupPairs, allGroupPairs));
}
if (_configService.Current.GroupUpSyncshells)
drawFolders.Add(new DrawGroupedGroupFolder(groupFolders, _tagHandler, _uiSharedService));
drawFolders.Add(new DrawGroupedGroupFolder(groupFolders, _tagHandler, _uiSharedService, _selectSyncshellForTagUi, _renameSyncshellTagUi, ""));
else
drawFolders.AddRange(groupFolders);
var tags = _tagHandler.GetAllTagsSorted();
var tags = _tagHandler.GetAllPairTagsSorted();
foreach (var tag in tags)
{
var allTagPairs = ImmutablePairList(allPairs
.Where(u => FilterTagusers(u, tag)));
.Where(u => FilterTagUsers(u, tag)));
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));
}
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
.Where(FilterNotTaggedUsers));
var onlineNotTaggedPairs = BasicSortedDictionary(filteredPairs
@@ -561,6 +574,27 @@ public class CompactUi : WindowMediatorSubscriberBase
ImmutablePairList(allPairs.Where(u => u.Key.IsOneSidedPair))));
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()

View File

@@ -19,16 +19,18 @@ public class DrawFolderGroup : DrawFolderBase
private readonly GroupFullInfoDto _groupFullInfoDto;
private readonly IdDisplayHandler _idDisplayHandler;
private readonly LightlessMediator _lightlessMediator;
private readonly SelectTagForSyncshellUi _selectTagForSyncshellUi;
public DrawFolderGroup(string id, GroupFullInfoDto groupFullInfoDto, ApiController apiController,
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)
{
_groupFullInfoDto = groupFullInfoDto;
_apiController = apiController;
_idDisplayHandler = idDisplayHandler;
_lightlessMediator = lightlessMediator;
_selectTagForSyncshellUi = selectTagForSyncshellUi;
}
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");
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())
{
_ = _apiController.GroupLeave(_groupFullInfoDto);

View File

@@ -13,10 +13,10 @@ public class DrawFolderTag : DrawFolderBase
{
private readonly ApiController _apiController;
private readonly SelectPairForTagUi _selectPairForTagUi;
private readonly RenameTagUi _renameTagUi;
private readonly RenamePairTagUi _renameTagUi;
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)
{
_apiController = apiController;
@@ -112,7 +112,7 @@ public class DrawFolderTag : DrawFolderBase
}
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 +
"Note: this will not unpair with users in this Group.");

View File

@@ -9,20 +9,27 @@ namespace LightlessSync.UI.Components;
public class DrawGroupedGroupFolder : IDrawFolder
{
private readonly string _tag;
private readonly IEnumerable<IDrawFolder> _groups;
private readonly TagHandler _tagHandler;
private readonly UiSharedService _uiSharedService;
private readonly SelectSyncshellForTagUi _selectSyncshellForTagUi;
private readonly RenameSyncshellTagUi _renameSyncshellTagUi;
private bool _wasHovered = false;
private float _menuWidth;
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 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;
_tagHandler = tagHandler;
_uiSharedService = uiSharedService;
_selectSyncshellForTagUi = selectSyncshellForTagUi;
_renameSyncshellTagUi = renameSyncshellTagUi;
_tag = tag;
}
public void Draw()
@@ -30,6 +37,11 @@ public class DrawGroupedGroupFolder : IDrawFolder
if (!_groups.Any()) return;
string _id = "__folder_syncshells";
if (_tag != "")
{
_id = $"__folder_{_tag}";
}
using var id = ImRaii.PushId(_id);
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())))
@@ -49,18 +61,36 @@ public class DrawGroupedGroupFolder : IDrawFolder
ImGui.SameLine();
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();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted("[" + OnlinePairs.ToString() + "]");
_uiSharedService.IconText(FontAwesomeIcon.FolderPlus);
}
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 +
TotalPairs + " pairs combined in all of your joined syncshells");
ImGui.SameLine();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted("All Syncshells");
if (_tag != "")
{
ImGui.TextUnformatted(_tag);
ImGui.SameLine();
DrawMenu();
} else
{
ImGui.TextUnformatted("All Syncshells");
}
}
color.Dispose();
_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

@@ -1,36 +1,34 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.UI.Handlers;
using System.Numerics;
namespace LightlessSync.UI.Components;
public class RenameTagUi
public class RenamePairTagUi
{
private readonly TagHandler _tagHandler;
private readonly UiSharedService _uiSharedService;
private string _desiredName = string.Empty;
private bool _opened = false;
private HashSet<string> _peopleInGroup = new(StringComparer.Ordinal);
private bool _show = false;
private string _tag = string.Empty;
public RenameTagUi(TagHandler tagHandler, UiSharedService uiSharedService)
public RenamePairTagUi(TagHandler tagHandler, UiSharedService uiSharedService)
{
_tagHandler = tagHandler;
_uiSharedService = uiSharedService;
}
public void Draw(List<Pair> pairs)
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 Group {_tag}";
var popupName = $"Renaming Pair Group {_tag}";
if (!_show)
{
@@ -55,7 +53,7 @@ public class RenameTagUi
{
if (_uiSharedService.IconTextButton(Dalamud.Interface.FontAwesomeIcon.Plus, "Rename Group"))
{
RenameTag(pairs, _tag, _desiredName);
RenameTag(_tag, _desiredName);
_show = false;
}
}
@@ -69,25 +67,13 @@ public class RenameTagUi
public void Open(string tag)
{
_peopleInGroup = _tagHandler.GetOtherUidsForTag(tag);
_tag = tag;
_desiredName = "";
_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.
_tagHandler.AddTag(newTag);
foreach (Pair pair in pairs)
{
var isInTag = _peopleInGroup.Contains(pair.UserData.UID);
if (isInTag)
{
_tagHandler.AddTagToPairedUid(pair.UserData.UID, newTag);
}
}
public void RenameTag(string oldTag, string newTag)
{
_tagHandler.RenamePairTag(oldTag, 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, 255, 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)
{
_tagHandler.AddTagToPairedUid(item.UserData.UID, _tag);
_tagHandler.AddPairTagToPairedUid(item.UserData.UID, _tag);
_peopleInGroup.Add(item.UserData.UID);
}
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))
{
var tags = _tagHandler.GetAllTagsSorted();
var tags = _tagHandler.GetAllPairTagsSorted();
var childHeight = tags.Count != 0 ? tags.Count * 25 : 1;
var childSize = new Vector2(0, childHeight > 100 ? 100 : childHeight) * ImGuiHelpers.GlobalScale;
@@ -101,13 +101,13 @@ public class SelectTagForPairUi
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;
if (ImGui.Checkbox(name, ref hasTag))
{
if (hasTag)
{
_tagHandler.AddTagToPairedUid(pair.UserData.UID, name);
_tagHandler.AddPairTagToPairedUid(pair.UserData.UID, name);
}
else
{
@@ -120,10 +120,10 @@ public class SelectTagForPairUi
{
if (!_tagNameToAdd.IsNullOrWhitespace() && _tagNameToAdd is not (TagHandler.CustomOfflineTag or TagHandler.CustomOnlineTag or TagHandler.CustomVisibleTag))
{
_tagHandler.AddTag(_tagNameToAdd);
_tagHandler.AddPairTag(_tagNameToAdd);
if (_pair != null)
{
_tagHandler.AddTagToPairedUid(_pair.UserData.UID, _tagNameToAdd);
_tagHandler.AddPairTagToPairedUid(_pair.UserData.UID, _tagNameToAdd);
}
_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, 40);
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

@@ -23,21 +23,25 @@ public class DrawEntityFactory
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
private readonly CharaDataManager _charaDataManager;
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 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,
ServerConfigurationManager serverConfigurationManager, UiSharedService uiSharedService,
PlayerPerformanceConfigService playerPerformanceConfigService, CharaDataManager charaDataManager)
PlayerPerformanceConfigService playerPerformanceConfigService, CharaDataManager charaDataManager,
SelectTagForSyncshellUi selectTagForSyncshellUi, RenameSyncshellTagUi renameSyncshellTagUi, SelectSyncshellForTagUi selectSyncshellForTagUi)
{
_logger = logger;
_apiController = apiController;
_uidDisplayHandler = uidDisplayHandler;
_selectTagForPairUi = selectTagForPairUi;
_renameTagUi = renameTagUi;
_renamePairTagUi = renamePairTagUi;
_mediator = mediator;
_tagHandler = tagHandler;
_selectPairForTagUi = selectPairForTagUi;
@@ -45,6 +49,9 @@ public class DrawEntityFactory
_uiSharedService = uiSharedService;
_playerPerformanceConfigService = playerPerformanceConfigService;
_charaDataManager = charaDataManager;
_selectTagForSyncshellUi = selectTagForSyncshellUi;
_renameSyncshellTagUi = renameSyncshellTagUi;
_selectSyncshellForTagUi = selectSyncshellForTagUi;
}
public DrawFolderGroup CreateDrawGroupFolder(GroupFullInfoDto groupFullInfoDto,
@@ -53,7 +60,16 @@ public class DrawEntityFactory
{
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(),
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,
@@ -61,7 +77,7 @@ public class DrawEntityFactory
IImmutableList<Pair> allPairs)
{
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)

View File

@@ -43,9 +43,9 @@ public class IdDisplayHandler
if (ImGui.IsItemClicked(ImGuiMouseButton.Left))
{
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;
}

View File

@@ -17,61 +17,146 @@ public class TagHandler
_serverConfigurationManager = serverConfigurationManager;
}
public void AddTag(string tag)
{
_serverConfigurationManager.AddTag(tag);
}
/// <summary>
/// Creation of an pair 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)
{
_serverConfigurationManager.AddTagForUid(uid, tagName);
}
/// <summary>
/// Creation of an syncshell tag
/// </summary>
/// <param name="tag">Name of the tag</param>
public void AddSyncshellTag(string tag) => _serverConfigurationManager.AddSyncshellTag(tag);
public List<string> GetAllTagsSorted()
{
return
[
/// <summary>
/// Add pair to tag
/// </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()
.OrderBy(s => s, StringComparer.OrdinalIgnoreCase)
.Order(StringComparer.OrdinalIgnoreCase)
,
];
}
public HashSet<string> GetOtherUidsForTag(string tag)
{
return _serverConfigurationManager.GetUidsForTag(tag);
}
/// <summary>
/// Get all syncshell tags
/// </summary>
public List<string> GetAllSyncshellTagsSorted() => [
.. _serverConfigurationManager.GetServerAvailableSyncshellTags()
.Order(StringComparer.OrdinalIgnoreCase)
,
];
public bool HasAnyTag(string uid)
{
return _serverConfigurationManager.HasTags(uid);
}
/// <summary>
/// Get all UIDs bound to an given tag
/// </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)
{
return _serverConfigurationManager.ContainsTag(uid, tagName);
}
/// <summary>
/// Get all syncshells bound to an given tag
/// </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>
/// Is this tag opened in the paired clients UI?
/// </summary>
/// <param name="tag">the tag</param>
/// <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);
}
public void RemoveTagFromPairedUid(string uid, string tagName)
{
_serverConfigurationManager.RemoveTagForUid(uid, tagName);
_serverConfigurationManager.RenameSyncshellTag(oldName, newName);
}
/// <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)
{
if (open)