Added UI elements for syncshell folders

This commit is contained in:
CakeAndBanana
2025-09-08 18:27:05 +02:00
parent 75d23021ef
commit 900af91013
11 changed files with 489 additions and 122 deletions

View File

@@ -22,16 +22,16 @@ Global
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BB929046-4CD2-B174-EBAA-C756AC3AC8DA}.Debug|Any CPU.ActiveCfg = Release|x64
{BB929046-4CD2-B174-EBAA-C756AC3AC8DA}.Debug|Any CPU.Build.0 = Release|x64
{BB929046-4CD2-B174-EBAA-C756AC3AC8DA}.Debug|Any CPU.ActiveCfg = Debug|x64
{BB929046-4CD2-B174-EBAA-C756AC3AC8DA}.Debug|Any CPU.Build.0 = Debug|x64
{BB929046-4CD2-B174-EBAA-C756AC3AC8DA}.Debug|x64.ActiveCfg = Debug|x64
{BB929046-4CD2-B174-EBAA-C756AC3AC8DA}.Debug|x64.Build.0 = Debug|x64
{BB929046-4CD2-B174-EBAA-C756AC3AC8DA}.Release|Any CPU.ActiveCfg = Release|x64
{BB929046-4CD2-B174-EBAA-C756AC3AC8DA}.Release|Any CPU.Build.0 = Release|x64
{BB929046-4CD2-B174-EBAA-C756AC3AC8DA}.Release|x64.ActiveCfg = Release|x64
{BB929046-4CD2-B174-EBAA-C756AC3AC8DA}.Release|x64.Build.0 = Release|x64
{A4E42AFA-5045-7E81-937F-3A320AC52987}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{A4E42AFA-5045-7E81-937F-3A320AC52987}.Debug|Any CPU.Build.0 = Release|Any CPU
{A4E42AFA-5045-7E81-937F-3A320AC52987}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A4E42AFA-5045-7E81-937F-3A320AC52987}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4E42AFA-5045-7E81-937F-3A320AC52987}.Debug|x64.ActiveCfg = Debug|Any CPU
{A4E42AFA-5045-7E81-937F-3A320AC52987}.Debug|x64.Build.0 = Debug|Any CPU
{A4E42AFA-5045-7E81-937F-3A320AC52987}.Release|Any CPU.ActiveCfg = Release|Any CPU

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>>(),
@@ -200,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

