diff --git a/LightlessAPI b/LightlessAPI index a337481..3a69c94 160000 --- a/LightlessAPI +++ b/LightlessAPI @@ -1 +1 @@ -Subproject commit a337481243a11490f3a115ca1ac0abfdd62c0554 +Subproject commit 3a69c94f7fb10a0cfc51c857b2194640fda48140 diff --git a/LightlessSync/Plugin.cs b/LightlessSync/Plugin.cs index 3eada46..f09832e 100644 --- a/LightlessSync/Plugin.cs +++ b/LightlessSync/Plugin.cs @@ -138,7 +138,7 @@ public sealed class Plugin : IDalamudPlugin s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); collection.AddSingleton((s) => new DtrEntry(s.GetRequiredService>(), dtrBar, s.GetRequiredService(), - s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); + s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); collection.AddSingleton(s => new PairManager(s.GetRequiredService>(), s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService(), contextMenu)); collection.AddSingleton(); diff --git a/LightlessSync/Services/UiFactory.cs b/LightlessSync/Services/UiFactory.cs index aaa7f96..5aaab5e 100644 --- a/LightlessSync/Services/UiFactory.cs +++ b/LightlessSync/Services/UiFactory.cs @@ -3,7 +3,6 @@ using LightlessSync.PlayerData.Pairs; using LightlessSync.Services.Mediator; using LightlessSync.Services.ServerConfiguration; using LightlessSync.UI; -using LightlessSync.UI.Components.Popup; using LightlessSync.WebAPI; using Microsoft.Extensions.Logging; diff --git a/LightlessSync/Services/UiService.cs b/LightlessSync/Services/UiService.cs index 0aceb78..4071b61 100644 --- a/LightlessSync/Services/UiService.cs +++ b/LightlessSync/Services/UiService.cs @@ -4,7 +4,6 @@ using Dalamud.Interface.Windowing; using LightlessSync.LightlessConfiguration; using LightlessSync.Services.Mediator; using LightlessSync.UI; -using LightlessSync.UI.Components.Popup; using Microsoft.Extensions.Logging; namespace LightlessSync.Services; diff --git a/LightlessSync/UI/CharaDataHubUi.GposeTogether.cs b/LightlessSync/UI/CharaDataHubUi.GposeTogether.cs index af9b602..0416ab7 100644 --- a/LightlessSync/UI/CharaDataHubUi.GposeTogether.cs +++ b/LightlessSync/UI/CharaDataHubUi.GposeTogether.cs @@ -90,7 +90,7 @@ internal sealed partial class CharaDataHubUi if (!_uiSharedService.IsInGpose) { 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(); ImGui.TextUnformatted("Users In Lobby"); @@ -104,7 +104,7 @@ internal sealed partial class CharaDataHubUi 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 { diff --git a/LightlessSync/UI/CharaDataHubUi.McdOnline.cs b/LightlessSync/UI/CharaDataHubUi.McdOnline.cs index ed2c624..e86ef10 100644 --- a/LightlessSync/UI/CharaDataHubUi.McdOnline.cs +++ b/LightlessSync/UI/CharaDataHubUi.McdOnline.cs @@ -23,7 +23,7 @@ internal sealed partial class CharaDataHubUi if (dataDto == null) { 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; } @@ -31,7 +31,7 @@ internal sealed partial class CharaDataHubUi 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; } @@ -75,7 +75,7 @@ internal sealed partial class CharaDataHubUi } 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) { - 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")) { @@ -112,7 +112,7 @@ internal sealed partial class CharaDataHubUi UiSharedService.DrawGrouped(() => { 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(); using (ImRaii.Disabled(_charaDataManager.CharaUpdateTask != null && !_charaDataManager.CharaUpdateTask.IsCompleted)) { @@ -259,7 +259,7 @@ internal sealed partial class CharaDataHubUi ImGui.SameLine(); ImGuiHelpers.ScaledDummy(20, 1); 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"); @@ -414,7 +414,7 @@ internal sealed partial class CharaDataHubUi } } 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"); ImGuiHelpers.ScaledDummy(5); @@ -424,7 +424,7 @@ internal sealed partial class CharaDataHubUi if (!_uiSharedService.IsInGpose && _charaDataManager.BrioAvailable) { 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); } else if (!_charaDataManager.BrioAvailable) @@ -443,7 +443,7 @@ internal sealed partial class CharaDataHubUi if (pose.Id == null) { 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."); } @@ -451,14 +451,14 @@ internal sealed partial class CharaDataHubUi if (poseHasChanges) { 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.ScaledSameLine(75); 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 { @@ -669,7 +669,7 @@ internal sealed partial class CharaDataHubUi var idText = entry.FullId; if (uDto?.HasChanges ?? false) { - UiSharedService.ColorText(idText, ImGuiColors.DalamudYellow); + UiSharedService.ColorText(idText, UIColors.Get("LightlessYellow")); UiSharedService.AttachToolTip("This entry has unsaved changes"); } else @@ -724,7 +724,7 @@ internal sealed partial class CharaDataHubUi FontAwesomeIcon eIcon = FontAwesomeIcon.None; if (!Equals(DateTime.MaxValue, entry.ExpiryDate)) eIcon = FontAwesomeIcon.Clock; - _uiSharedService.IconText(eIcon, ImGuiColors.DalamudYellow); + _uiSharedService.IconText(eIcon, UIColors.Get("LightlessYellow")); if (ImGui.IsItemClicked()) SelectedDtoId = entry.Id; if (eIcon != FontAwesomeIcon.None) { @@ -759,13 +759,13 @@ internal sealed partial class CharaDataHubUi if (_charaDataManager.OwnCharaData.Count == _charaDataManager.MaxCreatableCharaData) { 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) { - 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) { diff --git a/LightlessSync/UI/CharaDataHubUi.NearbyPoses.cs b/LightlessSync/UI/CharaDataHubUi.NearbyPoses.cs index e7d985f..f93d861 100644 --- a/LightlessSync/UI/CharaDataHubUi.NearbyPoses.cs +++ b/LightlessSync/UI/CharaDataHubUi.NearbyPoses.cs @@ -78,7 +78,7 @@ internal partial class CharaDataHubUi if (!_uiSharedService.IsInGpose) { 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); } @@ -93,7 +93,7 @@ internal partial class CharaDataHubUi using var indent = ImRaii.PushIndent(5f); 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; diff --git a/LightlessSync/UI/CharaDataHubUi.cs b/LightlessSync/UI/CharaDataHubUi.cs index f0a4eb9..9016e6c 100644 --- a/LightlessSync/UI/CharaDataHubUi.cs +++ b/LightlessSync/UI/CharaDataHubUi.cs @@ -190,7 +190,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase } if (!string.IsNullOrEmpty(_charaDataManager.DataApplicationProgress)) { - UiSharedService.ColorTextWrapped(_charaDataManager.DataApplicationProgress, ImGuiColors.DalamudYellow); + UiSharedService.ColorTextWrapped(_charaDataManager.DataApplicationProgress, UIColors.Get("LightlessYellow")); } if (_charaDataManager.DataApplicationTask != null) { @@ -436,7 +436,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase if (!_hasValidGposeTarget) { 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); @@ -595,7 +595,7 @@ internal sealed partial class CharaDataHubUi : WindowMediatorSubscriberBase 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(); 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) { @@ -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.", ImGuiColors.DalamudRed); 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 { - 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); } 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(); } diff --git a/LightlessSync/UI/Components/DrawFolderGroup.cs b/LightlessSync/UI/Components/DrawFolderGroup.cs index d6e5b04..11737e9 100644 --- a/LightlessSync/UI/Components/DrawFolderGroup.cs +++ b/LightlessSync/UI/Components/DrawFolderGroup.cs @@ -185,7 +185,7 @@ public class DrawFolderGroup : DrawFolderBase _uiSharedService.IconText(FontAwesomeIcon.UsersCog, (_groupFullInfoDto.GroupPermissions.IsPreferDisableAnimations() != individualAnimDisabled || _groupFullInfoDto.GroupPermissions.IsPreferDisableSounds() != individualSoundsDisabled - || _groupFullInfoDto.GroupPermissions.IsPreferDisableVFX() != individualVFXDisabled) ? ImGuiColors.DalamudYellow : null); + || _groupFullInfoDto.GroupPermissions.IsPreferDisableVFX() != individualVFXDisabled) ? UIColors.Get("LightlessYellow") : null); if (ImGui.IsItemHovered()) { ImGui.BeginTooltip(); diff --git a/LightlessSync/UI/Components/DrawUserPair.cs b/LightlessSync/UI/Components/DrawUserPair.cs index b4f5848..398af1a 100644 --- a/LightlessSync/UI/Components/DrawUserPair.cs +++ b/LightlessSync/UI/Components/DrawUserPair.cs @@ -196,7 +196,7 @@ public class DrawUserPair if (_pair.IsPaused) { - using var _ = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudYellow); + using var _ = ImRaii.PushColor(ImGuiCol.Text, UIColors.Get("LightlessYellow")); _uiSharedService.IconText(FontAwesomeIcon.PauseCircle); userPairText = _pair.UserData.AliasOrUID + " is paused"; } @@ -274,7 +274,7 @@ public class DrawUserPair { 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; bool shownVram = false; @@ -376,7 +376,7 @@ public class DrawUserPair currentRightSide -= (_uiSharedService.GetIconSize(individualIcon).X + spacingX); 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); if (ImGui.IsItemHovered()) { diff --git a/LightlessSync/UI/DataAnalysisUi.cs b/LightlessSync/UI/DataAnalysisUi.cs index 032b3d4..e1ef15c 100644 --- a/LightlessSync/UI/DataAnalysisUi.cs +++ b/LightlessSync/UI/DataAnalysisUi.cs @@ -371,7 +371,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase 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, " + "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); 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); @@ -399,7 +399,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase if (_transientResourceManager.IsTransientRecording) { 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); 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)) { 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); } @@ -485,7 +485,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase if (isAnalyzing) { UiSharedService.ColorTextWrapped($"Analyzing {_characterAnalyzer.CurrentFile}/{_characterAnalyzer.TotalFiles}", - ImGuiColors.DalamudYellow); + UIColors.Get("LightlessYellow")); if (_uiSharedService.IconTextButton(FontAwesomeIcon.StopCircle, "Cancel analysis")) { _characterAnalyzer.CancelAnalyze(); @@ -496,7 +496,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase 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", - ImGuiColors.DalamudYellow); + UIColors.Get("LightlessYellow")); if (_uiSharedService.IconTextButton(FontAwesomeIcon.PlayCircle, "Start analysis (missing entries)")) { _ = _characterAnalyzer.ComputeAnalysis(print: false); @@ -592,7 +592,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase { UiSharedService.ColorText($"You exceed your own threshold by " + $"{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 " + $"{actualTriCount - (currentTriWarning * 1000)} triangles.", - ImGuiColors.DalamudYellow); + UIColors.Get("LightlessYellow")); } } @@ -629,7 +629,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase { string fileGroupText = fileGroup.Key + " [" + fileGroup.Count() + "]"; 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) { fileGroupText += " (!)"; @@ -668,7 +668,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase ImGui.Checkbox("Enable BC7 Conversion Mode", ref _enableBc7ConversionMode); if (_enableBc7ConversionMode) { - UiSharedService.ColorText("WARNING BC7 CONVERSION:", ImGuiColors.DalamudYellow); + UiSharedService.ColorText("WARNING BC7 CONVERSION:", UIColors.Get("LightlessYellow")); ImGui.SameLine(); 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." + @@ -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 + "- 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." - , ImGuiColors.DalamudYellow); + , UIColors.Get("LightlessYellow")); if (_texturesToConvert.Count > 0 && _uiSharedService.IconTextButton(FontAwesomeIcon.PlayCircle, "Start conversion of " + _texturesToConvert.Count + " texture(s)")) { _conversionCancellationTokenSource = _conversionCancellationTokenSource.CancelRecreate(); @@ -697,7 +697,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase ImGui.TextUnformatted("Selected file:"); ImGui.SameLine(); - UiSharedService.ColorText(_selectedHash, ImGuiColors.DalamudYellow); + UiSharedService.ColorText(_selectedHash, UIColors.Get("LightlessYellow")); 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)) { - ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg1, UiSharedService.Color(ImGuiColors.DalamudYellow)); - ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg0, UiSharedService.Color(ImGuiColors.DalamudYellow)); + ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg1, UiSharedService.Color(UIColors.Get("LightlessYellow"))); + ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg0, UiSharedService.Color(UIColors.Get("LightlessYellow"))); } ImGui.TextUnformatted(item.Hash); if (ImGui.IsItemClicked()) _selectedHash = item.Hash; diff --git a/LightlessSync/UI/DtrEntry.cs b/LightlessSync/UI/DtrEntry.cs index f83c4c6..0335136 100644 --- a/LightlessSync/UI/DtrEntry.cs +++ b/LightlessSync/UI/DtrEntry.cs @@ -6,7 +6,9 @@ using LightlessSync.LightlessConfiguration; using LightlessSync.LightlessConfiguration.Configurations; using LightlessSync.PlayerData.Pairs; using LightlessSync.Services.Mediator; +using LightlessSync.Services.ServerConfiguration; using LightlessSync.WebAPI; +using LightlessSync.WebAPI.SignalR.Utils; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System.Runtime.InteropServices; @@ -16,6 +18,7 @@ namespace LightlessSync.UI; public sealed class DtrEntry : IDisposable, IHostedService { private readonly ApiController _apiController; + private readonly ServerConfigurationManager _serverManager; private readonly CancellationTokenSource _cancellationTokenSource = new(); private readonly ConfigurationServiceBase _configService; private readonly IDtrBar _dtrBar; @@ -28,7 +31,7 @@ public sealed class DtrEntry : IDisposable, IHostedService private string? _tooltip; private Colors _colors; - public DtrEntry(ILogger logger, IDtrBar dtrBar, ConfigurationServiceBase configService, LightlessMediator lightlessMediator, PairManager pairManager, ApiController apiController) + public DtrEntry(ILogger logger, IDtrBar dtrBar, ConfigurationServiceBase configService, LightlessMediator lightlessMediator, PairManager pairManager, ApiController apiController, ServerConfigurationManager serverManager) { _logger = logger; _dtrBar = dtrBar; @@ -37,6 +40,7 @@ public sealed class DtrEntry : IDisposable, IHostedService _lightlessMediator = lightlessMediator; _pairManager = pairManager; _apiController = apiController; + _serverManager = serverManager; } public void Dispose() @@ -59,7 +63,7 @@ public sealed class DtrEntry : IDisposable, IHostedService public async Task StopAsync(CancellationToken cancellationToken) { - _cancellationTokenSource.Cancel(); + await _cancellationTokenSource.CancelAsync().ConfigureAwait(false); try { await _runTask!.ConfigureAwait(false); @@ -89,10 +93,43 @@ public sealed class DtrEntry : IDisposable, IHostedService { _logger.LogTrace("Creating new DtrBar entry"); var entry = _dtrBar.Get("Lightless Sync"); - entry.OnClick = _ => _lightlessMediator.Publish(new UiToggleMessage(typeof(CompactUi))); + entry.OnClick = interactionEvent => OnClickEvent(interactionEvent); 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() { diff --git a/LightlessSync/UI/EventViewerUI.cs b/LightlessSync/UI/EventViewerUI.cs index 89c7083..9ce1536 100644 --- a/LightlessSync/UI/EventViewerUI.cs +++ b/LightlessSync/UI/EventViewerUI.cs @@ -110,7 +110,7 @@ internal class EventViewerUI : WindowMediatorSubscriberBase { ImGui.SameLine(); 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"); @@ -180,7 +180,7 @@ internal class EventViewerUI : WindowMediatorSubscriberBase var iconColor = ev.EventSeverity switch { EventSeverity.Informational => new Vector4(), - EventSeverity.Warning => ImGuiColors.DalamudYellow, + EventSeverity.Warning => UIColors.Get("LightlessYellow"), EventSeverity.Error => ImGuiColors.DalamudRed, _ => new Vector4() }; diff --git a/LightlessSync/UI/IntroUI.cs b/LightlessSync/UI/IntroUI.cs index f21e968..bc32128 100644 --- a/LightlessSync/UI/IntroUI.cs +++ b/LightlessSync/UI/IntroUI.cs @@ -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 " + "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; ImGui.Separator(); 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."); 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. " + - "Otherwise on the next launch a full re-scan of the file cache database will be initiated.", 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.", 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.", UIColors.Get("LightlessYellow")); _uiShared.DrawCacheDirectorySetting(); } @@ -197,7 +197,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase _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 " + - "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) @@ -255,7 +255,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase ImGuiHelpers.ScaledDummy(5); 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. " + - "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); ImGui.AlignTextToFramePadding(); diff --git a/LightlessSync/UI/JoinSyncshellUI.cs b/LightlessSync/UI/JoinSyncshellUI.cs index cb5c376..3de9026 100644 --- a/LightlessSync/UI/JoinSyncshellUI.cs +++ b/LightlessSync/UI/JoinSyncshellUI.cs @@ -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 + "- 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 + - "- 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 @@ -111,7 +111,7 @@ internal class JoinSyncshellUI : WindowMediatorSubscriberBase || _groupJoinInfo.GroupPermissions.IsPreferDisableAnimations() != _ownPermissions.DisableGroupAnimations) { 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) { ImGui.AlignTextToFramePadding(); diff --git a/LightlessSync/UI/PopoutProfileUi.cs b/LightlessSync/UI/PopoutProfileUi.cs index 5b28dc1..5a6557c 100644 --- a/LightlessSync/UI/PopoutProfileUi.cs +++ b/LightlessSync/UI/PopoutProfileUi.cs @@ -135,12 +135,12 @@ public class PopoutProfileUi : WindowMediatorSubscriberBase if (_pair.UserPair.OwnPermissions.IsPaused()) { ImGui.SameLine(); - UiSharedService.ColorText("You: paused", ImGuiColors.DalamudYellow); + UiSharedService.ColorText("You: paused", UIColors.Get("LightlessYellow")); } if (_pair.UserPair.OtherPermissions.IsPaused()) { ImGui.SameLine(); - UiSharedService.ColorText("They: paused", ImGuiColors.DalamudYellow); + UiSharedService.ColorText("They: paused", UIColors.Get("LightlessYellow")); } } if (_pair.UserPair.Groups.Any()) diff --git a/LightlessSync/UI/SettingsUi.cs b/LightlessSync/UI/SettingsUi.cs index 6f3158b..2832dd6 100644 --- a/LightlessSync/UI/SettingsUi.cs +++ b/LightlessSync/UI/SettingsUi.cs @@ -373,8 +373,8 @@ public class SettingsUi : WindowMediatorSubscriberBase } else if (!_speedTestTask.IsCompleted) { - UiSharedService.ColorTextWrapped("Running Speedtest to File Servers...", ImGuiColors.DalamudYellow); - UiSharedService.ColorTextWrapped("Please be patient, depending on usage and load this can take a while.", 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.", UIColors.Get("LightlessYellow")); if (_uiShared.IconTextButton(FontAwesomeIcon.Ban, "Cancel speedtest")) { _speedTestCts?.Cancel(); @@ -393,7 +393,7 @@ public class SettingsUi : WindowMediatorSubscriberBase } 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); - UiSharedService.ColorTextWrapped("Exporting MCDF has moved.", ImGuiColors.DalamudYellow); + UiSharedService.ColorTextWrapped("Exporting MCDF has moved.", UIColors.Get("LightlessYellow")); ImGuiHelpers.ScaledDummy(5); UiSharedService.TextWrapped("It is now found in the Main UI under \"Your User Menu\" ("); ImGui.SameLine(); @@ -720,7 +720,7 @@ public class SettingsUi : WindowMediatorSubscriberBase bool isLinux = _dalamudUtilService.IsWine; 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 (ImGui.Checkbox("Use file compactor", ref useFileCompactor)) @@ -756,7 +756,7 @@ public class SettingsUi : WindowMediatorSubscriberBase } 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) { @@ -974,37 +974,98 @@ public class SettingsUi : WindowMediatorSubscriberBase _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(); } - using (ImRaii.Disabled(!useColorsInDtr)) + ImGui.SameLine(); + if (InputDtrColors("Not Connected", ref dtrColorsNotConnected)) { - using var indent2 = ImRaii.PushIndent(); - if (InputDtrColors("Default", ref dtrColorsDefault)) - { - _configService.Current.DtrColorsDefault = dtrColorsDefault; - _configService.Save(); - } + _configService.Current.DtrColorsNotConnected = dtrColorsNotConnected; + _configService.Save(); + } - ImGui.SameLine(); - if (InputDtrColors("Not Connected", ref dtrColorsNotConnected)) - { - _configService.Current.DtrColorsNotConnected = dtrColorsNotConnected; - _configService.Save(); - } - - ImGui.SameLine(); - if (InputDtrColors("Pairs in Range", ref dtrColorsPairsInRange)) - { - _configService.Current.DtrColorsPairsInRange = dtrColorsPairsInRange; - _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 nameColors = _configService.Current.NameplateColors; var isFriendOverride = _configService.Current.overrideFriendColor; @@ -1016,6 +1077,7 @@ public class SettingsUi : WindowMediatorSubscriberBase _configService.Save(); _nameplateService.RequestRedraw(); } + _uiShared.DrawHelpText("This will override the nameplate colors for visible paired players in-game."); using (ImRaii.Disabled(!nameColorsEnabled)) { @@ -1119,7 +1181,6 @@ public class SettingsUi : WindowMediatorSubscriberBase _configService.Current.UseFocusTarget = useFocusTarget; _configService.Save(); } - _uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f); ImGui.TreePop(); } @@ -1553,7 +1614,7 @@ public class SettingsUi : WindowMediatorSubscriberBase var selectedServer = _serverConfigurationManager.GetServerByIndex(idx); 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; @@ -1565,7 +1626,7 @@ public class SettingsUi : WindowMediatorSubscriberBase if (selectedServer.SecretKeys.Any() || useOauth) { 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; _uiShared.DrawUpdateOAuthUIDsButton(selectedServer); @@ -1586,14 +1647,14 @@ public class SettingsUi : WindowMediatorSubscriberBase } 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) { Vector4? textColor = null; if (_secretKeysConversionTask.Result.PartialSuccess) { - textColor = ImGuiColors.DalamudYellow; + textColor = UIColors.Get("LightlessYellow"); } if (!_secretKeysConversionTask.Result.Success) { @@ -1627,10 +1688,10 @@ public class SettingsUi : WindowMediatorSubscriberBase if (authWithCid != null) { 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)) 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)) UiSharedService.ColorText("Current: " + youName + " - " + _dalamudUtilService.WorldData.Value[(ushort)youWorld], UIColors.Get("LightlessBlue")); ImGuiHelpers.ScaledDummy(5); @@ -1776,7 +1837,7 @@ public class SettingsUi : WindowMediatorSubscriberBase } 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(); @@ -1810,7 +1871,7 @@ public class SettingsUi : WindowMediatorSubscriberBase } 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()) @@ -1990,7 +2051,7 @@ public class SettingsUi : WindowMediatorSubscriberBase else { 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(); diff --git a/LightlessSync/UI/StandaloneProfileUi.cs b/LightlessSync/UI/StandaloneProfileUi.cs index 4484013..ca7d779 100644 --- a/LightlessSync/UI/StandaloneProfileUi.cs +++ b/LightlessSync/UI/StandaloneProfileUi.cs @@ -130,12 +130,12 @@ public class StandaloneProfileUi : WindowMediatorSubscriberBase if (Pair.UserPair.OwnPermissions.IsPaused()) { ImGui.SameLine(); - UiSharedService.ColorText("You: paused", ImGuiColors.DalamudYellow); + UiSharedService.ColorText("You: paused", UIColors.Get("LightlessYellow")); } if (Pair.UserPair.OtherPermissions.IsPaused()) { ImGui.SameLine(); - UiSharedService.ColorText("They: paused", ImGuiColors.DalamudYellow); + UiSharedService.ColorText("They: paused", UIColors.Get("LightlessYellow")); } } diff --git a/LightlessSync/UI/SyncshellAdminUI.cs b/LightlessSync/UI/SyncshellAdminUI.cs index b3c70d2..4cf254b 100644 --- a/LightlessSync/UI/SyncshellAdminUI.cs +++ b/LightlessSync/UI/SyncshellAdminUI.cs @@ -13,7 +13,7 @@ using LightlessSync.WebAPI; using Microsoft.Extensions.Logging; using System.Globalization; -namespace LightlessSync.UI.Components.Popup; +namespace LightlessSync.UI; public class SyncshellAdminUI : WindowMediatorSubscriberBase { @@ -63,7 +63,7 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase using var id = ImRaii.PushId("syncshell_admin_" + GroupFullInfo.GID); using (_uiSharedService.UidFont.Push()) - ImGui.TextUnformatted(GroupFullInfo.GroupAliasOrGID + " Administrative Panel"); + _uiSharedService.UnderlinedBigText(GroupFullInfo.GroupAliasOrGID + " Administrative Panel", UIColors.Get("LightlessBlue")); ImGui.Separator(); var perm = GroupFullInfo.GroupPermissions; @@ -72,133 +72,203 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase if (tabbar) { - var inviteTab = ImRaii.TabItem("Invites"); - if (inviteTab) - { - bool isInvitesDisabled = perm.IsDisableInvites(); + DrawInvites(perm); - if (_uiSharedService.IconTextButton(isInvitesDisabled ? FontAwesomeIcon.Unlock : FontAwesomeIcon.Lock, - isInvitesDisabled ? "Unlock Syncshell" : "Lock Syncshell")) + DrawManagement(); + + 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)); } + } - 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.AlignTextToFramePadding(); + ImGui.Text("Suggest Animation Sync"); + _uiSharedService.BooleanToColoredIcon(!isDisableAnimations); + 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); - } - 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); - } + perm.SetPreferDisableAnimations(!perm.IsPreferDisableAnimations()); + _ = _apiController.GroupChangeGroupPermissionState(new(GroupFullInfo.Group, perm)); } } - inviteTab.Dispose(); - var mgmtTab = ImRaii.TabItem("User Management"); - if (mgmtTab) + ImGui.AlignTextToFramePadding(); + 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 (userNode) + if (_uiSharedService.IconTextButton(isDisableVfx ? FontAwesomeIcon.Sun : FontAwesomeIcon.Circle, + 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); - if (table) + ImGui.TableSetupColumn("Alias/UID/Note", ImGuiTableColumnFlags.None, 5); + ImGui.TableSetupColumn("Flags", ImGuiTableColumnFlags.None, 1); + ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 2); + ImGui.TableHeadersRow(); + + var groupedPairs = new Dictionary(pairs.Select(p => new KeyValuePair(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); - ImGui.TableSetupColumn("Online/Name", ImGuiTableColumnFlags.None, 2); - ImGui.TableSetupColumn("Flags", ImGuiTableColumnFlags.None, 1); - ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.None, 2); - ImGui.TableHeadersRow(); + if (p.Value == null) return 10; + if (string.Equals(p.Key.UserData.UID, GroupFullInfo.OwnerUID, StringComparison.Ordinal)) return 0; + if (p.Value.Value.IsModerator()) return 1; + if (p.Value.Value.IsPinned()) return 2; + 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(pairs.Select(p => new KeyValuePair(p, - GroupFullInfo.GroupPairUserInfos.TryGetValue(p.UserData.UID, out GroupPairUserInfo value) ? value : null))); - - foreach (var pair in groupedPairs.OrderBy(p => + 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(); + var boolcolor = UiSharedService.GetBoolColor(pair.Key.IsOnline); + UiSharedService.ColorText(text, boolcolor); + if (!string.IsNullOrEmpty(pair.Key.PlayerName)) { - if (p.Value == null) return 10; - if (p.Value.Value.IsModerator()) return 0; - if (p.Value.Value.IsPinned()) return 1; - return 10; - }).ThenBy(p => p.Key.GetNote() ?? p.Key.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase)) + UiSharedService.AttachToolTip(pair.Key.PlayerName); + ImGui.SameLine(); + } + + 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); - - 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)) + if (pair.Value.Value.IsModerator()) { - onlineText += " (" + pair.Key.PlayerName + ")"; + _uiSharedService.IconText(FontAwesomeIcon.UserShield, UIColors.Get("LightlessPurple")); + UiSharedService.AttachToolTip("Moderator"); } - var boolcolor = UiSharedService.GetBoolColor(pair.Key.IsOnline); - 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.IsPinned() && !isUserOwner) { - if (pair.Value.Value.IsModerator()) - { - _uiSharedService.IconText(FontAwesomeIcon.UserShield); - UiSharedService.AttachToolTip("Moderator"); - } - if (pair.Value.Value.IsPinned()) - { - _uiSharedService.IconText(FontAwesomeIcon.Thumbtack); - UiSharedService.AttachToolTip("Pinned"); - } + _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 - if (_isOwner) + ImGui.TableNextColumn(); // actions + 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)); - } - UiSharedService.AttachToolTip(pair.Value != null && pair.Value.Value.IsModerator() ? "Demod user" : "Mod user"); - ImGui.SameLine(); + _ = _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(); + } - 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)) { @@ -208,9 +278,12 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase _ = _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())) { if (_uiSharedService.IconButton(FontAwesomeIcon.Trash)) @@ -218,10 +291,13 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase _ = _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())) { if (_uiSharedService.IconButton(FontAwesomeIcon.Ban)) @@ -229,224 +305,190 @@ public class SyncshellAdminUI : WindowMediatorSubscriberBase Mediator.Publish(new OpenBanUserPopupMessage(pair.Key, GroupFullInfo)); } } - UiSharedService.AttachToolTip("Ban user from Syncshell" - + UiSharedService.TooltipSeparator + "Hold CTRL to enable this button"); } - } - } - } - } - 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.AttachToolTip("Ban user from Syncshell" + 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) - { - UiSharedService.ColorTextWrapped("Pruning Syncshell...", ImGuiColors.DalamudYellow); - } - else - { - UiSharedService.TextWrapped($"Syncshell was pruned and {_pruneTask.Result} inactive user(s) have been removed."); - } + _ = _apiController.GroupClear(new(GroupFullInfo.Group)); } } - 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"); - if (banNode) + ImGuiHelpers.ScaledDummy(2f); + 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); } - - if (ImGui.BeginTable("bannedusertable" + GroupFullInfo.GID, 6, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingStretchProp | ImGuiTableFlags.ScrollY)) + else { - 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.AlignTextToFramePadding(); + UiSharedService.TextWrapped($"Found {_pruneTestTask.Result} user(s) that have not logged into Lightless in the past {_pruneDays} day(s)."); + if (_pruneTestTask.Result > 0) { - 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")) + using (ImRaii.Disabled(!UiSharedService.CtrlPressed())) { - _apiController.GroupUnbanUser(bannedUser); - _bannedUsers.RemoveAll(b => string.Equals(b.UID, bannedUser.UID, StringComparison.Ordinal)); + 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"); } - - ImGui.EndTable(); } } - banNode.Dispose(); - } - 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")) + if (_pruneTask != null) { - perm.SetPreferDisableSounds(!perm.IsPreferDisableSounds()); - _ = _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 (!_pruneTask.IsCompleted) { - 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; - _newPassword = string.Empty; + _apiController.GroupUnbanUser(bannedUser); + _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."); - - 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."); + ImGui.EndTable(); + } + _uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f); + ImGui.TreePop(); + } + ImGui.Separator(); + } + mgmtTab.Dispose(); + + } + + private void DrawInvites(GroupPermissions perm) + { + 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() diff --git a/LightlessSync/UI/UIColors.cs b/LightlessSync/UI/UIColors.cs index a93f904..5f08846 100644 --- a/LightlessSync/UI/UIColors.cs +++ b/LightlessSync/UI/UIColors.cs @@ -5,7 +5,7 @@ namespace LightlessSync.UI { internal static class UIColors { - private static readonly Dictionary HexColors = new(StringComparer.OrdinalIgnoreCase) + private static readonly Dictionary DefaultHexColors = new(StringComparer.OrdinalIgnoreCase) { { "LightlessPurple", "#ad8af5" }, { "LightlessBlue", "#a6c2ff" }, @@ -14,14 +14,55 @@ namespace LightlessSync.UI { "DimRed", "#d44444" }, }; + private static readonly Dictionary CustomColors = new(StringComparer.OrdinalIgnoreCase); + public static Vector4 Get(string name) { - if (!HexColors.TryGetValue(name, out var hex)) + if (CustomColors.TryGetValue(name, out var customColor)) + return customColor; + + if (!DefaultHexColors.TryGetValue(name, out var hex)) throw new ArgumentException($"Color '{name}' not found in UIColors."); return HexToRgba(hex); } + public static void Set(string name, Vector4 color) + { + if (!DefaultHexColors.ContainsKey(name)) + throw new ArgumentException($"Color '{name}' not found in UIColors."); + + CustomColors[name] = color; + } + + public static void Reset(string name) + { + CustomColors.Remove(name); + } + + public static void ResetAll() + { + CustomColors.Clear(); + } + + 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 CustomColors.ContainsKey(name); + } + + public static IEnumerable GetColorNames() + { + return DefaultHexColors.Keys; + } + public static Vector4 HexToRgba(string hexColor) { hexColor = hexColor.TrimStart('#'); @@ -31,5 +72,14 @@ namespace LightlessSync.UI 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); } + + 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") : "")}"; + } } -} +} \ No newline at end of file diff --git a/LightlessSync/UI/UISharedService.cs b/LightlessSync/UI/UISharedService.cs index acd8c1c..ffca698 100644 --- a/LightlessSync/UI/UISharedService.cs +++ b/LightlessSync/UI/UISharedService.cs @@ -405,7 +405,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase } 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) { @@ -537,7 +537,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase 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; ImGui.InputText("Storage Folder##cache", ref cacheDirectory, 255, ImGuiInputTextFlags.ReadOnly); @@ -723,7 +723,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase { if (!_discordOAuthCheck.IsCompleted) { - ColorTextWrapped($"Checking OAuth2 compatibility with {selectedServer.ServerUri}", ImGuiColors.DalamudYellow); + ColorTextWrapped($"Checking OAuth2 compatibility with {selectedServer.ServerUri}", UIColors.Get("LightlessYellow")); } else { @@ -814,7 +814,7 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase { if (!_discordOAuthUIDs.IsCompleted) { - ColorTextWrapped("Checking UIDs on Server", ImGuiColors.DalamudYellow); + ColorTextWrapped("Checking UIDs on Server", UIColors.Get("LightlessYellow")); } else {