@@ -341,7 +341,7 @@ public class ServerConfigurationManager
}
else
{
CurrentPairTagStorage().UidServerPairedUserTags[syncshellName] = [tagName];
CurrentSyncshellTagStorage().SyncshellPairedTags[syncshellName] = [tagName];
}
_syncshellTagConfig.Save();
@@ -608,7 +608,7 @@ public class ServerConfigurationManager
private void TryCreateCurrentSyncshellTagStorage()
{
if (!_pairTagConfig.Current.ServerTagStorage.ContainsKey(CurrentApiUrl))
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;
@@ -36,9 +35,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 +59,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 +73,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 +206,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.ToList());
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)
@@ -534,12 +544,29 @@ public class CompactUi : WindowMediatorSubscriberBase
_logger.LogInformation($"Loading {syncshellTags.Count} syncshell tags");
foreach (var syncshelltag in syncshellTags)
{
var allTagPairs = ImmutablePairList(allPairs
.Where(u => FilterTagUsers(u, syncshelltag)));
var filteredTagPairs = BasicSortedDictionary(filteredPairs
.Where(u => FilterTagUsers(u, syncshelltag) && FilterOnlineOrPausedSelf(u)));
foreach (var group in _pairManager.GroupPairs.Select(g => g.Key).OrderBy(g => g.GroupAliasOrGID, StringComparer.OrdinalIgnoreCase))
{
var allGroupPairs = ImmutablePairList(allPairs
.Where(u => FilterTagSyncshells(u, syncshelltag)));
drawFolders.Add(_drawEntityFactory.CreateDrawTagFolder(syncshelltag, filteredTagPairs, allTagPairs));
var filteredGroupPairs = filteredPairs
.Where(u => FilterTagSyncshells(u, syncshelltag) && 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, syncshelltag));
}
}
var allOnlineNotTaggedPairs = ImmutablePairList(allPairs

View File

@@ -19,16 +19,26 @@ public class DrawFolderGroup : DrawFolderBase
private readonly GroupFullInfoDto _groupFullInfoDto;
private readonly IdDisplayHandler _idDisplayHandler;
private readonly LightlessMediator _lightlessMediator;
private readonly SelectSyncshellForTagUi _selectSyncshellForTagUi;
private readonly RenameSyncshellTagUi _renameTagUi;
private readonly SelectTagForSyncshellUi _selectTagForSyncshellUi;
private readonly bool _isTag;
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,
SelectSyncshellForTagUi selectSyncshellForTagUi, RenameSyncshellTagUi renameTagUi, SelectTagForSyncshellUi selectTagForSyncshellUi,
bool isTag) :
base(id, drawPairs, allPairs, tagHandler, uiSharedService)
{
_groupFullInfoDto = groupFullInfoDto;
_apiController = apiController;
_idDisplayHandler = idDisplayHandler;
_lightlessMediator = lightlessMediator;
_selectSyncshellForTagUi = selectSyncshellForTagUi;
_renameTagUi = renameTagUi;
_selectTagForSyncshellUi = selectTagForSyncshellUi;
_isTag = isTag;
}
protected override bool RenderIfEmpty => true;
@@ -81,81 +91,109 @@ public class DrawFolderGroup : DrawFolderBase
protected override void DrawMenu(float menuWidth)
{
ImGui.TextUnformatted("Syncshell Menu (" + _groupFullInfoDto.GroupAliasOrGID + ")");
ImGui.Separator();
ImGui.TextUnformatted("General Syncshell Actions");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Copy, "Copy ID", menuWidth, true))
{
ImGui.CloseCurrentPopup();
ImGui.SetClipboardText(_groupFullInfoDto.GroupAliasOrGID);
}
UiSharedService.AttachToolTip("Copy Syncshell ID to Clipboard");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.StickyNote, "Copy Notes", menuWidth, true))
{
ImGui.CloseCurrentPopup();
ImGui.SetClipboardText(UiSharedService.GetNotes(DrawPairs.Select(k => k.Pair).ToList()));
}
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.ArrowCircleLeft, "Leave Syncshell", menuWidth, true) && UiSharedService.CtrlPressed())
{
_ = _apiController.GroupLeave(_groupFullInfoDto);
ImGui.CloseCurrentPopup();
}
UiSharedService.AttachToolTip("Hold CTRL and click to leave this Syncshell" + (!string.Equals(_groupFullInfoDto.OwnerUID, _apiController.UID, StringComparison.Ordinal)
? string.Empty : Environment.NewLine + "WARNING: This action is irreversible" + Environment.NewLine + "Leaving an owned Syncshell will transfer the ownership to a random person in the Syncshell."));
ImGui.Separator();
ImGui.TextUnformatted("Permission Settings");
var perm = _groupFullInfoDto.GroupUserPermissions;
bool disableSounds = perm.IsDisableSounds();
bool disableAnims = perm.IsDisableAnimations();
bool disableVfx = perm.IsDisableVFX();
if ((_groupFullInfoDto.GroupPermissions.IsPreferDisableAnimations() != disableAnims
|| _groupFullInfoDto.GroupPermissions.IsPreferDisableSounds() != disableSounds
|| _groupFullInfoDto.GroupPermissions.IsPreferDisableVFX() != disableVfx)
&& _uiSharedService.IconTextButton(FontAwesomeIcon.Check, "Align with suggested permissions", menuWidth, true))
{
perm.SetDisableVFX(_groupFullInfoDto.GroupPermissions.IsPreferDisableVFX());
perm.SetDisableSounds(_groupFullInfoDto.GroupPermissions.IsPreferDisableSounds());
perm.SetDisableAnimations(_groupFullInfoDto.GroupPermissions.IsPreferDisableAnimations());
_ = _apiController.GroupChangeIndividualPermissionState(new(_groupFullInfoDto.Group, new(_apiController.UID), perm));
ImGui.CloseCurrentPopup();
}
if (_uiSharedService.IconTextButton(disableSounds ? FontAwesomeIcon.VolumeUp : FontAwesomeIcon.VolumeOff, disableSounds ? "Enable Sound Sync" : "Disable Sound Sync", menuWidth, true))
{
perm.SetDisableSounds(!disableSounds);
_ = _apiController.GroupChangeIndividualPermissionState(new(_groupFullInfoDto.Group, new(_apiController.UID), perm));
ImGui.CloseCurrentPopup();
}
if (_uiSharedService.IconTextButton(disableAnims ? FontAwesomeIcon.Running : FontAwesomeIcon.Stop, disableAnims ? "Enable Animation Sync" : "Disable Animation Sync", menuWidth, true))
{
perm.SetDisableAnimations(!disableAnims);
_ = _apiController.GroupChangeIndividualPermissionState(new(_groupFullInfoDto.Group, new(_apiController.UID), perm));
ImGui.CloseCurrentPopup();
}
if (_uiSharedService.IconTextButton(disableVfx ? FontAwesomeIcon.Sun : FontAwesomeIcon.Circle, disableVfx ? "Enable VFX Sync" : "Disable VFX Sync", menuWidth, true))
{
perm.SetDisableVFX(!disableVfx);
_ = _apiController.GroupChangeIndividualPermissionState(new(_groupFullInfoDto.Group, new(_apiController.UID), perm));
ImGui.CloseCurrentPopup();
}
if (IsModerator || IsOwner)
if (!_isTag)
{
ImGui.TextUnformatted("Syncshell Menu (" + _groupFullInfoDto.GroupAliasOrGID + ")");
ImGui.Separator();
ImGui.TextUnformatted("Syncshell Admin Functions");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Cog, "Open Admin Panel", menuWidth, true))
ImGui.TextUnformatted("General Syncshell Actions");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Copy, "Copy ID", menuWidth, true))
{
ImGui.CloseCurrentPopup();
_lightlessMediator.Publish(new OpenSyncshellAdminPanel(_groupFullInfoDto));
ImGui.SetClipboardText(_groupFullInfoDto.GroupAliasOrGID);
}
UiSharedService.AttachToolTip("Copy Syncshell ID to Clipboard");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.StickyNote, "Copy Notes", menuWidth, true))
{
ImGui.CloseCurrentPopup();
ImGui.SetClipboardText(UiSharedService.GetNotes(DrawPairs.Select(k => k.Pair).ToList()));
}
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);
ImGui.CloseCurrentPopup();
}
UiSharedService.AttachToolTip("Hold CTRL and click to leave this Syncshell" + (!string.Equals(_groupFullInfoDto.OwnerUID, _apiController.UID, StringComparison.Ordinal)
? string.Empty : Environment.NewLine + "WARNING: This action is irreversible" + Environment.NewLine + "Leaving an owned Syncshell will transfer the ownership to a random person in the Syncshell."));
ImGui.Separator();
ImGui.TextUnformatted("Permission Settings");
var perm = _groupFullInfoDto.GroupUserPermissions;
bool disableSounds = perm.IsDisableSounds();
bool disableAnims = perm.IsDisableAnimations();
bool disableVfx = perm.IsDisableVFX();
if ((_groupFullInfoDto.GroupPermissions.IsPreferDisableAnimations() != disableAnims
|| _groupFullInfoDto.GroupPermissions.IsPreferDisableSounds() != disableSounds
|| _groupFullInfoDto.GroupPermissions.IsPreferDisableVFX() != disableVfx)
&& _uiSharedService.IconTextButton(FontAwesomeIcon.Check, "Align with suggested permissions", menuWidth, true))
{
perm.SetDisableVFX(_groupFullInfoDto.GroupPermissions.IsPreferDisableVFX());
perm.SetDisableSounds(_groupFullInfoDto.GroupPermissions.IsPreferDisableSounds());
perm.SetDisableAnimations(_groupFullInfoDto.GroupPermissions.IsPreferDisableAnimations());
_ = _apiController.GroupChangeIndividualPermissionState(new(_groupFullInfoDto.Group, new(_apiController.UID), perm));
ImGui.CloseCurrentPopup();
}
if (_uiSharedService.IconTextButton(disableSounds ? FontAwesomeIcon.VolumeUp : FontAwesomeIcon.VolumeOff, disableSounds ? "Enable Sound Sync" : "Disable Sound Sync", menuWidth, true))
{
perm.SetDisableSounds(!disableSounds);
_ = _apiController.GroupChangeIndividualPermissionState(new(_groupFullInfoDto.Group, new(_apiController.UID), perm));
ImGui.CloseCurrentPopup();
}
if (_uiSharedService.IconTextButton(disableAnims ? FontAwesomeIcon.Running : FontAwesomeIcon.Stop, disableAnims ? "Enable Animation Sync" : "Disable Animation Sync", menuWidth, true))
{
perm.SetDisableAnimations(!disableAnims);
_ = _apiController.GroupChangeIndividualPermissionState(new(_groupFullInfoDto.Group, new(_apiController.UID), perm));
ImGui.CloseCurrentPopup();
}
if (_uiSharedService.IconTextButton(disableVfx ? FontAwesomeIcon.Sun : FontAwesomeIcon.Circle, disableVfx ? "Enable VFX Sync" : "Disable VFX Sync", menuWidth, true))
{
perm.SetDisableVFX(!disableVfx);
_ = _apiController.GroupChangeIndividualPermissionState(new(_groupFullInfoDto.Group, new(_apiController.UID), perm));
ImGui.CloseCurrentPopup();
}
if (IsModerator || IsOwner)
{
ImGui.Separator();
ImGui.TextUnformatted("Syncshell Admin Functions");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Cog, "Open Admin Panel", menuWidth, true))
{
ImGui.CloseCurrentPopup();
_lightlessMediator.Publish(new OpenSyncshellAdminPanel(_groupFullInfoDto));
}
}
}
else
{
ImGui.TextUnformatted("Group Menu");
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Users, "Select Syncshells", menuWidth, isInPopup: true))
{
_selectSyncshellForTagUi.Open(_id);
}
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Edit, "Rename Syncshell Group", menuWidth, isInPopup: true))
{
_renameTagUi.Open(_id);
}
if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete Syncshell Group", menuWidth, isInPopup: true) && UiSharedService.CtrlPressed())
{
_tagHandler.RemoveSyncshellTag(_id);
}
UiSharedService.AttachToolTip("Hold CTRL to remove this Group permanently." + Environment.NewLine +
"Note: this will not unpair the Group.");
}
}

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;

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.RemovePairTag(oldTag);
//Creation of new tag and adding of old group pairs in new one.
_tagHandler.AddPairTag(newTag);
foreach (Pair pair in pairs)
{
var isInTag = _peopleInGroup.Contains(pair.UserData.UID);
if (isInTag)
{
_tagHandler.AddPairTagToPairedUid(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 Pair 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.RenamePairTag(oldTag, newTag);
}
}

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.GID, StringComparer.OrdinalIgnoreCase)
.ToList())
{
var isInGroup = _syncshellsInGroup.Contains(group.GID);
if (ImGui.Checkbox(group.GID, 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

@@ -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.GID;
var popupName = $"Choose Groups for {_group.GID}";
// 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, _selectSyncshellForTagUi, _renameSyncshellTagUi, _selectTagForSyncshellUi, false);
}
public DrawFolderGroup CreateDrawGroupFolder(GroupFullInfoDto groupFullInfoDto,
Dictionary<Pair, List<GroupFullInfoDto>> filteredPairs,
IImmutableList<Pair> allPairs, string tag)
{
return new DrawFolderGroup(tag, groupFullInfoDto, _apiController,
filteredPairs.Select(p => CreateDrawPair(tag, p.Key, p.Value, groupFullInfoDto)).ToImmutableList(),
allPairs, _tagHandler, _uidDisplayHandler, _mediator, _uiSharedService, _selectSyncshellForTagUi, _renameSyncshellTagUi, _selectTagForSyncshellUi, true);
}
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)